@@ -37,6 +37,10 @@ int credential_match(const struct credential *want,
37
37
#undef CHECK
38
38
}
39
39
40
+
41
+ static int credential_from_potentially_partial_url (struct credential * c ,
42
+ const char * url );
43
+
40
44
static int credential_config_callback (const char * var , const char * value ,
41
45
void * data )
42
46
{
@@ -377,8 +381,31 @@ static int check_url_component(const char *url, int quiet,
377
381
return -1 ;
378
382
}
379
383
380
- int credential_from_url_gently (struct credential * c , const char * url ,
381
- int quiet )
384
+ /*
385
+ * Potentially-partial URLs can, but do not have to, contain
386
+ *
387
+ * - a protocol (or scheme) of the form "<protocol>://"
388
+ *
389
+ * - a host name (the part after the protocol and before the first slash after
390
+ * that, if any)
391
+ *
392
+ * - a user name and potentially a password (as "<user>[:<password>]@" part of
393
+ * the host name)
394
+ *
395
+ * - a path (the part after the host name, if any, starting with the slash)
396
+ *
397
+ * Missing parts will be left unset in `struct credential`. Thus, `https://`
398
+ * will have only the `protocol` set, `example.com` only the host name, and
399
+ * `/git` only the path.
400
+ *
401
+ * Note that an empty host name in an otherwise fully-qualified URL (e.g.
402
+ * `cert:///path/to/cert.pem`) will be treated as unset if we expect the URL to
403
+ * be potentially partial, and only then (otherwise, the empty string is used).
404
+ *
405
+ * The credential_from_url() function does not allow partial URLs.
406
+ */
407
+ static int credential_from_url_1 (struct credential * c , const char * url ,
408
+ int allow_partial_url , int quiet )
382
409
{
383
410
const char * at , * colon , * cp , * slash , * host , * proto_end ;
384
411
@@ -391,12 +418,12 @@ int credential_from_url_gently(struct credential *c, const char *url,
391
418
* (3) proto://<user>:<pass>@<host>/...
392
419
*/
393
420
proto_end = strstr (url , "://" );
394
- if (!proto_end || proto_end == url ) {
421
+ if (!allow_partial_url && (! proto_end || proto_end == url ) ) {
395
422
if (!quiet )
396
423
warning (_ ("url has no scheme: %s" ), url );
397
424
return -1 ;
398
425
}
399
- cp = proto_end + 3 ;
426
+ cp = proto_end ? proto_end + 3 : url ;
400
427
at = strchr (cp , '@' );
401
428
colon = strchr (cp , ':' );
402
429
@@ -427,8 +454,10 @@ int credential_from_url_gently(struct credential *c, const char *url,
427
454
host = at + 1 ;
428
455
}
429
456
430
- c -> protocol = xmemdupz (url , proto_end - url );
431
- c -> host = url_decode_mem (host , slash - host );
457
+ if (proto_end && proto_end - url > 0 )
458
+ c -> protocol = xmemdupz (url , proto_end - url );
459
+ if (!allow_partial_url || slash - host > 0 )
460
+ c -> host = url_decode_mem (host , slash - host );
432
461
/* Trim leading and trailing slashes from path */
433
462
while (* slash == '/' )
434
463
slash ++ ;
@@ -450,6 +479,17 @@ int credential_from_url_gently(struct credential *c, const char *url,
450
479
return 0 ;
451
480
}
452
481
482
+ static int credential_from_potentially_partial_url (struct credential * c ,
483
+ const char * url )
484
+ {
485
+ return credential_from_url_1 (c , url , 1 , 0 );
486
+ }
487
+
488
+ int credential_from_url_gently (struct credential * c , const char * url , int quiet )
489
+ {
490
+ return credential_from_url_1 (c , url , 0 , quiet );
491
+ }
492
+
453
493
void credential_from_url (struct credential * c , const char * url )
454
494
{
455
495
if (credential_from_url_gently (c , url , 0 ) < 0 )
0 commit comments