[prev in list] [next in list] [prev in thread] [next in thread] 

List:       sylpheed
Subject:    [sylpheed:14622] IMAP & double quote in strings
From:       Thomas HERAULT <Thomas.Herault () lri ! fr>
Date:       2002-06-27 13:04:54
[Download RAW message or body]

Hello,

I've had a problem with IMAP implementation : when a '"' is in strings,
the current quotation algorithm isn't working. According to IMAP4rev1's
rfc (rfc 2060), strings including a '"' a \n or a \r must be written using
literal strings technique. This technique is as follow : the size of the
string is sended first between matching braces, then on continuation
request from server side,  the data of the string followed by the rest
of the command should be sended. (like this :)

C> A2 LOGIN myAccount {24}
S> +  Ready for additional command text
C> myFucking"PassWithQuotes
S> A2 OK LOGIN completed

The attached patch implements this literal string notation at the level
of imap_cmd_gen_send, by checking if a %s is requested, then looking
if the %s should be quoted, literal transmitted, or simply put. It's working
for me. It let me type my Fucking Password with double quotes, log in
and also create folders with double quotes, which wasn't working before.

Cheers, T. Herault

["imap.c.patch" (application/octet-stream)]

--- sylpheed-0.7.8/src/imap.c	Sun Jun  9 14:22:54 2002
+++ sylpheed-0.7.8-patch/src/imap.c	Wed Jun 26 17:11:27 2002
@@ -54,21 +54,6 @@
 #define IMAPS_PORT	993
 #endif
 
-#define QUOTE_IF_REQUIRED(out, str)				\
-{								\
-	if (*str != '"' && strpbrk(str, " \t(){}%*") != NULL) {	\
-		gchar *__tmp;					\
-		gint len;					\
-								\
-		len = strlen(str) + 3;				\
-		Xalloca(__tmp, len, return IMAP_ERROR);		\
-		g_snprintf(__tmp, len, "\"%s\"", str);		\
-		out = __tmp;					\
-	} else {						\
-		Xstrdup_a(out, str, return IMAP_ERROR);		\
-	}							\
-}
-
 static GList *session_list = NULL;
 
 static gint imap_cmd_count = 0;
@@ -233,6 +218,8 @@
 
 static gint imap_cmd_ok		(SockInfo	*sock,
 				 GPtrArray	*argbuf);
+static gint imap_cmd_cont       (SockInfo       *sock,
+				 GPtrArray      *argbuf);
 static void imap_cmd_gen_send	(SockInfo	*sock,
 				 const gchar	*format, ...);
 static gint imap_cmd_gen_recv	(SockInfo	*sock,
@@ -1013,7 +1000,6 @@
 
 	Xstrcat_a(wildcard_path, real_path, wildcard,
 		  {g_free(real_path); return IMAP_ERROR;});
-	QUOTE_IF_REQUIRED(wildcard_path, wildcard_path);
 
 	imap_cmd_gen_send(SESSION(session)->sock, "LIST \"\" %s",
 			  wildcard_path);
@@ -2271,7 +2257,6 @@
 			gint *unseen)
 {
 	gchar *real_path;
-	gchar *real_path_;
 	gint ok;
 	GPtrArray *argbuf;
 	gchar *str;
@@ -2281,10 +2266,9 @@
 	argbuf = g_ptr_array_new();
 
 	real_path = imap_get_real_path(folder, path);
-	QUOTE_IF_REQUIRED(real_path_, real_path);
 	imap_cmd_gen_send(SESSION(session)->sock, "STATUS %s "
 			  "(MESSAGES RECENT UIDNEXT UIDVALIDITY UNSEEN)",
-			  real_path_);
+			  real_path);
 
 	ok = imap_cmd_ok(SESSION(session)->sock, argbuf);
 	if (ok != IMAP_SUCCESS) THROW(ok);
