Skip to content

Commit d3e847c

Browse files
peffgitster
authored andcommitted
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:[email protected]/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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent abca927 commit d3e847c

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

Documentation/technical/api-credentials.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ Functions
6767
that they may store the result to be used again. Any errors
6868
from helpers are ignored.
6969

70+
`credential_from_url`::
71+
72+
Parse a URL into broken-down credential fields.
73+
7074
Example
7175
-------
7276

credential.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "credential.h"
33
#include "string-list.h"
44
#include "run-command.h"
5+
#include "url.h"
56

67
void credential_init(struct credential *c)
78
{
@@ -232,3 +233,54 @@ void credential_reject(struct credential *c)
232233
c->password = NULL;
233234
c->approved = 0;
234235
}
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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ void credential_approve(struct credential *);
2424
void credential_reject(struct credential *);
2525

2626
int credential_read(struct credential *, FILE *);
27+
void credential_from_url(struct credential *, const char *url);
2728

2829
#endif /* CREDENTIAL_H */

0 commit comments

Comments
 (0)