From 61ec5b754bb8acf189d0ac083bf8e0cb0c98ebc0 Mon Sep 17 00:00:00 2001 From: Chris Toshok Date: Fri, 23 Jun 2000 02:03:35 +0000 Subject: ignore test-newsrc 2000-06-22 Chris Toshok * providers/nntp/.cvsignore: ignore test-newsrc * providers/nntp/camel-nntp-store.c, providers/nntp/camel-nntp-store.h, providers/nntp/camel-nntp-folder.c, providers/nntp/camel-nntp-folder.h, providers/nntp/camel-nntp-utils.c: Bring the nntp provider up to a state where it builds and is usable with the current camel. there are still warts (semi-broken .newsrc file handling, and a lack of a subscribe ui -- in fact no way to add a new server, really), but it'll display news messages. * providers/nntp/Makefile.am (libcamelnntp_la_SOURCES): add camel-nntp-newsrc.c (libcamelnntpinclude_HEADERS): add camel-nntp-newsrc.h also, add test-newsrc stuff. * providers/nntp/test-newsrc.c: new file that tests the newsrc stuff by parsing and regurgitating a .newsrc file for a particular server. * providers/nntp/camel-nntp-newsrc.c, providers/nntp/camel-nntp-newsrc.h: new files, initial support for .newsrc files. svn path=/trunk/; revision=3702 --- camel/providers/nntp/.cvsignore | 1 + camel/providers/nntp/Makefile.am | 15 +- camel/providers/nntp/camel-nntp-folder.c | 666 ++++++++++++------------------- camel/providers/nntp/camel-nntp-folder.h | 1 + camel/providers/nntp/camel-nntp-newsrc.c | 461 +++++++++++++++++++++ camel/providers/nntp/camel-nntp-newsrc.h | 27 ++ camel/providers/nntp/camel-nntp-store.c | 91 ++--- camel/providers/nntp/camel-nntp-store.h | 3 + camel/providers/nntp/camel-nntp-utils.c | 37 +- camel/providers/nntp/test-newsrc.c | 10 + 10 files changed, 840 insertions(+), 472 deletions(-) create mode 100644 camel/providers/nntp/camel-nntp-newsrc.c create mode 100644 camel/providers/nntp/camel-nntp-newsrc.h create mode 100644 camel/providers/nntp/test-newsrc.c (limited to 'camel') diff --git a/camel/providers/nntp/.cvsignore b/camel/providers/nntp/.cvsignore index fd6b811c68..1f5b9d35fb 100644 --- a/camel/providers/nntp/.cvsignore +++ b/camel/providers/nntp/.cvsignore @@ -5,3 +5,4 @@ Makefile.in .deps *.lo *.la +test-newsrc diff --git a/camel/providers/nntp/Makefile.am b/camel/providers/nntp/Makefile.am index 48f85e836d..a205f5bb83 100644 --- a/camel/providers/nntp/Makefile.am +++ b/camel/providers/nntp/Makefile.am @@ -17,15 +17,28 @@ INCLUDES = -I.. -I$(srcdir)/.. -I$(includedir) \ libcamelnntp_la_SOURCES = \ camel-nntp-folder.c \ + camel-nntp-newsrc.c \ camel-nntp-provider.c \ camel-nntp-store.c \ camel-nntp-utils.c libcamelnntpinclude_HEADERS = \ camel-nntp-folder.h \ + camel-nntp-newsrc.h \ camel-nntp-store.h - 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) +# $(BONOBO_LIBS) + +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 8bc623add7..a3cfc49d26 100644 --- a/camel/providers/nntp/camel-nntp-folder.c +++ b/camel/providers/nntp/camel-nntp-folder.c @@ -57,163 +57,39 @@ static CamelFolderClass *parent_class=NULL; #define CNNTPS_CLASS(so) CAMEL_STORE_CLASS (GTK_OBJECT(so)->klass) -static void _init (CamelFolder *folder, CamelStore *parent_store, - CamelFolder *parent_folder, const gchar *name, - gchar separator, CamelException *ex); - -static void _open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex); -static void _close (CamelFolder *folder, gboolean expunge, CamelException *ex); -static gboolean _exists (CamelFolder *folder, CamelException *ex); -static gboolean _create(CamelFolder *folder, CamelException *ex); -static gboolean _delete (CamelFolder *folder, gboolean recurse, CamelException *ex); -static gboolean _delete_messages (CamelFolder *folder, CamelException *ex); -static GList *_list_subfolders (CamelFolder *folder, CamelException *ex); -static CamelMimeMessage *_get_message_by_number (CamelFolder *folder, gint number, CamelException *ex); -static gint _get_message_count (CamelFolder *folder, CamelException *ex); -static void _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex); -static GPtrArray *_get_uid_array (CamelFolder *folder, CamelException *ex); -static CamelMimeMessage *_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex); -#if 0 -static void _expunge (CamelFolder *folder, CamelException *ex); -static void _copy_message_to (CamelFolder *folder, CamelMimeMessage *message, CamelFolder *dest_folder, CamelException *ex); -#endif -static const gchar *_get_message_uid (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex); - -static void _finalize (GtkObject *object); - -static void -camel_nntp_folder_class_init (CamelNNTPFolderClass *camel_nntp_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_nntp_folder_class); - GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_folder_class); - - parent_class = gtk_type_class (camel_folder_get_type ()); - - /* virtual method definition */ - - /* virtual method overload */ - camel_folder_class->init = _init; - camel_folder_class->open = _open; - camel_folder_class->close = _close; - camel_folder_class->exists = _exists; - camel_folder_class->create = _create; - camel_folder_class->delete = _delete; - camel_folder_class->delete_messages = _delete_messages; - camel_folder_class->list_subfolders = _list_subfolders; - camel_folder_class->get_message_count = _get_message_count; - camel_folder_class->get_uid_array = _get_uid_array; - camel_folder_class->get_message_by_uid = _get_message_by_uid; -#if 0 - camel_folder_class->append_message = _append_message; - camel_folder_class->expunge = _expunge; - camel_folder_class->copy_message_to = _copy_message_to; - camel_folder_class->get_message_uid = _get_message_uid; -#endif - - gtk_object_class->finalize = _finalize; - -} - -static void -_finalize (GtkObject *object) -{ - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (object); - - g_free (nntp_folder->summary_file_path); - - GTK_OBJECT_CLASS (parent_class)->finalize (object); -} - -GtkType -camel_nntp_folder_get_type (void) -{ - static GtkType camel_nntp_folder_type = 0; - - if (!camel_nntp_folder_type) { - GtkTypeInfo camel_nntp_folder_info = - { - "CamelNNTPFolder", - sizeof (CamelNNTPFolder), - sizeof (CamelNNTPFolderClass), - (GtkClassInitFunc) camel_nntp_folder_class_init, - (GtkObjectInitFunc) NULL, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - camel_nntp_folder_type = gtk_type_unique (CAMEL_FOLDER_TYPE, &camel_nntp_folder_info); - } - - return camel_nntp_folder_type; -} +static void _check_get_or_maybe_generate_summary_file (CamelNNTPFolder *nntp_folder, + CamelException *ex); static void -_init (CamelFolder *folder, CamelStore *parent_store, - CamelFolder *parent_folder, const gchar *name, gchar separator, - CamelException *ex) +nntp_folder_init (CamelFolder *folder, CamelStore *parent_store, + CamelFolder *parent_folder, const gchar *name, + gchar *separator, gboolean path_begins_with_sep, + CamelException *ex) { + const gchar *root_dir_path; + CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); + /* call parent method */ parent_class->init (folder, parent_store, parent_folder, - name, separator, ex); + name, separator, path_begins_with_sep, + ex); if (camel_exception_get_id (ex)) return; - /* we assume that the parent init - method checks for the existance of @folder */ - - if (!strcmp(name, "/")) - { - folder->has_summary_capability = FALSE; - folder->can_hold_messages = FALSE; - folder->can_hold_folders = TRUE; - } - else - { - folder->has_summary_capability = TRUE; - folder->can_hold_messages = TRUE; - folder->can_hold_folders = TRUE; - } - - folder->has_uid_capability = TRUE; - folder->has_search_capability = FALSE; -} - -/* 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); + /* set flags */ - 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); + if (!strcmp (name, "/")) { + /* the root folder is the only folder that has "subfolders" */ + folder->can_hold_folders = TRUE; + folder->can_hold_messages = FALSE; + } + else { + folder->can_hold_folders = FALSE; + folder->can_hold_messages = TRUE; + folder->has_summary_capability = TRUE; } -} - - -static void -_open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex) -{ - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - const gchar *root_dir_path; - /* call parent class */ - parent_class->open (folder, mode, ex); - if (camel_exception_get_id(ex)) - return; + /* XX */ + nntp_folder->group_name = g_strdup (strrchr (name, '/') + 1); #if 0 /* get (or create) uid list */ @@ -223,135 +99,43 @@ _open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex) 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, folder->name); - - _check_get_or_maybe_generate_summary_file (nntp_folder, ex); + nntp_folder->summary_file_path = g_strdup_printf ("%s/%s-ev-summary", + root_dir_path, nntp_folder->group_name); } - static void -_close (CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - CamelFolderSummary *summary = nntp_folder->summary; - - /* call parent implementation */ - parent_class->close (folder, expunge, ex); - - /* XXX only if dirty? */ - camel_folder_summary_save (summary); -} - -static gboolean -_exists (CamelFolder *folder, CamelException *ex) -{ -#if 0 - CamelNNTPFolder *nntp_folder; - struct stat stat_buf; - gint stat_error; - gboolean exists; - - g_assert(folder != NULL); - - nntp_folder = CAMEL_NNTP_FOLDER (folder); - - /* check if the nntp summary path is determined */ - if (!nntp_folder->summary_file_path) { - camel_exception_set (ex, - CAMEL_EXCEPTION_FOLDER_INVALID, - "undetermined folder summary path. Maybe use set_name ?"); - return FALSE; - } - - /* check if the nntp file exists */ - stat_error = stat (nntp_folder->summary_file_path, &stat_buf); - if (stat_error == -1) - return FALSE; - - exists = S_ISREG (stat_buf.st_mode); - /* we should check the rights here */ - - return exists; -#endif - return TRUE; -} - -static gboolean -_create (CamelFolder *folder, CamelException *ex) +nntp_folder_sync (CamelFolder *folder, gboolean expunge, + CamelException *ex) { -#if 0 - CamelNNTPSummary *summary; - g_assert(folder != NULL); - - /* call default implementation */ - parent_class->create (folder, ex); - - /* create the summary object */ - summary = CAMEL_NNTP_SUMMARY (gtk_object_new (camel_nntp_summary_get_type (), NULL)); - summary->nb_message = 0; - summary->next_uid = 1; - summary->nntp_file_size = 0; - summary->message_info = g_array_new (FALSE, FALSE, sizeof (CamelNNTPSummaryInformation)); -#endif - - return TRUE; + camel_folder_summary_save (CAMEL_NNTP_FOLDER(folder)->summary); } -static gboolean -_delete (CamelFolder *folder, gboolean recurse, CamelException *ex) +static const gchar * +nntp_folder_get_name (CamelFolder *folder) { -#if 0 - gboolean folder_already_exists; - - g_assert(folder != NULL); - - /* check if the folder object exists */ - - /* in the case where the folder does not exist, - return immediatly */ - folder_already_exists = camel_folder_exists (folder, ex); - if (camel_exception_get_id (ex)) - return FALSE; - - if (!folder_already_exists) - return TRUE; - - - /* call default implementation. - It should delete the messages in the folder - and recurse the operation to subfolders */ - parent_class->delete (folder, recurse, ex); -#endif - return TRUE; + g_assert(0); + return NULL; } -gboolean -_delete_messages (CamelFolder *folder, CamelException *ex) +static const gchar * +nntp_folder_get_full_name (CamelFolder *folder) { - - gboolean folder_already_exists; - - g_assert(folder!=NULL); - - /* in the case where the folder does not exist, - return immediatly */ - folder_already_exists = camel_folder_exists (folder, ex); - if (camel_exception_get_id (ex)) return FALSE; - - if (!folder_already_exists) return TRUE; - - return TRUE; + g_assert(0); + return NULL; } -static GList * -_list_subfolders (CamelFolder *folder, CamelException *ex) +static CamelFolder* +nntp_folder_get_subfolder (CamelFolder *folder, + const gchar *folder_name, + gboolean create, + CamelException *ex) { - /* newsgroups don't have subfolders */ + g_assert (0); return NULL; } static gint -_get_message_count (CamelFolder *folder, CamelException *ex) +nntp_folder_get_message_count (CamelFolder *folder, CamelException *ex) { CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER(folder); @@ -361,155 +145,50 @@ _get_message_count (CamelFolder *folder, CamelException *ex) return camel_folder_summary_count(nntp_folder->summary); } -#if 0 -static void -_append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex) +static guint32 +nntp_folder_get_message_flags (CamelFolder *folder, const char *uid, CamelException *ex) { CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); -#if 0 - CamelNNTPSummary *summary = CAMEL_NNTP_SUMMARY (folder->summary); -#endif - CamelStream *output_stream; - guint32 tmp_file_size; - guint32 next_uid; - gint tmp_file_fd; - GArray *message_info_array; -#if 0 - GArray *nntp_summary_info; -#endif - gchar *tmp_message_filename; - gint fd1, fd2; - int i; - - /* write the message itself */ - output_stream = camel_stream_fs_new_with_name (tmp_message_filename, - CAMEL_STREAM_FS_WRITE); - if (output_stream != NULL) { - camel_stream_write_string (output_stream, "From - \n"); - camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), output_stream); - } - camel_stream_flush (output_stream); - gtk_object_unref (GTK_OBJECT (output_stream)); - - /* at this point we have saved the message to a - temporary file, now, we have to add the x-evolution - field and also update the main summary */ - - /* - First : parse the nntp file, but only from the - position where the message has been added, - wich happens to be the last postion in the - nntp file before we added the message. - This position is still stored in the summary - for the moment - */ - next_uid = summary->next_uid; - tmp_file_fd = open (tmp_message_filename, O_RDONLY); - message_info_array = - camel_nntp_parse_file (tmp_file_fd, "From - ", 0, - &tmp_file_size, &next_uid, TRUE, - NULL, 0, ex); - - close (tmp_file_fd); - - /* get the value of the last available UID - as saved in the summary file, again */ - next_uid = summary->next_uid; - - /* make sure all our of message info's have 0 uid - ignore any - set elsewhere */ - for (i=0;ilen;i++) { - g_array_index(message_info_array, CamelNNTPParserMessageInfo, i).uid = 0; - } - - /* - OK, this is not very efficient, we should not use the same - method as for parsing an entire mail file, - but I have no time to write a simpler parser - */ -#if 0 - next_uid = camel_nntp_write_xev (nntp_folder, tmp_message_filename, - message_info_array, &tmp_file_size, next_uid, ex); - -#endif - if (camel_exception_get_id (ex)) { - /* ** FIXME : free the preparsed information */ - return; - } + CamelMessageInfo *info = camel_folder_summary_uid (nntp_folder->summary, uid); -#if 0 - nntp_summary_info = - parsed_information_to_nntp_summary (message_info_array); -#endif - - /* store the number of messages as well as the summary array */ - summary->nb_message += 1; - summary->next_uid = next_uid; + return info->flags; +} - ((CamelNNTPSummaryInformation *)(nntp_summary_info->data))->position += - summary->nntp_file_size; - summary->nntp_file_size += tmp_file_size; +static void +nntp_folder_set_message_flags (CamelFolder *folder, const char *uid, + guint32 flags, guint32 set, CamelException *ex) +{ + CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); + CamelMessageInfo *info = camel_folder_summary_uid (nntp_folder->summary, uid); - camel_nntp_summary_append_entries (summary, nntp_summary_info); - g_array_free (nntp_summary_info, TRUE); - + info->flags = set; - /* append the temporary file message to the nntp file */ - fd1 = open (tmp_message_filename, O_RDONLY); - fd2 = open (nntp_folder->folder_file_path, - O_WRONLY | O_CREAT | O_APPEND, - 0600); + 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); - if (fd2 == -1) { - camel_exception_setv (ex, - CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, - "could not open the nntp folder file for appending the message\n" - "\t%s\n" - "Full error is : %s\n", - nntp_folder->folder_file_path, - strerror (errno)); - return; + camel_nntp_newsrc_mark_article_read (store->newsrc, + nntp_folder->group_name, + 1 /* XXX */); } - - camel_nntp_copy_file_chunk (fd1, - fd2, - tmp_file_size, - ex); - close (fd1); - close (fd2); - - /* remove the temporary file */ - unlink (tmp_message_filename); - - g_free (tmp_message_filename); } -#endif - - -static GPtrArray * -_get_uid_array (CamelFolder *folder, CamelException *ex) +static const gchar* +nntp_folder_get_message_uid (CamelFolder *folder, + CamelMimeMessage *message, + CamelException *ex) { - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - GPtrArray *message_info_array, *out; - CamelMessageInfo *message_info; - int i; - - message_info_array = nntp_folder->summary->messages; - - out = g_ptr_array_new (); - g_ptr_array_set_size (out, message_info_array->len); - - for (i=0; ilen; i++) { - message_info = (CamelMessageInfo *)(message_info_array->pdata) + i; - out->pdata[i] = g_strdup (message_info->uid); - } - - return out; + g_assert (0); + return NULL; } static CamelMimeMessage * -_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex) +nntp_folder_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex) { CamelStream *nntp_istream; CamelStream *message_stream; @@ -550,7 +229,7 @@ _get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex) buf[0] = 0; while (!done) { - char *line = camel_stream_buffer_read_line ( CAMEL_STREAM_BUFFER ( nntp_istream ), ex); + char *line = camel_stream_buffer_read_line ( CAMEL_STREAM_BUFFER ( nntp_istream )); int line_length; /* XXX check exception */ @@ -589,9 +268,7 @@ _get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex) gtk_object_unref ((GtkObject *)message_stream); /* init other fields? */ - message->folder = folder; gtk_object_ref((GtkObject *)folder); - message->message_uid = g_strdup(uid); #if 0 gtk_signal_connect((GtkObject *)message, "message_changed", message_changed, folder); @@ -600,18 +277,193 @@ _get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex) return message; } -/* get message info for a range of messages */ +static void +nntp_folder_delete_message_by_uid (CamelFolder *folder, + const gchar *uid, + CamelException *ex) +{ + g_assert (0); +} + +static GPtrArray * +nntp_folder_get_uids (CamelFolder *folder, + CamelException *ex) +{ + CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); + GPtrArray *message_info_array, *out; + CamelMessageInfo *message_info; + int i; + + message_info_array = nntp_folder->summary->messages; + + out = g_ptr_array_new (); + g_ptr_array_set_size (out, message_info_array->len); + + for (i=0; ilen; i++) { + message_info = (CamelMessageInfo *)(message_info_array->pdata) + i; + out->pdata[i] = g_strdup (message_info->uid); + } + + return out; +} + +static void +nntp_folder_free_uids (CamelFolder *folder, + GPtrArray *array) +{ + int i; + for (i = 0; i < array->len; i ++) { + g_free (g_ptr_array_index (array, i)); + } + g_ptr_array_free (array, TRUE /* XXX? */); +} + +static GPtrArray * +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; +} + +static void +nntp_folder_free_summary (CamelFolder *folder, + GPtrArray *summary) +{ + g_assert (0); +} + static GPtrArray * -summary_get_message_info (CamelFolder *folder, int first, int count) +nntp_folder_get_subfolder_names (CamelFolder *folder, CamelException *ex) +{ + if (!strcmp (folder->name, "/")) { + CamelStore *store = camel_folder_get_parent_store (folder, ex); + GPtrArray *array = camel_nntp_newsrc_get_subscribed_group_names (CAMEL_NNTP_STORE (store)->newsrc); + return array; + } + else { + return NULL; + } +} + +static void +nntp_folder_free_subfolder_names (CamelFolder *folder, GPtrArray *subfolders) +{ + if (subfolders) { + CamelException *ex = camel_exception_new (); + CamelStore *store = camel_folder_get_parent_store (folder, ex); + camel_nntp_newsrc_free_group_names (CAMEL_NNTP_STORE (store)->newsrc, subfolders); + camel_exception_free (ex); + } +} + +static GList* +nntp_folder_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex) { - GPtrArray *array = g_ptr_array_new(); - int i, maxcount; - CamelNNTPFolder *nntp_folder = (CamelNNTPFolder *)folder; + g_assert (0); + return NULL; +} + +static const CamelMessageInfo* +nntp_folder_summary_get_by_uid (CamelFolder *folder, const char *uid) +{ + g_assert(0); + return NULL; +} + +static void +nntp_folder_finalize (GtkObject *object) +{ + CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (object); + + g_free (nntp_folder->summary_file_path); + + GTK_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +camel_nntp_folder_class_init (CamelNNTPFolderClass *camel_nntp_folder_class) +{ + CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_nntp_folder_class); + GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_folder_class); + + parent_class = gtk_type_class (camel_folder_get_type ()); + + /* virtual method definition */ + + /* virtual method overload */ + camel_folder_class->init = nntp_folder_init; + camel_folder_class->sync = nntp_folder_sync; + camel_folder_class->get_name = nntp_folder_get_name; + camel_folder_class->get_full_name = nntp_folder_get_full_name; + camel_folder_class->get_subfolder = nntp_folder_get_subfolder; + camel_folder_class->get_message_count = nntp_folder_get_message_count; + camel_folder_class->set_message_flags = nntp_folder_set_message_flags; + camel_folder_class->get_message_flags = nntp_folder_get_message_flags; + camel_folder_class->get_message_uid = nntp_folder_get_message_uid; + camel_folder_class->get_message_by_uid = nntp_folder_get_message_by_uid; + camel_folder_class->delete_message_by_uid = nntp_folder_delete_message_by_uid; + camel_folder_class->get_uids = nntp_folder_get_uids; + camel_folder_class->free_uids = nntp_folder_free_uids; + camel_folder_class->get_summary = nntp_folder_get_summary; + camel_folder_class->free_summary = nntp_folder_free_summary; + camel_folder_class->get_subfolder_names = nntp_folder_get_subfolder_names; + camel_folder_class->free_subfolder_names = nntp_folder_free_subfolder_names; + camel_folder_class->search_by_expression = nntp_folder_search_by_expression; + camel_folder_class->summary_get_by_uid = nntp_folder_summary_get_by_uid; + + gtk_object_class->finalize = nntp_folder_finalize; + +} + +GtkType +camel_nntp_folder_get_type (void) +{ + static GtkType camel_nntp_folder_type = 0; + + if (!camel_nntp_folder_type) { + GtkTypeInfo camel_nntp_folder_info = + { + "CamelNNTPFolder", + sizeof (CamelNNTPFolder), + sizeof (CamelNNTPFolderClass), + (GtkClassInitFunc) camel_nntp_folder_class_init, + (GtkObjectInitFunc) NULL, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + camel_nntp_folder_type = gtk_type_unique (CAMEL_FOLDER_TYPE, &camel_nntp_folder_info); + } + + 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); - maxcount = camel_folder_summary_count(nntp_folder->summary); - maxcount = MIN(first + count, maxcount); - for (i=first;isummary->messages, i)); + nntp_folder->summary = camel_folder_summary_new (); + camel_folder_summary_set_filename (nntp_folder->summary, nntp_folder->summary_file_path); - return array; + 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-folder.h b/camel/providers/nntp/camel-nntp-folder.h index 7a445d697f..f6c04bb005 100644 --- a/camel/providers/nntp/camel-nntp-folder.h +++ b/camel/providers/nntp/camel-nntp-folder.h @@ -47,6 +47,7 @@ extern "C" { typedef struct { CamelFolder parent_object; + gchar *group_name; gchar *summary_file_path; /* contains the messages summary */ CamelFolderSummary *summary; } CamelNNTPFolder; diff --git a/camel/providers/nntp/camel-nntp-newsrc.c b/camel/providers/nntp/camel-nntp-newsrc.c new file mode 100644 index 0000000000..fc0f4c2a1a --- /dev/null +++ b/camel/providers/nntp/camel-nntp-newsrc.c @@ -0,0 +1,461 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camel-nntp-newsrc.c - .newsrc parsing/regurgitating code */ +/* + * + * Copyright (C) 2000 Helix Code, Inc. + * + * 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 + +#include +#include +#include +#include +#include "camel-nntp-newsrc.h" + +typedef struct { + guint low; + guint high; +} ArticleRange; + +typedef struct { + char *name; + GArray *ranges; + gboolean subscribed; +} NewsrcGroup; + +struct CamelNNTPNewsrc { + gchar *filename; + GHashTable *groups; + GHashTable *subscribed_groups; + gboolean dirty; +} ; + +static NewsrcGroup * +camel_nntp_newsrc_group_add (CamelNNTPNewsrc *newsrc, char *group_name, gboolean subscribed) +{ + NewsrcGroup *new_group = g_malloc(sizeof(NewsrcGroup)); + + new_group->name = g_strdup(group_name); + new_group->subscribed = subscribed; + new_group->ranges = g_array_new (FALSE, FALSE, sizeof (ArticleRange)); + + g_hash_table_insert (newsrc->groups, new_group->name, new_group); + if (subscribed) + g_hash_table_insert (newsrc->subscribed_groups, new_group->name, new_group); + + newsrc->dirty = TRUE; + + return new_group; +} + +static long +camel_nntp_newsrc_group_get_highest_article_read(CamelNNTPNewsrc *newsrc, NewsrcGroup *group) +{ + if (group->ranges->len == 0) + return 0; + + return g_array_index(group->ranges, ArticleRange, group->ranges->len - 1).high; +} + +static void +camel_nntp_newsrc_group_mark_range_read(CamelNNTPNewsrc *newsrc, NewsrcGroup *group, long low, long high) +{ + int i; + + if (group->ranges->len == 1 + && g_array_index (group->ranges, ArticleRange, 0).low == 0 + && g_array_index (group->ranges, ArticleRange, 0).high == 0) { + g_array_index (group->ranges, ArticleRange, 0).low = low; + g_array_index (group->ranges, ArticleRange, 0).high = high; + + newsrc->dirty = TRUE; + } + else { + ArticleRange tmp_range; + + for (i = 0; i < group->ranges->len; i ++) { + guint range_low = g_array_index (group->ranges, ArticleRange, i).low; + guint range_high = g_array_index (group->ranges, ArticleRange, i).high; + + /* if it's already part of a range, return immediately. */ + if (low >= range_low && + low <= range_high && + high >= range_low && + high <= range_high) { + return; + } + /* if we have a new lower bound for this range, set it. */ + else if (low <= range_low + && high >= range_low + && high <= range_high) { + g_array_index (group->ranges, ArticleRange, i).low = low; + newsrc->dirty = TRUE; + return; + } + /* if we have a new upper bound for this range, set it. */ + else if (high >= range_high + && low >= range_low + && low <= range_high) { + g_array_index (group->ranges, ArticleRange, i).high = high; + newsrc->dirty = TRUE; + return; + } + /* if we would be inserting another range that + starts one index higher than an existing + one, make the upper value of the existing + range the upper value of the new one. */ + else if (low == range_high + 1) { + g_array_index (group->ranges, ArticleRange, i).high = high; + newsrc->dirty = TRUE; + return; + } + /* if we would be inserting another range that + ends one index lower than an existing one, + group the existing range by setting its low + to the new low */ + else if (high == range_low - 1) { + g_array_index (group->ranges, ArticleRange, i).low = low; + newsrc->dirty = TRUE; + return; + } + /* if the range lies entirely outside another + range, doesn't coincide with it's + endpoints, and has lower values, insert it + into the middle of the list. */ + else if (low < range_low + && high < range_low) { + tmp_range.low = low; + tmp_range.high = high; + + group->ranges = g_array_insert_val (group->ranges, i, tmp_range); + newsrc->dirty = TRUE; + + return; + } + } + + /* if we made it here, the range needs to go at the end */ + tmp_range.low = low; + tmp_range.high = high; + group->ranges = g_array_append_val (group->ranges, tmp_range); + newsrc->dirty = TRUE; + } +} + +int +camel_nntp_newsrc_get_highest_article_read (CamelNNTPNewsrc *newsrc, char *group_name) +{ + NewsrcGroup *group; + + group = g_hash_table_lookup (newsrc->groups, group_name); + + return camel_nntp_newsrc_group_get_highest_article_read (newsrc, group); +} + +void +camel_nntp_newsrc_mark_article_read (CamelNNTPNewsrc *newsrc, char *group_name, int num) +{ + camel_nntp_newsrc_mark_range_read (newsrc, group_name, num, num); +} + +void +camel_nntp_newsrc_mark_range_read(CamelNNTPNewsrc *newsrc, char *group_name, long low, long high) +{ + NewsrcGroup *group; + + /* swap them if they're in the wrong order. */ + if (low > high) { + long tmp; + + tmp = high; + high = low; + low = tmp; + } + + group = g_hash_table_lookup (newsrc->groups, group_name); + + camel_nntp_newsrc_group_mark_range_read (newsrc, group, low, high); +} + +gboolean +camel_nntp_newsrc_article_is_read (CamelNNTPNewsrc *newsrc, char *group_name, long num) +{ + int i; + NewsrcGroup *group; + + group = g_hash_table_lookup (newsrc->groups, group_name); + + for (i = 0; i < group->ranges->len; i++) { + if (num >= g_array_index (group->ranges, ArticleRange, i).low && + num <= g_array_index (group->ranges, ArticleRange, i).high) { + return TRUE; + } + } + + return FALSE; +} + +struct newsrc_ptr_array { + GPtrArray *ptr_array; + gboolean subscribed_only; +}; + +static void +get_group_foreach (char *group_name, NewsrcGroup *group, struct newsrc_ptr_array *npa) +{ + if (group->subscribed || !npa->subscribed_only) { + g_ptr_array_add (npa->ptr_array, group_name); + } +} + +GPtrArray * +camel_nntp_newsrc_get_subscribed_group_names (CamelNNTPNewsrc *newsrc) +{ + struct newsrc_ptr_array npa; + + npa.ptr_array = g_ptr_array_new(); + npa.subscribed_only = TRUE; + + g_hash_table_foreach (newsrc->subscribed_groups, + (GHFunc)get_group_foreach, &npa); + + return npa.ptr_array; +} + +GPtrArray * +camel_nntp_newsrc_get_all_group_names (CamelNNTPNewsrc *newsrc) +{ + struct newsrc_ptr_array npa; + + npa.ptr_array = g_ptr_array_new(); + npa.subscribed_only = FALSE; + + g_hash_table_foreach (newsrc->groups, + (GHFunc)get_group_foreach, &npa); + + return npa.ptr_array; +} + +void +camel_nntp_newsrc_free_group_names (CamelNNTPNewsrc *newsrc, GPtrArray *group_names) +{ + g_ptr_array_free (group_names, TRUE); +} + +struct newsrc_fp { + CamelNNTPNewsrc *newsrc; + FILE *fp; +}; + +static void +camel_nntp_newsrc_write_group_line(gpointer key, NewsrcGroup *group, struct newsrc_fp *newsrc_fp) +{ + CamelNNTPNewsrc *newsrc; + FILE *fp; + int i; + int line_length = 0; + + fp = newsrc_fp->fp; + newsrc = newsrc_fp->newsrc; + + fprintf (fp, "%s%c", group->name, group->subscribed ? ':' : '!'); + + line_length += strlen(group->name) + 1; + + if (group->ranges->len == 1 + && g_array_index (group->ranges, ArticleRange, 0).low == 0 + && g_array_index (group->ranges, ArticleRange, 0).high == 0) { + fprintf (fp, "\n"); + + return; /* special case since our parsing code will insert this + bogus range if there were no read articles. The code + to add a range is smart enough to remove this one if we + ever mark an article read, but we still need to deal with + it if that code doesn't get hit. */ + } + + fprintf (fp, " "); + line_length += 1; + + for (i = 0; i < group->ranges->len; i ++) { + char range_buffer[100]; + guint low = g_array_index (group->ranges, ArticleRange, i).low; + guint high = g_array_index (group->ranges, ArticleRange, i).high; + + if (low == high) + sprintf(range_buffer, "%d", low); + else if (low == high - 1) + sprintf(range_buffer, "%d,%d", low, high); + else + sprintf(range_buffer, "%d-%d", low, high); + + if (i != group->ranges->len - 1) + strcat(range_buffer, ","); + + /* this constant (991) gives the same line breaking as faried's .newsrc file */ + if (line_length + strlen(range_buffer) > 991 /*XXX*/) { + char range_buffer2[101]; + int num_to_print = 991 - line_length; + + strcpy(range_buffer2, range_buffer); + range_buffer2[num_to_print] = '!'; + range_buffer2[num_to_print+1] = '\n'; + range_buffer2[num_to_print+2] = '\0'; + + fprintf (fp, range_buffer2); + + fprintf (fp, range_buffer + num_to_print); + + line_length = strlen(range_buffer) - num_to_print; + } + else { + fprintf (fp, range_buffer); + line_length += strlen(range_buffer); + } + } + + fprintf (fp, "\n"); +} + +void +camel_nntp_newsrc_write_to_file(CamelNNTPNewsrc *newsrc, FILE *fp) +{ + struct newsrc_fp newsrc_fp; + + newsrc_fp.newsrc = newsrc; + newsrc_fp.fp = fp; + + g_hash_table_foreach (newsrc->groups, + (GHFunc)camel_nntp_newsrc_write_group_line, + &newsrc_fp); +} + +void +camel_nntp_newsrc_write(CamelNNTPNewsrc *newsrc) +{ + FILE *fp; + + if (!newsrc->dirty) + return; + + if ((fp = fopen(newsrc->filename, "w")) == NULL) { + g_warning ("Couldn't open newsrc file '%s'.\n", newsrc->filename); + return; + } + + camel_nntp_newsrc_write_to_file(newsrc, fp); + + fclose(fp); +} + +static void +camel_nntp_newsrc_parse_line(CamelNNTPNewsrc *newsrc, char *line) +{ + char *p, sep, *comma, *dash; + gboolean is_subscribed; + NewsrcGroup *group; + + p = strchr(line, ':'); + + if (p) { + is_subscribed = TRUE; + } + else { + p = strchr(line, '!'); + if (p) + is_subscribed = FALSE; + else + return; /* bogus line. */ + } + + sep = *p; + *p = '\0'; + + group = camel_nntp_newsrc_group_add (newsrc, line, is_subscribed); + + *p = sep; + + p++; + + do { + guint high, low; + + comma = strchr(p, ','); + + if (comma) + *comma = '\0'; + + dash = strchr(p, '-'); + + if (!dash) { /* there wasn't a dash. must be just one number */ + high = low = atol(p); + } + else { /* there was a dash. */ + *dash = '\0'; + low = atol(p); + *dash = '-'; + p = dash + 1; + high = atol(p); + } + + camel_nntp_newsrc_group_mark_range_read (newsrc, group, low, high); + + if (comma) { + *comma = ','; + p = comma + 1; + } + + } while(comma); +} + +#define MAX_LINE_LENGTH 1500 +#define BUFFER_LENGTH (20 * MAX_LINE_LENGTH) + +CamelNNTPNewsrc * +camel_nntp_newsrc_read_for_server (const char *server) +{ + FILE *fp; + char buf[BUFFER_LENGTH]; + CamelNNTPNewsrc *newsrc = g_new0(CamelNNTPNewsrc, 1); + + newsrc->filename = g_strdup_printf ("%s/.newsrc-%s", g_get_home_dir(), server); + 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. + Too bad for them. */ + while(strlen(buf) < sizeof(buf) + && buf[strlen(buf) - 2] == '!') { + fgets(&buf[strlen(buf) - 2], MAX_LINE_LENGTH, fp); + } + + camel_nntp_newsrc_parse_line(newsrc, buf); + } + + fclose(fp); + + return newsrc; +} diff --git a/camel/providers/nntp/camel-nntp-newsrc.h b/camel/providers/nntp/camel-nntp-newsrc.h new file mode 100644 index 0000000000..3f4be6de8d --- /dev/null +++ b/camel/providers/nntp/camel-nntp-newsrc.h @@ -0,0 +1,27 @@ + +#ifndef _CAMEL_NNTP_NEWSRC_H_ +#define _CAMEL_NNTP_NEWSRC_H_ + +#include +#include "glib.h" + +typedef struct CamelNNTPNewsrc CamelNNTPNewsrc; + +int camel_nntp_newsrc_get_highest_article_read (CamelNNTPNewsrc *newsrc, char *group_name); +void camel_nntp_newsrc_mark_article_read (CamelNNTPNewsrc *newsrc, + char *group_name, int num); +void camel_nntp_newsrc_mark_range_read (CamelNNTPNewsrc *newsrc, + char *group_name, long low, long high); + +gboolean camel_nntp_newsrc_article_is_read (CamelNNTPNewsrc *newsrc, + char *group_name, long num); + +GPtrArray *camel_nntp_newsrc_get_subscribed_group_names (CamelNNTPNewsrc *newsrc); +GPtrArray *camel_nntp_newsrc_get_all_group_names (CamelNNTPNewsrc *newsrc); +void camel_nntp_newsrc_free_group_names (CamelNNTPNewsrc *newsrc, GPtrArray *group_names); + +void camel_nntp_newsrc_write_to_file (CamelNNTPNewsrc *newsrc, FILE *fp); +void camel_nntp_newsrc_write (CamelNNTPNewsrc *newsrc); +CamelNNTPNewsrc *camel_nntp_newsrc_read_for_server (const char *server); + +#endif /* _CAMEL_NNTP_NEWSRC_H_ */ diff --git a/camel/providers/nntp/camel-nntp-store.c b/camel/providers/nntp/camel-nntp-store.c index 2a0084eee2..765cd8796b 100644 --- a/camel/providers/nntp/camel-nntp-store.c +++ b/camel/providers/nntp/camel-nntp-store.c @@ -55,13 +55,48 @@ 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 CamelFolder *_get_folder (CamelStore *store, const gchar *folder_name, CamelException *ex); -static char *_get_folder_name (CamelStore *store, const char *folder_name, - CamelException *ex); - static gboolean nntp_connect (CamelService *service, CamelException *ex); static gboolean nntp_disconnect (CamelService *service, CamelException *ex); + +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); + + /* 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); + + /* check if folder has already been created */ + /* call the standard routine for that when */ + /* it is done ... */ + + new_nntp_folder = gtk_type_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); + + return new_folder; +} + + +static char * +nntp_store_get_folder_name (CamelStore *store, const char *folder_name, + CamelException *ex) +{ + return g_strdup (folder_name); +} + + static void camel_nntp_store_class_init (CamelNNTPStoreClass *camel_nntp_store_class) { @@ -70,8 +105,8 @@ camel_nntp_store_class_init (CamelNNTPStoreClass *camel_nntp_store_class) service_class = gtk_type_class (camel_service_get_type ()); /* virtual method overload */ - camel_store_class->get_folder = _get_folder; - camel_store_class->get_folder_name = _get_folder_name; + camel_store_class->get_folder = nntp_store_get_folder; + camel_store_class->get_folder_name = nntp_store_get_folder_name; } @@ -108,37 +143,6 @@ camel_nntp_store_get_type (void) return camel_nntp_store_type; } -static CamelFolder * -_get_folder (CamelStore *store, const gchar *folder_name, CamelException *ex) -{ - CamelNNTPFolder *new_nntp_folder; - CamelFolder *new_folder; - - /* check if folder has already been created */ - /* call the standard routine for that when */ - /* it is done ... */ - - new_nntp_folder = gtk_type_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, '/', ex); - - return new_folder; -} - - -static char * -_get_folder_name (CamelStore *store, const char *folder_name, - CamelException *ex) -{ - return g_strdup (folder_name); -} - /** * camel_nntp_store_open: Connect to the server if we are currently * disconnected. @@ -206,7 +210,7 @@ nntp_connect (CamelService *service, CamelException *ex) CAMEL_STREAM_BUFFER_READ); /* Read the greeting */ - buf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (store->istream), ex /* XX check this */); + buf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (store->istream)); if (!buf) { return -1; } @@ -286,12 +290,12 @@ camel_nntp_command (CamelNNTPStore *store, char **ret, char *fmt, ...) } /* Send the command */ - camel_stream_write (store->ostream, cmdbuf, strlen (cmdbuf), ex /* XXX */); + camel_stream_write (store->ostream, cmdbuf, strlen (cmdbuf)); g_free (cmdbuf); - camel_stream_write (store->ostream, "\r\n", 2, ex /* XXX */); + camel_stream_write (store->ostream, "\r\n", 2); /* Read the response */ - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (store->istream), ex /* XXX */); + respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (store->istream)); resp_code = atoi (respbuf); if (resp_code < 400) @@ -333,11 +337,10 @@ camel_nntp_command_get_additional_data (CamelNNTPStore *store) GPtrArray *data; char *buf; int i, status = CAMEL_NNTP_OK; - CamelException *ex = camel_exception_new(); data = g_ptr_array_new (); while (1) { - buf = camel_stream_buffer_read_line (stream, ex /* XXX */); + buf = camel_stream_buffer_read_line (stream); if (!buf) { status = CAMEL_NNTP_FAIL; break; @@ -376,8 +379,6 @@ camel_nntp_store_subscribe_group (CamelStore *store, char *ret = NULL; CamelException *ex = camel_exception_new(); - camel_nntp_store_open(CAMEL_NNTP_STORE(store), ex); - if (camel_exception_get_id (ex)) { g_free (root_dir); camel_exception_free (ex); diff --git a/camel/providers/nntp/camel-nntp-store.h b/camel/providers/nntp/camel-nntp-store.h index 257772d7cb..9d4d6edebc 100644 --- a/camel/providers/nntp/camel-nntp-store.h +++ b/camel/providers/nntp/camel-nntp-store.h @@ -33,6 +33,7 @@ extern "C" { #include #include "camel-store.h" +#include "camel-nntp-newsrc.h" #define CAMEL_NNTP_STORE_TYPE (camel_nntp_store_get_type ()) #define CAMEL_NNTP_STORE(obj) (GTK_CHECK_CAST((obj), CAMEL_NNTP_STORE_TYPE, CamelNNTPStore)) @@ -46,6 +47,8 @@ typedef struct { #define CAMEL_NNTP_EXT_XOVER 0x01 guint32 extensions; + CamelNNTPNewsrc *newsrc; + CamelStream *istream, *ostream; } CamelNNTPStore; diff --git a/camel/providers/nntp/camel-nntp-utils.c b/camel/providers/nntp/camel-nntp-utils.c index 7100be0aed..ae1f676cc3 100644 --- a/camel/providers/nntp/camel-nntp-utils.c +++ b/camel/providers/nntp/camel-nntp-utils.c @@ -51,8 +51,7 @@ get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, while (!done) { char *line; - line = camel_stream_buffer_read_line ( - CAMEL_STREAM_BUFFER ( nntp_istream ), ex /* XXX */); + line = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER ( nntp_istream )); if (*line == '.') { done = TRUE; @@ -63,9 +62,9 @@ get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, new_info->subject = g_strdup(split_line[1]); new_info->from = g_strdup(split_line[2]); - new_info->to = g_strdup(folder->name); + new_info->to = g_strdup(nntp_folder->group_name); + new_info->date_sent = header_decode_date(split_line[3], NULL); #if 0 - new_info->date_sent = g_strdup(split_line[3]); /* XXX do we need to fill in both dates? */ new_info->headers.date_received = g_strdup(split_line[3]); #endif @@ -87,10 +86,6 @@ get_HEAD_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, { int i; int status; - GArray *array; - CamelMessageInfo info; - - array = g_array_new(FALSE, FALSE, sizeof(CamelMessageInfo)); for (i = first_message; i < last_message; i ++) { status = camel_nntp_command (nntp_store, NULL, @@ -105,6 +100,7 @@ get_HEAD_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, CamelStream *header_stream; GArray *header_array; CamelStream *nntp_istream; + CamelMessageInfo *new_info = g_new0(CamelMessageInfo, 1); buf_alloc = 2048; buf_len = 0; @@ -150,21 +146,23 @@ get_HEAD_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, for (h = 0; h < header_array->len; h ++) { Rfc822Header *header = &((Rfc822Header*)header_array->data)[h]; if (!g_strcasecmp(header->name, "From")) - info.from = g_strdup(header->value); + new_info->from = g_strdup(header->value); else if (!g_strcasecmp(header->name, "To")) - info.to = g_strdup(header->value); + new_info->to = g_strdup(header->value); else if (!g_strcasecmp(header->name, "Subject")) - info.subject = g_strdup(header->value); + new_info->subject = g_strdup(header->value); else if (!g_strcasecmp(header->name, "Message-ID")) - info.uid = g_strdup(header->value); + new_info->uid = g_strdup(header->value); else if (!g_strcasecmp(header->name, "Date")) { + new_info->date_sent = header_decode_date (header->value); #if 0 - info.date_sent = g_strdup(header->value); - info.date_received = g_strdup(header->value); + new_info->date_sent = g_strdup(header->value); + new_info->date_received = g_strdup(header->value); #endif } } - g_array_append_val(array, info); + + camel_folder_summary_add (nntp_folder->summary, new_info); } else if (status == CAMEL_NNTP_FAIL) { /* nasty things are afoot */ @@ -172,7 +170,6 @@ get_HEAD_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, break; } } - return array; } #endif @@ -188,7 +185,7 @@ camel_nntp_get_headers (CamelStore *store, int status; status = camel_nntp_command (nntp_store, &ret, - "GROUP %s", folder->name); + "GROUP %s", CAMEL_NNTP_FOLDER (folder)->group_name); sscanf (ret, "%d %d %d", &nb_message, &first_message, &last_message); g_free (ret); @@ -199,13 +196,15 @@ 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 } else { -#if 0 get_HEAD_headers (nntp_store, folder, first_message, last_message, ex); -#endif } +#endif } diff --git a/camel/providers/nntp/test-newsrc.c b/camel/providers/nntp/test-newsrc.c new file mode 100644 index 0000000000..c4b985e565 --- /dev/null +++ b/camel/providers/nntp/test-newsrc.c @@ -0,0 +1,10 @@ +#include +#include +#include "camel-nntp-newsrc.h" + +int +main(int argc, char *argv[]) +{ + CamelNNTPNewsrc *newsrc = camel_nntp_newsrc_read_for_server (argv[1]); + camel_nntp_newsrc_write_to_file (newsrc, stdout); +} -- cgit v1.2.3