changeset 883:39e0b536e708 HEAD

Storage can now specify if errors should be sent to user as BAD or NO. Some changes to messageset parsing as specified by latest IMAP4rev1 draft. Bad charset error is prefixed with [BADCHARSET]. Fixed a crash in SEARCH the last commit in it caused.
author Timo Sirainen <tss@iki.fi>
date Thu, 02 Jan 2003 12:21:41 +0200
parents 38b3bc6ddcc4
children c5897896c4f1
files src/imap/cmd-close.c src/imap/cmd-search.c src/imap/commands-util.c src/lib-storage/index/index-messageset.c src/lib-storage/index/index-search.c src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/mail-storage.c src/lib-storage/mail-storage.h
diffstat 9 files changed, 84 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/cmd-close.c	Thu Jan 02 11:34:01 2003 +0200
+++ b/src/imap/cmd-close.c	Thu Jan 02 12:21:41 2003 +0200
@@ -5,8 +5,12 @@
 
 static void client_send_untagged_storage_error(Client *client)
 {
-	client_send_line(client, t_strconcat("* NO ",
-		client->storage->get_last_error(client->storage), NULL));
+	const char *error;
+	int syntax;
+
+	error = client->storage->get_last_error(client->storage, &syntax);
+	client_send_line(client,
+			 t_strconcat(syntax ? "* BAD " : "* NO ", error, NULL));
 }
 
 int cmd_close(Client *client)
--- a/src/imap/cmd-search.c	Thu Jan 02 11:34:01 2003 +0200
+++ b/src/imap/cmd-search.c	Thu Jan 02 12:21:41 2003 +0200
@@ -52,8 +52,11 @@
 		if (client->mailbox->search(client->mailbox, charset,
 					    sargs, NULL,
 					    client->output, client->cmd_uid)) {
-			/* NOTE: syncing isn't allowed here */
-			client_sync_without_expunges(client);
+			/* NOTE: syncing is allowed when returning UIDs */
+			if (client->cmd_uid)
+				client_sync_full(client);
+			else
+				client_sync_without_expunges(client);
 			client_send_tagline(client, "OK Search completed.");
 		} else {
 			client_send_storage_error(client);
--- a/src/imap/commands-util.c	Thu Jan 02 11:34:01 2003 +0200
+++ b/src/imap/commands-util.c	Thu Jan 02 12:21:41 2003 +0200
@@ -98,6 +98,9 @@
 
 void client_send_storage_error(Client *client)
 {
+	const char *error;
+	int syntax;
+
 	if (client->mailbox != NULL &&
 	    client->mailbox->is_inconsistency_error(client->mailbox)) {
 		/* we can't do forced CLOSE, so have to disconnect */
@@ -107,8 +110,9 @@
 		return;
 	}
 
-	client_send_tagline(client, t_strconcat("NO ",
-		client->storage->get_last_error(client->storage), NULL));
+	error = client->storage->get_last_error(client->storage, &syntax);
+	client_send_tagline(client, t_strconcat(syntax ? "BAD " : "NO ",
+						error, NULL));
 }
 
 int client_parse_mail_flags(Client *client, ImapArg *args, size_t args_count,
--- a/src/lib-storage/index/index-messageset.c	Thu Jan 02 11:34:01 2003 +0200
+++ b/src/lib-storage/index/index-messageset.c	Thu Jan 02 12:21:41 2003 +0200
@@ -24,22 +24,18 @@
 
 static int mail_index_foreach(MailIndex *index,
 			      unsigned int seq, unsigned int seq2,
-			      MsgsetForeachFunc func, void *context,
-			      const char **error)
+			      MsgsetForeachFunc func, void *context)
 {
 	MailIndexRecord *rec;
 	const ModifyLogExpunge *expunges;
-	unsigned int idx_seq, expunges_before;
+	unsigned int idx_seq, expunges_before, temp;
 	int expunges_found;
 
 	if (seq > seq2) {
-		/* Second sequence can't be smaller than first - we could swap
-		   them but I think it's a bug in client if it does this,
-		   and better complain about it immediately than later let
-		   them wonder why it doesn't work with other imapds.. */
-		*error = t_strdup_printf("Invalid messageset range: %u > %u",
-					 seq, seq2);
-		return -2;
+		/* swap, as specified by latest IMAP4rev1 spec */
+		temp = seq;
+		seq = seq2;
+		seq2 = temp;
 	}
 
 	/* get list of expunged messages in our range. the expunges_before
@@ -108,8 +104,8 @@
 
 	*error = NULL;
 	if (messages_count == 0) {
-		/* no messages in mailbox */
-		return 1;
+		*error = "No messages in mailbox";
+		return -2;
 	}
 
 	all_found = TRUE;
@@ -168,8 +164,7 @@
 		}
 
 		t_push();
