aboutsummaryrefslogtreecommitdiffstats
path: root/camel
diff options
context:
space:
mode:
Diffstat (limited to 'camel')
-rw-r--r--camel/ChangeLog6
-rw-r--r--camel/providers/imap/camel-imap-utils.c502
2 files changed, 333 insertions, 175 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 7d286ccf31..4c3a60d500 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,5 +1,11 @@
2000-08-31 Jeffrey Stedfast <fejj@helixcode.com>
+ * providers/imap/camel-imap-utils.c (imap_translate_sexp):
+ Reimplemented. It should now work correctly for most possible
+ VFolder rules.
+
+2000-08-31 Jeffrey Stedfast <fejj@helixcode.com>
+
* providers/imap/camel-imap-store.c (camel_imap_command_extended):
Don't save any exceptions caused by camel_imap_folder_changed
(camel_imap_fetch_command): Same.
diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c
index 7bb5044564..d25a2f5159 100644
--- a/camel/providers/imap/camel-imap-utils.c
+++ b/camel/providers/imap/camel-imap-utils.c
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <string.h>
+#include <time.h>
#include <gtk/gtk.h>
#include "camel-imap-utils.h"
@@ -30,23 +31,8 @@
#define d(x) x
-static char *esexp_keys[] = { "and", "or", "body-contains", "header-contains", "match-all", "user-flag", NULL };
-static char *imap_keys[] = { NULL, "OR", "BODY", "HEADER", NULL, NULL };
-
-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 const char *get_func (struct sexp_node *node);
-static char *get_data (struct sexp_node *node);
-static char *str_sexp_node (struct sexp_node *node);
-static void free_sexp_node (struct sexp_node *node);
char *
@@ -162,230 +148,396 @@ get_token (char *string, int *len)
return g_strndup (p, *len);
}
-struct sexp_node *
-get_sexp_node (const char *exp)
+static ESExpResult *
+func_and (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
{
- struct sexp_node *node = NULL;
- char *left_exp, *right_exp, *this_exp;
- char *p, *ep;
- int len, pbal;
-
- if (exp && *exp) {
- node = g_malloc0 (sizeof (struct sexp_node));
- node->l_node = NULL;
- node->r_node = NULL;
- node->function = NULL;
- node->data = NULL;
+ GList **list = data;
+ ESExpResult *r;
+
+ fprintf (stderr, "in AND func (argc = %d)\n", argc);
+ if (argc > 0) {
+ char **strings;
+ int i;
+
+ strings = g_new (char*, argc+1);
+ strings[argc] = NULL;
- p = (char *) exp + 1;
- for (ep = p, pbal = 1; *ep && pbal; ep++) {
- if (*ep == '(')
- pbal++;
- if (*ep == ')')
- pbal--;
+ for (i = 0; i < argc; i++) {
+ GList *list_head = *list;
+
+ fprintf (stderr, "\tAND func: %s\n", (*list) ? (char *) (*list)->data : "(null)");
+ strings[argc - (i+1)] = (*list) ? (*list)->data : g_strdup ("");
+ *list = g_list_remove_link (*list, *list);
+ g_list_free_1 (list_head);
}
- this_exp = g_strndup (p, (gint)(ep - p));
+ *list = g_list_prepend (*list, g_strjoinv (" ", strings));
+ fprintf (stderr, "%s\n", (char *) (*list)->data);
- for (left_exp = ep; *left_exp && *left_exp != '('; left_exp++);
- left_exp = g_strdup (left_exp);
+ for (i = 0 ; i < argc; i ++)
+ g_free (strings[i]);
- for (right_exp = this_exp; *right_exp && *right_exp != '('; right_exp++);
- pbal = 1;
- for (ep = right_exp; *ep && pbal; ep++) {
- if (*ep == '(')
- pbal++;
- if (*ep == ')')
- pbal--;
+ g_free (strings);
+ }
+
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
+
+ return r;
+}
+
+static ESExpResult *
+func_or (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ ESExpResult *r;
+
+ fprintf (stderr, "in OR func (argc = %d)\n", argc);
+ if (argc == 2 && (*list)->data && (*list)->next && (*list)->next->data) {
+ char **strings;
+ int i;
+
+ strings = g_new (char*, argc+2);
+ strings[0] = g_strdup ("OR");
+ strings[argc+2 - 1] = NULL;
+
+ for (i = 0; i < 2; i++) {
+ GList *list_head = *list;
+
+ fprintf (stderr, "\tOR func: %s\n", (*list) ? (char *) (*list)->data : "(null)");
+ strings[argc - i] = (*list) ? (*list)->data : g_strdup ("");
+ *list = g_list_remove_link (*list, *list);
+ g_list_free_1 (list_head);
}
- right_exp = g_strndup (right_exp, (gint)(ep - right_exp));
- /* fill in the node */
- node->function = get_token (this_exp, &len);
- p = this_exp + len;
- for (ep = p; *ep && *ep != '(' && *ep != ')'; ep++);
- node->data = g_strndup (p, (gint)(ep - p));
+ *list = g_list_prepend (*list, g_strjoinv (" ", strings));
+ fprintf (stderr, "%s\n", (char *) (*list)->data);
- g_strstrip (node->data);
-
- node->l_node = get_sexp_node (left_exp);
- node->r_node = get_sexp_node (right_exp);
+ for (i = 0 ; i < argc + 2; i ++)
+ g_free (strings[i]);
+
+ g_free (strings);
+ }
+
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
+
+ return r;
+}
- g_free (this_exp);
- g_free (left_exp);
- g_free (right_exp);
+static ESExpResult *
+func_not (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ ESExpResult *r;
+
+ fprintf (stderr, "in NOT func\n");
+ /* 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);
+ fprintf (stderr, "%s\n", (char *) (*list)->data);
+ g_free (term);
}
- return node;
+ 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 char *tz_months [] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+static char *
+format_date (time_t time, int offset)
{
- int i;
+ struct tm tm;
- for (i = 0; i < depth; i++)
- d(fprintf (stderr, " "));
+ time += ((offset / 100) * (60*60)) + (offset % 100)*60;
- d(fprintf (stderr, "%s\n", node->function));
+ d(printf("converting date %s", ctime (&time)));
- if (*node->data) {
- for (i = 0; i < depth + 1; i++)
- d(fprintf (stderr, " "));
+ memcpy (&tm, gmtime (&time), sizeof (tm));
+
+ return g_strdup_printf ("%d-%s-%04d",
+ tm.tm_mday, tz_months[tm.tm_mon],
+ tm.tm_year + 1900);
+}
+
+static ESExpResult *
+func_lt (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ char *type = (*list)->data;
+ time_t date = (time_t) (argv[1])->value.number;
+ ESExpResult *r;
+
+ fprintf (stderr, "in less-than func: (%d) (%s) (%d)\n", argc, type, (int) date);
+ if (argc > 0) {
+ char *string, *date_str;
- d(fprintf (stderr, "%s\n", node->data));
+ date_str = format_date (date, 0);
+
+ if (!strcmp ("SENT", type)) {
+ string = g_strdup_printf ("SENTBEFORE \"%s\"", date_str);
+ } else {
+ string = g_strdup_printf ("BEFORE \"%s\"", date_str);
+ }
+
+ (*list)->data = string;
+ g_free (type);
}
- 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 const char *
-get_func (struct sexp_node *node)
+static ESExpResult *
+func_gt (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
{
- int i;
+ GList **list = data;
+ char *type = (*list)->data;
+ time_t date = (time_t) (argv[1])->value.number;
+ ESExpResult *r;
+
+ fprintf (stderr, "in greater-than func: (%d) (%s) (%d)\n", argc, type, (int) date);
+ if (argc > 0) {
+ char *string, *date_str;
+
+ date_str = format_date (date, 0);
+
+ if (!strcmp ("SENT", type)) {
+ string = g_strdup_printf ("SENTSINCE \"%s\"", date_str);
+ } else {
+ string = g_strdup_printf ("SINCE \"%s\"", date_str);
+ }
+
+ (*list)->data = string;
+ g_free (type);
+ }
- for (i = 0; esexp_keys[i]; i++)
- if (!strncmp (esexp_keys[i], node->function, strlen (node->function)))
- break;
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
- if (esexp_keys[i])
- return imap_keys[i];
- else
- return node->function;
+ return r;
}
-static char *
-get_data (struct sexp_node *node)
+static ESExpResult *
+func_eq (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ char *type = (*list)->data;
+ time_t date = (time_t) (argv[1])->value.number;
+ ESExpResult *r;
+
+ fprintf (stderr, "in equal-to func: (%d) (%s) (%d)\n", argc, type, (int) date);
+ if (argc > 0) {
+ char *string, *date_str;
+
+ date_str = format_date (date, 0);
+
+ if (!strcmp ("SENT", type)) {
+ string = g_strdup_printf ("SENTON \"%s\"", date_str);
+ } else {
+ string = g_strdup_printf ("ON \"%s\"", date_str);
+ }
+
+ (*list)->data = string;
+ g_free (type);
+ }
+
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
+
+ return r;
+}
+
+static ESExpResult *
+func_match_all (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
{
- GPtrArray *args;
- const char *func;
- char *data, *token, *p;
- int i, len;
+ /* match-all doesn't have a IMAP equiv */
+ ESExpResult *r;
- func = get_func (node);
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
- args = g_ptr_array_new ();
+ return r;
+}
+
+static ESExpResult *
+func_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ char *value = (*argv)->value.string;
+ ESExpResult *r;
- p = node->data;
- while (p && *p) {
- token = get_token (p, &len);
- g_ptr_array_add (args, token);
- p += len;
+ if (argc > 0) {
+ char *string;
+
+ string = g_strdup_printf ("BODY \"%s\"", value);
+
+ *list = g_list_prepend (*list, string);
}
- if (func && !strcmp ("HEADER", func) && args->len > 0)
- string_unquote (args->pdata[0]);
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
- if (args->len > 0) {
- data = g_strjoinv (" ", (char **) args->pdata);
- } else {
- data = g_strdup ("");
+ return r;
+}
+
+static ESExpResult *
+func_header_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ char *header = (argv[0])->value.string;
+ char *match = (argv[1])->value.string;
+ ESExpResult *r;
+
+ if (argc == 2) {
+ char *string;
+ string = g_strdup_printf ("HEADER %s \"%s\"", header, match);
+
+ *list = g_list_prepend (*list, string);
}
- for (i = 0; i < args->len; i++)
- g_free (args->pdata[i]);
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
- g_ptr_array_free (args, TRUE);
+ return r;
+}
+
+static ESExpResult *
+func_user_tag (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ /* FIXME: what do I do here? */
+ ESExpResult *r;
- return data;
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
+
+ return r;
}
-static char *
-str_sexp_node (struct sexp_node *node)
+static ESExpResult *
+func_user_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
{
- char *node_str, *data, *str, *l_str, *r_str;
- const char *func;
+ /* FIXME: what do I do here? */
+ ESExpResult *r;
- func = get_func (node);
- data = get_data (node);
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
- if (func) {
- if (*data)
- str = g_strdup_printf ("%s %s", func, data);
- else
- str = g_strdup (func);
- } else {
- str = NULL;
- }
+ return r;
+}
+
+static ESExpResult *
+func_get_sent_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ ESExpResult *r;
- g_free (data);
+ *list = g_list_prepend (*list, g_strdup ("SENT"));
- r_str = NULL;
- if (node->r_node)
- r_str = str_sexp_node (node->r_node);
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
- l_str = NULL;
- if (node->l_node)
- l_str = str_sexp_node (node->l_node);
+ return r;
+}
+
+static ESExpResult *
+func_get_received_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
+{
+ GList **list = data;
+ ESExpResult *r;
- 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 ("");
- }
- }
+ *list = g_list_prepend (*list, g_strdup ("RECEIVED"));
- 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_get_current_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data)
{
- if (node->r_node)
- free_sexp_node (node->r_node);
+ /* FIXME: what do I do here? */
+ ESExpResult *r;
- if (node->l_node)
- free_sexp_node (node->l_node);
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = FALSE;
- g_free (node->function);
- g_free (node->data);
- g_free (node);
+ 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", (ESExpFunc *) func_and, 0 },
+ { "or", (ESExpFunc *) func_or, 0 },
+ { "not", (ESExpFunc *) func_not, 0 },
+ { "<", (ESExpFunc *) func_lt, 0 },
+ { ">", (ESExpFunc *) func_gt, 0 },
+ { "=", (ESExpFunc *) func_eq, 0 },
+ { "match-all", (ESExpFunc *) func_match_all, 0 },
+ { "body-contains", (ESExpFunc *) func_body_contains, 0 },
+ { "header-contains", (ESExpFunc *) func_header_contains, 0 },
+ { "user-tag", (ESExpFunc *) func_user_tag, 1 },
+ { "user-flag", (ESExpFunc *) func_user_flag, 1 },
+ { "get-sent-date", (ESExpFunc *) func_get_sent_date, 1 },
+ { "get-received-date", (ESExpFunc *) func_get_received_date, 1 },
+ { "get-current-date", (ESExpFunc *) func_get_current_date, 1 }
+};
+
char *
imap_translate_sexp (const char *expression)
{
- struct sexp_node *root;
- char *sexp, *exp;
+ ESExp *sexp;
+ ESExpResult *r;
+ gchar *retval;
+ GList *list = NULL;
+ int i;
+
+ sexp = e_sexp_new ();
+
+ 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));
- exp = g_strdup (expression);
- strip (exp, '\n');
- root = get_sexp_node (exp);
- g_free (exp);
+ e_sexp_parse (sexp);
- d(print_node (root, 0));
- d(fprintf (stderr, "\n"));
+ r = e_sexp_eval (sexp);
- sexp = str_sexp_node (root);
+ gtk_object_unref (GTK_OBJECT (sexp));
+ e_sexp_result_free (r);
+
+ if (list->next) {
+ g_warning ("conversion to IMAP SEARCH 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;
}