GUACAMOLE-637: Simplify SFTP path normalization logic. Correct behavior to match documentation.
This commit is contained in:
parent
591e494dfd
commit
1591980579
@ -36,77 +36,66 @@
|
|||||||
int guac_common_ssh_sftp_normalize_path(char* fullpath,
|
int guac_common_ssh_sftp_normalize_path(char* fullpath,
|
||||||
const char* path) {
|
const char* path) {
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
int path_depth = 0;
|
int path_depth = 0;
|
||||||
char path_component_data[GUAC_COMMON_SSH_SFTP_MAX_PATH];
|
|
||||||
const char* path_components[GUAC_COMMON_SSH_SFTP_MAX_DEPTH];
|
const char* path_components[GUAC_COMMON_SSH_SFTP_MAX_DEPTH];
|
||||||
|
|
||||||
const char* current_path_component_data = &(path_component_data[0]);
|
|
||||||
|
|
||||||
/* If original path is not absolute, normalization fails */
|
/* If original path is not absolute, normalization fails */
|
||||||
if (path[0] != '\\' && path[0] != '/')
|
if (path[0] != '\\' && path[0] != '/')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Skip past leading slash */
|
/* Create scratch copy of path excluding leading slash (we will be
|
||||||
path++;
|
* replacing path separators with null terminators and referencing those
|
||||||
|
* substrings directly as path components) */
|
||||||
|
char path_scratch[GUAC_COMMON_SSH_SFTP_MAX_PATH - 1];
|
||||||
|
int length = guac_strlcpy(path_scratch, path + 1,
|
||||||
|
sizeof(path_scratch));
|
||||||
|
|
||||||
/* Copy path into component data for parsing */
|
/* Fail if provided path is too long */
|
||||||
int length = guac_strlcpy(path_component_data, path,
|
if (length >= sizeof(path_scratch))
|
||||||
sizeof(path_component_data));
|
|
||||||
|
|
||||||
/* Fail if input path was truncated */
|
|
||||||
if (length >= sizeof(path_component_data))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Find path components within path */
|
/* Locate all path components within path */
|
||||||
for (i = 0; i < sizeof(path_component_data); i++) {
|
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 */
|
/* If current character is a path separator, parse as component */
|
||||||
char c = path_component_data[i];
|
char c = path_scratch[i];
|
||||||
if (c == '/' || c == '\\' || c == '\0') {
|
if (c == '/' || c == '\\' || c == '\0') {
|
||||||
|
|
||||||
/* Terminate current component */
|
/* Terminate current component */
|
||||||
path_component_data[i] = '\0';
|
path_scratch[i] = '\0';
|
||||||
|
|
||||||
/* If component refers to parent, just move up in depth */
|
/* If component refers to parent, just move up in depth */
|
||||||
if (strcmp(current_path_component_data, "..") == 0) {
|
if (strcmp(current_path_component, "..") == 0) {
|
||||||
if (path_depth > 0)
|
if (path_depth > 0)
|
||||||
path_depth--;
|
path_depth--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, if component not current directory, add to list */
|
/* Otherwise, if component not current directory, add to list */
|
||||||
else if (strcmp(current_path_component_data, ".") != 0
|
else if (strcmp(current_path_component, ".") != 0
|
||||||
&& strcmp(current_path_component_data, "") != 0) {
|
&& strcmp(current_path_component, "") != 0) {
|
||||||
|
|
||||||
/* Fail normalization if path is too deep */
|
/* Fail normalization if path is too deep */
|
||||||
if (path_depth >= GUAC_COMMON_SSH_SFTP_MAX_DEPTH)
|
if (path_depth >= GUAC_COMMON_SSH_SFTP_MAX_DEPTH)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
path_components[path_depth++] = current_path_component_data;
|
path_components[path_depth++] = current_path_component;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If end of string, stop */
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Update start of next component */
|
/* Update start of next component */
|
||||||
current_path_component_data = &(path_component_data[i+1]);
|
current_path_component = &(path_scratch[i+1]);
|
||||||
|
|
||||||
} /* end if separator */
|
} /* end if separator */
|
||||||
|
|
||||||
} /* end for each character */
|
} /* end for each character */
|
||||||
|
|
||||||
/* If no components, the path is simply root */
|
/* Add leading slash for resulting absolute path */
|
||||||
if (path_depth == 0) {
|
fullpath[0] = '/';
|
||||||
strcpy(fullpath, "/");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert components back into path */
|
/* Append normalized components to path, separated by slashes */
|
||||||
guac_strljoin(fullpath, path_components, path_depth,
|
guac_strljoin(fullpath + 1, path_components, path_depth,
|
||||||
"/", GUAC_COMMON_SSH_SFTP_MAX_PATH);
|
"/", GUAC_COMMON_SSH_SFTP_MAX_PATH - 1);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user