int guac_rdp_fs_normalize_path()

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;

}