Back to index

courier  0.68.2
storeinfo.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2003 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #if    HAVE_CONFIG_H
00007 #include      "config.h"
00008 #endif
00009 #if     HAVE_UNISTD_H
00010 #include        <unistd.h>
00011 #endif
00012 #include      <errno.h>
00013 #include      "imaptoken.h"
00014 #include      "imapscanclient.h"
00015 #include      "imapwrite.h"
00016 #include      "storeinfo.h"
00017 #include      "maildir/maildirquota.h"
00018 #include      "maildir/maildirmisc.h"
00019 #include      "maildir/maildircreate.h"
00020 #include      "maildir/maildiraclt.h"
00021 #include      "outbox.h"
00022 
00023 #include      <stdio.h>
00024 #include      <stdlib.h>
00025 #include      <string.h>
00026 #include      <ctype.h>
00027 #include      <fcntl.h>
00028 #include      <sys/stat.h>
00029 #if    HAVE_UTIME_H
00030 #include      <utime.h>
00031 #endif
00032 #if TIME_WITH_SYS_TIME
00033 #include      <sys/time.h>
00034 #include      <time.h>
00035 #else
00036 #if HAVE_SYS_TIME_H
00037 #include      <sys/time.h>
00038 #else
00039 #include      <time.h>
00040 #endif
00041 #endif
00042 
00043 
00044 #if SMAP
00045 extern int smapflag;
00046 #endif
00047 
00048 extern char *get_reflagged_filename(const char *fn, struct imapflags *newfl);
00049 extern int is_trash(const char *);
00050 extern int get_flagname(const char *, struct imapflags *);
00051 extern int get_flagsAndKeywords(struct imapflags *flags,
00052                             struct libmail_kwMessage **kwPtr);
00053 extern void get_message_flags( struct imapscanmessageinfo *,
00054                             char *, struct imapflags *);
00055 extern int reflag_filename(struct imapscanmessageinfo *, struct imapflags *,
00056        int);
00057 extern void fetchflags(unsigned long);
00058 extern void fetchflags_byuid(unsigned long);
00059 extern FILE *maildir_mkfilename(const char *, struct imapflags *,
00060                             unsigned long, char **, char **);
00061 extern int acl_flags_adjust(const char *access_rights,
00062                          struct imapflags *flags);
00063 
00064 extern struct imapscaninfo current_maildir_info;
00065 extern char *current_mailbox;
00066 extern char *current_mailbox_acl;
00067 extern int fastkeywords();
00068 
00069 int storeinfo_init(struct storeinfo *si)
00070 {
00071 struct imaptoken *t=currenttoken();
00072 const char *p;
00073 
00074        if (t->tokentype != IT_ATOM)       return (-1);
00075        si->plusminus=0;
00076        si->silent=0;
00077 
00078        p=t->tokenbuf;
00079        if (*p == '+' || *p == '-')
00080               si->plusminus= *p++;
00081        if (strncmp(p, "FLAGS", 5)) return (-1);
00082        p += 5;
00083        if (*p)
00084        {
00085               if (strcmp(p, ".SILENT"))   return (-1);
00086               si->silent=1;
00087        }
00088 
00089        memset(&si->flags, 0, sizeof(si->flags));
00090 
00091        if ((si->keywords=libmail_kwmCreate()) == NULL)
00092               write_error_exit(0);
00093 
00094        t=nexttoken_noparseliteral();
00095        if (t->tokentype == IT_LPAREN)
00096        {
00097               if (get_flagsAndKeywords(&si->flags, &si->keywords))
00098               {
00099                      libmail_kwmDestroy(si->keywords);
00100                      si->keywords=NULL;
00101                      return (-1);
00102               }
00103               nexttoken();
00104        }
00105        else if (t->tokentype == IT_NIL)
00106               nexttoken();
00107        else if (t->tokentype == IT_ATOM)
00108        {
00109               if (get_flagname(t->tokenbuf, &si->flags))
00110                      libmail_kwmSetName(current_maildir_info
00111                                    .keywordList,
00112                                    si->keywords,
00113                                    t->tokenbuf);
00114               nexttoken();
00115        }
00116        return (0);
00117 }
00118 
00119 int do_store(unsigned long n, int byuid, void *voidptr)
00120 {
00121 struct storeinfo *si=(struct storeinfo *)voidptr;
00122 int    fd;
00123  struct imapflags new_flags, old_flags;
00124 int changedKeywords;
00125 struct libmail_kwMessageEntry *kme;
00126 int kwAllowed=1;
00127 
00128        --n;
00129        fd=imapscan_openfile(current_mailbox, &current_maildir_info, n);
00130        if (fd < 0)   return (0);
00131 
00132        changedKeywords=0;
00133        get_message_flags(current_maildir_info.msgs+n, 0, &new_flags);
00134 
00135        old_flags=new_flags;
00136 
00137        if (current_mailbox_acl)
00138        {
00139               if (strchr(current_mailbox_acl, ACL_WRITE[0]) == NULL)
00140                      kwAllowed=0;
00141        }
00142 
00143 
00144        if (si->plusminus == '+')
00145        {
00146               if (si->flags.drafts)       new_flags.drafts=1;
00147               if (si->flags.seen)  new_flags.seen=1;
00148               if (si->flags.answered)     new_flags.answered=1;
00149               if (si->flags.deleted)      new_flags.deleted=1;
00150               if (si->flags.flagged)      new_flags.flagged=1;
00151 
00152               for (kme=si->keywords ? si->keywords->firstEntry:NULL;
00153                    kme; kme=kme->next)
00154               {
00155                      int rc;
00156 
00157                      if (!kwAllowed)
00158                      {
00159                             current_maildir_info.msgs[n].changedflags=1;
00160                             continue;
00161                      }
00162 
00163                      imapscan_createKeyword(&current_maildir_info, n);
00164 
00165                      if ((rc=libmail_kwmSet(current_maildir_info.msgs[n]
00166                                           .keywordMsg,
00167                                           kme->libmail_keywordEntryPtr))
00168                          < 0)
00169                      {
00170                             write_error_exit(0);
00171                             return 0;
00172                      }
00173 
00174                      if (rc == 0)
00175                      {
00176                             if (fastkeywords())
00177                                    changedKeywords=1;
00178                             current_maildir_info.msgs[n].changedflags=1;
00179                      }
00180               }
00181        }
00182        else if (si->plusminus == '-')
00183        {
00184               if (si->flags.drafts)       new_flags.drafts=0;
00185               if (si->flags.seen)  new_flags.seen=0;
00186               if (si->flags.answered)     new_flags.answered=0;
00187               if (si->flags.deleted)      new_flags.deleted=0;
00188               if (si->flags.flagged)      new_flags.flagged=0;
00189 
00190               if (current_maildir_info.msgs[n].keywordMsg && kwAllowed)
00191                      for (kme=si->keywords ?
00192                                  si->keywords->firstEntry:NULL;
00193                           kme; kme=kme->next)
00194                      {
00195                             if (!kwAllowed)
00196                             {
00197                                    current_maildir_info.msgs[n]
00198                                           .changedflags=1;
00199                                    continue;
00200                             }
00201 
00202                             if (libmail_kwmClear(current_maildir_info.msgs[n]
00203                                            .keywordMsg,
00204                                            kme->libmail_keywordEntryPtr)==0)
00205                             {
00206                                    if (fastkeywords())
00207                                           changedKeywords=1;
00208                                    current_maildir_info.msgs[n]
00209                                           .changedflags=1;
00210                             }
00211                      }
00212 
00213               if (current_maildir_info.msgs[n].keywordMsg &&
00214                   !current_maildir_info.msgs[n].keywordMsg->firstEntry)
00215               {
00216                      libmail_kwmDestroy(current_maildir_info.msgs[n]
00217                                          .keywordMsg);
00218                      current_maildir_info.msgs[n].keywordMsg=NULL;
00219               }
00220        }
00221        else
00222        {
00223               struct libmail_kwMessage *kw;
00224 
00225               new_flags=si->flags;
00226 
00227               kw=current_maildir_info.msgs[n].keywordMsg;
00228 
00229               if (kw && kw->firstEntry == NULL)
00230                      kw=NULL;
00231 
00232               if (si->keywords && si->keywords->firstEntry == NULL)
00233                      si->keywords=NULL;
00234 
00235               if ((si->keywords && !kw) ||
00236                   (!si->keywords && kw) ||
00237                   (si->keywords && kw && libmail_kwmCmp(si->keywords, kw)))
00238               {
00239                      if (kwAllowed)
00240                      {
00241                             kw=current_maildir_info.msgs[n].keywordMsg;
00242 
00243                             if (kw)
00244                                    libmail_kwmDestroy(kw);
00245 
00246                             current_maildir_info.msgs[n].keywordMsg=NULL;
00247 
00248                             if (si->keywords && si->keywords->firstEntry)
00249                             {
00250                                    struct libmail_kwMessageEntry *kme;
00251 
00252                                    kw=imapscan_createKeyword(&current_maildir_info,
00253                                                           n);
00254 
00255                                    for (kme=si->keywords->lastEntry; kme;
00256                                         kme=kme->prev)
00257                                           if (libmail_kwmSet(kw,
00258                                                            kme->libmail_keywordEntryPtr)
00259                                               < 0)
00260                                                  write_error_exit(0);
00261                                    current_maildir_info.msgs[n].keywordMsg=kw;
00262                             }
00263                      }
00264 
00265                      changedKeywords=1;
00266               }
00267        }
00268 
00269        if (current_mailbox_acl)
00270        {
00271               if (strchr(current_mailbox_acl, ACL_WRITE[0]) == NULL)
00272               {
00273                      new_flags.drafts=old_flags.drafts;
00274                      new_flags.answered=old_flags.answered;
00275                      new_flags.flagged=old_flags.flagged;
00276               }
00277 
00278               if (strchr(current_mailbox_acl, ACL_SEEN[0]) == NULL)
00279               {
00280                      new_flags.seen=old_flags.seen;
00281               }
00282 
00283               if (strchr(current_mailbox_acl, ACL_DELETEMSGS[0])
00284                   == NULL)
00285               {
00286                      new_flags.deleted=old_flags.deleted;
00287               }
00288        }
00289 
00290        if (changedKeywords)
00291        {
00292               current_maildir_info.msgs[n].changedflags=1;
00293               if (imapscan_updateKeywords(current_maildir_info.msgs[n]
00294                                        .filename,
00295                                        current_maildir_info.msgs[n]
00296                                        .keywordMsg))
00297               {
00298                      close(fd);
00299                      return -1;
00300               }
00301        }
00302 
00303        if (reflag_filename(current_maildir_info.msgs+n, &new_flags, fd))
00304        {
00305               close(fd);
00306               return (-1);
00307        }
00308        close(fd);
00309        if (si->silent)
00310               current_maildir_info.msgs[n].changedflags=0;
00311        else
00312        {
00313 #if SMAP
00314               /* SMAP flag notification is handled elsewhere */
00315 
00316               if (!smapflag)
00317 #endif
00318               {
00319                      if (byuid)
00320                             fetchflags_byuid(n);
00321                      else
00322                             fetchflags(n);
00323               }
00324        }
00325 
00326        return (0);
00327 }
00328 
00329 static int copy_message(int fd,
00330                      struct do_copy_info *cpy_info,
00331                      struct imapflags *flags,
00332                      struct libmail_kwMessage *keywords,
00333                      unsigned long old_uid)
00334 {
00335 char   *tmpname;
00336 char   *newname;
00337 FILE   *fp;
00338 struct stat   stat_buf;
00339 char   buf[BUFSIZ];
00340 struct uidplus_info *new_uidplus_info;
00341 
00342        if (fstat(fd, &stat_buf) < 0
00343            || (new_uidplus_info=(struct uidplus_info *)
00344               malloc(sizeof(struct uidplus_info))) == NULL)
00345        {
00346               return (-1);
00347        }
00348        memset(new_uidplus_info, 0, sizeof(*new_uidplus_info));
00349 
00350        fp=maildir_mkfilename(cpy_info->mailbox, flags, stat_buf.st_size,
00351                            &tmpname, &newname);
00352 
00353        if (!fp)
00354        {
00355               free(new_uidplus_info);
00356               return (-1);
00357        }
00358 
00359        while (stat_buf.st_size)
00360        {
00361        int    n=sizeof(buf);
00362 
00363               if (n > stat_buf.st_size)
00364                      n=stat_buf.st_size;
00365 
00366               n=read(fd, buf, n);
00367 
00368               if (n <= 0 || fwrite(buf, 1, n, fp) != n)
00369               {
00370                      fprintf(stderr,
00371                      "ERR: error copying a message, user=%s, errno=%d\n",
00372                             getenv("AUTHENTICATED"), errno);
00373 
00374                      fclose(fp);
00375                      unlink(tmpname);
00376                      free(tmpname);
00377                      free(newname);
00378                      free(new_uidplus_info);
00379                      return (-1);
00380               }
00381               stat_buf.st_size -= n;
00382        }
00383 
00384        if (fflush(fp) || ferror(fp))
00385        {
00386               fclose(fp);
00387               free(tmpname);
00388               free(newname);
00389               free(new_uidplus_info);
00390               return (-1);
00391        }
00392        fclose(fp);
00393 
00394        new_uidplus_info->mtime = stat_buf.st_mtime;
00395 
00396        if (check_outbox(tmpname, cpy_info->mailbox))
00397        {
00398               unlink(tmpname);
00399               free(tmpname);
00400               free(newname);
00401               free(new_uidplus_info);
00402               return (-1);
00403        }
00404 
00405        if (keywords && keywords->firstEntry &&
00406            maildir_kwSave(cpy_info->mailbox,
00407                         strrchr(newname, '/')+1,
00408                         keywords,
00409                         &new_uidplus_info->tmpkeywords,
00410                         &new_uidplus_info->newkeywords, 0))
00411        {
00412               unlink(tmpname);
00413               free(tmpname);
00414               free(newname);
00415               free(new_uidplus_info);
00416               perror("maildir_kwSave");
00417               return (-1);
00418        }
00419 
00420        new_uidplus_info->tmpfilename=tmpname;
00421        new_uidplus_info->curfilename=newname;
00422        new_uidplus_info->next=NULL;
00423        new_uidplus_info->old_uid=old_uid;
00424        *cpy_info->uidplus_tail=new_uidplus_info;
00425        cpy_info->uidplus_tail=&new_uidplus_info->next;
00426        return (0);
00427 }
00428 
00429 int do_copy_message(unsigned long n, int byuid, void *voidptr)
00430 {
00431        struct do_copy_info *cpy_info=(struct do_copy_info *)voidptr;
00432        int    fd;
00433        struct imapflags new_flags;
00434 
00435        --n;
00436        fd=imapscan_openfile(current_mailbox, &current_maildir_info, n);
00437        if (fd < 0)   return (0);
00438        get_message_flags(current_maildir_info.msgs+n, 0, &new_flags);
00439 
00440        if (copy_message(fd, cpy_info, &new_flags,
00441 
00442                       acl_flags_adjust(cpy_info->acls,
00443                                      &new_flags) ? NULL
00444                       : current_maildir_info.msgs[n].keywordMsg,
00445                       current_maildir_info.msgs[n].uid))
00446        {
00447               close(fd);
00448               return (-1);
00449        }
00450        close(fd);
00451        current_maildir_info.msgs[n].copiedflag=1;
00452        return (0);
00453 }
00454 
00455 int do_copy_quota_calc(unsigned long n, int byuid, void *voidptr)
00456 {
00457 struct copyquotainfo *info=(struct copyquotainfo *)voidptr;
00458 const char *filename;
00459 unsigned long nbytes;
00460 struct stat   stat_buf;
00461 int    fd;
00462 struct imapflags flags;
00463 char *ff;
00464 
00465        --n;
00466 
00467        fd=imapscan_openfile(current_mailbox, &current_maildir_info, n);
00468        if (fd < 0)   return (0);
00469        filename=current_maildir_info.msgs[n].filename;
00470 
00471        get_message_flags(&current_maildir_info.msgs[n], NULL, &flags);
00472 
00473        (void)acl_flags_adjust(info->acls, &flags);
00474 
00475        ff=get_reflagged_filename(filename, &flags);
00476 
00477        if (maildirquota_countfile(ff))
00478        {
00479               if (maildir_parsequota(ff, &nbytes))
00480               {
00481                      if (fstat(fd, &stat_buf) < 0)
00482                      {
00483                             close(fd);
00484                             free(ff);
00485                             return (0);
00486                      }
00487                      nbytes=stat_buf.st_size;
00488               }
00489               info->nbytes += nbytes;
00490               info->nfiles += 1;
00491        }
00492        close(fd);
00493        free(ff);
00494        return (0);
00495 }