-		ret = mail_index_foreach(index, seq, seq2,
-					 func, context, error);
+		ret = mail_index_foreach(index, seq, seq2, func, context);
 		t_pop();
 		if (ret <= 0)
 			return ret;
@@ -182,19 +177,18 @@
 
 static int mail_index_uid_foreach(MailIndex *index,
 				  unsigned int uid, unsigned int uid2,
-				  MsgsetForeachFunc func, void *context,
-				  const char **error)
+				  MsgsetForeachFunc func, void *context)
 {
 	MailIndexRecord *rec;
 	const ModifyLogExpunge *expunges;
-	unsigned int client_seq, idx_seq, expunges_before;
+	unsigned int client_seq, idx_seq, expunges_before, temp;
 	int expunges_found;
 
 	if (uid > uid2) {
-		/* not allowed - see mail_index_foreach() */
-		*error = t_strdup_printf("Invalid uidset range: %u > %u",
-					 uid, uid2);
-		return -2;
+		/* swap, as specified by latest IMAP4rev1 spec */
+		temp = uid;
+		uid = uid2;
+		uid2 = temp;
 	}
 
 	/* get list of expunged messages in our range. */
@@ -290,12 +284,6 @@
 				}
 			} else {
 				uid2 = index->header->next_uid-1;
-				if (uid2 < uid) {
-					/* allow requesting "n:*" where n is
-					   larger than the actual (synced)
-					   messages count */
-					uid2 = uid;
-				}
 				input++;
 			}
 		}
@@ -308,18 +296,14 @@
 			return -2;
 		}
 
-		if (uid >= index->header->next_uid) {
-			/* too large .. ignore silently */
-		} else {
-			t_push();
-			ret = mail_index_uid_foreach(index, uid, uid2,
-						     func, context, error);
-			t_pop();
-			if (ret <= 0)
-				return ret;
-			if (ret == 2)
-				all_found = FALSE;
-		}
+		t_push();
+		ret = mail_index_uid_foreach(index, uid, uid2,
+					     func, context);
+		t_pop();
+		if (ret <= 0)
+			return ret;
+		if (ret == 2)
+			all_found = FALSE;
 	}
 
 	return all_found ? 1 : 2;
@@ -345,7 +329,8 @@
 	if (ret < 0) {
 		if (ret == -2) {
 			/* user error */
-			mail_storage_set_error(ibox->box.storage, "%s", error);
+			mail_storage_set_syntax_error(ibox->box.storage,
+						      "%s", error);
 		} else {
 			mail_storage_set_index_error(ibox);
 		}
--- a/src/lib-storage/index/index-search.c	Thu Jan 02 11:34:01 2003 +0200
+++ b/src/lib-storage/index/index-search.c	Thu Jan 02 12:21:41 2003 +0200
@@ -26,7 +26,7 @@
 		(arg)->result = !(arg)->not ? (res) : -(res); \
 	} STMT_END
 
-#define TXT_UNKNOWN_CHARSET "Unknown charset"
+#define TXT_UNKNOWN_CHARSET "[BADCHARSET] Unknown charset"
 #define TXT_INVALID_SEARCH_KEY "Invalid search key"
 
 typedef struct {
@@ -406,6 +406,12 @@
 				break;
 			}
 
