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>
This commit is contained in:
Jeff King 2011-12-10 05:31:17 -05:00 committed by Junio C Hamano
parent abca927dbe
commit d3e847c107
3 changed files with 57 additions and 0 deletions

View File

@ -67,6 +67,10 @@ Functions
that they may store the result to be used again. Any errors that they may store the result to be used again. Any errors
from helpers are ignored. from helpers are ignored.
`credential_from_url`::
Parse a URL into broken-down credential fields.
Example Example
------- -------

View File

@ -2,6 +2,7 @@
#include "credential.h" #include "credential.h"
#include "string-list.h" #include "string-list.h"
#include "run-command.h" #include "run-command.h"
#include "url.h"
void credential_init(struct credential *c) void credential_init(struct credential *c)
{ {
@ -232,3 +233,54 @@ void credential_reject(struct credential *c)
c->password = NULL; c->password = NULL;
c->approved = 0; c->approved = 0;
} }
void credential_from_url(struct credential *c, const char *url)
{
const char *at, *colon, *cp, *slash, *host, *proto_end;
credential_clear(c);
/*
* Match one of:
* (1) proto://<host>/...
* (2) proto://<user>@<host>/...
* (3) proto://<user>:<pass>@<host>/...
*/
proto_end = strstr(url, "://");
if (!proto_end)
return;
cp = proto_end + 3;
at = strchr(cp, '@');
colon = strchr(cp, ':');
slash = strchrnul(cp, '/');
if (!at || slash <= at) {
/* Case (1) */
host = cp;
}
else if (!colon || at <= colon) {
/* Case (2) */
c->username = url_decode_mem(cp, at - cp);
host = at + 1;
} else {
/* Case (3) */
c->username = url_decode_mem(cp, colon - cp);
c->password = url_decode_mem(colon + 1, at - (colon + 1));
host = at + 1;
}
if (proto_end - url > 0)
c->protocol = xmemdupz(url, proto_end - url);
if (slash - host > 0)
c->host = url_decode_mem(host, slash - host);
/* Trim leading and trailing slashes from path */
while (*slash == '/')
slash++;
if (*slash) {
char *p;
c->path = url_decode(slash);
p = c->path + strlen(c->path) - 1;
while (p > c->path && *p == '/')
*p-- = '\0';
}
}

View File

@ -24,5 +24,6 @@ void credential_approve(struct credential *);
void credential_reject(struct credential *); void credential_reject(struct credential *);
int credential_read(struct credential *, FILE *); int credential_read(struct credential *, FILE *);
void credential_from_url(struct credential *, const char *url);
#endif /* CREDENTIAL_H */ #endif /* CREDENTIAL_H */