Back to index

courier  0.68.2
Classes | Functions | Variables
maildirinfo.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "config.h"
#include "maildirinfo.h"
#include "maildirmisc.h"
#include "maildirnewshared.h"
#include "unicode/unicode.h"

Go to the source code of this file.

Classes

struct  imap_find_shared
struct  get_existing_folder_info

Functions

void maildir_info_destroy (struct maildir_info *info)
static int imap_find_cb (struct maildir_newshared_enum_cb *cb)
int maildir_info_imap_find (struct maildir_info *info, const char *path, const char *myId)
static char * smaptoUtf7 (char **ptr)
char ** maildir_smapfn_fromutf7 (const char *modutf7)
void maildir_smapfn_free (char **fn)
static void get_existing_callback (const char *f, void *vp)
static char * smap_path (const char *homedir, char **words)
int maildir_info_smap_find (struct maildir_info *info, char **folder, const char *myId)
void maildir_info_munge_complex (int f)
static size_t munge_complex (const char *, char *)
char * maildir_info_imapmunge (const char *name)

Variables

static int complex_flag

Class Documentation

struct imap_find_shared

Definition at line 55 of file maildirinfo.c.

Collaboration diagram for imap_find_shared:
Class Members
char * homedir
struct maildir_info * info
char * maildir
const char * path
size_t path_l
struct get_existing_folder_info

Definition at line 544 of file maildirinfo.c.

Class Members
char ** fn
char * pathname

Function Documentation

static void get_existing_callback ( const char *  f,
void *  vp 
) [static]

Definition at line 549 of file maildirinfo.c.

