All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/5] config: add support for http.<url>.* settings
@ 2013-07-15  9:50 Kyle J. McKay
  2013-07-15  9:50 ` [PATCH v5 1/5] http.c: fix parsing of http.sslCertPasswordProtected variable Kyle J. McKay
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Kyle J. McKay @ 2013-07-15  9:50 UTC (permalink / raw)
  To: git
  Cc: David Aguilar, Petr Baudis, Junio C Hamano, Richard Hartmann,
	Jeff King, Daniel Knittl-Frank, Jan Krüger, Alejandro Mery,
	Aaron Schrab

This patch series adds support for url-specific http.* settings.

It has been suggested that a preparatory patch to address the way the
http.sslCertPasswordProtected variable is handled be included.

I'm not sure if the intent was to make that a separate patch or include it
in a patch series together with the http.<url>.* settings updates.  I have,
however, included it here this time along with a second patch that does the
same thing for the GIT_SSL_CERT_PASSWORD_PROTECTED environment variable.

There is talk about possibly altering GIT_SSL_NO_VERIFY, GIT_CURL_FTP_NO_EPSV
and GIT_CURL_VERBOSE to behave similarly.  No patch is included here for that.

The http.<url>.* settings support addresses various feedback.  To better
support matching URLs that are equivalent but spelled differently, a
url_normalize function has been added.  Currently this patch leaves it in
http.c as http_options_url_normalize as I am unclear whether it should go into
url.{h,c} at this time since only http.c uses.

Since the url_normalize function's behavior is non-trivial, it is presented as
a separate patch on top of the basic http.<url>.* settings support.  A new test
for it has also been included as the final patch.  I am unclear on the proper
number for this test, but have gone ahead and put it with the other http tests
since this patch series places the url_normalize function into http.c.

Junio C Hamano (1):
  http.c: fix parsing of http.sslCertPasswordProtected variable

Kyle J. McKay (4):
  http.c: fix parsing of GIT_SSL_CERT_PASSWORD_PROTECTED variable
  config: add support for http.<url>.* settings
  config: improve support for http.<url>.* settings
  tests: add new test for the url_normalize function

 .gitignore               |   1 +
 Documentation/config.txt |  14 ++
 Makefile                 |   5 +
 http.c                   | 397 ++++++++++++++++++++++++++++++++++++++++++++---
 t/t5200-url-normalize.sh | 109 +++++++++++++
 test-url-normalize.c     |  62 ++++++++
 6 files changed, 565 insertions(+), 23 deletions(-)
 create mode 100755 t/t5200-url-normalize.sh
 create mode 100644 test-url-normalize.c

-- 
1.8.3

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v5 1/5] http.c: fix parsing of http.sslCertPasswordProtected variable
  2013-07-15  9:50 [PATCH v5 0/5] config: add support for http.<url>.* settings Kyle J. McKay
@ 2013-07-15  9:50 ` Kyle J. McKay
  2013-07-15  9:50 ` [PATCH v5 2/5] http.c: fix parsing of GIT_SSL_CERT_PASSWORD_PROTECTED variable Kyle J. McKay
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Kyle J. McKay @ 2013-07-15  9:50 UTC (permalink / raw)
  To: git
  Cc: David Aguilar, Petr Baudis, Junio C Hamano, Richard Hartmann,
	Jeff King, Daniel Knittl-Frank, Jan Krüger, Alejandro Mery,
	Aaron Schrab

From: Junio C Hamano <gitster@pobox.com>

The existing code triggers only when the configuration variable is
set to true.  Once the variable is set to true in a more generic
configuration file (e.g. ~/.gitconfig), it cannot be overriden to
false in the repository specific one (e.g. .git/config).

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 http.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/http.c b/http.c
index 2d086ae..e65661e 100644
--- a/http.c
+++ b/http.c
@@ -160,8 +160,7 @@ static int http_options(const char *var, const char *value, void *cb)
 	if (!strcmp("http.sslcainfo", var))
 		return git_config_string(&ssl_cainfo, var, value);
 	if (!strcmp("http.sslcertpasswordprotected", var)) {
-		if (git_config_bool(var, value))
-			ssl_cert_password_required = 1;
+		ssl_cert_password_required = git_config_bool(var, value);
 		return 0;
 	}
 	if (!strcmp("http.ssltry", var)) {
-- 
1.8.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v5 2/5] http.c: fix parsing of GIT_SSL_CERT_PASSWORD_PROTECTED variable
  2013-07-15  9:50 [PATCH v5 0/5] config: add support for http.<url>.* settings Kyle J. McKay
  2013-07-15  9:50 ` [PATCH v5 1/5] http.c: fix parsing of http.sslCertPasswordProtected variable Kyle J. McKay
@ 2013-07-15  9:50 ` Kyle J. McKay
  2013-07-15  9:51 ` [PATCH v5 3/5] config: add support for http.<url>.* settings Kyle J. McKay
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Kyle J. McKay @ 2013-07-15  9:50 UTC (permalink / raw)
  To: git
  Cc: David Aguilar, Petr Baudis, Junio C Hamano, Richard Hartmann,
	Jeff King, Daniel Knittl-Frank, Jan Krüger, Alejandro Mery,
	Aaron Schrab

The existing code triggers whenever GIT_SSL_CERT_PASSWORD_PROTECTED
is defined.  Setting GIT_SSL_CERT_PASSWORD_PROTECTED to a false
value could not be used to override the http.sslCertPasswordProtected
setting once it had been turned on.

Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
---
 http.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/http.c b/http.c
index e65661e..9542a59 100644
--- a/http.c
+++ b/http.c
@@ -403,11 +403,10 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
 		curl_ftp_no_epsv = 1;
 
 	if (url) {
+		int pwdreq = git_env_bool("GIT_SSL_CERT_PASSWORD_PROTECTED", -1);
 		credential_from_url(&http_auth, url);
-		if (!ssl_cert_password_required &&
-		    getenv("GIT_SSL_CERT_PASSWORD_PROTECTED") &&
-		    !prefixcmp(url, "https://"))
-			ssl_cert_password_required = 1;
+		if (pwdreq != -1 && !prefixcmp(url, "https://"))
+			ssl_cert_password_required = pwdreq;
 	}
 
 #ifndef NO_CURL_EASY_DUPHANDLE
