aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/nntp/camel-nntp-store.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers/nntp/camel-nntp-store.c')
-rw-r--r--camel/providers/nntp/camel-nntp-store.c876
1 files changed, 0 insertions, 876 deletions
diff --git a/camel/providers/nntp/camel-nntp-store.c b/camel/providers/nntp/camel-nntp-store.c
deleted file mode 100644
index 19510af334..0000000000
--- a/camel/providers/nntp/camel-nntp-store.c
+++ /dev/null
@@ -1,876 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-nntp-store.c : class for an nntp store */
-
-/*
- *
- * Copyright (C) 2000 Ximian, Inc. <toshok@ximian.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 <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "libgnome/libgnome.h"
-
-#include "camel-nntp-resp-codes.h"
-#include "camel-folder-summary.h"
-#include "camel-nntp-store.h"
-#include "camel-nntp-grouplist.h"
-#include "camel-nntp-folder.h"
-#include "camel-nntp-auth.h"
-#include "camel-exception.h"
-#include "camel-url.h"
-#include "string-utils.h"
-
-#define NNTP_PORT 119
-
-#define DUMP_EXTENSIONS
-
-/* define if you want the subscribe ui to show folders in tree form */
-/* #define INFO_AS_TREE */
-
-static CamelRemoteStoreClass *remote_store_class = NULL;
-
-static CamelServiceClass *service_class = NULL;
-
-/* Returns the class for a CamelNNTPStore */
-#define CNNTPS_CLASS(so) CAMEL_NNTP_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so))
-#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
-#define CNNTPF_CLASS(so) CAMEL_NNTP_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
-
-static gboolean ensure_news_dir_exists (CamelNNTPStore *store);
-
-static void
-camel_nntp_store_get_extensions (CamelNNTPStore *store, CamelException *ex)
-{
- int rc;
-
- store->extensions = 0;
-
- CAMEL_NNTP_STORE_LOCK(store);
- rc = camel_nntp_command(store, ex, NULL, "LIST EXTENSIONS");
- if (rc == NNTP_LIST_FOLLOWS || rc == NNTP_EXTENSIONS_SUPPORTED) {
- gboolean done = FALSE;
- CamelException ex;
-
- camel_exception_init (&ex);
-
- while (!done) {
- char *line;
-
- if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &line, &ex) < 0)
- break; /* XXX */
-
- if (*line == '.') {
- done = TRUE;
- }
- else {
-#define CHECK_EXT(name,val) if (!strcasecmp (line, (name))) store->extensions |= (val)
-
- CHECK_EXT ("SEARCH", CAMEL_NNTP_EXT_SEARCH);
- CHECK_EXT ("SETGET", CAMEL_NNTP_EXT_SETGET);
- CHECK_EXT ("OVER", CAMEL_NNTP_EXT_OVER);
- CHECK_EXT ("XPATTEXT", CAMEL_NNTP_EXT_XPATTEXT);
- CHECK_EXT ("XACTIVE", CAMEL_NNTP_EXT_XACTIVE);
- CHECK_EXT ("LISTMOTD", CAMEL_NNTP_EXT_LISTMOTD);
- CHECK_EXT ("LISTSUBSCR", CAMEL_NNTP_EXT_LISTSUBSCR);
- CHECK_EXT ("LISTPNAMES", CAMEL_NNTP_EXT_LISTPNAMES);
-
-#undef CHECK_EXT
- }
-
- g_free (line);
- }
- }
- CAMEL_NNTP_STORE_UNLOCK(store);
-
-#ifdef DUMP_EXTENSIONS
- g_print ("NNTP Extensions:");
-#define DUMP_EXT(name,val) if (store->extensions & (val)) g_print (" %s", name);
- DUMP_EXT ("SEARCH", CAMEL_NNTP_EXT_SEARCH);
- DUMP_EXT ("SETGET", CAMEL_NNTP_EXT_SETGET);
- DUMP_EXT ("OVER", CAMEL_NNTP_EXT_OVER);
- DUMP_EXT ("XPATTEXT", CAMEL_NNTP_EXT_XPATTEXT);
- DUMP_EXT ("XACTIVE", CAMEL_NNTP_EXT_XACTIVE);
- DUMP_EXT ("LISTMOTD", CAMEL_NNTP_EXT_LISTMOTD);
- DUMP_EXT ("LISTSUBSCR", CAMEL_NNTP_EXT_LISTSUBSCR);
- DUMP_EXT ("LISTPNAMES", CAMEL_NNTP_EXT_LISTPNAMES);
- g_print ("\n");
-#undef DUMP_EXT
-#endif
-}
-
-static void
-camel_nntp_store_get_overview_fmt (CamelNNTPStore *store, CamelException *ex)
-{
- int status;
- int i;
- gboolean done = FALSE;
-
- CAMEL_NNTP_STORE_LOCK(store);
- status = camel_nntp_command (store, ex, NULL,
- "LIST OVERVIEW.FMT");
-
- if (status != NNTP_LIST_FOLLOWS) {
- if (store->extensions & CAMEL_NNTP_EXT_OVER) {
- /* if we can't get the overview format, we should
- disable OVER support */
- g_warning ("server reported support of OVER but LIST OVERVIEW.FMT failed."
- " disabling OVER.\n");
- store->extensions &= ~CAMEL_NNTP_EXT_OVER;
- return;
- }
- }
- else {
- if (!(store->extensions & CAMEL_NNTP_EXT_OVER)) {
- g_warning ("server didn't report support of OVER but LIST OVERVIEW.FMT worked."
- " enabling OVER.\n");
- store->extensions |= CAMEL_NNTP_EXT_OVER;
- }
- }
-
- /* start at 1 because the article number is always first */
- store->num_overview_fields = 1;
-
- for (i = 0; i < CAMEL_NNTP_OVER_LAST; i ++) {
- store->overview_field [i].index = -1;
- }
-
- while (!done) {
- char *line;
-
- if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &line, ex) < 0)
- break; /* XXX */
-
- if (*line == '.') {
- done = TRUE;
- }
- else {
- CamelNNTPOverField *over_field = NULL;
- char *colon = NULL;;
-
- if (!strncasecmp (line, "From:", 5)) {
- over_field = &store->overview_field [ CAMEL_NNTP_OVER_FROM ];
- over_field->index = store->num_overview_fields;
- colon = line + 5;
- }
- else if (!strncasecmp (line, "Subject:", 7)) {
- over_field = &store->overview_field [ CAMEL_NNTP_OVER_SUBJECT ];
- over_field->index = store->num_overview_fields;
- colon = line + 7;
- }
- else if (!strncasecmp (line, "Date:", 5)) {
- over_field = &store->overview_field [ CAMEL_NNTP_OVER_DATE ];
- over_field->index = store->num_overview_fields;
- colon = line + 5;
- }
- else if (!strncasecmp (line, "Message-ID:", 11)) {
- over_field = &store->overview_field [ CAMEL_NNTP_OVER_MESSAGE_ID ];
- over_field->index = store->num_overview_fields;
- colon = line + 11;
- }
- else if (!strncasecmp (line, "References:", 11)) {
- over_field = &store->overview_field [ CAMEL_NNTP_OVER_REFERENCES ];
- over_field->index = store->num_overview_fields;
- colon = line + 11;
- }
- else if (!strncasecmp (line, "Bytes:", 6)) {
- over_field = &store->overview_field [ CAMEL_NNTP_OVER_BYTES ];
- over_field->index = store->num_overview_fields;
- colon = line + 11;
- }
-
- if (colon && !strncmp (colon + 1, "full", 4))
- over_field->full = TRUE;
-
- store->num_overview_fields ++;
- }
-
- g_free (line);
- }
-
- for (i = 0; i < CAMEL_NNTP_OVER_LAST; i ++) {
- if (store->overview_field [i].index == -1) {
- g_warning ("server's OVERVIEW.FMT doesn't support minimum set we require,"
- " disabling OVER support.\n");
- store->extensions &= ~CAMEL_NNTP_EXT_OVER;
- }
- }
- CAMEL_NNTP_STORE_UNLOCK(store);
-}
-
-static gboolean
-nntp_store_connect (CamelService *service, CamelException *ex)
-{
- char *buf;
- int resp_code;
- CamelNNTPStore *store = CAMEL_NNTP_STORE (service);
-
- if (!ensure_news_dir_exists(store)) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Could not open directory for news server: %s"),
- strerror (errno));
- return FALSE;
- }
-
- if (CAMEL_SERVICE_CLASS (remote_store_class)->connect (service, ex) == FALSE)
- return FALSE;
-
- /* Read the greeting */
- if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (service), &buf, ex) < 0) {
- return FALSE;
- }
-
- resp_code = atoi (buf);
- /* Check to see if we have any permissions on this server. */
- if (resp_code == NNTP_NO_PERMISSION)
- return FALSE;
-
- /* check if posting is allowed. */
- if (resp_code == NNTP_GREETING_POSTING_OK) {
- g_print ("posting allowed\n");
- store->posting_allowed = TRUE;
- }
- else if (resp_code == NNTP_GREETING_NO_POSTING) {
- g_print ("no posting allowed\n");
- store->posting_allowed = FALSE;
- }
- else {
- g_warning ("unexpected server greeting code %d, no posting allowed\n", resp_code);
- store->posting_allowed = FALSE;
- }
-
- g_free (buf);
-
- /* get a list of extensions that the server supports */
- camel_nntp_store_get_extensions (store, ex);
-
- /* try to get the overview.fmt */
- camel_nntp_store_get_overview_fmt (store, ex);
-
- return TRUE;
-}
-
-static gboolean
-nntp_store_disconnect (CamelService *service, gboolean clean, CamelException *ex)
-{
- CamelNNTPStore *store = CAMEL_NNTP_STORE (service);
-
- if (clean)
- camel_nntp_command (store, ex, NULL, "QUIT");
-
- if (store->newsrc)
- camel_nntp_newsrc_write (store->newsrc);
-
- if (!service_class->disconnect (service, clean, ex))
- return FALSE;
-
- return TRUE;
-}
-
-static char *
-nntp_store_get_name (CamelService *service, gboolean brief)
-{
- if (brief)
- return g_strdup_printf ("%s", service->url->host);
- else
- return g_strdup_printf (_("USENET News via %s"), service->url->host);
-
-}
-
-static CamelServiceAuthType password_authtype = {
- N_("Password"),
-
- N_("This option will authenticate with the NNTP server using a "
- "plaintext password."),
-
- "",
- TRUE
-};
-
-static GList *
-nntp_store_query_auth_types (CamelService *service, CamelException *ex)
-{
- GList *prev;
-
- g_warning ("nntp::query_auth_types: not implemented. Defaulting.");
- prev = CAMEL_SERVICE_CLASS (remote_store_class)->query_auth_types (service, ex);
- return g_list_prepend (prev, &password_authtype);
-}
-
-static CamelFolder *
-nntp_store_get_folder (CamelStore *store, const gchar *folder_name,
- guint32 flags, CamelException *ex)
-{
- 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);
-
- if (!nntp_store->newsrc) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Unable to open or create .newsrc file for %s: %s"),
- CAMEL_SERVICE(store)->url->host,
- strerror(errno));
- return NULL;
- }
-
- return camel_nntp_folder_new (store, folder_name, ex);
-}
-
-#ifdef INFO_AS_TREE
-static void
-build_folder_info (CamelNNTPStore *nntp_store, CamelFolderInfo **root,
- CamelFolderInfo *parent, CamelNNTPGroupListEntry *entry,
- char *prefix, char *suffix,
- GHashTable *name_to_info)
-{
- CamelURL *url = CAMEL_SERVICE (nntp_store)->url;
- char *dot;
- if ((dot = strchr (suffix, '.'))) {
- /* it's an internal node, figure out the next node in
- the chain */
- CamelFolderInfo *node;
- char *node_name, *node_full_name;
-
- node_name = g_malloc0 (dot - suffix + 1);
- strncpy (node_name, suffix, dot - suffix);
- node_full_name = g_strdup_printf ("%s.%s", prefix, node_name);
-
- node = g_hash_table_lookup (name_to_info, node_full_name);
- if (!node) {
- /* we need to add one */
- node = g_new0 (CamelFolderInfo, 1);
- node->name = g_strdup (node_name);
- node->full_name = g_strdup (node_full_name);
- node->url = NULL;
- node->unread_message_count = -1;
-
- if (parent) {
- if (parent->child) {
- node->sibling = parent->child;
- parent->child = node;
- }
- else {
- parent->child = node;
- }
- }
- else {
- if (*root) {
- *root = node;
- }
- else {
- node->sibling = *root;
- *root = node;
- }
- }
-
- g_hash_table_insert (name_to_info, node_full_name, node);
- }
-
- build_folder_info (nntp_store, root, node, entry, node_full_name, dot + 1, name_to_info);
- }
- else {
- /* it's a leaf node, make the CamelFolderInfo and
- append it to @parent's list of children. */
- CamelFolderInfo *new_group;
-
- new_group = g_new0 (CamelFolderInfo, 1);
- new_group->name = g_strdup (entry->group_name);
- new_group->full_name = g_strdup (entry->group_name);
- new_group->url = g_strdup_printf ("nntp://%s%s%s/%s",
- url->user ? url->user : "",
- url->user ? "@" : "",
- url->host, (char *)entry->group_name);
-
- new_group->unread_message_count = (entry->high - entry->low -
- camel_nntp_newsrc_get_num_articles_read (nntp_store->newsrc, entry->group_name));
-
- if (parent) {
- if (parent->child) {
- new_group->sibling = parent->child;
- parent->child = new_group;
- }
- else {
- parent->child = new_group;
- }
- }
- else {
- if (*root) {
- *root = new_group;
- }
- else {
- new_group->sibling = *root;
- *root = new_group;
- }
- }
- }
-}
-#endif
-
-static CamelFolderInfo *
-build_folder_info_from_grouplist (CamelNNTPStore *nntp_store, const char *top)
-{
- GList *g;
- CamelFolderInfo *groups = NULL;
-#ifdef INFO_AS_TREE
- GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
-#else
- CamelFolderInfo *last = NULL, *fi;
- CamelURL *url = CAMEL_SERVICE (nntp_store)->url;
-#endif
-
- for (g = nntp_store->group_list->group_list; g; g = g_list_next (g)) {
- CamelNNTPGroupListEntry *entry = g->data;
-
- if (!top || !strncmp (top, entry->group_name, strlen (top))) {
-#ifdef INFO_AS_TREE
- build_folder_info (nntp_store, &groups, NULL, entry,
- "", entry->group_name, hash);
-#else
-
- fi = g_new0 (CamelFolderInfo, 1);
- fi->name = g_strdup (entry->group_name);
- fi->full_name = g_strdup (entry->group_name);
- fi->url = g_strdup_printf ("nntp://%s%s%s/%s",
- url->user ? url->user : "",
- url->user ? "@" : "",
- url->host, (char *)entry->group_name);
-
- fi->unread_message_count = (entry->high - entry->low -
- camel_nntp_newsrc_get_num_articles_read (
- nntp_store->newsrc, entry->group_name));
-
- if (last)
- last->sibling = fi;
- else
- groups = fi;
- last = fi;
-#endif
- }
- }
-
- return groups;
-}
-
-static CamelFolderInfo *
-nntp_store_get_folder_info (CamelStore *store, const char *top,
- guint32 flags,
- CamelException *ex)
-{
- CamelURL *url = CAMEL_SERVICE (store)->url;
- CamelNNTPStore *nntp_store = (CamelNNTPStore *)store;
- GPtrArray *names;
- CamelFolderInfo *groups = NULL, *last = NULL, *fi;
- int i;
-
- /* 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);
-
- if (!nntp_store->newsrc) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Unable to open or create .newsrc file for %s: %s"),
- CAMEL_SERVICE(store)->url->host,
- strerror(errno));
- return NULL;
- }
-
- if (!(flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED)) {
- if (!nntp_store->group_list)
- nntp_store->group_list = camel_nntp_grouplist_fetch (nntp_store, ex);
- if (camel_exception_is_set (ex)) {
- return NULL;
- }
- else {
- fi = build_folder_info_from_grouplist (nntp_store, top);
- return fi;
- }
- }
-
- if (top == NULL) {
- /* return the list of groups */
- names = camel_nntp_newsrc_get_subscribed_group_names (nntp_store->newsrc);
- for (i = 0; i < names->len; i++) {
- fi = g_new0 (CamelFolderInfo, 1);
- fi->name = g_strdup (names->pdata[i]);
- fi->full_name = g_strdup (names->pdata[i]);
- fi->url = g_strdup_printf ("nntp://%s%s%s/%s",
- url->user ? url->user : "",
- url->user ? "@" : "",
- url->host, (char *)names->pdata[i]);
- /* FIXME */
- fi->unread_message_count = -1;
-
- if (last)
- last->sibling = fi;
- else
- groups = fi;
- last = fi;
- }
- camel_nntp_newsrc_free_group_names (nntp_store->newsrc, names);
-
- return groups;
- }
- else {
- /* getting a specific group */
-
- fi = g_new0 (CamelFolderInfo, 1);
- fi->name = g_strdup (top);
- fi->full_name = g_strdup (top);
- fi->url = g_strdup_printf ("nntp://%s/%s", url->host, top);
- /* FIXME */
- fi->unread_message_count = -1;
-
- return fi;
- }
-}
-
-static gboolean
-nntp_store_folder_subscribed (CamelStore *store, const char *folder_name)
-{
- CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store);
-
- return camel_nntp_newsrc_group_is_subscribed (nntp_store->newsrc, folder_name);
-}
-
-static void
-nntp_store_subscribe_folder (CamelStore *store, const char *folder_name,
- CamelException *ex)
-{
- CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store);
-
- camel_nntp_newsrc_subscribe_group (nntp_store->newsrc, folder_name);
-}
-
-static void
-nntp_store_unsubscribe_folder (CamelStore *store, const char *folder_name,
- CamelException *ex)
-{
- CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store);
-
- camel_nntp_newsrc_unsubscribe_group (nntp_store->newsrc, folder_name);
-}
-
-static void
-finalize (CamelObject *object)
-{
- CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (object);
- if (nntp_store->newsrc)
- camel_nntp_newsrc_write (nntp_store->newsrc);
-#ifdef ENABLE_THREADS
- e_mutex_destroy(nntp_store->command_lock);
-#endif
-}
-
-static void
-camel_nntp_store_class_init (CamelNNTPStoreClass *camel_nntp_store_class)
-{
- CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_nntp_store_class);
- CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_nntp_store_class);
-
- remote_store_class = CAMEL_REMOTE_STORE_CLASS(camel_type_get_global_classfuncs
- (camel_remote_store_get_type ()));
-
- service_class = CAMEL_SERVICE_CLASS (camel_type_get_global_classfuncs (camel_service_get_type ()));
-
- /* virtual method overload */
- camel_service_class->connect = nntp_store_connect;
- camel_service_class->disconnect = nntp_store_disconnect;
- camel_service_class->query_auth_types = nntp_store_query_auth_types;
- camel_service_class->get_name = nntp_store_get_name;
-
- camel_store_class->get_folder = nntp_store_get_folder;
- camel_store_class->get_folder_info = nntp_store_get_folder_info;
- camel_store_class->free_folder_info = camel_store_free_folder_info_full;
-
- camel_store_class->folder_subscribed = nntp_store_folder_subscribed;
- camel_store_class->subscribe_folder = nntp_store_subscribe_folder;
- camel_store_class->unsubscribe_folder = nntp_store_unsubscribe_folder;
-}
-
-
-
-static void
-camel_nntp_store_init (gpointer object, gpointer klass)
-{
- CamelRemoteStore *remote_store = CAMEL_REMOTE_STORE (object);
- CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE(object);
- CamelStore *store = CAMEL_STORE (object);
-
- remote_store->default_port = NNTP_PORT;
-
- store->flags = CAMEL_STORE_SUBSCRIPTIONS;
-
-#ifdef ENABLE_THREADS
- nntp_store->command_lock = e_mutex_new(E_MUTEX_REC);
-#endif
-}
-
-CamelType
-camel_nntp_store_get_type (void)
-{
- static CamelType camel_nntp_store_type = CAMEL_INVALID_TYPE;
-
- if (camel_nntp_store_type == CAMEL_INVALID_TYPE) {
- camel_nntp_store_type = camel_type_register (CAMEL_REMOTE_STORE_TYPE, "CamelNNTPStore",
- sizeof (CamelNNTPStore),
- sizeof (CamelNNTPStoreClass),
- (CamelObjectClassInitFunc) camel_nntp_store_class_init,
- NULL,
- (CamelObjectInitFunc) camel_nntp_store_init,
- (CamelObjectFinalizeFunc) finalize);
- }
-
- return camel_nntp_store_type;
-}
-
-
-/**
- * camel_nntp_command: Send a command to a NNTP server.
- * @store: the NNTP store
- * @ret: a pointer to return the full server response in
- * @fmt: a printf-style format string, followed by arguments
- *
- * This command sends the command specified by @fmt and the following
- * arguments to the connected NNTP store specified by @store. It then
- * reads the server's response and parses out the status code. If
- * the caller passed a non-NULL pointer for @ret, camel_nntp_command
- * will set it to point to an buffer containing the rest of the
- * response from the NNTP server. (If @ret was passed but there was
- * no extended response, @ret will be set to NULL.) The caller must
- * free this buffer when it is done with it.
- *
- * Return value: the response code of the nntp command.
- **/
-static int
-camel_nntp_command_send_recv (CamelNNTPStore *store, CamelException *ex, char **ret, char *cmd)
-{
- char *respbuf;
- int resp_code;
- gboolean again;
-
- do {
- again = FALSE;
-
- /* Send the command */
- if (camel_remote_store_send_string (CAMEL_REMOTE_STORE (store), ex, cmd) < 0) {
- return NNTP_PROTOCOL_ERROR;
- }
-
- /* Read the response */
- if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &respbuf, ex) < 0) {
- if (ret)
- *ret = g_strdup (g_strerror (errno));
- return NNTP_PROTOCOL_ERROR;
- }
-
- resp_code = atoi (respbuf);
-
- /* this is kind of a gross hack, but since an auth challenge
- can pop up at any time, and we want to shield this from our
- callers, we handle authentication here. */
- if (resp_code == NNTP_AUTH_REQUIRED) {
- resp_code = camel_nntp_auth_authenticate (store, ex);
- if (resp_code != NNTP_AUTH_ACCEPTED) {
- return resp_code;
- }
-
- /* need to resend our command here */
- again = TRUE;
- }
- } while (again);
-
- if (ret) {
- *ret = strchr (respbuf, ' ');
- if (*ret)
- *ret = g_strdup (*ret + 1);
- }
- g_free (respbuf);
-
- return resp_code;
-}
-
-int
-camel_nntp_command (CamelNNTPStore *store, CamelException *ex, char **ret, char *fmt, ...)
-{
- char *cmdbuf;
- va_list ap;
- int resp_code;
- char *real_fmt;
-
- real_fmt = g_strdup_printf ("%s\r\n", fmt);
-
- va_start (ap, fmt);
- cmdbuf = g_strdup_vprintf (real_fmt, ap);
- va_end (ap);
-
- g_free (real_fmt);
-
- resp_code = camel_nntp_command_send_recv (store, ex, ret, cmdbuf);
-
- if(camel_exception_get_id(ex) ==
- CAMEL_EXCEPTION_SERVICE_NOT_CONNECTED) {
- /* the connect might have timed out, give it another shot.. */
- camel_exception_clear(ex);
- if(nntp_store_connect(CAMEL_SERVICE(store), ex))
- resp_code =
- camel_nntp_command_send_recv (store, ex, ret, cmdbuf);
- /* that's it, no more tries */
- }
-
- g_free (cmdbuf);
-
- return resp_code;
-}
-
-void
-camel_nntp_store_subscribe_group (CamelStore *store,
- const gchar *group_name)
-{
- gchar *root_dir = camel_nntp_store_get_toplevel_dir(CAMEL_NNTP_STORE(store));
- char *ret = NULL;
- CamelException *ex = camel_exception_new();
-
- if (camel_exception_get_id (ex)) {
- g_free (root_dir);
- camel_exception_free (ex);
- return;
- }
-
- if (camel_nntp_command ( CAMEL_NNTP_STORE (store),
- ex, &ret, "GROUP %s", group_name) == NNTP_GROUP_SELECTED) {
- /* we create an empty summary file here, so that when
- the group is opened we'll know we need to build it. */
- gchar *summary_file;
- int fd;
- summary_file = g_strdup_printf ("%s/%s-ev-summary", root_dir, group_name);
-
- fd = open (summary_file, O_CREAT | O_RDWR, 0666);
- close (fd);
-
- g_free (summary_file);
- }
- if (ret) g_free (ret);
-
- g_free (root_dir);
- camel_exception_free (ex);
-}
-
-void
-camel_nntp_store_unsubscribe_group (CamelStore *store,
- const gchar *group_name)
-{
- gchar *root_dir = camel_nntp_store_get_toplevel_dir(CAMEL_NNTP_STORE(store));
- gchar *summary_file;
-
- summary_file = g_strdup_printf ("%s/%s-ev-summary", root_dir, group_name);
- if (g_file_exists (summary_file))
- unlink (summary_file);
- g_free (summary_file);
-
- g_free (root_dir);
-}
-
-GList *
-camel_nntp_store_list_subscribed_groups(CamelStore *store)
-{
- GList *group_name_list = NULL;
- struct stat stat_buf;
- gint stat_error = 0;
- gchar *entry_name;
- gchar *full_entry_name;
- gchar *real_group_name;
- struct dirent *dir_entry;
- DIR *dir_handle;
- gchar *root_dir = camel_nntp_store_get_toplevel_dir(CAMEL_NNTP_STORE(store));
-
- dir_handle = opendir (root_dir);
- g_return_val_if_fail (dir_handle, NULL);
-
- /* read the first entry in the directory */
- dir_entry = readdir (dir_handle);
- while ((stat_error != -1) && (dir_entry != NULL)) {
-
- /* get the name of the next entry in the dir */
- entry_name = dir_entry->d_name;
- full_entry_name = g_strdup_printf ("%s/%s", root_dir, entry_name);
- stat_error = stat (full_entry_name, &stat_buf);
- g_free (full_entry_name);
-
- /* is it a normal file ending in -ev-summary ? */
- if ((stat_error != -1) && S_ISREG (stat_buf.st_mode)) {
- gboolean summary_suffix_found;
-
- real_group_name = string_prefix (entry_name, "-ev-summary",
- &summary_suffix_found);
-
- if (summary_suffix_found)
- /* add the folder name to the list */
- group_name_list = g_list_append (group_name_list,
- real_group_name);
- }
- /* read next entry */
- dir_entry = readdir (dir_handle);
- }
-
- closedir (dir_handle);
-
- return group_name_list;
-}
-
-gchar *
-camel_nntp_store_get_toplevel_dir (CamelNNTPStore *store)
-{
- CamelURL *url = CAMEL_SERVICE (store)->url;
- char *top_dir;
-
- g_assert(url != NULL);
-
- top_dir = g_strdup_printf( "%s/evolution/news/%s",
- g_get_home_dir (),
- url->host );
-
- return top_dir;
-}
-
-static gboolean
-ensure_news_dir_exists (CamelNNTPStore *store)
-{
- gchar *dir = camel_nntp_store_get_toplevel_dir (store);
-
- if (access (dir, F_OK) == 0) {
- g_free (dir);
- return TRUE;
- }
-
- if (camel_mkdir_hier (dir, S_IRWXU) == -1) {
- g_free (dir);
- return FALSE;
- }
-
- return TRUE;
-}