diff options
author | Chris Toshok <toshok@helixcode.com> | 2000-09-01 08:57:20 +0800 |
---|---|---|
committer | Chris Toshok <toshok@src.gnome.org> | 2000-09-01 08:57:20 +0800 |
commit | 3cf4f0d243e0c84b519fe027a3299a925e7075fb (patch) | |
tree | 666af08cf25c07ea8c2da1235c4ab512f30193ce /camel | |
parent | 65d4250703d68534210c57f4ed413f95b24390d3 (diff) | |
download | gsoc2013-evolution-3cf4f0d243e0c84b519fe027a3299a925e7075fb.tar.gz gsoc2013-evolution-3cf4f0d243e0c84b519fe027a3299a925e7075fb.tar.zst gsoc2013-evolution-3cf4f0d243e0c84b519fe027a3299a925e7075fb.zip |
make this a bit more robust. try to create an empty .newsrc file for the
2000-08-31 Chris Toshok <toshok@helixcode.com>
* providers/nntp/camel-nntp-newsrc.c
(camel_nntp_newsrc_read_for_server): make this a bit more robust.
try to create an empty .newsrc file for the server if we can't
open it for reading. also, don't allocate everything until we've
opened the file.
* providers/nntp/camel-nntp-utils.c (get_OVER_headers): make use
of our overview field indices.
(camel_nntp_get_headers): only call get_OVER_headers if the
extension is present. warn if it's not - since get_HEAD_headers
needs work before it works.
* providers/nntp/camel-nntp-store.c
(camel_nntp_store_get_extensions): new function - query the server
for it's extensions.
(camel_nntp_store_get_overview_fmt): new function - query the
server for the overview format and build our table of the indices
we care about. support the "full" suffix on fields.
(nntp_store_connect): call camel_nntp_store_get_extensions and
camel_nntp_store_get_overview_fmt.
* providers/nntp/camel-nntp-store.h: add codes for extensions
found on news.mozilla.org. only one that we care about is OVER.
also, add CamelNNTPOverField and an enum of the overview fields
that we care about.
svn path=/trunk/; revision=5152
Diffstat (limited to 'camel')
-rw-r--r-- | camel/ChangeLog | 28 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-newsrc.c | 32 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-store.c | 184 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-store.h | 31 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-utils.c | 56 |
5 files changed, 294 insertions, 37 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 4c3a60d500..410a5dfaf8 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,31 @@ +2000-08-31 Chris Toshok <toshok@helixcode.com> + + * providers/nntp/camel-nntp-newsrc.c + (camel_nntp_newsrc_read_for_server): make this a bit more robust. + try to create an empty .newsrc file for the server if we can't + open it for reading. also, don't allocate everything until we've + opened the file. + + * providers/nntp/camel-nntp-utils.c (get_OVER_headers): make use + of our overview field indices. + (camel_nntp_get_headers): only call get_OVER_headers if the + extension is present. warn if it's not - since get_HEAD_headers + needs work before it works. + + * providers/nntp/camel-nntp-store.c + (camel_nntp_store_get_extensions): new function - query the server + for it's extensions. + (camel_nntp_store_get_overview_fmt): new function - query the + server for the overview format and build our table of the indices + we care about. support the "full" suffix on fields. + (nntp_store_connect): call camel_nntp_store_get_extensions and + camel_nntp_store_get_overview_fmt. + + * providers/nntp/camel-nntp-store.h: add codes for extensions + found on news.mozilla.org. only one that we care about is OVER. + also, add CamelNNTPOverField and an enum of the overview fields + that we care about. + 2000-08-31 Jeffrey Stedfast <fejj@helixcode.com> * providers/imap/camel-imap-utils.c (imap_translate_sexp): diff --git a/camel/providers/nntp/camel-nntp-newsrc.c b/camel/providers/nntp/camel-nntp-newsrc.c index 81594d3dcd..9510fe5bfa 100644 --- a/camel/providers/nntp/camel-nntp-newsrc.c +++ b/camel/providers/nntp/camel-nntp-newsrc.c @@ -26,6 +26,8 @@ #include <string.h> #include <stdlib.h> #include <glib.h> +#include <fcntl.h> +#include <unistd.h> #include "camel-nntp-newsrc.h" typedef struct { @@ -440,17 +442,33 @@ camel_nntp_newsrc_read_for_server (const char *server) { FILE *fp; char buf[BUFFER_LENGTH]; - CamelNNTPNewsrc *newsrc = g_new0(CamelNNTPNewsrc, 1); + char *filename = g_strdup_printf ("%s/.newsrc-%s", g_get_home_dir(), server); + CamelNNTPNewsrc *newsrc; + + if ((fp = fopen(filename, "r")) == NULL) { + int fd; + + g_warning ("~/.newsrc-%s not present. creating empty file\n", server); + + if ((fd = open (filename, O_CREAT, O_TRUNC, O_WRONLY, 0777)) < 0) { + g_warning ("unable to create ~/.newsrc-%s file\n", server); + g_free (filename); + return NULL; + } + close (fd); - newsrc->filename = g_strdup_printf ("%s/.newsrc-%s", g_get_home_dir(), server); + if ((fp = fopen(filename, "r")) == NULL) { + g_warning ("unable to open ~/.newsrc-%s file on second try.\n", server); + g_free (filename); + return NULL; + } + } + + newsrc = g_new0(CamelNNTPNewsrc, 1); + newsrc->filename = filename; newsrc->groups = g_hash_table_new (g_str_hash, g_str_equal); newsrc->subscribed_groups = g_hash_table_new (g_str_hash, g_str_equal); - if ((fp = fopen(newsrc->filename, "r")) == NULL) { - g_free (newsrc->filename); - g_free (newsrc); - return NULL; - } while (fgets(buf, MAX_LINE_LENGTH, fp) != NULL) { /* we silently ignore (and lose!) lines longer than 20 * 1500 chars. diff --git a/camel/providers/nntp/camel-nntp-store.c b/camel/providers/nntp/camel-nntp-store.c index 5c9475ed14..37cb184f28 100644 --- a/camel/providers/nntp/camel-nntp-store.c +++ b/camel/providers/nntp/camel-nntp-store.c @@ -48,6 +48,8 @@ #define NNTP_PORT 119 +#define DUMP_EXTENSIONS + static CamelServiceClass *service_class = NULL; /* Returns the class for a CamelNNTPStore */ @@ -57,6 +59,143 @@ static CamelServiceClass *service_class = NULL; static gboolean ensure_news_dir_exists (CamelNNTPStore *store); +static void +camel_nntp_store_get_extensions (CamelNNTPStore *store) +{ + store->extensions = 0; + + if (CAMEL_NNTP_OK == camel_nntp_command (store, NULL, "LIST EXTENSIONS")) { + gboolean done = FALSE; + + while (!done) { + char *line; + + line = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER(store->istream)); + + if (*line == '.') { + done = TRUE; + } + else { +#define CHECK_EXT(name,val) if (!strcasecmp (line, (name))) store->extensions |= (val) + + CHECK_EXT ("SEARCH", CAMEL_NNTP_EXT_SEARCH); + CHECK_EXT ("SETGET", CAMEL_NNTP_EXT_SETGET); + CHECK_EXT ("OVER", CAMEL_NNTP_EXT_OVER); + CHECK_EXT ("XPATTEXT", CAMEL_NNTP_EXT_XPATTEXT); + CHECK_EXT ("XACTIVE", CAMEL_NNTP_EXT_XACTIVE); + CHECK_EXT ("LISTMOTD", CAMEL_NNTP_EXT_LISTMOTD); + CHECK_EXT ("LISTSUBSCR", CAMEL_NNTP_EXT_LISTSUBSCR); + CHECK_EXT ("LISTPNAMES", CAMEL_NNTP_EXT_LISTPNAMES); + +#undef CHECK_EXT + } + + g_free (line); + } + } + +#ifdef DUMP_EXTENSIONS + g_print ("NNTP Extensions:"); +#define DUMP_EXT(name,val) if (store->extensions & (val)) g_print (" %s", name); + DUMP_EXT ("SEARCH", CAMEL_NNTP_EXT_SEARCH); + DUMP_EXT ("SETGET", CAMEL_NNTP_EXT_SETGET); + DUMP_EXT ("OVER", CAMEL_NNTP_EXT_OVER); + DUMP_EXT ("XPATTEXT", CAMEL_NNTP_EXT_XPATTEXT); + DUMP_EXT ("XACTIVE", CAMEL_NNTP_EXT_XACTIVE); + DUMP_EXT ("LISTMOTD", CAMEL_NNTP_EXT_LISTMOTD); + DUMP_EXT ("LISTSUBSCR", CAMEL_NNTP_EXT_LISTSUBSCR); + DUMP_EXT ("LISTPNAMES", CAMEL_NNTP_EXT_LISTPNAMES); + g_print ("\n"); +#undef DUMP_EXT +#endif +} + +static void +camel_nntp_store_get_overview_fmt (CamelNNTPStore *store) +{ + int status; + char *result; + char *field; + int i; + + status = camel_nntp_command (store, NULL, + "LIST OVERVIEW.FMT"); + + if (status != CAMEL_NNTP_OK) { + /* 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." + " disabling OVER\n"); + store->extensions &= ~CAMEL_NNTP_EXT_OVER; + return; + } + + result = camel_nntp_command_get_additional_data (store); + + /* count the number of fields the server returns in the + overview. start at 1 because the article number is always + first */ + store->num_overview_fields = 1; + + for (i = 0; i < CAMEL_NNTP_OVER_LAST; i ++) { + store->overview_field [i].index = -1; + } + + while ((field = strsep (&result, "\n"))) { + CamelNNTPOverField *over_field = NULL; + char *colon = NULL;; + + if (field[0] == '\0') + break; + + if (!strncasecmp (field, "From:", 5)) { + over_field = &store->overview_field [ CAMEL_NNTP_OVER_FROM ]; + over_field->index = store->num_overview_fields; + colon = field + 5; + } + else if (!strncasecmp (field, "Subject:", 7)) { + over_field = &store->overview_field [ CAMEL_NNTP_OVER_SUBJECT ]; + over_field->index = store->num_overview_fields; + colon = field + 7; + } + else if (!strncasecmp (field, "Date:", 5)) { + over_field = &store->overview_field [ CAMEL_NNTP_OVER_DATE ]; + over_field->index = store->num_overview_fields; + colon = field + 5; + } + else if (!strncasecmp (field, "Message-ID:", 11)) { + over_field = &store->overview_field [ CAMEL_NNTP_OVER_MESSAGE_ID ]; + over_field->index = store->num_overview_fields; + colon = field + 11; + } + else if (!strncasecmp (field, "References:", 11)) { + over_field = &store->overview_field [ CAMEL_NNTP_OVER_REFERENCES ]; + over_field->index = store->num_overview_fields; + colon = field + 11; + } + else if (!strncasecmp (field, "Bytes:", 6)) { + over_field = &store->overview_field [ CAMEL_NNTP_OVER_BYTES ]; + over_field->index = store->num_overview_fields; + colon = field + 11; + } + + if (colon && !strcmp (colon + 1, "full")) + over_field->full = TRUE; + + store->num_overview_fields ++; + } + + g_free (result); + + for (i = 0; i < CAMEL_NNTP_OVER_LAST; i ++) { + if (store->overview_field [i].index == -1) { + g_warning ("server's OVERVIEW.FMT doesn't support minimum set we require," + " disabling OVER support.\n"); + store->extensions &= ~CAMEL_NNTP_EXT_OVER; + } + } +} + static gboolean nntp_store_connect (CamelService *service, CamelException *ex) { @@ -64,6 +203,7 @@ nntp_store_connect (CamelService *service, CamelException *ex) struct sockaddr_in sin; int fd; char *buf; + int resp_code; CamelNNTPStore *store = CAMEL_NNTP_STORE (service); if (!ensure_news_dir_exists(store)) { @@ -106,14 +246,29 @@ nntp_store_connect (CamelService *service, CamelException *ex) return -1; } + /* check if posting is allowed. */ + resp_code = atoi (buf); + if (resp_code == 200) { + g_print ("posting allowed\n"); + store->posting_allowed = TRUE; + } + else if (resp_code == 201) { + g_print ("no posting allowed\n"); + store->posting_allowed = FALSE; + } + else { + g_warning ("unexpected server greeting code %d, no posting allowed\n", resp_code); + store->posting_allowed = FALSE; + } + g_free (buf); /* get a list of extensions that the server supports */ - if (CAMEL_NNTP_OK == camel_nntp_command (store, NULL, "LIST EXTENSIONS")) { - char *ext_response = camel_nntp_command_get_additional_data(store); + camel_nntp_store_get_extensions (store); - g_free (ext_response); - } + /* 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); return TRUE; } @@ -162,6 +317,14 @@ nntp_store_get_folder (CamelStore *store, const gchar *folder_name, nntp_store->newsrc = camel_nntp_newsrc_read_for_server (CAMEL_SERVICE(store)->url->host); + if (!nntp_store->newsrc) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, + "Unable to open or create .newsrc file for %s: %s", + CAMEL_SERVICE(store)->url->host, + strerror(errno)); + return NULL; + } + /* check if folder has already been created */ /* call the standard routine for that when */ /* it is done ... */ @@ -329,13 +492,12 @@ camel_nntp_command (CamelNNTPStore *store, char **ret, char *fmt, ...) * a NNTP command. * @store: the NNTP store * - * This command gets the additional data returned by - * This command gets the additional data returned by "multi-line" POP - * commands, such as LIST, RETR, TOP, and UIDL. This command _must_ - * be called after a successful (CAMEL_NNTP_OK) call to - * camel_nntp_command for a command that has a multi-line response. - * The returned data is un-byte-stuffed, and has lines termined by - * newlines rather than CR/LF pairs. + * This command gets the additional data returned by This command gets + * the additional data returned by "multi-line" NNTP commands, such as + * LIST. This command must only be called after a successful + * (CAMEL_NNTP_OK) call to camel_nntp_command for a command that has a + * multi-line response. The returned data is un-byte-stuffed, and has + * lines termined by newlines rather than CR/LF pairs. * * Return value: the data, which the caller must free. **/ diff --git a/camel/providers/nntp/camel-nntp-store.h b/camel/providers/nntp/camel-nntp-store.h index 3099f84962..a74ea84f5e 100644 --- a/camel/providers/nntp/camel-nntp-store.h +++ b/camel/providers/nntp/camel-nntp-store.h @@ -40,12 +40,41 @@ extern "C" { #define IS_CAMEL_NNTP_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_NNTP_STORE_TYPE)) +enum { + CAMEL_NNTP_OVER_FROM, + CAMEL_NNTP_OVER_SUBJECT, + CAMEL_NNTP_OVER_DATE, + CAMEL_NNTP_OVER_MESSAGE_ID, + CAMEL_NNTP_OVER_REFERENCES, + CAMEL_NNTP_OVER_BYTES, + + CAMEL_NNTP_OVER_LAST +}; + +typedef struct { + int index; + gboolean full; /* full in the OVER sense - the field name + precedes the ':' in the XOVER list. */ +} CamelNNTPOverField; + typedef struct { CamelStore parent_object; -#define CAMEL_NNTP_EXT_XOVER 0x01 +#define CAMEL_NNTP_EXT_SEARCH (1<<0) +#define CAMEL_NNTP_EXT_SETGET (1<<1) +#define CAMEL_NNTP_EXT_OVER (1<<2) +#define CAMEL_NNTP_EXT_XPATTEXT (1<<3) +#define CAMEL_NNTP_EXT_XACTIVE (1<<4) +#define CAMEL_NNTP_EXT_LISTMOTD (1<<5) +#define CAMEL_NNTP_EXT_LISTSUBSCR (1<<6) +#define CAMEL_NNTP_EXT_LISTPNAMES (1<<7) guint32 extensions; + gboolean posting_allowed; + + int num_overview_fields; + CamelNNTPOverField overview_field[ CAMEL_NNTP_OVER_LAST ]; + CamelNNTPNewsrc *newsrc; CamelStream *istream, *ostream; diff --git a/camel/providers/nntp/camel-nntp-utils.c b/camel/providers/nntp/camel-nntp-utils.c index e0a331f2a7..01b7876134 100644 --- a/camel/providers/nntp/camel-nntp-utils.c +++ b/camel/providers/nntp/camel-nntp-utils.c @@ -33,7 +33,7 @@ #include <string.h> static void -get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, +get_OVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, int first_message, int last_message, CamelException *ex) { int status; @@ -43,7 +43,7 @@ get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, "XOVER %d-%d", first_message, last_message); - + if (status == CAMEL_NNTP_OK) { CamelStream *nntp_istream = nntp_store->istream; gboolean done = FALSE; @@ -55,23 +55,44 @@ get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, if (*line == '.') { done = TRUE; + g_print ("done\n"); } else { CamelMessageInfo *new_info = g_new0(CamelMessageInfo, 1); char **split_line = g_strsplit (line, "\t", 7); - - new_info->subject = g_strdup(split_line[1]); - new_info->from = g_strdup(split_line[2]); + char *subject, *from, *date, *message_id, *bytes; + + subject = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_SUBJECT].index]; + from = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_FROM].index]; + date = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_DATE].index]; + message_id = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_MESSAGE_ID].index]; + bytes = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_BYTES].index]; + + /* if the overview format flagged this + field as "full", skip over the + preceding field name and colon */ + if (nntp_store->overview_field [ CAMEL_NNTP_OVER_SUBJECT ].full) + subject += strlen ("Subject:"); + if (nntp_store->overview_field [ CAMEL_NNTP_OVER_FROM ].full) + from += strlen ("From:"); + if (nntp_store->overview_field [ CAMEL_NNTP_OVER_DATE ].full) + date += strlen ("Date:"); + if (nntp_store->overview_field [ CAMEL_NNTP_OVER_MESSAGE_ID ].full) + message_id += strlen ("Message-ID:"); + if (nntp_store->overview_field [ CAMEL_NNTP_OVER_BYTES ].full) + bytes += strlen ("Bytes:"); + + new_info->subject = g_strdup(subject); + new_info->from = g_strdup(from); new_info->to = g_strdup(nntp_folder->group_name); - new_info->date_sent = header_decode_date(split_line[3], NULL); + new_info->date_sent = header_decode_date(date, NULL); #if 0 /* XXX do we need to fill in both dates? */ - new_info->headers.date_received = g_strdup(split_line[3]); + new_info->headers.date_received = g_strdup(date); #endif - new_info->size = atoi(split_line[5]); - new_info->uid = g_strdup_printf ("%s,%s", split_line[0], split_line[4]); - new_info->message_id = g_strdup(split_line[4]); - g_strfreev (split_line); + new_info->size = atoi(bytes); + new_info->uid = g_strdup_printf ("%s,%s", split_line[0], message_id); + new_info->message_id = g_strdup(message_id); if (camel_nntp_newsrc_article_is_read (nntp_store->newsrc, nntp_folder->group_name, @@ -79,6 +100,7 @@ get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, new_info->flags |= CAMEL_MESSAGE_SEEN; camel_folder_summary_add (nntp_folder->summary, new_info); + g_strfreev (split_line); } g_free (line); } @@ -204,15 +226,13 @@ camel_nntp_get_headers (CamelStore *store, return; } -#if 0 - if (nntp_store->extensions & CAMEL_NNTP_EXT_XOVER) { -#endif - get_XOVER_headers (nntp_store, folder, first_message, last_message, ex); -#if 0 + if (nntp_store->extensions & CAMEL_NNTP_EXT_OVER) { + get_OVER_headers (nntp_store, folder, first_message, last_message, ex); } else { + g_warning ("need to fix get_HEAD_headers\n"); +#if 0 get_HEAD_headers (nntp_store, folder, first_message, last_message, ex); - } #endif + } } - |