-- 
1.8.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v5 3/5] config: add support for http.<url>.* settings
  2013-07-15  9:50 [PATCH v5 0/5] config: add support for http.<url>.* settings Kyle J. McKay
  2013-07-15  9:50 ` [PATCH v5 1/5] http.c: fix parsing of http.sslCertPasswordProtected variable Kyle J. McKay
  2013-07-15  9:50 ` [PATCH v5 2/5] http.c: fix parsing of GIT_SSL_CERT_PASSWORD_PROTECTED variable Kyle J. McKay
@ 2013-07-15  9:51 ` Kyle J. McKay
  2013-07-15  9:51 ` [PATCH v5 4/5] config: improve " Kyle J. McKay
  2013-07-15  9:51 ` [PATCH v5 5/5] tests: add new test for the url_normalize function Kyle J. McKay
  4 siblings, 0 replies; 9+ messages in thread
From: Kyle J. McKay @ 2013-07-15  9:51 UTC (permalink / raw)
  To: git
  Cc: David Aguilar, Petr Baudis, Junio C Hamano, Richard Hartmann,
	Jeff King, Daniel Knittl-Frank, Jan Krüger, Alejandro Mery,
	Aaron Schrab

The credentials configuration values already support url-specific
configuration items in the form credential.<url>.*.  This patch
adds similar support for http configuration values.

The <url> value is considered a match to a url if the <url> value
is either an exact match or a prefix of the url which ends on a
path component boundary ('/').  So "https://example.com/test" will
match "https://example.com/test" and "https://example.com/test/too"
but not "https://example.com/testextra".

Longer matches take precedence over shorter matches with
environment variable settings taking precedence over all.

With this configuration:

[http]
        useragent = other-agent
        noEPSV = true
[http "https://example.com"]
        useragent = example-agent
        sslVerify = false
[http "https://example.com/path"]
        useragent = path-agent

The "https://other.example.com/" url will have useragent
"other-agent" and sslVerify will be on.

The "https://example.com/" url will have useragent
"example-agent" and sslVerify will be off.

The "https://example.com/path/sub" url will have useragent
"path-agent" and sslVerify will be off.

All three of the examples will have noEPSV enabled.

Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
---
 Documentation/config.txt |  15 +++++
 http.c                   | 169 ++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 167 insertions(+), 17 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 81856dd..ceced99 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1531,6 +1531,21 @@ http.useragent::
 	of common USER_AGENT strings (but not including those like git/1.7.1).
 	Can be overridden by the 'GIT_HTTP_USER_AGENT' environment variable.
 
+http.<url>.*::
+	Any of the http.* options above can be applied selectively to some urls.
+	For example "http.https://example.com.useragent" would set the user
+	agent only for https connections to example.com.  The <url> value
+	matches a url if it is an exact match or a prefix of the url matching
+	at a "/" boundary.  Longer <url> matches take precedence over shorter
+	ones with the environment variable settings taking precedence over all.
+	Note that <url> must match the url passed to git exactly (other than
+	possibly being a prefix).  This means any user, password and/or port
+	setting that appears in a url as well as any %XX escapes that are
+	present must also appear in <url> to have a successful match.  The urls
+	that are matched against are those given directly to git commands.  In
+	other words, use exactly the same url that was passed to git (possibly
+	shortened) for the <url> value of the config setting.
+
 i18n.commitEncoding::
 	Character encoding the commit messages are stored in; Git itself
 	does not care per se, but this information is necessary e.g. when
diff --git a/http.c b/http.c
index 9542a59..758e5b1 100644
--- a/http.c
+++ b/http.c
@@ -30,6 +30,34 @@ static CURL *curl_default;
 
 char curl_errorstr[CURL_ERROR_SIZE];
 
+enum http_option_type {
+	OPT_POST_BUFFER,
+	OPT_MIN_SESSIONS,
+	OPT_SSL_VERIFY,
+	OPT_SSL_TRY,
+	OPT_SSL_CERT,
+	OPT_SSL_CAINFO,
+	OPT_LOW_SPEED,
+	OPT_LOW_TIME,
+	OPT_NO_EPSV,
+	OPT_HTTP_PROXY,
+	OPT_COOKIE_FILE,
+	OPT_USER_AGENT,
+	OPT_PASSWD_REQ,
+#ifdef USE_CURL_MULTI
+	OPT_MAX_REQUESTS,
+#endif
+#if LIBCURL_VERSION_NUM >= 0x070903
+	OPT_SSL_KEY,
+#endif
+#if LIBCURL_VERSION_NUM >= 0x070908
+	OPT_SSL_CAPATH,
+#endif
+	OPT_MAX
+};
+
+static size_t http_option_max_matched_len[OPT_MAX];
+
 static int curl_ssl_verify = -1;
 static int curl_ssl_try;
 static const char *ssl_cert;
@@ -141,33 +169,121 @@ static void process_curl_messages(void)
 }
 #endif
 
+static size_t http_options_url_match_prefix(const char *url,
+					    const char *url_prefix,
+					    size_t url_prefix_len)
+{
+	/*
+	 * url_prefix matches url if url_prefix is an exact match for url or it
+	 * is a prefix of url and the match ends on a path component boundary.
+	 * Both url and url_prefix are considered to have an implicit '/' on the
+	 * end for matching purposes if they do not already.
+	 *
+	 * url must be NUL terminated.  url_prefix_len is the length of
+	 * url_prefix which need not be NUL terminated.
+	 *
+	 * The return value is the length of the match in characters (excluding
+	 * any final '/') or 0 for no match.  Passing "/" as url_prefix will
+	 * always cause 0 to be returned.
+	 */
+	size_t url_len;
+	if (url_prefix_len && url_prefix[url_prefix_len - 1] == '/')
+		url_prefix_len--;
+	if (!url_prefix_len || strncmp(url, url_prefix, url_prefix_len))
+		return 0;
+	url_len = strlen(url);
+	if ((url_len == url_prefix_len) || (url[url_prefix_len] == '/'))
+		return url_prefix_len;
+	return 0;
+}
+
+static int new_match_is_shorter(size_t matchlen, enum http_option_type opt)
+{
+	/*
+	 * Compare matchlen to the last matched length of option opt and
+	 * return true if matchlen is shorter than the last matched length
+	 * (meaning the config setting should be ignored).  Upon seeing the
+	 * _same_ key (i.e. new key has the same match length which is therefore
+	 * not shorter) the new setting will override the previous setting.
+	 * Otherwise return false and record matchlen as the current last
+	 * matched length of option opt.
+	 */
+	if (matchlen < http_option_max_matched_len[opt])
+		return 1;
+	http_option_max_matched_len[opt] = matchlen;
+	return 0;
+}
+
 static int http_options(const char *var, const char *value, void *cb)
 {
-	if (!strcmp("http.sslverify", var)) {
+	const char *url = cb;
+	const char *key, *dot;
+	size_t matchlen = 0;
+
+	key = skip_prefix(var, "http.");
+	if (!key)
+		return git_default_config(var, value, cb);
+
+	/*
+	 * If the part following the leading "http." contains a '.' then check
+	 * to see if the part between "http." and the last '.' is a match to
+	 * url.  If it's not then ignore the setting.  Otherwise set key to
+	 * point to the option which is the part after the final '.' and
+	 * use key in subsequent comparisons to determine the option type.
+	 */
+	dot = strrchr(key, '.');
+	if (dot) {
+		matchlen = http_options_url_match_prefix(url, key, dot - key);
+		if (!matchlen)
+			return 0;
+		key = dot + 1;
+	}
+
+	if (!strcmp("sslverify", key)) {
+		if (new_match_is_shorter(matchlen, OPT_SSL_VERIFY))
+			return 0;
 		curl_ssl_verify = git_config_bool(var, value);
 		return 0;
 	}
-	if (!strcmp("http.sslcert", var))
+	if (!strcmp("sslcert", key)) {
+		if (new_match_is_shorter(matchlen, OPT_SSL_CERT))
+			return 0;
 		return git_config_string(&ssl_cert, var, value);
+	}
 #if LIBCURL_VERSION_NUM >= 0x070903
-	if (!strcmp("http.sslkey", var))
+	if (!strcmp("sslkey", key)) {
+		if (new_match_is_shorter(matchlen, OPT_SSL_KEY))
+			return 0;
 		return git_config_string(&ssl_key, var, value);
+	}
 #endif
 #if LIBCURL_VERSION_NUM >= 0x070908
-	if (!strcmp("http.sslcapath", var))
+	if (!strcmp("sslcapath", key)) {
+		if (new_match_is_shorter(matchlen, OPT_SSL_CAPATH))
+			return 0;
 		return git_config_string(&ssl_capath, var, value);
+	}
 #endif
-	if (!strcmp("http.sslcainfo", var))
+	if (!strcmp("sslcainfo", key)) {
+		if (new_match_is_shorter(matchlen, OPT_SSL_CAINFO))
+			return 0;
 		return git_config_string(&ssl_cainfo, var, value);
-	if (!strcmp("http.sslcertpasswordprotected", var)) {
+	}
+	if (!strcmp("sslcertpasswordprotected", key)) {
+		if (new_match_is_shorter(matchlen, OPT_PASSWD_REQ))
+			return 0;
 		ssl_cert_password_required = git_config_bool(var, value);
 		return 0;
 	}
-	if (!strcmp("http.ssltry", var)) {
+	if (!strcmp("ssltry", key)) {
+		if (new_match_is_shorter(matchlen, OPT_SSL_TRY))
+			return 0;
 		curl_ssl_try = git_config_bool(var, value);
 		return 0;
 	}
-	if (!strcmp("http.minsessions", var)) {
+	if (!strcmp("minsessions", key)) {
+		if (new_match_is_shorter(matchlen, OPT_MIN_SESSIONS))
+			return 0;
 		min_curl_sessions = git_config_int(var, value);
 #ifndef USE_CURL_MULTI
 		if (min_curl_sessions > 1)
@@ -176,39 +292,58 @@ static int http_options(const char *var, const char *value, void *cb)
 		return 0;
 	}
 #ifdef USE_CURL_MULTI
-	if (!strcmp("http.maxrequests", var)) {
+	if (!strcmp("maxrequests", key)) {
+		if (new_match_is_shorter(matchlen, OPT_MAX_REQUESTS))
+			return 0;
 		max_requests = git_config_int(var, value);
 		return 0;
 	}
 #endif
-	if (!strcmp("http.lowspeedlimit", var)) {
+	if (!strcmp("lowspeedlimit", key)) {
+		if (new_match_is_shorter(matchlen, OPT_LOW_SPEED))
+			return 0;
 		curl_low_speed_limit = (long)git_config_int(var, value);
 		return 0;
 	}
-	if (!strcmp("http.lowspeedtime", var)) {
+	if (!strcmp("lowspeedtime", key)) {
+		if (new_match_is_shorter(matchlen, OPT_LOW_TIME))
+			return 0;
 		curl_low_speed_time = (long)git_config_int(var, value);
 		return 0;
 	}
 
-	if (!strcmp("http.noepsv", var)) {
+	if (!strcmp("noepsv", key)) {
+		if (new_match_is_shorter(matchlen, OPT_NO_EPSV))
+			return 0;
 		curl_ftp_no_epsv = git_config_bool(var, value);
 		return 0;
 	}
-	if (!strcmp("http.proxy", var))
+	if (!strcmp("proxy", key)) {
+		if (new_match_is_shorter(matchlen, OPT_HTTP_PROXY))
+			return 0;
 		return git_config_string(&curl_http_proxy, var, value);
+	}
 
-	if (!strcmp("http.cookiefile", var))
+	if (!strcmp("cookiefile", key)) {
+		if (new_match_is_shorter(matchlen, OPT_COOKIE_FILE))
+			return 0;
 		return git_config_string(&curl_cookie_file, var, value);
+	}
 
-	if (!strcmp("http.postbuffer", var)) {
+	if (!strcmp("postbuffer", key)) {
+		if (new_match_is_shorter(matchlen, OPT_POST_BUFFER))
+			return 0;
 		http_post_buffer = git_config_int(var, value);
 		if (http_post_buffer < LARGE_PACKET_MAX)
 			http_post_buffer = LARGE_PACKET_MAX;
 		return 0;
 	}
 
-	if (!strcmp("http.useragent", var))
+	if (!strcmp("useragent", key)) {
+		if (new_match_is_shorter(matchlen, OPT_USER_AGENT))
+			return 0;
 		return git_config_string(&user_agent, var, value);
+	}
 
 	/* Fall back on the default ones */
 	return git_default_config(var, value, cb);
@@ -343,7 +478,7 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
 
 	http_is_verbose = 0;
 
-	git_config(http_options, NULL);
+	git_config(http_options, (void *)url);
 
 	curl_global_init(CURL_GLOBAL_ALL);
 
-- 
1.8.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v5 4/5] config: improve support for http.<url>.* settings
  2013-07-15  9:50 [PATCH v5 0/5] config: add support for http.<url>.* settings Kyle J. McKay
                   ` (2 preceding siblings ...)
  2013-07-15  9:51 ` [PATCH v5 3/5] config: add support for http.<url>.* settings Kyle J. McKay
@ 2013-07-15  9:51 ` Kyle J. McKay
  2013-07-15 23:12   ` Eric Sunshine
  2013-07-15  9:51 ` [PATCH v5 5/5] tests: add new test for the url_normalize function Kyle J. McKay
  4 siblings, 1 reply; 9+ messages in thread
