Back to index

courier  0.68.2
Functions | Variables
storeinfo.c File Reference
#include <errno.h>
#include "imaptoken.h"
#include "imapscanclient.h"
#include "imapwrite.h"
#include "storeinfo.h"
#include "maildir/maildirquota.h"
#include "maildir/maildirmisc.h"
#include "maildir/maildircreate.h"
#include "maildir/maildiraclt.h"
#include "outbox.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>

Go to the source code of this file.

Functions

char * get_reflagged_filename (const char *fn, struct imapflags *newfl)
int is_trash (const char *)
int get_flagname (const char *, struct imapflags *)
int get_flagsAndKeywords (struct imapflags *flags, struct libmail_kwMessage **kwPtr)
void get_message_flags (struct imapscanmessageinfo *, char *, struct imapflags *)
int reflag_filename (struct imapscanmessageinfo *, struct imapflags *, int)
void fetchflags (unsigned long)
void fetchflags_byuid (unsigned long)
FILE * maildir_mkfilename (const char *, struct imapflags *, unsigned long, char **, char **)
int acl_flags_adjust (const char *access_rights, struct imapflags *flags)
int fastkeywords ()
int storeinfo_init (struct storeinfo *si)
int do_store (unsigned long n, int byuid, void *voidptr)
static int copy_message (int fd, struct do_copy_info *cpy_info, struct imapflags *flags, struct libmail_kwMessage *keywords, unsigned long old_uid)
int do_copy_message (unsigned long n, int byuid, void *voidptr)
int do_copy_quota_calc (unsigned long n, int byuid, void *voidptr)

Variables

char * current_mailbox
char * current_mailbox_acl

Function Documentation

int acl_flags_adjust ( const char *  access_rights,
struct imapflags flags 
)

Definition at line 3683 of file imapd.c.

{
       if (strchr(access_rights, ACL_DELETEMSGS[0]) == NULL)
              flags->deleted=0;
       if (strchr(access_rights, ACL_SEEN[0]) == NULL)
              flags->seen=0;
       if (strchr(access_rights, ACL_WRITE[0]) == NULL)
       {
              flags->answered=flags->flagged=flags->drafts=0;
              return 1;
       }
       return 0;
}

Here is the caller graph for this function:

static int copy_message ( int  fd,
struct do_copy_info cpy_info,
struct imapflags flags,
struct libmail_kwMessage keywords,
unsigned long  old_uid 
) [static]

Definition at line 329 of file storeinfo.c.

