]> code.citadel.org Git - citadel.git/blobdiff - citadel/serv_autocompletion.c
mk_module_init.sh now tests to see if echo supports -e and -E
[citadel.git] / citadel / serv_autocompletion.c
index 109a0efdb6fae15fbdf1ebfbc5553648ace74b89..ddea4f0dcc0077b015eeb7424b23fe62d2087ef4 100644 (file)
@@ -4,10 +4,6 @@
  * Autocompletion of email recipients, etc.
  */
 
-#ifdef DLL_EXPORT
-#define IN_LIBCIT
-#endif
-
 #include "sysdep.h"
 #include <stdlib.h>
 #include <unistd.h>
@@ -35,8 +31,6 @@
 #include <limits.h>
 #include "citadel.h"
 #include "server.h"
-#include "serv_extensions.h"
-#include "sysdep_decls.h"
 #include "citserver.h"
 #include "support.h"
 #include "config.h"
 #include "room_ops.h"
 #include "database.h"
 #include "vcard.h"
+#include "serv_fulltext.h"
 #include "serv_autocompletion.h"
 
+#include "ctdl_module.h"
+
 
 #ifndef HAVE_SNPRINTF
 #include "snprintf.h"
@@ -65,11 +62,16 @@ char *n_to_fn(char *value) {
 
        nnn = malloc(strlen(value) + 10);
        strcpy(nnn, "");
-       extract_token(&nnn[strlen(nnn)] , value, 3, ';', 999);  strcat(nnn, " ");
-       extract_token(&nnn[strlen(nnn)] , value, 1, ';', 999);  strcat(nnn, " ");
-       extract_token(&nnn[strlen(nnn)] , value, 2, ';', 999);  strcat(nnn, " ");
-       extract_token(&nnn[strlen(nnn)] , value, 0, ';', 999);  strcat(nnn, " ");
-       extract_token(&nnn[strlen(nnn)] , value, 4, ';', 999);  strcat(nnn, " ");
+       extract_token(&nnn[strlen(nnn)] , value, 3, ';', 999);
+       strcat(nnn, " ");
+       extract_token(&nnn[strlen(nnn)] , value, 1, ';', 999);
+       strcat(nnn, " ");
+       extract_token(&nnn[strlen(nnn)] , value, 2, ';', 999);
+       strcat(nnn, " ");
+       extract_token(&nnn[strlen(nnn)] , value, 0, ';', 999);
+       strcat(nnn, " ");
+       extract_token(&nnn[strlen(nnn)] , value, 4, ';', 999);
+       strcat(nnn, " ");
        for (i=0; i<strlen(nnn); ++i) {
                if (!strncmp(&nnn[i], "  ", 2)) strcpy(&nnn[i], &nnn[i+1]);
        }
@@ -83,8 +85,7 @@ char *n_to_fn(char *value) {
 /*
  * Back end for cmd_auto()
  */
-void hunt_for_autocomplete(long msgnum, void *data) {
-       char *search_string;
+void hunt_for_autocomplete(long msgnum, char *search_string) {
        struct CtdlMessage *msg;
        struct vCard *v;
        char *value = NULL;
@@ -92,8 +93,6 @@ void hunt_for_autocomplete(long msgnum, void *data) {
        int i = 0;
        char *nnn = NULL;
 
-       search_string = (char *) data;
-
        msg = CtdlFetchMessage(msgnum, 1);
        if (msg == NULL) return;
 
@@ -101,8 +100,9 @@ void hunt_for_autocomplete(long msgnum, void *data) {
        CtdlFreeMessage(msg);
 
        /*
-        * Try to match from a friendly name (the "fn" field).  If there is a
-        * match, return the entry in the form of:  Display Name <user@domain.org>
+        * Try to match from a friendly name (the "fn" field).  If there is
+        * a match, return the entry in the form of:
+        *     Display Name <user@domain.org>
         */
        value = vcard_get_prop(v, "fn", 0, 0, 0);
        if (value != NULL) if (bmstrcasestr(value, search_string)) {
@@ -114,8 +114,9 @@ void hunt_for_autocomplete(long msgnum, void *data) {
        }
 
        /*
-        * Try to match from a structured name (the "n" field).  If there is a
-        * match, return the entry in the form of:  Display Name <user@domain.org>
+        * Try to match from a structured name (the "n" field).  If there is
+        * a match, return the entry in the form of:
+        *     Display Name <user@domain.org>
         */
        value = vcard_get_prop(v, "n", 0, 0, 0);
        if (value != NULL) if (bmstrcasestr(value, search_string)) {
@@ -163,33 +164,95 @@ void hunt_for_autocomplete(long msgnum, void *data) {
 void cmd_auto(char *argbuf) {
        char hold_rm[ROOMNAMELEN];
        char search_string[256];
-
+       long *msglist = NULL;
+       int num_msgs = 0;
+       long *fts_msgs = NULL;
+       int fts_num_msgs = 0;
+       struct cdbdata *cdbfr;
+       int r = 0;
+       int i = 0;
+       int j = 0;
+       int search_match = 0;
+       char *rooms_to_try[] = { USERCONTACTSROOM, ADDRESS_BOOK_ROOM };
+               
        if (CtdlAccessCheck(ac_logged_in)) return;
        extract_token(search_string, argbuf, 0, '|', sizeof search_string);
        if (strlen(search_string) == 0) {
-               cprintf("%d You supplied an empty partial.\n", ERROR + ILLEGAL_VALUE);
+               cprintf("%d You supplied an empty partial.\n",
+                       ERROR + ILLEGAL_VALUE);
                return;
        }
 
        strcpy(hold_rm, CC->room.QRname);       /* save current room */
+       cprintf("%d try these:\n", LISTING_FOLLOWS);
 
-       if (getroom(&CC->room, USERCONTACTSROOM) != 0) {
-               getroom(&CC->room, hold_rm);
-               lprintf(CTDL_CRIT, "cannot get user contacts room\n");
-               cprintf("%d Your address book was not found.\n", ERROR + ROOM_NOT_FOUND);
-               return;
+       /*
+        * Gather up message pointers in rooms containing vCards
+        */
+       for (r=0; r < (sizeof(rooms_to_try) / sizeof(char *)); ++r) {
+               if (getroom(&CC->room, rooms_to_try[r]) == 0) {
+                       cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long));
+                       if (cdbfr != NULL) {
+                               msglist = realloc(msglist, (num_msgs * sizeof(long)) + cdbfr->len + 1);
+                               memcpy(&msglist[num_msgs], cdbfr->ptr, cdbfr->len);
+                               num_msgs += (cdbfr->len / sizeof(long));
+                               cdb_free(cdbfr);
+                       }
+               }
        }
 
-       cprintf("%d try these:\n", LISTING_FOLLOWS);
-       CtdlForEachMessage(MSGS_ALL, 0, "text/x-vcard", NULL, hunt_for_autocomplete, search_string);
+       /*
+        * Search-reduce the results if we have the full text index available
+        */
+       if (config.c_enable_fulltext) {
+               ft_search(&fts_num_msgs, &fts_msgs, search_string);
+               if (fts_msgs) {
+                       for (i=0; i<num_msgs; ++i) {
+                               search_match = 0;
+                               for (j=0; j<fts_num_msgs; ++j) {
+                                       if (msglist[i] == fts_msgs[j]) {
+                                               search_match = 1;
+                                               j = fts_num_msgs + 1;   /* end the search */
+                                       }
+                               }
+                               if (!search_match) {
+                                       msglist[i] = 0;         /* invalidate this result */
+                               }
+                       }
+                       free(fts_msgs);
+               }
+               else {
+                       /* If no results, invalidate the whole list */
+                       free(msglist);
+                       msglist = NULL;
+                       num_msgs = 0;
+               }
+       }
+
+       /*
+        * Now output the ones that look interesting
+        */
+       if (num_msgs > 0) for (i=0; i<num_msgs; ++i) {
+               if (msglist[i] != 0) {
+                       hunt_for_autocomplete(msglist[i], search_string);
+               }
+       }
+       
        cprintf("000\n");
+       if (strcmp(CC->room.QRname, hold_rm)) {
+               getroom(&CC->room, hold_rm);    /* return to saved room */
+       }
 
-       getroom(&CC->room, hold_rm);    /* return to saved room */
+       if (msglist) {
+               free(msglist);
+       }
+       
 }
 
 
-char *serv_autocompletion_init(void)
-{
-       CtdlRegisterProtoHook(cmd_auto, "AUTO", "Perform recipient autocompletion");
+CTDL_MODULE_INIT(autocompletion) {
+       CtdlRegisterProtoHook(cmd_auto, "AUTO", "Do recipient autocompletion");
+
+       /* return our Subversion id for the Log */
        return "$Id$";
 }