Skip to content

Commit

Permalink
credential: add function for parsing url components
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jeff King authored and Junio C Hamano committed Dec 12, 2011
1 parent abca927 commit d3e847c
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Documentation/technical/api-credentials.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ Functions
that they may store the result to be used again. Any errors
from helpers are ignored.

`credential_from_url`::

Parse a URL into broken-down credential fields.

Example
-------

Expand Down
52 changes: 52 additions & 0 deletions credential.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "credential.h"
#include "string-list.h"
#include "run-command.h"
#include "url.h"

void credential_init(struct credential *c)
{
Expand Down Expand Up @@ -232,3 +233,54 @@ void credential_reject(struct credential *c)
c->password = NULL;
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';
}
}
1 change: 1 addition & 0 deletions credential.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ void credential_approve(struct credential *);
void credential_reject(struct credential *);

int credential_read(struct credential *, FILE *);
void credential_from_url(struct credential *, const char *url);

#endif /* CREDENTIAL_H */

0 comments on commit d3e847c

Please sign in to comment.