warning fixes
[apps/madmutt.git] / imap / imap.c
index 06e14ed..db9901a 100644 (file)
@@ -18,7 +18,6 @@
 #include "mutt.h"
 #include "ascii.h"
 #include "buffer.h"
-#include "mutt_curses.h"
 #include "mx.h"
 #include "globals.h"
 #include "sort.h"
@@ -183,7 +182,7 @@ void imap_logout_all (void)
 /* imap_read_literal: read bytes bytes from server into file. Not explicitly
  *   buffered, relies on FILE buffering. NOTE: strips \r from \r\n.
  *   Apparently even literals use \r\n-terminated strings ?! */
-int imap_read_literal (FILE * fp, IMAP_DATA * idata, long bytes)
+int imap_read_literal (FILE * fp, IMAP_DATA * idata, long bytes, progress_t* bar)
 {
   long pos;
   char c;
@@ -212,8 +211,10 @@ int imap_read_literal (FILE * fp, IMAP_DATA * idata, long bytes)
       r = 0;
 #endif
     fputc (c, fp);
+    if (bar && !(pos % 1024))
+      mutt_progress_bar (bar, pos);
 #ifdef DEBUG
-    if (DebugLevel >= IMAP_LOG_LTRL)
+    if (DebugFile && DebugLevel >= IMAP_LOG_LTRL)
       fputc (c, DebugFile);
 #endif
   }
