diff options
Diffstat (limited to 'camel/providers/nntp/camel-nntp-summary.c')
-rw-r--r-- | camel/providers/nntp/camel-nntp-summary.c | 386 |
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; +} |