X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fimap%2Fimap_tools.c;h=e3cc6bffce11a878c15b5f25e8783ae4c51ccd89;hb=721e2cc8f2ea53d2b3b21c7fb0bda27138545006;hp=7173d3adb7e39321a58abdd6b78e92b202317c3e;hpb=9f3b914e91665cb14de25b5c80658c184f374b70;p=citadel.git diff --git a/citadel/modules/imap/imap_tools.c b/citadel/modules/imap/imap_tools.c index 7173d3adb..e3cc6bffc 100644 --- a/citadel/modules/imap/imap_tools.c +++ b/citadel/modules/imap/imap_tools.c @@ -1,12 +1,10 @@ /* - * $Id$ - * * Utility functions for the IMAP module. * * Copyright (c) 2001-2009 by the citadel.org team and others, except for * most of the UTF7 and UTF8 handling code which was lifted from Evolution. * - * This program is free software; you can redistribute it and/or modify + * This program is open source software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. @@ -21,17 +19,19 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define SHOW_ME_VAPPEND_PRINTF #include #include #include #include #include +#include #include #include "citadel.h" #include "sysdep_decls.h" #include "internet_addressing.h" -#include "imap_tools.h" #include "serv_imap.h" +#include "imap_tools.h" #include "ctdl_module.h" #ifndef HAVE_SNPRINTF @@ -84,7 +84,7 @@ static void string_append_sn(struct string* s, char* p, int len) static void string_append_c(struct string* s, int c) { - char buf[5]; + char UmlChar[5]; int len = 0; /* Don't do anything if there's no room. */ @@ -102,27 +102,27 @@ static void string_append_c(struct string* s, int c) } else if (c <= 0x7FF) { - buf[0] = 0xC0 | (c >> 6); - buf[1] = 0x80 | (c & 0x3F); + UmlChar[0] = 0xC0 | (c >> 6); + UmlChar[1] = 0x80 | (c & 0x3F); len = 2; } else if (c <= 0xFFFF) { - buf[0] = 0xE0 | (c >> 12); - buf[1] = 0x80 | ((c >> 6) & 0x3f); - buf[2] = 0x80 | (c & 0x3f); + UmlChar[0] = 0xE0 | (c >> 12); + UmlChar[1] = 0x80 | ((c >> 6) & 0x3f); + UmlChar[2] = 0x80 | (c & 0x3f); len = 3; } else { - buf[0] = 0xf0 | c >> 18; - buf[1] = 0x80 | ((c >> 12) & 0x3f); - buf[2] = 0x80 | ((c >> 6) & 0x3f); - buf[3] = 0x80 | (c & 0x3f); + UmlChar[0] = 0xf0 | c >> 18; + UmlChar[1] = 0x80 | ((c >> 12) & 0x3f); + UmlChar[2] = 0x80 | ((c >> 6) & 0x3f); + UmlChar[3] = 0x80 | (c & 0x3f); len = 4; } - string_append_sn(s, buf, len); + string_append_sn(s, UmlChar, len); } /* Reads a UTF8 character from a char*, advancing the pointer. */ @@ -225,7 +225,7 @@ static char* toimap(char* destp, char* destend, char* src) *destp = 0; string_init(&dest, destp, destend-destp); - /* CtdlLogPrintf(CTDL_DEBUG, "toimap %s\r\n", src); */ + /* IMAP_syslog(LOG_DEBUG, "toimap %s", src); */ for (;;) { @@ -291,7 +291,7 @@ static char* toimap(char* destp, char* destend, char* src) if (state == 1) utf7_closeb64(&dest, v, i); - /* CtdlLogPrintf(CTDL_DEBUG, " -> %s\r\n", destp); */ + /* IMAP_syslog(LOG_DEBUG, " -> %s", destp); */ return string_end(&dest); } @@ -309,7 +309,7 @@ static char* fromimap(char* destp, char* destend, const char* src) *destp = 0; string_init(&dest, destp, destend-destp); - /* CtdlLogPrintf(CTDL_DEBUG, "fromimap %s\r\n", src); */ + /* IMAP_syslog(LOG_DEBUG, "fromimap %s", src); */ do { c = *p++; @@ -367,7 +367,7 @@ static char* fromimap(char* destp, char* destend, const char* src) } } while (c != '\0'); - /* CtdlLogPrintf(CTDL_DEBUG, " -> %s\r\n", destp); */ + /* IMAP_syslog(LOG_DEBUG, " -> %s", destp); */ return string_end(&dest); } @@ -383,59 +383,6 @@ static int cfrommap(int c) return c; } -/* 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.) */ - -void plain_imap_strout(char *buf) -{ - int i; - int is_literal = 0; - long len; - - if (buf == NULL) { /* yeah, we handle this */ - cprintf("NIL"); - return; - } - - len = strlen(buf); - for (i = 0; i < len; ++i) { - if ((buf[i] == '\"') || (buf[i] == '\\')) - is_literal = 1; - } - - if (is_literal) { - cprintf("{%ld}\r\n%s", len, buf); - } else { - cprintf("\"%s\"", buf); - } -} - -/* 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.) */ - -void imap_strout(ConstStr *args) -{ - int i; - int is_literal = 0; - - if ((args == NULL) || (args->len == 0)) - { /* yeah, we handle this */ - cprintf("NIL"); - return; - } - - for (i = 0; i < args->len; ++i) { - if ((args->Key[i] == '\"') || (args->Key[i] == '\\')) - is_literal = 1; - } - - if (is_literal) { - cprintf("{%ld}\r\n%s", args->len, args->Key); - } else { - cprintf("\"%s\"", args->Key); - } -} - @@ -606,65 +553,6 @@ int imap_parameterize(citimap_command *Cmd) return Cmd->num_parms; } -int old_imap_parameterize(char** args, char *in) -{ - char* out = in; - int num = 0; - - for (;;) - { - /* Skip whitespace. */ - - while (isspace(*in)) - in++; - if (*in == 0) - break; - - /* Found the start of a token. */ - - args[num++] = out; - - /* Read in the token. */ - - for (;;) - { - int c = *in++; - if (isspace(c)) - break; - - if (c == '\"') - { - /* Found a quoted section. */ - - for (;;) - { - c = *in++; - if (c == '\"') - break; - else if (c == '\\') - c = *in++; - - *out++ = c; - if (c == 0) - return num; - } - } - else if (c == '\\') - { - c = *in++; - *out++ = c; - } - else - *out++ = c; - - if (c == 0) - return num; - } - *out++ = '\0'; - } - - return num; -} /* Convert a struct ctdlroom to an IMAP-compatible mailbox name. */ @@ -681,13 +569,13 @@ void imap_mailboxname(char *buf, int bufsize, struct ctdlroom *qrbuf) if (qrbuf->QRflags & QR_MAILBOX) { if (strcasecmp(qrbuf->QRname+11, MAILROOM) == 0) - p = toimap(p, bufend, "INBOX"); + toimap(p, bufend, "INBOX"); else { p = toimap(p, bufend, "INBOX"); if (p < bufend) *p++ = '/'; - p = toimap(p, bufend, qrbuf->QRname+11); + toimap(p, bufend, qrbuf->QRname+11); } } else @@ -698,7 +586,7 @@ void imap_mailboxname(char *buf, int bufsize, struct ctdlroom *qrbuf) p = toimap(p, bufend, fl->f_name); if (p < bufend) *p++ = '/'; - p = toimap(p, bufend, qrbuf->QRname); + toimap(p, bufend, qrbuf->QRname); } } @@ -716,8 +604,9 @@ void imap_mailboxname(char *buf, int bufsize, struct ctdlroom *qrbuf) int imap_roomname(char *rbuf, int bufsize, const char *foldername) { + struct CitContext *CCC = CC; int levels; - char floorname[256]; + char floorname[ROOMNAMELEN*2]; char roomname[ROOMNAMELEN]; int i; struct floor *fl; @@ -760,10 +649,12 @@ int imap_roomname(char *rbuf, int bufsize, const char *foldername) levels = num_tokens(rbuf, FDELIM); if (levels > 1) { + long len; /* Extract the main room name. */ - extract_token(floorname, rbuf, 0, FDELIM, sizeof floorname); - strcpy(roomname, &rbuf[strlen(floorname)+1]); + len = extract_token(floorname, rbuf, 0, FDELIM, sizeof floorname); + if (len < 0) len = 0; + safestrncpy(roomname, &rbuf[len + 1], sizeof(roomname)); /* Try and find it on any floor. */ @@ -790,7 +681,7 @@ int imap_roomname(char *rbuf, int bufsize, const char *foldername) ret = (0 | IR_MAILBOX); exit: - CtdlLogPrintf(CTDL_DEBUG, "(That translates to \"%s\")\n", rbuf); + IMAP_syslog(LOG_DEBUG, "(That translates to \"%s\")", rbuf); return(ret); } @@ -802,22 +693,22 @@ void imap_ial_out(struct internet_address_list *ialist) struct internet_address_list *iptr; if (ialist == NULL) { - cprintf("NIL"); + IAPuts("NIL"); return; } - cprintf("("); + IAPuts("("); for (iptr = ialist; iptr != NULL; iptr = iptr->next) { - cprintf("("); + IAPuts("("); plain_imap_strout(iptr->ial_name); - cprintf(" NIL "); + IAPuts(" NIL "); plain_imap_strout(iptr->ial_user); - cprintf(" "); + IAPuts(" "); plain_imap_strout(iptr->ial_node); - cprintf(")"); + IAPuts(")"); } - cprintf(")"); + IAPuts(")"); } @@ -872,22 +763,30 @@ static int do_imap_match(const char *supplied_text, const char *supplied_p) { int matched, i; char lcase_text[SIZ], lcase_p[SIZ]; - char *text = lcase_text; - char *p = lcase_p; - long len; - + char *text; + char *p; + /* Copy both strings and lowercase them, in order to * make this entire operation case-insensitive. */ - len = strlen(supplied_text); - for (i=0; i<=len; ++i) + for (i=0; + ((supplied_text[i] != '\0') && + (i < sizeof(lcase_text))); + ++i) lcase_text[i] = tolower(supplied_text[i]); - len = strlen(supplied_p); - for (i=0; i<=len; ++i) - p[i] = tolower(supplied_p[i]); + lcase_text[i] = '\0'; + + for (i=0; + ((supplied_p[i] != '\0') && + (i < sizeof(lcase_p))); + ++i) + lcase_p[i] = tolower(supplied_p[i]); + lcase_p[i] = '\0'; /* Start matching */ - for (; *p; text++, p++) { + for (p = lcase_p, text = lcase_text; + !IsEmptyStr(p) && !IsEmptyStr(text); + text++, p++) { if ((*text == '\0') && (*p != '*') && (*p != '%')) { return WILDMAT_ABORT; } @@ -917,7 +816,8 @@ star: } return WILDMAT_ABORT; case '%': - while (++p, ((*p == '*') || (*p == '%'))) { + while (++p, (!IsEmptyStr(p) && ((*p == '*') || (*p == '%')))) + { /* Consecutive %'s act just like one, but even * a single star makes the sequence act like * one star, instead. @@ -932,7 +832,7 @@ star: * Trailing % matches everything * without a delimiter. */ - while (*text) { + while (!IsEmptyStr(text)) { if (*text == WILDMAT_DELIM) { return WILDMAT_FALSE; } @@ -940,7 +840,10 @@ star: } return WILDMAT_TRUE; } - while (*text && (*(text - 1) != WILDMAT_DELIM)) { + while (!IsEmptyStr(text) && + /* make shure texst - 1 isn't before lcase_p */ + ((text == lcase_text) || (*(text - 1) != WILDMAT_DELIM))) + { if ((matched = do_imap_match(text++, p)) != WILDMAT_FALSE) { return matched; @@ -950,7 +853,8 @@ star: } } - return (*text == '\0'); + if ((*text == '\0') && (*p == '\0')) return WILDMAT_TRUE; + else return WILDMAT_FALSE; } @@ -959,7 +863,7 @@ star: * Support function for mailbox pattern name matching in LIST and LSUB * Returns nonzero if the supplied mailbox name matches the supplied pattern. */ -int imap_mailbox_matches_pattern(char *pattern, char *mailboxname) +int imap_mailbox_matches_pattern(const char *pattern, char *mailboxname) { /* handle just-star case quickly */ if ((pattern[0] == '*') && (pattern[1] == '\0')) { @@ -1023,3 +927,137 @@ int imap_datecmp(const char *datestr, time_t msgtime) { return(0); } + + + + +void IAPrintf(const char *Format, ...) +{ + va_list arg_ptr; + + va_start(arg_ptr, Format); + StrBufVAppendPrintf(IMAP->Reply, Format, arg_ptr); + va_end(arg_ptr); +} + +void iaputs(const char *Str, long Len) +{ + StrBufAppendBufPlain(IMAP->Reply, Str, Len, 0); +} + +void ireply(const char *Msg, long len) +{ + citimap *Imap = IMAP; + + StrBufAppendBufPlain(Imap->Reply, + CKEY(Imap->Cmd.Params[0]), 0); + StrBufAppendBufPlain(Imap->Reply, + HKEY(" "), 0); + StrBufAppendBufPlain(Imap->Reply, + Msg, len, 0); + + StrBufAppendBufPlain(Imap->Reply, + HKEY("\r\n"), 0); + +} + +void IReplyPrintf(const char *Format, ...) +{ + citimap *Imap = IMAP; + va_list arg_ptr; + + + StrBufAppendBufPlain(Imap->Reply, + CKEY(Imap->Cmd.Params[0]), 0); + + StrBufAppendBufPlain(Imap->Reply, + HKEY(" "), 0); + + va_start(arg_ptr, Format); + StrBufVAppendPrintf(IMAP->Reply, Format, arg_ptr); + va_end(arg_ptr); + + StrBufAppendBufPlain(Imap->Reply, + HKEY("\r\n"), 0); + +} + + + +/* 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.) */ + +void plain_imap_strout(char *buf) +{ + int i; + int is_literal = 0; + long Len; + citimap *Imap = IMAP; + + if (buf == NULL) { /* yeah, we handle this */ + IAPuts("NIL"); + return; + } + + Len = strlen(buf); + for (i = 0; i < Len; ++i) { + if ((buf[i] == '\"') || (buf[i] == '\\')) + is_literal = 1; + } + + if (is_literal) { + StrBufAppendPrintf(Imap->Reply, "{%ld}\r\n", Len); + StrBufAppendBufPlain(Imap->Reply, buf, Len, 0); + } else { + StrBufAppendBufPlain(Imap->Reply, + HKEY("\""), 0); + StrBufAppendBufPlain(Imap->Reply, + buf, Len, 0); + StrBufAppendBufPlain(Imap->Reply, + HKEY("\""), 0); + } +} + + +/* 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.) */ + + +void IPutStr(const char *Msg, long Len) +{ + int i; + int is_literal = 0; + citimap *Imap = IMAP; + + + if ((Msg == NULL) || (Len == 0)) + { /* yeah, we handle this */ + StrBufAppendBufPlain(Imap->Reply, HKEY("NIL"), 0); + return; + } + + for (i = 0; i < Len; ++i) { + if ((Msg[i] == '\"') || (Msg[i] == '\\')) + is_literal = 1; + } + + if (is_literal) { + StrBufAppendPrintf(Imap->Reply, "{%ld}\r\n", Len); + StrBufAppendBufPlain(Imap->Reply, Msg, Len, 0); + } else { + StrBufAppendBufPlain(Imap->Reply, + HKEY("\""), 0); + StrBufAppendBufPlain(Imap->Reply, + Msg, Len, 0); + StrBufAppendBufPlain(Imap->Reply, + HKEY("\""), 0); + } +} + +void IUnbuffer (void) +{ + citimap *Imap = IMAP; + + cputbuf(Imap->Reply); + FlushStrBuf(Imap->Reply); +}