diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/oid.c | 28 | ||||
-rw-r--r-- | src/path.c | 74 | ||||
-rw-r--r-- | src/path.h | 3 | ||||
-rw-r--r-- | src/transports/local.c | 27 | ||||
-rw-r--r-- | src/util.h | 23 |
5 files changed, 120 insertions, 35 deletions
@@ -11,24 +11,6 @@ #include <string.h> #include <limits.h> -static signed char from_hex[] = { --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00 */ --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */ --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20 */ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 30 */ --1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 40 */ --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 50 */ --1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 60 */ --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 */ --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */ --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */ --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a0 */ --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* b0 */ --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* c0 */ --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* d0 */ --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* e0 */ --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* f0 */ -}; static char to_hex[] = "0123456789abcdef"; int git_oid_fromstrn(git_oid *out, const char *str, size_t length) @@ -43,8 +25,8 @@ int git_oid_fromstrn(git_oid *out, const char *str, size_t length) length = GIT_OID_HEXSZ; for (p = 0; p < length - 1; p += 2) { - v = (from_hex[(unsigned char)str[p + 0]] << 4) - | from_hex[(unsigned char)str[p + 1]]; + v = (git__fromhex(str[p + 0]) << 4) + | git__fromhex(str[p + 1]); if (v < 0) return git__throw(GIT_ENOTOID, "Failed to generate sha1. Given string is not a valid sha1 hash"); @@ -53,7 +35,7 @@ int git_oid_fromstrn(git_oid *out, const char *str, size_t length) } if (length % 2) { - v = (from_hex[(unsigned char)str[p + 0]] << 4); + v = (git__fromhex(str[p + 0]) << 4); if (v < 0) return git__throw(GIT_ENOTOID, "Failed to generate sha1. Given string is not a valid sha1 hash"); @@ -346,7 +328,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid) is_leaf = 0; for (i = 0; i < GIT_OID_HEXSZ; ++i) { - int c = from_hex[(int)text_oid[i]]; + int c = git__fromhex(text_oid[i]); trie_node *node; if (c == -1) @@ -360,7 +342,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid) tail = node->tail; node->tail = NULL; - node = push_leaf(os, idx, from_hex[(int)tail[0]], &tail[1]); + node = push_leaf(os, idx, git__fromhex(tail[0]), &tail[1]); if (node == NULL) return GIT_ENOMEM; } 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; +} diff --git a/src/path.h b/src/path.h index 0c8cc349c..c308c5bd4 100644 --- a/src/path.h +++ b/src/path.h @@ -74,4 +74,7 @@ GIT_INLINE(void) git_path_mkposix(char *path) # define git_path_mkposix(p) /* blank */ #endif +extern int git__percent_decode(git_buf *decoded_out, const char *input); +extern int git_path_fromurl(git_buf *local_path_out, const char *file_url); + #endif diff --git a/src/transports/local.c b/src/transports/local.c index 2937da06d..a2135e73e 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -13,6 +13,8 @@ #include "refs.h" #include "transport.h" #include "posix.h" +#include "path.h" +#include "buffer.h" typedef struct { git_transport parent; @@ -148,7 +150,6 @@ static int local_ls(git_transport *transport, git_headlist_cb list_cb, void *pay return GIT_SUCCESS; } - /* * Try to open the url as a git directory. The direction doesn't * matter in this case because we're calulating the heads ourselves. @@ -159,24 +160,26 @@ static int local_connect(git_transport *transport, int GIT_UNUSED(direction)) int error; transport_local *t = (transport_local *) transport; const char *path; + git_buf buf = GIT_BUF_INIT; + GIT_UNUSED_ARG(direction); /* The repo layer doesn't want the prefix */ if (!git__prefixcmp(transport->url, "file://")) { - path = transport->url + strlen("file://"); - -#ifdef _MSC_VER - /* skip the leading slash on windows before the drive letter */ - if (*path != '/') - return git__throw(GIT_EINVALIDPATH, "Invalid local uri '%s'.", transport->url); - - path++; -#endif - - } else + error = git_path_fromurl(&buf, transport->url); + if (error < GIT_SUCCESS) { + git_buf_free(&buf); + return git__rethrow(error, "Failed to parse remote path"); + } + path = git_buf_cstr(&buf); + + } else /* We assume transport->url is already a path */ path = transport->url; error = git_repository_open(&repo, path); + + git_buf_free(&buf); + if (error < GIT_SUCCESS) return git__rethrow(error, "Failed to open remote"); diff --git a/src/util.h b/src/util.h index 2367bb5f3..2654e2de2 100644 --- a/src/util.h +++ b/src/util.h @@ -138,5 +138,28 @@ typedef void (*git_refcount_freeptr)(void *r); #define GIT_REFCOUNT_OWNER(r) (((git_refcount *)(r))->owner) +static signed char from_hex[] = { +-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00 */ +-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */ +-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 30 */ +-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 40 */ +-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 50 */ +-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 60 */ +-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 */ +-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */ +-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */ +-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a0 */ +-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* b0 */ +-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* c0 */ +-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* d0 */ +-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* e0 */ +-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* f0 */ +}; + +GIT_INLINE(int) git__fromhex(char h) +{ + return from_hex[(unsigned char) h]; +} #endif /* INCLUDE_util_h__ */ |