diff options
Diffstat (limited to 'src/path.c')
-rw-r--r-- | src/path.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/path.c b/src/path.c index e4b49f35d..8c1bd41eb 100644 --- a/src/path.c +++ b/src/path.c @@ -237,3 +237,77 @@ void git_path_string_to_dir(char* path, size_t size) } } +int git__percent_decode(git_buf *decoded_out, const char *input) +{ + int len, hi, lo, i, error = GIT_SUCCESS; + assert(decoded_out && input); + + len = strlen(input); + git_buf_clear(decoded_out); + + for(i = 0; i < len; i++) + { + char c = input[i]; + + if (c != '%') + goto append; + + if (i >= len - 2) + goto append; + + hi = git__fromhex(input[i + 1]); + lo = git__fromhex(input[i + 2]); + + if (hi < 0 || lo < 0) + goto append; + + c = (char)(hi << 4 | lo); + i += 2; + +append: + error = git_buf_putc(decoded_out, c); + if (error < GIT_SUCCESS) + return git__rethrow(error, "Failed to percent decode '%s'.", input); + } + + return error; +} + +int git_path_fromurl(git_buf *local_path_out, const char *file_url) +{ + int error = GIT_SUCCESS, offset = 0, len; + + assert(local_path_out && file_url); + + if (git__prefixcmp(file_url, "file://") != 0) + return git__throw(GIT_EINVALIDPATH, + "Parsing of '%s' failed. A file Uri is expected (ie. with 'file://' scheme).", + file_url); + + offset += 7; + len = strlen(file_url); + + if (offset < len && file_url[offset] == '/') + offset++; + else if (offset < len && git__prefixcmp(file_url + offset, "localhost/") == 0) + offset += 10; + else + return git__throw(GIT_EINVALIDPATH, + "Parsing of '%s' failed. A local file Uri is expected.", file_url); + + if (offset >= len || file_url[offset] == '/') + return git__throw(GIT_EINVALIDPATH, + "Parsing of '%s' failed. Invalid file Uri format.", file_url); + +#ifndef _MSC_VER + offset--; /* A *nix absolute path starts with a forward slash */ +#endif + + git_buf_clear(local_path_out); + + error = git__percent_decode(local_path_out, file_url + offset); + if (error < GIT_SUCCESS) + return git__rethrow(error, "Parsing of '%s' failed.", file_url); + + return error; +} |