+			if (field == NULL) {
+				/* doesn't exist */
+				ret = 0;
+				break;
+			}
+
 			hdr_search_ctx = search_header_context(ctx, arg);
 			if (hdr_search_ctx == NULL) {
 				ret = 0;
--- a/src/lib-storage/index/maildir/maildir-storage.c	Thu Jan 02 11:34:01 2003 +0200
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Thu Jan 02 12:21:41 2003 +0200
@@ -538,7 +538,9 @@
 	NULL,
 	NULL,
 	NULL,
-	NULL, NULL
+	NULL, NULL,
+
+	0
 };
 
 Mailbox maildir_mailbox = {
--- a/src/lib-storage/index/mbox/mbox-storage.c	Thu Jan 02 11:34:01 2003 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Thu Jan 02 12:21:41 2003 +0200
@@ -513,7 +513,9 @@
 	NULL,
 	NULL,
 	NULL,
-	NULL, NULL
+	NULL, NULL,
+
+	0
 };
 
 Mailbox mbox_mailbox = {
--- a/src/lib-storage/mail-storage.c	Thu Jan 02 11:34:01 2003 +0200
+++ b/src/lib-storage/mail-storage.c	Thu Jan 02 12:21:41 2003 +0200
@@ -127,6 +127,8 @@
 {
 	i_free(storage->error);
 	storage->error = NULL;
+
+	storage->syntax_error = FALSE;
 }
 
 void mail_storage_set_error(MailStorage *storage, const char *fmt, ...)
@@ -140,6 +142,23 @@
 	else {
 		va_start(va, fmt);
 		storage->error = i_strdup_vprintf(fmt, va);
+		storage->syntax_error = FALSE;
+		va_end(va);
+	}
+}
+
+void mail_storage_set_syntax_error(MailStorage *storage, const char *fmt, ...)
+{
+	va_list va;
+
+	i_free(storage->error);
+
+	if (fmt == NULL)
+		storage->error = NULL;
+	else {
+		va_start(va, fmt);
+		storage->error = i_strdup_vprintf(fmt, va);
+		storage->syntax_error = TRUE;
 		va_end(va);
 	}
 }
@@ -153,6 +172,7 @@
 
 	storage->error = strftime(str, sizeof(str), CRITICAL_MSG, tm) > 0 ?
 		i_strdup(str) : i_strdup("Internal error");
+	storage->syntax_error = FALSE;
 }
 
 void mail_storage_set_critical(MailStorage *storage, const char *fmt, ...)
@@ -174,8 +194,10 @@
 	}
 }
 
-const char *mail_storage_get_last_error(MailStorage *storage)
+const char *mail_storage_get_last_error(MailStorage *storage, int *syntax)
 {
+	if (syntax != NULL)
+		*syntax = storage->syntax_error;
 	return storage->error;
 }
 
--- a/src/lib-storage/mail-storage.h	Thu Jan 02 11:34:01 2003 +0200
+++ b/src/lib-storage/mail-storage.h	Thu Jan 02 12:21:41 2003 +0200
@@ -111,7 +111,7 @@
 				       MailboxNameStatus *status);
 
 	/* Returns the error message of last occured error. */
-	const char *(*get_last_error)(MailStorage *storage);
+	const char *(*get_last_error)(MailStorage *storage, int *syntax_error);
 
 /* private: */
 	char *dir; /* root directory */
@@ -123,6 +123,8 @@
 
 	MailStorageCallbacks *callbacks;
 	void *callback_context;
+
+	unsigned int syntax_error:1; /* Give a BAD reply instead of NO */
 };
 
 struct _Mailbox {
@@ -282,11 +284,13 @@
 void mail_storage_clear_error(MailStorage *storage);
 void mail_storage_set_error(MailStorage *storage, const char *fmt, ...)
 	__attr_format__(2, 3);
+void mail_storage_set_syntax_error(MailStorage *storage, const char *fmt, ...)
+	__attr_format__(2, 3);
 void mail_storage_set_critical(MailStorage *storage, const char *fmt, ...)
 	__attr_format__(2, 3);
 void mail_storage_set_internal_error(MailStorage *storage);
 
-const char *mail_storage_get_last_error(MailStorage *storage);
+const char *mail_storage_get_last_error(MailStorage *storage, int *syntax);
 int mail_storage_is_inconsistency_error(Mailbox *box);
 
 #endif