diff --git a/builtin-fetch.c b/builtin-fetch.c index ec75df0900..b944cac6e6 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -289,7 +289,7 @@ static int update_local_ref(struct ref *ref, } } -static int store_updated_refs(const char *url, const char *remote_name, +static int store_updated_refs(const char *raw_url, const char *remote_name, struct ref *ref_map) { FILE *fp; @@ -298,11 +298,13 @@ static int store_updated_refs(const char *url, const char *remote_name, char note[1024]; const char *what, *kind; struct ref *rm; - char *filename = git_path("FETCH_HEAD"); + char *url, *filename = git_path("FETCH_HEAD"); fp = fopen(filename, "a"); if (!fp) return error("cannot open %s: %s\n", filename, strerror(errno)); + + url = transport_anonymize_url(raw_url); for (rm = ref_map; rm; rm = rm->next) { struct ref *ref = NULL; @@ -382,6 +384,7 @@ static int store_updated_refs(const char *url, const char *remote_name, fprintf(stderr, " %s\n", note); } } + free(url); fclose(fp); if (rc & 2) error("some local refs could not be updated; try running\n" diff --git a/transport.c b/transport.c index 3dfb03c06e..8ad317bf32 100644 --- a/transport.c +++ b/transport.c @@ -1083,3 +1083,51 @@ int transport_disconnect(struct transport *transport) free(transport); return ret; } + +/* + * Strip username (and password) from an url and return + * it in a newly allocated string. + */ +char *transport_anonymize_url(const char *url) +{ + char *anon_url, *scheme_prefix, *anon_part; + size_t anon_len, prefix_len = 0; + + anon_part = strchr(url, '@'); + if (is_local(url) || !anon_part) + goto literal_copy; + + anon_len = strlen(++anon_part); + scheme_prefix = strstr(url, "://"); + if (!scheme_prefix) { + if (!strchr(anon_part, ':')) + /* cannot be "me@there:/path/name" */ + goto literal_copy; + } else { + const char *cp; + /* make sure scheme is reasonable */ + for (cp = url; cp < scheme_prefix; cp++) { + switch (*cp) { + /* RFC 1738 2.1 */ + case '+': case '.': case '-': + break; /* ok */ + default: + if (isalnum(*cp)) + break; + /* it isn't */ + goto literal_copy; + } + } + /* @ past the first slash does not count */ + cp = strchr(scheme_prefix + 3, '/'); + if (cp && cp < anon_part) + goto literal_copy; + prefix_len = scheme_prefix - url + 3; + } + anon_url = xcalloc(1, 1 + prefix_len + anon_len); + memcpy(anon_url, url, prefix_len); + memcpy(anon_url + prefix_len, anon_part, anon_len); + return anon_url; +literal_copy: + return xstrdup(url); +} diff --git a/transport.h b/transport.h index b1c2252766..27bfc528ac 100644 --- a/transport.h +++ b/transport.h @@ -74,5 +74,6 @@ const struct ref *transport_get_remote_refs(struct transport *transport); int transport_fetch_refs(struct transport *transport, const struct ref *refs); void transport_unlock_pack(struct transport *transport); int transport_disconnect(struct transport *transport); +char *transport_anonymize_url(const char *url); #endif