X-Git-Url: http://git.marmaro.de/?a=blobdiff_plain;f=sbr%2Fpath.c;h=b3a8fff58ac81de6ace96c9c331ab243626fb267;hb=097c84b61603c4a4c5837f3dcc09c30a1e751702;hp=a01385fad05d094a08dc6027f2a10dad106aed69;hpb=a485ed478abbd599d8c9aab48934e7a26733ecb1;p=mmh diff --git a/sbr/path.c b/sbr/path.c index a01385f..b3a8fff 100644 --- a/sbr/path.c +++ b/sbr/path.c @@ -1,163 +1,193 @@ /* - * path.c -- return a pathname - * - * This code is Copyright (c) 2002, by the authors of nmh. See the - * COPYRIGHT file in the root directory of the nmh distribution for - * complete copyright information. - */ +** path.c -- return a pathname +** +** This code is Copyright (c) 2002, by the authors of nmh. See the +** COPYRIGHT file in the root directory of the nmh distribution for +** complete copyright information. +*/ #include -#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 *); -char * -pluspath(char *name) +/* +** 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 +packpath(char *f) { - return path(name + 1, *name == '+' ? TFOLDER : TSUBCWF); -} + char *cp, *dp; + int abspath; -char * -path(char *name, int flag) -{ - register char *cp, *ep; + if (!f || !*f) { + return; + } + abspath = (*f == '/'); - if ((cp = expath (name, flag)) - && (ep = cp + strlen (cp) - 1) > cp - && *ep == '/') - *ep = '\0'; + for (cp=f; *cp; ) { + if (*cp != '/') { + /* Skip. Interesting places are only after slashes. */ + /* We don't care about "./" beginnings */ + cp++; + continue; + } - return cp; + /* Let's see what follows the slash ... */ + switch (*++cp) { + case '\0': + *--cp = '\0'; + continue; /* ... and thus exit the loop */ + + 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; + } + + default: + /* nothing special */ + cp++; + continue; + } + } + + if (!strlen(f)) { + /* We have removed everything, but need something. */ + strcpy(f, abspath ? "/" : "."); + } } +/* +** +*/ 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) { - snprintf (buffer, sizeof(buffer), "%s/%s", getfolder (1), name); - name = m_mailpath (buffer); - compath (name); - snprintf (buffer, sizeof(buffer), "%s/", m_maildir ("")); - if (ssequal (buffer, name)) { + if (type == TSUBCWF) { + /* @folder to +folder */ + 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); + 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)))) - return getcpy (name); + if (*name == '/') { + return getcpy(name); + } - if (pwds == NULL) - pwds = pwd (); + 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 (strcmp (name, DOT) == 0 || strcmp (name, CWD) == 0) - return getcpy (pwds); + if (pwds == NULL) { + pwds = pwd(); + } - ep = pwds + strlen (pwds); - if ((cp = strrchr(pwds, '/')) == NULL) + if (strcmp(name, ".") == 0 || strcmp(name, "./") == 0) { + return getcpy(pwds); + } + + ep = pwds + strlen(pwds); + 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); - return getcpy (buffer); + 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); - return getcpy (buffer); + snprintf(buffer, sizeof(buffer), "%.*s/%s", + (int)(cp - pwds), pwds, name); + return getcpy(buffer); } -static void -compath (char *f) +/* +** +*/ +char * +path(char *name, int type) { - register char *cp, *dp; + char *cp, *ep; - if (*f != '/') - return; + if ((cp = expath(name, type)) && + (ep = cp+strlen(cp)-1) > cp && + *ep == '/') { + *ep = '\0'; + } - 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; + return cp; +} - 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; - default: - cp++; - continue; - } - break; - } else - cp++; +/* +** Call path() appropriately for ``+folder'' or ``@folder'' +*/ +char * +pluspath(char *name) +{ + return path(name+1, (*name == '+') ? TFOLDER : TSUBCWF); }