Imported Upstream version 2.4.12
Ondřej Surý
12 years ago
63 | 63 | COMPILE_ET = @COMPILE_ET@ |
64 | 64 | |
65 | 65 | PACKAGE = cyrus-imapd |
66 | VERSION = 2.4.11 | |
66 | VERSION = 2.4.12 | |
67 | 67 | GIT_VERSION = $(VERSION).git$(shell date +'%Y%m%d%H%M') |
68 | 68 | |
69 | 69 | all:: xversion |
7200 | 7200 | fi |
7201 | 7201 | |
7202 | 7202 | |
7203 | if test "$ac_cv_header_pcreposix_h" == "yes"; then | |
7203 | if test "$ac_cv_header_pcreposix_h" = "yes"; then | |
7204 | 7204 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for utf8 enabled pcre" >&5 |
7205 | 7205 | $as_echo_n "checking for utf8 enabled pcre... " >&6; } |
7206 | 7206 | if ${cyrus_cv_pcre_utf8+:} false; then : |
7228 | 7228 | fi |
7229 | 7229 | fi |
7230 | 7230 | |
7231 | if test "$cyrus_cv_pcre_utf8" == "yes"; then | |
7231 | if test "$cyrus_cv_pcre_utf8" = "yes"; then | |
7232 | 7232 | LIBS="$LIBS -lpcre -lpcreposix"; |
7233 | 7233 | |
7234 | 7234 | $as_echo "#define ENABLE_REGEX /**/" >>confdefs.h |
7249 | 7249 | |
7250 | 7250 | done |
7251 | 7251 | |
7252 | if test "$ac_cv_header_rxposix_h" == "yes"; then | |
7252 | if test "$ac_cv_header_rxposix_h" = "yes"; then | |
7253 | 7253 | LIBS="$LIBS -lrx" |
7254 | 7254 | |
7255 | 7255 | $as_echo "#define ENABLE_REGEX /**/" >>confdefs.h |
402 | 402 | |
403 | 403 | if test "$testpcre" != "no"; then |
404 | 404 | AC_CHECK_HEADER(pcreposix.h) |
405 | if test "$ac_cv_header_pcreposix_h" == "yes"; then | |
405 | if test "$ac_cv_header_pcreposix_h" = "yes"; then | |
406 | 406 | AC_MSG_CHECKING(for utf8 enabled pcre) |
407 | 407 | AC_CACHE_VAL(cyrus_cv_pcre_utf8, AC_TRY_CPP([#include <pcreposix.h> |
408 | 408 | #ifndef REG_UTF8 |
414 | 414 | fi |
415 | 415 | fi |
416 | 416 | |
417 | if test "$cyrus_cv_pcre_utf8" == "yes"; then | |
417 | if test "$cyrus_cv_pcre_utf8" = "yes"; then | |
418 | 418 | LIBS="$LIBS -lpcre -lpcreposix"; |
419 | 419 | AC_DEFINE(ENABLE_REGEX, [], [Do we have a regex library?]) |
420 | 420 | AC_DEFINE(HAVE_PCREPOSIX_H, [], [Do we have usable pcre library?]) |
421 | 421 | else |
422 | 422 | AC_CHECK_HEADERS(rxposix.h) |
423 | if test "$ac_cv_header_rxposix_h" == "yes"; then | |
423 | if test "$ac_cv_header_rxposix_h" = "yes"; then | |
424 | 424 | LIBS="$LIBS -lrx" |
425 | 425 | AC_DEFINE(ENABLE_REGEX, [], |
426 | 426 | [Do we have a regex library?]) |
6 | 6 | <title>Changes to the Cyrus IMAP Server</title> |
7 | 7 | </head> |
8 | 8 | <body> |
9 | ||
10 | ||
11 | <h1>Changes to the Cyrus IMAP Server since 2.4.11</h1> | |
12 | <ul> | |
13 | <li>Bug #3150 - fix issue with overview and messages without | |
14 | a References header</li> | |
15 | <li>fixed nntp login with tab and space in password</li> | |
16 | <li>Bug #3501 - be more relaxed about names of DELETED folders</li> | |
17 | <li>Bug #3553 - fix QRESYNC passing to murder backend - thanks | |
18 | alec <alec@alec.pl></li> | |
19 | <li>Bug #3554 - only show ENABLED response the first time each | |
20 | option is ENABLEd</li> | |
21 | <li>Lots of cleanup of build process and backporting of APIs</li> | |
22 | <li>Bug #3502 - make configure.in more portable - thanks | |
23 | OBATA Akio <obata@lins.jp></li> | |
24 | <li>Bug #3533 - add missing break statements in sieve - | |
25 | thanks Thomas Jarosch <thomas.jarosch@intra2net.com></li> | |
26 | <li>Bug #3550 - support wildcards for ACLS in cyradm - | |
27 | thanks <mark.cave-ayland@siriusit.co.uk></li> | |
28 | <li>Bug #3556 - print remote server in mbpath - | |
29 | thanks Wolfgang Breyha <wbreyha@gmx.net></li> | |
30 | <li>Bug #3559 - make XFER work with unlimited quota - | |
31 | thanks Wolfgang Breyha <wbreyha@gmx.net></li> | |
32 | <li>Bug #3547 - use strconcat() in writefile()</li> | |
33 | <li>fixed a case where skiplist library could write error | |
34 | messages directly to stdout</li> | |
35 | <li>Bug #3545 - fix sign extension in squat_decode_64</li> | |
36 | <li>Bug #3558 - return error if backend doesn't support | |
37 | LIST-EXTENDED</li> | |
38 | <li>Bug #3565 - clean up in preparation for automake</li> | |
39 | <li>fixed incomplete authentication checks in nntpd, | |
40 | reported by Secunia as SA46093</li> | |
41 | </ul> | |
9 | 42 | |
10 | 43 | <h1>Changes to the Cyrus IMAP Server since 2.4.10</h1> |
11 | 44 | <ul> |
6 | 6 | <body> |
7 | 7 | |
8 | 8 | <h1>Upgrading From Previous Versions</h1> |
9 | ||
10 | <h1>Upgrading from 2.4.11</h2> | |
11 | <ul> | |
12 | <li>To support bug-interoperability with older versions of Cyrus, | |
13 | the quota command now supports "-1" as a synonym for | |
14 | unlimited storage</li> | |
15 | </ul> | |
9 | 16 | |
10 | 17 | <h1>Upgrading from 2.4.10</h2> |
11 | 18 | <ul> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:38 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:49 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:38 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:49 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:38 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:49 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:38 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:49 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:38 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:49 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:38 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:49 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:39 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:50 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:39 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:50 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:39 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:50 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:39 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:50 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:39 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:50 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:39 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:50 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:39 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:50 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:39 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:50 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:39 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:50 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:39 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:50 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:40 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:51 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
1097 | 1097 | |
1098 | 1098 | <p style="margin-left:18%; margin-top: 1em">Allowed values: |
1099 | 1099 | <i>header</i>, <i>index</i>, <i>cache</i>, <i>expunge</i>, |
1100 | <i>squat</i>, <i>lock</i></p> | |
1100 | <i>squat</i></p> | |
1101 | 1101 | |
1102 | 1102 | <p style="margin-left:11%;"><b>metapartition-name:</b> |
1103 | 1103 | <none></p> |
1898 | 1898 | <p style="margin-left:18%;">Suppress the named capabilities |
1899 | 1899 | from any capability response. Use the exact case as it |
1900 | 1900 | appears in the response, e.g. "suppress_capabilities: |
1901 | ESEARCH QRESYNC WITHIN XLIST" if you have a murder with | |
1902 | 2.3.x backends and don’t want clients being confused | |
1903 | by new capabilities that some backends don’t | |
1904 | support.</p> | |
1901 | ESEARCH QRESYNC WITHIN XLIST LIST-EXTENDED" if you have | |
1902 | a murder with 2.3.x backends and don’t want clients | |
1903 | being confused by new capabilities that some backends | |
1904 | don’t support.</p> | |
1905 | 1905 | |
1906 | 1906 | <p style="margin-left:11%;"><b>statuscache:</b> 0</p> |
1907 | 1907 |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:40 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:51 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:40 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:51 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:40 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:51 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:40 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:51 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:40 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:51 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:40 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:51 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:40 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:51 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:40 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:51 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:40 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:51 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:41 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:51 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:41 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:52 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:41 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:52 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:41 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:52 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:41 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:52 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:41 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:52 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:41 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:52 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:41 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:52 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:41 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:52 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:41 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:52 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:41 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:52 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:41 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:52 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:41 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:52 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:42 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:53 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:42 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:53 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:42 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:53 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:42 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:53 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:42 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:53 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:42 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:53 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:42 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:53 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | 0 | <!-- Creator : groff version 1.21 --> |
1 | <!-- CreationDate: Thu Sep 8 21:03:42 2011 --> | |
1 | <!-- CreationDate: Tue Oct 4 22:03:53 2011 --> | |
2 | 2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
3 | 3 | "http://www.w3.org/TR/html4/loose.dtd"> |
4 | 4 | <html> |
0 | Changes to the Cyrus IMAP Server since 2.4.11 | |
1 | ||
2 | * Bug #3150 - fix issue with overview and messages without a | |
3 | References header | |
4 | * fixed nntp login with tab and space in password | |
5 | * Bug #3501 - be more relaxed about names of DELETED folders | |
6 | * Bug #3553 - fix QRESYNC passing to murder backend - thanks alec | |
7 | <alec@alec.pl> | |
8 | * Bug #3554 - only show ENABLED response the first time each option | |
9 | is ENABLEd | |
10 | * Lots of cleanup of build process and backporting of APIs | |
11 | * Bug #3502 - make configure.in more portable - thanks OBATA Akio | |
12 | <obata@lins.jp> | |
13 | * Bug #3533 - add missing break statements in sieve - thanks Thomas | |
14 | Jarosch <thomas.jarosch@intra2net.com> | |
15 | * Bug #3550 - support wildcards for ACLS in cyradm - thanks | |
16 | <mark.cave-ayland@siriusit.co.uk> | |
17 | * Bug #3556 - print remote server in mbpath - thanks Wolfgang Breyha | |
18 | <wbreyha@gmx.net> | |
19 | * Bug #3559 - make XFER work with unlimited quota - thanks Wolfgang | |
20 | Breyha <wbreyha@gmx.net> | |
21 | * Bug #3547 - use strconcat() in writefile() | |
22 | * fixed a case where skiplist library could write error messages | |
23 | directly to stdout | |
24 | * Bug #3545 - fix sign extension in squat_decode_64 | |
25 | * Bug #3558 - return error if backend doesn't support LIST-EXTENDED | |
26 | * Bug #3565 - clean up in preparation for automake | |
27 | * fixed incomplete authentication checks in nntpd, reported by | |
28 | Secunia as SA46093 | |
29 | ||
0 | 30 | Changes to the Cyrus IMAP Server since 2.4.10 |
1 | 31 | |
2 | 32 | * fixed replication recovery from different messages at the each end |
346 | 346 | $(CC) $(LDFLAGS) -o $@ unexpunge.o $(CLIOBJS) \ |
347 | 347 | libimap.a $(DEPLIBS) $(LIBS) |
348 | 348 | |
349 | make_md5: make_md5.o libimap.a mutex_fake.o $(DEPLIBS) | |
350 | $(CC) $(LDFLAGS) -o make_md5 make_md5.o libimap.a mutex_fake.o $(DEPLIBS) $(LIBS) | |
351 | ||
352 | make_sha1: make_sha1.o libimap.a mutex_fake.o $(DEPLIBS) | |
353 | $(CC) $(LDFLAGS) -o make_sha1 make_sha1.o libimap.a mutex_fake.o $(DEPLIBS) $(LIBS) | |
354 | ||
355 | 349 | sync_client: sync_client.o sync_support.o \ |
356 | 350 | backend.o tls.o imapparse.o libimap.a mutex_fake.o $(DEPLIBS) |
357 | 351 | $(CC) $(LDFLAGS) -o \ |
1425 | 1425 | theentry.value = value ? value : "NIL"; |
1426 | 1426 | |
1427 | 1427 | return write_entry(mboxname, entry, userid, &theentry, tid); |
1428 | } | |
1429 | ||
1430 | int annotatemore_commit(struct txn *tid) { | |
1431 | return tid ? DB->commit(anndb, tid) : 0; | |
1432 | } | |
1433 | ||
1434 | int annotatemore_abort(struct txn *tid) { | |
1435 | return tid ? DB->abort(anndb, tid) : 0; | |
1428 | 1436 | } |
1429 | 1437 | |
1430 | 1438 | struct storedata { |
2274 | 2282 | ae = xmalloc(sizeof(struct annotate_st_entry)); |
2275 | 2283 | |
2276 | 2284 | p2 = p; |
2277 | for (; *p && (isalnum(*p) || *p=='.' || *p=='-' || *p=='_' || *p=='/'); | |
2285 | for (; *p && (isalnum(*p) || | |
2286 | *p=='.' || *p=='-' || *p=='_' || *p=='/' || *p==':'); | |
2278 | 2287 | p++); |
2279 | 2288 | /* TV-TODO: should test for empty */ |
2280 | 2289 | ae->name = xstrndup(p2, p-p2); |
142 | 142 | const char *value, const char *contenttype, |
143 | 143 | size_t size, time_t modifiedsince, |
144 | 144 | struct txn **tid); |
145 | int annotatemore_commit(struct txn *tid); | |
146 | int annotatemore_abort(struct txn *tid); | |
145 | 147 | |
146 | 148 | /* rename the annotations for 'oldmboxname' to 'newmboxname' |
147 | 149 | * if 'olduserid' is non-NULL then the private annotations |
438 | 438 | static int subscribed_cb(const char *name, int matchlen, int maycreate, |
439 | 439 | struct list_rock *rock); |
440 | 440 | static void list_data(struct listargs *listargs); |
441 | static void list_data_remote(char *tag, struct listargs *listargs); | |
441 | static int list_data_remote(char *tag, struct listargs *listargs); | |
442 | 442 | |
443 | 443 | extern int saslserver(sasl_conn_t *conn, const char *mech, |
444 | 444 | const char *init_resp, const char *resp_prefix, |
3657 | 3657 | prot_printf(backend_current->out, "%s %s {" SIZE_T_FMT "+}\r\n%s", |
3658 | 3658 | tag, cmd, strlen(name), name); |
3659 | 3659 | if (v->uidvalidity) { |
3660 | prot_printf(backend_current->out, " (QRESYNC %lu " MODSEQ_FMT, | |
3660 | prot_printf(backend_current->out, " (QRESYNC (%lu " MODSEQ_FMT, | |
3661 | 3661 | v->uidvalidity, v->modseq); |
3662 | 3662 | if (v->sequence) { |
3663 | 3663 | prot_printf(backend_current->out, " %s", v->sequence); |
3666 | 3666 | prot_printf(backend_current->out, " (%s %s)", |
3667 | 3667 | v->match_seq, v->match_uid); |
3668 | 3668 | } |
3669 | prot_printf(backend_current->out, ")"); | |
3669 | prot_printf(backend_current->out, "))"); | |
3670 | 3670 | } |
3671 | 3671 | prot_printf(backend_current->out, "\r\n"); |
3672 | 3672 | |
5996 | 5996 | mailboxes locally (frontend) and the subscriptions remotely |
5997 | 5997 | (INBOX backend). We can only pass the buck to the INBOX backend |
5998 | 5998 | if its running a unified config */ |
5999 | list_data_remote(tag, listargs); | |
5999 | if (list_data_remote(tag, listargs)) | |
6000 | return; | |
6000 | 6001 | } else { |
6001 | 6002 | list_data(listargs); |
6002 | 6003 | } |
6633 | 6634 | c = getword(imapd_in, &arg); |
6634 | 6635 | if (c != ' ' && c != ')') goto badlist; |
6635 | 6636 | if (arg.s[0] == '\0') goto badlist; |
6636 | newquota = 0; | |
6637 | for (p = arg.s; *p; p++) { | |
6638 | if (!Uisdigit(*p)) goto badlist; | |
6639 | newquota = newquota * 10 + *p - '0'; | |
6640 | if (newquota < 0) goto badlist; /* overflow */ | |
6637 | /* accept "(storage -1)" as "()" to make move from unpatched cyrus possible */ | |
6638 | if (strcmp(arg.s, "-1") != 0) { | |
6639 | newquota = 0; | |
6640 | for (p = arg.s; *p; p++) { | |
6641 | if (!Uisdigit(*p)) goto badlist; | |
6642 | newquota = newquota * 10 + *p - '0'; | |
6643 | if (newquota < 0) goto badlist; /* overflow */ | |
6644 | } | |
6641 | 6645 | } |
6642 | 6646 | if (c == ')') break; |
6643 | 6647 | } |
8853 | 8857 | |
8854 | 8858 | /* note use of + to force the setting of a nonexistant |
8855 | 8859 | * quotaroot */ |
8856 | prot_printf(xfer->be->out, "Q01 SETQUOTA {" SIZE_T_FMT "+}\r\n" \ | |
8857 | "+%s (STORAGE %d)\r\n", | |
8858 | strlen(extname)+1, extname, quota.limit); | |
8860 | if (quota.limit == -1) { | |
8861 | prot_printf(xfer->be->out, "Q01 SETQUOTA {" SIZE_T_FMT "+}\r\n" \ | |
8862 | "+%s ()\r\n", | |
8863 | strlen(extname)+1, extname); | |
8864 | } | |
8865 | else { | |
8866 | prot_printf(xfer->be->out, "Q01 SETQUOTA {" SIZE_T_FMT "+}\r\n" \ | |
8867 | "+%s (STORAGE %d)\r\n", | |
8868 | strlen(extname)+1, extname, quota.limit); | |
8869 | } | |
8859 | 8870 | r = getresult(xfer->be->in, "Q01"); |
8860 | 8871 | if (r) syslog(LOG_ERR, |
8861 | 8872 | "Could not move mailbox: %s, " \ |
10317 | 10328 | * Retrieves the data and prints the untagged responses for a LIST command in |
10318 | 10329 | * the case of a remote inbox. |
10319 | 10330 | */ |
10320 | static void list_data_remote(char *tag, struct listargs *listargs) | |
10331 | static int list_data_remote(char *tag, struct listargs *listargs) | |
10321 | 10332 | { |
10322 | 10333 | if ((listargs->cmd & LIST_CMD_EXTENDED) && |
10323 | 10334 | !CAPA(backend_inbox, CAPA_LISTEXTENDED)) { |
10324 | 10335 | /* client wants to use extended list command but backend doesn't |
10325 | 10336 | * support it */ |
10326 | prot_printf(backend_inbox->out, | |
10337 | prot_printf(imapd_out, | |
10327 | 10338 | "%s NO Backend server does not support LIST-EXTENDED\r\n", |
10328 | 10339 | tag); |
10329 | return; | |
10340 | return IMAP_MAILBOX_NOTSUPPORTED; | |
10330 | 10341 | } |
10331 | 10342 | |
10332 | 10343 | /* print tag, command and list selection options */ |
10382 | 10393 | prot_printf(backend_inbox->out, "\r\n"); |
10383 | 10394 | pipe_lsub(backend_inbox, imapd_userid, tag, 0, |
10384 | 10395 | (listargs->cmd & LIST_CMD_LSUB) ? "LSUB" : "LIST"); |
10396 | ||
10397 | return 0; | |
10385 | 10398 | } |
10386 | 10399 | |
10387 | 10400 | /* Reset the given sasl_conn_t to a sane state */ |
10995 | 11008 | { |
10996 | 11009 | static struct buf arg; |
10997 | 11010 | int c; |
10998 | ||
10999 | prot_printf(imapd_out, "* ENABLED"); | |
11011 | unsigned new_capa = imapd_client_capa; | |
11000 | 11012 | |
11001 | 11013 | do { |
11002 | 11014 | c = getword(imapd_in, &arg); |
11007 | 11019 | eatline(imapd_in, c); |
11008 | 11020 | return; |
11009 | 11021 | } |
11010 | lcase(arg.s); | |
11011 | if (!strcmp(arg.s, "condstore")) { | |
11012 | imapd_client_capa |= CAPA_CONDSTORE; | |
11013 | prot_printf(imapd_out, " CONDSTORE"); | |
11014 | } | |
11015 | else if (!strcmp(arg.s, "qresync")) { | |
11016 | imapd_client_capa |= CAPA_QRESYNC | CAPA_CONDSTORE; | |
11017 | if (imapd_index) imapd_index->qresync = 1; | |
11018 | prot_printf(imapd_out, " QRESYNC CONDSTORE"); | |
11019 | } | |
11022 | if (!strcasecmp(arg.s, "condstore")) | |
11023 | new_capa |= CAPA_CONDSTORE; | |
11024 | else if (!strcasecmp(arg.s, "qresync")) | |
11025 | new_capa |= CAPA_QRESYNC | CAPA_CONDSTORE; | |
11020 | 11026 | } while (c == ' '); |
11021 | ||
11022 | prot_printf(imapd_out, "\r\n"); | |
11023 | 11027 | |
11024 | 11028 | /* check for CRLF */ |
11025 | 11029 | if (c == '\r') c = prot_getc(imapd_in); |
11030 | 11034 | return; |
11031 | 11035 | } |
11032 | 11036 | |
11037 | prot_printf(imapd_out, "* ENABLED"); | |
11038 | if (!(imapd_client_capa & CAPA_CONDSTORE) && | |
11039 | (new_capa & CAPA_CONDSTORE)) { | |
11040 | prot_printf(imapd_out, " CONDSTORE"); | |
11041 | } | |
11042 | if (!(imapd_client_capa & CAPA_QRESYNC) && | |
11043 | (new_capa & CAPA_QRESYNC)) { | |
11044 | prot_printf(imapd_out, " QRESYNC"); | |
11045 | /* RFC5161 says that enable while selected is actually bogus, | |
11046 | * but it's no skin off our nose to support it */ | |
11047 | if (imapd_index) imapd_index->qresync = 1; | |
11048 | } | |
11049 | prot_printf(imapd_out, "\r\n"); | |
11050 | ||
11051 | /* track the new capabilities */ | |
11052 | imapd_client_capa = new_capa; | |
11053 | ||
11033 | 11054 | prot_printf(imapd_out, "%s OK %s\r\n", tag, |
11034 | 11055 | error_message(IMAP_OK_COMPLETED)); |
11035 | 11056 | } |
5041 | 5041 | struct mailbox *mailbox = state->mailbox; |
5042 | 5042 | struct index_map *im = &state->map[msgno-1]; |
5043 | 5043 | |
5044 | /* flush any previous data */ | |
5045 | memset(&over, 0, sizeof(struct nntp_overview)); | |
5046 | ||
5044 | 5047 | if (mailbox_cacherecord(mailbox, &im->record)) |
5045 | 5048 | return NULL; /* upper layers can cope! */ |
5046 | 5049 | |
5096 | 5099 | |
5097 | 5100 | over.from = from; |
5098 | 5101 | } |
5099 | else | |
5100 | over.from = NULL; | |
5101 | 5102 | |
5102 | 5103 | /* massage references */ |
5103 | 5104 | refhdr.s = "references"; |
1432 | 1432 | } |
1433 | 1433 | |
1434 | 1434 | /* |
1435 | * bsearch() function to compare two index record buffers by UID | |
1436 | */ | |
1437 | static int rec_compar(const void *key, const void *mem) | |
1438 | { | |
1439 | uint32_t uid = *((uint32_t *) key); | |
1440 | struct index_record record; | |
1441 | int r; | |
1442 | ||
1443 | if ((r = mailbox_buf_to_index_record(mem, &record))) return r; | |
1444 | ||
1445 | if (uid < record.uid) return -1; | |
1446 | return (uid > record.uid); | |
1447 | } | |
1448 | ||
1449 | /* | |
1450 | * Find the index record in mailbox corresponding to UID | |
1451 | */ | |
1452 | int mailbox_find_index_record(struct mailbox *mailbox, uint32_t uid, | |
1453 | struct index_record *record) | |
1454 | { | |
1455 | const void *mem, *base = mailbox->index_base + mailbox->i.start_offset; | |
1456 | size_t num_records = mailbox->i.num_records; | |
1457 | size_t size = mailbox->i.record_size; | |
1458 | int r; | |
1459 | ||
1460 | mem = bsearch(&uid, base, num_records, size, rec_compar); | |
1461 | if (!mem) return CYRUSDB_NOTFOUND; | |
1462 | ||
1463 | if ((r = mailbox_buf_to_index_record(mem, record))) return r; | |
1464 | ||
1465 | record->recno = ((mem - base) / size) + 1; | |
1466 | ||
1467 | return 0; | |
1468 | } | |
1469 | ||
1470 | /* | |
1435 | 1471 | * Lock the index file for 'mailbox'. Reread index file header if necessary. |
1436 | 1472 | */ |
1437 | 1473 | int mailbox_lock_index(struct mailbox *mailbox, int locktype) |
456 | 456 | struct index_record *record); |
457 | 457 | extern int mailbox_append_index_record(struct mailbox *mailbox, |
458 | 458 | struct index_record *record); |
459 | extern int mailbox_find_index_record(struct mailbox *mailbox, uint32_t uid, | |
460 | struct index_record *record); | |
459 | 461 | |
460 | 462 | extern int mailbox_set_acl(struct mailbox *mailbox, const char *acl, |
461 | 463 | int dirty_modseq); |
918 | 918 | * A thorough fix might remove the prefix and timestamp |
919 | 919 | * then continue with the check |
920 | 920 | */ |
921 | if (!mboxname_isdeletedmailbox(name)) { | |
922 | if (strlen(name) > MAX_MAILBOX_NAME) | |
923 | return IMAP_MAILBOX_BADNAME; | |
924 | } | |
921 | if (mboxname_isdeletedmailbox(name)) | |
922 | return 0; | |
923 | ||
924 | if (strlen(name) > MAX_MAILBOX_NAME) | |
925 | return IMAP_MAILBOX_BADNAME; | |
926 | ||
925 | 927 | for (i = 0; i < NUM_BADMBOXPATTERNS; i++) { |
926 | 928 | g = glob_init(badmboxpatterns[i], GLOB_ICASE); |
927 | 929 | if (GLOB_TEST(g, name) != -1) { |
134 | 134 | |
135 | 135 | if ((rc = mboxlist_lookup(buf, &mbentry, NULL)) == 0) { |
136 | 136 | if (mbentry.mbtype & MBTYPE_REMOTE) { |
137 | fprintf(stderr, "Remote mailbox: %s\n", argv[i]); | |
137 | printf("%s\n", mbentry.partition); | |
138 | 138 | } else { |
139 | 139 | char *path = mboxname_metapath(mbentry.partition, mbentry.name, 0, 0); |
140 | 140 | printf("%s\n", path); |
83 | 83 | int encode; |
84 | 84 | }; |
85 | 85 | |
86 | /* cyrus.cache file item buffer */ | |
87 | struct ibuf { | |
88 | char *start, *end, *last; | |
89 | }; | |
90 | ||
91 | /* | |
92 | * Parsed form of a body-part | |
93 | */ | |
94 | struct body { | |
95 | /* Content-* header information */ | |
96 | char *type; | |
97 | char *subtype; | |
98 | struct param *params; | |
99 | char *id; | |
100 | char *description; | |
101 | char *encoding; | |
102 | char *md5; | |
103 | char *disposition; | |
104 | struct param *disposition_params; | |
105 | struct param *language; | |
106 | char *location; | |
107 | ||
108 | /* Location/size information */ | |
109 | long header_offset; | |
110 | long header_size; | |
111 | long header_lines; | |
112 | long content_offset; | |
113 | long content_size; | |
114 | long content_lines; | |
115 | long boundary_size; /* Size of terminating boundary */ | |
116 | long boundary_lines; | |
117 | ||
118 | int numparts; /* For multipart types */ | |
119 | struct body *subpart; /* For message/rfc822 and multipart types */ | |
120 | ||
121 | /* | |
122 | * Other header information. | |
123 | * Only meaningful for body-parts at top level or | |
124 | * enclosed in message/rfc-822 | |
125 | */ | |
126 | char *date; | |
127 | char *subject; | |
128 | struct address *from; | |
129 | struct address *sender; | |
130 | struct address *reply_to; | |
131 | struct address *to; | |
132 | struct address *cc; | |
133 | struct address *bcc; | |
134 | char *in_reply_to; | |
135 | char *message_id; | |
136 | char *received_date; | |
137 | ||
138 | /* | |
139 | * Cached headers. Only filled in at top-level | |
140 | */ | |
141 | struct ibuf cacheheaders; | |
142 | ||
143 | /* | |
144 | * decoded body. Filled in as needed. | |
145 | */ | |
146 | char *decoded_body; | |
147 | ||
148 | /* Message GUID. Only filled in at top level */ | |
149 | struct message_guid guid; | |
150 | }; | |
151 | ||
152 | /* List of Content-type parameters */ | |
153 | struct param { | |
154 | struct param *next; | |
155 | char *attribute; | |
156 | char *value; | |
157 | }; | |
158 | ||
159 | 86 | /* List of pending multipart boundaries */ |
160 | 87 | struct boundary { |
161 | 88 | char **id; |
0 | 0 | /* message.h -- Message parsing |
1 | 1 | * |
2 | * Copyright (c) 1994-2008 Carnegie Mellon University. All rights reserved. | |
2 | * Copyright (c) 1994-2010 Carnegie Mellon University. All rights reserved. | |
3 | 3 | * |
4 | 4 | * Redistribution and use in source and binary forms, with or without |
5 | 5 | * modification, are permitted provided that the following conditions |
57 | 57 | #include "prot.h" |
58 | 58 | #include "mailbox.h" |
59 | 59 | |
60 | /* cyrus.cache file item buffer */ | |
61 | struct ibuf { | |
62 | char *start, *end, *last; | |
63 | }; | |
64 | ||
65 | /* | |
66 | * Parsed form of a body-part | |
67 | */ | |
68 | struct body { | |
69 | /* Content-* header information */ | |
70 | char *type; | |
71 | char *subtype; | |
72 | struct param *params; | |
73 | char *id; | |
74 | char *description; | |
75 | char *encoding; | |
76 | char *md5; | |
77 | char *disposition; | |
78 | struct param *disposition_params; | |
79 | struct param *language; | |
80 | char *location; | |
81 | ||
82 | /* Location/size information */ | |
83 | long header_offset; | |
84 | long header_size; | |
85 | long header_lines; | |
86 | long content_offset; | |
87 | long content_size; | |
88 | long content_lines; | |
89 | long boundary_size; /* Size of terminating boundary */ | |
90 | long boundary_lines; | |
91 | ||
92 | int numparts; /* For multipart types */ | |
93 | struct body *subpart; /* For message/rfc822 and multipart types */ | |
94 | ||
95 | /* | |
96 | * Other header information. | |
97 | * Only meaningful for body-parts at top level or | |
98 | * enclosed in message/rfc-822 | |
99 | */ | |
100 | char *date; | |
101 | char *subject; | |
102 | struct address *from; | |
103 | struct address *sender; | |
104 | struct address *reply_to; | |
105 | struct address *to; | |
106 | struct address *cc; | |
107 | struct address *bcc; | |
108 | char *in_reply_to; | |
109 | char *message_id; | |
110 | char *received_date; | |
111 | ||
112 | /* | |
113 | * Cached headers. Only filled in at top-level | |
114 | */ | |
115 | struct ibuf cacheheaders; | |
116 | ||
117 | /* | |
118 | * decoded body. Filled in as needed. | |
119 | */ | |
120 | char *decoded_body; | |
121 | ||
122 | /* Message GUID. Only filled in at top level */ | |
123 | struct message_guid guid; | |
124 | }; | |
125 | ||
126 | /* List of Content-type parameters */ | |
127 | struct param { | |
128 | struct param *next; | |
129 | char *attribute; | |
130 | char *value; | |
131 | }; | |
60 | 132 | extern int message_copy_strict P((struct protstream *from, FILE *to, |
61 | 133 | unsigned size, int allow_null)); |
62 | 134 |
213 | 213 | static void cmdloop(void); |
214 | 214 | static int open_group(char *name, int has_prefix, |
215 | 215 | struct backend **ret, int *postable); |
216 | static int getuserpass(struct protstream *in, struct buf *buf); | |
216 | 217 | static int parserange(char *str, uint32_t *uid, uint32_t *last, |
217 | 218 | char **msgid, struct backend **be); |
218 | 219 | static time_t parse_datetime(char *datestr, char *timestr, char *gmt); |
898 | 899 | |
899 | 900 | /* Only Authinfo/Capabilities/Check/Head/Help/Ihave/List Active/ |
900 | 901 | Mode/Quit/Starttls/Stat/Takethis allowed when not logged in */ |
901 | if (!nntp_userid && !allowanonymous && | |
902 | if (!nntp_authstate && !allowanonymous && | |
902 | 903 | !strchr("ACHILMQST", cmd.s[0])) goto nologin; |
903 | 904 | |
904 | 905 | /* In case a [LIST]GROUP fails or |
908 | 909 | switch (cmd.s[0]) { |
909 | 910 | case 'A': |
910 | 911 | if (!strcmp(cmd.s, "Authinfo")) { |
911 | arg2.len = arg3.len = 0; | |
912 | 912 | if (c != ' ') goto missingargs; |
913 | 913 | c = getword(nntp_in, &arg1); /* subcommand */ |
914 | 914 | if (c == EOF) goto missingargs; |
915 | 915 | |
916 | 916 | lcase(arg1.s); |
917 | 917 | |
918 | if (strcmp(arg1.s, "generic") && c != ' ') { | |
919 | /* arg2 is required for all subcommands except generic */ | |
920 | goto missingargs; | |
918 | if (!strcmp(arg1.s, "user") || !strcmp(arg1.s, "pass")) { | |
919 | if (c != ' ') goto missingargs; | |
920 | c = getuserpass(nntp_in, &arg2); /* user/pass */ | |
921 | if (c == EOF) goto missingargs; | |
922 | ||
923 | if (c == '\r') c = prot_getc(nntp_in); | |
924 | if (c != '\n') goto extraargs; | |
925 | ||
926 | if (arg1.s[0] == 'u') | |
927 | cmd_authinfo_user(arg2.s); | |
928 | else | |
929 | cmd_authinfo_pass(arg2.s); | |
921 | 930 | } |
922 | if (c == ' ') { | |
923 | c = getword(nntp_in, &arg2); /* argument/sasl mech */ | |
924 | if (c == EOF) goto missingargs; | |
925 | } | |
926 | ||
927 | if (!strcmp(arg1.s, "sasl") && c == ' ') { | |
928 | c = getword(nntp_in, &arg3); /* init response (optional) */ | |
929 | if (c == EOF) goto missingargs; | |
930 | } | |
931 | if (c == '\r') c = prot_getc(nntp_in); | |
932 | if (c != '\n') goto extraargs; | |
933 | ||
934 | if (!strcmp(arg1.s, "user")) | |
935 | cmd_authinfo_user(arg2.s); | |
936 | else if (!strcmp(arg1.s, "pass")) | |
937 | cmd_authinfo_pass(arg2.s); | |
938 | else if (!strcmp(arg1.s, "sasl") || !strcmp(arg1.s, "generic")) | |
931 | else if (!strcmp(arg1.s, "sasl") || !strcmp(arg1.s, "generic")) { | |
932 | arg2.len = arg3.len = 0; | |
933 | ||
934 | /* mech name required for SASL but not GENERIC */ | |
935 | if ((arg1.s[0] == 's') && (c != ' ')) goto missingargs; | |
936 | ||
937 | if (c == ' ') { | |
938 | c = getword(nntp_in, &arg2); /* mech name */ | |
939 | if (c == EOF) goto missingargs; | |
940 | ||
941 | if (c == ' ') { | |
942 | c = getword(nntp_in, &arg3); /* init response */ | |
943 | if (c == EOF) goto missingargs; | |
944 | } | |
945 | } | |
946 | ||
947 | if (c == '\r') c = prot_getc(nntp_in); | |
948 | if (c != '\n') goto extraargs; | |
949 | ||
939 | 950 | cmd_authinfo_sasl(arg1.s, arg2.len ? arg2.s : NULL, |
940 | 951 | arg3.len ? arg3.s : NULL); |
952 | } | |
941 | 953 | else |
942 | 954 | prot_printf(nntp_out, |
943 | 955 | "501 Unrecognized AUTHINFO command\r\n"); |
944 | 956 | } |
945 | 957 | else if (!(nntp_capa & MODE_READ)) goto noperm; |
946 | else if (!nntp_userid && !allowanonymous) goto nologin; | |
958 | else if (!nntp_authstate && !allowanonymous) goto nologin; | |
947 | 959 | else if (!strcmp(cmd.s, "Article")) { |
948 | 960 | char *msgid; |
949 | 961 | |
1135 | 1147 | cmd_help(); |
1136 | 1148 | } |
1137 | 1149 | else if (!(nntp_capa & MODE_READ)) goto noperm; |
1138 | else if (!nntp_userid && !allowanonymous) goto nologin; | |
1150 | else if (!nntp_authstate && !allowanonymous) goto nologin; | |
1139 | 1151 | else if (!strcmp(cmd.s, "Hdr")) { |
1140 | 1152 | char *msgid; |
1141 | 1153 | |
1214 | 1226 | goto prevgroup; /* In case we did LIST [ACTIVE] */ |
1215 | 1227 | } |
1216 | 1228 | else if (!(nntp_capa & MODE_READ)) goto noperm; |
1217 | else if (!nntp_userid && !allowanonymous) goto nologin; | |
1229 | else if (!nntp_authstate && !allowanonymous) goto nologin; | |
1218 | 1230 | else if (!strcmp(cmd.s, "Last")) { |
1219 | 1231 | if (c == '\r') c = prot_getc(nntp_in); |
1220 | 1232 | if (c != '\n') goto extraargs; |
1414 | 1426 | mode = ARTICLE_STAT; |
1415 | 1427 | goto article; |
1416 | 1428 | } |
1417 | else if (!nntp_userid && !allowanonymous) goto nologin; | |
1429 | else if (!nntp_authstate && !allowanonymous) goto nologin; | |
1418 | 1430 | else if (!strcmp(cmd.s, "Slave")) { |
1419 | 1431 | if (c == '\r') c = prot_getc(nntp_in); |
1420 | 1432 | if (c != '\n') goto extraargs; |
1586 | 1598 | } |
1587 | 1599 | |
1588 | 1600 | return 1; |
1601 | } | |
1602 | ||
1603 | /* | |
1604 | * Parse a username or password (token which may contain SP or TAB) | |
1605 | */ | |
1606 | #define MAX_NNTP_ARG 497 | |
1607 | static int getuserpass(struct protstream *in, struct buf *buf) | |
1608 | { | |
1609 | int c; | |
1610 | ||
1611 | buf_reset(buf); | |
1612 | for (;;) { | |
1613 | c = prot_getc(in); | |
1614 | if (c == EOF || c == '\r' || c == '\n') { | |
1615 | buf_cstring(buf); /* appends a '\0' */ | |
1616 | return c; | |
1617 | } | |
1618 | buf_putc(buf, c); | |
1619 | if (buf_len(buf) > MAX_NNTP_ARG) { | |
1620 | fatal("argument too long", EC_IOERR); | |
1621 | } | |
1622 | } | |
1589 | 1623 | } |
1590 | 1624 | |
1591 | 1625 | static int parserange(char *str, uint32_t *uid, uint32_t *last, |
1765 | 1799 | if (newserver) { |
1766 | 1800 | /* remote group */ |
1767 | 1801 | backend_next = proxy_findserver(newserver, &nntp_protocol, |
1768 | nntp_userid ? nntp_userid : "anonymous", | |
1802 | nntp_authstate ? nntp_userid : "anonymous", | |
1769 | 1803 | &backend_cached, &backend_current, |
1770 | 1804 | NULL, nntp_in); |
1771 | 1805 | if (!backend_next) return IMAP_SERVER_UNAVAILABLE; |
1776 | 1810 | /* local group */ |
1777 | 1811 | struct index_init init; |
1778 | 1812 | memset(&init, 0, sizeof(struct index_init)); |
1779 | init.userid = nntp_userid; | |
1813 | init.userid = nntp_authstate ? nntp_userid : NULL; | |
1780 | 1814 | init.authstate = nntp_authstate; |
1781 | 1815 | r = index_open(name, &init, &group_state); |
1782 | 1816 | if (r) return r; |
1823 | 1857 | if (mechcount) prot_printf(nntp_out, "%s", mechlist); |
1824 | 1858 | |
1825 | 1859 | /* add the reader capabilities/extensions */ |
1826 | if ((nntp_capa & MODE_READ) && (nntp_userid || allowanonymous)) { | |
1860 | if ((nntp_capa & MODE_READ) && (nntp_authstate || allowanonymous)) { | |
1827 | 1861 | prot_printf(nntp_out, "READER\r\n"); |
1828 | 1862 | prot_printf(nntp_out, "POST\r\n"); |
1829 | 1863 | if (config_getswitch(IMAPOPT_ALLOWNEWNEWS)) |
1841 | 1875 | |
1842 | 1876 | /* add the LIST variants */ |
1843 | 1877 | prot_printf(nntp_out, "LIST ACTIVE%s\r\n", |
1844 | ((nntp_capa & MODE_READ) && (nntp_userid || allowanonymous)) ? | |
1878 | ((nntp_capa & MODE_READ) && (nntp_authstate || allowanonymous)) ? | |
1845 | 1879 | " HEADERS NEWSGROUPS OVERVIEW.FMT" : ""); |
1846 | 1880 | |
1847 | 1881 | prot_printf(nntp_out, ".\r\n"); |
2320 | 2354 | { |
2321 | 2355 | prot_printf(nntp_out, "100 Supported commands:\r\n"); |
2322 | 2356 | |
2323 | if ((nntp_capa & MODE_READ) && (nntp_userid || allowanonymous)) { | |
2357 | if ((nntp_capa & MODE_READ) && (nntp_authstate || allowanonymous)) { | |
2324 | 2358 | prot_printf(nntp_out, "\tARTICLE [ message-id | number ]\r\n" |
2325 | 2359 | "\t\tRetrieve entirety of the specified article.\r\n"); |
2326 | 2360 | } |
2335 | 2369 | prot_printf(nntp_out, "\tAUTHINFO PASS password\r\n" |
2336 | 2370 | "\t\tPresent clear-text password for authentication.\r\n"); |
2337 | 2371 | } |
2338 | if ((nntp_capa & MODE_READ) && (nntp_userid || allowanonymous)) { | |
2372 | if ((nntp_capa & MODE_READ) && (nntp_authstate || allowanonymous)) { | |
2339 | 2373 | prot_printf(nntp_out, "\tBODY [ message-id | number ]\r\n" |
2340 | 2374 | "\t\tRetrieve body of the specified article.\r\n"); |
2341 | 2375 | } |
2345 | 2379 | prot_printf(nntp_out, "\tCHECK message-id\r\n" |
2346 | 2380 | "\t\tCheck if the server wants the specified article.\r\n"); |
2347 | 2381 | } |
2348 | if ((nntp_capa & MODE_READ) && (nntp_userid || allowanonymous)) { | |
2382 | if ((nntp_capa & MODE_READ) && (nntp_authstate || allowanonymous)) { | |
2349 | 2383 | prot_printf(nntp_out, "\tDATE\r\n" |
2350 | 2384 | "\t\tRequest the current server UTC date and time.\r\n"); |
2351 | 2385 | prot_printf(nntp_out, "\tGROUP group\r\n" |
2362 | 2396 | prot_printf(nntp_out, "\tIHAVE message-id\r\n" |
2363 | 2397 | "\t\tPresent/transfer the specified article to the server.\r\n"); |
2364 | 2398 | } |
2365 | if ((nntp_capa & MODE_READ) && (nntp_userid || allowanonymous)) { | |
2399 | if ((nntp_capa & MODE_READ) && (nntp_authstate || allowanonymous)) { | |
2366 | 2400 | prot_printf(nntp_out, "\tLAST\r\n" |
2367 | 2401 | "\t\tSelect the previous article.\r\n"); |
2368 | 2402 | } |
2369 | 2403 | prot_printf(nntp_out, "\tLIST [ ACTIVE wildmat ]\r\n" |
2370 | 2404 | "\t\tList the (subset of) valid newsgroups.\r\n"); |
2371 | if ((nntp_capa & MODE_READ) && (nntp_userid || allowanonymous)) { | |
2405 | if ((nntp_capa & MODE_READ) && (nntp_authstate || allowanonymous)) { | |
2372 | 2406 | prot_printf(nntp_out, "\tLIST HEADERS [ MSGID | RANGE ]\r\n" |
2373 | 2407 | "\t\tList the headers and metadata items available via HDR.\r\n"); |
2374 | 2408 | prot_printf(nntp_out, "\tLIST NEWSGROUPS [wildmat]\r\n" |
2401 | 2435 | prot_printf(nntp_out, "\tTAKETHIS message-id\r\n" |
2402 | 2436 | "\t\tTransfer the specified article to the server.\r\n"); |
2403 | 2437 | } |
2404 | if ((nntp_capa & MODE_READ) && (nntp_userid || allowanonymous)) { | |
2438 | if ((nntp_capa & MODE_READ) && (nntp_authstate || allowanonymous)) { | |
2405 | 2439 | prot_printf(nntp_out, "\tXPAT header message-id|range wildmat\r\n" |
2406 | 2440 | "\t\tList the specified article(s) in which the contents\r\n" |
2407 | 2441 | "\t\tof the specified header/metadata matches the wildmat.\r\n"); |
2469 | 2503 | char *result; |
2470 | 2504 | |
2471 | 2505 | be = proxy_findserver(server, &nntp_protocol, |
2472 | nntp_userid ? nntp_userid : "anonymous", | |
2506 | nntp_authstate ? nntp_userid : "anonymous", | |
2473 | 2507 | &backend_cached, &backend_current, NULL, nntp_in); |
2474 | 2508 | if (!be) return; |
2475 | 2509 | |
2604 | 2638 | strcpy(pattern, newsprefix); |
2605 | 2639 | strcat(pattern, "*"); |
2606 | 2640 | list_cb(NULL, 0, 0, NULL); |
2607 | mboxlist_findall(NULL, pattern, 0, nntp_userid, nntp_authstate, | |
2641 | mboxlist_findall(NULL, pattern, 0, | |
2642 | nntp_authstate ? nntp_userid : NULL, nntp_authstate, | |
2608 | 2643 | list_cb, &lrock); |
2609 | 2644 | |
2610 | 2645 | /* proxy to the backends */ |
2626 | 2661 | prot_printf(nntp_out, "502 Permission denied\r\n"); |
2627 | 2662 | return; |
2628 | 2663 | } |
2629 | else if (!nntp_userid && !allowanonymous) { | |
2664 | else if (!nntp_authstate && !allowanonymous) { | |
2630 | 2665 | prot_printf(nntp_out, "480 Authentication required\r\n"); |
2631 | 2666 | return; |
2632 | 2667 | } |
2663 | 2698 | strcpy(pattern, newsprefix); |
2664 | 2699 | strcat(pattern, "*"); |
2665 | 2700 | list_cb(NULL, 0, 0, NULL); |
2666 | mboxlist_findall(NULL, pattern, 0, nntp_userid, nntp_authstate, | |
2701 | mboxlist_findall(NULL, pattern, 0, | |
2702 | nntp_authstate ? nntp_userid : NULL, nntp_authstate, | |
2667 | 2703 | list_cb, &lrock); |
2668 | 2704 | |
2669 | 2705 | /* proxy to the backends */ |
3239 | 3275 | char buf[4096]; |
3240 | 3276 | |
3241 | 3277 | be = proxy_findserver(d->server, &nntp_protocol, |
3242 | nntp_userid ? nntp_userid : "anonymous", | |
3278 | nntp_authstate ? nntp_userid : "anonymous", | |
3243 | 3279 | &backend_cached, &backend_current, |
3244 | 3280 | NULL, nntp_in); |
3245 | 3281 | if (!be) return IMAP_SERVER_UNAVAILABLE; |
3317 | 3353 | continue; |
3318 | 3354 | } |
3319 | 3355 | |
3320 | r = append_setup(&as, rcpt, nntp_userid, nntp_authstate, ACL_POST, 0); | |
3356 | r = append_setup(&as, rcpt, | |
3357 | nntp_authstate ? nntp_userid : NULL, | |
3358 | nntp_authstate, ACL_POST, 0); | |
3321 | 3359 | |
3322 | 3360 | if (!r) { |
3323 | 3361 | prot_rewind(msg->data); |
135 | 135 | |
136 | 136 | |
137 | 137 | |
138 | #define MAX(x, y) (x > y ? x : y) | |
139 | 138 | |
140 | 139 | /* Comparator function that sorts ranges by the low value, |
141 | 140 | and coalesces intersecting ranges to have the same high value */ |
196 | 196 | skip && *skip && strcasecmp(name, *skip); skip++); |
197 | 197 | if (!skip || !*skip) { |
198 | 198 | /* write the header name to the output */ |
199 | fputs(name, fout); | |
199 | if (fout) fputs(name, fout); | |
200 | 200 | skip = NULL; |
201 | 201 | } |
202 | 202 | s = (c == ':' ? BODY_START : COLON); |
219 | 219 | } else if (c != ' ' && c != '\t') { |
220 | 220 | /* i want to avoid confusing dot-stuffing later */ |
221 | 221 | while (c == '.') { |
222 | if (!skip) fputc(c, fout); | |
222 | if (fout && !skip) fputc(c, fout); | |
223 | 223 | c = prot_getc(fin); |
224 | 224 | } |
225 | 225 | r = IMAP_MESSAGE_BADHEADER; |
240 | 240 | |
241 | 241 | peek = prot_getc(fin); |
242 | 242 | |
243 | if (!skip) { | |
243 | if (fout && !skip) { | |
244 | 244 | fputc('\r', fout); |
245 | 245 | fputc('\n', fout); |
246 | 246 | } |
281 | 281 | } |
282 | 282 | |
283 | 283 | /* copy this to the output */ |
284 | if (s != NAME && !skip) fputc(c, fout); | |
284 | if (fout && s != NAME && !skip) fputc(c, fout); | |
285 | 285 | } |
286 | 286 | |
287 | 287 | /* if we fall off the end of the loop, we hit some sort of error |
71 | 71 | return s + 4; |
72 | 72 | } |
73 | 73 | |
74 | SquatInt64 squat_decode_64(char const* s) { | |
75 | unsigned char* v = (unsigned char*)s; | |
76 | return ((SquatInt64)v[0] << 56) | ((SquatInt64)v[1] << 48) | |
77 | | ((SquatInt64)v[2] << 40) | ((SquatInt64)v[3] << 32) | |
78 | | (((SquatInt32)v[4] << 24) | ((SquatInt32)v[5] << 16) | |
79 | | ((SquatInt32)v[6] << 8) | (SquatInt32)v[7]); | |
74 | SquatInt64 squat_decode_64(char const *s) | |
75 | { | |
76 | unsigned char* v = (unsigned char*)s; | |
77 | return ((SquatInt64)v[0] << 56) | ((SquatInt64)v[1] << 48) | | |
78 | ((SquatInt64)v[2] << 40) | ((SquatInt64)v[3] << 32) | | |
79 | ((SquatInt64)v[4] << 24) | ((SquatInt64)v[5] << 16) | | |
80 | ((SquatInt64)v[6] << 8) | (SquatInt64)v[7]; | |
80 | 81 | } |
81 | 82 | |
82 | 83 | char* squat_encode_64(char* s, SquatInt64 v) { |
101 | 101 | LIBCYRM_HDRS = $(srcdir)/hash.h $(srcdir)/mpool.h $(srcdir)/xmalloc.h \ |
102 | 102 | $(srcdir)/xstrlcat.h $(srcdir)/xstrlcpy.h $(srcdir)/util.h \ |
103 | 103 | $(srcdir)/strhash.h $(srcdir)/libconfig.h $(srcdir)/assert.h \ |
104 | imapopts.h $(srcdir)/crc32.h | |
104 | imapopts.h | |
105 | 105 | LIBCYRM_OBJS = libconfig.o imapopts.o hash.o mpool.o xmalloc.o strhash.o \ |
106 | xstrlcat.o xstrlcpy.o assert.o util.o signals.o crc32.o @IPV6_OBJS@ | |
106 | xstrlcat.o xstrlcpy.o assert.o util.o signals.o @IPV6_OBJS@ | |
107 | 107 | |
108 | 108 | all: $(BUILTSOURCES) libcyrus_min.a libcyrus.a |
109 | 109 |
1939 | 1939 | offset = FORWARD(ptr, i); |
1940 | 1940 | |
1941 | 1941 | if (offset > db->map_size) { |
1942 | fprintf(stdout, | |
1942 | syslog(LOG_ERR, | |
1943 | 1943 | "skiplist inconsistent: %04X: ptr %d is %04X; " |
1944 | 1944 | "eof is %04X\n", |
1945 | 1945 | (unsigned int) (ptr - db->map_base), |
1955 | 1955 | |
1956 | 1956 | cmp = db->compar(KEY(ptr), KEYLEN(ptr), KEY(q), KEYLEN(q)); |
1957 | 1957 | if (cmp >= 0) { |
1958 | fprintf(stdout, | |
1958 | syslog(LOG_ERR, | |
1959 | 1959 | "skiplist inconsistent: %04X: ptr %d is %04X; " |
1960 | 1960 | "db->compar() = %d\n", |
1961 | 1961 | (unsigned int) (ptr - db->map_base), |
684 | 684 | { "mboxname_lockpath", NULL, STRING } |
685 | 685 | /* Path to mailbox name lock files (default $conf/lock) */ |
686 | 686 | |
687 | { "metapartition_files", "", BITFIELD("header", "index", "cache", "expunge", "squat", "lock") } | |
687 | { "metapartition_files", "", BITFIELD("header", "index", "cache", "expunge", "squat") } | |
688 | 688 | /* Space-separated list of metadata files to be stored on a |
689 | 689 | \fImetapartition\fR rather than in the mailbox directory on a spool |
690 | 690 | partition. */ |
1199 | 1199 | { "suppress_capabilities", NULL, STRING } |
1200 | 1200 | /* Suppress the named capabilities from any capability response. Use the |
1201 | 1201 | exact case as it appears in the response, e.g. |
1202 | "suppress_capabilities: ESEARCH QRESYNC WITHIN XLIST" if you have | |
1203 | a murder with 2.3.x backends and don't want clients being confused | |
1204 | by new capabilities that some backends don't support. */ | |
1202 | "suppress_capabilities: ESEARCH QRESYNC WITHIN XLIST LIST-EXTENDED" | |
1203 | if you have a murder with 2.3.x backends and don't want clients being | |
1204 | confused by new capabilities that some backends don't support. */ | |
1205 | 1205 | |
1206 | 1206 | { "statuscache", 0, SWITCH } |
1207 | 1207 | /* Enable/disable the imap status cache. */ |
416 | 416 | { "cache" , IMAP_ENUM_METAPARTITION_FILES_CACHE }, |
417 | 417 | { "expunge" , IMAP_ENUM_METAPARTITION_FILES_EXPUNGE }, |
418 | 418 | { "squat" , IMAP_ENUM_METAPARTITION_FILES_SQUAT }, |
419 | { "lock" , IMAP_ENUM_METAPARTITION_FILES_LOCK }, | |
420 | 419 | { NULL, IMAP_ENUM_ZERO } } }, |
421 | 420 | { IMAPOPT_MUPDATE_AUTHNAME, "mupdate_authname", 0, OPT_STRING, |
422 | 421 | {(void *)(NULL)}, |
282 | 282 | IMAP_ENUM_METAPARTITION_FILES_CACHE = (1<<2), |
283 | 283 | IMAP_ENUM_METAPARTITION_FILES_EXPUNGE = (1<<3), |
284 | 284 | IMAP_ENUM_METAPARTITION_FILES_SQUAT = (1<<4), |
285 | IMAP_ENUM_METAPARTITION_FILES_LOCK = (1<<5), | |
286 | 285 | IMAP_ENUM_MUPDATE_CONFIG_STANDARD = 0, |
287 | 286 | IMAP_ENUM_MUPDATE_CONFIG_UNIFIED, |
288 | 287 | IMAP_ENUM_MUPDATE_CONFIG_REPLICATED, |
85 | 85 | * Create a new protection stream for file descriptor 'fd'. Stream |
86 | 86 | * will be used for writing iff 'write' is nonzero. |
87 | 87 | */ |
88 | struct protstream *prot_new(fd, write) | |
89 | int fd; | |
90 | int write; | |
88 | struct protstream *prot_new(int fd, int write) | |
91 | 89 | { |
92 | 90 | struct protstream *newstream; |
93 | 91 | |
104 | 102 | if(write) |
105 | 103 | newstream->cnt = PROT_BUFSIZE; |
106 | 104 | |
107 | newstream->can_unget = 0; | |
108 | newstream->bytes_in = 0; | |
109 | newstream->bytes_out = 0; | |
105 | return newstream; | |
106 | } | |
107 | ||
108 | /* Create a protstream which is just an interface to a mapped piece of | |
109 | * memory, allowing prot commands to be used to read from it */ | |
110 | struct protstream *prot_readmap(const char *buf, uint32_t len) | |
111 | { | |
112 | struct protstream *newstream; | |
113 | ||
114 | newstream = (struct protstream *) xzmalloc(sizeof(struct protstream)); | |
115 | /* dodgy, but the alternative is two pointers */ | |
116 | newstream->ptr = (unsigned char *)buf; | |
117 | newstream->cnt = len; | |
118 | newstream->fixedsize = 1; | |
119 | newstream->fd = PROT_NO_FD; | |
120 | newstream->logfd = PROT_NO_FD; | |
121 | newstream->big_buffer = PROT_NO_FD; | |
110 | 122 | |
111 | 123 | return newstream; |
112 | 124 | } |
133 | 145 | if (s->zbuf) free(s->zbuf); |
134 | 146 | #endif |
135 | 147 | |
136 | free((char*)s); | |
148 | free(s); | |
137 | 149 | |
138 | 150 | return 0; |
139 | 151 | } |
565 | 577 | /* Zero errno just in case */ |
566 | 578 | errno = 0; |
567 | 579 | |
580 | if (s->fixedsize) s->eof = 1; | |
568 | 581 | if (s->eof || s->error) return EOF; |
569 | 582 | |
570 | 583 | do { |
1691 | 1704 | { |
1692 | 1705 | assert(!s->write); |
1693 | 1706 | |
1707 | if (c == EOF) return EOF; | |
1708 | ||
1694 | 1709 | if (!s->can_unget) |
1695 | 1710 | fatal("Can't unwind any more", EC_SOFTWARE); |
1696 | 1711 | |
1697 | 1712 | s->cnt++; |
1698 | 1713 | s->can_unget--; |
1699 | 1714 | s->bytes_in--; |
1700 | *--(s->ptr) = c; | |
1715 | s->ptr--; | |
1716 | if (*s->ptr != c) | |
1717 | fatal("Trying to unput wrong character", EC_SOFTWARE); | |
1701 | 1718 | |
1702 | 1719 | return c; |
1703 | 1720 | } |
112 | 112 | /* Status Flags */ |
113 | 113 | int eof; |
114 | 114 | int boundary; /* Type of data is about to change */ |
115 | int fixedsize; | |
115 | 116 | char *error; |
116 | 117 | |
117 | 118 | /* Parameters */ |
181 | 182 | |
182 | 183 | /* Allocate/free the protstream structure */ |
183 | 184 | extern struct protstream *prot_new(int fd, int write); |
185 | extern struct protstream *prot_readmap(const char *buf, uint32_t len); | |
184 | 186 | extern int prot_free(struct protstream *s); |
185 | 187 | |
186 | 188 | /* Set the telemetry logfile for a given protstream */ |
526 | 526 | *len = buf->len; |
527 | 527 | } |
528 | 528 | |
529 | unsigned buf_len(struct buf *buf) | |
529 | unsigned buf_len(const struct buf *buf) | |
530 | 530 | { |
531 | 531 | return buf->len; |
532 | 532 | } |
537 | 537 | buf->flags &= ~BUF_CSTRING; |
538 | 538 | } |
539 | 539 | |
540 | void buf_setcstr(struct buf *buf, char *str) | |
540 | void buf_truncate(struct buf *buf, unsigned int len) | |
541 | { | |
542 | if (len > buf->alloc) { | |
543 | /* grow the buffer and zero-fill the new bytes */ | |
544 | unsigned int more = len - buf->len; | |
545 | buf_ensure(buf, more); | |
546 | memset(buf->s + buf->len, 0, more); | |
547 | } | |
548 | buf->len = len; | |
549 | buf->flags &= ~BUF_CSTRING; | |
550 | } | |
551 | ||
552 | void buf_setcstr(struct buf *buf, const char *str) | |
541 | 553 | { |
542 | 554 | buf_setmap(buf, str, strlen(str)); |
543 | 555 | } |
544 | 556 | |
545 | void buf_setmap(struct buf *buf, char *base, int len) | |
557 | void buf_setmap(struct buf *buf, const char *base, int len) | |
546 | 558 | { |
547 | 559 | buf_reset(buf); |
548 | 560 | if (len) { |
552 | 564 | } |
553 | 565 | } |
554 | 566 | |
555 | void buf_copy(struct buf *dst, struct buf *src) | |
567 | void buf_copy(struct buf *dst, const struct buf *src) | |
556 | 568 | { |
557 | 569 | buf_setmap(dst, src->s, src->len); |
558 | 570 | } |
559 | 571 | |
560 | void buf_append(struct buf *dst, struct buf *src) | |
572 | void buf_append(struct buf *dst, const struct buf *src) | |
561 | 573 | { |
562 | 574 | buf_appendmap(dst, src->s, src->len); |
563 | 575 | } |
564 | 576 | |
565 | void buf_appendcstr(struct buf *buf, char *str) | |
577 | void buf_appendcstr(struct buf *buf, const char *str) | |
566 | 578 | { |
567 | 579 | buf_appendmap(buf, str, strlen(str)); |
568 | 580 | } |
574 | 586 | buf_appendmap(buf, item, 4); |
575 | 587 | } |
576 | 588 | |
577 | void buf_appendmap(struct buf *buf, char *base, int len) | |
589 | void buf_appendmap(struct buf *buf, const char *base, int len) | |
578 | 590 | { |
579 | 591 | if (len) { |
580 | 592 | buf_ensure(buf, len); |
589 | 601 | buf_ensure(buf, 1); |
590 | 602 | buf->s[buf->len++] = c; |
591 | 603 | buf->flags &= ~BUF_CSTRING; |
604 | } | |
605 | ||
606 | void buf_printf(struct buf *buf, const char *fmt, ...) | |
607 | { | |
608 | va_list args; | |
609 | int room; | |
610 | int n; | |
611 | ||
612 | /* Add some more room to the buffer. We just guess a | |
613 | * size and rely on vsnprintf() to tell us if it | |
614 | * needs to overrun the size. */ | |
615 | buf_ensure(buf, 1024); | |
616 | ||
617 | room = buf->alloc - buf->len - 1; | |
618 | va_start(args, fmt); | |
619 | n = vsnprintf(buf->s + buf->len, room+1, fmt, args); | |
620 | va_end(args); | |
621 | ||
622 | if (n > room) { | |
623 | /* woops, we guessed wrong...retry */ | |
624 | buf_ensure(buf, n-room); | |
625 | va_start(args, fmt); | |
626 | n = vsnprintf(buf->s + buf->len, n+1, fmt, args); | |
627 | va_end(args); | |
628 | } | |
629 | ||
630 | buf->len += n; | |
631 | /* vsnprintf() gave us a trailing NUL, so we may as well remember | |
632 | * that for later */ | |
633 | buf->flags |= BUF_CSTRING; | |
634 | } | |
635 | ||
636 | /** | |
637 | * Replace all instances of the string literal @match in @buf | |
638 | * with the string @replace, which may be NULL to just remove | |
639 | * instances of @match. | |
640 | * Returns: the number of substitutions made. | |
641 | */ | |
642 | unsigned int buf_replace_all(struct buf *buf, const char *match, | |
643 | const char *replace) | |
644 | { | |
645 | unsigned int n = 0; | |
646 | int matchlen = strlen(match); | |
647 | int replacelen = (replace ? strlen(replace) : 0); | |
648 | char *p; | |
649 | ||
650 | /* we need buf to be a nul terminated string now please */ | |
651 | buf_cstring(buf); | |
652 | ||
653 | p = buf->s; | |
654 | while ((p = strstr(p, match))) { | |
655 | if (replacelen > matchlen) { | |
656 | /* string will need to expand */ | |
657 | int dp = (p - buf->s); | |
658 | buf_ensure(buf, replacelen - matchlen); | |
659 | p = buf->s + dp; | |
660 | } | |
661 | if (matchlen != replacelen) { | |
662 | memmove(p+replacelen, p+matchlen, | |
663 | buf->len - (p - buf->s) - matchlen + replacelen + 1); | |
664 | buf->len += (replacelen - matchlen); | |
665 | } | |
666 | if (replace) | |
667 | memcpy(p, replace, replacelen); | |
668 | n++; | |
669 | p += replacelen; | |
670 | } | |
671 | ||
672 | return n; | |
673 | } | |
674 | ||
675 | /* | |
676 | * Compare two struct bufs bytewise. Returns a number | |
677 | * like strcmp(), suitable for sorting e.g. with qsort(), | |
678 | */ | |
679 | int buf_cmp(const struct buf *a, const struct buf *b) | |
680 | { | |
681 | unsigned len = MIN(a->len, b->len); | |
682 | int r = 0; | |
683 | ||
684 | if (len) | |
685 | r = memcmp(a->s, b->s, len); | |
686 | ||
687 | if (!r) { | |
688 | if (a->len < b->len) | |
689 | r = -1; | |
690 | else if (a->len > b->len) | |
691 | r = 1; | |
692 | } | |
693 | ||
694 | return r; | |
695 | } | |
696 | ||
697 | void buf_init(struct buf *buf) | |
698 | { | |
699 | buf->alloc = 0; | |
700 | buf->len = 0; | |
701 | buf->flags = 0; | |
702 | buf->s = NULL; | |
703 | } | |
704 | ||
705 | /* | |
706 | * Initialise a struct buf to point to read-only data. The key here is | |
707 | * setting buf->alloc=0 which indicates CoW is in effect, i.e. the data | |
708 | * pointed to needs to be copied should it ever be modified. | |
709 | */ | |
710 | void buf_init_ro(struct buf *buf, const char *base, int len) | |
711 | { | |
712 | buf->alloc = 0; | |
713 | buf->len = len; | |
714 | buf->flags = 0; | |
715 | buf->s = (char *)base; | |
592 | 716 | } |
593 | 717 | |
594 | 718 | void buf_free(struct buf *buf) |
599 | 723 | buf->s = NULL; |
600 | 724 | buf->len = 0; |
601 | 725 | buf->flags = 0; |
726 | } | |
727 | ||
728 | void buf_move(struct buf *dst, struct buf *src) | |
729 | { | |
730 | if (dst->alloc) | |
731 | free(dst->s); | |
732 | *dst = *src; | |
733 | buf_init(src); | |
602 | 734 | } |
603 | 735 | |
604 | 736 | char *strconcat(const char *s1, ...) |
91 | 91 | #define TOUPPER(c) (convert_to_uppercase[(unsigned char)(c)]) |
92 | 92 | #define TOLOWER(c) (convert_to_lowercase[(unsigned char)(c)]) |
93 | 93 | |
94 | #ifndef MAX | |
95 | #define MAX(x, y) ((x) > (y) ? (x) : (y)) | |
96 | #endif | |
97 | #ifndef MIN | |
98 | #define MIN(x, y) ((x) < (y) ? (x) : (y)) | |
99 | #endif | |
100 | ||
94 | 101 | typedef struct keyvalue { |
95 | 102 | char *key, *value; |
96 | 103 | } keyvalue; |
172 | 179 | unsigned alloc; |
173 | 180 | int flags; |
174 | 181 | }; |
182 | #define BUF_INITIALIZER { NULL, 0, 0, 0 } | |
175 | 183 | |
176 | 184 | const char *buf_cstring(struct buf *buf); |
185 | void buf_ensure(struct buf *buf, int morebytes); | |
177 | 186 | void buf_getmap(struct buf *buf, const char **base, int *len); |
178 | unsigned buf_len(struct buf *buf); | |
187 | unsigned buf_len(const struct buf *buf); | |
179 | 188 | void buf_reset(struct buf *buf); |
180 | void buf_setcstr(struct buf *buf, char *str); | |
181 | void buf_setmap(struct buf *buf, char *base, int len); | |
182 | void buf_copy(struct buf *dst, struct buf *src); | |
183 | void buf_append(struct buf *dst, struct buf *src); | |
184 | void buf_appendcstr(struct buf *buf, char *str); | |
189 | void buf_truncate(struct buf *buf, unsigned int len); | |
190 | void buf_setcstr(struct buf *buf, const char *str); | |
191 | void buf_setmap(struct buf *buf, const char *base, int len); | |
192 | void buf_copy(struct buf *dst, const struct buf *src); | |
193 | void buf_append(struct buf *dst, const struct buf *src); | |
194 | void buf_appendcstr(struct buf *buf, const char *str); | |
185 | 195 | void buf_appendbit32(struct buf *buf, bit32 num); |
186 | void buf_appendmap(struct buf *buf, char *base, int len); | |
196 | void buf_appendmap(struct buf *buf, const char *base, int len); | |
187 | 197 | void buf_putc(struct buf *buf, char c); |
198 | void buf_printf(struct buf *buf, const char *fmt, ...) | |
199 | __attribute__((format(printf,2,3))); | |
200 | unsigned int buf_replace_all(struct buf *buf, const char *match, | |
201 | const char *replace); | |
202 | int buf_cmp(const struct buf *, const struct buf *); | |
203 | void buf_init(struct buf *buf); | |
204 | void buf_init_ro(struct buf *buf, const char *base, int len); | |
188 | 205 | void buf_free(struct buf *buf); |
206 | void buf_move(struct buf *dst, struct buf *src); | |
189 | 207 | |
190 | 208 | /* use getpassphrase on machines which support it */ |
191 | 209 | #ifdef HAVE_GETPASSPHRASE |
588 | 588 | \fImetapartition\fR rather than in the mailbox directory on a spool |
589 | 589 | partition. |
590 | 590 | |
591 | Allowed values: \fIheader\fR, \fIindex\fR, \fIcache\fR, \fIexpunge\fR, \fIsquat\fR, \fIlock\fR | |
591 | Allowed values: \fIheader\fR, \fIindex\fR, \fIcache\fR, \fIexpunge\fR, \fIsquat\fR | |
592 | 592 | .IP "\fBmetapartition-name:\fR <none>" 5 |
593 | 593 | The pathname of the metadata partition \fIname\fR, corresponding to |
594 | 594 | spool partition \fBpartition-name\fR. For any mailbox residing in |
1016 | 1016 | .IP "\fBsuppress_capabilities:\fR <none>" 5 |
1017 | 1017 | Suppress the named capabilities from any capability response. Use the |
1018 | 1018 | exact case as it appears in the response, e.g. |
1019 | "suppress_capabilities: ESEARCH QRESYNC WITHIN XLIST" if you have | |
1020 | a murder with 2.3.x backends and don't want clients being confused | |
1021 | by new capabilities that some backends don't support. | |
1019 | "suppress_capabilities: ESEARCH QRESYNC WITHIN XLIST LIST-EXTENDED" | |
1020 | if you have a murder with 2.3.x backends and don't want clients being | |
1021 | confused by new capabilities that some backends don't support. | |
1022 | 1022 | .IP "\fBstatuscache:\fR 0" 5 |
1023 | 1023 | Enable/disable the imap status cache. |
1024 | 1024 | .IP "\fBstatuscache_db:\fR skiplist" 5 |
123 | 123 | .\" ======================================================================== |
124 | 124 | .\" |
125 | 125 | .IX Title "SIEVESHELL 1" |
126 | .TH SIEVESHELL 1 "2011-09-08" "perl v5.12.4" "User Contributed Perl Documentation" | |
126 | .TH SIEVESHELL 1 "2011-10-04" "perl v5.12.4" "User Contributed Perl Documentation" | |
127 | 127 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes |
128 | 128 | .\" way too many mistakes in technical documents. |
129 | 129 | .if n .ad l |
1176 | 1176 | my $name = $mbx->[0]; |
1177 | 1177 | my $flags = $mbx->[1]; |
1178 | 1178 | next if($flags =~ /(\\noselect|\\nonexistent|\\placeholder)/i); |
1179 | # If id of '*' is passed then delete all existing acls | |
1180 | if ($nargv[1] eq '*') { | |
1181 | my %acl = $$cyrref->listaclmailbox($name); | |
1182 | if (defined $$cyrref->error) { | |
1183 | print($$cyrref->error, "\n"); | |
1184 | next; | |
1185 | } | |
1186 | pop(@nargv); | |
1187 | foreach my $acl (keys %acl) { | |
1188 | push(@nargv, $acl, $acl{$acl}); | |
1189 | } | |
1190 | } | |
1179 | 1191 | print "Deleting acl on $name..."; |
1180 | 1192 | $nargv[0] = $name; |
1181 | 1193 | my $rc = $$cyrref->deleteacl(@nargv); |
1187 | 1199 | } |
1188 | 1200 | } |
1189 | 1201 | } else { |
1202 | # If id of '*' is passed then delete all existing acls | |
1203 | if ($nargv[1] eq '*') { | |
1204 | my %acl = $$cyrref->listaclmailbox($nargv[0]); | |
1205 | if (defined $$cyrref->error) { | |
1206 | print($$cyrref->error, "\n"); | |
1207 | next; | |
1208 | } | |
1209 | pop(@nargv); | |
1210 | foreach my $acl (keys %acl) { | |
1211 | push(@nargv, $acl, $acl{$acl}); | |
1212 | } | |
1213 | } | |
1190 | 1214 | $$cyrref->deleteacl(@nargv) || |
1191 | 1215 | die "deleteaclmailbox: " . $$cyrref->error . "\n"; |
1192 | 1216 | } |
546 | 546 | |
547 | 547 | char *scrname; |
548 | 548 | |
549 | scrname=malloc(strlen(name)+10); | |
550 | strcpy(scrname, name); | |
551 | strcat(scrname, ".script"); | |
549 | scrname = strconcat(name, ".script", (char *)NULL); | |
552 | 550 | |
553 | 551 | stream=fopen(scrname,"w"); |
554 | 552 |
105 | 105 | # $(LEX) -t -Paddr $(srcdir)/addr-lex.l > $@ |
106 | 106 | |
107 | 107 | addr.c addr.h: addr.y |
108 | $(YACC) $(YFLAGS) -p addr $(srcdir)/addr.y | |
108 | $(YACC) $(YFLAGS) $(srcdir)/addr.y | |
109 | 109 | mv -f y.tab.c addr.c |
110 | 110 | mv -f y.tab.h addr.h |
111 | 111 |
69 | 69 | %} |
70 | 70 | |
71 | 71 | %token ATOM QTEXT DTEXT |
72 | ||
72 | %name-prefix "addr" | |
73 | 73 | %% |
74 | 74 | sieve_address: addrspec /* simple address */ |
75 | 75 | | phrase '<' addrspec '>' /* name & addr-spec */ |