dovecot-2.2: lib-imap: Added IMAP URL parser.
dovecot at dovecot.org
dovecot at dovecot.org
Sat Jun 2 19:02:27 EEST 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/9eef4f7b0187
changeset: 14590:9eef4f7b0187
user: Stephan Bosch <stephan at rename-it.nl>
date: Sat Jun 02 17:53:31 2012 +0300
description:
lib-imap: Added IMAP URL parser.
Includes support for IMAP URLAUTH URLs.
Includes extensive testsuite.
Creation of IMAP URL string from struct data is not implemented and
deferred to a future patch when this functionality is needed.
diffstat:
src/lib-imap/Makefile.am | 7 +
src/lib-imap/imap-url.c | 936 +++++++++++++++++++++++++++++++++++++++++++
src/lib-imap/imap-url.h | 70 +++
src/lib-imap/test-imap-url.c | 900 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 1913 insertions(+), 0 deletions(-)
diffs (truncated from 1956 to 300 lines):
diff -r c54dd35e1c0e -r 9eef4f7b0187 src/lib-imap/Makefile.am
--- a/src/lib-imap/Makefile.am Sat Jun 02 17:15:18 2012 +0300
+++ b/src/lib-imap/Makefile.am Sat Jun 02 17:53:31 2012 +0300
@@ -16,6 +16,7 @@
imap-match.c \
imap-parser.c \
imap-quote.c \
+ imap-url.c \
imap-seqset.c \
imap-utf7.c \
imap-util.c
@@ -31,6 +32,7 @@
imap-parser.h \
imap-resp-code.h \
imap-quote.h \
+ imap-url.h \
imap-seqset.h \
imap-utf7.h \
imap-util.h
@@ -41,6 +43,7 @@
test_programs = \
test-imap-match \
test-imap-parser \
+ test-imap-url \
test-imap-utf7 \
test-imap-util
@@ -58,6 +61,10 @@
test_imap_parser_LDADD = imap-parser.lo imap-arg.lo $(test_libs)
test_imap_parser_DEPENDENCIES = imap-parser.lo imap-arg.lo $(test_libs)
+test_imap_url_SOURCES = test-imap-url.c
+test_imap_url_LDADD = imap-url.lo $(test_libs)
+test_imap_url_DEPENDENCIES = imap-url.lo $(test_libs)
+
test_imap_utf7_SOURCES = test-imap-utf7.c
test_imap_utf7_LDADD = imap-utf7.lo $(test_libs)
test_imap_utf7_DEPENDENCIES = imap-utf7.lo $(test_libs)
diff -r c54dd35e1c0e -r 9eef4f7b0187 src/lib-imap/imap-url.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-imap/imap-url.c Sat Jun 02 17:53:31 2012 +0300
@@ -0,0 +1,936 @@
+/* Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "str.h"
+#include "strfuncs.h"
+#include "str-sanitize.h"
+#include "hex-binary.h"
+#include "network.h"
+#include "iso8601-date.h"
+#include "uri-util.h"
+
+#include "imap-url.h"
+
+#include <ctype.h>
+
+/*
+ * IMAP URL parsing
+ */
+
+/*
+IMAP URL Grammar overview
+
+RFC5092 Section 11:
+
+imapurl = "imap://" iserver ipath-query
+ ; Defines an absolute IMAP URL
+iserver = [iuserinfo "@"] host [ ":" port ]
+ ; This is the same as "authority" defined in [URI-GEN].
+iuserinfo = enc-user [iauth] / [enc-user] iauth
+ ; conforms to the generic syntax of "userinfo" as
+ ; defined in [URI-GEN].
+enc-user = 1*achar
+ ; %-encoded version of [IMAP4] authorization identity or
+ ; "userid".
+iauth = ";AUTH=" ( "*" / enc-auth-type )
+enc-auth-type = 1*achar
+ ; %-encoded version of [IMAP4] "auth-type"
+ipath-query = ["/" [ icommand ]]
+ ; Corresponds to "path-abempty [ "?" query ]" in
+ ; [URI-GEN]
+icommand = imessagelist /
+ imessagepart [iurlauth]
+imessagelist = imailbox-ref [ "?" enc-search ]
+ ; "enc-search" is [URI-GEN] "query".
+imessagepart = imailbox-ref iuid [isection] [ipartial]
+imailbox-ref = enc-mailbox [uidvalidity]
+uidvalidity = ";UIDVALIDITY=" nz-number
+ ; See [IMAP4] for "nz-number" definition
+iuid = "/" iuid-only
+iuid-only = ";UID=" nz-number
+ ; See [IMAP4] for "nz-number" definition
+isection = "/" isection-only
+isection-only = ";SECTION=" enc-section
+ipartial = "/" ipartial-only
+ipartial-only = ";PARTIAL=" partial-range
+enc-search = 1*bchar
+ ; %-encoded version of [IMAPABNF]
+ ; "search-program". Note that IMAP4
+ ; literals may not be used in
+ ; a "search-program", i.e., only
+ ; quoted or non-synchronizing
+ ; literals (if the server supports
+ ; LITERAL+ [LITERAL+]) are allowed.
+enc-mailbox = 1*bchar
+ ; %-encoded version of [IMAP4] "mailbox"
+enc-section = 1*bchar
+ ; %-encoded version of [IMAP4] "section-spec"
+partial-range = number ["." nz-number]
+ ; partial FETCH. The first number is
+ ; the offset of the first byte,
+ ; the second number is the length of
+ ; the fragment.
+bchar = achar / ":" / "@" / "/"
+achar = uchar / "&" / "="
+ ;; Same as [URI-GEN] 'unreserved / sub-delims /
+ ;; pct-encoded', but ";" is disallowed.
+uchar = unreserved / sub-delims-sh / pct-encoded
+sub-delims-sh = "!" / "$" / "'" / "(" / ")" /
+ "*" / "+" / ","
+ ;; Same as [URI-GEN] sub-delims,
+ ;; but without ";", "&" and "=".
+
+The following rules are only used in the presence of the IMAP
+[URLAUTH] extension:
+
+authimapurl = "imap://" iserver "/" imessagepart
+ ; Same as "imapurl" when "[icommand]" is
+ ; "imessagepart"
+authimapurlfull = authimapurl iurlauth
+ ; Same as "imapurl" when "[icommand]" is
+ ; "imessagepart iurlauth"
+authimapurlrump = authimapurl iurlauth-rump
+
+iurlauth = iurlauth-rump iua-verifier
+enc-urlauth = 32*HEXDIG
+iua-verifier = ":" uauth-mechanism ":" enc-urlauth
+iurlauth-rump = [expire] ";URLAUTH=" access
+access = ("submit+" enc-user) / ("user+" enc-user) /
+ "authuser" / "anonymous"
+expire = ";EXPIRE=" date-time
+ ; date-time is defined in [DATETIME]
+uauth-mechanism = "INTERNAL" / 1*(ALPHA / DIGIT / "-" / ".")
+ ; Case-insensitive.
+
+[URI-GEN] RFC3986 Appendix A:
+
+Implemented in src/lib/uri-util.c
+
+*/
+
+/*
+ * Imap URL parser
+ */
+
+struct imap_url_parser {
+ struct uri_parser parser;
+
+ enum imap_url_parse_flags flags;
+
+ struct imap_url *url;
+ struct imap_url *base;
+
+ unsigned int relative:1;
+};
+
+static int
+imap_url_parse_number(struct uri_parser *parser, const char *data,
+ uint32_t *number_r)
+{
+ uint32_t number = 0;
+ const char *p = data;
+
+ /* [IMAP4] RFC3501, Section 9
+ *
+ * number = 1*DIGIT
+ * ; Unsigned 32-bit integer
+ * ; (0 <= n < 4,294,967,296)
+ */
+
+ if (i_isdigit(*p)) {
+ do {
+ uint32_t prev = number;
+
+ number = number * 10 + (*p - '0');
+ if (number < prev) {
+ parser->error = "IMAP number is too high";
+ return -1;
+ }
+ p++;
+ } while (i_isdigit(*p));
+
+ if (*p == '\0') {
+ if (number_r != NULL)
+ *number_r = number;
+ return 1;
+ }
+ }
+
+ parser->error = t_strdup_printf(
+ "Value '%s' is not a valid IMAP number", data);
+ return -1;
+}
+
+static int
+imap_url_parse_offset(struct uri_parser *parser, const char *data,
+ uoff_t *number_r)
+{
+ uoff_t number = 0;
+ const char *p = data;
+
+ /* Syntax for big (uoff_t) numbers. Not strictly IMAP syntax, but this
+ is handled similarly for Dovecot IMAP FETCH BODY partial <.>
+ implementation. */
+ if (i_isdigit(*p)) {
+ do {
+ uoff_t prev = number;
+
+ number = number * 10 + (*p - '0');
+ if (number < prev) {
+ parser->error = "IMAP number is too high";
+ return -1;
+ }
+ p++;
+ } while (i_isdigit(*p));
+
+ if (*p == '\0') {
+ if (number_r != NULL)
+ *number_r = number;
+ return 1;
+ }
+ }
+
+ parser->error = t_strdup_printf(
+ "Value '%s' is not a valid IMAP number", data);
+ return -1;
+}
+
+static int imap_url_parse_iserver(struct imap_url_parser *url_parser)
+{
+ struct uri_parser *parser = &url_parser->parser;
+ struct uri_authority auth;
+ struct imap_url *url = url_parser->url;
+ const char *data;
+ int ret = 0;
+
+ /* imapurl = "imap://" iserver {...}
+ * inetwork-path = "//" iserver {...}
+ * iserver = [iuserinfo "@"] host [":" port]
+ * ; This is the same as "authority" defined
+ * ; in [URI-GEN].
+ * iuserinfo = enc-user [iauth] / [enc-user] iauth
+ * ; conforms to the generic syntax of "userinfo" as
+ * ; defined in [URI-GEN].
+ * enc-user = 1*achar
+ * ; %-encoded version of [IMAP4] authorization identity or
+ * ; "userid".
+ * iauth = ";AUTH=" ( "*" / enc-auth-type )
+ * enc-auth-type = 1*achar
+ * ; %-encoded version of [IMAP4] "auth-type"
+ */
+
+ /* "//" iserver */
+ if ((ret = uri_parse_authority(parser, &auth)) <= 0)
+ return ret;
+
+ /* iuserinfo = enc-user [iauth] / [enc-user] iauth */
+ if (auth.enc_userinfo != NULL) {
+ const char *p;
+
+ /* Scan for ";AUTH=" */
+ p = strchr(auth.enc_userinfo, ';');
+ if (p != NULL) {
+ if (strncasecmp(p, ";AUTH=",6) != 0) {
+ parser->error = t_strdup_printf(
+ "Stray ';' in userinfo `%s'",
+ auth.enc_userinfo);
+ return -1;
+ }
+
+ if (strchr(p+1, ';') != NULL) {
+ parser->error = "Stray ';' after `;AUTH='";
+ return -1;
+ }
+ }
+
+ /* enc-user */
+ if (url != NULL && p != auth.enc_userinfo) {
+ if (!uri_data_decode(parser, auth.enc_userinfo, p, &data))
+ return -1;
+ url->userid = p_strdup(parser->pool, data);
+ }
+
+ /* ( "*" / enc-auth-type ) */
+ if (p != NULL) {
+ p += 6;
+ if (*p == '\0') {
+ parser->error = "Empty auth-type value after ';AUTH='";
More information about the dovecot-cvs
mailing list