int guac_common_ssh_sftp_normalize_path()

in src/common-ssh/sftp.c [37:103]


int guac_common_ssh_sftp_normalize_path(char* fullpath,
        const char* path) {

    int path_depth = 0;
    const char* path_components[GUAC_COMMON_SSH_SFTP_MAX_DEPTH];

    /* If original path is not absolute, normalization fails */
    if (path[0] != '\\' && path[0] != '/')
        return 0;

    /* 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_COMMON_SSH_SFTP_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 0;

    /* 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_COMMON_SSH_SFTP_MAX_DEPTH)
                    return 0;

                path_components[path_depth++] = current_path_component;

            }

            /* Update start of next component */
            current_path_component = &(path_scratch[i+1]);

        } /* end if separator */

    } /* end for each character */

    /* Add leading slash for resulting absolute path */
    fullpath[0] = '/';

    /* Append normalized components to path, separated by slashes */
    guac_strljoin(fullpath + 1, path_components, path_depth,
            "/", GUAC_COMMON_SSH_SFTP_MAX_PATH - 1);

    return 1;

}