@@ -2335,12 +2319,9 @@
 static gint imap_cmd_login(SockInfo *sock,
 			   const gchar *user, const gchar *pass)
 {
-	gchar *user_, *pass_;
 	gint ok;
 
-	QUOTE_IF_REQUIRED(user_, user);
-	QUOTE_IF_REQUIRED(pass_, pass);
-	imap_cmd_gen_send(sock, "LOGIN %s %s", user_, pass_);
+	imap_cmd_gen_send(sock, "LOGIN %s %s", user, pass);
 
 	ok = imap_cmd_ok(sock, NULL);
 	if (ok != IMAP_SUCCESS)
@@ -2397,14 +2378,10 @@
 static gint imap_cmd_list(SockInfo *sock, const gchar *ref,
 			  const gchar *mailbox, GPtrArray *argbuf)
 {
-	gchar *ref_, *mailbox_;
-
 	if (!ref) ref = "\"\"";
 	if (!mailbox) mailbox = "\"\"";
 
-	QUOTE_IF_REQUIRED(ref_, ref);
-	QUOTE_IF_REQUIRED(mailbox_, mailbox);
-	imap_cmd_gen_send(sock, "LIST %s %s", ref_, mailbox_);
+	imap_cmd_gen_send(sock, "LIST %s %s", ref, mailbox);
 
 	return imap_cmd_ok(sock, argbuf);
 }
@@ -2420,7 +2397,6 @@
 	gchar *resp_str;
 	GPtrArray *argbuf;
 	gchar *select_cmd;
-	gchar *folder_;
 
 	*exists = *recent = *unseen = *uid_validity = 0;
 	argbuf = g_ptr_array_new();
@@ -2430,8 +2406,7 @@
 	else
 		select_cmd = "SELECT";
 
-	QUOTE_IF_REQUIRED(folder_, folder);
-	imap_cmd_gen_send(sock, "%s %s", select_cmd, folder_);
+	imap_cmd_gen_send(sock, "%s %s", select_cmd, folder);
 
 	if ((ok = imap_cmd_ok(sock, argbuf)) != IMAP_SUCCESS) THROW;
 
@@ -2495,10 +2470,7 @@
 
 static gint imap_cmd_create(SockInfo *sock, const gchar *folder)
 {
-	gchar *folder_;
-
-	QUOTE_IF_REQUIRED(folder_, folder);
-	imap_cmd_gen_send(sock, "CREATE %s", folder_);
+	imap_cmd_gen_send(sock, "CREATE %s", folder);
 
 	return imap_cmd_ok(sock, NULL);
 }
@@ -2506,21 +2478,14 @@
 static gint imap_cmd_rename(SockInfo *sock, const gchar *old_folder,
 			    const gchar *new_folder)
 {
-	gchar *old_folder_, *new_folder_;
-
-	QUOTE_IF_REQUIRED(old_folder_, old_folder);
-	QUOTE_IF_REQUIRED(new_folder_, new_folder);
-	imap_cmd_gen_send(sock, "RENAME %s %s", old_folder_, new_folder_);
+	imap_cmd_gen_send(sock, "RENAME %s %s", old_folder, new_folder);
 
 	return imap_cmd_ok(sock, NULL);
 }
 
 static gint imap_cmd_delete(SockInfo *sock, const gchar *folder)
 {
-	gchar *folder_;
-
-	QUOTE_IF_REQUIRED(folder_, folder);
-	imap_cmd_gen_send(sock, "DELETE %s", folder_);
+	imap_cmd_gen_send(sock, "DELETE %s", folder);
 
 	return imap_cmd_ok(sock, NULL);
 }
@@ -2574,7 +2539,6 @@
 {
 	gint ok;
 	gint size;
-	gchar *destfolder_;
 	gchar buf[BUFFSIZE];
 	FILE *fp;
 
@@ -2585,12 +2549,11 @@
 		FILE_OP_ERROR(file, "fopen");
 		return -1;
 	}
-	QUOTE_IF_REQUIRED(destfolder_, destfolder);
-	imap_cmd_gen_send(sock, "APPEND %s (\\Seen) {%d}", destfolder_, size);
+	imap_cmd_gen_send(sock, "APPEND %s (\\Seen) {%d}", destfolder, size);
 
 	ok = imap_cmd_gen_recv(sock, buf, sizeof(buf));
 	if (ok != IMAP_SUCCESS || buf[0] != '+' || buf[1] != ' ') {
-		log_warning(_("can't append %s to %s\n"), file, destfolder_);
+		log_warning(_("can't append %s to %s\n"), file, destfolder);
 		fclose(fp);
 		return IMAP_ERROR;
 	}
@@ -2622,16 +2585,14 @@
 static gint imap_cmd_copy(SockInfo *sock, guint32 uid, const gchar *destfolder)
 {
 	gint ok;
-	gchar *destfolder_;
 
 	g_return_val_if_fail(destfolder != NULL, IMAP_ERROR);
 
-	QUOTE_IF_REQUIRED(destfolder_, destfolder);
-	imap_cmd_gen_send(sock, "UID COPY %d %s", uid, destfolder_);
+	imap_cmd_gen_send(sock, "UID COPY %d %s", uid, destfolder);
 
 	ok = imap_cmd_ok(sock, NULL);
 	if (ok != IMAP_SUCCESS) {
-		log_warning(_("can't copy %d to %s\n"), uid, destfolder_);
+		log_warning(_("can't copy %d to %s\n"), uid, destfolder);
 		return -1;
 	}
 
@@ -2651,9 +2612,11 @@
 			   gchar *sub_cmd)
 {
 	gint ok;
+	gchar cmd[IMAPBUFSIZE];
+	
+	sprintf(cmd, "UID STORE %%d:%%d %s", sub_cmd);
 
-	imap_cmd_gen_send(sock, "UID STORE %d:%d %s",
-			  first_uid, last_uid, sub_cmd);
+	imap_cmd_gen_send(sock, cmd, first_uid, last_uid);
 
 	if ((ok = imap_cmd_ok(sock, NULL)) != IMAP_SUCCESS) {
 		log_warning(_("error while imap command: STORE %d:%d %s\n"),
@@ -2706,27 +2669,88 @@
 	return ok;
 }
 
+static gint imap_cmd_continue(SockInfo *sock, GPtrArray *argbuf)
+{
+	gint cont;
+	gchar buf[IMAPBUFSIZE];
+	gint cmd_num;
+	gchar cmd_status[IMAPBUFSIZE];
+
+	cont = imap_cmd_gen_recv(sock, buf, sizeof(buf));
+	if(cont == IMAP_SUCCESS) {
+		if (buf[0] == '+' && buf[1] == ' ') {
+			if (argbuf)
+				g_ptr_array_add(argbuf, g_strdup(buf + 2));
+			return IMAP_SUCCESS;
+		}
+		return IMAP_ERROR;
+	}
+	
+	return cont;
+}
+
 static void imap_cmd_gen_send(SockInfo *sock, const gchar *format, ...)
 {
 	gchar buf[IMAPBUFSIZE];
 	gchar tmp[IMAPBUFSIZE];
 	gchar *p;
+	int pl;
 	va_list args;
 
-	va_start(args, format);
-	g_vsnprintf(tmp, sizeof(tmp), format, args);
-	va_end(args);
-
 	imap_cmd_count++;
+	bzero(buf, IMAPBUFSIZE);
+	sprintf(buf, "%d ", imap_cmd_count);
 
-	g_snprintf(buf, sizeof(buf), "%d %s\r\n", imap_cmd_count, tmp);
-	if (!strncasecmp(tmp, "LOGIN ", 6) && (p = strchr(tmp + 6, ' '))) {
-		*p = '\0';
-		log_print("IMAP4> %d %s ********\n", imap_cmd_count, tmp);
-	} else
-		log_print("IMAP4> %d %s\n", imap_cmd_count, tmp);
-
-	sock_write(sock, buf, strlen(buf));
+	va_start(args, format);
+	while(*format) {
+	  if(*format == '%')
+	    {
+	      format++;
+	      switch(*format) {
+	      case '%': 
+		buf[strlen(buf)] = '%'; 
+		break;
+	      case 's': 
+		p = va_arg(args, char *);
+		if( strpbrk(p, "\"") )
+		  {
+		    pl = strlen(p);
+		    sprintf(tmp, "%s{%d}\r\n", buf, pl);
+		    sock_write(sock, tmp, strlen(tmp));
+		    bzero(buf, IMAPBUFSIZE);
+		    if(imap_cmd_continue(sock, NULL) != IMAP_SUCCESS)
+		      {
+			log_message("IMAP4 !!!!!! server does not agree to continue\n");
+			return ;
+		      }
+		    sprintf(buf, "%s", p);
+		  } else if( strpbrk(p, " \t(){}%*")) {
+		    strcat(buf, "\"");
+		    strcat(buf, p);
+		    strcat(buf, "\"");
+		  } else {
+		    strcat(buf, p);
+		  }
+		break;
+	      case 'd':
+		sprintf(tmp, "%d", va_arg(args, int));
+		strcat(buf, tmp);
+		break;
+	      default :
+		log_message("IMAP4 !!!!!! Flag non-implemented. Expect crash\n");
+	      }
+	    }
+	  else {
+	    buf[strlen(buf)] = *format;
+	  }
+	  format++;
+	}
+	va_end(args);
+	if(strlen(buf))
+	  {
+	    strcat(buf, "\r\n");
+	    sock_write(sock, buf, strlen(buf));
+	  }
 }
 
 static gint imap_cmd_gen_recv(SockInfo *sock, gchar *buf, gint size)


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic