Implemented nntp_folder_search_by_expression and nntp_folder_search_free.
2001-07-02 Sam Creasey <sammy@oh.verio.com> * providers/nntp/camel-nntp-folder.c: Implemented nntp_folder_search_by_expression and nntp_folder_search_free. Basic search functionality e.g. unread marking now works for NNTP folders. * camel_filter_search.c (get_size): Added get-size sexp directive to get the size of a message for filters. * providers/nntp/camel-nntp-folder.c (camel_nntp_folder_new): Always check with the NNTP server after summary load -- this function now always expires old summary entries and syncs with the news server. * providers/nntp/camel-nntp-utils.c (camel_nntp_get_headers): Only fetch headers for articles not already logged in the summary file. * providers/nntp/camel-nntp-grouplist.c (camel_nntp_get_grouplist_from_*): change from g_list_append() to g_list_prepend() + g_list_reverse. Traversing 40,000 element linked lists sucks. * providers/nntp/camel-nntp-store.c (camel_nntp_command): Should the NNTP connection die with CAMEL_EXCEPTION_SERVICE_NOT_CONNECTED, make a single retry attempt. Timing out the NNTP link is less painful this way. svn path=/trunk/; revision=10716
This commit is contained in:
@ -1,3 +1,32 @@
|
||||
2001-07-02 Sam Creasey <sammy@oh.verio.com>
|
||||
|
||||
* providers/nntp/camel-nntp-folder.c: Implemented
|
||||
nntp_folder_search_by_expression and
|
||||
nntp_folder_search_free. Basic search functionality e.g. unread
|
||||
marking now works for NNTP folders.
|
||||
|
||||
* camel_filter_search.c (get_size): Added get-size sexp directive
|
||||
to get the size of a message for filters.
|
||||
|
||||
* providers/nntp/camel-nntp-folder.c (camel_nntp_folder_new):
|
||||
Always check with the NNTP server after summary load -- this
|
||||
function now always expires old summary entries and syncs with
|
||||
the news server.
|
||||
|
||||
* providers/nntp/camel-nntp-utils.c (camel_nntp_get_headers):
|
||||
Only fetch headers for articles not already logged in
|
||||
the summary file.
|
||||
|
||||
* providers/nntp/camel-nntp-grouplist.c
|
||||
(camel_nntp_get_grouplist_from_*): change from g_list_append()
|
||||
to g_list_prepend() + g_list_reverse. Traversing 40,000
|
||||
element linked lists sucks.
|
||||
|
||||
* providers/nntp/camel-nntp-store.c (camel_nntp_command):
|
||||
Should the NNTP connection die with
|
||||
CAMEL_EXCEPTION_SERVICE_NOT_CONNECTED, make a single retry
|
||||
attempt. Timing out the NNTP link is less painful this way.
|
||||
|
||||
2001-07-02 Peter Williams <peterw@ximian.com>
|
||||
|
||||
* README (Introduction): Add comment noting that Camel actually
|
||||
|
||||
@ -73,6 +73,7 @@ static ESExpResult *get_received_date (struct _ESExp *f, int argc, struct _ESExp
|
||||
static ESExpResult *get_current_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
|
||||
static ESExpResult *get_score (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
|
||||
static ESExpResult *get_source (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
|
||||
static ESExpResult *get_size (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
|
||||
|
||||
/* builtin functions */
|
||||
static struct {
|
||||
@ -100,6 +101,7 @@ static struct {
|
||||
{ "get-current-date", (ESExpFunc *) get_current_date, 0 },
|
||||
{ "get-score", (ESExpFunc *) get_score, 0 },
|
||||
{ "get-source", (ESExpFunc *) get_source, 0 },
|
||||
{ "get-size", (ESExpFunc *) get_size, 0 },
|
||||
};
|
||||
|
||||
static ESExpResult *
|
||||
@ -407,6 +409,18 @@ get_source (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessag
|
||||
return r;
|
||||
}
|
||||
|
||||
/* remember, the size comparisons are done at Kbytes */
|
||||
static ESExpResult *
|
||||
get_size (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
|
||||
{
|
||||
ESExpResult *r;
|
||||
|
||||
r = e_sexp_result_new(f, ESEXP_RES_INT);
|
||||
r->value.number = fms->info->size / 1024;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
gboolean
|
||||
camel_filter_search_match (CamelMimeMessage *message, CamelMessageInfo *info,
|
||||
const char *source, const char *expression, CamelException *ex)
|
||||
|
||||
@ -45,9 +45,8 @@ camel_nntp_auth_authenticate (CamelNNTPStore *store, CamelException *ex)
|
||||
prompt = g_strdup_printf (_("Please enter the NNTP password for %s@%s"),
|
||||
service->url->user, service->url->host);
|
||||
service->url->passwd =
|
||||
camel_session_query_authenticator (session,
|
||||
CAMEL_AUTHENTICATOR_ASK, prompt,
|
||||
TRUE, service, "password", ex);
|
||||
camel_session_get_password (session, prompt,
|
||||
TRUE, service, "password", ex);
|
||||
g_free (prompt);
|
||||
|
||||
if (!service->url->passwd) {
|
||||
|
||||
@ -46,6 +46,7 @@
|
||||
#include "camel-data-wrapper.h"
|
||||
#include "camel-mime-message.h"
|
||||
#include "camel-folder-summary.h"
|
||||
#include "camel-folder-search.h"
|
||||
|
||||
#include "camel-exception.h"
|
||||
|
||||
@ -183,8 +184,30 @@ nntp_folder_get_message (CamelFolder *folder, const gchar *uid, CamelException *
|
||||
static GPtrArray*
|
||||
nntp_folder_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex)
|
||||
{
|
||||
g_assert (0);
|
||||
return NULL;
|
||||
CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder);
|
||||
GPtrArray *matches, *summary;
|
||||
|
||||
if(nntp_folder->search == NULL)
|
||||
nntp_folder->search = camel_folder_search_new();
|
||||
|
||||
camel_folder_search_set_folder(nntp_folder->search, folder);
|
||||
summary = camel_folder_get_summary(folder);
|
||||
camel_folder_search_set_summary(nntp_folder->search, summary);
|
||||
|
||||
matches = camel_folder_search_execute_expression(nntp_folder->search, expression, ex);
|
||||
|
||||
camel_folder_free_summary(folder, summary);
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
static void
|
||||
nntp_folder_search_free(CamelFolder *folder, GPtrArray *result)
|
||||
{
|
||||
CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder);
|
||||
|
||||
camel_folder_search_free_result(nntp_folder->search, result);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@ -209,6 +232,7 @@ camel_nntp_folder_class_init (CamelNNTPFolderClass *camel_nntp_folder_class)
|
||||
camel_folder_class->set_message_flags = nntp_folder_set_message_flags;
|
||||
camel_folder_class->get_message = nntp_folder_get_message;
|
||||
camel_folder_class->search_by_expression = nntp_folder_search_by_expression;
|
||||
camel_folder_class->search_free = nntp_folder_search_free;
|
||||
}
|
||||
|
||||
CamelType
|
||||
@ -238,6 +262,7 @@ camel_nntp_folder_new (CamelStore *parent, const char *folder_name, CamelExcepti
|
||||
|
||||
camel_folder_construct (folder, parent, folder_name, folder_name);
|
||||
folder->has_summary_capability = TRUE;
|
||||
folder->has_search_capability = TRUE;
|
||||
|
||||
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",
|
||||
@ -248,18 +273,17 @@ camel_nntp_folder_new (CamelStore *parent, const char *folder_name, CamelExcepti
|
||||
camel_folder_summary_set_filename (folder->summary,
|
||||
nntp_folder->summary_file_path);
|
||||
|
||||
if (-1 == camel_folder_summary_load (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)) {
|
||||
camel_object_unref (CAMEL_OBJECT (folder));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* XXX check return value */
|
||||
camel_folder_summary_save (folder->summary);
|
||||
camel_folder_summary_load (folder->summary);
|
||||
|
||||
camel_nntp_get_headers (CAMEL_FOLDER( folder )->parent_store,
|
||||
nntp_folder, ex);
|
||||
if (camel_exception_get_id (ex)) {
|
||||
camel_object_unref (CAMEL_OBJECT (folder));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* XXX check return value */
|
||||
camel_folder_summary_save (folder->summary);
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ typedef struct {
|
||||
|
||||
gchar *summary_file_path; /* contains the messages summary */
|
||||
CamelFolderSummary *summary;
|
||||
CamelFolderSearch *search;
|
||||
} CamelNNTPFolder;
|
||||
|
||||
|
||||
|
||||
@ -52,8 +52,10 @@ camel_nntp_get_grouplist_from_server (CamelNNTPStore *store, CamelException *ex)
|
||||
while (!done) {
|
||||
char *line;
|
||||
|
||||
if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &line, ex) < 0)
|
||||
if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &line, ex) < 0) {
|
||||
list->group_list = g_list_reverse(list->group_list);
|
||||
return list;
|
||||
}
|
||||
|
||||
if (*line == '.') {
|
||||
done = TRUE;
|
||||
@ -68,10 +70,11 @@ camel_nntp_get_grouplist_from_server (CamelNNTPStore *store, CamelException *ex)
|
||||
|
||||
g_strfreev (split_line);
|
||||
|
||||
list->group_list = g_list_append (list->group_list, entry);
|
||||
list->group_list = g_list_prepend (list->group_list, entry);
|
||||
}
|
||||
}
|
||||
|
||||
list->group_list = g_list_reverse(list->group_list);
|
||||
return list;
|
||||
}
|
||||
|
||||
@ -123,11 +126,12 @@ camel_nntp_get_grouplist_from_file (CamelNNTPStore *store, CamelException *ex)
|
||||
|
||||
g_strfreev (split_line);
|
||||
|
||||
list->group_list = g_list_append (list->group_list, entry);
|
||||
list->group_list = g_list_prepend (list->group_list, entry);
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
|
||||
list->group_list = g_list_reverse(list->group_list);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@ -225,9 +225,7 @@ camel_nntp_newsrc_get_num_articles_read (CamelNNTPNewsrc *newsrc, const char *gr
|
||||
void
|
||||
camel_nntp_newsrc_mark_article_read (CamelNNTPNewsrc *newsrc, const char *group_name, int num)
|
||||
{
|
||||
NEWSRC_LOCK(newsrc, lock);
|
||||
camel_nntp_newsrc_mark_range_read (newsrc, group_name, num, num);
|
||||
NEWSRC_UNLOCK(newsrc, lock);
|
||||
}
|
||||
|
||||
void
|
||||
@ -474,8 +472,10 @@ camel_nntp_newsrc_write(CamelNNTPNewsrc *newsrc)
|
||||
|
||||
NEWSRC_LOCK(newsrc, lock);
|
||||
|
||||
if (!newsrc->dirty)
|
||||
if (!newsrc->dirty) {
|
||||
NEWSRC_UNLOCK(newsrc, lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((fp = fopen(newsrc->filename, "w")) == NULL) {
|
||||
g_warning ("Couldn't open newsrc file '%s'.\n", newsrc->filename);
|
||||
|
||||
@ -298,7 +298,7 @@ static CamelServiceAuthType password_authtype = {
|
||||
};
|
||||
|
||||
static GList *
|
||||
nntp_store_query_auth_types (CamelService *service, gboolean connect, CamelException *ex)
|
||||
nntp_store_query_auth_types (CamelService *service, CamelException *ex)
|
||||
{
|
||||
GList *prev;
|
||||
|
||||
@ -313,8 +313,6 @@ nntp_store_get_folder (CamelStore *store, const gchar *folder_name,
|
||||
{
|
||||
CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store);
|
||||
|
||||
printf ("get_folder called on folder_name=%s\n", folder_name);
|
||||
|
||||
/* if we haven't already read our .newsrc, read it now */
|
||||
if (!nntp_store->newsrc)
|
||||
nntp_store->newsrc =
|
||||
@ -468,8 +466,7 @@ build_folder_info_from_grouplist (CamelNNTPStore *nntp_store, const char *top)
|
||||
|
||||
static CamelFolderInfo *
|
||||
nntp_store_get_folder_info (CamelStore *store, const char *top,
|
||||
gboolean fast, gboolean recursive,
|
||||
gboolean subscribed_only,
|
||||
guint32 flags,
|
||||
CamelException *ex)
|
||||
{
|
||||
CamelURL *url = CAMEL_SERVICE (store)->url;
|
||||
@ -491,7 +488,7 @@ nntp_store_get_folder_info (CamelStore *store, const char *top,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!subscribed_only) {
|
||||
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)) {
|
||||
@ -716,6 +713,16 @@ camel_nntp_command (CamelNNTPStore *store, CamelException *ex, char **ret, char
|
||||
|
||||
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;
|
||||
|
||||
@ -64,7 +64,7 @@ get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder,
|
||||
g_print ("done\n");
|
||||
}
|
||||
else {
|
||||
CamelMessageInfo *new_info = camel_folder_summary_info_new(nntp_folder->summary);
|
||||
CamelMessageInfo *new_info = camel_folder_summary_info_new(folder->summary);
|
||||
char **split_line = g_strsplit (line, "\t", 7);
|
||||
char *subject, *from, *date, *message_id, *bytes;
|
||||
char *uid;
|
||||
@ -74,7 +74,7 @@ get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder,
|
||||
date = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_DATE].index];
|
||||
message_id = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_MESSAGE_ID].index];
|
||||
bytes = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_BYTES].index];
|
||||
|
||||
|
||||
/* if the overview format flagged this
|
||||
field as "full", skip over the
|
||||
preceding field name and colon */
|
||||
@ -109,7 +109,7 @@ get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder,
|
||||
atoi (split_line[0])))
|
||||
new_info->flags |= CAMEL_MESSAGE_SEEN;
|
||||
|
||||
camel_folder_summary_add (nntp_folder->summary, new_info);
|
||||
camel_folder_summary_add (folder->summary, new_info);
|
||||
g_strfreev (split_line);
|
||||
}
|
||||
g_free (line);
|
||||
@ -217,6 +217,33 @@ get_HEAD_headers(CamelNNTPStore *nntp_store, CamelFolder *folder,
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
uid_num (CamelFolderSummary *summary, int index)
|
||||
{
|
||||
char *tmp;
|
||||
char *brk;
|
||||
CamelMessageInfo *minfo;
|
||||
int ret;
|
||||
|
||||
minfo = camel_folder_summary_index(summary, index);
|
||||
if(minfo == NULL)
|
||||
return 0;
|
||||
|
||||
tmp = g_strdup(camel_message_info_uid(minfo));
|
||||
camel_message_info_free(minfo);
|
||||
|
||||
if((brk = strchr(tmp, ',')) == NULL)
|
||||
ret = 0;
|
||||
else {
|
||||
*brk = 0;
|
||||
ret = atoi(tmp);
|
||||
}
|
||||
|
||||
g_free(tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
camel_nntp_get_headers (CamelStore *store,
|
||||
CamelNNTPFolder *nntp_folder,
|
||||
@ -225,15 +252,32 @@ camel_nntp_get_headers (CamelStore *store,
|
||||
CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store);
|
||||
CamelFolder *folder = CAMEL_FOLDER (nntp_folder);
|
||||
char *ret;
|
||||
int first_message, nb_message, last_message;
|
||||
int first_message, nb_message, last_message, last_summary;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
status = camel_nntp_command (nntp_store, ex, &ret,
|
||||
"GROUP %s", folder->name);
|
||||
|
||||
sscanf (ret, "%d %d %d", &nb_message, &first_message, &last_message);
|
||||
g_free (ret);
|
||||
|
||||
i = camel_folder_summary_count(folder->summary);
|
||||
if(i != 0) {
|
||||
last_summary = uid_num(folder->summary, i-1);
|
||||
|
||||
if(last_summary < first_message)
|
||||
camel_folder_summary_clear(folder->summary);
|
||||
else {
|
||||
while(uid_num(folder->summary, 0) < first_message)
|
||||
camel_folder_summary_remove_index(folder->summary, 0);
|
||||
|
||||
if(last_summary >= last_message)
|
||||
return;
|
||||
|
||||
first_message = last_summary;
|
||||
}
|
||||
}
|
||||
|
||||
if (status == NNTP_NO_SUCH_GROUP) {
|
||||
/* XXX throw invalid group exception */
|
||||
camel_exception_setv (ex,
|
||||
@ -253,4 +297,5 @@ camel_nntp_get_headers (CamelStore *store,
|
||||
get_HEAD_headers (nntp_store, folder, first_message, last_message, ex);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user