Back to index

courier  0.68.2
maildirinfo.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 #include      <fcntl.h>
00015 #if    HAVE_UNISTD_H
00016 #include      <unistd.h>
00017 #endif
00018 #if    HAVE_UTIME_H
00019 #include      <utime.h>
00020 #endif
00021 #if TIME_WITH_SYS_TIME
00022 #include      <sys/time.h>
00023 #include      <time.h>
00024 #else
00025 #if HAVE_SYS_TIME_H
00026 #include      <sys/time.h>
00027 #else
00028 #include      <time.h>
00029 #endif
00030 #endif
00031 
00032 #include      <sys/types.h>
00033 #include      <sys/stat.h>
00034 
00035 #include      "config.h"
00036 #include      "maildirinfo.h"
00037 
00038 #include      "maildirmisc.h"
00039 #include      "maildirnewshared.h"
00040 #include      "unicode/unicode.h"
00041 
00042 void maildir_info_destroy(struct maildir_info *info)
00043 {
00044        if (info->homedir)
00045               free(info->homedir);
00046        if (info->maildir)
00047               free(info->maildir);
00048        if (info->owner)
00049               free(info->owner);
00050        info->homedir=NULL;
00051        info->maildir=NULL;
00052        info->owner=NULL;
00053 }
00054 
00055 struct imap_find_shared {
00056        struct maildir_info *info;
00057        const char *path;
00058        size_t path_l;
00059        char *homedir;
00060        char *maildir;
00061 };
00062 
00063 static int imap_find_cb(struct maildir_newshared_enum_cb *cb)
00064 {
00065        struct imap_find_shared *ifs=(struct imap_find_shared *)cb->cb_arg;
00066 
00067        if (cb->homedir)
00068        {
00069               ifs->homedir=strdup(cb->homedir);
00070               if (!ifs->homedir)
00071                      return -1;
00072        }
00073 
00074        if (cb->maildir)
00075        {
00076               ifs->maildir=strdup(cb->maildir);
00077 
00078               if (!ifs->maildir)
00079               {
00080                      if (cb->homedir)
00081                      {
00082                             free(ifs->homedir);
00083                             ifs->homedir=NULL;
00084                      }
00085                      return -1;
00086               }
00087        }
00088 
00089        return 0;
00090 }
00091 
00092 int maildir_info_imap_find(struct maildir_info *info, const char *path,
00093                         const char *myId)
00094 {
00095        const char *p;
00096        struct imap_find_shared ifs;
00097        const char *indexfile;
00098        char *indexfile_cpy;
00099        struct maildir_shindex_cache *curcache;
00100        const char *subhierarchy;
00101 
00102        info->homedir=NULL;
00103        info->maildir=NULL;
00104        info->owner=NULL;
00105 
00106        if (strchr(path, '/'))
00107        {
00108               errno=EINVAL;
00109               return -1;
00110        }
00111 
00112        for (p=path; *p; p++)
00113               if (*p == '.' && p[1] == '.')
00114               {
00115                      errno=EINVAL;
00116                      return -1;
00117               }
00118 
00119        if (strncmp(path, SHARED, sizeof(SHARED)-1) == 0)
00120        {
00121               path += sizeof(SHARED)-1;
00122 
00123               info->homedir=strdup(".");
00124               if (!info->homedir)
00125                      return -1;
00126 
00127               info->mailbox_type=MAILBOXTYPE_OLDSHARED;
00128               info->owner=strdup("anonymous");
00129 
00130               if (!info->owner)
00131               {
00132                      maildir_info_destroy(info);
00133                      return -1;
00134               }
00135 
00136               /* We need to specialcase "shared" and "shared.name".
00137               ** maildir_shareddir will return NULL for these cases, because
00138               ** it will insist on "name.folder", but we need to return a
00139               ** non NULL value to indicate that this is a valid hierarchy
00140               ** name.  We return a special value of an empty string, which
00141               ** is checked for in situations where a valid folder is
00142               ** required.
00143               */
00144 
00145               if (*path && *path != '.')
00146               {
00147                      maildir_info_destroy(info);
00148                      errno=EINVAL;
00149                      return -1;
00150               }
00151 
00152               return 0;
00153        }
00154 
00155        if (strncasecmp(path, INBOX, sizeof(INBOX)-1) == 0)
00156        {
00157               switch (path[sizeof(INBOX)-1]) {
00158               case 0:
00159               case '.':
00160                      break;
00161               default:
00162                      errno=EINVAL;
00163                      return -1;
00164               }
00165 
00166               info->homedir=strdup(".");
00167 
00168               if (!info->homedir)
00169                      return -1;
00170 
00171               info->maildir=strdup(path);
00172               if (!info->maildir)
00173               {
00174                      maildir_info_destroy(info);
00175                      return -1;
00176               }
00177 
00178               info->owner=malloc(strlen(myId)+sizeof("user="));
00179 
00180               if (!info->owner)
00181               {
00182                      maildir_info_destroy(info);
00183                      return -1;
00184               }
00185 
00186               info->mailbox_type=MAILBOXTYPE_INBOX;
00187               strcat(strcpy(info->owner, "user="), myId);
00188               return 0;
00189        }
00190 
00191        if (strncmp(path, NEWSHARED,
00192                   sizeof(NEWSHARED)-1) != 0)
00193        {
00194               errno=EINVAL;
00195               return -1;
00196        }
00197 
00198        ifs.info=info;
00199        ifs.path=path+sizeof(NEWSHARED)-1;
00200 
00201        info->mailbox_type=MAILBOXTYPE_NEWSHARED;
00202        info->homedir=NULL;
00203        info->maildir=NULL;
00204        info->owner=strdup("vendor=courier.internal");
00205 
00206        if (!info->owner)
00207               return -1;
00208 
00209        ifs.homedir=NULL;
00210        ifs.maildir=NULL;
00211 
00212        indexfile=NULL;
00213        indexfile_cpy=NULL;
00214        curcache=NULL;
00215        subhierarchy=NULL;
00216 
00217        while (*ifs.path)
00218        {
00219               int rc, eof;
00220               size_t i;
00221 
00222               curcache=maildir_shared_cache_read(curcache, indexfile,
00223                                              subhierarchy);
00224 
00225               if (indexfile_cpy)
00226               {
00227                      free(indexfile_cpy);
00228                      indexfile_cpy=NULL;
00229               }
00230 
00231               if (!curcache)
00232                      break;
00233 
00234               p=strchr(ifs.path, '.');
00235 
00236               if (p)
00237                      ifs.path_l=p-ifs.path;
00238               else
00239                      ifs.path_l=strlen(ifs.path);
00240 
00241 
00242               if (ifs.homedir)
00243                      free(ifs.homedir);
00244               if (ifs.maildir)
00245                      free(ifs.maildir);
00246 
00247               ifs.homedir=NULL;
00248               ifs.maildir=NULL;
00249 
00250               for (i=0; i < curcache->nrecords; i++)
00251               {
00252                      char *n=maildir_info_imapmunge(curcache->
00253                                                  records[i].name);
00254 
00255                      if (n == NULL)
00256                      {
00257                             i=curcache->nrecords;
00258                             break;
00259                      }
00260 
00261                      if (strlen(n) == ifs.path_l &&
00262                          strncmp(n, ifs.path, ifs.path_l) == 0)
00263                      {
00264                             free(n);
00265                             break;
00266                      }
00267                      free(n);
00268               }
00269 
00270               if (i >= curcache->nrecords)
00271                      break;
00272 
00273               curcache->indexfile.startingpos=
00274                      curcache->records[i].offset;
00275               rc=maildir_newshared_nextAt(&curcache->indexfile,
00276                                        &eof,
00277                                        imap_find_cb, &ifs);
00278 
00279               if (rc || eof)
00280               {
00281                      fprintf(stderr, "ERR: Internal error -"
00282                             " maildir_newshared_nextAt: %s\n",
00283                             strerror(errno));
00284                      fflush(stderr);
00285                      break;
00286               }
00287 
00288               if (!ifs.homedir && !ifs.maildir)
00289                      break;
00290 
00291               if (!ifs.homedir)
00292               {
00293                      indexfile=indexfile_cpy=ifs.maildir;
00294                      ifs.maildir=NULL;
00295                      subhierarchy=curcache->records[i].name;
00296 
00297                      ifs.path += ifs.path_l;
00298                      if (*ifs.path)
00299                             ++ifs.path;
00300                      continue;
00301               }
00302 
00303               info->homedir=maildir_location(ifs.homedir,
00304                                         ifs.maildir);
00305 
00306               free(ifs.homedir);
00307               free(ifs.maildir);
00308 
00309               free(info->owner);
00310 
00311               if (!info->homedir)
00312               {
00313                      info->maildir=NULL;
00314                      info->owner=NULL;
00315                      return -1;
00316               }
00317 
00318               if (!subhierarchy || !*subhierarchy)
00319               {
00320                      info->owner=strdup("vendor=courier.internal");
00321                      if (!info->owner)
00322                      {
00323                             free(info->homedir);
00324                             info->homedir=NULL;
00325                             info->maildir=NULL;
00326                             return -1;
00327                      }
00328               }
00329               else
00330               {
00331                      char *owner_utf8;
00332 
00333                      info->owner=malloc(strlen(subhierarchy)
00334                                       +sizeof("user="));
00335 
00336                      if (!info->owner)
00337                      {
00338                             free(info->homedir);
00339                             info->homedir=NULL;
00340                             info->maildir=NULL;
00341                             info->owner=NULL;
00342                             return -1;
00343                      }
00344                      strcpy(info->owner, "user=");
00345                      strcat(info->owner, subhierarchy);
00346 
00347                      /*
00348                      ** The folder path is in modified-UTF7.  The owner is
00349                      ** obtained from shared hierarchy, but in ACL2 the
00350                      ** identifiers are in UTF8.
00351                      */
00352 
00353                      owner_utf8=
00354                             libmail_u_convert_tobuf(info->owner,
00355                                                  unicode_x_imap_modutf7,
00356                                                  "utf-8", NULL);
00357 
00358                      if (!owner_utf8)
00359                      {
00360                             free(info->homedir);
00361                             info->homedir=NULL;
00362                             return (0);
00363                      }
00364 
00365                      free(info->owner);
00366                      info->owner=owner_utf8;
00367               }
00368 
00369               ifs.path += ifs.path_l;
00370 
00371               info->maildir=malloc(strlen(INBOX)+1+strlen(ifs.path));
00372               if (!info->maildir)
00373               {
00374                      free(info->owner);
00375                      free(info->homedir);
00376                      info->owner=NULL;
00377                      info->homedir=NULL;
00378                      return -1;
00379               }
00380               strcat(strcpy(info->maildir, INBOX), ifs.path);
00381 
00382               if (maildir_info_suppress(info->homedir))
00383               {
00384 
00385                      free(info->homedir);
00386                      free(info->maildir);
00387                      info->homedir=NULL;
00388                      info->maildir=NULL;
00389                      info->mailbox_type=MAILBOXTYPE_IGNORE;
00390                      free(info->owner);
00391                      info->owner=NULL;
00392                      info->owner=strdup("vendor=courier.internal");
00393                      if (!info->owner)
00394                      {
00395                             return -1;
00396                      }
00397               }
00398 
00399               return 0;
00400        }
00401 
00402        if (indexfile_cpy)
00403               free(indexfile_cpy);
00404        if (ifs.homedir)
00405        {
00406               free(ifs.homedir);
00407               ifs.homedir=NULL;
00408        }
00409 
00410        if (ifs.maildir)
00411        {
00412               free(ifs.maildir);
00413               ifs.maildir=NULL;
00414        }
00415        return 0;
00416 }
00417 
00418 /***************************************************************************/
00419 
00420 /*
00421 ** Maildir folders are named in IMAP-compatible modified-UTF7 encoding,
00422 ** with periods as hierarchy delimiters.  One exception: ".", "/", "~", and
00423 ** ":" are also encoded using modified-UTF7, making folder names that contain
00424 ** those characters incompatible with IMAP.
00425 **
00426 ** smaptoUtf7 crates a modified-UTF7-encoded folder name from a vector
00427 ** of UTF-8 words.
00428 **
00429 ** input:  "INBOX" "a" "b"
00430 ** output: "INBOX.a.b"
00431 **
00432 */
00433 
00434 static char *smaptoUtf7(char **ptr)
00435 {
00436        char *f=NULL;
00437        char *n;
00438 
00439        while ((n=*ptr++) != NULL && *n)
00440        {
00441               char *p=libmail_u_convert_tobuf(n, "utf-8",
00442                                           unicode_x_imap_modutf7 " ./~:",
00443                                           NULL);
00444 
00445               if (!p)
00446               {
00447                      if (f)
00448                             free(f);
00449                      return NULL;
00450               }
00451 
00452               n= f ? realloc(f, strlen(f)+strlen(p)+2):malloc(strlen(p)+1);
00453 
00454               if (!n)
00455               {
00456                      free(p);
00457                      if (f)
00458                             free(f);
00459                      return NULL;
00460               }
00461               if (f)
00462                      f=strcat(strcat(n, "."), p);
00463               else
00464                      f=strcpy(n, p);
00465               free(p);
00466        }
00467 
00468        if (!f)
00469               errno=EINVAL;
00470        return f;
00471 }
00472 
00473 /*
00474 ** Legacy IMAP creates maildir folders using modified-UTF7.
00475 **
00476 ** Convert modified-UTF7 folder name into an array of UTF-8 words, that
00477 ** represent a folder name.
00478 */
00479 
00480 char **maildir_smapfn_fromutf7(const char *modutf7)
00481 {
00482        char *p=strdup(modutf7), *q;
00483        size_t n, i;
00484        char **fn;
00485 
00486        if (!p)
00487               return NULL;
00488 
00489        n=1;
00490        for (i=0; p[i]; i++)
00491               if (p[i] == '.' && p[i+1] && p[i+1] != '.')
00492               {
00493                      ++n;
00494               }
00495 
00496        fn=malloc((n+1)*sizeof(char *));
00497 
00498        if (!fn)
00499        {
00500               free(p);
00501               return NULL;
00502        }
00503 
00504        n=0;
00505        q=p;
00506        do
00507        {
00508               for (i=0; q[i]; i++)
00509                      if (q[i] == '.' && q[i+1] && q[i+1] != '.')
00510                      {
00511                             q[i++]=0;
00512                             break;
00513                      }
00514 
00515               fn[n]=libmail_u_convert_tobuf(q,
00516                                          unicode_x_imap_modutf7 " ./~:",
00517                                          "utf-8", NULL);
00518               q += i;
00519 
00520               if (!fn[n])
00521               {
00522                      while (n)
00523                             free(fn[--n]);
00524                      free(fn);
00525                      free(p);
00526                      return NULL;
00527               }
00528               n++;
00529        } while (*q);
00530        fn[n]=0;
00531        free(p);
00532        return fn;
00533 }
00534 
00535 void maildir_smapfn_free(char **fn)
00536 {
00537        size_t i;
00538 
00539        for (i=0; fn[i]; i++)
00540               free(fn[i]);
00541        free(fn);
00542 }
00543 
00544 struct get_existing_folder_info {
00545        char **fn;
00546        char *pathname;
00547 };
00548 
00549 static void get_existing_callback(const char *f, void *vp)
00550 {
00551        char **fn;
00552 
00553        struct get_existing_folder_info *gefi=
00554               (struct get_existing_folder_info *)vp;
00555        size_t i;
00556        size_t j;
00557 
00558        if (gefi->pathname)
00559               return;
00560 
00561        fn=maildir_smapfn_fromutf7(f);
00562        if (!fn)
00563        {
00564               perror(f);
00565               return;
00566        }
00567 
00568        for (i=0; gefi->fn[i]; i++)
00569               if (fn[i] == NULL || strcmp(fn[i], gefi->fn[i]))
00570               {
00571                      maildir_smapfn_free(fn);
00572                      return;
00573               }
00574 
00575        maildir_smapfn_free(fn);
00576 
00577        for (j=0; i && f[j]; j++)
00578               if (f[j] == '.' && f[j+1] && f[j+1] != '.')
00579               {
00580                      --i;
00581                      if (i == 0)
00582                             break;
00583               }
00584 
00585        gefi->pathname=malloc(j+1);
00586 
00587        if (!gefi->pathname)
00588        {
00589               perror("malloc");
00590               return;
00591        }
00592 
00593        memcpy(gefi->pathname, f, j);
00594        gefi->pathname[j]=0;
00595 }
00596 
00597 static char *smap_path(const char *homedir,
00598                      char **words)  /* words[0] better be INBOX! */
00599 {
00600        struct get_existing_folder_info gefi;
00601        char *n, *p;
00602        struct stat stat_buf;
00603 
00604        if ((n=smaptoUtf7(words)) == NULL)
00605               return NULL;
00606 
00607        p=maildir_name2dir(homedir, n);
00608 
00609        if (!p)
00610        {
00611               free(n);
00612               return NULL;
00613        }
00614 
00615        if (stat(p, &stat_buf) == 0)
00616        {
00617               free(p);
00618               return n;
00619        }
00620 
00621        gefi.fn=words;
00622        gefi.pathname=NULL;
00623 
00624        maildir_list(homedir ? homedir:".",
00625                    &get_existing_callback, &gefi);
00626 
00627        if (gefi.pathname)
00628        {
00629               free(n);
00630               free(p);
00631 
00632               return gefi.pathname;
00633        }
00634 
00635        free(p);
00636        return n;
00637 }
00638 
00639 int maildir_info_smap_find(struct maildir_info *info, char **folder,
00640                         const char *myId)
00641 {
00642        char *p;
00643        size_t n;
00644        const char *indexfile;
00645        struct maildir_shindex_cache *curcache;
00646        const char *subhierarchy;
00647        struct imap_find_shared ifs;
00648        int rc, eof;
00649        char *indexfile_cpy=NULL;
00650 
00651        info->homedir=NULL;
00652        info->maildir=NULL;
00653        info->owner=NULL;
00654        info->mailbox_type=MAILBOXTYPE_IGNORE;
00655 
00656        if (folder[0] == NULL)
00657        {
00658               errno=EINVAL;
00659               return -1;
00660        }
00661 
00662        if (strcmp(folder[0], PUBLIC))
00663        {
00664               if (strcmp(folder[0], INBOX))
00665               {
00666                      errno=EINVAL;
00667                      return -1;
00668               }
00669 
00670               info->maildir=smap_path(NULL, folder);
00671 
00672               if (info->maildir == NULL)
00673                      return -1;
00674               info->homedir=strdup(".");
00675               if (!info->homedir)
00676               {
00677                      maildir_info_destroy(info);
00678                      return -1;
00679               }
00680 
00681               info->mailbox_type=MAILBOXTYPE_INBOX;
00682 
00683               info->owner=malloc(strlen(myId)+sizeof("user="));
00684 
00685               if (!info->owner)
00686               {
00687                      maildir_info_destroy(info);
00688                      return -1;
00689               }
00690 
00691               strcat(strcpy(info->owner, "user="), myId);
00692 
00693               return 0;
00694        }
00695 
00696        indexfile=NULL;
00697        curcache=NULL;
00698        subhierarchy=NULL;
00699        n=1;
00700        ifs.homedir=NULL;
00701        ifs.maildir=NULL;
00702 
00703        while (folder[n])
00704        {
00705               size_t i;
00706 
00707               curcache=maildir_shared_cache_read(curcache, indexfile,
00708                                              subhierarchy);
00709 
00710               if (!curcache)
00711                      break;
00712 
00713               for (i=0; i<curcache->nrecords; i++)
00714                      if (strcmp(curcache->records[i].name,
00715                                folder[n]) == 0)
00716                             break;
00717 
00718               if (i >= curcache->nrecords)
00719                      break;
00720               curcache->indexfile.startingpos=
00721                      curcache->records[i].offset;
00722 
00723               if (ifs.homedir)
00724                      free(ifs.homedir);
00725               if (ifs.maildir)
00726                      free(ifs.maildir);
00727               ifs.homedir=NULL;
00728               ifs.maildir=NULL;
00729 
00730               rc=maildir_newshared_nextAt(&curcache->indexfile,
00731                                        &eof,
00732                                        imap_find_cb, &ifs);
00733 
00734               if (rc || eof)
00735               {
00736                      fprintf(stderr, "ERR: Internal error -"
00737                             " maildir_newshared_nextAt: %s\n",
00738                             strerror(errno));
00739                      fflush(stderr);
00740                      break;
00741               }
00742 
00743               if (!ifs.homedir && !ifs.maildir)
00744                      break;
00745 
00746               if (!ifs.homedir)
00747               {
00748                      if (indexfile_cpy)
00749                             free(indexfile_cpy);
00750                      indexfile=indexfile_cpy=ifs.maildir;
00751                      ifs.maildir=NULL;
00752                      subhierarchy=curcache->records[i].name;
00753                      ++n;
00754                      continue;
00755               }
00756 
00757               if (indexfile_cpy)
00758                      free(indexfile_cpy);
00759               info->homedir=maildir_location(ifs.homedir,
00760                                           ifs.maildir);
00761               free(ifs.homedir);
00762               free(ifs.maildir);
00763 
00764               info->maildir=NULL;
00765 
00766               if (maildir_info_suppress(info->homedir))
00767               {
00768 
00769                      free(info->homedir);
00770                      info->homedir=NULL;
00771                      info->maildir=NULL;
00772                      info->mailbox_type=MAILBOXTYPE_IGNORE;
00773                      info->owner=NULL;
00774                      info->owner=strdup("vendor=courier.internal");
00775                      if (!info->owner)
00776                      {
00777                             maildir_info_destroy(info);
00778                             return -1;
00779                      }
00780 
00781                      return 0;
00782               }
00783 
00784 
00785               if (!subhierarchy || !*subhierarchy)
00786               {
00787                      info->owner=strdup("vendor=courier.internal");
00788                      if (!info->owner)
00789                      {
00790                             maildir_info_destroy(info);
00791                             return -1;
00792                      }
00793               }
00794               else
00795               {
00796                      info->owner=malloc(strlen(subhierarchy)
00797                                       +sizeof("user="));
00798 
00799                      if (!info->owner)
00800                      {
00801                             free(info->homedir);
00802                             info->homedir=NULL;
00803                             info->maildir=NULL;
00804                             return -1;
00805                      }
00806                      strcpy(info->owner, "user=");
00807                      strcat(info->owner, subhierarchy);
00808               }
00809 
00810               p=folder[n];
00811               folder[n]=INBOX;
00812               info->maildir=smap_path(info->homedir, folder+n);
00813               folder[n]=p;
00814 
00815               if (!info->maildir)
00816               {
00817                      free(info->homedir);
00818                      free(info->owner);
00819                      info->homedir=NULL;
00820                      info->maildir=NULL;
00821                      info->owner=NULL;
00822                      return -1;
00823               }
00824 
00825               info->mailbox_type=MAILBOXTYPE_NEWSHARED;
00826               return 0;
00827        }
00828 
00829        if (ifs.homedir)
00830               free(ifs.homedir);
00831        if (ifs.maildir)
00832               free(ifs.maildir);
00833        if (indexfile_cpy)
00834               free(indexfile_cpy);
00835 
00836        if (folder[n] == 0)
00837        {
00838               info->mailbox_type=MAILBOXTYPE_NEWSHARED;
00839               info->owner=strdup("vendor=courier.internal");
00840               if (!info->owner)
00841               {
00842                      maildir_info_destroy(info);
00843                      return -1;
00844               }
00845 
00846               /* Intermediate shared namespce */
00847               return 0;
00848        }
00849 
00850        return -1;
00851 }
00852 
00853 static int complex_flag;
00854 
00855 void maildir_info_munge_complex(int f)
00856 {
00857        complex_flag=f;
00858 }
00859 
00860 static size_t munge_complex(const char *, char *);
00861 
00862 char *maildir_info_imapmunge(const char *name)
00863 {
00864        char *n=libmail_u_convert_tobuf(name, "utf8",
00865                                    unicode_x_imap_modutf7, NULL);
00866        char *p;
00867        size_t cnt;
00868 
00869        if (!n)
00870               return NULL;
00871 
00872        if (!complex_flag)
00873        {
00874               for (p=n; *p; p++)
00875               {
00876                      if (*p == '.' || *p == '/')
00877                             *p=' ';
00878               }
00879 
00880               return n;
00881        }
00882 
00883        cnt=munge_complex(n, NULL);
00884        p=malloc(cnt);
00885        if (!p)
00886        {
00887               free(n);
00888               return NULL;
00889        }
00890 
00891        munge_complex(n, p);
00892 
00893        free(n);
00894        return p;
00895 }
00896 
00897 static size_t munge_complex(const char *orig, char *n)
00898 {
00899        size_t cnt=0;
00900 
00901        while (*orig)
00902        {
00903               switch (*orig) {
00904               case '.':
00905                      if (n)
00906                      {
00907                             *n++='\\';
00908                             *n++=':';
00909                      }
00910                      cnt += 2;
00911                      break;
00912               case '/':
00913                      if (n)
00914                      {
00915                             *n++='\\';
00916                             *n++=';';
00917                      }
00918                      cnt += 2;
00919                      break;
00920               case '\\':
00921                      if (n)
00922                      {
00923                             *n++='\\';
00924                             *n++='\\';
00925                      }
00926                      cnt += 2;
00927                      break;
00928               default:
00929                      if (n) *n++ = *orig;
00930                      ++cnt;
00931               }
00932               ++orig;
00933        }
00934 
00935        if (n) *n=0;
00936        return cnt+1;
00937 }
00938