aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog4
-rw-r--r--camel/providers/imap/camel-imap-folder.c36
-rw-r--r--camel/providers/imap/camel-imap-utils.c425
3 files changed, 257 insertions, 208 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index ab022c1d10..ee2cd43dd5 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,5 +1,9 @@
2000-07-31 Jeffrey Stedfast <fejj@helixcode.com>
+ * providers/imap/camel-imap-folder.c (imap_get_message_info_internal):
+ Some IMAP servers don't wrap the UID in ()'s so don't depend on that
+ (imap_get_summary_internal): Same
+
* providers/imap/camel-imap-utils.c (free_sexp_node): Oops, forgot to
free node->function - not good.
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index 2118482eac..3dafa48451 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -1150,17 +1150,17 @@ imap_get_summary_internal (CamelFolder *folder, CamelException *ex)
info = g_malloc0 (sizeof (CamelMessageInfo));
/* lets grab the UID... */
- if (!(uid = strstr (headers->pdata[i], "(UID "))) {
+ if (!(uid = strstr (headers->pdata[i], "UID "))) {
d(fprintf (stderr, "Cannot get a uid for %d\n\n%s\n\n", i+1, (char *) headers->pdata[i]));
g_free (info);
break;
}
- for (uid += 5; *uid && (*uid < '0' || *uid > '9'); uid++); /* advance to <uid> */
+ for (uid += 4; *uid && (*uid < '0' || *uid > '9'); uid++); /* advance to <uid> */
for (q = uid; *q && *q >= '0' && *q <= '9'; q++); /* find the end of the <uid> */
info->uid = g_strndup (uid, (gint)(q - uid));
d(fprintf (stderr, "*** info->uid = %s\n", info->uid));
-
+
/* now lets grab the FLAGS */
if (!(flags = strstr (q, "FLAGS "))) {
d(fprintf (stderr, "We didn't seem to get any flags for %d...\n", i));
@@ -1168,12 +1168,12 @@ imap_get_summary_internal (CamelFolder *folder, CamelException *ex)
g_free (info);
break;
}
-
+
for (flags += 6; *flags && *flags != '('; flags++); /* advance to <flags> */
for (q = flags; *q && *q != ')'; q++); /* find the end of <flags> */
flags = g_strndup (flags, (gint)(q - flags + 1));
d(fprintf (stderr, "*** info->flags = %s\n", flags));
-
+
/* now we gotta parse for the flags */
info->flags = 0;
if (strstr (flags, "\\Seen"))
@@ -1196,7 +1196,7 @@ imap_get_summary_internal (CamelFolder *folder, CamelException *ex)
for (j = 0; *header_fields[j]; j++) {
struct _header_raw *raw;
char *field, *value;
-
+
field = g_strdup_printf ("\n%s:", header_fields[j]);
value = get_header_field (header, field);
g_free (field);
@@ -1208,7 +1208,7 @@ imap_get_summary_internal (CamelFolder *folder, CamelException *ex)
raw->name = g_strdup (header_fields[j]);
raw->value = value;
raw->offset = -1;
-
+
if (!h) {
h = raw;
tail = h;
@@ -1217,7 +1217,7 @@ imap_get_summary_internal (CamelFolder *folder, CamelException *ex)
tail = raw;
}
}
-
+
/* construct the CamelMessageInfo */
info->subject = camel_summary_format_string (h, "subject");
info->from = camel_summary_format_address (h, "from");
@@ -1238,7 +1238,7 @@ imap_get_summary_internal (CamelFolder *folder, CamelException *ex)
info->references = header_references_decode (header_raw_find (&h, "references", NULL));
if (info->references == NULL)
info->references = header_references_decode (header_raw_find (&h, "in-reply-to", NULL));
-
+
while (h->next) {
struct _header_raw *next = h->next;
@@ -1247,15 +1247,15 @@ imap_get_summary_internal (CamelFolder *folder, CamelException *ex)
g_free (h);
h = next;
}
-
+
g_ptr_array_add (summary, info);
g_hash_table_insert (hash, info->uid, info);
}
-
+
for (i = 0; i < headers->len; i++)
g_free (headers->pdata[i]);
g_ptr_array_free (headers, TRUE);
-
+
/* clean up any previous summary data */
imap_folder_summary_free (imap_folder);
@@ -1298,13 +1298,13 @@ imap_get_message_info_internal (CamelFolder *folder, guint id)
}
/* lets grab the UID... */
- if (!(uid = (char *) e_strstrcase (result, "(UID "))) {
+ if (!(uid = (char *) e_strstrcase (result, "UID "))) {
d(fprintf (stderr, "Cannot get a uid for %d\n\n%s\n\n", id, result));
g_free (result);
return NULL;
}
- for (uid += 5; *uid && (*uid < '0' || *uid > '9'); uid++); /* advance to <uid> */
+ for (uid += 4; *uid && (*uid < '0' || *uid > '9'); uid++); /* advance to <uid> */
for (q = uid; *q && *q >= '0' && *q <= '9'; q++); /* find the end of the <uid> */
uid = g_strndup (uid, (gint)(q - uid));
@@ -1424,7 +1424,7 @@ imap_search_by_expression (CamelFolder *folder, const char *expression, CamelExc
{
/* NOTE: This is experimental code... */
GPtrArray *uids = NULL;
- char *result, *sexp;
+ char *result, *sexp, *p;
int status;
d(fprintf (stderr, "camel sexp: '%s'\n", expression));
@@ -1453,11 +1453,11 @@ imap_search_by_expression (CamelFolder *folder, const char *expression, CamelExc
g_free (sexp);
return uids;
}
-
- if (*result == '*' && !strncmp ("SEARCH", imap_next_word (result), 6)) {
+
+ if ((p = strstr (result, "* SEARCH"))) {
char *word;
- word = imap_next_word (result); /* word now points to SEARCH */
+ word = imap_next_word (p); /* word now points to SEARCH */
for (word = imap_next_word (word); *word && *word != '*'; word = imap_next_word (word)) {
gboolean word_is_numeric = TRUE;
diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c
index 954defabc5..af4cec0cb2 100644
--- a/camel/providers/imap/camel-imap-utils.c
+++ b/camel/providers/imap/camel-imap-utils.c
@@ -23,24 +23,13 @@
#include <stdio.h>
#include <string.h>
+#include <gtk/gtk.h>
#include "camel-imap-utils.h"
#include "string-utils.h"
+#include <e-sexp.h>
#define d(x) x
-struct sexp_node {
- struct sexp_node *l_node, *r_node;
- char *function;
- char *data;
-};
-
-static char *get_quoted_token (char *string, int *len);
-static char *get_token (char *string, int *len);
-struct sexp_node *get_sexp_node (const char *exp);
-static void print_node (struct sexp_node *node, int depth);
-static char *str_sexp_node (struct sexp_node *node);
-static void free_sexp_node (struct sexp_node *node);
-
char *
imap_next_word (char *buf)
{
@@ -109,233 +98,289 @@ imap_parse_list_response (char *buf, char *namespace, char **flags, char **sep,
return TRUE;
}
-static char *
-get_quoted_token (char *string, int *len)
+struct prop_info {
+ char *query_prop;
+ char *imap_attr;
+} prop_info_table[] = {
+ /* query prop, imap attr */
+ { "body-contains", "BODY" },
+ { "header-contains", "HEADER" }
+};
+
+static int num_prop_infos = sizeof (prop_info_table) / sizeof (prop_info_table[0]);
+
+static gchar *
+query_prop_to_imap (gchar *query_prop)
{
- char *ep;
-
- for (ep = string + 1; *ep; ep++)
- if (*ep == '"' && *(ep - 1) != '\\')
- break;
- if (*ep)
- ep++;
-
- *len = ep - string;
-
- return g_strndup (string, *len);
+ int i;
+
+ for (i = 0; i < num_prop_infos; i ++)
+ if (!strcmp (query_prop, prop_info_table[i].query_prop))
+ return prop_info_table[i].imap_attr;
+
+ return NULL;
}
-static char *
-get_token (char *string, int *len)
+static ESExpResult *
+func_and (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
{
- char *p, *ep;
+ GList **list = data;
+ ESExpResult *r;
+ char **strings;
- for (p = string; *p && *p == ' '; p++);
-
- if (*p == '"') {
- char *token;
+ if (argc > 0) {
int i;
- token = get_quoted_token (p, &i);
+ strings = g_malloc0 (argc + 3);
+ strings[0] = g_strdup ("(AND");
+ strings[argc+3 - 2] = g_strdup (")");
+ strings[argc+3 - 1] = NULL;
- *len = i + (p - string);
+ for (i = 0; i < argc; i++) {
+ GList *list_head = *list;
+ strings[argc - i] = (*list)->data;
+ *list = g_list_remove_link (*list, *list);
+ g_list_free_1 (list_head);
+ }
- return token;
+ *list = g_list_prepend (*list, g_strjoinv (" ", strings));
+
+ for (i = 0 ; i < argc + 2; i++)
+ g_free (strings[i]);
+
+ g_free (strings);
}
- for (ep = p; *ep && *ep != ' '; ep++);
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
- *len = ep - string;
-
- return g_strndup (p, *len);
+ return r;
}
-struct sexp_node *
-get_sexp_node (const char *exp)
+static ESExpResult *
+func_or (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
{
- struct sexp_node *node = NULL;
- char *p, *ep;
- int len;
-
- switch (*exp) {
- case '(':
- node = g_malloc0 (sizeof (struct sexp_node));
- node->l_node = NULL;
- node->r_node = NULL;
- node->data = NULL;
-
- p = (char *) exp + 1;
-
- node->function = get_token (p, &len);
-
- p += len;
- for (ep = p; *ep && *ep != '(' && *ep != ')'; ep++);
- node->data = g_strndup (p, (gint)(ep - p));
- g_strstrip (node->data);
-
- p = ep;
-
- if (*p == '(')
- node->r_node = get_sexp_node (p);
- else
- node->l_node = get_sexp_node (p);
-
- return node;
- break;
- case '\0':
- return NULL;
- break;
- case ')':
- for (p = (char *) exp + 1; *p && *p == ' '; p++);
- return get_sexp_node (p);
- break;
- default:
- node = g_malloc0 (sizeof (struct sexp_node));
- node->l_node = NULL;
- node->r_node = NULL;
- node->data = NULL;
-
- p = (char *) exp;
+ GList **list = data;
+ ESExpResult *r;
+ char **strings;
+
+ if (argc > 0) {
+ int i;
- node->function = get_token (p, &len);
-
- p += len;
- for (ep = p; *ep && *ep != '(' && *ep != ')'; ep++);
- node->data = g_strndup (p, (gint)(ep - p));
- g_strstrip (node->data);
+ strings = g_malloc0 (argc+3);
+ strings[0] = g_strdup ("(OR");
+ strings[argc+3 - 2] = g_strdup (")");
+ strings[argc+3 - 1] = NULL;
+ for (i = 0; i < argc; i++) {
+ GList *list_head = *list;
+ strings[argc - i] = (*list)->data;
+ *list = g_list_remove_link (*list, *list);
+ g_list_free_1 (list_head);
+ }
- p = ep;
+ *list = g_list_prepend (*list, g_strjoinv (" ", strings));
- if (*p == '(')
- node->r_node = get_sexp_node (p);
- else
- node->l_node = get_sexp_node (p);
+ for (i = 0 ; i < argc + 2; i++)
+ g_free (strings[i]);
- return node;
+ g_free (strings);
}
+
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
+
+ return r;
}
-static void
-print_node (struct sexp_node *node, int depth)
+static ESExpResult *
+func_not (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
{
- int i;
-
- for (i = 0; i < depth; i++)
- d(fprintf (stderr, " "));
+ GList **list = data;
+ ESExpResult *r;
+
+ /* just replace the head of the list with the NOT of it. */
+ if (argc > 0) {
+ char *term = (*list)->data;
+ (*list)->data = g_strdup_printf ("(NOT %s)", term);
+ g_free (term);
+ }
- d(fprintf (stderr, "%s\n", node->function));
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
- if (*node->data) {
- for (i = 0; i < depth + 1; i++)
- d(fprintf (stderr, " "));
+ return r;
+}
+
+static ESExpResult *
+func_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ ESExpResult *r;
+
+ if (argc == 2
+ && argv[0]->type == ESEXP_RES_STRING
+ && argv[1]->type == ESEXP_RES_STRING) {
+ char *propname = argv[0]->value.string;
+ char *str = argv[1]->value.string;
+ char *imap_attr = query_prop_to_imap (propname);
+ gboolean one_star = FALSE;
- d(fprintf (stderr, "%s\n", node->data));
+ if (strlen (str) == 0)
+ one_star = TRUE;
+
+ if (imap_attr)
+ *list = g_list_prepend (*list,
+ g_strdup_printf ("(%s=*%s%s)",
+ imap_attr,
+ str,
+ one_star ? "" : "*"));
}
- if (node->r_node)
- print_node (node->r_node, depth + 1);
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
- if (node->l_node)
- print_node (node->l_node, depth);
+ return r;
}
-static char *esexp_keys[] = { "or", "body-contains", "header-contains", "match-all", NULL };
-static char *imap_keys[] = { "OR", "BODY", "HEADER", NULL };
-
-static char *
-str_sexp_node (struct sexp_node *node)
+static ESExpResult *
+func_is (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
{
- char *node_str, *func, *str, *l_str, *r_str;
- int i;
-
- for (i = 0; esexp_keys[i]; i++)
- if (!strncmp (esexp_keys[i], node->function, strlen (node->function)))
- break;
-
- if (esexp_keys[i])
- func = imap_keys[i];
- else
- func = node->function;
-
- if (func) {
- if (*node->data)
- str = g_strdup_printf ("%s %s", func, node->data);
- else
- str = g_strdup (func);
- } else {
- str = NULL;
+ GList **list = data;
+ ESExpResult *r;
+
+ if (argc == 2
+ && argv[0]->type == ESEXP_RES_STRING
+ && argv[1]->type == ESEXP_RES_STRING) {
+ char *propname = argv[0]->value.string;
+ char *str = argv[1]->value.string;
+ char *imap_attr = query_prop_to_imap (propname);
+
+ if (imap_attr)
+ *list = g_list_prepend (*list,
+ g_strdup_printf ("(%s=%s)",
+ imap_attr, str));
}
- r_str = NULL;
- if (node->r_node)
- r_str = str_sexp_node (node->r_node);
-
- l_str = NULL;
- if (node->l_node)
- l_str = str_sexp_node (node->l_node);
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
- if (str) {
- if (r_str) {
- if (l_str)
- node_str = g_strdup_printf ("(%s (%s)) %s", str, r_str, l_str);
- else
- node_str = g_strdup_printf ("(%s %s)", str, r_str);
- } else {
- if (l_str)
- node_str = g_strdup_printf ("(%s) %s", str, l_str);
- else
- node_str = g_strdup_printf ("(%s)", str);
- }
- } else {
- if (r_str) {
- if (l_str)
- node_str = g_strdup_printf ("(%s) %s", r_str, l_str);
- else
- node_str = g_strdup_printf ("%s", r_str);
- } else {
- if (l_str)
- node_str = g_strdup_printf ("%s", l_str);
- else
- node_str = g_strdup ("");
- }
+ return r;
+}
+
+static ESExpResult *
+func_beginswith (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ ESExpResult *r;
+
+ if (argc == 2
+ && argv[0]->type == ESEXP_RES_STRING
+ && argv[1]->type == ESEXP_RES_STRING) {
+ char *propname = argv[0]->value.string;
+ char *str = argv[1]->value.string;
+ char *imap_attr = query_prop_to_imap (propname);
+ gboolean one_star = FALSE;
+
+ if (strlen(str) == 0)
+ one_star = TRUE;
+
+ if (imap_attr)
+ *list = g_list_prepend (*list,
+ g_strdup_printf ("(%s=%s*)",
+ imap_attr,
+ str));
}
- g_free (str);
- g_free (l_str);
- g_free (r_str);
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
- return node_str;
+ return r;
}
-static void
-free_sexp_node (struct sexp_node *node)
+static ESExpResult *
+func_endswith (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
{
- if (node->r_node)
- free_sexp_node (node->r_node);
+ GList **list = data;
+ ESExpResult *r;
+
+ if (argc == 2
+ && argv[0]->type == ESEXP_RES_STRING
+ && argv[1]->type == ESEXP_RES_STRING) {
+ char *propname = argv[0]->value.string;
+ char *str = argv[1]->value.string;
+ char *imap_attr = query_prop_to_imap (propname);
+ gboolean one_star = FALSE;
+
+ if (strlen (str) == 0)
+ one_star = TRUE;
+
+ if (imap_attr)
+ *list = g_list_prepend (*list,
+ g_strdup_printf ("(%s=*%s)",
+ imap_attr,
+ str));
+ }
- if (node->l_node)
- free_sexp_node (node->l_node);
-
- g_free (node->function);
- g_free (node->data);
- g_free (node);
+ r = e_sexp_result_new(ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
+
+ return r;
}
+/* 'builtin' functions */
+static struct {
+ char *name;
+ ESExpFunc *func;
+ int type; /* set to 1 if a function can perform shortcut evaluation, or
+ doesn't execute everything, 0 otherwise */
+} symbols[] = {
+ { "and", func_and, 0 },
+ { "or", func_or, 0 },
+ { "not", func_not, 0 },
+ { "contains", func_contains, 0 },
+ { "is", func_is, 0 },
+ { "beginswith", func_beginswith, 0 },
+ { "endswith", func_endswith, 0 },
+};
+
char *
imap_translate_sexp (const char *expression)
{
- struct sexp_node *root;
- char *sexp;
+ ESExp *sexp;
+ ESExpResult *r;
+ gchar *retval;
+ GList *list = NULL;
+ int i;
- root = get_sexp_node (expression);
+ sexp = e_sexp_new ();
- d(print_node (root, 0));
+ for (i = 0; i < sizeof (symbols) / sizeof (symbols[0]); i++) {
+ if (symbols[i].type == 1) {
+ e_sexp_add_ifunction (sexp, 0, symbols[i].name,
+ (ESExpIFunc *)symbols[i].func, &list);
+ } else {
+ e_sexp_add_function (sexp, 0, symbols[i].name,
+ symbols[i].func, &list);
+ }
+ }
+
+ e_sexp_input_text (sexp, expression, strlen (expression));
+ e_sexp_parse (sexp);
- sexp = str_sexp_node (root);
- sexp[strlen (sexp) - 1] = '\0';
- strcpy (sexp, sexp + 1);
+ r = e_sexp_eval (sexp);
+
+ gtk_object_unref (GTK_OBJECT (sexp));
+ e_sexp_result_free (r);
+
+ if (list->next) {
+ g_warning ("conversion to imap expression string failed");
+ retval = NULL;
+ g_list_foreach (list, (GFunc)g_free, NULL);
+ } else {
+ retval = list->data;
+ }
- free_sexp_node (root);
+ g_list_free (list);
- return sexp;
+ return retval;
}