From: Kyle J. McKay @ 2013-07-15  9:51 UTC (permalink / raw)
  To: git
  Cc: David Aguilar, Petr Baudis, Junio C Hamano, Richard Hartmann,
	Jeff King, Daniel Knittl-Frank, Jan Krüger, Alejandro Mery,
	Aaron Schrab

Improve on the http.<url>.* url matching behavior by first
normalizing the urls before they are compared.

With this change, for example, the following configuration
section:

[http "https://example.com/path"]
        useragent = example-agent
        sslVerify = false

will properly match a "HTTPS://example.COM/p%61th" url which
is equivalent.

The normalization rules are based on RFC 3986 and should
result in any two equivalent urls being a match.

Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
---
 Documentation/config.txt |  19 ++--
 http.c                   | 222 ++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 229 insertions(+), 12 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index ceced99..98eee23 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1535,16 +1535,15 @@ http.<url>.*::
 	Any of the http.* options above can be applied selectively to some urls.
 	For example "http.https://example.com.useragent" would set the user
 	agent only for https connections to example.com.  The <url> value
-	matches a url if it is an exact match or a prefix of the url matching
-	at a "/" boundary.  Longer <url> matches take precedence over shorter
-	ones with the environment variable settings taking precedence over all.
-	Note that <url> must match the url passed to git exactly (other than
-	possibly being a prefix).  This means any user, password and/or port
-	setting that appears in a url as well as any %XX escapes that are
-	present must also appear in <url> to have a successful match.  The urls
-	that are matched against are those given directly to git commands.  In
-	other words, use exactly the same url that was passed to git (possibly
-	shortened) for the <url> value of the config setting.
+	matches a url if it is an exact match or if it is a prefix of the url
+	matching at a "/" boundary.  Longer <url> matches take precedence over
+	shorter ones with the environment variable settings taking precedence
+	over all.  The urls are normalized before testing for a match.  Note,
+	however, that any user, password and/or port setting that appears in a
+	url must also match that part of <url> to have a successful match.  The
+	urls that are matched against are those given directly to git commands.
+	This means any urls visited as a result of a redirection do not
+	participate in matching.
 
 i18n.commitEncoding::
 	Character encoding the commit messages are stored in; Git itself
