diff options
Diffstat (limited to 'camel/providers')
-rw-r--r-- | camel/providers/nntp/Makefile.am | 2 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-auth.c | 57 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-auth.h | 42 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-folder.c | 29 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-folder.h | 2 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-resp-codes.h | 53 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-store.c | 149 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-store.h | 3 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-utils.c | 23 |
9 files changed, 263 insertions, 97 deletions
diff --git a/camel/providers/nntp/Makefile.am b/camel/providers/nntp/Makefile.am index d9122e9026..1cdc9c4718 100644 --- a/camel/providers/nntp/Makefile.am +++ b/camel/providers/nntp/Makefile.am @@ -18,6 +18,7 @@ INCLUDES = -I../.. \ -DG_LOG_DOMAIN=\"camel-nntp-provider\" libcamelnntp_la_SOURCES = \ + camel-nntp-auth.c \ camel-nntp-folder.c \ camel-nntp-newsrc.c \ camel-nntp-provider.c \ @@ -25,6 +26,7 @@ libcamelnntp_la_SOURCES = \ camel-nntp-utils.c libcamelnntpinclude_HEADERS = \ + camel-nntp-resp-codes.h \ camel-nntp-folder.h \ camel-nntp-newsrc.h \ camel-nntp-store.h \ diff --git a/camel/providers/nntp/camel-nntp-auth.c b/camel/providers/nntp/camel-nntp-auth.c new file mode 100644 index 0000000000..7b48bde808 --- /dev/null +++ b/camel/providers/nntp/camel-nntp-auth.c @@ -0,0 +1,57 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camel-nntp-auth.c : authentication for nntp */ + +/* + * + * Copyright (C) 2000 Helix Code, Inc. <toshok@helixcode.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + +#include <camel-nntp-store.h> +#include <camel-nntp-resp-codes.h> +#include <camel-exception.h> + +int +camel_nntp_auth_authenticate (CamelNNTPStore *store, CamelException *ex) +{ + int resp; + + /* first send username */ + resp = camel_nntp_command (store, ex, NULL, "AUTHINFO USER %s", "username"); /* XXX */ + + if (resp == NNTP_AUTH_REJECTED) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, + "Server rejected username"); + return resp; + } + else if (resp != NNTP_AUTH_CONTINUE) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, + "Failed to send username to server"); + return resp; + } + + /* then send the username if the server asks for it */ + resp = camel_nntp_command (store, ex, NULL, "AUTHINFO PASS %s", "password"); /* XXX */ + if (resp == NNTP_AUTH_REJECTED) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, + "Server rejected username/password"); + return resp; + } + + return resp; +} diff --git a/camel/providers/nntp/camel-nntp-auth.h b/camel/providers/nntp/camel-nntp-auth.h new file mode 100644 index 0000000000..61b07d4b2f --- /dev/null +++ b/camel/providers/nntp/camel-nntp-auth.h @@ -0,0 +1,42 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camel-nntp-auth.h : authentication for nntp */ + +/* + * + * Author : Chris Toshok <toshok@helixcode.com> + * + * Copyright (C) 1999 Helix Code . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + +#ifndef CAMEL_NNTP_AUTH_H +#define CAMEL_NNTP_AUTH_H 1 + + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + +int camel_nntp_auth_authenticate (CamelNNTPStore *store, CamelException *ex); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CAMEL_NNTP_AUTH_H */ diff --git a/camel/providers/nntp/camel-nntp-folder.c b/camel/providers/nntp/camel-nntp-folder.c index 43209758a7..6ab92923a2 100644 --- a/camel/providers/nntp/camel-nntp-folder.c +++ b/camel/providers/nntp/camel-nntp-folder.c @@ -35,6 +35,7 @@ #include <fcntl.h> #include "camel-folder-summary.h" +#include "camel-nntp-resp-codes.h" #include "camel-nntp-store.h" #include "camel-nntp-folder.h" #include "camel-nntp-store.h" @@ -85,12 +86,6 @@ nntp_folder_init (CamelFolder *folder, CamelStore *parent_store, /* XX */ nntp_folder->group_name = g_strdup (strrchr (name, '/') + 1); - -#if 0 - /* get (or create) uid list */ - if (!(nntp_load_uid_list (nntp_folder) > 0)) - nntp_generate_uid_list (nntp_folder); -#endif } static void @@ -209,16 +204,21 @@ nntp_folder_get_message (CamelFolder *folder, const gchar *uid, CamelException * parent_store = camel_folder_get_parent_store (folder); message_id = strchr (uid, ',') + 1; - status = camel_nntp_command (CAMEL_NNTP_STORE( parent_store ), NULL, "ARTICLE %s", message_id); + status = camel_nntp_command (CAMEL_NNTP_STORE( parent_store ), ex, NULL, "ARTICLE %s", message_id); /* if the message_id was not found, raise an exception and return */ - if (status != CAMEL_NNTP_OK) { + if (status == NNTP_NO_SUCH_ARTICLE) { camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, "message %s not found.", message_id); return NULL; } + else if (status != NNTP_ARTICLE_FOLLOWS) { + /* XXX */ + g_warning ("weird nntp error %d\n", status); + return NULL; + } /* XXX ick ick ick. read the entire message into a buffer and then create a stream_mem for it. */ @@ -395,3 +395,16 @@ camel_nntp_folder_get_type (void) return camel_nntp_folder_type; } + +CamelFolder * +camel_nntp_folder_new (CamelStore *parent, const char *folder_name, CamelException *ex) +{ + CamelFolder *new_folder = CAMEL_FOLDER (camel_object_new (CAMEL_NNTP_FOLDER_TYPE)); + + CF_CLASS (new_folder)->init (new_folder, parent, NULL, + folder_name, ".", FALSE, ex); + + CF_CLASS (new_folder)->refresh_info (new_folder, ex); + + return new_folder; +} diff --git a/camel/providers/nntp/camel-nntp-folder.h b/camel/providers/nntp/camel-nntp-folder.h index 9bbd1466b9..db1687c907 100644 --- a/camel/providers/nntp/camel-nntp-folder.h +++ b/camel/providers/nntp/camel-nntp-folder.h @@ -66,6 +66,8 @@ typedef struct { /* Standard Camel function */ CamelType camel_nntp_folder_get_type (void); +CamelFolder *camel_nntp_folder_new (CamelStore *parent, const char *folder_name, CamelException *ex); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/camel/providers/nntp/camel-nntp-resp-codes.h b/camel/providers/nntp/camel-nntp-resp-codes.h new file mode 100644 index 0000000000..8b9dc8ff6c --- /dev/null +++ b/camel/providers/nntp/camel-nntp-resp-codes.h @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camel-nntp-resp-codes.h : #defines for all the response codes we care about */ + +/* + * + * Copyright (C) 2000 Helix Code, Inc. <toshok@helixcode.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#ifndef CAMEL_NNTP_RESP_CODES_H +#define CAMEL_NNTP_RESP_CODES_H 1 + +#define CAMEL_NNTP_OK(x) ((x) < 400) +#define CAMEL_NNTP_ERR(x) (!CAMEL_NNTP_OK(x) && (x) < 500) +#define CAMEL_NNTP_FAIL(x) (!CAMEL_NNTP_OK(x) && !CAMEL_NNTP_ERR(x)) + +#define NNTP_GREETING_POSTING_OK 200 +#define NNTP_GREETING_NO_POSTING 201 + +#define NNTP_GROUP_SELECTED 211 +#define NNTP_LIST_FOLLOWS 215 +#define NNTP_ARTICLE_FOLLOWS 220 +#define NNTP_HEAD_FOLLOWS 221 +#define NNTP_DATA_FOLLOWS 224 +#define NNTP_NEW_ARTICLE_LIST_FOLLOWS 230 +#define NNTP_NEW_GROUP_LIST_FOLLOWS 231 + +#define NNTP_NO_SUCH_GROUP 411 +#define NNTP_NO_SUCH_ARTICLE 430 + +/* authentication */ +#define NNTP_AUTH_ACCEPTED 281 +#define NNTP_AUTH_CONTINUE 381 +#define NNTP_AUTH_REQUIRED 480 +#define NNTP_AUTH_REJECTED 482 + +#define NNTP_PROTOCOL_ERROR 666 + +#endif /* CAMEL_NNTP_RESP_CODES_H */ diff --git a/camel/providers/nntp/camel-nntp-store.c b/camel/providers/nntp/camel-nntp-store.c index 75b8ef9409..bedcd3f13c 100644 --- a/camel/providers/nntp/camel-nntp-store.c +++ b/camel/providers/nntp/camel-nntp-store.c @@ -35,17 +35,17 @@ #include "libgnome/libgnome.h" +#include "camel-nntp-resp-codes.h" #include "camel-folder-summary.h" #include "camel-nntp-store.h" #include "camel-nntp-folder.h" +#include "camel-nntp-auth.h" #include "camel-exception.h" #include "camel-url.h" #include "string-utils.h" #define NNTP_PORT 119 -#define DUMP_EXTENSIONS - static CamelRemoteStoreClass *remote_store_class = NULL; static CamelServiceClass *service_class = NULL; @@ -58,11 +58,11 @@ static CamelServiceClass *service_class = NULL; static gboolean ensure_news_dir_exists (CamelNNTPStore *store); static void -camel_nntp_store_get_extensions (CamelNNTPStore *store) +camel_nntp_store_get_extensions (CamelNNTPStore *store, CamelException *ex) { store->extensions = 0; - if (CAMEL_NNTP_OK == camel_nntp_command (store, NULL, "LIST EXTENSIONS")) { + if (camel_nntp_command (store, ex, NULL, "LIST EXTENSIONS") == NNTP_LIST_FOLLOWS) { gboolean done = FALSE; CamelException ex; @@ -113,19 +113,16 @@ camel_nntp_store_get_extensions (CamelNNTPStore *store) } static void -camel_nntp_store_get_overview_fmt (CamelNNTPStore *store) +camel_nntp_store_get_overview_fmt (CamelNNTPStore *store, CamelException *ex) { int status; int i; gboolean done = FALSE; - CamelException ex; - - camel_exception_init (&ex); - status = camel_nntp_command (store, NULL, + status = camel_nntp_command (store, ex, NULL, "LIST OVERVIEW.FMT"); - if (status != CAMEL_NNTP_OK) { + if (status != NNTP_LIST_FOLLOWS) { /* if we can't get the overview format, we should disable OVER support */ g_warning ("server reported support of OVER but LIST OVERVIEW.FMT failed." @@ -144,7 +141,7 @@ camel_nntp_store_get_overview_fmt (CamelNNTPStore *store) while (!done) { char *line; - if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &line, &ex) < 0) + if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &line, ex) < 0) break; /* XXX */ if (*line == '.') { @@ -227,11 +224,11 @@ nntp_store_connect (CamelService *service, CamelException *ex) /* check if posting is allowed. */ resp_code = atoi (buf); - if (resp_code == 200) { + if (resp_code == NNTP_GREETING_POSTING_OK) { g_print ("posting allowed\n"); store->posting_allowed = TRUE; } - else if (resp_code == 201) { + else if (resp_code == NNTP_GREETING_NO_POSTING) { g_print ("no posting allowed\n"); store->posting_allowed = FALSE; } @@ -243,11 +240,11 @@ nntp_store_connect (CamelService *service, CamelException *ex) g_free (buf); /* get a list of extensions that the server supports */ - camel_nntp_store_get_extensions (store); + camel_nntp_store_get_extensions (store, ex); /* if the server supports the OVER extension, get the overview.fmt */ if (store->extensions & CAMEL_NNTP_EXT_OVER) - camel_nntp_store_get_overview_fmt (store); + camel_nntp_store_get_overview_fmt (store, ex); return TRUE; } @@ -257,11 +254,7 @@ nntp_store_disconnect (CamelService *service, CamelException *ex) { CamelNNTPStore *store = CAMEL_NNTP_STORE (service); - /*if (!service->connected) - * return TRUE; - */ - - camel_nntp_command (store, NULL, "QUIT"); + camel_nntp_command (store, ex, NULL, "QUIT"); if (store->newsrc) camel_nntp_newsrc_write (store->newsrc); @@ -283,8 +276,6 @@ static CamelFolder * nntp_store_get_folder (CamelStore *store, const gchar *folder_name, gboolean get_folder, CamelException *ex) { - CamelNNTPFolder *new_nntp_folder; - CamelFolder *new_folder; CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store); printf ("get_folder called on folder_name=%s\n", folder_name); @@ -302,23 +293,7 @@ nntp_store_get_folder (CamelStore *store, const gchar *folder_name, return NULL; } - /* check if folder has already been created */ - /* call the standard routine for that when */ - /* it is done ... */ - - new_nntp_folder = CAMEL_NNTP_FOLDER (camel_object_new (CAMEL_NNTP_FOLDER_TYPE)); - new_folder = CAMEL_FOLDER (new_nntp_folder); - - /* XXX We shouldn't be passing NULL here, but it's equivalent to - * what was there before, and there's no - * CamelNNTPFolder::get_subfolder yet anyway... - */ - CF_CLASS (new_folder)->init (new_folder, store, NULL, - folder_name, ".", FALSE, ex); - - CF_CLASS (new_folder)->refresh_info (new_folder, ex); - - return new_folder; + return camel_nntp_folder_new (store, folder_name, ex); } static void @@ -396,22 +371,63 @@ camel_nntp_store_get_type (void) * no extended response, @ret will be set to NULL.) The caller must * free this buffer when it is done with it. * - * Return value: one of CAMEL_NNTP_OK (command executed successfully), - * CAMEL_NNTP_ERR (command encounted an error), or CAMEL_NNTP_FAIL - * (a protocol-level error occurred, and Camel is uncertain of the - * result of the command.) + * Return value: the response code of the nntp command. **/ +static int +camel_nntp_command_send_recv (CamelNNTPStore *store, CamelException *ex, char **ret, char *cmd) +{ + char *respbuf; + int resp_code; + gboolean again; + + do { + again = FALSE; + + /* Send the command */ + if (camel_remote_store_send_string (CAMEL_REMOTE_STORE (store), ex, cmd) < 0) { + return NNTP_PROTOCOL_ERROR; + } + + /* Read the response */ + if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &respbuf, ex) < 0) { + if (ret) + *ret = g_strdup (g_strerror (errno)); + return NNTP_PROTOCOL_ERROR; + } + + resp_code = atoi (respbuf); + + /* this is kind of a gross hack, but since an auth challenge + can pop up at any time, and we want to shield this from our + callers, we handle authentication here. */ + if (resp_code == NNTP_AUTH_REQUIRED) { + resp_code = camel_nntp_auth_authenticate (store, ex); + if (resp_code != NNTP_AUTH_ACCEPTED) { + return resp_code; + } + + /* need to resend our command here */ + again = TRUE; + } + } while (again); + + if (ret) { + *ret = strchr (respbuf, ' '); + if (*ret) + *ret = g_strdup (*ret + 1); + } + g_free (respbuf); + + return resp_code; +} + int -camel_nntp_command (CamelNNTPStore *store, char **ret, char *fmt, ...) +camel_nntp_command (CamelNNTPStore *store, CamelException *ex, char **ret, char *fmt, ...) { - char *cmdbuf, *respbuf; + char *cmdbuf; va_list ap; - int status; int resp_code; char *real_fmt; - CamelException ex; - - camel_exception_init (&ex); real_fmt = g_strdup_printf ("%s\r\n", fmt); @@ -421,38 +437,11 @@ camel_nntp_command (CamelNNTPStore *store, char **ret, char *fmt, ...) g_free (real_fmt); - /* Send the command */ - if (camel_remote_store_send_string (CAMEL_REMOTE_STORE (store), &ex, cmdbuf) < 0) { - g_free (cmdbuf); - return CAMEL_NNTP_FAIL; - } + resp_code = camel_nntp_command_send_recv (store, ex, ret, cmdbuf); g_free (cmdbuf); - /* Read the response */ - if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &respbuf, &ex) < 0) { - if (ret) - *ret = g_strdup (g_strerror (errno)); - return CAMEL_NNTP_FAIL; - } - - resp_code = atoi (respbuf); - - if (resp_code < 400) - status = CAMEL_NNTP_OK; - else if (resp_code < 500) - status = CAMEL_NNTP_ERR; - else - status = CAMEL_NNTP_FAIL; - - if (ret) { - *ret = strchr (respbuf, ' '); - if (*ret) - *ret = g_strdup (*ret + 1); - } - g_free (respbuf); - - return status; + return resp_code; } void @@ -469,8 +458,8 @@ camel_nntp_store_subscribe_group (CamelStore *store, return; } - if (CAMEL_NNTP_OK == camel_nntp_command ( CAMEL_NNTP_STORE (store), - &ret, "GROUP %s", group_name)) { + if (camel_nntp_command ( CAMEL_NNTP_STORE (store), + ex, &ret, "GROUP %s", group_name) == NNTP_GROUP_SELECTED) { /* we create an empty summary file here, so that when the group is opened we'll know we need to build it. */ gchar *summary_file; diff --git a/camel/providers/nntp/camel-nntp-store.h b/camel/providers/nntp/camel-nntp-store.h index 77f04d87ee..0d30a38097 100644 --- a/camel/providers/nntp/camel-nntp-store.h +++ b/camel/providers/nntp/camel-nntp-store.h @@ -99,8 +99,7 @@ GList *camel_nntp_store_list_subscribed_groups(CamelStore *store); gchar *camel_nntp_store_get_toplevel_dir (CamelNNTPStore *store); /* support functions */ -enum { CAMEL_NNTP_OK, CAMEL_NNTP_ERR, CAMEL_NNTP_FAIL }; -int camel_nntp_command (CamelNNTPStore *store, char **ret, char *fmt, ...); +int camel_nntp_command (CamelNNTPStore *store, CamelException *ex, char **ret, char *fmt, ...); /* Standard Camel function */ CamelType camel_nntp_store_get_type (void); diff --git a/camel/providers/nntp/camel-nntp-utils.c b/camel/providers/nntp/camel-nntp-utils.c index 509fe452cc..c741146f26 100644 --- a/camel/providers/nntp/camel-nntp-utils.c +++ b/camel/providers/nntp/camel-nntp-utils.c @@ -23,10 +23,12 @@ */ #include "camel-folder-summary.h" +#include "camel-nntp-resp-codes.h" #include "camel-nntp-folder.h" #include "camel-nntp-store.h" #include "camel-nntp-utils.h" #include "camel-stream-mem.h" +#include "camel-exception.h" #include <stdlib.h> #include <string.h> @@ -38,12 +40,12 @@ get_OVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, int status; CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - status = camel_nntp_command (nntp_store, NULL, + status = camel_nntp_command (nntp_store, ex, NULL, "XOVER %d-%d", first_message, last_message); - if (status == CAMEL_NNTP_OK) { + if (status == NNTP_DATA_FOLLOWS) { gboolean done = FALSE; while (!done) { @@ -106,6 +108,10 @@ get_OVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, g_free (line); } } + else { + /* XXX */ + g_warning ("weird nntp response for XOVER: %d\n", status); + } } #if 0 @@ -117,10 +123,10 @@ get_HEAD_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, int status; for (i = first_message; i < last_message; i ++) { - status = camel_nntp_command (nntp_store, NULL, + status = camel_nntp_command (nntp_store, ex, NULL, "HEAD %d", i); - if (status == CAMEL_NNTP_OK) { + if (status == NNTP_HEAD_FOLLOWS) { gboolean done = FALSE; char *buf; int buf_len; @@ -215,15 +221,18 @@ camel_nntp_get_headers (CamelStore *store, int first_message, nb_message, last_message; int status; - status = camel_nntp_command (nntp_store, &ret, + status = camel_nntp_command (nntp_store, ex, &ret, "GROUP %s", CAMEL_NNTP_FOLDER (folder)->group_name); sscanf (ret, "%d %d %d", &nb_message, &first_message, &last_message); g_free (ret); - if (status != CAMEL_NNTP_OK) { + if (status == NNTP_NO_SUCH_GROUP) { /* XXX throw invalid group exception */ - printf ("invalid group\n"); + camel_exception_setv (ex, + CAMEL_EXCEPTION_FOLDER_INVALID, + "group %s not found on server", + CAMEL_NNTP_FOLDER (folder)->group_name); return; } |