Enlightenment CVS committal Author : englebass Project : e_modules Module : mail
Dir : e_modules/mail Modified Files: imap2.h imap2.c Log Message: Implement SEARCH and take care when the data does not end with \r\n. =================================================================== RCS file: /cvs/e/e_modules/mail/imap2.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -3 -r1.2 -r1.3 --- imap2.h 22 Jun 2007 13:36:35 -0000 1.2 +++ imap2.h 25 Jul 2007 18:27:21 -0000 1.3 @@ -15,7 +15,10 @@ IMAP_STATE_DISCONNECTED, IMAP_STATE_CONNECTED, IMAP_STATE_AUTHENTICATED, - IMAP_STATE_SELECTED + IMAP_STATE_IDLING, + IMAP_STATE_SEARCH_UNSEEN, + IMAP_STATE_SEARCH_RECENT, + IMAP_STATE_SEARCH_NEW } ImapState; struct _ImapClient @@ -23,7 +26,7 @@ Config_Box *config; Ecore_Con_Server *server; - int cmd; + unsigned int cmd; ImapState state; int idle; unsigned char idling : 1; @@ -33,6 +36,11 @@ Ecore_Event_Handler *data_handler; void *data; + + struct { + char *data; + unsigned int size; + } old; }; void _mail_imap_check_mail(void *data); @@ -41,8 +49,3 @@ void _mail_imap_shutdown(); #endif - -//imap.1and1.com -//m39988144-2/3 -////testing/2 -// =================================================================== RCS file: /cvs/e/e_modules/mail/imap2.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -3 -r1.7 -r1.8 --- imap2.c 20 Jul 2007 12:50:31 -0000 1.7 +++ imap2.c 25 Jul 2007 18:27:21 -0000 1.8 @@ -7,11 +7,8 @@ /* * TODO: - * * Make it possible to get Unseen mail - * * Let the user select between Unseen and Recent mail - * * When a client reads the mailbox we don't always get <n> EXISTS - * and <n> RECENT updates. Need to parse f.eks. - * '* 71 FETCH (FLAGS (\Seen \Deleted \Recent NonJunk))' + * * Let the user select between Unseen, Recent and New mail + * * Don't fail on incomplete data from the server */ static ImapClient *_mail_imap_client_find (Ecore_Con_Server *server); @@ -24,6 +21,9 @@ static void _mail_imap_server_idle (ImapClient *ic); static void _mail_imap_server_noop (ImapClient *ic); +static int elements (char *p); +static char *find_rn (char *data, unsigned int size); + static Evas_List *iclients = NULL; void @@ -70,7 +70,7 @@ } else { - if (ic->idle == 1) _mail_imap_server_idle (ic); + if (ic->idling) _mail_imap_server_idle (ic); else _mail_imap_server_noop (ic); /* Need to set this to revert the state of the icon */ _mail_set_text (ic->data); @@ -111,7 +111,6 @@ iclients = evas_list_remove (iclients, ic); _mail_imap_client_logout (ic); E_FREE (ic); - } void @@ -130,6 +129,7 @@ ecore_event_handler_del (ic->data_handler); iclients = evas_list_remove_list (iclients, iclients); _mail_imap_client_logout (ic); + E_FREE (ic->old.data); E_FREE (ic); } } @@ -210,6 +210,7 @@ ic->state = IMAP_STATE_DISCONNECTED; } + E_FREE (ic->old.data); ecore_con_server_del (ic->server); ic->server = NULL; @@ -224,7 +225,7 @@ ImapClient *ic; char *reply, *p, *pp; char out[1024]; - int len; + unsigned int len, size; ic = _mail_imap_client_find (ev->server); if (!ic) @@ -232,36 +233,83 @@ if (ic->state == IMAP_STATE_DISCONNECTED) return 1; - reply = ev->data; - /* Check for correct EOD */ - if ((*(reply + ev->size - 2) != '\r') && (*(reply + ev->size - 1) != '\n')) + /* Hijack server data. + * We require minimum 2 characters, as the minimum server data is '\r\n' */ + if ((ic->old.data) || (ev->size < 2)) + { + /* TODO: Check that we don't grow to big! */ + ic->old.data = realloc (ic->old.data, ic->old.size + ev->size); + memcpy (ic->old.data + ic->old.size, ev->data, ev->size); + ic->old.size += ev->size; + E_FREE (ev->data); + if (ic->old.size < 2) return 0; + + reply = ic->old.data; + size = ic->old.size; + ic->old.data = NULL; + ic->old.size = 0; + } + else { - printf ("Imap Failure: Data from imap server has wrong eol termination 0x%x0x%x!\n", - *(reply + ev->size - 2), *(reply + ev->size - 2)); - _mail_imap_client_logout (ic); - return 0; + reply = ev->data; + size = ev->size; } - - p = reply; - while ((p) && ((p - reply) < ev->size)) + ev->data = NULL; + /* Check for correct EOD */ + if ((*(reply + size - 2) != '\r') && (*(reply + size - 1) != '\n')) { - /* find eol */ - pp = strstr (p, "\r\n"); - if (pp) *pp = '\0'; + /* We got incomplete data, search for last EOD */ + unsigned int pos = 0; + char *data; + + data = reply; + while (pos < (size - 1)) + { + if ((*(reply + pos) == '\r') && (*(reply + pos + 1) == '\n')) + data = reply + pos + 2; + pos++; + } + ic->old.size = size - (data - reply); + ic->old.data = malloc (ic->old.size); + memcpy (ic->old.data, data, ic->old.size); + + /* Remove captured data from reply */ + if (data == reply) + E_FREE (reply); else { - printf ("Imap Failure: Couldn't find eol\n"); - _mail_imap_client_logout (ic); - return 0; + data -= 2; + data = NULL; + data += 2; + size -= ic->old.size; } - /* parse data */ - if (!_mail_imap_server_data_parse (ic, p)) + } + + if (reply) + { + p = reply; + pp = p; + while ((p) && ((p - reply) < size)) { - _mail_imap_client_logout (ic); - return 0; + /* find EOL */ + pp = find_rn (p, size - (pp - p)); + if (!pp) + { + printf ("Imap Failure: Couldn't find EOL\n"); + _mail_imap_client_logout (ic); + return 0; + } + *pp = '\0'; + /* parse data */ + if (!_mail_imap_server_data_parse (ic, p)) + { + _mail_imap_client_logout (ic); + return 0; + } + /* next */ + p = pp + 2; } - /* next */ - p = pp + 2; + free (reply); } switch (ic->state) @@ -282,23 +330,42 @@ len = snprintf (out, sizeof (out), "A%04i LOGIN %s %s\r\n", ic->cmd++, ic->config->user, ic->config->pass); ecore_con_server_send (ic->server, out, len); - ic->state++; + ic->state = IMAP_STATE_AUTHENTICATED; } break; case IMAP_STATE_AUTHENTICATED: len = snprintf (out, sizeof (out), "A%04i EXAMINE %s\r\n", ic->cmd++, ic->config->new_path); ecore_con_server_send (ic->server, out, len); - ic->state++; + ic->state = IMAP_STATE_SEARCH_UNSEEN; break; - case IMAP_STATE_SELECTED: + case IMAP_STATE_IDLING: if ((ic->idle == 1) && (!ic->idling)) { + printf ("Begin idle\n"); len = snprintf (out, sizeof (out), "A%04i IDLE\r\n", ic->cmd++); ecore_con_server_send (ic->server, out, len); ic->idling = 1; } break; + case IMAP_STATE_SEARCH_UNSEEN: + _mail_imap_server_idle (ic); + len = snprintf (out, sizeof (out), "A%04i SEARCH UNSEEN UNDELETED\r\n", ic->cmd++); + ecore_con_server_send (ic->server, out, len); + ic->state = IMAP_STATE_IDLING; + break; + case IMAP_STATE_SEARCH_RECENT: + _mail_imap_server_idle (ic); + len = snprintf (out, sizeof (out), "A%04i SEARCH RECENT UNDELETED\r\n", ic->cmd++); + ecore_con_server_send (ic->server, out, len); + ic->state = IMAP_STATE_IDLING; + break; + case IMAP_STATE_SEARCH_NEW: + _mail_imap_server_idle (ic); + len = snprintf (out, sizeof (out), "A%04i SEARCH NEW UNDELETED\r\n", ic->cmd++); + ecore_con_server_send (ic->server, out, len); + ic->state = IMAP_STATE_IDLING; + break; } if (ic->cmd > 9999) ic->cmd = 1; @@ -400,6 +467,11 @@ { printf ("Flags: %s\n", value); } + else if (!strcmp (result, "SEARCH")) + { + ic->config->num_new = elements (value); + printf ("New mail: %d\n", ic->config->num_new); + } else { char *p; @@ -410,16 +482,35 @@ if (!strcmp (value, "RECENT")) { printf ("Recent mails: %d\n", atoi (result)); - ic->config->num_new = atoi (result); + //ic->state = IMAP_STATE_SEARCH_UNSEEN; + //ic->state = IMAP_STATE_SEARCH_RECENT; + ic->state = IMAP_STATE_SEARCH_NEW; } else if (!strcmp (value, "EXISTS")) { printf ("Existing mails: %d\n", atoi (result)); ic->config->num_total = atoi (result); } + else if (!strcmp (value, "FETCH")) + { + printf ("Reading mail: %d\n", atoi (result)); + //ic->state = IMAP_STATE_SEARCH_UNSEEN; + //ic->state = IMAP_STATE_SEARCH_RECENT; + ic->state = IMAP_STATE_SEARCH_NEW; + } + else if (!strcmp (value, "EXPUNGE")) + { + printf ("Deleting mail: %d\n", atoi (result)); + //ic->state = IMAP_STATE_SEARCH_UNSEEN; + //ic->state = IMAP_STATE_SEARCH_RECENT; + ic->state = IMAP_STATE_SEARCH_NEW; + } else { printf ("Unknown untagged reply: %s %s\n", line, value); + //ic->state = IMAP_STATE_SEARCH_UNSEEN; + //ic->state = IMAP_STATE_SEARCH_RECENT; + //ic->state = IMAP_STATE_SEARCH_NEW; } } } @@ -440,6 +531,7 @@ if (!ic) return; + E_FREE (ic->old.data); if (ic->server) { int len; @@ -474,3 +566,29 @@ len = snprintf (out, sizeof (out), "A%04i NOOP\r\n", ic->cmd++); ecore_con_server_send (ic->server, out, len); } + +static int +elements (char *p) +{ + int count = 0; + if (!p) return 0; + do { + if (*p) count++; + p = strchr (p, ' '); + if (p) p++; + } while (p); + return count; +} + +static char * +find_rn (char *data, unsigned int size) +{ + while (size >= 2) + { + if ((*data == '\r') && (*(data + 1) == '\n')) return data; + data++; + size--; + } + return NULL; +} + ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ enlightenment-cvs mailing list enlightenment-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs