]> code.citadel.org Git - citadel.git/blobdiff - citadel/imap_tools.c
* Changed a bunch of localtime() calls to localtime_r(), for great justice.
[citadel.git] / citadel / imap_tools.c
index 15b35627aaf4a4a3750c07596f8ed7e6d266da96..d1f2654fe40449c5e5a4e92cf0f558b249e19214 100644 (file)
 #include "imap_tools.h"
 
 
+#ifndef HAVE_SNPRINTF
+#include "snprintf.h"
+#endif
+
 /*
  * Output a string to the IMAP client, either as a literal or quoted.
  * (We do a literal if it has any double-quotes or backslashes.)
@@ -37,7 +41,7 @@ void imap_strout(char *buf)
        }
 
        if (is_literal) {
-               cprintf("{%d}\r\n%s", strlen(buf), buf);
+               cprintf("{%ld}\r\n%s", (long)strlen(buf), buf);
        } else {
                cprintf("\"%s\"", buf);
        }
@@ -85,29 +89,51 @@ int imap_parameterize(char **args, char *buf)
 }
 
 /*
- * Convert a struct quickroom to an IMAP-compatible mailbox name.
+ * Convert a struct ctdlroom to an IMAP-compatible mailbox name.
  */
-void imap_mailboxname(char *buf, int bufsize, struct quickroom *qrbuf)
+void imap_mailboxname(char *buf, int bufsize, struct ctdlroom *qrbuf)
 {
        struct floor *fl;
+       int i;
+       char buf2[SIZ];
+       int sfstart = 0;
 
        /*
-        * For mailboxes, just do it straight...
+        * For mailboxes, just do it straight.
+        * Do the Cyrus-compatible thing: all private folders are
+        * subfolders of INBOX.
         */
        if (qrbuf->QRflags & QR_MAILBOX) {
                safestrncpy(buf, qrbuf->QRname, bufsize);
                strcpy(buf, &buf[11]);
-               if (!strcasecmp(buf, MAILROOM))
+               if (!strcasecmp(buf, MAILROOM)) {
                        strcpy(buf, "INBOX");
+                       sfstart = 5;
+               }
+               else {
+                       sprintf(buf2, "INBOX/%s", buf);
+                       strcpy(buf, buf2);
+                       sfstart = 6;
+               }
        }
        /*
         * Otherwise, prefix the floor name as a "public folders" moniker
         */
        else {
                fl = cgetfloor(qrbuf->QRfloor);
-               snprintf(buf, bufsize, "%s|%s",
+               snprintf(buf, bufsize, "%s/%s",
                         fl->f_name,
                         qrbuf->QRname);
+               sfstart = strlen(fl->f_name) + 1;
+       }
+
+       /*
+        * Replace delimiter characters with "/" for pseudo-folder-delimiting
+        * and replace actual slashes with "|" because they're illegal here.
+        */
+       for (i=sfstart; i<strlen(buf); ++i) {
+               if (buf[i] == FDELIM) buf[i] = '/';
+               else if (buf[i] == '/') buf[i] = '|';
        }
 }
 
@@ -126,46 +152,60 @@ void imap_mailboxname(char *buf, int bufsize, struct quickroom *qrbuf)
 int imap_roomname(char *rbuf, int bufsize, char *foldername)
 {
        int levels;
-       char buf[SIZ];
+       char floorname[SIZ];
+       char roomname[SIZ];
        int i;
        struct floor *fl;
+       int ret = (-1);
 
-       if (foldername == NULL)
-               return (-1);
-       levels = num_parms(foldername);
-
-       /* When we can support hierarchial mailboxes, take this out. */
-       if (levels > 2)
-               return (-1);
+       if (foldername == NULL) return(-1);
+       levels = num_tokens(foldername, '/');
 
        /*
         * Convert the crispy idiot's reserved names to our reserved names.
+        * Also handle Cyrus-compatible folder names.
         */
        if (!strcasecmp(foldername, "INBOX")) {
                safestrncpy(rbuf, MAILROOM, bufsize);
-               return (0 | IR_MAILBOX);
+               ret = (0 | IR_MAILBOX);
+       }
+       else if (!strncasecmp(foldername, "INBOX/", 6)) {
+               safestrncpy(rbuf, &foldername[6], bufsize);
+               ret = (0 | IR_MAILBOX);
        }
-       if (levels > 1) {
-               extract(buf, foldername, 0);
+       else if (levels > 1) {
+               extract_token(floorname, foldername, 0, '/');
+               strcpy(roomname, &foldername[strlen(floorname)+1]);
                for (i = 0; i < MAXFLOORS; ++i) {
                        fl = cgetfloor(i);
-                       lprintf(9, "floor %d: %s\n", i, fl->f_name);    /* FIXME take out */
                        if (fl->f_flags & F_INUSE) {
-                               if (!strcasecmp(buf, fl->f_name)) {
-                                       extract(rbuf, foldername, 1);
-                                       return (i);
+                               if (!strcasecmp(floorname, fl->f_name)) {
+                                       strcpy(rbuf, roomname);
+                                       ret = i;
                                }
                        }
                }
 
-               /* since we don't allow multi-level yet, fail.
-                  extract(rbuf, buf, 1);
-                  return(0);
-                */
-               return (-1);
+               if (ret < 0) {
+                       /* No subfolderificationalisticism on this one... */
+                       safestrncpy(rbuf, foldername, bufsize);
+                       ret = (0 | IR_MAILBOX);
+               }
+
+       }
+       else {
+               safestrncpy(rbuf, foldername, bufsize);
+               ret = (0 | IR_MAILBOX);
+       }
+
+       /* Undelimiterizationalisticize the room name (change '/' and '|') */
+       for (i=0; i<strlen(rbuf); ++i) {
+               if (rbuf[i] == '/') rbuf[i] = FDELIM;
+               else if (rbuf[i] == '|') rbuf[i] = '/';
        }
-       safestrncpy(rbuf, foldername, bufsize);
-       return (0 | IR_MAILBOX);
+
+       lprintf(CTDL_DEBUG, "(That translates to \"%s\")\n", rbuf);
+       return(ret);
 }
 
 
@@ -241,7 +281,7 @@ int imap_is_message_set(char *buf)
 #define WILDMAT_TRUE   1
 #define WILDMAT_FALSE  0
 #define WILDMAT_ABORT  -1
-#define WILDMAT_DELIM  '|'
+#define WILDMAT_DELIM  '/'
 
 /*
  * Match text and p, return TRUE, FALSE, or ABORT.
@@ -342,3 +382,54 @@ int imap_mailbox_matches_pattern(char *pattern, char *mailboxname)
        }
        return (do_imap_match(mailboxname, pattern) == WILDMAT_TRUE);
 }
+
+
+
+/*
+ * Compare an IMAP date string (date only, no time) to the date found in
+ * a Unix timestamp.
+ */
+int imap_datecmp(char *datestr, time_t msgtime) {
+       char daystr[SIZ];
+       char monthstr[SIZ];
+       char yearstr[SIZ];
+       int i;
+       int day, month, year;
+       int msgday, msgmonth, msgyear;
+       struct tm msgtm;
+
+       if (datestr == NULL) return(0);
+
+       /* Expecting a date in the form dd-Mmm-yyyy */
+       extract_token(daystr, datestr, 0, '-');
+       extract_token(monthstr, datestr, 1, '-');
+       extract_token(yearstr, datestr, 2, '-');
+
+       day = atoi(daystr);
+       year = atoi(yearstr);
+       month = 0;
+       for (i=0; i<12; ++i) {
+               if (!strcasecmp(monthstr, ascmonths[i])) {
+                       month = i;
+               }
+       }
+
+       /* Extract day/month/year from message timestamp */
+       localtime_r(&msgtime, &msgtm);
+       msgday = msgtm.tm_mday;
+       msgmonth = msgtm.tm_mon;
+       msgyear = msgtm.tm_year + 1900;
+
+       /* Now start comparing */
+
+       if (year < msgyear) return(+1);
+       if (year > msgyear) return(-1);
+
+       if (month < msgmonth) return(+1);
+       if (month > msgmonth) return(-1);
+
+       if (day < msgday) return(+1);
+       if (day > msgday) return(-1);
+
+       return(0);
+}