diff -Nur dovecot-2-0-urlauth-58df9942b16b/COPYING dovecot-2.0-urlauth/COPYING
--- dovecot-2-0-urlauth-58df9942b16b/COPYING	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/COPYING	2010-06-11 12:49:32.000000000 -0500
@@ -75,3 +75,37 @@
  not be used in advertising or otherwise to promote the sale, use or other
  dealings in these Data Files or Software without prior written
  authorization of the copyright holder.
+
+CATENATE support in src/imap/cmd-append.c
+src/lib/lib-imap/imap-url.c
+src/lib/lib-imap/imap-url.h
+src/plugins/urlauth/*
+
+ Copyright (c) 2008-2010 Apple Inc. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without  
+ modification, are permitted provided that the following conditions  
+ are met:
+ 
+ 1.  Redistributions of source code must retain the above copyright  
+ notice, this list of conditions and the following disclaimer.
+ 2.  Redistributions in binary form must reproduce the above  
+ copyright notice, this list of conditions and the following  
+ disclaimer in the documentation and/or other materials provided  
+ with the distribution.
+ 3.  Neither the name of Apple Inc. ("Apple") nor the names of its  
+ contributors may be used to endorse or promote products derived  
+ from this software without specific prior written permission.
+ 
+ THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND  
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,  
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A  
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS  
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT  
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF  
+ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND  
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,  
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  
+ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  
+ SUCH DAMAGE.
diff -Nur dovecot-2-0-urlauth-58df9942b16b/configure.in dovecot-2.0-urlauth/configure.in
--- dovecot-2-0-urlauth-58df9942b16b/configure.in	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/configure.in	2010-06-11 12:35:29.000000000 -0500
@@ -2591,7 +2591,7 @@
 dnl **
 
 capability_banner="IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE"
-capability="$capability_banner SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT IDLE CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS"
+capability="$capability_banner SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND CATENATE UNSELECT IDLE CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS"
 AC_DEFINE_UNQUOTED(CAPABILITY_STRING, "$capability", IMAP capabilities)
 AC_DEFINE_UNQUOTED(CAPABILITY_BANNER_STRING, "$capability_banner", IMAP capabilities advertised in banner) 
 
@@ -2683,6 +2683,7 @@
 src/plugins/quota/Makefile
 src/plugins/imap-quota/Makefile
 src/plugins/trash/Makefile
+src/plugins/urlauth/Makefile
 src/plugins/virtual/Makefile
 src/plugins/zlib/Makefile
 src/plugins/imap-zlib/Makefile
diff -Nur dovecot-2-0-urlauth-58df9942b16b/doc/example-config/conf.d/auth.conf dovecot-2.0-urlauth/doc/example-config/conf.d/auth.conf
--- dovecot-2-0-urlauth-58df9942b16b/doc/example-config/conf.d/auth.conf	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/doc/example-config/conf.d/auth.conf	2010-06-11 13:00:01.000000000 -0500
@@ -87,6 +87,7 @@
 # Space separated list of wanted authentication mechanisms:
 #   plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi otp skey
 #   gss-spnego
+# (APPLE) x-plain-submit lets submission server use PLAIN (for BURL) but nobody else
 # NOTE: See also disable_plaintext_auth setting.
 auth_mechanisms = plain
 
@@ -109,6 +110,7 @@
 
 #!include auth-deny.conf.ext
 #!include auth-master.conf.ext
+#!include auth-submit.conf.ext
 !include auth-system.conf.ext
 #!include auth-sql.conf.ext
 #!include auth-ldap.conf.ext
diff -Nur dovecot-2-0-urlauth-58df9942b16b/doc/example-config/conf.d/logging.conf dovecot-2.0-urlauth/doc/example-config/conf.d/logging.conf
--- dovecot-2-0-urlauth-58df9942b16b/doc/example-config/conf.d/logging.conf	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/doc/example-config/conf.d/logging.conf	2010-06-11 12:58:23.000000000 -0500
@@ -38,6 +38,7 @@
 
 # Enable mail process debugging. This can help you figure out why Dovecot
 # isn't finding your mails.
+# (APPLE) This also helps troubleshoot URLFETCH issues.
 #mail_debug = no
 
 # Show protocol level SSL errors.
diff -Nur dovecot-2-0-urlauth-58df9942b16b/doc/example-config/conf.d/plugin.conf dovecot-2.0-urlauth/doc/example-config/conf.d/plugin.conf
--- dovecot-2-0-urlauth-58df9942b16b/doc/example-config/conf.d/plugin.conf	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/doc/example-config/conf.d/plugin.conf	2010-06-11 12:58:55.000000000 -0500
@@ -52,4 +52,8 @@
   # To let users LIST mailboxes shared by other users, Dovecot needs a
   # shared mailbox dictionary. For example:
   #acl_shared_dict = file:/var/lib/dovecot/shared-mailboxes
+
+  # (APPLE) Server name for GENURLAUTH/URLFETCH.  Can be host:port or
+  # just a FQHN.  Default is the system's real hostname.
+  #urlauth_hostport = 
 }
diff -Nur dovecot-2-0-urlauth-58df9942b16b/src/auth/auth-request-handler.c dovecot-2.0-urlauth/src/auth/auth-request-handler.c
--- dovecot-2-0-urlauth-58df9942b16b/src/auth/auth-request-handler.c	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/src/auth/auth-request-handler.c	2010-06-11 12:45:54.000000000 -0500
@@ -513,6 +513,11 @@
 					      "submit_user",
 					      request->submit_user);
 		}
+		if (request->anonymous_username != NULL) {
+			auth_stream_reply_add(request->userdb_reply,
+					      "anonymous_username",
+					      request->anonymous_username);
+		}
 
 		auth_stream_reply_import(reply,
 			auth_stream_reply_export(request->userdb_reply));
diff -Nur dovecot-2-0-urlauth-58df9942b16b/src/auth/auth-request.c dovecot-2.0-urlauth/src/auth/auth-request.c
--- dovecot-2-0-urlauth-58df9942b16b/src/auth/auth-request.c	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/src/auth/auth-request.c	2010-06-11 12:46:40.000000000 -0500
@@ -150,9 +150,14 @@
 	}
 
 	/* APPLE - urlauth */