diff --git a/http.c b/http.c
index 758e5b1..d04386e 100644
--- a/http.c
+++ b/http.c
@@ -169,6 +169,210 @@ static void process_curl_messages(void)
 }
 #endif
 
+#define URL_ALPHA "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+#define URL_DIGIT "0123456789"
+#define URL_HEXDIGIT URL_DIGIT "ABCDEFabcdef"
+#define URL_ALPHADIGIT URL_ALPHA URL_DIGIT
+#define URL_SCHEME_CHARS URL_ALPHADIGIT "+.-"
+#define URL_HOST_CHARS URL_ALPHADIGIT ".-[:]" /* IPv6 literals need [:] */
+#define URL_UNSAFE_CHARS " <>\"%{}|\\^`" /* plus 0x00-0x1F,0x7F-0xFF */
+#define URL_GEN_RESERVED ":/?#[]@"
+#define URL_SUB_RESERVED "!$&'()*+,;="
+#define URL_RESERVED URL_GEN_RESERVED URL_SUB_RESERVED /* only allowed delims */
+
+static int hex_digit_value(int ch)
+{
+	/*
+	 * Returns the hexadecimal digit value (0x00..0x0F) of character ch.
+	 * If ch is not a hexadecimal digit, the return value is undefined.
+	 */
+
+	if ('0' <= ch && ch <= '9')
+		return ch - '0';
+	return toupper(ch) - 'A' + 10;
+}
+
+static int append_normalized_escapes(struct strbuf *buf,
+				     const char *from,
+				     size_t from_len,
+				     const char *esc_extra,
+				     const char *esc_ok)
+{
+	/*
+	 * Append to strbuf buf characters from string from with length from_len
+	 * while unescaping characters that do not need to be escaped and
+	 * escaping characters that do.  The set of characters to escape (the
+	 * complement of which is unescaped) starts out as the RFC 3986 unsafe
+	 * characters (0x00-0x1F,0x7F-0xFF," <>\"#%{}|\\^`").  If esc_extra
+	 * is not NULL, those additional characters will also always be escaped.
+	 * If esc_ok is not NULL, those characters will be left escaped if found
+	 * that way, but will not be unescaped otherwise (used for delimiters).
+	 * If a %-escape sequence is encountered that is not followed by 2
+	 * hexadecimal digits, the sequence is invalid and false (0) will be
+	 * returned.  Otherwise true (1) will be returned for success.
+	 *
+	 * Note that all %-escape sequences will be normalized to UPPERCASE
+	 * as indicated in RFC 3986.  Unless included in esc_extra or esc_ok
+	 * alphanumerics and "-._~" will always be unescaped as per RFC 3986.
+	 */
+
+	while (from_len) {
+		int ch = *from++;
+		int was_esc = 0;
+
+		from_len--;
+		if (ch == '%') {
+			if (from_len < 2 ||
+			    !strchr(URL_HEXDIGIT, from[0]) ||
+			    !strchr(URL_HEXDIGIT, from[1]))
+				return 0;
+			ch = hex_digit_value(*from++) << 4;
+			ch |= hex_digit_value(*from++);
+			from_len -= 2;
+			was_esc = 1;
+		}
+		if (ch <= 0x1F || ch >= 0x7F || strchr(URL_UNSAFE_CHARS, ch) ||
+		    (esc_extra && strchr(esc_extra, ch)) ||
+		    (was_esc && strchr(esc_ok, ch)))
+			strbuf_addf(buf, "%%%02X", ch);
+		else
+			strbuf_addch(buf, ch);
+	}
+
+	return 1;
+}
+
+static char *http_options_url_normalize(const char *url, size_t *out_len)
+{
+	/*
+	 * Normalize NUL-terminated url using the following rules:
+	 *
+	 * 1. Case-insensitive parts of url will be converted to lower case
+	 * 2. %-encoded characters that do not need to be will be unencoded
+	 * 3. Characters that are not %-encoded and must be will be encoded
+	 * 4. All %-encodings will be converted to upper case hexadecimal
+	 * 5. If the default port for the scheme is given it will be removed
+	 * 6. If the user:password part is given and empty it will be removed
+	 * 7. A path part (including empty) not starting with '/' has one added
+	 * 8. IPv6 host literals are allowed (but not normalized or validated)
+	 *
+	 * The rules are based on information in RFC 3986.
+	 *
+	 * Please note this function requires a full URL including a scheme
+	 * and host part (except for file: URLs which may have an empty host).
+	 *
+	 * The return value is a newly allocated string that must be freed
+	 * or NULL if the url is not valid.
+	 *
+	 * If a non-NULL value is returned and out_len is not NULL then the
+	 * length of the result will be stored in *out_len.
+	 *
+	 * This is NOT a URL validation function.  Full URL validation is NOT
+	 * performed.  Some invalid host names are passed through this function
+	 * undetected.  Invalid port numbers may also be passed through
+	 * undetected.  However, most all other problems that make a URL invalid
+	 * will be detected (including a missing host for non file: URLs).
+	 */
+
+	size_t url_len = strlen(url);
+	struct strbuf norm;
+	size_t spanned;
+	const char *slash_ptr, *at_ptr, *colon_ptr;
+
+	/* Copy lowercased scheme and :// suffix, %-escapes are not allowed */
+	spanned = strspn(url, URL_SCHEME_CHARS);
+	if (!spanned || spanned + 3 > url_len || url[spanned] != ':' ||
+	    url[spanned+1] != '/' || url[spanned+2] != '/')
+		return NULL; /* Bad scheme and/or missing "://" part */
+	strbuf_init(&norm, url_len);
+	spanned += 3;
+	url_len -= spanned;
+	while (spanned--)
+		strbuf_addch(&norm, tolower(*url++));
+
+	/* Copy any username:password if present normalizing %-escapes */
+	at_ptr = strchr(url, '@');
+	slash_ptr = url + strcspn(url, "/?#");
+	if (at_ptr && at_ptr < slash_ptr) {
+		if (at_ptr > url) {
+			if (!append_normalized_escapes(&norm, url, at_ptr - url,
+						       "", URL_RESERVED)) {
+				strbuf_release(&norm);
+				return NULL;
+			}
+			strbuf_addch(&norm, '@');
+		}
+		url_len -= (++at_ptr - url);
+		url = at_ptr;
+	}
+
+	/* Copy the host part excluding any port part, no %-escapes allowed */
+	if (!url_len || strchr(":/?#", *url)) {
+		/* Missing host invalid for all URL schemes except file */
+		if (strncmp(norm.buf, "file:", 5)) {
+			strbuf_release(&norm);
+			return NULL;
+		}
+	}
+	colon_ptr = slash_ptr - 1;
+	while (colon_ptr > url && *colon_ptr != ':' && *colon_ptr != ']')
+		colon_ptr--;
+	if (*colon_ptr != ':')
+		colon_ptr = slash_ptr;
+	spanned = strspn(url, URL_HOST_CHARS);
+	if (spanned < colon_ptr - url) {
+		/* Host name has invalid characters */
+		strbuf_release(&norm);
+		return NULL;
+	}
+	while (url < colon_ptr) {
+		strbuf_addch(&norm, tolower(*url++));
+		url_len--;
+	}
+
+	/* Check the port part and copy if not the default, no %-escapes */
+	if (colon_ptr < slash_ptr) {
+		if (colon_ptr + 1 == slash_ptr) {
+			/* Skip ":" port with no number, it's same as default */
+		} else if (slash_ptr - colon_ptr == 3 &&
+			   !strncmp(norm.buf, "http:", 5) &&
+			   !strncmp(url, ":80", 3)) {
+			/* Skip http :80 as it's the default */
+		} else if (slash_ptr - colon_ptr == 4 &&
+			   !strncmp(norm.buf, "https:", 6) &&
+			   !strncmp(url, ":443", 4)) {
+			/* Skip https :443 as it's the default */
+		} else {
+			/* Port number must be all digits */
+			spanned = strspn(url + 1, URL_DIGIT);
+			if (spanned + 1 < slash_ptr - colon_ptr) {
+				/* port number has invalid characters */
+				strbuf_release(&norm);
+				return NULL;
+			}
+			strbuf_add(&norm, url, slash_ptr - colon_ptr);
+		}
+		url_len -= slash_ptr - colon_ptr;
+		url = slash_ptr;
+	}
+
+	/*
+	 * Now simply copy the rest, if any, only normalizing %-escapes and
+	 * being careful to not corrupt the URL by unescaping any delimiters,
+	 * but do add an initial '/' if it's missing
+	 */
+	if (*url != '/')
+		strbuf_addch(&norm, '/');
+	if (*url) {
+		if (!append_normalized_escapes(&norm, url, url_len, "", URL_RESERVED)) {
+			strbuf_release(&norm);
+			return NULL;
+		}
+	}
+
+	return strbuf_detach(&norm, out_len);
+}
+
 static size_t http_options_url_match_prefix(const char *url,
 					    const char *url_prefix,
 					    size_t url_prefix_len)
