From 8eac29db12e027867644fcac287a6b4c34e067c7 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Sun, 27 Aug 2006 02:07:18 +0000 Subject: [PATCH] MSGS command can now do full text search on the room --- citadel/citadel.h | 4 +-- citadel/euidindex.c | 2 +- citadel/msgbase.c | 62 ++++++++++++++++++++++++++++++++--- citadel/msgbase.h | 21 +++++++----- citadel/serv_autocompletion.c | 4 +-- citadel/serv_calendar.c | 7 ++-- citadel/serv_expire.c | 2 +- citadel/serv_fulltext.c | 2 +- citadel/serv_inetcfg.c | 2 +- citadel/serv_network.c | 4 +-- citadel/serv_pop3.c | 2 +- citadel/serv_smtp.c | 2 +- citadel/serv_vandelay.c | 2 +- citadel/serv_vcard.c | 6 ++-- citadel/server_main.c | 2 ++ citadel/techdoc/protocol.txt | 4 +++ 16 files changed, 96 insertions(+), 32 deletions(-) diff --git a/citadel/citadel.h b/citadel/citadel.h index e4e5d894c..c12b99ecc 100644 --- a/citadel/citadel.h +++ b/citadel/citadel.h @@ -33,7 +33,7 @@ extern "C" { /* * Text description of this software */ -#define CITADEL "Citadel 6.83" +#define CITADEL "Citadel 6.84" /* * REV_LEVEL is the current version number (multiplied by 100 to avoid having @@ -45,7 +45,7 @@ extern "C" { * usually more strict because you're not really supposed to dump/load and * upgrade at the same time. */ -#define REV_LEVEL 683 /* This version */ +#define REV_LEVEL 684 /* This version */ #define REV_MIN 591 /* Oldest compatible database */ #define EXPORT_REV_MIN 655 /* Oldest compatible export files */ diff --git a/citadel/euidindex.c b/citadel/euidindex.c index bd0da8929..dd9b171dc 100644 --- a/citadel/euidindex.c +++ b/citadel/euidindex.c @@ -192,7 +192,7 @@ void rebuild_euid_index_for_room(struct ctdlroom *qrbuf, void *data) { "Rebuilding EUID index for <%s>\n", rplist->name); usergoto(rplist->name, 0, 0, NULL, NULL); - CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, + CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, rebuild_euid_index_for_msg, NULL); } } diff --git a/citadel/msgbase.c b/citadel/msgbase.c index bdee54e1e..d000812dd 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -504,14 +504,14 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, * API function to perform an operation for each qualifying message in the * current room. (Returns the number of messages processed.) */ -int CtdlForEachMessage(int mode, long ref, +int CtdlForEachMessage(int mode, long ref, char *search_string, char *content_type, struct CtdlMessage *compare, void (*CallBack) (long, void *), void *userdata) { - int a; + int a, i, j; struct visit vbuf; struct cdbdata *cdbfr; long *msglist = NULL; @@ -523,6 +523,8 @@ int CtdlForEachMessage(int mode, long ref, int is_seen = 0; long lastold = 0L; int printed_lastold = 0; + int num_search_msgs = 0; + long *search_msgs = NULL; /* Learn about the user and room in question */ get_mm(); @@ -587,7 +589,45 @@ int CtdlForEachMessage(int mode, long ref, } } + /* If a search string was specified, get a message list from + * the full text index and remove messages which aren't on both + * lists. + * + * How this works: + * Since the lists are sorted and strictly ascending, and the + * output list is guaranteed to be shorter than or equal to the + * input list, we overwrite the bottom of the input list. This + * eliminates the need to memmove big chunks of the list over and + * over again. + */ + if ( (num_msgs > 0) && (mode == MSGS_SEARCH) && (search_string) ) { + ft_search(&num_search_msgs, &search_msgs, search_string); + if (num_search_msgs > 0) { + int orig_num_msgs; + + orig_num_msgs = num_msgs; + num_msgs = 0; + for (i=0; ilogged_in)) && (!(CC->internal_pgm))) { cprintf("%d not logged in\n", ERROR + NOT_LOGGED_IN); return; } + if ( (mode == MSGS_SEARCH) && (!config.c_enable_fulltext) ) { + cprintf("%d Full text index is not enabled on this server.\n", + ERROR + CMD_NOT_SUPPORTED); + return; + } + if (with_template) { unbuffer_output(); cprintf("%d Send template then receive message list\n", @@ -695,7 +746,8 @@ void cmd_msgs(char *cmdbuf) } CtdlForEachMessage(mode, - cm_ref, + ( (mode == MSGS_SEARCH) ? 0 : cm_ref ), + ( (mode == MSGS_SEARCH) ? search_string : NULL ), NULL, template, (with_headers ? headers_listing : simple_listing), @@ -3827,7 +3879,7 @@ char *CtdlGetSysConfig(char *sysconfname) { /* We want the last (and probably only) config in this room */ begin_critical_section(S_CONFIG); config_msgnum = (-1L); - CtdlForEachMessage(MSGS_LAST, 1, sysconfname, NULL, + CtdlForEachMessage(MSGS_LAST, 1, NULL, sysconfname, NULL, CtdlGetSysConfigBackend, NULL); msgnum = config_msgnum; end_critical_section(S_CONFIG); diff --git a/citadel/msgbase.h b/citadel/msgbase.h index fc0219e31..88c58ecac 100644 --- a/citadel/msgbase.h +++ b/citadel/msgbase.h @@ -2,13 +2,16 @@ #define aide_message(text) quickie_message("Citadel",NULL,AIDEROOM,text,0,NULL) -#define MSGS_ALL 0 -#define MSGS_OLD 1 -#define MSGS_NEW 2 -#define MSGS_FIRST 3 -#define MSGS_LAST 4 -#define MSGS_GT 5 -#define MSGS_EQ 6 +enum { + MSGS_ALL, + MSGS_OLD, + MSGS_NEW, + MSGS_FIRST, + MSGS_LAST, + MSGS_GT, + MSGS_EQ, + MSGS_SEARCH +}; /* * Possible return codes from CtdlOutputMsg() @@ -99,7 +102,9 @@ void PutMetaData(struct MetaData *); void AdjRefCount(long, int); void simple_listing(long, void *); int CtdlMsgCmp(struct CtdlMessage *msg, struct CtdlMessage *template); -int CtdlForEachMessage(int mode, long ref, +int CtdlForEachMessage(int mode, + long ref, + char *searchstring, char *content_type, struct CtdlMessage *compare, void (*CallBack) (long, void *), diff --git a/citadel/serv_autocompletion.c b/citadel/serv_autocompletion.c index 71aa0a035..1a6e38fab 100644 --- a/citadel/serv_autocompletion.c +++ b/citadel/serv_autocompletion.c @@ -180,13 +180,13 @@ void cmd_auto(char *argbuf) { /* Take a spin through the user's personal address book */ if (getroom(&CC->room, USERCONTACTSROOM) == 0) { - CtdlForEachMessage(MSGS_ALL, 0, "text/x-vcard", NULL, + CtdlForEachMessage(MSGS_ALL, 0, NULL, "text/x-vcard", NULL, hunt_for_autocomplete, search_string); } /* FIXME try the global address book */ if (getroom(&CC->room, ADDRESS_BOOK_ROOM) == 0) { - CtdlForEachMessage(MSGS_ALL, 0, "text/x-vcard", NULL, + CtdlForEachMessage(MSGS_ALL, 0, NULL, "text/x-vcard", NULL, hunt_for_autocomplete, search_string); } diff --git a/citadel/serv_calendar.c b/citadel/serv_calendar.c index 596271cc9..a847f2000 100644 --- a/citadel/serv_calendar.c +++ b/citadel/serv_calendar.c @@ -976,7 +976,7 @@ void ical_hunt_for_conflicts(icalcomponent *cal) { cprintf("%d Conflicting events:\n", LISTING_FOLLOWS); - CtdlForEachMessage(MSGS_ALL, 0, "text/calendar", + CtdlForEachMessage(MSGS_ALL, 0, NULL, "text/calendar", NULL, ical_hunt_for_conflicts_backend, (void *) cal @@ -1281,7 +1281,7 @@ void ical_freebusy(char *who) { /* Add busy time from events */ lprintf(CTDL_DEBUG, "Adding busy time from events\n"); - CtdlForEachMessage(MSGS_ALL, 0, "text/calendar", + CtdlForEachMessage(MSGS_ALL, 0, NULL, "text/calendar", NULL, ical_freebusy_backend, (void *)fb ); @@ -1421,7 +1421,8 @@ void ical_getics(void) icalcomponent_set_method(encaps, ICAL_METHOD_PUBLISH); /* Now go through the room encapsulating all calendar items. */ - CtdlForEachMessage(MSGS_ALL, 0, "text/calendar", + CtdlForEachMessage(MSGS_ALL, 0, NULL, + "text/calendar", NULL, ical_getics_backend, (void *) encaps diff --git a/citadel/serv_expire.c b/citadel/serv_expire.c index 28b0968de..6927a6509 100644 --- a/citadel/serv_expire.c +++ b/citadel/serv_expire.c @@ -745,7 +745,7 @@ void do_fsck_msg(long msgnum, void *userdata) { void do_fsck_room(struct ctdlroom *qrbuf, void *data) { getroom(&CC->room, qrbuf->QRname); - CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, do_fsck_msg, NULL); + CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, do_fsck_msg, NULL); } /* diff --git a/citadel/serv_fulltext.c b/citadel/serv_fulltext.c index 9c6f1d896..ab78a7428 100644 --- a/citadel/serv_fulltext.c +++ b/citadel/serv_fulltext.c @@ -208,7 +208,7 @@ void ft_index_msg(long msgnum, void *userdata) { void ft_index_room(struct ctdlroom *qrbuf, void *data) { getroom(&CC->room, qrbuf->QRname); - CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, ft_index_msg, NULL); + CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, ft_index_msg, NULL); } diff --git a/citadel/serv_inetcfg.c b/citadel/serv_inetcfg.c index 89b5e5d66..5d49d5fa8 100644 --- a/citadel/serv_inetcfg.c +++ b/citadel/serv_inetcfg.c @@ -165,7 +165,7 @@ void spamstrings_init_backend(long msgnum, void *userdata) { void inetcfg_init(void) { if (getroom(&CC->room, SYSCONFIGROOM) != 0) return; - CtdlForEachMessage(MSGS_LAST, 1, INTERNETCFG, NULL, + CtdlForEachMessage(MSGS_LAST, 1, NULL, INTERNETCFG, NULL, inetcfg_init_backend, NULL); } diff --git a/citadel/serv_network.c b/citadel/serv_network.c index 27704f103..a769aab3e 100644 --- a/citadel/serv_network.c +++ b/citadel/serv_network.c @@ -992,7 +992,7 @@ void network_spoolout_room(char *room_to_spool) { } /* Do something useful */ - CtdlForEachMessage(MSGS_GT, sc.lastsent, NULL, NULL, + CtdlForEachMessage(MSGS_GT, sc.lastsent, NULL, NULL, NULL, network_spool_msg, &sc); /* If we wrote a digest, deliver it and then close it */ @@ -1127,7 +1127,7 @@ int network_sync_to(char *target_node) { if (!found_node) return(-1); /* Send ALL messages */ - num_spooled = CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, + num_spooled = CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, network_spool_msg, &sc); /* Concise cleanup because we know there's only one node in the sc */ diff --git a/citadel/serv_pop3.c b/citadel/serv_pop3.c index a6f004e00..db1689fb8 100644 --- a/citadel/serv_pop3.c +++ b/citadel/serv_pop3.c @@ -180,7 +180,7 @@ int pop3_grab_mailbox(void) { if (getroom(&CC->room, MAILROOM) != 0) return(-1); /* Load up the messages */ - CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, + CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, pop3_add_message, NULL); /* Figure out which are old and which are new */ diff --git a/citadel/serv_smtp.c b/citadel/serv_smtp.c index e1a933475..ac12d1eaa 100644 --- a/citadel/serv_smtp.c +++ b/citadel/serv_smtp.c @@ -1700,7 +1700,7 @@ void smtp_do_queue(void) { lprintf(CTDL_ERR, "Cannot find room <%s>\n", SMTP_SPOOLOUT_ROOM); return; } - CtdlForEachMessage(MSGS_ALL, 0L, + CtdlForEachMessage(MSGS_ALL, 0L, NULL, SPOOLMIME, NULL, smtp_do_procmsg, NULL); lprintf(CTDL_INFO, "SMTP: queue run completed\n"); diff --git a/citadel/serv_vandelay.c b/citadel/serv_vandelay.c index 501e5b74f..730eee13c 100644 --- a/citadel/serv_vandelay.c +++ b/citadel/serv_vandelay.c @@ -103,7 +103,7 @@ void artv_export_rooms_backend(struct ctdlroom *qrbuf, void *data) { /* format of message list export is all message numbers output * one per line terminated by a 0. */ - CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, + CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, artv_export_room_msg, NULL); cprintf("0\n"); diff --git a/citadel/serv_vcard.c b/citadel/serv_vcard.c index 2d91b75bd..6ec6d2167 100644 --- a/citadel/serv_vcard.c +++ b/citadel/serv_vcard.c @@ -189,7 +189,7 @@ void cmd_igab(char *argbuf) { CtdlDirectoryInit(); /* We want *all* vCards in this room */ - CtdlForEachMessage(MSGS_ALL, 0, "text/x-vcard", + CtdlForEachMessage(MSGS_ALL, 0, NULL, "text/x-vcard", NULL, vcard_add_to_directory, NULL); getroom(&CC->room, hold_rm); /* return to saved room */ @@ -522,7 +522,7 @@ struct vCard *vcard_get_user(struct ctdluser *u) { /* We want the last (and probably only) vcard in this room */ VCmsgnum = (-1); - CtdlForEachMessage(MSGS_LAST, 1, "text/x-vcard", + CtdlForEachMessage(MSGS_LAST, 1, NULL, "text/x-vcard", NULL, vcard_gu_backend, (void *)&VCmsgnum ); getroom(&CC->room, hold_rm); /* return to saved room */ @@ -1051,7 +1051,7 @@ void store_this_ha(struct addresses_to_be_filed *aptr) { /* First remove any addresses we already have in the address book */ usergoto(aptr->roomname, 0, 0, NULL, NULL); - CtdlForEachMessage(MSGS_ALL, 0, "text/x-vcard", NULL, + CtdlForEachMessage(MSGS_ALL, 0, NULL, "text/x-vcard", NULL, strip_addresses_already_have, aptr->collected_addresses); if (strlen(aptr->collected_addresses) > 0) diff --git a/citadel/server_main.c b/citadel/server_main.c index 68f663b4d..134e56434 100644 --- a/citadel/server_main.c +++ b/citadel/server_main.c @@ -80,7 +80,9 @@ int main(int argc, char **argv) int home=0; char relhome[PATH_MAX]=""; char ctdldir[PATH_MAX]=CTDLDIR; +#ifdef HAVE_RUN_DIR struct stat filestats; +#endif /* initialize the master context */ InitializeMasterCC(); diff --git a/citadel/techdoc/protocol.txt b/citadel/techdoc/protocol.txt index 75b8bac48..767e3cd66 100644 --- a/citadel/techdoc/protocol.txt +++ b/citadel/techdoc/protocol.txt @@ -474,6 +474,10 @@ which case that many message pointers will be returned; "first" plus a number, for the corresponding effect; or "gt" plus a number, to list all messages in the current room with a message number greater than the one specified. If no parameters are specified, "all" is assumed. + + In addition, the first parameter may be set to "search", in which case the +third parameter must be a search string. This will request all messages +in the current room whose text contains the search string. The third argument, may be either 0 or 1. If it is 1, this command behaves differently: before a listing is returned, the client must transmit a list -- 2.30.2