{
char   *tmpname;
char   *newname;
FILE   *fp;
struct stat   stat_buf;
char   buf[BUFSIZ];
struct uidplus_info *new_uidplus_info;

       if (fstat(fd, &stat_buf) < 0
           || (new_uidplus_info=(struct uidplus_info *)
              malloc(sizeof(struct uidplus_info))) == NULL)
       {
              return (-1);
       }
       memset(new_uidplus_info, 0, sizeof(*new_uidplus_info));

       fp=maildir_mkfilename(cpy_info->mailbox, flags, stat_buf.st_size,
                           &tmpname, &newname);

       if (!fp)
       {
              free(new_uidplus_info);
              return (-1);
       }

       while (stat_buf.st_size)
       {
       int    n=sizeof(buf);

              if (n > stat_buf.st_size)
                     n=stat_buf.st_size;

              n=read(fd, buf, n);

              if (n <= 0 || fwrite(buf, 1, n, fp) != n)
              {
                     fprintf(stderr,
                     "ERR: error copying a message, user=%s, errno=%d\n",
                            getenv("AUTHENTICATED"), errno);

                     fclose(fp);
                     unlink(tmpname);
                     free(tmpname);
                     free(newname);
                     free(new_uidplus_info);
                     return (-1);
              }
              stat_buf.st_size -= n;
       }

       if (fflush(fp) || ferror(fp))
       {
              fclose(fp);
              free(tmpname);
              free(newname);
              free(new_uidplus_info);
              return (-1);
       }
       fclose(fp);

       new_uidplus_info->mtime = stat_buf.st_mtime;

       if (check_outbox(tmpname, cpy_info->mailbox))
       {
              unlink(tmpname);
              free(tmpname);
              free(newname);
              free(new_uidplus_info);
              return (-1);
       }

       if (keywords && keywords->firstEntry &&
           maildir_kwSave(cpy_info->mailbox,
                        strrchr(newname, '/')+1,
                        keywords,
                        &new_uidplus_info->tmpkeywords,
                        &new_uidplus_info->newkeywords, 0))
       {
              unlink(tmpname);
              free(tmpname);
              free(newname);
              free(new_uidplus_info);
              perror("maildir_kwSave");
              return (-1);
       }

       new_uidplus_info->tmpfilename=tmpname;
       new_uidplus_info->curfilename=newname;
       new_uidplus_info->next=NULL;
       new_uidplus_info->old_uid=old_uid;
       *cpy_info->uidplus_tail=new_uidplus_info;
       cpy_info->uidplus_tail=&new_uidplus_info->next;
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int do_copy_message ( unsigned long  n,
int  byuid,
void *  voidptr 
)

Definition at line 429 of file storeinfo.c.

{
       struct do_copy_info *cpy_info=(struct do_copy_info *)voidptr;
       int    fd;
       struct imapflags new_flags;

       --n;
       fd=imapscan_openfile(current_mailbox, &current_maildir_info, n);
       if (fd < 0)   return (0);
       get_message_flags(current_maildir_info.msgs+n, 0, &new_flags);

       if (copy_message(fd, cpy_info, &new_flags,

                      acl_flags_adjust(cpy_info->acls,
                                     &new_flags) ? NULL
                      : current_maildir_info.msgs[n].keywordMsg,
                      current_maildir_info.msgs[n].uid))
       {
              close(fd);
              return (-1);
       }
       close(fd);
       current_maildir_info.msgs[n].copiedflag=1;
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int do_copy_quota_calc ( unsigned long  n,
int  byuid,
void *  voidptr 
)

Definition at line 455 of file storeinfo.c.

{
struct copyquotainfo *info=(struct copyquotainfo *)voidptr;
const char *filename;
unsigned long nbytes;
struct stat   stat_buf;
int    fd;
struct imapflags flags;
char *ff;

       --n;

       fd=imapscan_openfile(current_mailbox, &current_maildir_info, n);
       if (fd < 0)   return (0);
       filename=current_maildir_info.msgs[n].filename;

       get_message_flags(&current_maildir_info.msgs[n], NULL, &flags);

       (void)acl_flags_adjust(info->acls, &flags);

       ff=get_reflagged_filename(filename, &flags);

       if (maildirquota_countfile(ff))
       {
              if (maildir_parsequota(ff, &nbytes))
              {
                     if (fstat(fd, &stat_buf) < 0)
                     {
                            close(fd);
                            free(ff);
                            return (0);
                     }
                     nbytes=stat_buf.st_size;
              }
              info->nbytes += nbytes;
              info->nfiles += 1;
       }
       close(fd);
       free(ff);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int do_store ( unsigned long  n,
int  byuid,
void *  voidptr 
)

Definition at line 119 of file storeinfo.c.

{
struct storeinfo *si=(struct storeinfo *)voidptr;
int    fd;
 struct imapflags new_flags, old_flags;
int changedKeywords;
struct libmail_kwMessageEntry *kme;
int kwAllowed=1;

       --n;
       fd=imapscan_openfile(current_mailbox, &current_maildir_info, n);
       if (fd < 0)   return (0);

       changedKeywords=0;
       get_message_flags(current_maildir_info.msgs+n, 0, &new_flags);

       old_flags=new_flags;

       if (current_mailbox_acl)
       {
              if (strchr(current_mailbox_acl, ACL_WRITE[0]) == NULL)
                     kwAllowed=0;
       }


       if (si->plusminus == '+')
       {
              if (si->flags.drafts)       new_flags.drafts=1;
              if (si->flags.seen)  new_flags.seen=1;
              if (si->flags.answered)     new_flags.answered=1;
              if (si->flags.deleted)      new_flags.deleted=1;
              if (si->flags.flagged)      new_flags.flagged=1;

              for (kme=si->keywords ? si->keywords->firstEntry:NULL;
                   kme; kme=kme->next)
              {
                     int rc;

                     if (!kwAllowed)
                     {
                            current_maildir_info.msgs[n].changedflags=1;
                            continue;
                     }

                     imapscan_createKeyword(&current_maildir_info, n);

                     if ((rc=libmail_kwmSet(current_maildir_info.msgs[n]
                                          .keywordMsg,
                                          kme->libmail_keywordEntryPtr))
                         < 0)
                     {
                            write_error_exit(0);
                            return 0;
                     }

                     if (rc == 0)
                     {
                            if (fastkeywords())
                                   changedKeywords=1;
                            current_maildir_info.msgs[n].changedflags=1;
                     }
              }
       }
       else if (si->plusminus == '-')
       {
              if (si->flags.drafts)       new_flags.drafts=0;
              if (si->flags.seen)  new_flags.seen=0;
              if (si->flags.answered)     new_flags.answered=0;
              if (si->flags.deleted)      new_flags.deleted=0;
              if (si->flags.flagged)      new_flags.flagged=0;

              if (current_maildir_info.msgs[n].keywordMsg && kwAllowed)
                     for (kme=si->keywords ?
                                 si->keywords->firstEntry:NULL;
                          kme; kme=kme->next)
                     {
                            if (!kwAllowed)
                            {
                                   current_maildir_info.msgs[n]
                                          .changedflags=1;
                                   continue;
                            }

                            if (libmail_kwmClear(current_maildir_info.msgs[n]
                                           .keywordMsg,
                                           kme->libmail_keywordEntryPtr)==0)
                            {
                                   if (fastkeywords())
                                          changedKeywords=1;
                                   current_maildir_info.msgs[n]
                                          .changedflags=1;
                            }
                     }

              if (current_maildir_info.msgs[n].keywordMsg &&
                  !current_maildir_info.msgs[n].keywordMsg->firstEntry)
              {
                     libmail_kwmDestroy(current_maildir_info.msgs[n]
                                         .keywordMsg);
                     current_maildir_info.msgs[n].keywordMsg=NULL;
              }
       }
       else
       {
              struct libmail_kwMessage *kw;

              new_flags=si->flags;

              kw=current_maildir_info.msgs[n].keywordMsg;

              if (kw && kw->firstEntry == NULL)
                     kw=NULL;

              if (si->keywords && si->keywords->firstEntry == NULL)
                     si->keywords=NULL;

              if ((si->keywords && !kw) ||
                  (!si->keywords && kw) ||
                  (si->keywords && kw && libmail_kwmCmp(si->keywords, kw)))
              {
                     if (kwAllowed)
                     {
                            kw=current_maildir_info.msgs[n].keywordMsg;

                            if (kw)
                                   libmail_kwmDestroy(kw);

                            current_maildir_info.msgs[n].keywordMsg=NULL;

                            if (si->keywords && si->keywords->firstEntry)
                            {
                                   struct libmail_kwMessageEntry *kme;

                                   kw=imapscan_createKeyword(&current_maildir_info,
                                                          n);

                                   for (kme=si->keywords->lastEntry; kme;
                                        kme=kme->prev)
                                          if (libmail_kwmSet(kw,
                                                           kme->libmail_keywordEntryPtr)
                                              < 0)
                                                 write_error_exit(0);
                                   current_maildir_info.msgs[n].keywordMsg=kw;
                            }
                     }

                     changedKeywords=1;
              }
       }

       if (current_mailbox_acl)
       {
              if (strchr(current_mailbox_acl, ACL_WRITE[0]) == NULL)
              {
                     new_flags.drafts=old_flags.drafts;
                     new_flags.answered=old_flags.answered;
                     new_flags.flagged=old_flags.flagged;
              }

              if (strchr(current_mailbox_acl, ACL_SEEN[0]) == NULL)
              {
                     new_flags.seen=old_flags.seen;
              }

              if (strchr(current_mailbox_acl, ACL_DELETEMSGS[0])
                  == NULL)
              {
                     new_flags.deleted=old_flags.deleted;
              }
       }

       if (changedKeywords)
       {
              current_maildir_info.msgs[n].changedflags=1;
              if (imapscan_updateKeywords(current_maildir_info.msgs[n]
                                       .filename,
                                       current_maildir_info.msgs[n]
                                       .keywordMsg))
              {
                     close(fd);
                     return -1;
              }
       }

       if (reflag_filename(current_maildir_info.msgs+n, &new_flags, fd))
       {
              close(fd);
              return (-1);
       }
       close(fd);
       if (si->silent)
              current_maildir_info.msgs[n].changedflags=0;
       else
       {
#if SMAP
              /* SMAP flag notification is handled elsewhere */

              if (!smapflag)
#endif
              {
                     if (byuid)
                            fetchflags_byuid(n);
                     else
                            fetchflags(n);
              }
       }

       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int fastkeywords ( )

Definition at line 56 of file capability.c.

{
       return capa_keywords == 1;
}

Here is the caller graph for this function:

void fetchflags ( unsigned  long)

Definition at line 451 of file fetch.c.

{
#if SMAP
       if (smapflag)
       {
              writes("* FETCH ");
              writen(n+1);
       }
       else
#endif
       {
              writes("* ");
              writen(n+1);
              writes(" FETCH (");
       }

       doflags(0, 0, &current_maildir_info, n, 0);

#if SMAP
       if (smapflag)
       {
              writes("\n");
       }
       else
#endif
              writes(")\r\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void fetchflags_byuid ( unsigned  long)

Definition at line 479 of file fetch.c.

{
       writes("* ");
       writen(n+1);
       writes(" FETCH (");
       uid(0, 0, &current_maildir_info, n, 0);
       writes(" ");
       doflags(0, 0, &current_maildir_info, n, 0);
       writes(")\r\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

int get_flagname ( const char *  ,
struct imapflags  
)

Definition at line 417 of file imapd.c.

{
       if (strcasecmp(p, "\\SEEN") == 0)
              flags->seen=1;
       else if (strcasecmp(p, "\\ANSWERED") == 0)
              flags->answered=1;
       else if (strcasecmp(p, "\\DRAFT") == 0)
              flags->drafts=1;
       else if (strcasecmp(p, "\\DELETED") == 0)
              flags->deleted=1;
       else if (strcasecmp(p, "\\FLAGGED") == 0)
              flags->flagged=1;
       else return (-1);
       return (0);
}

Here is the caller graph for this function:

int get_flagsAndKeywords ( struct imapflags flags,
struct libmail_kwMessage **  kwPtr 
)

Definition at line 460 of file imapd.c.

{
struct imaptoken *t;

       while ((t=nexttoken_nouc())->tokentype == IT_ATOM)
       {
              if (get_flagname(t->tokenbuf, flags))
              {
                     if (!valid_keyword(t->tokenbuf))
                            return -1;

                     if (get_keyword(kwPtr, t->tokenbuf))
                            return -1;
              }
       }
       return (t->tokentype == IT_RPAREN ? 0:-1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void get_message_flags ( struct imapscanmessageinfo ,
char *  ,
struct imapflags  
)

Definition at line 479 of file imapd.c.

{
       const char *filename=mi->filename;

       const char *DRAFT="\\Draft";
       const char *FLAGGED="\\Flagged";
       const char *REPLIED="\\Answered";
       const char *SEEN="\\Seen";
       const char *DELETED="\\Deleted";
       const char *RECENT="\\Recent";

       const char *SPC=" ";

       if (buf)
              *buf=0;

       if (flags)
              flags->seen=flags->answered=flags->deleted=flags->flagged
              =flags->recent=flags->drafts=0;

       if ((filename=strrchr(filename, MDIRSEP[0])) == 0
              || strncmp(filename, MDIRSEP "2,", 3))    return;

#if SMAP
       if (smapflag)
       {
              SPC=",";
              DRAFT="DRAFT";
              FLAGGED="MARKED";
              REPLIED="REPLIED";
              SEEN="SEEN";
              DELETED="DELETED";
              RECENT="RECENT";
       }
#endif

       if (strchr(filename, 'D'))
       {
              if (buf) strcat(buf, DRAFT);
              if (flags)  flags->drafts=1;
       }

       if (strchr(filename, 'F'))
       {
              if (buf) strcat(strcat(buf, *buf ? SPC:""), FLAGGED);
              if (flags)    flags->flagged=1;
       }
       if (strchr(filename, 'R'))
       {
              if (buf) strcat(strcat(buf, *buf ? SPC:""), REPLIED);
              if (flags)    flags->answered=1;
       }

       if (strchr(filename, 'S') != NULL)
       {
              if (buf) strcat(strcat(buf, *buf ? SPC:""), SEEN);
              if (flags)    flags->seen=1;
       }

       if (strchr(filename, 'T'))
       {
              if (buf) strcat(strcat(buf, *buf ? SPC:""), DELETED);
              if (flags)    flags->deleted=1;
       }

       if (mi->recentflag)
       {
              if (flags) flags->recent=1;
              if (buf) strcat(strcat(buf, *buf ? SPC:""), RECENT);
       }
}
char* get_reflagged_filename ( const char *  fn,
struct imapflags newfl 
)

Definition at line 164 of file fetch.c.

{
       char *p=malloc(strlen(fn)+20);
       char *q;

       if (!p)       write_error_exit(0);
       strcpy(p, fn);
       if ((q=strrchr(p, MDIRSEP[0])) != 0)      *q=0;
       strcat(p, MDIRSEP "2,");
       append_flags(p, newflags);
       return p;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int is_trash ( const char *  )

Definition at line 217 of file imapd.c.

{
       if (strcmp(m, dot_trash))
       {
              /*
               * not trying to delete .Trash but folder inside of .Trash
               */
              return (0);
       }
       else
       {
              /*
               * trying to delete .Trash - stop them
               */
              return (1);
       }
}
FILE* maildir_mkfilename ( const char *  ,
struct imapflags ,
unsigned  long,
char **  ,
char **   
)

Definition at line 608 of file imapd.c.

{
       char   *p;
       char   uniqbuf[80];
       static unsigned uniqcnt=0;
       FILE   *fp;
       struct maildir_tmpcreate_info createInfo;

       sprintf(uniqbuf, "%u", uniqcnt++);

       maildir_tmpcreate_init(&createInfo);
       createInfo.openmode=0666;
       createInfo.maildir=mailbox;
       createInfo.uniq=uniqbuf;
       createInfo.msgsize=s;
       createInfo.hostname=getenv("HOSTNAME");
       createInfo.doordie=1;

       if ((fp=maildir_tmpcreate_fp(&createInfo)) == NULL)
              return NULL;

       *tmpname=createInfo.tmpname;
       *newname=createInfo.newname;

       createInfo.tmpname=NULL;
       createInfo.newname=NULL;
       maildir_tmpcreate_free(&createInfo);

       strcpy(uniqbuf, MDIRSEP "2,");
       append_flags(uniqbuf, flags);

       /* Ok, this message will really go to cur, not new */

       p=malloc(strlen(*newname)+strlen(uniqbuf)+1);
       if (!p)       write_error_exit(0);
       strcpy(p, *newname);
       memcpy(strrchr(p, '/')-3, "cur", 3);      /* HACK OF THE MILLENIA */
       strcat(p, uniqbuf);
       free(*newname);
       *newname=p;
       return fp;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int reflag_filename ( struct imapscanmessageinfo ,
struct imapflags ,
int   
)

Definition at line 177 of file fetch.c.

{
char    *p, *q, *r;
int    rc=0;
struct imapflags old_flags;
struct stat   stat_buf;

       get_message_flags(mi, 0, &old_flags);

       p=get_reflagged_filename(mi->filename, flags);

       q=malloc(strlen(current_mailbox)+strlen(mi->filename)+sizeof("/cur/"));
       r=malloc(strlen(current_mailbox)+strlen(p)+sizeof("/cur/"));
       if (!q || !r) write_error_exit(0);
       strcat(strcat(strcpy(q, current_mailbox), "/cur/"), mi->filename);
       strcat(strcat(strcpy(r, current_mailbox), "/cur/"), p);
       if (strcmp(q, r))
       {
              if (maildirquota_countfolder(current_mailbox)
                     && old_flags.deleted != flags->deleted
                     && fstat(fd, &stat_buf) == 0)
              {
                     struct maildirsize quotainfo;
                     int64_t       nbytes;
                     unsigned long unbytes;
                     int    nmsgs=1;

                     if (maildir_parsequota(mi->filename, &unbytes) == 0)
                            nbytes=unbytes;
                     else
                            nbytes=stat_buf.st_size;
                     if ( flags->deleted )
                     {
                            nbytes= -nbytes;
                            nmsgs= -nmsgs;
                     }

                     if ( maildir_quota_delundel_start(current_mailbox,
                                                   &quotainfo,
                                                   nbytes, nmsgs))
                            rc= -1;
                     else
                            maildir_quota_delundel_end(&quotainfo,
                                                    nbytes, nmsgs);
              }

              if (rc == 0)
                     rename(q, r);

#if SMAP
              snapshot_needed();
#endif
       }
       free(q);
       free(r);
       free(mi->filename);
       mi->filename=p;

#if 0
       if (is_sharedsubdir(current_mailbox))
              maildir_shared_updateflags(current_mailbox, p);
#endif

       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int storeinfo_init ( struct storeinfo si)

Definition at line 69 of file storeinfo.c.

{
struct imaptoken *t=currenttoken();
const char *p;

       if (t->tokentype != IT_ATOM)       return (-1);
       si->plusminus=0;
       si->silent=0;

       p=t->tokenbuf;
       if (*p == '+' || *p == '-')
              si->plusminus= *p++;
       if (strncmp(p, "FLAGS", 5)) return (-1);
       p += 5;
       if (*p)
       {
              if (strcmp(p, ".SILENT"))   return (-1);
              si->silent=1;
       }

       memset(&si->flags, 0, sizeof(si->flags));

       if ((si->keywords=libmail_kwmCreate()) == NULL)
              write_error_exit(0);

       t=nexttoken_noparseliteral();
       if (t->tokentype == IT_LPAREN)
       {
              if (get_flagsAndKeywords(&si->flags, &si->keywords))
              {
                     libmail_kwmDestroy(si->keywords);
                     si->keywords=NULL;
                     return (-1);
              }
              nexttoken();
       }
       else if (t->tokentype == IT_NIL)
              nexttoken();
       else if (t->tokentype == IT_ATOM)
       {
              if (get_flagname(t->tokenbuf, &si->flags))
                     libmail_kwmSetName(current_maildir_info
                                   .keywordList,
                                   si->keywords,
                                   t->tokenbuf);
              nexttoken();
       }
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 124 of file imapd.c.

Definition at line 135 of file imapd.c.