diff options
-rw-r--r-- | camel/ChangeLog | 32 | ||||
-rw-r--r-- | camel/providers/nntp/Makefile.am | 18 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-folder.c | 109 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-store.c | 259 | ||||
-rw-r--r-- | camel/providers/nntp/camel-nntp-utils.c | 5 |
5 files changed, 244 insertions, 179 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 8e897990dd..3b00513daa 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,35 @@ +2000-07-12 Chris Toshok <toshok@helixcode.com> + + * providers/nntp/Makefile.am: don't add test-newsrc to the build + since it needs libcamel (which isn't built at the time test-newsrc + needs linking.) + + * providers/nntp/camel-nntp-utils.c (get_HEAD_headers): fill in + MessageInfo->message_id. + (get_XOVER_headers): same. + + * providers/nntp/camel-nntp-folder.c (nntp_folder_init): move + summary loading here. + (nntp_folder_sync): summary/newsrc changes should be stored here. + put a comment to that effect. + (nntp_folder_set_message_flags): don't save the newsrc here. + (nntp_folder_get_uids): use g_ptr_array_index instead of the + cast/addition. + (nntp_folder_get_summary): no need to check if we should generate + the summary here. already done. + (nntp_folder_get_message_info): implement. + + * providers/nntp/camel-nntp-store.c + (camel_nntp_store_get_toplevel_dir): use evolution_dir instead of + computing it ourselves. + (nntp_store_disconnect): call camel_nntp_newsrc_write. + (ensure_news_dir_exists): new function to create the news/<news + server> subdir. + (camel_nntp_store_class_init): hook up connect/disconnect and + finalize. + (nntp_store_connect): if ensure_news_dir_exists fails throw an + exception. + 2000-07-12 Peter Williams <peterw@helixcode.com> * camel-folder.c (camel_folder_set_message_flags): Emit a message_changed diff --git a/camel/providers/nntp/Makefile.am b/camel/providers/nntp/Makefile.am index a205f5bb83..5f96e78615 100644 --- a/camel/providers/nntp/Makefile.am +++ b/camel/providers/nntp/Makefile.am @@ -31,14 +31,14 @@ libcamelnntp_la_LDFLAGS = -version-info 0:0:0 EXTRA_DIST = libcamelnntp.urls -noinst_PROGRAMS = test-newsrc - -LDADD = \ - $(top_builddir)/camel/libcamel.la \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/libibex/libibex.la \ - $(GNOME_LIBDIR) \ - $(GNOMEUI_LIBS) $(INTLLIBS) $(EXTRA_GNOME_LIBS) +#noinst_PROGRAMS = test-newsrc + +#LDADD = \ + #$(top_builddir)/camel/libcamel.la \ + #$(top_builddir)/e-util/libeutil.la \ + #$(top_builddir)/libibex/libibex.la \ + #$(GNOME_LIBDIR) \ + #$(GNOMEUI_LIBS) $(INTLLIBS) $(EXTRA_GNOME_LIBS) # $(BONOBO_LIBS) -test_newsrc_LDADD = libcamelnntp.la $(LDADD) +#test_newsrc_LDADD = libcamelnntp.la $(LDADD) diff --git a/camel/providers/nntp/camel-nntp-folder.c b/camel/providers/nntp/camel-nntp-folder.c index ae5e371fb1..00e709b20b 100644 --- a/camel/providers/nntp/camel-nntp-folder.c +++ b/camel/providers/nntp/camel-nntp-folder.c @@ -57,9 +57,6 @@ static CamelFolderClass *parent_class=NULL; #define CNNTPS_CLASS(so) CAMEL_STORE_CLASS (GTK_OBJECT(so)->klass) -static void _check_get_or_maybe_generate_summary_file (CamelNNTPFolder *nntp_folder, - CamelException *ex); - static void nntp_folder_init (CamelFolder *folder, CamelStore *parent_store, CamelFolder *parent_folder, const gchar *name, @@ -99,8 +96,30 @@ nntp_folder_init (CamelFolder *folder, CamelStore *parent_store, root_dir_path = camel_nntp_store_get_toplevel_dir (CAMEL_NNTP_STORE(folder->parent_store)); - nntp_folder->summary_file_path = g_strdup_printf ("%s/%s-ev-summary", - root_dir_path, nntp_folder->group_name); + + /* load the summary if we have that ability */ + if (folder->has_summary_capability) { + nntp_folder->summary_file_path = g_strdup_printf ("%s/%s-ev-summary", + root_dir_path, + nntp_folder->group_name); + + nntp_folder->summary = camel_folder_summary_new (); + camel_folder_summary_set_filename (nntp_folder->summary, + nntp_folder->summary_file_path); + + if (-1 == camel_folder_summary_load (nntp_folder->summary)) { + /* Bad or nonexistant summary file */ + camel_nntp_get_headers (CAMEL_FOLDER( folder )->parent_store, + nntp_folder, ex); + if (camel_exception_get_id (ex)) + return; + + /* XXX check return value */ + camel_folder_summary_save (nntp_folder->summary); + } + } + + } static void @@ -108,6 +127,26 @@ nntp_folder_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) { camel_folder_summary_save (CAMEL_NNTP_FOLDER(folder)->summary); + + /* XXX + + loop through the messages in the summary and store out the .newsrc, + using something similar to this bit snipped from _set_message_flags: + + + if (set & CAMEL_MESSAGE_SEEN) { + CamelNNTPStore *store; + CamelException *ex; + + ex = camel_exception_new (); + store = CAMEL_NNTP_STORE (camel_folder_get_parent_store (folder, ex)); + camel_exception_free (ex); + + camel_nntp_newsrc_mark_article_read (store->newsrc, + nntp_folder->group_name, + XXX); + } + */ } static const gchar * @@ -164,18 +203,6 @@ nntp_folder_set_message_flags (CamelFolder *folder, const char *uid, info->flags = set; camel_folder_summary_touch (nntp_folder->summary); - if (set & CAMEL_MESSAGE_SEEN) { - CamelNNTPStore *store; - CamelException *ex; - - ex = camel_exception_new (); - store = CAMEL_NNTP_STORE (camel_folder_get_parent_store (folder, ex)); - camel_exception_free (ex); - - camel_nntp_newsrc_mark_article_read (store->newsrc, - nntp_folder->group_name, - 1 /* XXX */); - } } static const gchar* @@ -290,17 +317,17 @@ nntp_folder_get_uids (CamelFolder *folder, CamelException *ex) { CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - GPtrArray *message_info_array, *out; + GPtrArray *infoarray, *out; CamelMessageInfo *message_info; int i; - message_info_array = nntp_folder->summary->messages; + infoarray = nntp_folder->summary->messages; out = g_ptr_array_new (); - g_ptr_array_set_size (out, message_info_array->len); + g_ptr_array_set_size (out, infoarray->len); - for (i=0; i<message_info_array->len; i++) { - message_info = (CamelMessageInfo *)(message_info_array->pdata) + i; + for (i=0; i<infoarray->len; i++) { + message_info = (CamelMessageInfo *) g_ptr_array_index (infoarray, i); out->pdata[i] = g_strdup (message_info->uid); } @@ -323,7 +350,6 @@ nntp_folder_get_summary (CamelFolder *folder, CamelException *ex) { CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - _check_get_or_maybe_generate_summary_file (nntp_folder, ex); return nntp_folder->summary->messages; } @@ -369,7 +395,16 @@ nntp_folder_search_by_expression (CamelFolder *folder, const char *expression, C static const CamelMessageInfo* nntp_folder_get_message_info (CamelFolder *folder, const char *uid) { - g_assert(0); + CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); + CamelMessageInfo *info = NULL; + int i; + + for (i = 0; i < nntp_folder->summary->messages->len; i++) { + info = g_ptr_array_index (nntp_folder->summary->messages, i); + if (!strcmp (info->uid, uid)) + return info; + } + return NULL; } @@ -441,29 +476,3 @@ camel_nntp_folder_get_type (void) return camel_nntp_folder_type; } - - -/* internal method used to : - - test for the existence of a summary file - - test the sync between the summary and the newsgroup - - load the summary or create it if necessary -*/ -static void -_check_get_or_maybe_generate_summary_file (CamelNNTPFolder *nntp_folder, - CamelException *ex) -{ - CamelFolder *folder = CAMEL_FOLDER (nntp_folder); - - nntp_folder->summary = camel_folder_summary_new (); - camel_folder_summary_set_filename (nntp_folder->summary, nntp_folder->summary_file_path); - - if (-1 == camel_folder_summary_load (nntp_folder->summary)) { - /* Bad or nonexistant summary file */ - camel_nntp_get_headers (CAMEL_FOLDER( folder )->parent_store, nntp_folder, ex); - if (camel_exception_get_id (ex)) - return; - - /* XXX check return value */ - camel_folder_summary_save (nntp_folder->summary); - } -} diff --git a/camel/providers/nntp/camel-nntp-store.c b/camel/providers/nntp/camel-nntp-store.c index 96d11b4915..a7b8f7df01 100644 --- a/camel/providers/nntp/camel-nntp-store.c +++ b/camel/providers/nntp/camel-nntp-store.c @@ -55,8 +55,98 @@ static CamelServiceClass *service_class = NULL; #define CF_CLASS(so) CAMEL_FOLDER_CLASS (GTK_OBJECT(so)->klass) #define CNNTPF_CLASS(so) CAMEL_NNTP_FOLDER_CLASS (GTK_OBJECT(so)->klass) -static gboolean nntp_connect (CamelService *service, CamelException *ex); -static gboolean nntp_disconnect (CamelService *service, CamelException *ex); +static gboolean ensure_news_dir_exists (CamelNNTPStore *store); + +static gboolean +nntp_store_connect (CamelService *service, CamelException *ex) +{ + struct hostent *h; + struct sockaddr_in sin; + int fd; + char *buf; + CamelNNTPStore *store = CAMEL_NNTP_STORE (service); + + if (!ensure_news_dir_exists(store)) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + "Could not open directory for news server: %s", + strerror (errno)); + return FALSE; + } + + if (!service_class->connect (service, ex)) + return FALSE; + + h = camel_service_gethost (service, ex); + if (!h) + return FALSE; + + sin.sin_family = h->h_addrtype; + sin.sin_port = htons (service->url->port ? service->url->port : NNTP_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, + "Could not connect to %s (port %s): %s", + service->url->host, service->url->port, + 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); + + /* Read the greeting */ + buf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (store->istream)); + if (!buf) { + return -1; + } + + 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); + + g_free (ext_response); + } + + return TRUE; +} + +static gboolean +nntp_store_disconnect (CamelService *service, CamelException *ex) +{ + CamelNNTPStore *store = CAMEL_NNTP_STORE (service); + + if (!service->connected) + return TRUE; + + camel_nntp_command (store, NULL, "QUIT"); + + if (store->newsrc) + camel_nntp_newsrc_write (store->newsrc); + + if (!service_class->disconnect (service, ex)) + return FALSE; + + gtk_object_unref (GTK_OBJECT (store->ostream)); + gtk_object_unref (GTK_OBJECT (store->istream)); + store->ostream = NULL; + store->istream = NULL; + return TRUE; +} + +static char * +nntp_store_get_name (CamelService *service, gboolean brief) +{ + /* Same info for long and brief... */ + return g_strdup_printf ("USENET news via %s", service->url->host); +} static CamelFolder * nntp_store_get_folder (CamelStore *store, const gchar *folder_name, @@ -68,7 +158,8 @@ nntp_store_get_folder (CamelStore *store, const gchar *folder_name, /* if we haven't already read our .newsrc, read it now */ if (!nntp_store->newsrc) - nntp_store->newsrc = camel_nntp_newsrc_read_for_server (CAMEL_SERVICE(store)->url->host); + nntp_store->newsrc = + camel_nntp_newsrc_read_for_server (CAMEL_SERVICE(store)->url->host); /* check if folder has already been created */ /* call the standard routine for that when */ @@ -83,11 +174,10 @@ nntp_store_get_folder (CamelStore *store, const gchar *folder_name, */ CF_CLASS (new_folder)->init (new_folder, store, NULL, folder_name, ".", FALSE, ex); - + return new_folder; } - static char * nntp_store_get_folder_name (CamelStore *store, const char *folder_name, CamelException *ex) @@ -95,23 +185,31 @@ nntp_store_get_folder_name (CamelStore *store, const char *folder_name, return g_strdup (folder_name); } -static char * -nntp_store_get_name (CamelService *service, gboolean brief) +static void +finalize (GtkObject *object) { - /* Same info for long and brief... */ - return g_strdup_printf ("USENET news via %s", service->url->host); -} + CamelException ex; + camel_exception_init (&ex); + nntp_store_disconnect (CAMEL_SERVICE (object), &ex); + camel_exception_clear (&ex); +} static void camel_nntp_store_class_init (CamelNNTPStoreClass *camel_nntp_store_class) { + GtkObjectClass *object_class = + GTK_OBJECT_CLASS (camel_nntp_store_class); CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_nntp_store_class); CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_nntp_store_class); service_class = gtk_type_class (camel_service_get_type ()); /* virtual method overload */ + object_class->finalize = finalize; + + camel_service_class->connect = nntp_store_connect; + camel_service_class->disconnect = nntp_store_disconnect; camel_service_class->get_name = nntp_store_get_name; camel_store_class->get_folder = nntp_store_get_folder; @@ -152,107 +250,6 @@ camel_nntp_store_get_type (void) return camel_nntp_store_type; } -/** - * camel_nntp_store_open: Connect to the server if we are currently - * disconnected. - * @store: the store - * @ex: a CamelException - * - **/ -void -camel_nntp_store_open (CamelNNTPStore *store, CamelException *ex) -{ - CamelService *service = CAMEL_SERVICE (store); - if (!camel_service_is_connected (service)) - nntp_connect (service, ex); -} - -/** - * camel_nntp_store_close: Close the connection to the server - * @store: the store - * @ex: a CamelException - * - **/ -void -camel_nntp_store_close (CamelNNTPStore *store, gboolean expunge, - CamelException *ex) -{ - camel_nntp_command (store, NULL, "QUIT"); - - nntp_disconnect (CAMEL_SERVICE (store), ex); -} - -static gboolean -nntp_connect (CamelService *service, CamelException *ex) -{ - struct hostent *h; - struct sockaddr_in sin; - int fd; - char *buf; - CamelNNTPStore *store = CAMEL_NNTP_STORE (service); - - if (!service_class->connect (service, ex)) - return FALSE; - - h = camel_service_gethost (service, ex); - if (!h) - return FALSE; - - sin.sin_family = h->h_addrtype; - sin.sin_port = htons (service->url->port ? service->url->port : NNTP_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, - "Could not connect to %s (port %s): %s", - service->url->host, service->url->port, - 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); - - /* Read the greeting */ - buf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (store->istream)); - if (!buf) { - return -1; - } - - 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); - - g_free (ext_response); - } - - return TRUE; -} - -static gboolean -nntp_disconnect (CamelService *service, CamelException *ex) -{ - CamelNNTPStore *store = CAMEL_NNTP_STORE (service); - - if (!service->connected) - return TRUE; - - if (!service_class->disconnect (service, ex)) - return FALSE; - - gtk_object_unref (GTK_OBJECT (store->ostream)); - gtk_object_unref (GTK_OBJECT (store->istream)); - store->ostream = NULL; - store->istream = NULL; - return TRUE; -} /** * camel_nntp_command: Send a command to a NNTP server. @@ -291,7 +288,7 @@ camel_nntp_command (CamelNNTPStore *store, char **ret, char *fmt, ...) /* make sure we're connected */ if (store->ostream == NULL) - nntp_connect (CAMEL_SERVICE (store), ex); + nntp_store_connect (CAMEL_SERVICE (store), ex); if (camel_exception_get_id (ex)) { camel_exception_free (ex); @@ -479,18 +476,42 @@ gchar * camel_nntp_store_get_toplevel_dir (CamelNNTPStore *store) { CamelURL *url = CAMEL_SERVICE (store)->url; - char *news_dir; char *top_dir; + extern char *evolution_dir; g_assert(url != NULL); - news_dir = gnome_util_prepend_user_home ("evolution/news"); - - top_dir = g_strdup_printf( "%s/%s", - news_dir, + top_dir = g_strdup_printf( "%s/news/%s", + evolution_dir, url->host ); - g_free (news_dir); - return top_dir; } + +static gboolean +ensure_news_dir_exists (CamelNNTPStore *store) +{ + gchar *dir = camel_nntp_store_get_toplevel_dir (store); + struct stat sb; + int rv; + + rv = stat (dir, &sb); + if (-1 == rv && errno != ENOENT) { + g_free (dir); + return FALSE; + } + + if (S_ISDIR (sb.st_mode)) { + g_free (dir); + return TRUE; + } + else { + rv = mkdir (dir, 0777); + g_free (dir); + + if (-1 == rv) + return FALSE; + else + return TRUE; + } +} diff --git a/camel/providers/nntp/camel-nntp-utils.c b/camel/providers/nntp/camel-nntp-utils.c index d4c2cda771..864271cd2c 100644 --- a/camel/providers/nntp/camel-nntp-utils.c +++ b/camel/providers/nntp/camel-nntp-utils.c @@ -70,6 +70,7 @@ get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, #endif new_info->size = atoi(split_line[5]); new_info->uid = g_strdup(split_line[4]); + new_info->message_id = g_strdup(split_line[4]); g_strfreev (split_line); camel_folder_summary_add (nntp_folder->summary, new_info); @@ -151,8 +152,10 @@ get_HEAD_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, new_info->to = g_strdup(header->value); else if (!g_strcasecmp(header->name, "Subject")) new_info->subject = g_strdup(header->value); - else if (!g_strcasecmp(header->name, "Message-ID")) + else if (!g_strcasecmp(header->name, "Message-ID")) { new_info->uid = g_strdup(header->value); + new_info->message_id = g_strdup(header->value); + } else if (!g_strcasecmp(header->name, "Date")) { new_info->date_sent = header_decode_date (header->value); #if 0 |