From 1f55b9176248673b78c77ff292fb5c6c988a7f8b Mon Sep 17 00:00:00 2001 From: =?utf-8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= <bombe@xxxxxxxxxxxxxxxxx> Date: Thu, 5 Jun 2008 00:53:56 +0200 Subject: [PATCH] handle http urls with query string ("?foo") correctly --- I'm a developer for the Freenet Project[1] and tried to get git running with Freenet's http-gateway. For several reasons I have to use URLs like "http://host:8888/USK@<lots-of-stuff>/project.git/4?type=text/plain". This breaks the way git creates http URLs to retrieve. The following patch remedys this situation by inserting the git-generated part of the URL (like "/info/refs") before the query string. http-walker.c | 31 ++++++++++++------------------- http.c | 43 ++++++++++++++++++++++++++++++++++--------- http.h | 2 ++ transport.c | 5 +++-- 4 files changed, 51 insertions(+), 30 deletions(-) diff --git a/http-walker.c b/http-walker.c index 99f397e..711e55b 100644 --- a/http-walker.c +++ b/http-walker.c @@ -100,7 +100,6 @@ static void start_object_request(struct walker *walker, char *hex = sha1_to_hex(obj_req->sha1); char prevfile[PATH_MAX]; char *url; - char *posn; int prevlocal; unsigned char prev_buf[PREV_BUF_SIZE]; ssize_t prev_read = 0; @@ -146,16 +145,11 @@ static void start_object_request(struct walker *walker, SHA1_Init(&obj_req->c); - url = xmalloc(strlen(obj_req->repo->base) + 51); + char *suffix = xmalloc(51); obj_req->url = xmalloc(strlen(obj_req->repo->base) + 51); - strcpy(url, obj_req->repo->base); - posn = url + strlen(obj_req->repo->base); - strcpy(posn, "/objects/"); - posn += 9; - memcpy(posn, hex, 2); - posn += 2; - *(posn++) = '/'; - strcpy(posn, hex + 2); + strcpy(suffix, "/objects/"); + sprintf(suffix + 9, "%c%c/%s", hex[0], hex[1], hex + 2); + url = transform_url(obj_req->repo->base, suffix); strcpy(obj_req->url, url); /* If a previous temp file is present, process what was already @@ -384,8 +378,9 @@ static int fetch_index(struct walker *walker, struct alt_base *repo, unsigned ch if (walker->get_verbosely) fprintf(stderr, "Getting index for pack %s\n", hex); - url = xmalloc(strlen(repo->base) + 64); - sprintf(url, "%s/objects/pack/pack-%s.idx", repo->base, hex); + char *index_url = xmalloc(64); + sprintf(index_url, "/objects/pack/pack-%s.idx", hex); + url = transform_url(repo->base, index_url); filename = sha1_pack_index_name(sha1); snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename); @@ -608,8 +603,7 @@ static void fetch_alternates(struct walker *walker, const char *base) if (walker->get_verbosely) fprintf(stderr, "Getting alternates list for %s\n", base); - url = xmalloc(strlen(base) + 31); - sprintf(url, "%s/objects/info/http-alternates", base); + url = transform_url(base, "/objects/info/http-alternates"); /* Use a callback to process the result, since another request may fail and need to have alternates loaded before continuing */ @@ -655,8 +649,7 @@ static int fetch_indices(struct walker *walker, struct alt_base *repo) if (walker->get_verbosely) fprintf(stderr, "Getting pack list for %s\n", repo->base); - url = xmalloc(strlen(repo->base) + 21); - sprintf(url, "%s/objects/info/packs", repo->base); + url = transform_url(repo->base, "/objects/info/packs"); slot = get_active_slot(); slot->results = &results; @@ -739,9 +732,9 @@ static int fetch_pack(struct walker *walker, struct alt_base *repo, unsigned cha sha1_to_hex(sha1)); } - url = xmalloc(strlen(repo->base) + 65); - sprintf(url, "%s/objects/pack/pack-%s.pack", - repo->base, sha1_to_hex(target->sha1)); + char *pack_url = xmalloc(65); + sprintf(pack_url, "/objects/pack/pack-%s.pack", sha1_to_hex(target->sha1)); + url = transform_url(repo->base, pack_url); filename = sha1_pack_name(target->sha1); snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename); diff --git a/http.c b/http.c index 2a21ccb..e2b764a 100644 --- a/http.c +++ b/http.c @@ -590,15 +590,17 @@ static char *quote_ref_url(const char *base, const char *ref) qref = xmalloc(len); memcpy(qref, base, baselen); dp = qref + baselen; - *(dp++) = '/'; - for (cp = ref; (ch = *cp) != 0; cp++) { - if (needs_quote(ch)) { - *dp++ = '%'; - *dp++ = hex((ch >> 4) & 0xF); - *dp++ = hex(ch & 0xF); + if (*ref) { + *(dp++) = '/'; + for (cp = ref; (ch = *cp) != 0; cp++) { + if (needs_quote(ch)) { + *dp++ = '%'; + *dp++ = hex((ch >> 4) & 0xF); + *dp++ = hex(ch & 0xF); + } + else + *dp++ = ch; } - else - *dp++ = ch; } *dp = 0; @@ -613,7 +615,10 @@ int http_fetch_ref(const char *base, struct ref *ref) struct slot_results results; int ret; - url = quote_ref_url(base, ref->name); + char *real_ref_name = xmalloc(strlen(ref->name) + 2); + sprintf(real_ref_name, "/%s", ref->name); + char *real_url = transform_url(base, real_ref_name); + url = quote_ref_url(real_url, ""); slot = get_active_slot(); slot->results = &results; curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer); @@ -643,3 +648,23 @@ int http_fetch_ref(const char *base, struct ref *ref) free(url); return ret; } + +char *transform_url(const char *url, const char *suffix) +{ + char *new_url; + char *question_mark; + ptrdiff_t offset; + + new_url = xmalloc(strlen(url) + strlen(suffix) + 1); + + if ((question_mark = strchr(url, '?'))) { + offset = (ptrdiff_t) question_mark - (ptrdiff_t) url; + snprintf(new_url, offset + 1, "%s", url); + strcat(new_url, suffix); + strcat(new_url, url + offset); + } else { + sprintf(new_url, "%s%s", url, suffix); + } + return new_url; +} + diff --git a/http.h b/http.h index a04fc6a..58730b8 100644 --- a/http.h +++ b/http.h @@ -107,4 +107,6 @@ static inline int missing__target(int code, int result) extern int http_fetch_ref(const char *base, struct ref *ref); +extern char *transform_url(const char *url, const char *suffix); + #endif /* HTTP_H */ diff --git a/transport.c b/transport.c index 3ff8519..b1966d8 100644 --- a/transport.c +++ b/transport.c @@ -1,3 +1,4 @@ +#include <stddef.h> #include "cache.h" #include "transport.h" #include "run-command.h" @@ -449,8 +450,7 @@ static struct ref *get_refs_via_curl(struct transport *transport) walker = transport->data; - refs_url = xmalloc(strlen(transport->url) + 11); - sprintf(refs_url, "%s/info/refs", transport->url); + refs_url = transform_url(transport->url, "/info/refs"); slot = get_active_slot(); slot->results = &results; @@ -833,3 +833,4 @@ int transport_disconnect(struct transport *transport) free(transport); return ret; } + -- 1.5.6.rc1.6.gc8c52
Attachment:
signature.asc
Description: This is a digitally signed message part.