ignore test-newsrc
authorChris Toshok <toshok@helixcode.com>
Fri, 23 Jun 2000 02:03:35 +0000 (02:03 +0000)
committerChris Toshok <toshok@src.gnome.org>
Fri, 23 Jun 2000 02:03:35 +0000 (02:03 +0000)
2000-06-22  Chris Toshok  <toshok@helixcode.com>

* 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.

camel/providers/nntp/.cvsignore
camel/providers/nntp/Makefile.am
camel/providers/nntp/camel-nntp-folder.c
camel/providers/nntp/camel-nntp-folder.h
camel/providers/nntp/camel-nntp-newsrc.c [new file with mode: 0644]
camel/providers/nntp/camel-nntp-newsrc.h [new file with mode: 0644]
camel/providers/nntp/camel-nntp-store.c
camel/providers/nntp/camel-nntp-store.h
camel/providers/nntp/camel-nntp-utils.c
camel/providers/nntp/test-newsrc.c [new file with mode: 0644]

index fd6b811..1f5b9d3 100644 (file)
@@ -5,3 +5,4 @@ Makefile.in
 .deps
 *.lo
 *.la
+test-newsrc
index 48f85e8..a205f5b 100644 (file)
@@ -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)
index 8bc623a..a3cfc49 100644 (file)
@@ -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;i<message_info_array->len;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; i<message_info_array->len; 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; i<message_info_array->len; 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;i<maxcount;i++)
-               g_ptr_array_add(array, g_ptr_array_index(nntp_folder->summary->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);
+       }
 }
index 7a445d6..f6c04bb 100644 (file)
@@ -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 (file)
index 0000000..fc0f4c2
--- /dev/null
@@ -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. <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 <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <glib.h>
+#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 (file)
index 0000000..3f4be6d
--- /dev/null
@@ -0,0 +1,27 @@
+
+#ifndef _CAMEL_NNTP_NEWSRC_H_
+#define _CAMEL_NNTP_NEWSRC_H_
+
+#include <stdio.h>
+#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_ */
index 2a0084e..765cd87 100644 (file)
@@ -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);
index 257772d..9d4d6ed 100644 (file)
@@ -33,6 +33,7 @@ extern "C" {
 
 #include <gtk/gtk.h>
 #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;
 
index 7100be0..ae1f676 100644 (file)
@@ -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 (file)
index 0000000..c4b985e
--- /dev/null
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include <glib.h>
+#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);
+}