{
       char **fn;

       struct get_existing_folder_info *gefi=
              (struct get_existing_folder_info *)vp;
       size_t i;
       size_t j;

       if (gefi->pathname)
              return;

       fn=maildir_smapfn_fromutf7(f);
       if (!fn)
       {
              perror(f);
              return;
       }

       for (i=0; gefi->fn[i]; i++)
              if (fn[i] == NULL || strcmp(fn[i], gefi->fn[i]))
              {
                     maildir_smapfn_free(fn);
                     return;
              }

       maildir_smapfn_free(fn);

       for (j=0; i && f[j]; j++)
              if (f[j] == '.' && f[j+1] && f[j+1] != '.')
              {
                     --i;
                     if (i == 0)
                            break;
              }

       gefi->pathname=malloc(j+1);

       if (!gefi->pathname)
       {
              perror("malloc");
              return;
       }

       memcpy(gefi->pathname, f, j);
       gefi->pathname[j]=0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int imap_find_cb ( struct maildir_newshared_enum_cb cb) [static]

Definition at line 63 of file maildirinfo.c.

{
       struct imap_find_shared *ifs=(struct imap_find_shared *)cb->cb_arg;

       if (cb->homedir)
       {
              ifs->homedir=strdup(cb->homedir);
              if (!ifs->homedir)
                     return -1;
       }

       if (cb->maildir)
       {
              ifs->maildir=strdup(cb->maildir);

              if (!ifs->maildir)
              {
                     if (cb->homedir)
                     {
                            free(ifs->homedir);
                            ifs->homedir=NULL;
                     }
                     return -1;
              }
       }

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void maildir_info_destroy ( struct maildir_info info)

Definition at line 42 of file maildirinfo.c.

{
       if (info->homedir)
              free(info->homedir);
       if (info->maildir)
              free(info->maildir);
       if (info->owner)
              free(info->owner);
       info->homedir=NULL;
       info->maildir=NULL;
       info->owner=NULL;
}

Here is the caller graph for this function:

int maildir_info_imap_find ( struct maildir_info info,
const char *  path,
const char *  myId 
)

Definition at line 92 of file maildirinfo.c.

{
       const char *p;
       struct imap_find_shared ifs;
       const char *indexfile;
       char *indexfile_cpy;
       struct maildir_shindex_cache *curcache;
       const char *subhierarchy;

       info->homedir=NULL;
       info->maildir=NULL;
       info->owner=NULL;

       if (strchr(path, '/'))
       {
              errno=EINVAL;
              return -1;
       }

       for (p=path; *p; p++)
              if (*p == '.' && p[1] == '.')
              {
                     errno=EINVAL;
                     return -1;
              }

       if (strncmp(path, SHARED, sizeof(SHARED)-1) == 0)
       {
              path += sizeof(SHARED)-1;

              info->homedir=strdup(".");
              if (!info->homedir)
                     return -1;

              info->mailbox_type=MAILBOXTYPE_OLDSHARED;
              info->owner=strdup("anonymous");

              if (!info->owner)
              {
                     maildir_info_destroy(info);
                     return -1;
              }

              /* We need to specialcase "shared" and "shared.name".
              ** maildir_shareddir will return NULL for these cases, because
              ** it will insist on "name.folder", but we need to return a
              ** non NULL value to indicate that this is a valid hierarchy
              ** name.  We return a special value of an empty string, which
              ** is checked for in situations where a valid folder is
              ** required.
              */

              if (*path && *path != '.')
              {
                     maildir_info_destroy(info);
                     errno=EINVAL;
                     return -1;
              }

              return 0;
       }

       if (strncasecmp(path, INBOX, sizeof(INBOX)-1) == 0)
       {
              switch (path[sizeof(INBOX)-1]) {
              case 0:
              case '.':
                     break;
              default:
                     errno=EINVAL;
                     return -1;
              }

              info->homedir=strdup(".");

              if (!info->homedir)
                     return -1;

              info->maildir=strdup(path);
              if (!info->maildir)
              {
                     maildir_info_destroy(info);
                     return -1;
              }

              info->owner=malloc(strlen(myId)+sizeof("user="));

              if (!info->owner)
              {
                     maildir_info_destroy(info);
                     return -1;
              }

              info->mailbox_type=MAILBOXTYPE_INBOX;
              strcat(strcpy(info->owner, "user="), myId);
              return 0;
       }

       if (strncmp(path, NEWSHARED,
                  sizeof(NEWSHARED)-1) != 0)
       {
              errno=EINVAL;
              return -1;
       }

       ifs.info=info;
       ifs.path=path+sizeof(NEWSHARED)-1;

       info->mailbox_type=MAILBOXTYPE_NEWSHARED;
       info->homedir=NULL;
       info->maildir=NULL;
       info->owner=strdup("vendor=courier.internal");

       if (!info->owner)
              return -1;

       ifs.homedir=NULL;
       ifs.maildir=NULL;

       indexfile=NULL;
       indexfile_cpy=NULL;
       curcache=NULL;
       subhierarchy=NULL;

       while (*ifs.path)
       {
              int rc, eof;
              size_t i;

              curcache=maildir_shared_cache_read(curcache, indexfile,
                                             subhierarchy);

              if (indexfile_cpy)
              {
                     free(indexfile_cpy);
                     indexfile_cpy=NULL;
              }

              if (!curcache)
                     break;

              p=strchr(ifs.path, '.');

              if (p)
                     ifs.path_l=p-ifs.path;
              else
                     ifs.path_l=strlen(ifs.path);


              if (ifs.homedir)
                     free(ifs.homedir);
              if (ifs.maildir)
                     free(ifs.maildir);

              ifs.homedir=NULL;
              ifs.maildir=NULL;

              for (i=0; i < curcache->nrecords; i++)
              {
                     char *n=maildir_info_imapmunge(curcache->
                                                 records[i].name);

                     if (n == NULL)
                     {
                            i=curcache->nrecords;
                            break;
                     }

                     if (strlen(n) == ifs.path_l &&
                         strncmp(n, ifs.path, ifs.path_l) == 0)
                     {
                            free(n);
                            break;
                     }
                     free(n);
              }

              if (i >= curcache->nrecords)
                     break;

              curcache->indexfile.startingpos=
                     curcache->records[i].offset;
              rc=maildir_newshared_nextAt(&curcache->indexfile,
                                       &eof,
                                       imap_find_cb, &ifs);

              if (rc || eof)
              {
                     fprintf(stderr, "ERR: Internal error -"
                            " maildir_newshared_nextAt: %s\n",
                            strerror(errno));
                     fflush(stderr);
                     break;
              }

              if (!ifs.homedir && !ifs.maildir)
                     break;

              if (!ifs.homedir)
              {
                     indexfile=indexfile_cpy=ifs.maildir;
                     ifs.maildir=NULL;
                     subhierarchy=curcache->records[i].name;

                     ifs.path += ifs.path_l;
                     if (*ifs.path)
                            ++ifs.path;
                     continue;
              }

              info->homedir=maildir_location(ifs.homedir,
                                        ifs.maildir);

              free(ifs.homedir);
              free(ifs.maildir);

              free(info->owner);

              if (!info->homedir)
              {
                     info->maildir=NULL;
                     info->owner=NULL;
                     return -1;
              }

              if (!subhierarchy || !*subhierarchy)
              {
                     info->owner=strdup("vendor=courier.internal");
                     if (!info->owner)
                     {
                            free(info->homedir);
                            info->homedir=NULL;
                            info->maildir=NULL;
                            return -1;
                     }
              }
              else
              {
                     char *owner_utf8;

                     info->owner=malloc(strlen(subhierarchy)
                                      +sizeof("user="));

                     if (!info->owner)
                     {
                            free(info->homedir);
                            info->homedir=NULL;
                            info->maildir=NULL;
                            info->owner=NULL;
                            return -1;
                     }
                     strcpy(info->owner, "user=");
                     strcat(info->owner, subhierarchy);

                     /*
                     ** The folder path is in modified-UTF7.  The owner is
                     ** obtained from shared hierarchy, but in ACL2 the
                     ** identifiers are in UTF8.
                     */

                     owner_utf8=
                            libmail_u_convert_tobuf(info->owner,
                                                 unicode_x_imap_modutf7,
                                                 "utf-8", NULL);

                     if (!owner_utf8)
                     {
                            free(info->homedir);
                            info->homedir=NULL;
                            return (0);
                     }

                     free(info->owner);
                     info->owner=owner_utf8;
              }

              ifs.path += ifs.path_l;

              info->maildir=malloc(strlen(INBOX)+1+strlen(ifs.path));
              if (!info->maildir)
              {
                     free(info->owner);
                     free(info->homedir);
                     info->owner=NULL;
                     info->homedir=NULL;
                     return -1;
              }
              strcat(strcpy(info->maildir, INBOX), ifs.path);

              if (maildir_info_suppress(info->homedir))
              {

                     free(info->homedir);
                     free(info->maildir);
                     info->homedir=NULL;
                     info->maildir=NULL;
                     info->mailbox_type=MAILBOXTYPE_IGNORE;
                     free(info->owner);
                     info->owner=NULL;
                     info->owner=strdup("vendor=courier.internal");
                     if (!info->owner)
                     {
                            return -1;
                     }
              }

              return 0;
       }

       if (indexfile_cpy)
              free(indexfile_cpy);
       if (ifs.homedir)
       {
              free(ifs.homedir);
              ifs.homedir=NULL;
       }

       if (ifs.maildir)
       {
              free(ifs.maildir);
              ifs.maildir=NULL;
       }
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* maildir_info_imapmunge ( const char *  name)

Definition at line 862 of file maildirinfo.c.

{
       char *n=libmail_u_convert_tobuf(name, "utf8",
                                   unicode_x_imap_modutf7, NULL);
       char *p;
       size_t cnt;

       if (!n)
              return NULL;

       if (!complex_flag)
       {
              for (p=n; *p; p++)
              {
                     if (*p == '.' || *p == '/')
                            *p=' ';
              }

              return n;
       }

       cnt=munge_complex(n, NULL);
       p=malloc(cnt);
       if (!p)
       {
              free(n);
              return NULL;
       }

       munge_complex(n, p);

       free(n);
       return p;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void maildir_info_munge_complex ( int  f)

Definition at line 855 of file maildirinfo.c.

Here is the caller graph for this function:

int maildir_info_smap_find ( struct maildir_info info,
char **  folder,
const char *  myId 
)

Definition at line 639 of file maildirinfo.c.

{
       char *p;
       size_t n;
       const char *indexfile;
       struct maildir_shindex_cache *curcache;
       const char *subhierarchy;
       struct imap_find_shared ifs;
       int rc, eof;
       char *indexfile_cpy=NULL;

       info->homedir=NULL;
       info->maildir=NULL;
       info->owner=NULL;
       info->mailbox_type=MAILBOXTYPE_IGNORE;

       if (folder[0] == NULL)
       {
              errno=EINVAL;
              return -1;
       }

       if (strcmp(folder[0], PUBLIC))
       {
              if (strcmp(folder[0], INBOX))
              {
                     errno=EINVAL;
                     return -1;
              }

              info->maildir=smap_path(NULL, folder);

              if (info->maildir == NULL)
                     return -1;
              info->homedir=strdup(".");
              if (!info->homedir)
              {
                     maildir_info_destroy(info);
                     return -1;
              }

              info->mailbox_type=MAILBOXTYPE_INBOX;

              info->owner=malloc(strlen(myId)+sizeof("user="));

              if (!info->owner)
              {
                     maildir_info_destroy(info);
                     return -1;
              }

              strcat(strcpy(info->owner, "user="), myId);

              return 0;
       }

       indexfile=NULL;
       curcache=NULL;
       subhierarchy=NULL;
       n=1;
       ifs.homedir=NULL;
       ifs.maildir=NULL;

       while (folder[n])
       {
              size_t i;

              curcache=maildir_shared_cache_read(curcache, indexfile,
                                             subhierarchy);

              if (!curcache)
                     break;

              for (i=0; i<curcache->nrecords; i++)
                     if (strcmp(curcache->records[i].name,
                               folder[n]) == 0)
                            break;

              if (i >= curcache->nrecords)
                     break;
              curcache->indexfile.startingpos=
                     curcache->records[i].offset;

              if (ifs.homedir)
                     free(ifs.homedir);
              if (ifs.maildir)
                     free(ifs.maildir);
              ifs.homedir=NULL;
              ifs.maildir=NULL;

              rc=maildir_newshared_nextAt(&curcache->indexfile,
                                       &eof,
                                       imap_find_cb, &ifs);

              if (rc || eof)
              {
                     fprintf(stderr, "ERR: Internal error -"
                            " maildir_newshared_nextAt: %s\n",
                            strerror(errno));
                     fflush(stderr);
                     break;
              }

              if (!ifs.homedir && !ifs.maildir)
                     break;

              if (!ifs.homedir)
              {
                     if (indexfile_cpy)
                            free(indexfile_cpy);
                     indexfile=indexfile_cpy=ifs.maildir;
                     ifs.maildir=NULL;
                     subhierarchy=curcache->records[i].name;
                     ++n;
                     continue;
              }

              if (indexfile_cpy)
                     free(indexfile_cpy);
              info->homedir=maildir_location(ifs.homedir,
                                          ifs.maildir);
              free(ifs.homedir);
              free(ifs.maildir);

              info->maildir=NULL;

              if (maildir_info_suppress(info->homedir))
              {

                     free(info->homedir);
                     info->homedir=NULL;
                     info->maildir=NULL;
                     info->mailbox_type=MAILBOXTYPE_IGNORE;
                     info->owner=NULL;
                     info->owner=strdup("vendor=courier.internal");
                     if (!info->owner)
                     {
                            maildir_info_destroy(info);
                            return -1;
                     }

                     return 0;
              }


              if (!subhierarchy || !*subhierarchy)
              {
                     info->owner=strdup("vendor=courier.internal");
                     if (!info->owner)
                     {
                            maildir_info_destroy(info);
                            return -1;
                     }
              }
              else
              {
                     info->owner=malloc(strlen(subhierarchy)
                                      +sizeof("user="));

                     if (!info->owner)
                     {
                            free(info->homedir);
                            info->homedir=NULL;
                            info->maildir=NULL;
                            return -1;
                     }
                     strcpy(info->owner, "user=");
                     strcat(info->owner, subhierarchy);
              }

              p=folder[n];
              folder[n]=INBOX;
              info->maildir=smap_path(info->homedir, folder+n);
              folder[n]=p;

              if (!info->maildir)
              {
                     free(info->homedir);
                     free(info->owner);
                     info->homedir=NULL;
                     info->maildir=NULL;
                     info->owner=NULL;
                     return -1;
              }

              info->mailbox_type=MAILBOXTYPE_NEWSHARED;
              return 0;
       }

       if (ifs.homedir)
              free(ifs.homedir);
       if (ifs.maildir)
              free(ifs.maildir);
       if (indexfile_cpy)
              free(indexfile_cpy);

       if (folder[n] == 0)
       {
              info->mailbox_type=MAILBOXTYPE_NEWSHARED;
              info->owner=strdup("vendor=courier.internal");
              if (!info->owner)
              {
                     maildir_info_destroy(info);
                     return -1;
              }

              /* Intermediate shared namespce */
              return 0;
       }

       return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void maildir_smapfn_free ( char **  fn)

Definition at line 535 of file maildirinfo.c.

{
       size_t i;

       for (i=0; fn[i]; i++)
              free(fn[i]);
       free(fn);
}

Here is the caller graph for this function:

char** maildir_smapfn_fromutf7 ( const char *  modutf7)

Definition at line 480 of file maildirinfo.c.

{
       char *p=strdup(modutf7), *q;
       size_t n, i;
       char **fn;

       if (!p)
              return NULL;

       n=1;
       for (i=0; p[i]; i++)
              if (p[i] == '.' && p[i+1] && p[i+1] != '.')
              {
                     ++n;
              }

       fn=malloc((n+1)*sizeof(char *));

       if (!fn)
       {
              free(p);
              return NULL;
       }

       n=0;
       q=p;
       do
       {
              for (i=0; q[i]; i++)
                     if (q[i] == '.' && q[i+1] && q[i+1] != '.')
                     {
                            q[i++]=0;
                            break;
                     }

              fn[n]=libmail_u_convert_tobuf(q,
                                         unicode_x_imap_modutf7 " ./~:",
                                         "utf-8", NULL);
              q += i;

              if (!fn[n])
              {
                     while (n)
                            free(fn[--n]);
                     free(fn);
                     free(p);
                     return NULL;
              }
              n++;
       } while (*q);
       fn[n]=0;
       free(p);
       return fn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static size_t munge_complex ( const char *  orig,
char *  n 
) [static]

Definition at line 897 of file maildirinfo.c.

{
       size_t cnt=0;

       while (*orig)
       {
              switch (*orig) {
              case '.':
                     if (n)
                     {
                            *n++='\\';
                            *n++=':';
                     }
                     cnt += 2;
                     break;
              case '/':
                     if (n)
                     {
                            *n++='\\';
                            *n++=';';
                     }
                     cnt += 2;
                     break;
              case '\\':
                     if (n)
                     {
                            *n++='\\';
                            *n++='\\';
                     }
                     cnt += 2;
                     break;
              default:
                     if (n) *n++ = *orig;
                     ++cnt;
              }
              ++orig;
       }

       if (n) *n=0;
       return cnt+1;
}

Here is the caller graph for this function:

static char* smap_path ( const char *  homedir,
char **  words 
) [static]

Definition at line 597 of file maildirinfo.c.

{
       struct get_existing_folder_info gefi;
       char *n, *p;
       struct stat stat_buf;

       if ((n=smaptoUtf7(words)) == NULL)
              return NULL;

       p=maildir_name2dir(homedir, n);

       if (!p)
       {
              free(n);
              return NULL;
       }

       if (stat(p, &stat_buf) == 0)
       {
              free(p);
              return n;
       }

       gefi.fn=words;
       gefi.pathname=NULL;

       maildir_list(homedir ? homedir:".",
                   &get_existing_callback, &gefi);

       if (gefi.pathname)
       {
              free(n);
              free(p);

              return gefi.pathname;
       }

       free(p);
       return n;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* smaptoUtf7 ( char **  ptr) [static]

Definition at line 434 of file maildirinfo.c.

{
       char *f=NULL;
       char *n;

       while ((n=*ptr++) != NULL && *n)
       {
              char *p=libmail_u_convert_tobuf(n, "utf-8",
                                          unicode_x_imap_modutf7 " ./~:",
                                          NULL);

              if (!p)
              {
                     if (f)
                            free(f);
                     return NULL;
              }

              n= f ? realloc(f, strlen(f)+strlen(p)+2):malloc(strlen(p)+1);

              if (!n)
              {
                     free(p);
                     if (f)
                            free(f);
                     return NULL;
              }
              if (f)
                     f=strcat(strcat(n, "."), p);
              else
                     f=strcpy(n, p);
              free(p);
       }

       if (!f)
              errno=EINVAL;
       return f;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

int complex_flag [static]

Definition at line 853 of file maildirinfo.c.