From 6e3d1bfe88fed0d85e85b0efcb53d702c4fcd22a Mon Sep 17 00:00:00 2001
From: alexm <alexm@zephirlidar.com>
Date: Wed, 14 Aug 2013 13:36:41 +0100
Subject: [PATCH 2/2] Created a new custom request handler.

Instead of having list perform all the custom requests, I've modified 
the code so custom requests are handled separately. This avoids the 
need to add a new line in imap_endofresp for each type of request the user performs.
---
 lib/imap.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++----------------
 lib/imap.h |  1 +
 2 files changed, 66 insertions(+), 22 deletions(-)

diff --git a/lib/imap.c b/lib/imap.c
index a8d9519..b93ff5d 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -302,13 +302,7 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
         break;
 
       case IMAP_LIST:
-        if((!imap->custom && !imap_matchresp(line, len, "LIST")) ||
-          (imap->custom && !imap_matchresp(line, len, imap->custom) &&
-           (strcmp(imap->custom, "STORE") ||
-            !imap_matchresp(line, len, "FETCH")) &&
-           strcmp(imap->custom, "SELECT") &&
-           strcmp(imap->custom, "EXAMINE") &&
-           strcmp(imap->custom, "SEARCH")))
+        if(!imap_matchresp(line, len, "LIST"))
           return FALSE;
         break;
 
@@ -322,6 +316,10 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
           return FALSE;
         break;
 
+      case IMAP_CUSTOM:
+        /* The user could be requesting anything, so don't check. */
+        break;
+
       /* Ignore other untagged responses */
       default:
         return FALSE;
@@ -642,27 +640,42 @@ static CURLcode imap_perform_list(struct connectdata *conn)
   struct IMAP *imap = data->req.protop;
   char *mailbox;
 
-  if(imap->custom)
-    /* Send the custom request */
-    result = imap_sendf(conn, "%s%s", imap->custom,
-                        imap->custom_params ? imap->custom_params : "");
-  else {
-    /* Make sure the mailbox is in the correct atom format */
-    mailbox = imap_atom(imap->mailbox ? imap->mailbox : "");
-    if(!mailbox)
-      return CURLE_OUT_OF_MEMORY;
+  /* Make sure the mailbox is in the correct atom format */
+  mailbox = imap_atom(imap->mailbox ? imap->mailbox : "");
+  if(!mailbox)
+    return CURLE_OUT_OF_MEMORY;
 
-    /* Send the LIST command */
-    result = imap_sendf(conn, "LIST \"%s\" *", mailbox);
-
-    Curl_safefree(mailbox);
-  }
+  /* Send the LIST command */
+  result = imap_sendf(conn, "LIST \"%s\" *", mailbox);
 
+  Curl_safefree(mailbox);
   if(!result)
     state(conn, IMAP_LIST);
 
   return result;
 }
+/***********************************************************************
+ *
+ * imap_perform_custom()
+ *
+ * Sends a custom request.
+ */
+static CURLcode imap_perform_custom(struct connectdata *conn)
+{
+  CURLcode result = CURLE_OK;
+  struct SessionHandle *data = conn->data;
+  struct IMAP *imap = data->req.protop;
+  char *mailbox;
+
+  /* Send the custom request */
+  result = imap_sendf(conn, "%s%s", imap->custom,
+                      imap->custom_params ? imap->custom_params : "");
+
+  if(!result)
+    state(conn, IMAP_CUSTOM);
+
+  return result;
+}
 
 /***********************************************************************
  *
@@ -1343,7 +1356,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
       imapc->mailbox = strdup(imap->mailbox);
 
       if(imap->custom)
-        result = imap_perform_list(conn);
+        result = imap_perform_custom(conn);
       else
         result = imap_perform_fetch(conn);
     }
@@ -1356,6 +1369,32 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
   return result;
 }
 
+/* For custom responses */
+static CURLcode imap_state_custom_resp(struct connectdata *conn, int imapcode,
+                                     imapstate instate)
+{
+  CURLcode result = CURLE_OK;
+  char *line = conn->data->state.buffer;
+  size_t len = strlen(line);
+
+  (void)instate; /* No use for this yet */
+
+  if(imapcode == '*') {
+    /* Temporarily add the LF character back and send as body to the client */
+    line[len] = '\n';
+    result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
+    line[len] = '\0';
+  }
+  else if(imapcode != 'O')
+    result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */
+  else
+    /* End of DO phase */
+    state(conn, IMAP_STOP);
+
+  return result;
+}
+
+
 /* For the (first line of the) FETCH responses */
 static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
                                       imapstate instate)
@@ -1609,6 +1648,10 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
       result = imap_state_select_resp(conn, imapcode, imapc->state);
       break;
 
+    case IMAP_CUSTOM:
+      result = imap_state_custom_resp(conn, imapcode, imapc->state);
+      break;
+
     case IMAP_FETCH:
       result = imap_state_fetch_resp(conn, imapcode, imapc->state);
       break;
diff --git a/lib/imap.h b/lib/imap.h
index bc0a83d..72513c6 100644
--- a/lib/imap.h
+++ b/lib/imap.h
@@ -47,6 +47,7 @@ typedef enum {
   IMAP_LOGIN,
   IMAP_LIST,
   IMAP_SELECT,
+  IMAP_CUSTOM,
   IMAP_FETCH,
   IMAP_FETCH_FINAL,
   IMAP_APPEND,
-- 
1.7.11.msysgit.1

