credential: add function for parsing url components

All of the components of a credential struct can be found in a URL. For example, the URL: http://foo:bar@example.com/repo.git contains: protocol=http host=example.com path=repo.git username=foo password=bar We want to be able to turn URLs into broken-down credential structs so that we know two things: 1. Which parts of the username/password we still need 2. What the context of the request is (for prompting or as a key for storing credentials). This code is based on http_auth_init in http.c, but needed a few modifications in order to get all of the components that the credential object is interested in. Once the http code is switched over to the credential API, then http_auth_init can just go away. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Dec 10, 2011 at 05:31 UTC d3e847c107c236126476e7efb272be3fa4339825
3 files changed +57
Documentation/technical/api-credentials.txt
+4
@@ -67,6 +67,10 @@ Functions
67 that they may store the result to be used again. Any errors
68 from helpers are ignored.
69
70 +`credential_from_url`::
71 +
72 + Parse a URL into broken-down credential fields.
73 +
74 Example
75 -------
76
credential.c
+52
@@ -2,6 +2,7 @@
2 #include "credential.h"
3 #include "string-list.h"
4 #include "run-command.h"
5 +#include "url.h"
6
7 void credential_init(struct credential *c)
8 {
@@ -232,3 +233,54 @@ void credential_reject(struct credential *c)
233 c->password = NULL;
234 c->approved = 0;
235 }
236 +
237 +void credential_from_url(struct credential *c, const char *url)
238 +{
239 + const char *at, *colon, *cp, *slash, *host, *proto_end;
240 +
241 + credential_clear(c);
242 +
243 + /*
244 + * Match one of:
245 + * (1) proto://<host>/...
246 + * (2) proto://<user>@<host>/...
247 + * (3) proto://<user>:<pass>@<host>/...
248 + */
249 + proto_end = strstr(url, "://");
250 + if (!proto_end)
251 + return;
252 + cp = proto_end + 3;
253 + at = strchr(cp, '@');
254 + colon = strchr(cp, ':');
255 + slash = strchrnul(cp, '/');
256 +
257 + if (!at || slash <= at) {
258 + /* Case (1) */
259 + host = cp;
260 + }
261 + else if (!colon || at <= colon) {
262 + /* Case (2) */
263 + c->username = url_decode_mem(cp, at - cp);
264 + host = at + 1;
265 + } else {
266 + /* Case (3) */
267 + c->username = url_decode_mem(cp, colon - cp);
268 + c->password = url_decode_mem(colon + 1, at - (colon + 1));
269 + host = at + 1;
270 + }
271 +
272 + if (proto_end - url > 0)
273 + c->protocol = xmemdupz(url, proto_end - url);
274 + if (slash - host > 0)
275 + c->host = url_decode_mem(host, slash - host);
276 + /* Trim leading and trailing slashes from path */
277 + while (*slash == '/')
278 + slash++;
279 + if (*slash) {
280 + char *p;
281 + c->path = url_decode(slash);
282 + p = c->path + strlen(c->path) - 1;
283 + while (p > c->path && *p == '/')
284 + *p-- = '\0';
285 + }
286 +}
credential.h
+1
@@ -24,5 +24,6 @@ void credential_approve(struct credential *);
24 void credential_reject(struct credential *);
25
26 int credential_read(struct credential *, FILE *);
27 +void credential_from_url(struct credential *, const char *url);
28
29 #endif /* CREDENTIAL_H */