-        if (request->submit_user != NULL)
+        if (request->submit_user != NULL) {
 		auth_stream_reply_add(reply, "submit_user",
 				      request->submit_user);
+	}
+	if (request->anonymous_username != NULL) {
+		auth_stream_reply_add(reply, "anonymous_username",
+				      request->anonymous_username);
+	}
 
 	auth_stream_reply_add(reply, "original_username",
 			      request->original_username);
@@ -194,6 +199,8 @@
 	/* APPLE - urlauth */
 	else if (strcmp(key, "submit_user") == 0)
 		request->submit_user = p_strdup(request->pool, value);
+	else if (strcmp(key, "anonymous_username") == 0)
+		request->anonymous_username = p_strdup(request->pool, value);
 
 	else if (strcmp(key, "original_username") == 0)
 		request->original_username = p_strdup(request->pool, value);
@@ -352,6 +359,12 @@
 
 	/* APPLE - urlauth */
 	if (submit)
+		request->submit_user = request->user;
+	else	/* reduce code deltas */
+	request->master_user = request->user;
+
+	/* APPLE - urlauth */
+	if (submit)
 		auth_request_log_info(request, "passdb",
 				      "Submit user logging in as %s",
 				      request->requested_login_user);
@@ -359,11 +372,6 @@
 	auth_request_log_info(request, "passdb", "Master user logging in as %s",
 			      request->requested_login_user);
 
-	/* APPLE - urlauth */
-	if (submit)
-		request->submit_user = request->user;
-	else	/* reduce code deltas */
-	request->master_user = request->user;
 	request->user = request->requested_login_user;
 	request->requested_login_user = NULL;
 
diff -Nur dovecot-2-0-urlauth-58df9942b16b/src/auth/auth-request.h dovecot-2.0-urlauth/src/auth/auth-request.h
--- dovecot-2-0-urlauth-58df9942b16b/src/auth/auth-request.h	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/src/auth/auth-request.h	2010-06-11 12:46:54.000000000 -0500
@@ -33,8 +33,9 @@
            user and user is set to requested_login_user. */
         char *user, *requested_login_user, *master_user;
 
-	/* APPLE - urlauth - when the master user is a submission server */
+	/* APPLE - urlauth */
 	char *submit_user;
