diff options
-rw-r--r-- | camel/ChangeLog | 11 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-store.c | 123 | ||||
-rw-r--r-- | camel/providers/pop3/camel-pop3-folder.c | 4 | ||||
-rw-r--r-- | camel/providers/pop3/camel-pop3-store.c | 169 |
4 files changed, 185 insertions, 122 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index dbf62f9751..e8344c9f88 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,5 +1,16 @@ 2000-06-28 Jeffrey Stedfast <fejj@helixcode.com> + * providers/imap/camel-imap-store.c (imap_connect): Changed to + keep prompting user for a valid password until it either + authenticates or until Canceled by the user. + (camel_imap_command_extended): Improved speed (replaced the + g_strjoinv call with a faster implementation) + + * providers/pop3/camel-pop3-store.c + (camel_pop3_command_get_additional_data): Fixed. + (pop3_connect): Changed to keep prompting the user for a + password until it either works or until Canceled by the user. + * providers/mbox/camel-mbox-summary.c: General cleanup (camel_mbox_summary_sync): Fixed a memory leak and added CamelException handling. diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index 61f9171b09..017ab97116 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -207,37 +207,27 @@ free_auth_types (CamelService *service, GList *authtypes) static gboolean imap_connect (CamelService *service, CamelException *ex) { + CamelImapStore *store = CAMEL_IMAP_STORE (service); struct hostent *h; struct sockaddr_in sin; gint fd, status; - gchar *buf, *msg, *result; - CamelImapStore *store = CAMEL_IMAP_STORE (service); + gchar *buf, *msg, *result, *errbuf = NULL; + gboolean authenticated = FALSE; h = camel_service_gethost (service, ex); if (!h) return FALSE; - if (!service->url->authmech && !service->url->passwd) { - gchar *prompt = g_strdup_printf ("Please enter the IMAP password for %s@%s", - service->url->user, h->h_name); - service->url->passwd = - camel_session_query_authenticator (camel_service_get_session (service), - CAMEL_AUTHENTICATOR_ASK, prompt, - TRUE, service, "password", ex); - g_free (prompt); - if (!service->url->passwd) - return FALSE; - } - + /* connect to the IMAP server */ sin.sin_family = h->h_addrtype; if (service->url->port) sin.sin_port = htons(service->url->port); else sin.sin_port = htons(IMAP_PORT); - + memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr)); - + fd = socket (h->h_addrtype, SOCK_STREAM, 0); if (fd == -1 || connect (fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, @@ -246,16 +236,15 @@ imap_connect (CamelService *service, CamelException *ex) strerror(errno)); if (fd > -1) close (fd); - + return FALSE; } - store->ostream = camel_stream_fs_new_with_fd (fd); store->istream = camel_stream_buffer_new (store->ostream, CAMEL_STREAM_BUFFER_READ); store->command = 0; - + /* Read the greeting, if any. */ buf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (store->istream)); if (!buf) { @@ -263,29 +252,56 @@ imap_connect (CamelService *service, CamelException *ex) "Could not read greeting from IMAP " "server: %s", camel_exception_get_description (ex)); - gtk_object_unref (GTK_OBJECT (store->ostream)); - gtk_object_unref (GTK_OBJECT (store->istream)); + + imap_disconnect (service, ex); return FALSE; } g_free (buf); - status = camel_imap_command (store, NULL, &msg, "LOGIN \"%s\" \"%s\"", - service->url->user, - service->url->passwd); + /* authenticate the user */ + while (!authenticated) { + if (errbuf) { + /* We need to un-cache the password before prompting again */ + camel_session_query_authenticator (camel_service_get_session (service), + CAMEL_AUTHENTICATOR_TELL, NULL, + TRUE, service, "password", ex); + g_free (service->url->passwd); + service->url->passwd = NULL; + } - if (status != CAMEL_IMAP_OK) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - "Unable to authenticate to IMAP " - "server. Error sending password:" - " %s", msg ? msg : "(Unknown)"); - g_free (msg); - gtk_object_unref (GTK_OBJECT (store->ostream)); - gtk_object_unref (GTK_OBJECT (store->istream)); - return FALSE; - } else { - g_message ("IMAP Service sucessfully authenticated user %s", service->url->user); - } + if (!service->url->authmech && !service->url->passwd) { + gchar *prompt; + + prompt = g_strdup_printf ("%sPlease enter the IMAP password for %s@%s", + errbuf ? errbuf : "", service->url->user, h->h_name); + service->url->passwd = + camel_session_query_authenticator (camel_service_get_session (service), + CAMEL_AUTHENTICATOR_ASK, prompt, + TRUE, service, "password", ex); + g_free (prompt); + g_free (errbuf); + errbuf = NULL; + + if (!service->url->passwd) { + imap_disconnect (service, ex); + return FALSE; + } + } + + status = camel_imap_command (store, NULL, &msg, "LOGIN \"%s\" \"%s\"", + service->url->user, + service->url->passwd); + if (status != CAMEL_IMAP_OK) { + errbuf = g_strdup_printf ("Unable to authenticate to IMAP server.\n" + "Error sending password: %s\n\n", + msg ? msg : "(Unknown)"); + } else { + g_message ("IMAP Service sucessfully authenticated user %s", service->url->user); + authenticated = TRUE; + } + } + /* Now lets find out the IMAP capabilities */ status = camel_imap_command_extended (store, NULL, &result, "CAPABILITY"); @@ -309,6 +325,7 @@ imap_connect (CamelService *service, CamelException *ex) fprintf (stderr, "IMAP provider does%shave SEARCH support\n", store->has_search_capability ? " " : "n't "); service_class->connect (service, ex); + return TRUE; } @@ -611,7 +628,7 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** GPtrArray *data; gchar *cmdid, *cmdbuf, *respbuf; va_list app; - gint status = CAMEL_IMAP_OK; + gint len = 0, status = CAMEL_IMAP_OK; if (folder && store->current_folder != folder && strncmp (fmt, "SELECT", 6) && strncmp (fmt, "EXAMINE", 7) && strncmp (fmt, "STATUS", 6) && @@ -644,10 +661,10 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** fprintf (stderr, "sending : %s %s\r\n", cmdid, cmdbuf); if (camel_stream_printf (store->ostream, "%s %s\r\n", cmdid, cmdbuf) == -1) { - g_free(cmdbuf); - g_free(cmdid); + g_free (cmdbuf); + g_free (cmdid); - *ret = g_strdup (strerror(errno)); + *ret = g_strdup (strerror (errno)); return CAMEL_IMAP_FAIL; } @@ -666,10 +683,13 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** fprintf (stderr, "received: %s\n", respbuf); g_ptr_array_add (data, respbuf); + len += strlen (respbuf) + 1; } if (respbuf) { g_ptr_array_add (data, respbuf); + len += strlen (respbuf) + 1; + status = camel_imap_status (cmdid, respbuf); } else { status = CAMEL_IMAP_FAIL; @@ -677,13 +697,22 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** g_free (cmdid); if (status == CAMEL_IMAP_OK) { - /* Append an empty string to the end of the array - * so when we g_strjoinv it, we get a "\n" after - * the last real line. - */ - g_ptr_array_add (data, ""); - g_ptr_array_add (data, NULL); - *ret = g_strjoinv ("\n", (gchar **)data->pdata); + char *p; + int i; + + *ret = g_malloc0 (len + 1); + + for (i = 0, p = *ret; i < data->len; i++) { + char *ptr, *datap; + + datap = (char *) data->pdata[i]; + ptr = (*datap == '.') ? datap + 1 : datap; + len = strlen (ptr); + memcpy (p, ptr, len); + p += len; + *p++ = '\n'; + } + *p = '\0'; } else { if (status != CAMEL_IMAP_FAIL && respbuf) *ret = g_strdup (strchr (respbuf, ' ' + 1)); diff --git a/camel/providers/pop3/camel-pop3-folder.c b/camel/providers/pop3/camel-pop3-folder.c index 9a2d982fcd..aebe62bbde 100644 --- a/camel/providers/pop3/camel-pop3-folder.c +++ b/camel/providers/pop3/camel-pop3-folder.c @@ -74,7 +74,6 @@ camel_pop3_folder_class_init (CamelPop3FolderClass *camel_pop3_folder_class) object_class->finalize = finalize; } - static void camel_pop3_folder_init (gpointer object, gpointer klass) { @@ -89,7 +88,6 @@ camel_pop3_folder_init (gpointer object, gpointer klass) pop3_folder->uids = NULL; } - GtkType camel_pop3_folder_get_type (void) { @@ -114,7 +112,6 @@ camel_pop3_folder_get_type (void) return camel_pop3_folder_type; } - void finalize (GtkObject *object) { @@ -140,7 +137,6 @@ pop3_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) if (expunge) camel_pop3_store_expunge (CAMEL_POP3_STORE (folder->parent_store), ex); } - static GPtrArray * parse_listing (int count, char *data) diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c index ba2b9857ac..bdfe8dd36e 100644 --- a/camel/providers/pop3/camel-pop3-store.c +++ b/camel/providers/pop3/camel-pop3-store.c @@ -102,13 +102,9 @@ camel_pop3_store_init (gpointer object, gpointer klass) { CamelService *service = CAMEL_SERVICE (object); - service->url_flags = ( CAMEL_SERVICE_URL_NEED_USER | - CAMEL_SERVICE_URL_NEED_HOST ); + service->url_flags = (CAMEL_SERVICE_URL_NEED_USER | CAMEL_SERVICE_URL_NEED_HOST); } - - - GtkType camel_pop3_store_get_type (void) { @@ -147,7 +143,6 @@ finalize (GtkObject *object) g_free (pop3_store->apop_timestamp); } - static CamelServiceAuthType password_authtype = { "Password", @@ -392,7 +387,10 @@ pop3_connect (CamelService *service, CamelException *ex) { CamelPop3Store *store = CAMEL_POP3_STORE (service); int status; - char *msg; + char *msg, *errbuf = NULL; + gboolean authenticated = FALSE; + gboolean auth_supported = TRUE; + #ifdef HAVE_KRB4 gboolean kpop = (service->url->authmech && !strcmp (service->url->authmech, "+KPOP")); @@ -404,72 +402,90 @@ pop3_connect (CamelService *service, CamelException *ex) if (!connect_to_server (service, TRUE, ex)) return FALSE; - /* The KPOP code will have set the password to be the username - * in connect_to_server. Password and APOP are the only other - * cases, and they both need a password. - */ - if (!service->url->passwd) { - char *prompt = g_strdup_printf ("Please enter the POP3 password for %s@%s", - service->url->user, - service->url->host); - service->url->passwd = camel_session_query_authenticator ( - camel_service_get_session (service), - CAMEL_AUTHENTICATOR_ASK, prompt, TRUE, - service, "password", ex); - g_free (prompt); + while (auth_supported && !authenticated) { + /* The KPOP code will have set the password to be the username + * in connect_to_server. Password and APOP are the only other + * cases, and they both need a password. + */ + + if (errbuf) { + /* We need to un-cache the password before prompting again */ + camel_session_query_authenticator (camel_service_get_session (service), + CAMEL_AUTHENTICATOR_TELL, NULL, + TRUE, service, "password", ex); + g_free (service->url->passwd); + service->url->passwd = NULL; + } + if (!service->url->passwd) { - pop3_disconnect (service, ex); - return FALSE; + char *prompt; + + prompt = g_strdup_printf ("%sPlease enter the POP3 password for %s@%s", + errbuf ? errbuf : "", + service->url->user, + service->url->host); + g_free (errbuf); + errbuf = NULL; + service->url->passwd = camel_session_query_authenticator ( + camel_service_get_session (service), + CAMEL_AUTHENTICATOR_ASK, prompt, TRUE, + service, "password", ex); + + g_free (prompt); + if (!service->url->passwd) { + pop3_disconnect (service, ex); + return FALSE; + } } - } - if (!service->url->authmech || - !strcmp (service->url->authmech, "+KPOP")) { - status = camel_pop3_command (store, &msg, "USER %s", - service->url->user); - if (status != CAMEL_POP3_OK) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - "Unable to connect to POP " - "server. Error sending username:" - " %s", msg ? msg : "(Unknown)"); + if (!service->url->authmech || !strcmp (service->url->authmech, "+KPOP")) { + status = camel_pop3_command (store, &msg, "USER %s", service->url->user); + if (status != CAMEL_POP3_OK) { + errbuf = g_strdup_printf ("Unable to connect to POP server.\n" + "Error sending username: %s\n\n", + msg ? msg : "(Unknown)"); + + g_free (msg); + continue; + } g_free (msg); + + status = camel_pop3_command (store, &msg, "PASS %s", service->url->passwd); + } else if (!strcmp (service->url->authmech, "+APOP") + && store->apop_timestamp) { + char *secret, md5asc[33], *d; + unsigned char md5sum[16], *s; + + secret = g_strdup_printf ("%s%s", store->apop_timestamp, service->url->passwd); + md5_get_digest (secret, strlen (secret), md5sum); + g_free (secret); + + for (s = md5sum, d = md5asc; d < md5asc + 32; s++, d += 2) + sprintf (d, "%.2x", *s); + + status = camel_pop3_command (store, &msg, "APOP %s %s", service->url->user, md5asc); + } else { + camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, + "No support for requested authentication mechanism."); + + auth_supported = FALSE; goto lose; } - g_free (msg); + + if (status != CAMEL_POP3_OK) { + errbuf = g_strdup_printf ("Unable to connect to POP server.\n" + "Error sending password: %s\n\n", + msg ? msg : "(Unknown)"); - status = camel_pop3_command (store, &msg, "PASS %s", - service->url->passwd); - } else if (!strcmp (service->url->authmech, "+APOP") - && store->apop_timestamp) { - char *secret, md5asc[33], *d; - unsigned char md5sum[16], *s; - - secret = g_strdup_printf ("%s%s", store->apop_timestamp, - service->url->passwd); - md5_get_digest (secret, strlen (secret), md5sum); - g_free (secret); - - for (s = md5sum, d = md5asc; d < md5asc + 32; s++, d += 2) - sprintf (d, "%.2x", *s); - - status = camel_pop3_command (store, &msg, "APOP %s %s", - service->url->user, md5asc); - } else { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - "No support for requested " - "authentication mechanism."); - goto lose; - } + g_free (msg); + continue; + } - if (status != CAMEL_POP3_OK) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - "Unable to authenticate to POP " - "server. Error sending password:" - " %s", msg ? msg : "(Unknown)"); g_free (msg); - goto lose; + authenticated = TRUE; } - g_free (msg); + + g_free (errbuf); service_class->connect (service, ex); return TRUE; @@ -480,6 +496,14 @@ pop3_connect (CamelService *service, CamelException *ex) CAMEL_AUTHENTICATOR_TELL, NULL, TRUE, service, "password", ex); + if (auth_supported && !authenticated) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, + "Unable to authenticate to POP server: %s", + msg ? msg : "(Unknown)"); + } + + g_free (errbuf); + pop3_disconnect (service, ex); return FALSE; } @@ -637,8 +661,7 @@ camel_pop3_command (CamelPop3Store *store, char **ret, char *fmt, ...) * Return value: the data, which the caller must free. **/ char * -camel_pop3_command_get_additional_data (CamelPop3Store *store, - CamelException *ex) +camel_pop3_command_get_additional_data (CamelPop3Store *store, CamelException *ex) { CamelStreamBuffer *stream = CAMEL_STREAM_BUFFER (store->istream); GPtrArray *data; @@ -655,18 +678,22 @@ camel_pop3_command_get_additional_data (CamelPop3Store *store, if (!strcmp (buf, ".")) break; - p = (*buf == '.') ? buf + 1 : buf; - g_ptr_array_add (data, p); - len += strlen (p) + 1; + + g_ptr_array_add (data, buf); + len += strlen (buf) + 1; } g_free (buf); if (status == CAMEL_POP3_OK) { - buf = g_malloc (len + 1); + buf = g_malloc0 (len + 1); for (i = 0, p = buf; i < data->len; i++) { - len = strlen (data->pdata[i]); - memcpy (p, data->pdata[i], len); + char *ptr, *datap; + + datap = (char *) data->pdata[i]; + ptr = (*datap == '.') ? datap + 1 : datap; + len = strlen (ptr); + memcpy (p, ptr, len); p += len; *p++ = '\n'; } |