Back to index

courier  0.68.2
maildirkeywords3.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2003 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #if    HAVE_CONFIG_H
00007 #include      "config.h"
00008 #endif
00009 #include      <stdio.h>
00010 #include      <stdlib.h>
00011 #include      <string.h>
00012 #include      <errno.h>
00013 #include      <ctype.h>
00014 
00015 #include      "maildirkeywords.h"
00016 
00017 void libmail_kwgInit(struct libmail_kwGeneric *g)
00018 {
00019        memset(g, 0, sizeof(*g));
00020        libmail_kwhInit(&g->kwHashTable);
00021 }
00022 
00023 int libmail_kwgDestroy(struct libmail_kwGeneric *g)
00024 {
00025        struct libmail_kwGenericEntry *p;
00026        size_t n;
00027 
00028        for (n=0; n<sizeof(g->messageHashTable)/sizeof(g->messageHashTable[0]);
00029             n++)
00030               while ((p=g->messageHashTable[n]) != NULL)
00031               {
00032                      g->messageHashTable[n]=p->next;
00033                      if (p->filename)
00034                             free(p->filename);
00035                      if (p->keywords)
00036                             libmail_kwmDestroy(p->keywords);
00037                      free(p);
00038               }
00039 
00040        if (g->messages)
00041               free(g->messages);
00042        g->messages=NULL;
00043        g->nMessages=0;
00044        g->messagesValid=0;
00045        return libmail_kwhCheck(&g->kwHashTable);
00046 }
00047 
00048 static unsigned filenameHash(const char *fn)
00049 {
00050        unsigned long hashBucket=0;
00051 
00052        while (*fn && *fn != MDIRSEP[0])
00053        {
00054               hashBucket=(hashBucket << 1) ^ (hashBucket & 0x8000 ? 0x1301:0)
00055                      ^ (unsigned char)*fn++;
00056        }
00057 
00058        return hashBucket & 0xFFFF;
00059 }
00060 
00061 static int filenameCmp(const char *a, const char *b)
00062 {
00063        char ca, cb;
00064 
00065        while ( (ca= *a == MDIRSEP[0] ? 0:*a)
00066               == (cb= *b == MDIRSEP[0] ? 0:*b) && ca)
00067        {
00068               ++a;
00069               ++b;
00070        }
00071 
00072        return (ca < cb ? -1:ca > cb ? 1:0);
00073 }
00074 
00075 static int srch(struct libmail_kwGeneric *g, const char *filename,
00076               struct libmail_kwGenericEntry ***ret)
00077 {
00078        struct libmail_kwGenericEntry **p;
00079 
00080        for (p= &g->messageHashTable[filenameHash(filename) %
00081                                  (sizeof(g->messageHashTable)
00082                                   /sizeof(g->messageHashTable[0]))];
00083             *p; p= &(*p)->next)
00084        {
00085               int cmp=filenameCmp( (*p)->filename, filename);
00086 
00087               if (cmp == 0)
00088               {
00089                      *ret=p;
00090                      return 0;
00091               }
00092 
00093               if (cmp > 0)
00094                      break;
00095        }
00096 
00097        *ret=p;
00098        return -1;
00099 }
00100 
00101 struct libmail_kwGenericEntry *
00102 libmail_kwgFindByName(struct libmail_kwGeneric *g, const char *filename)
00103 {
00104        const char *p=strrchr(filename, '/');
00105        struct libmail_kwGenericEntry **ret;
00106 
00107        if (p)
00108               filename=p+1;
00109 
00110        if (srch(g, filename, &ret) == 0)
00111               return *ret;
00112 
00113        return NULL;
00114 }
00115 
00116 struct libmail_kwGenericEntry *
00117 libmail_kwgFindByIndex(struct libmail_kwGeneric *g, size_t n)
00118 {
00119        if (!g->messagesValid || n >= g->nMessages)
00120               return NULL;
00121 
00122        return g->messages[n];
00123 }
00124 
00125 /***************************************************************************/
00126 
00127 static struct libmail_kwMessage **g_findMessageByFilename(const char
00128                                                    *filename,
00129                                                    int autocreate,
00130                                                    size_t *indexNum,
00131                                                    void *voidarg);
00132 static size_t g_getMessageCount(void *voidarg);
00133 
00134 static struct libmail_kwMessage **g_findMessageByIndex(size_t indexNum,
00135                                                  int autocreate,
00136                                                  void *voidarg);
00137 
00138 static const char *g_getMessageFilename(size_t n, void *voidarg);
00139 
00140 static struct libmail_kwHashtable *g_getKeywordHashtable(void *voidarg);
00141 
00142 static void g_updateKeywords(size_t n, struct libmail_kwMessage *kw,
00143                           void *voidarg);
00144 static int g_validIndex(struct libmail_kwGeneric *g);
00145 
00146 int libmail_kwgReadMaildir(struct libmail_kwGeneric *g,
00147                         const char *maildir)
00148 {
00149        struct maildir_kwReadInfo ri;
00150 
00151        memset(&ri, 0, sizeof(ri));
00152 
00153        ri.findMessageByFilename= &g_findMessageByFilename;
00154        ri.getMessageCount= &g_getMessageCount;
00155        ri.findMessageByIndex= &g_findMessageByIndex;
00156        ri.getMessageFilename= &g_getMessageFilename;
00157        ri.getKeywordHashtable= &g_getKeywordHashtable;
00158        ri.updateKeywords=&g_updateKeywords;
00159        ri.voidarg=g;
00160 
00161        if (maildir_kwRead(maildir, &ri) < 0)
00162        {
00163               libmail_kwgDestroy(g);
00164               return -1;
00165        }
00166 
00167        if (ri.tryagain)
00168        {
00169               libmail_kwgDestroy(g); /* Free memory */
00170               return 1;
00171        }
00172 
00173        if (g_validIndex(g) < 0)
00174        {
00175               libmail_kwgDestroy(g); /* Free memory */
00176               return -1;
00177        }
00178        return 0;
00179 }
00180 
00181 static struct libmail_kwGenericEntry *g_create(const char *filename)
00182 {
00183        struct libmail_kwGenericEntry *e=
00184               malloc(sizeof (struct libmail_kwGenericEntry));
00185        char *p;
00186 
00187        if (e && (e->filename=strdup(filename)) == NULL)
00188        {
00189               free(e);
00190               e=NULL;
00191        }
00192 
00193        if (!e)
00194               return NULL;
00195 
00196        e->keywords=NULL;
00197 
00198        if ((p=strrchr(e->filename, MDIRSEP[0])) != 0)
00199               *p=0;
00200        return e;
00201 }
00202 
00203 static struct libmail_kwMessage **g_findMessageByFilename(const char
00204                                                    *filename,
00205                                                    int autocreate,
00206                                                    size_t *indexNum,
00207                                                    void *voidarg)
00208 {
00209        struct libmail_kwGeneric *g=(struct libmail_kwGeneric *)voidarg;
00210        const char *p=strrchr(filename, '/');
00211        struct libmail_kwGenericEntry **ret;
00212 
00213        if (p)
00214               filename=p+1;
00215 
00216        if (srch(g, filename, &ret))
00217        {
00218               struct libmail_kwGenericEntry *n;
00219 
00220               n=g_create(filename);
00221               if (!n)
00222                      return NULL;
00223 
00224               g->messagesValid=0;
00225               n->messageNum= g->nMessages++;
00226 
00227               n->next= *ret;
00228               *ret=n;
00229        }
00230 
00231        if (indexNum)
00232               *indexNum=(*ret)->messageNum;
00233 
00234        if ( (*ret)->keywords == NULL && autocreate)
00235               (*ret)->keywords=libmail_kwmCreate();
00236 
00237        return & (*ret)->keywords;
00238 }
00239 
00240 static size_t g_getMessageCount(void *voidarg)
00241 {
00242        struct libmail_kwGeneric *g=(struct libmail_kwGeneric *)voidarg;
00243 
00244        return g->nMessages;
00245 }
00246 
00247 static int g_validIndex(struct libmail_kwGeneric *g)
00248 {
00249        struct libmail_kwGenericEntry *p;
00250        size_t n;
00251 
00252        if (g->messagesValid)
00253               return 0;
00254 
00255        if (g->messages)
00256               free(g->messages);
00257        g->messages=NULL;
00258 
00259        if (g->nMessages == 0)
00260        {
00261               g->messagesValid=1;
00262               return 0;
00263        }
00264 
00265        if ((g->messages=malloc(g->nMessages * sizeof(*g->messages)))
00266            == NULL)
00267               return -1;
00268 
00269        for (n=0; n<sizeof(g->messageHashTable)/sizeof(g->messageHashTable[0]);
00270             n++)
00271               for (p=g->messageHashTable[n]; p; p=p->next)
00272                      g->messages[p->messageNum]=p;
00273 
00274        g->messagesValid=1;
00275 
00276        return 0;
00277 }
00278 
00279 static struct libmail_kwMessage **g_findMessageByIndex(size_t indexNum,
00280                                                  int autocreate,
00281                                                  void *voidarg)
00282 {
00283        struct libmail_kwGeneric *g=(struct libmail_kwGeneric *)voidarg;
00284 
00285        if (g_validIndex(g))
00286               return NULL;
00287 
00288        if (indexNum >= g->nMessages)
00289               return NULL;
00290 
00291        if ( g->messages[indexNum]->keywords == NULL && autocreate)
00292               g->messages[indexNum]->keywords=libmail_kwmCreate();
00293 
00294        return &g->messages[indexNum]->keywords;
00295 }
00296 
00297 static const char *g_getMessageFilename(size_t indexNum, void *voidarg)
00298 {
00299        struct libmail_kwGeneric *g=(struct libmail_kwGeneric *)voidarg;
00300 
00301        if (g_validIndex(g))
00302               return NULL;
00303 
00304        if (indexNum >= g->nMessages)
00305               return NULL;
00306 
00307        return g->messages[indexNum]->filename;
00308 }
00309 
00310 static struct libmail_kwHashtable *g_getKeywordHashtable(void *voidarg)
00311 {
00312        struct libmail_kwGeneric *g=(struct libmail_kwGeneric *)voidarg;
00313 
00314        return &g->kwHashTable;
00315 }
00316 
00317 static void g_updateKeywords(size_t indexNum, struct libmail_kwMessage *kw,
00318                           void *voidarg)
00319 {
00320        struct libmail_kwGeneric *g=(struct libmail_kwGeneric *)voidarg;
00321 
00322        if (g_validIndex(g))
00323               return;
00324 
00325        if (indexNum >= g->nMessages)
00326               return;
00327 
00328        if ( g->messages[indexNum]->keywords)
00329               libmail_kwmDestroy(g->messages[indexNum]->keywords);
00330 
00331        g->messages[indexNum]->keywords=kw;
00332 }