+	char *anonymous_username;
 
 	/* original_username contains the username exactly as given by the
 	   client. this is needed at least with DIGEST-MD5 for password
diff -Nur dovecot-2-0-urlauth-58df9942b16b/src/auth/auth-settings.c dovecot-2.0-urlauth/src/auth/auth-settings.c
--- dovecot-2-0-urlauth-58df9942b16b/src/auth/auth-settings.c	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/src/auth/auth-settings.c	2010-06-11 12:37:17.000000000 -0500
@@ -104,6 +104,7 @@
 	DEF(SET_BOOL, deny),
 	DEF(SET_BOOL, pass),
 	DEF(SET_BOOL, master),
+	DEF(SET_BOOL, submit),				/* APPLE - urlauth */
 
 	SETTING_DEFINE_LIST_END
 };
@@ -113,7 +114,8 @@
 	.args = "",
 	.deny = FALSE,
 	.pass = FALSE,
-	.master = FALSE
+	.master = FALSE,
+	.submit = FALSE					/* APPLE - urlauth */
 };
 
 const struct setting_parser_info auth_passdb_setting_parser_info = {
diff -Nur dovecot-2-0-urlauth-58df9942b16b/src/auth/auth-settings.h dovecot-2.0-urlauth/src/auth/auth-settings.h
--- dovecot-2-0-urlauth-58df9942b16b/src/auth/auth-settings.h	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/src/auth/auth-settings.h	2010-06-11 12:45:32.000000000 -0500
@@ -10,7 +10,7 @@
 	bool deny;
 	bool pass;
 	bool master;
-	bool submit;
+	bool submit;					/* APPLE - urlauth */
 };
 
 struct auth_userdb_settings {
diff -Nur dovecot-2-0-urlauth-58df9942b16b/src/auth/auth.c dovecot-2.0-urlauth/src/auth/auth.c
--- dovecot-2-0-urlauth-58df9942b16b/src/auth/auth.c	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/src/auth/auth.c	2010-06-11 12:45:20.000000000 -0500
@@ -71,7 +71,8 @@
 
 	/* initialize passdbs first and count them */
 	for (passdb_count = 0, i = 0; i < db_count; i++) {
-		if (passdbs[i]->master)
+		if (passdbs[i]->master ||
+		    passdbs[i]->submit)			/* APPLE - urlauth */
 			continue;
 
 		auth_passdb_preinit(auth, passdbs[i], &auth->passdbs);
@@ -82,15 +83,24 @@
 		i_fatal("Last passdb can't have pass=yes");
 
 	for (i = 0; i < db_count; i++) {
-		if (!passdbs[i]->master)
+		if (!passdbs[i]->master &&
+		    !passdbs[i]->submit)		/* APPLE - urlauth */
 			continue;
 
 		if (passdbs[i]->deny)
-			i_fatal("Master passdb can't have deny=yes");
-		if (passdbs[i]->submit)
+					/* APPLE - urlauth */
+			i_fatal("Master/submit passdb can't have deny=yes");
+
+		/* APPLE - urlauth - Submit user has much less power than
+		   master user.  Forbid both master and submit in one passdb
+		   so that unaware services (pop3, managesieve) don't
+		   compromise security. */
+		if (passdbs[i]->master && passdbs[i]->submit)
 			i_fatal("Passdb can't have master=yes and submit=yes");
+
 		if (passdbs[i]->pass && passdb_count == 0) {
-			i_fatal("Master passdb can't have pass=yes "
+					/* APPLE - urlauth */
+			i_fatal("Master/submit passdb can't have pass=yes "
 				"if there are no passdbs");
 		}
 		auth_passdb_preinit(auth, passdbs[i], &auth->masterdbs);
diff -Nur dovecot-2-0-urlauth-58df9942b16b/src/auth/mech-anonymous.c dovecot-2.0-urlauth/src/auth/mech-anonymous.c
--- dovecot-2-0-urlauth-58df9942b16b/src/auth/mech-anonymous.c	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/src/auth/mech-anonymous.c	2010-06-11 12:37:17.000000000 -0500
@@ -20,6 +20,12 @@
 	request->user = p_strdup(request->pool,
 				 request->set->anonymous_username);
 
+	/* APPLE - urlauth - could add anonymous_username to every reply
+	   but it's only needed (for now) on anonymous auths; let's not
+	   inflate every reply if we don't have to */
+	request->anonymous_username =
+		p_strdup(request->pool, request->set->anonymous_username);
+
 	auth_request_success(request, NULL, 0);
 }
 
diff -Nur dovecot-2-0-urlauth-58df9942b16b/src/imap/cmd-append.c dovecot-2.0-urlauth/src/imap/cmd-append.c
--- dovecot-2-0-urlauth-58df9942b16b/src/imap/cmd-append.c	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/src/imap/cmd-append.c	2010-06-11 12:48:52.000000000 -0500
@@ -615,9 +615,8 @@
 
 static bool args_indicate_catenate(const struct imap_arg *args)
 {
-	while (args->type != IMAP_ARG_EOL) {
-		if (args->type == IMAP_ARG_ATOM &&
-		    strcasecmp(args->_data.str, "CATENATE") == 0)
+	while (!IMAP_ARG_IS_EOL(args)) {
+		if (imap_arg_atom_equals(args, "CATENATE"))
 			return TRUE;
 		args++;
 	}
@@ -1049,13 +1048,13 @@
 	// continuing the CATENATE list
 	if (!imap_arg_get_list(args, &listargs))
 		i_unreached();
-	if (args[1].type != IMAP_ARG_EOL) {
+	if (!IMAP_ARG_IS_EOL(&args[1])) {
 		i_assert(ctx->args == NULL);
 		ctx->args = &args[1];		// MULTIAPPEND
 	}
 	args = listargs;
 
-	if (args->type == IMAP_ARG_EOL) {
+	if (IMAP_ARG_IS_EOL(args)) {
 		/* end of CATENATE list.  finish the message and return
 		   to regular MULTIAPPEND processing */
 		client->input_skip_line = ctx->args == NULL;
@@ -1277,8 +1276,9 @@
 		}
 	}
 
-	/* [<internal date>] */
-	if (imap_arg_get_astring(args, &str)) {
+	/* [<internal date>]
+	   MUST be a STRING only, no atom or literal */
+	if (args->type == IMAP_ARG_STRING && imap_arg_get_string(args, &str)) {
 		++args;
 
 		if (!imap_parse_datetime(str, &internal_date,
@@ -1307,12 +1307,12 @@
 
 	/* MULTIAPPEND syntax on a single line, e.g.:
 	   APPEND <mailbox> CATENATE (URL <url>) CATENATE (... */
-	if (args[2].type != IMAP_ARG_EOL)
+	if (!IMAP_ARG_IS_EOL(&args[2]))
 		ctx->args = &args[2];
 
 	// remainder of CATENATE parsing cares only about the items in the list
 	args = listargs;
-	if (args->type == IMAP_ARG_EOL) {	// empty list
+	if (IMAP_ARG_IS_EOL(args)) {	// empty list
 		client_send_tagline(cmd, "BAD Invalid arguments.");
 		if (keywords != NULL)
 			mailbox_keywords_unref(ctx->box, &keywords);
@@ -1386,12 +1386,12 @@
 
 	/* MULTIAPPEND syntax on a single line, e.g.:
 	   APPEND <mailbox> CATENATE (URL <url>) CATENATE (... */
-	if (args[2].type != IMAP_ARG_EOL)
+	if (!IMAP_ARG_IS_EOL(&args[2]))
 		ctx->args = &args[2];
 
 	// remainder of CATENATE parsing cares only about the items in the list
 	args = listargs;
-	if (args->type == IMAP_ARG_EOL)		// empty list
+	if (IMAP_ARG_IS_EOL(args))		// empty list
 		return catenate_cancel(ctx, nonsync);
 
 	return catenate_cancel_args(cmd, args, nonsync);
@@ -1403,8 +1403,7 @@
 	struct cmd_append_context *ctx = cmd->context;
 
 	/* [URL <url>] ... [URL <literal>] */
-	while (args->type == IMAP_ARG_ATOM &&
-	       strcasecmp(args->_data.str, "URL") == 0) {
+	while (imap_arg_atom_equals(args, "URL")) {
 		if (++ctx->cat.parts > MAX_CATENATE_PARTS) {
 			client_send_tagline(cmd,
 					    "BAD Too many message parts.");
@@ -1435,8 +1434,7 @@
 	}
 
 	/* [TEXT <literal>] */
-	if (args->type == IMAP_ARG_ATOM &&
-	    strcasecmp(args->_data.str, "TEXT") == 0 &&
+	if (imap_arg_atom_equals(args, "TEXT") &&
 	    (args[1].type == IMAP_ARG_LITERAL_SIZE ||
 	     args[1].type == IMAP_ARG_LITERAL_SIZE_NONSYNC)) {
 		if (++ctx->cat.parts > MAX_CATENATE_PARTS) {
@@ -1455,7 +1453,7 @@
 		catenate_solicit(ctx, nonsync);
 		cmd->func = catenate_continue_text;
 		return catenate_continue_text(cmd);
-	} else if (args->type != IMAP_ARG_EOL) {
+	} else if (!IMAP_ARG_IS_EOL(args)) {
 		client_send_tagline(cmd, "BAD Invalid arguments.");
 		return catenate_cancel(ctx, nonsync);
 	}
@@ -1469,8 +1467,7 @@
 	struct cmd_append_context *ctx = cmd->context;
 
 	/* [URL <url>] ... [URL <literal>] */
-	while (args->type == IMAP_ARG_ATOM &&
-	       strcasecmp(args->_data.str, "URL") == 0) {
+	while (imap_arg_atom_equals(args, "URL")) {
 		++args;
 		if (args->type == IMAP_ARG_ATOM ||
 		    args->type == IMAP_ARG_STRING)
@@ -1481,12 +1478,11 @@
 	}
 
 	/* [TEXT <literal>] */
-	if (args->type == IMAP_ARG_ATOM &&
-	    strcasecmp(args->_data.str, "TEXT") == 0 &&
+	if (imap_arg_atom_equals(args, "TEXT") &&
 	    (args[1].type == IMAP_ARG_LITERAL_SIZE ||
 	     args[1].type == IMAP_ARG_LITERAL_SIZE_NONSYNC))
 		return catenate_cancel(ctx, nonsync);
-	else if (args->type != IMAP_ARG_EOL)
+	else if (!IMAP_ARG_IS_EOL(args))
 		return catenate_cancel(ctx, nonsync);
 
 	return catenate_finish(ctx, TRUE);
diff -Nur dovecot-2-0-urlauth-58df9942b16b/src/imap/imap-client.c dovecot-2.0-urlauth/src/imap/imap-client.c
--- dovecot-2-0-urlauth-58df9942b16b/src/imap/imap-client.c	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/src/imap/imap-client.c	2010-06-11 12:48:19.000000000 -0500
@@ -66,7 +66,9 @@
 	client->command_pool =
 		pool_alloconly_create(MEMPOOL_GROWING"client command", 1024*2);
 	client->user = user;
-	client->submit = mail_user_plugin_getenv(user, "submit_user") != NULL;   /* APPLE - urlauth */
+
+	/* APPLE - urlauth */
+	client->submit = mail_user_plugin_getenv(user, "submit_user") != NULL;
 
 	mail_namespaces_set_storage_callbacks(user->namespaces,
 					      &mail_storage_callbacks, client);
diff -Nur dovecot-2-0-urlauth-58df9942b16b/src/plugins/acl/acl-storage.c dovecot-2.0-urlauth/src/plugins/acl/acl-storage.c
--- dovecot-2-0-urlauth-58df9942b16b/src/plugins/acl/acl-storage.c	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/src/plugins/acl/acl-storage.c	2010-06-11 12:47:56.000000000 -0500
@@ -35,6 +35,7 @@
 
 	auser->acl_env = env;
 	auser->master_user = mail_user_plugin_getenv(user, "master_user");
+	/* APPLE - urlauth */
 	auser->submit_user = mail_user_plugin_getenv(user, "submit_user");
 
 	env = mail_user_plugin_getenv(user, "acl_groups");
diff -Nur dovecot-2-0-urlauth-58df9942b16b/src/plugins/urlauth/Makefile.am dovecot-2.0-urlauth/src/plugins/urlauth/Makefile.am
--- dovecot-2-0-urlauth-58df9942b16b/src/plugins/urlauth/Makefile.am	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/src/plugins/urlauth/Makefile.am	2010-06-11 12:47:25.000000000 -0500
@@ -37,12 +37,10 @@
 	-I$(top_srcdir)/src/lib-storage \
 	-I$(top_srcdir)/src/imap
 
-imap_moduledir = $(moduledir)/imap
-
 lib10_urlauth_plugin_la_LDFLAGS = -module -avoid-version
 lib10_urlauth_plugin_la_LIBADD = -lcrypto
 
-imap_module_LTLIBRARIES = \
+module_LTLIBRARIES = \
 	lib10_urlauth_plugin.la
 
 lib10_urlauth_plugin_la_SOURCES = \
diff -Nur dovecot-2-0-urlauth-58df9942b16b/src/plugins/urlauth/urlauth-keys.c dovecot-2.0-urlauth/src/plugins/urlauth/urlauth-keys.c
--- dovecot-2-0-urlauth-58df9942b16b/src/plugins/urlauth/urlauth-keys.c	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/src/plugins/urlauth/urlauth-keys.c	2010-06-11 12:47:43.000000000 -0500
@@ -186,7 +186,7 @@
 			hash_table_insert(keys, (void *) box->name,
 					  (void *) hex);
 			modified = TRUE;
-		} /* else mailbox="" for foiling timing attacks */
+		} /* else box->name="" for foiling timing attacks */
 		break;
 	case URLAUTH_KEYS_DELETE:
 		hex = hash_table_lookup(keys, (void *) box->name);
diff -Nur dovecot-2-0-urlauth-58df9942b16b/src/plugins/urlauth/urlauth-plugin.c dovecot-2.0-urlauth/src/plugins/urlauth/urlauth-plugin.c
--- dovecot-2-0-urlauth-58df9942b16b/src/plugins/urlauth/urlauth-plugin.c	2010-04-10 03:41:50.000000000 -0500
+++ dovecot-2.0-urlauth/src/plugins/urlauth/urlauth-plugin.c	2010-06-11 12:47:13.000000000 -0500
@@ -41,6 +41,7 @@
 #include "ostream.h"
 #include "mail-user.h"
 #include "mail-search.h"
+#include "mail-storage-private.h"
 #include "imap-fetch.h"
 #include "imap-search-args.h"
 #include "urlauth-plugin.h"
@@ -279,13 +280,13 @@
 static int urlfetch_url(struct urlfetch_context *ufctx, const char **error)
 {
 	struct imap_url_parts enc_parts, dec_parts;
-	bool authorized = FALSE;
+	bool authorized = FALSE, foil = FALSE;
 	buffer_t *key;
 	string_t *urlauth, *fetch_text;
 	struct mail_namespace *ns;
 	struct mailbox_status status;
 	const struct imap_arg *fetch_args = NULL, *next_arg = NULL;
-	const char *mailbox;
+	const char *mailbox, *foilbox;
 
 	memset(&enc_parts, 0, sizeof enc_parts);
 	memset(&dec_parts, 0, sizeof dec_parts);
@@ -312,7 +313,9 @@
 		authorized = TRUE;
 	} else if (strcasecmp(dec_parts.access, "authuser") == 0) {
 		/* any non-anonymous user */
-		const char *anonymous = getenv("AUTH_ANONYMOUS_USERNAME");
+		const char *anonymous =
+			mail_user_plugin_getenv(ufctx->cmd->client->user,
+						"anonymous_username");
 		authorized = anonymous == NULL ||
 			strcmp(ufctx->cmd->client->user->username,
 			       anonymous) != 0;
@@ -322,7 +325,10 @@
 				    ufctx->cmd->client->user->username) == 0;
 	} else if (strncasecmp(dec_parts.access, "submit+", 7) == 0) {
 		/* logged-in user via submit-user login */
-		authorized = mail_user_plugin_getenv(ufctx->cmd->client->user, "submit_user") != NULL &&
+		const char *submit =
+			mail_user_plugin_getenv(ufctx->cmd->client->user,
+						"submit_user");
+		authorized = submit != NULL &&
 			strcmp(dec_parts.access + 7,
 			       ufctx->cmd->client->user->username) == 0;
 	}
@@ -339,19 +345,24 @@
 	if (ns == NULL) {
 		// invent a key to foil timing attacks
 		ns = client_find_namespace(ufctx->cmd, "INBOX", &mailbox, NULL);
+		foil = TRUE;
 	}
 	ufctx->box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_READONLY |
 				   MAILBOX_FLAG_KEEP_RECENT);
+	foilbox = ufctx->box->name;
+	if (foil)
+		ufctx->box->name = "";
 	if (!urlauth_keys_get(ufctx->box, key)) {
 		*error = "can't get mailbox key";
+		ufctx->box->name = foilbox;
 		return -1;
 	}
+	ufctx->box->name = foilbox;
 
 	// generate an access token and compare it to the one given
 	urlauth = t_str_new(strlen(dec_parts.urlauth));
 	urlauth_urlauth_generate_internal(enc_parts.rump, key, urlauth);
-	if (strcasecmp(dec_parts.urlauth, str_c(urlauth)) != 0 ||
-	    *mailbox == '\0') {
+	if (strcasecmp(dec_parts.urlauth, str_c(urlauth)) != 0 || foil) {
 		*error = "access token mismatch";
 		return -1;
 	}
