int UnLslR(const FTPCIPtr cip, FTPFileInfoListPtr filp, FTPLineListPtr llp, int serverType) { char curdir[512]; char line[512]; int len; size_t curdirlen = 0; char fname[256]; char linkto[256]; char *cp; longest_int fsize; int ftype; time_t ftime, now; int thisyear; struct tm nowtm; int rc; FTPLinePtr lp; FTPFileInfo fi; int linesread = 0; int linesconverted = 0; size_t maxFileLen = 0; size_t maxPlugLen = 0; size_t fileLen; int plugend; int skipdir = 0; size_t cwdlen; if (Localtime(time(&now), &nowtm) == NULL) thisyear = 1970; /* should never happen */ else thisyear = nowtm.tm_year + 1900; curdir[0] = '\0'; cip->buf[0] = '\0'; cwdlen = 0; InitFileInfoList(filp); for (lp = llp->first; lp != NULL; lp = lp->next) { len = (int) strlen(STRNCPY(line, lp->line)); for (cp = line; ; cp++) { if ((*cp == '\0') || (!isspace((int) *cp))) break; } if (*cp == '\0') { /* Entire line was blank. */ /* separator line between dirs */ continue; } if (serverType == kServerTypeMicrosoftFTP) { /* IIS runs on WinNT only, and NT * can use / as a separator rather * that \. We will convert them * here. */ for (cp = line; *cp != '\0'; cp++) { if (*cp == '\\') *cp = '/'; } } linesread++; rc = UnLslRLine(line, curdir, curdirlen, fname, sizeof(fname), linkto, sizeof(linkto), &ftype, &fsize, &ftime, now, thisyear, &plugend); if ((rc < 0) && (serverType == kServerTypeMicrosoftFTP)) { rc = UnDosLine(line, curdir, curdirlen, fname, sizeof(fname), &ftype, &fsize, &ftime); if (rc == 0) { *linkto = '\0'; plugend = 0; } } if (rc == 0) { if (skipdir != 0) continue; cp = fname + curdirlen; if ((cp[0] == '.') && ((cp[1] == '\0') || ((cp[1] == '.') && (cp[2] == '\0')))) continue; /* ignore . and .. */ linesconverted++; cp = fname; if ((cp[0] == '.') && ((cp[1] == '/') || (cp[1] == '\\'))) cp += 2; if ((*cp == '/') || (*cp == '\\')) { /* Absolute pathnames not allowed unless * they are in the cwd. */ if (cip->buf[0] == '\0') { (void) FTPGetCWD(cip, cip->buf, cip->bufSize); cwdlen = strlen(cip->buf); } /* In root directory (cwdlen == 1), paths * from root are OK. */ if (cwdlen > 1) { if (memcmp(cp, cip->buf, cwdlen) == 0) { /* Abs path prefixed with cwd */ cp += cwdlen; if ((*cp == '/') || (*cp == '\\')) cp++; } else { /* Abs path not prefixed with cwd */ continue; } } } if (PathContainsIntermediateDotDotSubDir(cp)) continue; fileLen = strlen(cp); if (fileLen > maxFileLen) maxFileLen = fileLen; fi.relnameLen = fileLen; fi.relname = StrDup(cp); fi.rname = NULL; fi.lname = NULL; fi.rlinkto = (linkto[0] == '\0') ? NULL : StrDup(linkto); fi.mdtm = ftime; fi.size = (longest_int) fsize; fi.type = ftype; fi.mode = -1; if (plugend > 0) { fi.plug = (char *) malloc((size_t) plugend + 1); if (fi.plug != NULL) { (void) memcpy(fi.plug, line, (size_t) plugend); fi.plug[plugend] = '\0'; if ((size_t) plugend > maxPlugLen) maxPlugLen = (size_t) plugend; } } else { fi.plug = (char *) malloc(32 + 1); if (fi.plug != NULL) { (void) strcpy(fi.plug, "---------- 1 ftpuser ftpusers"); fi.plug[0] = (char) ftype; if (32 > maxPlugLen) maxPlugLen = (size_t) 32; } } (void) AddFileInfo(filp, &fi); } else if ((rc < 0) && (line[len - 1] == ':')) { if ((line[0] == '.') && (line[1] == '/')) { line[len - 1] = '/'; (void) memcpy(curdir, line + 2, (size_t) len + 1 - 2); curdirlen = (size_t) (len - 2); } else if ((line[0] == '.') && (line[1] == '\\')) { line[len - 1] = '\\'; (void) memcpy(curdir, line + 2, (size_t) len + 1 - 2); curdirlen = (size_t) (len - 2); } else { line[len - 1] = '/'; (void) memcpy(curdir, line, (size_t) len + 1); curdirlen = (size_t) len; } skipdir = 0; cp = curdir; if ((*cp == '/') || (*cp == '\\')) { skipdir = 1; /* absolute pathnames not allowed */ if (cip->buf[0] == '\0') { (void) FTPGetCWD(cip, cip->buf, cip->bufSize); cwdlen = strlen(cip->buf); } if (cwdlen == 1) { /* In root directory, so paths * from root are OK. */ skipdir = 0; } else { if (memcmp(cp, cip->buf, cwdlen) == 0) { cp += cwdlen; if ((*cp == '/') || (*cp == '\\')) cp++; memmove(curdir, cp, strlen(cp) + 1); skipdir = 0; cp = curdir; } } } if (PathContainsIntermediateDotDotSubDir(cp)) { skipdir = 1; } } } filp->maxFileLen = maxFileLen; filp->maxPlugLen = maxPlugLen; if (linesread == 0) return (0); return ((linesconverted > 0) ? linesconverted : (-1)); } /* UnLslR */
int UnMlsD(const FTPCIPtr cip, FTPFileInfoListPtr filp, FTPLineListPtr llp) { MLstItem mli; char plug[64]; char og[32]; int rc; FTPLinePtr lp; FTPFileInfo fi; int linesread = 0; int linesconverted = 0; int linesignored = 0; size_t maxFileLen = 0; size_t maxPlugLen = 0; size_t fileLen, plugLen; int m1, m2, m3; const char *cm1, *cm2, *cm3; InitFileInfoList(filp); for (lp = llp->first; lp != NULL; lp = lp->next) { linesread++; rc = UnMlsT(cip, lp->line, &mli); if (rc == 0) { if (PathContainsIntermediateDotDotSubDir(mli.fname)) { linesignored++; continue; } fileLen = strlen(mli.fname); linesconverted++; if (fileLen > maxFileLen) maxFileLen = fileLen; fi.relnameLen = fileLen; fi.relname = StrDup(mli.fname); fi.rname = NULL; fi.lname = NULL; fi.rlinkto = (mli.linkto[0] == '\0') ? NULL : StrDup(mli.linkto); fi.mdtm = mli.ftime; fi.size = (longest_int) mli.fsize; fi.type = mli.ftype; fi.mode = -1; plug[0] = (char) mli.ftype; plug[1] = '\0'; m1 = 0; m2 = 0; m3 = -1; if (mli.mode != (-1)) { fi.mode = mli.mode; m1 = (mli.mode & 00700) >> 6; m2 = (mli.mode & 00070) >> 3; m3 = (mli.mode & 00007); } if (mli.perm[0] != '\0') { m3 = 0; if (fi.type == 'd') { if (strchr(mli.perm, 'e') != NULL) { /* execute -> execute */ m3 |= 00001; } if (strchr(mli.perm, 'c') != NULL) { /* create -> write */ m3 |= 00002; } if (strchr(mli.perm, 'l') != NULL) { /* list -> read */ m3 |= 00004; } } else { if (strchr(mli.perm, 'w') != NULL) { /* write -> write */ m3 |= 00002; } if (strchr(mli.perm, 'r') != NULL) { /* read -> read */ m3 |= 00004; } } } if (m3 != (-1)) { cm1 = rwx[m1]; cm2 = rwx[m2]; cm3 = rwx[m3]; sprintf(plug + 1, "%s%s%s", cm1, cm2, cm3); } if (mli.owner[0] != '\0') { if (mli.group[0] != '\0') { #ifdef HAVE_SNPRINTF snprintf(og, sizeof(og) - 1, #else sprintf(og, #endif /* HAVE_SNPRINTF */ " %-8.8s %s", mli.owner, mli.group ); STRNCAT(plug, og); } else { STRNCAT(plug, " "); STRNCAT(plug, mli.owner); } }
void RemoteGlobCollapse(const FTPCIPtr cip, const char *pattern, FTPLineListPtr fileList) { FTPLinePtr lp, nextLine; char *patPrefix; char *patDir; char *cur, *prev; char *cp; char *newpath; size_t plen; /* Copy all characters before and including the last path delimiter. */ patDir = NULL; cp = StrRFindLocalPathDelim(pattern); if (cp != NULL) { patDir = StrDup(pattern); if (patDir == NULL) return; patDir[(cp - pattern) + 1] = '\0'; } /* Copy all characters before the first glob-char. */ cp = strpbrk(pattern, kGlobChars); patPrefix = StrDup(pattern); if (patPrefix == NULL) { free(patDir); return; } if (cp != NULL) { plen = (size_t) (cp - pattern); patPrefix[plen] = '\0'; } else { plen = strlen(patPrefix); } cur = prev = NULL; for (lp=fileList->first; lp != NULL; lp = nextLine) { nextLine = lp->next; if (ISTRNEQ(lp->line, patPrefix, plen)) { if (Dynsrecpy(&cur, lp->line + plen, 0) == NULL) goto done; cp = strpbrk(cur, "/\\"); if (cp != NULL) *cp = '\0'; if ((prev != NULL) && (STREQ(cur, prev))) { PrintF(cip, " Rglob omitted: [%s] (type 2)\n", lp->line); nextLine = RemoveLine(fileList, lp); } else if (PathContainsIntermediateDotDotSubDir(lp->line + plen)) { PrintF(cip, " Rglob omitted: [%s] (type 3)\n", lp->line); nextLine = RemoveLine(fileList, lp); } else { if (Dynsrecpy(&prev, cur, 0) == NULL) goto done; /* We are playing with a dynamically * allocated string, but since the * following expression is guaranteed * to be the same or shorter, we won't * overwrite the bounds. */ (void) sprintf(lp->line, "%s%s", patPrefix, cur); } } else if (strpbrk(lp->line, "/\\") == NULL) { if (patDir != NULL) { newpath = NULL; if (Dynsrecpy(&newpath, patDir, lp->line, 0) == NULL) goto done; PrintF(cip, " Rglob changed: [%s] to [%s]\n", lp->line, newpath); free(lp->line); lp->line = newpath; } } else { PrintF(cip, " Rglob omitted: [%s] (type 4)\n", lp->line); nextLine = RemoveLine(fileList, lp); } } done: StrFree(&patDir); StrFree(&patPrefix); StrFree(&cur); StrFree(&prev); } /* RemoteGlobCollapse */