in src/protocols/rdp/fs.c [630:699]
int guac_rdp_fs_normalize_path(const char* path, char* abs_path) {
int path_depth = 0;
const char* path_components[GUAC_RDP_MAX_PATH_DEPTH];
/* If original path is not absolute, normalization fails */
if (path[0] != '\\' && path[0] != '/')
return 1;
/* Create scratch copy of path excluding leading slash (we will be
* replacing path separators with null terminators and referencing those
* substrings directly as path components) */
char path_scratch[GUAC_RDP_FS_MAX_PATH - 1];
int length = guac_strlcpy(path_scratch, path + 1,
sizeof(path_scratch));
/* Fail if provided path is too long */
if (length >= sizeof(path_scratch))
return 1;
/* Locate all path components within path */
const char* current_path_component = &(path_scratch[0]);
for (int i = 0; i <= length; i++) {
/* If current character is a path separator, parse as component */
char c = path_scratch[i];
if (c == '/' || c == '\\' || c == '\0') {
/* Terminate current component */
path_scratch[i] = '\0';
/* If component refers to parent, just move up in depth */
if (strcmp(current_path_component, "..") == 0) {
if (path_depth > 0)
path_depth--;
}
/* Otherwise, if component not current directory, add to list */
else if (strcmp(current_path_component, ".") != 0
&& strcmp(current_path_component, "") != 0) {
/* Fail normalization if path is too deep */
if (path_depth >= GUAC_RDP_MAX_PATH_DEPTH)
return 1;
path_components[path_depth++] = current_path_component;
}
/* Update start of next component */
current_path_component = &(path_scratch[i+1]);
} /* end if separator */
/* We do not currently support named streams */
else if (c == ':')
return 1;
} /* end for each character */
/* Add leading slash for resulting absolute path */
abs_path[0] = '\\';
/* Append normalized components to path, separated by slashes */
guac_strljoin(abs_path + 1, path_components, path_depth,
"\\", GUAC_RDP_FS_MAX_PATH - 1);
return 0;
}