Code

credential: add function for parsing url components
authorJeff King <peff@peff.net>
Sat, 10 Dec 2011 10:31:17 +0000 (05:31 -0500)
committerJunio C Hamano <gitster@pobox.com>
Mon, 12 Dec 2011 07:16:24 +0000 (23:16 -0800)
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>
Documentation/technical/api-credentials.txt
credential.c
credential.h

index f624aefc6faae828e7caabb4b335a9c659444768..21ca6a2553280a111eca47f2f7aea37ea43ecfa0 100644 (file)
@@ -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
 -------
 
index 86397f392b8e6bd9580928653f6d1103b05f4417..c349b9aac3999ba4dbce16fd82b582cd60d61761 100644 (file)
@@ -2,6 +2,7 @@
 #include "credential.h"
 #include "string-list.h"
 #include "run-command.h"
+#include "url.h"
 
 void credential_init(struct credential *c)
 {
@@ -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';
+       }
+}
index 2ea7d495d6bbcd4ad5496dbce759c45a880175ba..8a6d162e7b477d329b23effae8f0007163f39f3d 100644 (file)
@@ -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 */