Completely reworked the path convertion functions
[mmh] / sbr / path.c
index 3dd552c..4132896 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** path.c -- return a pathname
+** path.c -- return or convert paths
 **
 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
 ** COPYRIGHT file in the root directory of the nmh distribution for
@@ -8,13 +8,13 @@
 
 #include <h/mh.h>
 
-static char *pwds;
-
 
 /*
-**  Compactify an absolute path name by removing unneccessary parts.
-**  Removes trailing slashes, but not if it would empty the string then.
-**  Modifies f.
+**  Compactify a path name by removing unneccessary parts.
+**  Removes trailing slashes. Cares to never remove all characters.
+**  Modifies f (never enlarges it).
+**
+**  FIXME: Cannot use strcpy() as the areas overlap!
 */
 static void
 packpath(char *f)
@@ -90,111 +90,147 @@ packpath(char *f)
 }
 
 
+
+
 /*
-**
+**  Get the default folder
+**  Return the Inbox profile entry or, as fallback, the compile time default
+**  Returns a pointer to the abs folpath
 */
-static char *
-expath(char *name, int type)
+char *
+getdeffol(void)
 {
-       char *cp, *ep;
-       char buffer[BUFSIZ];
-
-       if (type == TSUBCWF) {
-               /* convert TSUBCWF to TFOLDER */
-               snprintf(buffer, sizeof(buffer), "%s/%s",
-                               getfolder(FCUR), name);
-               name = m_mailpath(buffer);
-               packpath(name);
-               snprintf(buffer, sizeof(buffer), "%s/", m_maildir(""));
-               if (isprefix(buffer, name)) {
-                       cp = name;
-                       name = getcpy(name + strlen(buffer));
-                       free(cp);
-               }
-               type = TFOLDER;
-       }
+       char *folder = context_find(inbox);
 
-       if (*name == '/') {
-               return getcpy(name);
+       if (!folder || !*folder) {
+               folder = defaultfolder;  /* the compile time default */
        }
-
-       if (type == TFOLDER &&
-                       (strncmp(name, "./", 2) && strcmp(name, ".") &&
-                       strcmp(name, "..") && strncmp(name, "../", 3))) {
-               /*
-               ** FIXME: Seems as if this check does not catch names like:
-               **        ``foo/../../..''.
-               */
-               return getcpy(name);
+       if (*folder == '+') {
+               folder++;
        }
+       return folder;
+}
 
-       if (pwds == NULL) {
-               pwds = pwd();
-       }
 
-       if (strcmp(name, ".") == 0 || strcmp(name, "./") == 0) {
-               return getcpy(pwds);
-       }
+/*
+**  Get the current folder
+**  Return the Current-Folder context entry or, as fallback, the default folder
+**  Returns a pointer to the abs folpath
+**
+**  Equivalent to: expandfol("@")
+*/
+char *
+getcurfol(void)
+{
+       char *folder = context_find(pfolder);
 
-       ep = pwds + strlen(pwds);
-       if ((cp = strrchr(pwds, '/')) == NULL) {
-               cp = ep;
-       } else if (cp == pwds)  {
-               cp++;
+       if (!folder || !*folder) {
+               folder = getdeffol();
        }
+       return folder;
+}
 
-       if (strncmp(name, "./", 2) == 0) {
-               name += 2;
-       }
 
-       if (strcmp(name, "..") == 0 || strcmp(name, "../") == 0) {
-               snprintf(buffer, sizeof(buffer), "%.*s",
-                               (int)(cp - pwds), pwds);
-               return getcpy(buffer);
-       }
+/*
+**  Expand folder path
+**  Convert rel folpaths (@) into abs folpaths
+**  dir paths are simply passed through
+**  Returns the abs folpath (without prefix), in static mem
+**
+**  TODO: Always copy into the static buffer, or just return the pointer?
+*/
+char *
+expandfol(char *f)
+{
+       static char buf[BUFSIZ];
+
+       if (*f == '@') {
+               /* f = concat(getcurfol(), "/", f+1, NULL); */
+               snprintf(buf, sizeof buf, "%s/%s", getcurfol(), f+1);
+
+       } else if (*f == '+') {
+               strcpy(buf, f+1);
 
-       if (strncmp(name, "../", 3) == 0) {
-               name += 3;
        } else {
-               cp = ep;
+               strcpy(buf, f);
        }
-
-       snprintf(buffer, sizeof(buffer), "%.*s/%s",
-                       (int)(cp - pwds), pwds, name);
-       return getcpy(buffer);
+       packpath(buf);
+       return buf;
 }
 
 
 /*
-** Return a path name
+**  Expand directory path
+**  Convert rel dirpath into abs dirpath
+**  The argument is assumed to be a dir path relative to the cwd,
+**  except when beginning with '/' (then it will be passed through).
+**  Returns the abs dirpath, in static mem
+**
+**  TODO: Always copy into the static buffer, or just return the pointer?
 */
 char *
-path(char *name, int type)
+expanddir(char *d)
 {
-       char *cp, *ep;
+       static char buf[BUFSIZ];
 
-       if ((cp = expath(name, type)) &&
-                       (ep = cp+strlen(cp)-1) > cp &&
-                       *ep == '/') {
-               *ep = '\0';
+       if (*d == '/') {
+               strcpy(buf, d);
+       } else {
+               getcwd(buf, sizeof buf);
+               int len = strlen(buf);
+               snprintf(buf+len, sizeof buf - len, "/%s", d);
        }
-
-       return cp;
+       packpath(buf);
+       return buf;
 }
 
 
 /*
-** Call path() appropriately for ``+folder'' or ``@folder''
+**  Anypath to absolute directory path
+**  Convert any kind of path into an abs dirpath
+**  A path without distinguishing prefix is assumed to be an abs folpath
+**  Abs dirpaths are passed unchanged
+**  Rel dirpaths ('.') get prefixed with the (abs) cwd
+**  Return pointer to static memory
+**
+**  To get the dir path of the mail storage root, call: toabsdir("+")
+**
+**  TODO: check lengths for copies
 */
 char *
-pluspath(char *name)
+toabsdir(char *path)
 {
-       switch (*name) {
-       case '+':
-               return path(name+1, TFOLDER);
-       case '@':
-               return path(name+1, TSUBCWF);
-       default:
-               return path(name, TFILE);
+       static char buf[BUFSIZ];
+
+       if (*path == '/') {
+               /* nothing to do */
+               strncpy(buf, path, sizeof buf);
+               packpath(buf);
+               return buf;
+
+       } else if (*path == '.') {
+               /* rel dir path */
+               strncpy(buf, expanddir(path), sizeof buf);
+               return buf;
+
+       } else {
+               /* folder path */
+               char *cp=buf, *pp;
+
+               if (!(pp = context_find("path")) || !*pp) {
+                       adios(NULL, "Non-empty profile entry `Path' required");
+               }
+               if (*pp != '/') {
+                       /* Path is relative to $HOME */
+                       snprintf(buf, sizeof buf, "%s/", mypath);
+                       cp += strlen(buf);
+               }
+               strcpy(cp, pp);
+               packpath(buf);
+               /* append the mail folder */
+               cp = buf + strlen(buf);
+               *cp++ = '/';
+               strcpy(cp, expandfol(path));
+               return buf;
        }
 }