"Fossies" - the Fresh Open Source Software Archive

Member "citadel/modules/autocompletion/serv_autocompletion.c" (5 Jun 2021, 5545 Bytes) of package /linux/www/citadel.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "serv_autocompletion.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 9.01_vs_902.

    1 /*
    2  * Autocompletion of email recipients, etc.
    3  *
    4  * Copyright (c) 1987-2020 by the citadel.org team
    5  *
    6  * This program is open source software; you can redistribute it and/or modify
    7  * it under the terms of the GNU General Public License version 3.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  */
   14 
   15 
   16 #include "ctdl_module.h"
   17 #include "serv_autocompletion.h"
   18 #include "config.h"
   19 
   20 
   21 /*
   22  * Convert a structured name into a friendly name.  Caller must free the
   23  * returned pointer.
   24  */
   25 char *n_to_fn(char *value) {
   26     char *nnn = NULL;
   27     int i;
   28 
   29     nnn = malloc(strlen(value) + 10);
   30     strcpy(nnn, "");
   31     extract_token(&nnn[strlen(nnn)] , value, 3, ';', 999);
   32     strcat(nnn, " ");
   33     extract_token(&nnn[strlen(nnn)] , value, 1, ';', 999);
   34     strcat(nnn, " ");
   35     extract_token(&nnn[strlen(nnn)] , value, 2, ';', 999);
   36     strcat(nnn, " ");
   37     extract_token(&nnn[strlen(nnn)] , value, 0, ';', 999);
   38     strcat(nnn, " ");
   39     extract_token(&nnn[strlen(nnn)] , value, 4, ';', 999);
   40     strcat(nnn, " ");
   41     for (i=0; i<strlen(nnn); ++i) {
   42         if (!strncmp(&nnn[i], "  ", 2)) strcpy(&nnn[i], &nnn[i+1]);
   43     }
   44     striplt(nnn);
   45     return(nnn);
   46 }
   47 
   48 
   49 
   50 
   51 /*
   52  * Back end for cmd_auto()
   53  */
   54 void hunt_for_autocomplete(long msgnum, char *search_string) {
   55     struct CtdlMessage *msg;
   56     struct vCard *v;
   57     char *value = NULL;
   58     char *value2 = NULL;
   59     int i = 0;
   60     char *nnn = NULL;
   61 
   62     msg = CtdlFetchMessage(msgnum, 1);
   63     if (msg == NULL) return;
   64 
   65     v = vcard_load(msg->cm_fields[eMesageText]);
   66     CM_Free(msg);
   67 
   68     /*
   69      * Try to match from a friendly name (the "fn" field).  If there is
   70      * a match, return the entry in the form of:
   71      *     Display Name <user@domain.org>
   72      */
   73     value = vcard_get_prop(v, "fn", 0, 0, 0);
   74     if (value != NULL) if (bmstrcasestr(value, search_string)) {
   75         value2 = vcard_get_prop(v, "email", 1, 0, 0);
   76         if (value2 == NULL) value2 = "";
   77         cprintf("%s <%s>\n", value, value2);
   78         vcard_free(v);
   79         return;
   80     }
   81 
   82     /*
   83      * Try to match from a structured name (the "n" field).  If there is
   84      * a match, return the entry in the form of:
   85      *     Display Name <user@domain.org>
   86      */
   87     value = vcard_get_prop(v, "n", 0, 0, 0);
   88     if (value != NULL) if (bmstrcasestr(value, search_string)) {
   89 
   90         value2 = vcard_get_prop(v, "email", 1, 0, 0);
   91         if (value2 == NULL) value2 = "";
   92         nnn = n_to_fn(value);
   93         cprintf("%s <%s>\n", nnn, value2);
   94         free(nnn);
   95         vcard_free(v);
   96         return;
   97     }
   98 
   99     /*
  100      * Try a partial match on all listed email addresses.
  101      */
  102     i = 0;
  103     while (value = vcard_get_prop(v, "email", 1, i++, 0), value != NULL) {
  104         if (bmstrcasestr(value, search_string)) {
  105             if (vcard_get_prop(v, "fn", 0, 0, 0)) {
  106                 cprintf("%s <%s>\n", vcard_get_prop(v, "fn", 0, 0, 0), value);
  107             }
  108             else if (vcard_get_prop(v, "n", 0, 0, 0)) {
  109                 nnn = n_to_fn(vcard_get_prop(v, "n", 0, 0, 0));
  110                 cprintf("%s <%s>\n", nnn, value);
  111                 free(nnn);
  112             
  113             }
  114             else {
  115                 cprintf("%s\n", value);
  116             }
  117             vcard_free(v);
  118             return;
  119         }
  120     }
  121 
  122     vcard_free(v);
  123 }
  124 
  125 
  126 
  127 /*
  128  * Attempt to autocomplete an address based on a partial...
  129  */
  130 void cmd_auto(char *argbuf) {
  131     char hold_rm[ROOMNAMELEN];
  132     char search_string[256];
  133     long *msglist = NULL;
  134     int num_msgs = 0;
  135     long *fts_msgs = NULL;
  136     int fts_num_msgs = 0;
  137     struct cdbdata *cdbfr;
  138     int r = 0;
  139     int i = 0;
  140     int j = 0;
  141     int search_match = 0;
  142     char *rooms_to_try[] = { USERCONTACTSROOM, ADDRESS_BOOK_ROOM };
  143         
  144     if (CtdlAccessCheck(ac_logged_in)) return;
  145     extract_token(search_string, argbuf, 0, '|', sizeof search_string);
  146     if (IsEmptyStr(search_string)) {
  147         cprintf("%d You supplied an empty partial.\n",
  148             ERROR + ILLEGAL_VALUE);
  149         return;
  150     }
  151 
  152     strcpy(hold_rm, CC->room.QRname);       /* save current room */
  153     cprintf("%d try these:\n", LISTING_FOLLOWS);
  154 
  155     /*
  156      * Gather up message pointers in rooms containing vCards
  157      */
  158     for (r=0; r < (sizeof(rooms_to_try) / sizeof(char *)); ++r) {
  159         if (CtdlGetRoom(&CC->room, rooms_to_try[r]) == 0) {
  160             cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long));
  161             if (cdbfr != NULL) {
  162                 msglist = realloc(msglist, (num_msgs * sizeof(long)) + cdbfr->len + 1);
  163                 memcpy(&msglist[num_msgs], cdbfr->ptr, cdbfr->len);
  164                 num_msgs += (cdbfr->len / sizeof(long));
  165                 cdb_free(cdbfr);
  166             }
  167         }
  168     }
  169 
  170     /*
  171      * Search-reduce the results if we have the full text index available
  172      */
  173     if (CtdlGetConfigInt("c_enable_fulltext")) {
  174         CtdlModuleDoSearch(&fts_num_msgs, &fts_msgs, search_string, "fulltext");
  175         if (fts_msgs) {
  176             for (i=0; i<num_msgs; ++i) {
  177                 search_match = 0;
  178                 for (j=0; j<fts_num_msgs; ++j) {
  179                     if (msglist[i] == fts_msgs[j]) {
  180                         search_match = 1;
  181                         j = fts_num_msgs + 1;   /* end the search */
  182                     }
  183                 }
  184                 if (!search_match) {
  185                     msglist[i] = 0;     /* invalidate this result */
  186                 }
  187             }
  188             free(fts_msgs);
  189         }
  190         else {
  191             /* If no results, invalidate the whole list */
  192             free(msglist);
  193             msglist = NULL;
  194             num_msgs = 0;
  195         }
  196     }
  197 
  198     /*
  199      * Now output the ones that look interesting
  200      */
  201     if (num_msgs > 0) for (i=0; i<num_msgs; ++i) {
  202         if (msglist[i] != 0) {
  203             hunt_for_autocomplete(msglist[i], search_string);
  204         }
  205     }
  206     
  207     cprintf("000\n");
  208     if (strcmp(CC->room.QRname, hold_rm)) {
  209         CtdlGetRoom(&CC->room, hold_rm);    /* return to saved room */
  210     }
  211 
  212     if (msglist) {
  213         free(msglist);
  214     }
  215     
  216 }
  217 
  218 
  219 CTDL_MODULE_INIT(autocompletion)
  220 {
  221     if (!threading)
  222     {
  223         CtdlRegisterProtoHook(cmd_auto, "AUTO", "Do recipient autocompletion");
  224     }
  225     /* return our module name for the log */
  226     return "autocompletion";
  227 }