aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/imap/camel-imap-utils.c
diff options
context:
space:
mode:
authorJeffrey Stedfast <fejj@helixcode.com>2000-08-01 04:00:20 +0800
committerJeffrey Stedfast <fejj@src.gnome.org>2000-08-01 04:00:20 +0800
commit3ef60c2537f654d15bed4347dbc12076be3064fc (patch)
treea9fca24bffe91e1e1f4b576e616876b54256c6ec /camel/providers/imap/camel-imap-utils.c
parentf67eb8f79172e77dadb0c02636409e087856baeb (diff)
downloadgsoc2013-evolution-3ef60c2537f654d15bed4347dbc12076be3064fc.tar
gsoc2013-evolution-3ef60c2537f654d15bed4347dbc12076be3064fc.tar.gz
gsoc2013-evolution-3ef60c2537f654d15bed4347dbc12076be3064fc.tar.bz2
gsoc2013-evolution-3ef60c2537f654d15bed4347dbc12076be3064fc.tar.lz
gsoc2013-evolution-3ef60c2537f654d15bed4347dbc12076be3064fc.tar.xz
gsoc2013-evolution-3ef60c2537f654d15bed4347dbc12076be3064fc.tar.zst
gsoc2013-evolution-3ef60c2537f654d15bed4347dbc12076be3064fc.zip
New convenience function to translate a Camel sexp into the equivalent
2000-07-31 Jeffrey Stedfast <fejj@helixcode.com> * providers/imap/camel-imap-utils.c (imap_translate_sexp): New convenience function to translate a Camel sexp into the equivalent IMAP sexp. * providers/imap/camel-imap-store.c: More places now use imap_next_word * providers/imap/camel-imap-folder.c (imap_search_by_expression): Implemented initial version (this may or may not work quite right) svn path=/trunk/; revision=4428
Diffstat (limited to 'camel/providers/imap/camel-imap-utils.c')
-rw-r--r--camel/providers/imap/camel-imap-utils.c243
1 files changed, 243 insertions, 0 deletions
diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c
index 6560481505..08a45de62a 100644
--- a/camel/providers/imap/camel-imap-utils.c
+++ b/camel/providers/imap/camel-imap-utils.c
@@ -28,6 +28,19 @@
#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)
{
@@ -95,3 +108,233 @@ imap_parse_list_response (char *buf, char *namespace, char **flags, char **sep,
return TRUE;
}
+
+static char *
+get_quoted_token (char *string, int *len)
+{
+ char *ep;
+
+ for (ep = string + 1; *ep; ep++)
+ if (*ep == '"' && *(ep - 1) != '\\')
+ break;
+ if (*ep)
+ ep++;
+
+ *len = ep - string;
+
+ return g_strndup (string, *len);
+}
+
+static char *
+get_token (char *string, int *len)
+{
+ char *p, *ep;
+
+ for (p = string; *p && *p == ' '; p++);
+
+ if (*p == '"') {
+ char *token;
+ int i;
+
+ token = get_quoted_token (p, &i);
+
+ *len = i + (p - string);
+
+ return token;
+ }
+
+ for (ep = p; *ep && *ep != ' '; ep++);
+
+ *len = ep - string;
+
+ return g_strndup (p, *len);
+}
+
+struct sexp_node *
+get_sexp_node (const char *exp)
+{
+ 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;
+
+ 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;
+ }
+}
+
+static void
+print_node (struct sexp_node *node, int depth)
+{
+ int i;
+
+ for (i = 0; i < depth; i++)
+ d(fprintf (stderr, " "));
+
+ d(fprintf (stderr, "%s\n", node->function));
+
+ if (*node->data) {
+ for (i = 0; i < depth + 1; i++)
+ d(fprintf (stderr, " "));
+
+ d(fprintf (stderr, "%s\n", node->data));
+ }
+
+ if (node->r_node)
+ print_node (node->r_node, depth + 1);
+
+ if (node->l_node)
+ print_node (node->l_node, depth);
+}
+
+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)
+{
+ 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;
+ }
+
+ 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);
+
+ 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 ("");
+ }
+ }
+
+ g_free (str);
+ g_free (l_str);
+ g_free (r_str);
+
+ return node_str;
+}
+
+static void
+free_sexp_node (struct sexp_node *node)
+{
+ if (node->r_node)
+ free_sexp_node (node->r_node);
+
+ if (node->l_node)
+ free_sexp_node (node->l_node);
+
+ g_free (node->data);
+ g_free (node);
+}
+
+char *
+imap_translate_sexp (const char *expression)
+{
+ struct sexp_node *root;
+ char *sexp;
+
+ root = get_sexp_node (expression);
+
+ d(print_node (root, 0));
+
+ sexp = str_sexp_node (root);
+ sexp[strlen (sexp) - 1] = '\0';
+ strcpy (sexp, sexp + 1);
+
+ free_sexp_node (root);
+
+ return sexp;
+}