summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/technical/api-credentials.txt4
-rw-r--r--credential.c52
-rw-r--r--credential.h1
3 files changed, 57 insertions, 0 deletions
diff --git a/Documentation/technical/api-credentials.txt b/Documentation/technical/api-credentials.txt
index f624aefc6f..21ca6a2553 100644
--- a/Documentation/technical/api-credentials.txt
+++ b/Documentation/technical/api-credentials.txt
@@ -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
-------
diff --git a/credential.c b/credential.c
index 86397f392b..c349b9aac3 100644
--- a/credential.c
+++ b/credential.c
@@ -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';
+ }
+}
diff --git a/credential.h b/credential.h
index 2ea7d495d6..8a6d162e7b 100644
--- a/credential.h
+++ b/credential.h
@@ -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 */