/** Removes "." and ".." from a path */ char *getCanonicalPath(const char *path){ char *prefix = NULL; char *rest = NULL; char *tmp = NULL; size_t offset = 0; char **src = NULL; List *dst = NULL; size_t ii = 0; Buffer *buf = NULL; char *result = NULL; if (path != NULL && strlen(path) > 0) { tmp = strxreplace(astrcpy(path), '\\', '/'); if (isDosPath(tmp) || isUncPath(tmp)) { if (isDosPath(tmp)) { prefix = getPathPart(tmp, PATH_DRIVE); offset = 0; } else if (isUncPath(tmp)) { prefix = getPathPart(tmp, PATH_HOST); offset = 2; } rest = astrcpy(strchr(&tmp[offset], '/')); } else { rest = astrcpy(tmp); } src = astrtok(rest, "/"); dst = new_List(); while (src[ii] != NULL) { if (strxequals(src[ii], "..")) { List_remove(dst, -1, false); } else if (!strxequals(src[ii], ".")) { List_append(dst, src[ii]); } ii++; } buf = new_Buffer(0); if (prefix != NULL) { Buffer_appendString(buf, prefix); } for (ii = 0; ii < List_length(dst); ++ii) { Buffer_appendString(buf, List_get(dst, ii)); if (ii != (List_length(dst) - 1)) { Buffer_appendChar(buf, '/'); } } result = astrcpy(buf->data); delete_Buffer(buf); delete_List(dst, false); astrtokfree(src); mu_free(prefix); mu_free(rest); mu_free(tmp); } return result; }
/** Joins two paths together, allowing for relative/absolute paths */ char *getCombinedPath(const char *path1, const char *path2) { char *tmp1 = NULL; char *tmp2 = NULL; char *tmp = NULL; Buffer *buf = NULL; char *result = NULL; char *final = NULL; if (!strxnullorempty(path1) && !strxnullorempty(path2)) { tmp1 = strxreplace(astrcpy(path1), '\\', '/'); tmp2 = strxreplace(astrcpy(path2), '\\', '/'); if (isDosPath(tmp2) || isUncPath(tmp2)) { /* Path2 is a fully-qualified DOS/Windows path; return it */ result = astrcpy(tmp2); } else { buf = new_Buffer(0); if (tmp2[0] == '/') { /* Path2 is an absolute path. If Path1 is a DOS/Windows or ** UNC path, prepend the drive letter or hostname; otherwise ** return it. */ if (isDosPath(tmp1)) { tmp = getPathPart(tmp1, PATH_DRIVE); Buffer_appendString(buf, tmp); Buffer_appendString(buf, tmp2); mu_free(tmp); } else if (isUncPath(tmp1)) { tmp = getPathPart(tmp1, PATH_HOST); Buffer_appendString(buf, "//"); Buffer_appendString(buf, tmp); Buffer_appendString(buf, tmp2); mu_free(tmp); } else { Buffer_appendString(buf, tmp2); } } else { /* Simply concatenate the two paths */ Buffer_appendString(buf, tmp1); if (tmp1[strlen(tmp1) - 1] != '/') { Buffer_appendChar(buf, '/'); } Buffer_appendString(buf, tmp2); } result = astrcpy(buf->data); delete_Buffer(buf); } mu_free(tmp1); mu_free(tmp2); } /* Remove any "." and ".." in the path */ final = getCanonicalPath(result);
/*! \internal */ QString QFSFileEnginePrivate::longFileName(const QString &path) { if (path.startsWith(QLatin1String("\\\\.\\"))) return path; QString absPath = QFileSystemEngine::nativeAbsoluteFilePath(path); #if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QString prefix = QLatin1String("\\\\?\\"); if (isUncPath(absPath)) { prefix.append(QLatin1String("UNC\\")); // "\\\\?\\UNC\\" absPath.remove(0, 2); } return prefix + absPath; #else return absPath; #endif }
/** Returns a part of a directory path */ char *getPathPart(const char *path, PathPart part) { char *result = NULL; char *tmp1 = NULL; char *tmp2 = NULL; size_t pos = 0; if (path != NULL && strlen(path) > 0) { tmp1 = strxreplace(astrcpy(path), '\\', '/'); switch(part){ case PATH_HOST: if (isUncPath(tmp1)) { tmp2 = &tmp1[2]; if (strxpos(tmp2, '/', &pos)) { result = astrleft(tmp2, pos); } else { result = astrcpy(tmp2); } } else { result = astrcpy(""); } break; case PATH_DRIVE: if (isDosPath(tmp1)) { result = astrleft(tmp1, 2); } else { result = astrcpy(""); } break; case PATH_DIR: if (isUncPath(tmp1) || isDosPath(tmp1)) { tmp2 = strchr(&tmp1[2], '/'); } else { tmp2 = tmp1; } if (tmp2 != NULL) { if (strxrpos(tmp2, '/', &pos)) { if (pos == 0) { result = astrcpy(tmp2); } else { result = astrleft(tmp2, pos); } } else { result = astrcpy(""); } } else { result = astrcpy(""); } break; case PATH_FILE: case PATH_FILEONLY: if ((tmp2 = strrchr(tmp1, '/')) != NULL) { result = &tmp2[1]; } else { result = tmp1; } if (part == PATH_FILE) { result = astrcpy(result); } else if (part == PATH_FILEONLY) { /* Strip off file extension */ if (strxrpos(result, '.', &pos)) { if(pos == 0) { result = astrcpy(result); } else { result = astrleft(result, pos); } } else { result = astrcpy(result); } } break; case PATH_EXT: if ((tmp2 = strrchr(tmp1, '.')) != NULL) { if (strchr(tmp2, '/') == NULL) { result = astrcpy(&tmp2[1]); } else { result = astrcpy(""); } } else { result = astrcpy(""); } break; default: result = astrcpy(""); break; } mu_free(tmp1); } return result; }