#include <h/mh.h>
-#define CWD "./"
-#define NCWD (sizeof(CWD) - 1)
-#define DOT "."
-#define DOTDOT ".."
-#define PWD "../"
-#define NPWD (sizeof(PWD) - 1)
-
static char *pwds;
/*
** static prototypes
*/
-static char *expath(char *,int);
-static void compath(char *);
+static char *expath(char *, int);
+static void packpath(char *);
char *
pluspath(char *name)
}
char *
-path(char *name, int flag)
+path(char *name, int type)
{
- register char *cp, *ep;
+ char *cp, *ep;
- if ((cp = expath(name, flag))
- && (ep = cp + strlen(cp) - 1) > cp
- && *ep == '/')
+ if ((cp = expath(name, type)) &&
+ (ep = cp+strlen(cp)-1) > cp &&
+ *ep == '/') {
*ep = '\0';
+ }
return cp;
}
static char *
-expath(char *name, int flag)
+expath(char *name, int type)
{
- register char *cp, *ep;
+ char *cp, *ep;
char buffer[BUFSIZ];
- if (flag == TSUBCWF) {
+ if (type == TSUBCWF) {
+ /* @folder to +folder */
snprintf(buffer, sizeof(buffer), "%s/%s", getfolder(1), name);
name = m_mailpath(buffer);
- compath(name);
+ packpath(name);
snprintf(buffer, sizeof(buffer), "%s/", m_maildir(""));
if (isprefix(buffer, name)) {
cp = name;
name = getcpy(name + strlen(buffer));
free(cp);
}
- flag = TFOLDER;
+ type = TFOLDER;
}
- if (*name == '/' || (flag == TFOLDER
- && (strncmp(name, CWD, NCWD) && strcmp(name, DOT)
- && strcmp(name, DOTDOT) && strncmp(name, PWD, NPWD))))
+ if (*name == '/') {
return getcpy(name);
+ }
- if (pwds == NULL)
+ 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 (pwds == NULL) {
pwds = pwd();
+ }
- if (strcmp(name, DOT) == 0 || strcmp(name, CWD) == 0)
+ if (strcmp(name, ".") == 0 || strcmp(name, "./") == 0) {
return getcpy(pwds);
+ }
ep = pwds + strlen(pwds);
- if ((cp = strrchr(pwds, '/')) == NULL)
+ if ((cp = strrchr(pwds, '/')) == NULL) {
cp = ep;
- else
- if (cp == pwds)
- cp++;
+ } else if (cp == pwds) {
+ cp++;
+ }
- if (strncmp(name, CWD, NCWD) == 0)
- name += NCWD;
+ if (strncmp(name, "./", 2) == 0) {
+ name += 2;
+ }
- if (strcmp(name, DOTDOT) == 0 || strcmp(name, PWD) == 0) {
- snprintf(buffer, sizeof(buffer), "%.*s", (int)(cp - pwds), pwds);
+ if (strcmp(name, "..") == 0 || strcmp(name, "../") == 0) {
+ snprintf(buffer, sizeof(buffer), "%.*s",
+ (int)(cp - pwds), pwds);
return getcpy(buffer);
}
- if (strncmp(name, PWD, NPWD) == 0)
- name += NPWD;
- else
+ if (strncmp(name, "../", 3) == 0) {
+ name += 3;
+ } else {
cp = ep;
+ }
- snprintf(buffer, sizeof(buffer), "%.*s/%s", (int)(cp - pwds), pwds, name);
+ snprintf(buffer, sizeof(buffer), "%.*s/%s",
+ (int)(cp - pwds), pwds, name);
return getcpy(buffer);
}
+/*
+** Compactify an absolute path name by removing unneccessary parts.
+** Removes trailing slashes, but not if it would empty the string then.
+** Modifies f.
+*/
static void
-compath(char *f)
+packpath(char *f)
{
- register char *cp, *dp;
+ char *cp, *dp;
+ int abspath;
- if (*f != '/')
+ if (!f || !*f) {
return;
+ }
+ abspath = (*f == '/');
- for (cp = f; *cp;)
- if (*cp == '/') {
- switch (*++cp) {
- case 0:
- if (--cp > f)
- *cp = '\0';
- break;
-
- case '/':
- for (dp = cp; *dp == '/'; dp++)
- continue;
- strcpy (cp--, dp);
- continue;
+ for (cp=f; *cp; ) {
+ if (*cp != '/') {
+ /* Skip. Interesting places are only after slashes. */
+ /* We don't care about "./" beginnings */
+ cp++;
+ continue;
+ }
- case '.':
- if (strcmp(cp, DOT) == 0) {
- if (cp > f + 1)
- cp--;
- *cp = '\0';
- break;
- }
- if (strcmp(cp, DOTDOT) == 0) {
- for (cp -= 2; cp > f; cp--)
- if (*cp == '/')
- break;
- if (cp <= f)
- cp = f + 1;
- *cp = '\0';
- break;
- }
- if (strncmp(cp, PWD, NPWD) == 0) {
- for (dp = cp - 2; dp > f; dp--)
- if (*dp == '/')
- break;
- if (dp <= f)
- dp = f;
- strcpy(dp, cp + NPWD - 1);
- cp = dp;
- continue;
- }
- if (strncmp(cp, CWD, NCWD) == 0) {
- strcpy(cp - 1, cp + NCWD - 1);
- cp--;
- continue;
- }
- continue;
+ /* Let's see what follows the slash ... */
+ switch (*++cp) {
+ case '\0':
+ *--cp = '\0';
+ continue; /* ... and thus exit the loop */
- default:
- cp++;
+ case '/':
+ /* reduce subsequent slashes to one */
+ for (dp = cp; *dp == '/'; dp++) {
+ continue;
+ }
+ strcpy(cp, dp);
+ cp--;
+ continue; /* ... at the slash */
+
+ case '.':
+ if (cp[1] == '/' || cp[1] == '\0') {
+ /* one-dot element */
+ strcpy(cp-1, cp+1);
+ cp--;
+ continue;
+ } else if ((strncmp(cp, "../", 3) == 0) ||
+ (strcmp(cp, "..") == 0)) {
+ /* dot-dot element */
+ /* crop out previous path element */
+ for (dp=cp-2; dp>f && *dp!='/'; dp--) {
continue;
+ }
+ if (dp < f) {
+ /* path starts with "/.." */
+ dp = f;
+ }
+ strcpy(dp, cp+2);
+ cp = dp;
+ continue;
+ } else {
+ /* a normal hidden file */
+ cp++;
+ continue;
}
- break;
- } else
+
+ default:
+ /* nothing special */
cp++;
+ continue;
+ }
+ }
+
+ if (!strlen(f)) {
+ /* We have removed everything, but need something. */
+ strcpy(f, abspath ? "/" : ".");
+ }
}