aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog11
-rw-r--r--camel/providers/imap/camel-imap-store.c123
-rw-r--r--camel/providers/pop3/camel-pop3-folder.c4
-rw-r--r--camel/providers/pop3/camel-pop3-store.c169
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';
}