@@ -433,10 +434,8 @@ int imap_open_connection (IMAP_DATA * idata)
         if ((rc = imap_exec (idata, "STARTTLS", IMAP_CMD_FAIL_OK)) == -1)
           goto bail;
         if (rc != -2) {
-#ifdef USE_SSL
+#if defined (USE_SSL) || defined (USE_GNUTLS)
           if (mutt_ssl_starttls (idata->conn))
-#elif USE_GNUTLS
-          if (mutt_gnutls_starttls (idata->conn))
 #endif
           {
             mutt_error (_("Could not negotiate TLS connection"));
@@ -1137,9 +1136,12 @@ int imap_check_mailbox (CONTEXT * ctx, int *index_hint, int force)
   return result;
 }
 
-/* returns count of recent messages if new = 1, else count of total messages.
- * (useful for at least postponed function)
- * Question of taste: use RECENT or UNSEEN for new?
+/*
+ * count messages:
+ *      new == 1:  recent
+ *      new == 2:  unseen
+ *      otherwise: total
+ * return:
  *   0+   number of messages in mailbox
  *  -1    error while polling mailboxes
  */
@@ -1187,7 +1189,7 @@ int imap_mailbox_check (char *path, int new)
   else if (mutt_bit_isset (idata->capabilities, IMAP4REV1) ||
            mutt_bit_isset (idata->capabilities, STATUS)) {
     snprintf (buf, sizeof (buf), "STATUS %s (%s)", mbox,
-              new ? "RECENT" : "MESSAGES");
+              new == 1 ? "RECENT" : (new == 2 ? "UNSEEN" : "MESSAGES"));
   }
   else
     /* Server does not support STATUS, and this is not the current mailbox.
@@ -1226,6 +1228,138 @@ int imap_mailbox_check (char *path, int new)
   return msgcount;
 }
 
+/* returns number of patterns in the search that should be done server-side
+ * (eg are full-text) */
+static int do_search (const pattern_t* search, int allpats)
+{
+  int rc = 0;
+  const pattern_t* pat;
+
+  for (pat = search; pat; pat = pat->next) {
+    switch (pat->op) {
+      case M_BODY:
+      case M_HEADER:
+      case M_WHOLE_MSG:
+        if (pat->stringmatch)
+          rc++;
+        break;
+      default:
+      if (pat->child && do_search (pat->child, 1))
+        rc++;
+    }
+
+    if (!allpats)
+      break;
+  }
+
+  return rc;
+}
+
+/* convert mutt pattern_t to IMAP SEARCH command containing only elements
+* that require full-text search (mutt already has what it needs for most
+* match types, and does a better job (eg server doesn't support regexps). */
+static int imap_compile_search (const pattern_t* pat, BUFFER* buf)
+{
+  if (! do_search (pat, 0))
+    return 0;
+
+  if (pat->not)
+    mutt_buffer_addstr (buf, "NOT ");
+
+  if (pat->child) {
+    int clauses;
+
+    if ((clauses = do_search (pat->child, 1)) > 0) {
+      const pattern_t* clause = pat->child;
+
+      mutt_buffer_addch (buf, '(');
+
+      while (clauses) {
+        if (do_search (clause, 0)) {
+          if (pat->op == M_OR && clauses > 1)
+            mutt_buffer_addstr (buf, "OR ");
+          clauses--;
+          if (imap_compile_search (clause, buf) < 0)
+            return -1;
+
+          if (clauses)
+            mutt_buffer_addch (buf, ' ');
+          
+          clause = clause->next;
+        }
+      }
+
+      mutt_buffer_addch (buf, ')');
+    }
+  } else {
+    char term[STRING];
+    char *delim;
+
+    switch (pat->op) {
+      case M_HEADER:
+        mutt_buffer_addstr (buf, "HEADER ");
+
+        /* extract header name */
+        if (! (delim = strchr (pat->str, ':'))) {
+          mutt_error (_("Header search without header name: %s"), pat->str);
+          return -1;
+        }
+        *delim = '\0';
+        imap_quote_string (term, sizeof (term), pat->str);
+        mutt_buffer_addstr (buf, term);
+        mutt_buffer_addch (buf, ' ');
+
+        /* and field */
+        *delim = ':';
+        delim++;
+        SKIPWS(delim);
+        imap_quote_string (term, sizeof (term), delim);
+        mutt_buffer_addstr (buf, term);
+        break;
+
+      case M_BODY:
+        mutt_buffer_addstr (buf, "BODY ");
+        imap_quote_string (term, sizeof (term), pat->str);
+        mutt_buffer_addstr (buf, term);
+        break;
+
+      case M_WHOLE_MSG:
+        mutt_buffer_addstr (buf, "TEXT ");
+        imap_quote_string (term, sizeof (term), pat->str);
+        mutt_buffer_addstr (buf, term);
+      break;
+    }
+  }
+
+  return 0;
+}
+
+int imap_search (CONTEXT* ctx, const pattern_t* pat) {
+  BUFFER buf;
+  IMAP_DATA* idata = (IMAP_DATA*)ctx->data;
+  int i;
+
+  for (i = 0; i < ctx->msgcount; i++)
+    ctx->hdrs[i]->matched = 0;
+
+  if (!do_search (pat, 1))
+    return 0;
+
+  memset (&buf, 0, sizeof (buf));
+  mutt_buffer_addstr (&buf, "UID SEARCH ");
+  if (imap_compile_search (pat, &buf) < 0) {
+    mem_free (&buf.data);
+    return -1;
+  }
+  if (imap_exec (idata, buf.data, 0) < 0) {
+    mem_free (&buf.data);
+    return -1;
+  }
+
+  mem_free (&buf.data);
+  return 0;
+}
+
 /* all this listing/browsing is a mess. I don't like that name is a pointer
  *   into idata->buf (used to be a pointer into the passed in buffer, just
  *   as bad), nor do I like the fact that the fetch is done here. This
@@ -1310,7 +1444,7 @@ int imap_subscribe (char *path, int subscribe)
   BUFFER err, token;
   IMAP_MBOX mx;
 
-  if (mx_get_magic (path) == M_IMAP || imap_parse_path (path, &mx)) {
+  if (mx_get_magic (path) != M_IMAP || imap_parse_path (path, &mx) < 0) {
     mutt_error (_("Bad mailbox name"));
     return -1;
   }
@@ -1388,7 +1522,7 @@ static int imap_complete_hosts (char *dest, size_t len) {
     }
   }
 
-  for (conn = mutt_socket_head (); conn->next; conn = conn->next) {
+  for (conn = mutt_socket_head (); conn && conn->next; conn = conn->next) {
     ciss_url_t url;
     char urlstr[LONG_STRING];