@@ -185,8 +389,13 @@ static size_t http_options_url_match_prefix(const char *url,
 	 * The return value is the length of the match in characters (excluding
 	 * any final '/') or 0 for no match.  Passing "/" as url_prefix will
 	 * always cause 0 to be returned.
+	 *
+	 * Passing NULL as url and/or url_prefix will always cause 0 to be
+	 * returned without causing any faults.
 	 */
 	size_t url_len;
+	if (!url || !url_prefix)
+		return 0;
 	if (url_prefix_len && url_prefix[url_prefix_len - 1] == '/')
 		url_prefix_len--;
 	if (!url_prefix_len || strncmp(url, url_prefix, url_prefix_len))
@@ -233,7 +442,14 @@ static int http_options(const char *var, const char *value, void *cb)
 	 */
 	dot = strrchr(key, '.');
 	if (dot) {
-		matchlen = http_options_url_match_prefix(url, key, dot - key);
+		char *config_url = xmemdupz(key, dot - key);
+		size_t norm_url_len;
+		char *norm_url = http_options_url_normalize(config_url, &norm_url_len);
+		free(config_url);
+		if (!norm_url)
+			return 0;
+		matchlen = http_options_url_match_prefix(url, norm_url, norm_url_len);
+		free(norm_url);
 		if (!matchlen)
 			return 0;
 		key = dot + 1;
@@ -475,10 +691,12 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
 {
 	char *low_speed_limit;
 	char *low_speed_time;
+	char *norm_url = http_options_url_normalize(url, NULL);
 
 	http_is_verbose = 0;
 
-	git_config(http_options, (void *)url);
+	git_config(http_options, norm_url);
+	free(norm_url);
 
 	curl_global_init(CURL_GLOBAL_ALL);
 
-- 
1.8.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v5 5/5] tests: add new test for the url_normalize function
  2013-07-15  9:50 [PATCH v5 0/5] config: add support for http.<url>.* settings Kyle J. McKay
                   ` (3 preceding siblings ...)
  2013-07-15  9:51 ` [PATCH v5 4/5] config: improve " Kyle J. McKay
@ 2013-07-15  9:51 ` Kyle J. McKay
  4 siblings, 0 replies; 9+ messages in thread
From: Kyle J. McKay @ 2013-07-15  9:51 UTC (permalink / raw)
  To: git
  Cc: David Aguilar, Petr Baudis, Junio C Hamano, Richard Hartmann,
	Jeff King, Daniel Knittl-Frank, Jan Krüger, Alejandro Mery,
	Aaron Schrab

In order to perform sane URL matching for http.<url>.* options,
http.c normalizes URLs before performing matches.

A new test-url-normalize test program is introduced along with
a new t5200-url-normalize.sh script to run the tests.

Since the url_normalize function currently lives in http.c this
test will be skipped if NO_CURL is defined since http.c is skipped
in that case.

Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
---
 .gitignore               |   1 +
 Makefile                 |   5 +++
 t/t5200-url-normalize.sh | 109 +++++++++++++++++++++++++++++++++++++++++++++++
 test-url-normalize.c     |  62 +++++++++++++++++++++++++++
 4 files changed, 177 insertions(+)
 create mode 100755 t/t5200-url-normalize.sh
 create mode 100644 test-url-normalize.c

diff --git a/.gitignore b/.gitignore
index efa8db0..b60a9df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -201,6 +201,7 @@
 /test-string-list
 /test-subprocess
 /test-svn-fe
+/test-url-normalize
 /test-wildmatch
 /common-cmds.h
 *.tar.gz
diff --git a/Makefile b/Makefile
index 0600eb4..195c62a 100644
--- a/Makefile
+++ b/Makefile
@@ -580,6 +580,7 @@ TEST_PROGRAMS_NEED_X += test-sigchain
 TEST_PROGRAMS_NEED_X += test-string-list
 TEST_PROGRAMS_NEED_X += test-subprocess
 TEST_PROGRAMS_NEED_X += test-svn-fe
+TEST_PROGRAMS_NEED_X += test-url-normalize
 TEST_PROGRAMS_NEED_X += test-wildmatch
 
 TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X))
@@ -2278,6 +2279,10 @@ test-parse-options$X: parse-options.o parse-options-cb.o
 
 test-svn-fe$X: vcs-svn/lib.a
 
+test-url-normalize$X: test-url-normalize.o GIT-LDFLAGS $(GITLIBS)
+	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+		$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
+
 .PRECIOUS: $(TEST_OBJS)
 
 test-%$X: test-%.o GIT-LDFLAGS $(GITLIBS)
diff --git a/t/t5200-url-normalize.sh b/t/t5200-url-normalize.sh
new file mode 100755
index 0000000..40ebcd3
--- /dev/null
+++ b/t/t5200-url-normalize.sh
@@ -0,0 +1,109 @@
+#!/bin/sh
+
+test_description='url normalization'
+. ./test-lib.sh
+
+if test -n "$NO_CURL"; then
+	skip_all='skipping test, git built without http support'
+	test_done
+fi
+
+# Note that only file: URLs should be allowed without a host
+
+test_expect_success 'url scheme' '
+	! test-url-normalize "" &&
+	! test-url-normalize "_" &&
+	! test-url-normalize "scheme" &&
+	! test-url-normalize "scheme:" &&
+	! test-url-normalize "scheme:/" &&
+	! test-url-normalize "scheme://" &&
+	! test-url-normalize "file" &&
+	! test-url-normalize "file:" &&
+	! test-url-normalize "file:/" &&
+	test-url-normalize "file://" &&
+	! test-url-normalize "://acme.co" &&
+	! test-url-normalize "x_test://acme.co" &&
+	! test-url-normalize "schem%6e://" &&
+	test-url-normalize "x-Test+v1.0://acme.co" &&
+	test "$(test-url-normalize -p "AbCdeF://x.Y")" = "abcdef://x.y/"
+'
+
+test_expect_success 'url authority' '
+	! test-url-normalize "scheme://user:pass@" &&
+	! test-url-normalize "scheme://?" &&
+	! test-url-normalize "scheme://#" &&
+	! test-url-normalize "scheme:///" &&
+	! test-url-normalize "scheme://:" &&
+	! test-url-normalize "scheme://:555" &&
+	test-url-normalize "file://user:pass@" &&
+	test-url-normalize "file://?" &&
+	test-url-normalize "file://#" &&
+	test-url-normalize "file:///" &&
+	test-url-normalize "file://:" &&
+	test-url-normalize "file://:555" &&
+	test-url-normalize "scheme://user:pass@host" &&
+	test-url-normalize "scheme://@host" &&
+	test-url-normalize "scheme://%00@host" &&
+	! test-url-normalize "scheme://%%@host" &&
+	! test-url-normalize "scheme://host_" &&
+	test-url-normalize "scheme://user:pass@host/" &&
+	test-url-normalize "scheme://@host/" &&
+	test-url-normalize "scheme://host/" &&
+	test-url-normalize "scheme://host?x" &&
+	test-url-normalize "scheme://host#x" &&
+	test-url-normalize "scheme://host/@" &&
+	test-url-normalize "scheme://host?@x" &&
+	test-url-normalize "scheme://host#@x" &&
+	test-url-normalize "scheme://[::1]" &&
+	test-url-normalize "scheme://[::1]/" &&
+	! test-url-normalize "scheme://hos%41/" &&
+	test-url-normalize "scheme://[invalid....:/" &&
+	test-url-normalize "scheme://invalid....:]/" &&
+	! test-url-normalize "scheme://invalid....:[/" &&
+	! test-url-normalize "scheme://invalid....:["
+'
+
+test_expect_success 'url port' '
+	test-url-normalize "xyz://q@some.host:" &&
+	test-url-normalize "xyz://q@some.host:456" &&
+	test-url-normalize "xyz://q@some.host:0" &&
+	test-url-normalize "xyz://q@some.host:99999" &&
+	test-url-normalize "http://q@some.host:80" &&
+	test-url-normalize "https://q@some.host:443"
+	! test-url-normalize "http://q@:8008" &&
+	! test-url-normalize "http://:8080" &&
+	! test-url-normalize "http://:" &&
+	test-url-normalize "xyz://q@some.host:456/" &&
+	test-url-normalize "xyz://[::1]:456/" &&
+	test-url-normalize "xyz://[::1]:/" &&
+	test-url-normalize "xyz://[::1]:000/" &&
+	! test-url-normalize "xyz://[::1]:0%300/" &&
+	! test-url-normalize "xyz://[::1]:030f/"
+'
+
+test_expect_success 'url general escapes' '
+	! test-url-normalize "http://x.y?%fg" &&
+	test "$(test-url-normalize -p "X://W/%7e%41^%3a")" = "x://w/~A%5E%3A" &&
+	test "$(test-url-normalize -p "X://W/:/?#[]@")" = "x://w/:/?#[]@" &&
+	test "$(test-url-normalize -p "X://W/$&()*+,;=")" = "x://w/$&()*+,;=" &&
+	test "$(test-url-normalize -p "X://W/'\''")" = "x://w/'\''" &&
+	test "$(test-url-normalize -p "X://W?'\!'")" = "x://w/?'\!'"
+';#'
+
+test_expect_success 'url username/password escapes' '
+	test "$(test-url-normalize -p "x://%41%62(^):%70+d@foo")" = "x://Ab(%5E):p+d@foo/"
+'
+
+test_expect_success 'url normalized lengths' '
+	test "$(test-url-normalize -l "Http://%4d%65:%4d^%70@The.Host")" = 25 &&
+	test "$(test-url-normalize -l "http://%41:%42@x.y/%61/")" = 17 &&
+	test "$(test-url-normalize -l "http://@x.y/^")" = 14
+'
+
+test_expect_success 'url equivalents' '
+	test-url-normalize "httP://x" "Http://X/" &&
+	test-url-normalize "Http://%4d%65:%4d^%70@The.Host" "hTTP://Me:%4D^p@the.HOST:80/" &&
+	test-url-normalize "https://@x.y/^" "httpS://x.y:443/^"
+'
+
+test_done
diff --git a/test-url-normalize.c b/test-url-normalize.c
new file mode 100644
index 0000000..1872964
--- /dev/null
+++ b/test-url-normalize.c
@@ -0,0 +1,62 @@
+#ifdef NO_CURL
+
+int main()
+{
+	return 125;
+}
+
+#else /* !NO_CURL */
+
+#include "http.c"
+
+#define url_normalize(u,s) http_options_url_normalize(u,s)
+
+int main(int argc, char **argv)
+{
+	const char *usage = "test-url-normalize [-p | -l] <url1> | <url1> <url2>";
+	char *url1, *url2;
+	int opt_p = 0, opt_l = 0;
+
+	/*
+	 * For one url, succeed if url_normalize succeeds on it, fail otherwise.
+	 * For two urls, succeed only if url_normalize succeeds on both and
+	 * the results compare equal with strcmp.  If -p is given (one url only)
+	 * and url_normalize succeeds, print the result followed by "\n".  If
+	 * -l is given (one url only) and url_normalize succeeds, print the
+	 * returned length in decimal followed by "\n".
+	 */
+
+	if (argc > 1 && !strcmp(argv[1], "-p")) {
+		opt_p = 1;
+		argc--;
+		argv++;
+	} else if (argc > 1 && !strcmp(argv[1], "-l")) {
+		opt_l = 1;
+		argc--;
+		argv++;
+	}
+
+	if (argc < 2 || argc > 3)
+		die(usage);
+
+	if (argc == 2) {
+		size_t s;
+		url1 = url_normalize(argv[1], &s);
+		if (!url1)
+			return 1;
+		if (opt_p)
+			printf("%s\n", url1);
+		if (opt_l)
+			printf("%u\n", (unsigned)s);
+		return 0;
+	}
+
+	if (opt_p || opt_l)
+		die(usage);
+
+	url1 = url_normalize(argv[1], NULL);
+	url2 = url_normalize(argv[2], NULL);
+	return (url1 && url2 && !strcmp(url1, url2)) ? 0 : 1;
+}
+
+#endif /* !NO_CURL */
-- 
1.8.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v5 4/5] config: improve support for http.<url>.* settings
  2013-07-15  9:51 ` [PATCH v5 4/5] config: improve " Kyle J. McKay
@ 2013-07-15 23:12   ` Eric Sunshine
  2013-07-16  9:53     ` Kyle J. McKay
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Sunshine @ 2013-07-15 23:12 UTC (permalink / raw)
  To: Kyle J. McKay
  Cc: Git List, David Aguilar, Petr Baudis, Junio C Hamano,
	Richard Hartmann, Jeff King, Daniel Knittl-Frank,
	Jan Krüger, Alejandro Mery, Aaron Schrab

On Mon, Jul 15, 2013 at 5:51 AM, Kyle J. McKay <mackyle@gmail.com> wrote:
> Improve on the http.<url>.* url matching behavior by first
> normalizing the urls before they are compared.
>
> diff --git a/http.c b/http.c
> index 758e5b1..d04386e 100644
> --- a/http.c
> +++ b/http.c
> @@ -169,6 +169,210 @@ static void process_curl_messages(void)
>  }
>  #endif
>
> +static int append_normalized_escapes(struct strbuf *buf,
> +                                    const char *from,
> +                                    size_t from_len,
> +                                    const char *esc_extra,
> +                                    const char *esc_ok)
> +{
> +       /*
> +        * Append to strbuf buf characters from string from with length from_len

s/from string from/from string/

> +        * while unescaping characters that do not need to be escaped and
> +        * escaping characters that do.  The set of characters to escape (the
> +        * complement of which is unescaped) starts out as the RFC 3986 unsafe
> +        * characters (0x00-0x1F,0x7F-0xFF," <>\"#%{}|\\^`").  If esc_extra
> +        * is not NULL, those additional characters will also always be escaped.
> +        * If esc_ok is not NULL, those characters will be left escaped if found
> +        * that way, but will not be unescaped otherwise (used for delimiters).
> +        * If a %-escape sequence is encountered that is not followed by 2
> +        * hexadecimal digits, the sequence is invalid and false (0) will be
> +        * returned.  Otherwise true (1) will be returned for success.
> +        *
> +        * Note that all %-escape sequences will be normalized to UPPERCASE
> +        * as indicated in RFC 3986.  Unless included in esc_extra or esc_ok
> +        * alphanumerics and "-._~" will always be unescaped as per RFC 3986.
> +        */

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v5 4/5] config: improve support for http.<url>.* settings
  2013-07-15 23:12   ` Eric Sunshine
@ 2013-07-16  9:53     ` Kyle J. McKay
  2013-07-16 10:01       ` Eric Sunshine
  0 siblings, 1 reply; 9+ messages in thread
From: Kyle J. McKay @ 2013-07-16  9:53 UTC (permalink / raw)
  To: Eric Sunshine
  Cc: Git List, David Aguilar, Petr Baudis, Junio C Hamano,
	Richard Hartmann, Jeff King, Daniel Knittl-Frank,
	Jan Krüger, Alejandro Mery, Aaron Schrab

On Jul 15, 2013, at 16:12, Eric Sunshine wrote:
> On Mon, Jul 15, 2013 at 5:51 AM, Kyle J. McKay <mackyle@gmail.com>  
> wrote:
>> +static int append_normalized_escapes(struct strbuf *buf,
>> +                                    const char *from,
>> +                                    size_t from_len,
>> +                                    const char *esc_extra,
>> +                                    const char *esc_ok)
>> +{
>> +       /*
>> +        * Append to strbuf buf characters from string from with  
>> length from_len
>
> s/from string from/from string/

Hmmm.  Actually it's meant to say "from string <parameter with name  
from>".

Do quotes make it read better:

   from string `from'

Or do you think it needs to be:

   from string parameter `from'

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v5 4/5] config: improve support for http.<url>.* settings
  2013-07-16  9:53     ` Kyle J. McKay
@ 2013-07-16 10:01       ` Eric Sunshine
  0 siblings, 0 replies; 9+ messages in thread
From: Eric Sunshine @ 2013-07-16 10:01 UTC (permalink / raw)
  To: Kyle J. McKay
  Cc: Git List, David Aguilar, Petr Baudis, Junio C Hamano,
	Richard Hartmann, Jeff King, Daniel Knittl-Frank,
	Jan Krüger, Alejandro Mery, Aaron Schrab

On Tue, Jul 16, 2013 at 5:53 AM, Kyle J. McKay <mackyle@gmail.com> wrote:
> On Jul 15, 2013, at 16:12, Eric Sunshine wrote:
>>
>> On Mon, Jul 15, 2013 at 5:51 AM, Kyle J. McKay <mackyle@gmail.com> wrote:
>>>
>>> +static int append_normalized_escapes(struct strbuf *buf,
>>> +                                    const char *from,
>>> +                                    size_t from_len,
>>> +                                    const char *esc_extra,
>>> +                                    const char *esc_ok)
>>> +{
>>> +       /*
>>> +        * Append to strbuf buf characters from string from with length
>>> from_len
>>
>>
>> s/from string from/from string/
>
> Hmmm.  Actually it's meant to say "from string <parameter with name from>".
>
> Do quotes make it read better:
>
>   from string `from'
>
> Or do you think it needs to be:
>
>   from string parameter `from'

Ah, I see now. Thanks for clarifying. Quoting 'from' (and the other
arguments) probably would make it sufficiently readable.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2013-07-16 10:01 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-15  9:50 [PATCH v5 0/5] config: add support for http.<url>.* settings Kyle J. McKay
2013-07-15  9:50 ` [PATCH v5 1/5] http.c: fix parsing of http.sslCertPasswordProtected variable Kyle J. McKay
2013-07-15  9:50 ` [PATCH v5 2/5] http.c: fix parsing of GIT_SSL_CERT_PASSWORD_PROTECTED variable Kyle J. McKay
2013-07-15  9:51 ` [PATCH v5 3/5] config: add support for http.<url>.* settings Kyle J. McKay
2013-07-15  9:51 ` [PATCH v5 4/5] config: improve " Kyle J. McKay
2013-07-15 23:12   ` Eric Sunshine
2013-07-16  9:53     ` Kyle J. McKay
2013-07-16 10:01       ` Eric Sunshine
2013-07-15  9:51 ` [PATCH v5 5/5] tests: add new test for the url_normalize function Kyle J. McKay

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.