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:
Sam Creasey
2001-07-03 02:54:06 +00:00
committed by Sam Creasy
parent 29700d38ae
commit 7cd517dc60
9 changed files with 156 additions and 33 deletions

View File

@ -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

View File

@ -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)

View File

@ -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) {

View File

@ -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;
}

View File

@ -48,6 +48,7 @@ typedef struct {
gchar *summary_file_path; /* contains the messages summary */
CamelFolderSummary *summary;
CamelFolderSearch *search;
} CamelNNTPFolder;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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
}
}