aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/nntp/camel-nntp-summary.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers/nntp/camel-nntp-summary.c')
-rw-r--r--camel/providers/nntp/camel-nntp-summary.c386
1 files changed, 135 insertions, 251 deletions
diff --git a/camel/providers/nntp/camel-nntp-summary.c b/camel/providers/nntp/camel-nntp-summary.c
index d897db24e9..d30fdc6267 100644
--- a/camel/providers/nntp/camel-nntp-summary.c
+++ b/camel/providers/nntp/camel-nntp-summary.c
@@ -50,24 +50,6 @@ extern int camel_verbose_debug;
#define CAMEL_NNTP_SUMMARY_VERSION (1)
-static int xover_setup(CamelNNTPSummary *cns, CamelException *ex);
-static int add_range_xover(CamelNNTPSummary *cns, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex);
-static int add_range_head(CamelNNTPSummary *cns, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex);
-
-enum _xover_t {
- XOVER_STRING = 0,
- XOVER_MSGID,
- XOVER_SIZE,
-};
-
-struct _xover_header {
- struct _xover_header *next;
-
- const char *name;
- unsigned int skip:8;
- enum _xover_t type:8;
-};
-
struct _CamelNNTPSummaryPrivate {
char *uid;
@@ -136,29 +118,16 @@ static void
camel_nntp_summary_finalise(CamelObject *obj)
{
CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(obj);
- struct _xover_header *xover, *xn;
-
- xover = cns->priv->xover;
- while (xover) {
- xn = xover->next;
- g_free(xover);
- xover = xn;
- }
g_free(cns->priv);
}
CamelNNTPSummary *
-camel_nntp_summary_new(CamelNNTPFolder *folder)
+camel_nntp_summary_new(const char *path)
{
CamelNNTPSummary *cns = (CamelNNTPSummary *)camel_object_new(camel_nntp_summary_get_type());
- char *path;
- cns->folder = folder;
- path = g_strdup_printf ("%s%s", folder->storage_path, ".ev-summary");
camel_folder_summary_set_filename((CamelFolderSummary *)cns, path);
- g_free(path);
-
camel_folder_summary_set_build_content((CamelFolderSummary *)cns, FALSE);
return cns;
@@ -230,198 +199,12 @@ summary_header_save(CamelFolderSummary *s, FILE *out)
return 0;
}
-/* Assumes we have the stream */
-int
-camel_nntp_summary_check(CamelNNTPSummary *cns, CamelFolderChangeInfo *changes, CamelException *ex)
-{
- CamelNNTPStore *store;
- CamelFolder *folder;
- CamelFolderSummary *s;
- int ret, i;
- char *line;
- unsigned int n, f, l;
- int count;
-
- folder = (CamelFolder *)cns->folder;
- store = (CamelNNTPStore *)folder->parent_store;
-
- if (((CamelDiscoStore *)store)->status == CAMEL_DISCO_STORE_OFFLINE)
- return 0;
-
- if (xover_setup (cns, ex) == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Connection error: %s"), strerror(errno));
- return -1;
- }
-
- s = (CamelFolderSummary *)cns;
-
- ret = camel_nntp_command(store, &line, "group %s", folder->full_name);
- if (ret == 411) {
- camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID,
- _("No such folder: %s"), line);
- return -1;
- } else if (ret != 211) {
- if (ret < 0)
- line = "";
- camel_exception_setv(ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Could not get group: %s"), line);
- return -1;
- }
-
- line +=3;
- n = strtoul(line, &line, 10);
- f = strtoul(line, &line, 10);
- l = strtoul(line, &line, 10);
-
- if (cns->low == f && cns->high == l) {
- dd(printf("nntp_summary: no work to do!\n"));
- return 0;
- }
-
- /* Need to work out what to do with our messages */
-
- /* Check for messages no longer on the server */
- if (cns->low != f) {
- count = camel_folder_summary_count(s);
- for (i = 0; i < count; i++) {
- CamelMessageInfo *mi = camel_folder_summary_index(s, i);
-
- if (mi) {
- const char *uid = camel_message_info_uid(mi);
- const char *msgid;
-
- n = strtoul(uid, NULL, 10);
- if (n < f || n > l) {
- dd(printf("nntp_summary: %u is lower/higher than lowest/highest article, removed\n", n));
- /* Since we use a global cache this could prematurely remove
- a cached message that might be in another folder - not that important as
- it is a true cache */
- msgid = strchr(uid, ',');
- if (msgid)
- camel_data_cache_remove(store->cache, "cache", msgid+1, NULL);
- camel_folder_change_info_remove_uid(changes, uid);
- camel_folder_summary_remove(s, mi);
- count--;
- i--;
- }
-
- camel_folder_summary_info_free(s, mi);
- }
- }
- cns->low = f;
- }
-
- if (cns->high < l) {
- if (cns->high < f)
- cns->high = f-1;
-
- if (cns->priv->xover) {
- ret = add_range_xover(cns, l, cns->high+1, changes, ex);
- } else {
- ret = add_range_head(cns, l, cns->high+1, changes, ex);
- }
- }
-
-
- /* TODO: not from here */
- camel_folder_summary_touch(s);
- camel_folder_summary_save(s);
-
- if (ret < 0)
- camel_exception_setv(ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Could not get messages: unspecified error"));
-
- return ret;
-}
-
-static struct {
- const char *name;
- int type;
-} headers[] = {
- { "subject", 0 },
- { "from", 0 },
- { "date", 0 },
- { "message-id", 1 },
- { "references", 0 },
- { "bytes", 2 },
-};
+/* ********************************************************************** */
+/* Note: This will be called from camel_nntp_command, so only use camel_nntp_raw_command */
static int
-xover_setup(CamelNNTPSummary *cns, CamelException *ex)
+add_range_xover(CamelNNTPSummary *cns, CamelNNTPStore *store, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex)
{
- CamelNNTPStore *store;
- CamelFolder *folder;
- CamelFolderSummary *s;
- int ret, i;
- char *line;
- unsigned int len;
- unsigned char c, *p;
- struct _xover_header *xover, *last;
-
- if (cns->priv->xover_setup)
- return 0;
-
- /* manual override */
- if (getenv("CAMEL_NNTP_DISABLE_XOVER") != NULL) {
- cns->priv->xover_setup = TRUE;
- return 0;
- }
-
- folder = (CamelFolder *)cns->folder;
- store = (CamelNNTPStore *)folder->parent_store;
- s = (CamelFolderSummary *)cns;
-
- ret = camel_nntp_command(store, &line, "list overview.fmt");
- if (ret == -1) {
- camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
- _("NNTP Command failed: %s"), strerror(errno));
- return -1;
- }
-
- cns->priv->xover_setup = TRUE;
-
- /* unsupported command? */
- if (ret != 215)
- return 0;
-
- last = (struct _xover_header *)&cns->priv->xover;
-
- /* supported command */
- while ((ret = camel_nntp_stream_line(store->stream, (unsigned char **)&line, &len)) > 0) {
- p = line;
- xover = g_malloc0(sizeof(*xover));
- last->next = xover;
- last = xover;
- while ((c = *p++)) {
- if (c == ':') {
- p[-1] = 0;
- for (i=0;i<sizeof(headers)/sizeof(headers[0]);i++) {
- if (strcmp(line, headers[i].name) == 0) {
- xover->name = headers[i].name;
- if (strncmp(p, "full", 4) == 0)
- xover->skip = strlen(xover->name)+1;
- else
- xover->skip = 0;
- xover->type = headers[i].type;
- break;
- }
- }
- break;
- } else {
- p[-1] = tolower(c);
- }
- }
- }
-
- return ret;
-}
-
-static int
-add_range_xover(CamelNNTPSummary *cns, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex)
-{
- CamelNNTPStore *store;
- CamelFolder *folder;
CamelFolderSummary *s;
CamelMessageInfo *mi;
struct _camel_header_raw *headers = NULL;
@@ -429,21 +212,20 @@ add_range_xover(CamelNNTPSummary *cns, unsigned int high, unsigned int low, Came
int len, ret;
unsigned int n, count, total, size;
struct _xover_header *xover;
- time_t last, now;
- folder = (CamelFolder *)cns->folder;
- store = (CamelNNTPStore *)folder->parent_store;
s = (CamelFolderSummary *)cns;
camel_operation_start(NULL, _("%s: Scanning new messages"), ((CamelService *)store)->url->host);
- ret = camel_nntp_command(store, &line, "xover %r", low, high);
+ ret = camel_nntp_raw_command(store, ex, &line, "xover %r", low, high);
if (ret != 224) {
camel_operation_end(NULL);
+ if (ret != -1)
+ camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Unexpected server response from xover: %s"), line);
return -1;
}
- last = time(0);
count = 0;
total = high-low+1;
while ((ret = camel_nntp_stream_line(store->stream, (unsigned char **)&line, &len)) > 0) {
@@ -453,7 +235,7 @@ add_range_xover(CamelNNTPSummary *cns, unsigned int high, unsigned int low, Came
if (*tab != '\t')
continue;
tab++;
- xover = cns->priv->xover;
+ xover = store->xover;
size = 0;
for (;tab[0] && xover;xover = xover->next) {
line = tab;
@@ -507,13 +289,6 @@ add_range_xover(CamelNNTPSummary *cns, unsigned int high, unsigned int low, Came
}
camel_header_raw_clear(&headers);
-
- now = time(0);
- if (last + 2 < now) {
- camel_object_trigger_event((CamelObject *)folder, "folder_changed", changes);
- camel_folder_change_info_clear(changes);
- last = now;
- }
}
camel_operation_end(NULL);
@@ -521,41 +296,36 @@ add_range_xover(CamelNNTPSummary *cns, unsigned int high, unsigned int low, Came
return ret;
}
+/* Note: This will be called from camel_nntp_command, so only use camel_nntp_raw_command */
static int
-add_range_head(CamelNNTPSummary *cns, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex)
+add_range_head(CamelNNTPSummary *cns, CamelNNTPStore *store, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex)
{
- CamelNNTPStore *store;
- CamelFolder *folder;
CamelFolderSummary *s;
int i, ret = -1;
char *line, *msgid;
unsigned int n, count, total;
CamelMessageInfo *mi;
CamelMimeParser *mp;
- time_t now, last;
- folder = (CamelFolder *)cns->folder;
- store = (CamelNNTPStore *)folder->parent_store;
s = (CamelFolderSummary *)cns;
mp = camel_mime_parser_new();
camel_operation_start(NULL, _("%s: Scanning new messages"), ((CamelService *)store)->url->host);
- last = time(0);
count = 0;
total = high-low+1;
for (i=low;i<high+1;i++) {
camel_operation_progress(NULL, (count * 100) / total);
count++;
- ret = camel_nntp_command(store, &line, "head %u", i);
+ ret = camel_nntp_raw_command(store, ex, &line, "head %u", i);
/* unknown article, ignore */
if (ret == 423)
continue;
else if (ret == -1)
- goto error;
+ goto ioerror;
else if (ret != 221) {
- camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Unknown server response: %s"), line);
+ camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Unexpected server response from head: %s"), line);
goto ioerror;
}
line += 3;
@@ -588,13 +358,6 @@ add_range_head(CamelNNTPSummary *cns, unsigned int high, unsigned int low, Camel
cns->priv->uid = NULL;
}
}
-
- now = time(0);
- if (last + 2 < now) {
- camel_object_trigger_event((CamelObject *)folder, "folder_changed", changes);
- camel_folder_change_info_clear(changes);
- last = now;
- }
}
ret = 0;
@@ -618,3 +381,124 @@ ioerror:
return ret;
}
+
+/* Assumes we have the stream */
+/* Note: This will be called from camel_nntp_command, so only use camel_nntp_raw_command */
+int
+camel_nntp_summary_check(CamelNNTPSummary *cns, CamelNNTPStore *store, char *line, CamelFolderChangeInfo *changes, CamelException *ex)
+{
+ CamelFolderSummary *s;
+ int ret = 0, i;
+ unsigned int n, f, l;
+ int count;
+ char *folder = NULL;
+ CamelNNTPStoreInfo *si;
+
+ s = (CamelFolderSummary *)cns;
+
+ line +=3;
+ n = strtoul(line, &line, 10);
+ f = strtoul(line, &line, 10);
+ l = strtoul(line, &line, 10);
+ if (line[0] == ' ') {
+ char *tmp;
+
+ folder = line+1;
+ tmp = strchr(folder, ' ');
+ if (tmp)
+ *tmp = 0;
+ tmp = g_alloca(strlen(folder)+1);
+ strcpy(tmp, folder);
+ folder = tmp;
+ }
+
+ if (cns->low == f && cns->high == l) {
+ dd(printf("nntp_summary: no work to do!\n"));
+ goto update;
+ }
+
+ /* Need to work out what to do with our messages */
+
+ /* Check for messages no longer on the server */
+ if (cns->low != f) {
+ count = camel_folder_summary_count(s);
+ for (i = 0; i < count; i++) {
+ CamelMessageInfo *mi = camel_folder_summary_index(s, i);
+
+ if (mi) {
+ const char *uid = camel_message_info_uid(mi);
+ const char *msgid;
+
+ n = strtoul(uid, NULL, 10);
+ if (n < f || n > l) {
+ dd(printf("nntp_summary: %u is lower/higher than lowest/highest article, removed\n", n));
+ /* Since we use a global cache this could prematurely remove
+ a cached message that might be in another folder - not that important as
+ it is a true cache */
+ msgid = strchr(uid, ',');
+ if (msgid)
+ camel_data_cache_remove(store->cache, "cache", msgid+1, NULL);
+ camel_folder_change_info_remove_uid(changes, uid);
+ camel_folder_summary_remove(s, mi);
+ count--;
+ i--;
+ }
+
+ camel_folder_summary_info_free(s, mi);
+ }
+ }
+ cns->low = f;
+ }
+
+ if (cns->high < l) {
+ if (cns->high < f)
+ cns->high = f-1;
+
+ if (store->xover) {
+ ret = add_range_xover(cns, store, l, cns->high+1, changes, ex);
+ } else {
+ ret = add_range_head(cns, store, l, cns->high+1, changes, ex);
+ }
+ }
+
+ /* TODO: not from here */
+ camel_folder_summary_touch(s);
+ camel_folder_summary_save(s);
+update:
+ /* update store summary if we have it */
+ if (folder
+ && (si = (CamelNNTPStoreInfo *)camel_store_summary_path((CamelStoreSummary *)store->summary, folder))) {
+ int unread = 0;
+
+ count = camel_folder_summary_count(s);
+ for (i = 0; i < count; i++) {
+ CamelMessageInfo *mi = camel_folder_summary_index(s, i);
+
+ if (mi) {
+ if ((mi->flags & CAMEL_MESSAGE_SEEN) == 0)
+ unread++;
+ camel_folder_summary_info_free(s, mi);
+ }
+ }
+
+ if (si->info.unread != unread
+ || si->info.total != count
+ || si->first != f
+ || si->last != l) {
+ si->info.unread = unread;
+ si->info.total = count;
+ si->first = f;
+ si->last = l;
+ camel_store_summary_touch((CamelStoreSummary *)store->summary);
+ camel_store_summary_save((CamelStoreSummary *)store->summary);
+ }
+ camel_store_summary_info_free ((CamelStoreSummary *)store->summary, (CamelStoreInfo *)si);
+ } else {
+ if (folder)
+ g_warning("Group '%s' not present in summary", folder);
+ else
+ g_warning("Missing group from group response");
+ }
+
+ return ret;
+}