*
* Utility functions for the IMAP module.
*
- * Note: most of the UTF7 and UTF8 handling in here was lifted from Evolution.
+ * 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
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
+#include <libcitadel.h>
#include "citadel.h"
#include "sysdep_decls.h"
-#include "tools.h"
-#include "room_ops.h"
#include "internet_addressing.h"
#include "imap_tools.h"
-
+#include "serv_imap.h"
+#include "ctdl_module.h"
#ifndef HAVE_SNPRINTF
#include "snprintf.h"
/* String handling helpers */
-/* This code uses some pretty narsty string manipulation. To make everything
+/* This code uses some pretty nasty string manipulation. To make everything
* manageable, we use this semi-high-level string manipulation API. Strings are
- * always \0-terminated, despite the fact that we keep track of the size. */
-
+ * always \0-terminated, despite the fact that we keep track of the size.
+ */
struct string {
char* buffer;
int maxsize;
loop:
if (r < 0x80)
{
- *ptr = p;
+ *ptr = (char*) p;
v = r;
break;
}
m<<=5;
} while (r & 0x40);
- *ptr = p;
+ *ptr = (char*)p;
v &= ~m;
break;
*destp = 0;
string_init(&dest, destp, destend-destp);
- /* lprintf(CTDL_DEBUG, "toimap %s\r\n", src); */
+ /* CtdlLogPrintf(CTDL_DEBUG, "toimap %s\r\n", src); */
for (;;)
{
if (state == 1)
utf7_closeb64(&dest, v, i);
- /* lprintf(CTDL_DEBUG, " -> %s\r\n", destp); */
+ /* CtdlLogPrintf(CTDL_DEBUG, " -> %s\r\n", destp); */
return string_end(&dest);
}
/* Convert from an IMAP-safe name back into a Citadel name. Returns the end of the destination. */
static int cfrommap(int c);
-static char* fromimap(char* destp, char* destend, char* src)
+static char* fromimap(char* destp, char* destend, const char* src)
{
struct string dest;
- unsigned char *p = (unsigned char*) src;
+ unsigned const char *p = (unsigned const char*) src;
int v = 0;
int i = 0;
int state = 0;
*destp = 0;
string_init(&dest, destp, destend-destp);
- /* lprintf(CTDL_DEBUG, "fromimap %s\r\n", src); */
+ /* CtdlLogPrintf(CTDL_DEBUG, "fromimap %s\r\n", src); */
do {
c = *p++;
}
} while (c != '\0');
- /* lprintf(CTDL_DEBUG, " -> %s\r\n", destp); */
+ /* CtdlLogPrintf(CTDL_DEBUG, " -> %s\r\n", destp); */
return string_end(&dest);
}
/* 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(char *buf)
+void plain_imap_strout(char *buf)
{
int i;
int is_literal = 0;
- int len;
+ long len;
if (buf == NULL) { /* yeah, we handle this */
cprintf("NIL");
}
if (is_literal) {
- cprintf("{%ld}\r\n%s", (long)strlen(buf), buf);
+ 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);
+ }
+}
+
+
+
+
/* Break a command down into tokens, unquoting any escaped characters. */
-int imap_parameterize(char** args, char* in)
+void MakeStringOf(StrBuf *Buf, int skip)
+{
+ int i;
+ citimap_command *Cmd = &IMAP->Cmd;
+
+ for (i=skip; i<Cmd->num_parms; ++i) {
+ StrBufAppendBufPlain(Buf, Cmd->Params[i].Key, Cmd->Params[i].len, 0);
+ if (i < (Cmd->num_parms-1)) StrBufAppendBufPlain(Buf, HKEY(" "), 0);
+ }
+}
+
+
+void TokenCutRight(citimap_command *Cmd,
+ ConstStr *CutMe,
+ int n)
+{
+ const char *CutAt;
+
+ if (CutMe->len < n) {
+ CutAt = CutMe->Key;
+ CutMe->len = 0;
+ }
+ else {
+ CutAt = CutMe->Key + CutMe->len - n;
+ CutMe->len -= n;
+ }
+ StrBufPeek(Cmd->CmdBuf, CutAt, -1, '\0');
+}
+
+void TokenCutLeft(citimap_command *Cmd,
+ ConstStr *CutMe,
+ int n)
+{
+ if (CutMe->len < n) {
+ CutMe->Key += CutMe->len;
+ CutMe->len = 0;
+ }
+ else {
+ CutMe->Key += n;
+ CutMe->len -= n;
+ }
+}
+
+
+
+int CmdAdjust(citimap_command *Cmd,
+ int nArgs,
+ int Realloc)
+{
+ ConstStr *Params;
+ if (nArgs > Cmd->avail_parms) {
+ Params = (ConstStr*) malloc(sizeof(ConstStr) * nArgs);
+ if (Realloc) {
+ memcpy(Params,
+ Cmd->Params,
+ sizeof(ConstStr) * Cmd->avail_parms);
+
+ memset(Cmd->Params +
+ sizeof(ConstStr) * Cmd->avail_parms,
+ 0,
+ sizeof(ConstStr) * nArgs -
+ sizeof(ConstStr) * Cmd->avail_parms
+ );
+ }
+ else {
+ Cmd->num_parms = 0;
+ memset(Params, 0,
+ sizeof(ConstStr) * nArgs);
+ }
+ Cmd->avail_parms = nArgs;
+ if (Cmd->Params != NULL)
+ free (Cmd->Params);
+ Cmd->Params = Params;
+ }
+ else {
+ if (!Realloc) {
+ memset(Cmd->Params,
+ 0,
+ sizeof(ConstStr) * Cmd->avail_parms);
+ Cmd->num_parms = 0;
+ }
+ }
+ return Cmd->avail_parms;
+}
+
+int imap_parameterize(citimap_command *Cmd)
+{
+ int nArgs;
+ const char *In, *End;
+
+ In = ChrPtr(Cmd->CmdBuf);
+ End = In + StrLength(Cmd->CmdBuf);
+
+ /* we start with 10 chars per arg, maybe we need to realloc later. */
+ nArgs = StrLength(Cmd->CmdBuf) / 10 + 10;
+ nArgs = CmdAdjust(Cmd, nArgs, 0);
+ while (In < End)
+ {
+ /* Skip whitespace. */
+ while (isspace(*In))
+ In++;
+ if (*In == '\0')
+ break;
+
+ /* Found the start of a token. */
+
+ Cmd->Params[Cmd->num_parms].Key = In;
+
+ /* Read in the token. */
+
+ for (;;)
+ {
+ if (isspace(*In))
+ break;
+
+ if (*In == '\"')
+ {
+ /* Found a quoted section. */
+
+ Cmd->Params[Cmd->num_parms].Key++;
+ //In++;
+ for (;;)
+ {
+ In++;
+ if (*In == '\"') {
+ StrBufPeek(Cmd->CmdBuf, In, -1, '\0');
+ break;
+ }
+ else if (*In == '\\')
+ In++;
+
+ if (*In == '\0') {
+ Cmd->Params[Cmd->num_parms].len =
+ In - Cmd->Params[Cmd->num_parms].Key;
+ Cmd->num_parms++;
+ return Cmd->num_parms;
+ }
+ }
+ break;
+ }
+ else if (*In == '\\')
+ {
+ In++;
+ }
+
+ if (*In == '\0') {
+ Cmd->Params[Cmd->num_parms].len =
+ In - Cmd->Params[Cmd->num_parms].Key;
+ Cmd->num_parms++;
+ return Cmd->num_parms;
+ }
+ In++;
+ }
+ StrBufPeek(Cmd->CmdBuf, In, -1, '\0');
+ Cmd->Params[Cmd->num_parms].len =
+ In - Cmd->Params[Cmd->num_parms].Key;
+ if (Cmd->num_parms + 1 >= Cmd->avail_parms) {
+ nArgs = CmdAdjust(Cmd, nArgs * 2, 1);
+ }
+ Cmd->num_parms ++;
+ In++;
+ }
+ return Cmd->num_parms;
+}
+
+int old_imap_parameterize(char** args, char *in)
{
char* out = in;
int num = 0;
{
/* Otherwise, prefix the floor name as a "public folders" moniker. */
- fl = cgetfloor(qrbuf->QRfloor);
+ fl = CtdlGetCachedFloor(qrbuf->QRfloor);
p = toimap(p, bufend, fl->f_name);
if (p < bufend)
*p++ = '/';
*
*/
-int imap_roomname(char *rbuf, int bufsize, char *foldername)
+int imap_roomname(char *rbuf, int bufsize, const char *foldername)
{
int levels;
char floorname[256];
for (i = 0; i < MAXFLOORS; ++i)
{
- fl = cgetfloor(i);
+ fl = CtdlGetCachedFloor(i);
if (fl->f_flags & F_INUSE)
{
if (strcasecmp(floorname, fl->f_name) == 0)
ret = (0 | IR_MAILBOX);
exit:
- lprintf(CTDL_DEBUG, "(That translates to \"%s\")\n", rbuf);
+ CtdlLogPrintf(CTDL_DEBUG, "(That translates to \"%s\")\n", rbuf);
return(ret);
}
for (iptr = ialist; iptr != NULL; iptr = iptr->next) {
cprintf("(");
- imap_strout(iptr->ial_name);
+ plain_imap_strout(iptr->ial_name);
cprintf(" NIL ");
- imap_strout(iptr->ial_user);
+ plain_imap_strout(iptr->ial_user);
cprintf(" ");
- imap_strout(iptr->ial_node);
+ plain_imap_strout(iptr->ial_node);
cprintf(")");
}
* return 1 for a valid message set. If any other character is found,
* return 0.
*/
-int imap_is_message_set(char *buf)
+int imap_is_message_set(const char *buf)
{
int i;
if (buf == NULL)
return (0); /* stupidity checks */
- if (strlen(buf) == 0)
+ if (IsEmptyStr(buf))
return (0);
if (!strcasecmp(buf, "ALL"))
return (1); /* macro? why? */
- for (i = 0; i < strlen(buf); ++i) { /* now start the scan */
+ for (i = 0; buf[i]; ++i) { /* now start the scan */
if (
(!isdigit(buf[i]))
&& (buf[i] != ':')
char lcase_text[SIZ], lcase_p[SIZ];
char *text = lcase_text;
char *p = lcase_p;
+ long len;
/* Copy both strings and lowercase them, in order to
* make this entire operation case-insensitive.
*/
- for (i=0; i<=strlen(supplied_text); ++i)
+ len = strlen(supplied_text);
+ for (i=0; i<=len; ++i)
lcase_text[i] = tolower(supplied_text[i]);
- for (i=0; i<=strlen(supplied_p); ++i)
+ len = strlen(supplied_p);
+ for (i=0; i<=len; ++i)
p[i] = tolower(supplied_p[i]);
/* Start matching */
* 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')) {
* 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) {
+int imap_datecmp(const char *datestr, time_t msgtime) {
char daystr[256];
char monthstr[256];
char yearstr[256];
int msgday, msgmonth, msgyear;
struct tm msgtm;
+ char *imap_datecmp_ascmonths[12] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+
if (datestr == NULL) return(0);
/* Expecting a date in the form dd-Mmm-yyyy */
year = atoi(yearstr);
month = 0;
for (i=0; i<12; ++i) {
- if (!strcasecmp(monthstr, ascmonths[i])) {
+ if (!strcasecmp(monthstr, imap_datecmp_ascmonths[i])) {
month = i;
}
}