* Potentially-partial URLs can, but do not have to, contain * * - a protocol (or scheme) of the form " ://" * * - a host name (the part after the protocol and before the first slash after * that, if any) * * - a user name and potentially a password (as " [: ]@" part of * the host name) * * - a path (the part after the host name, if any, starting with the slash)
| 618 | * The credential_from_url() function does not allow partial URLs. |
| 619 | */ |
| 620 | static int credential_from_url_1(struct credential *c, const char *url, |
| 621 | int allow_partial_url, int quiet) |
| 622 | { |
| 623 | const char *at, *colon, *cp, *slash, *host, *proto_end; |
| 624 | |
| 625 | credential_clear(c); |
| 626 | |
| 627 | /* |
| 628 | * Match one of: |
| 629 | * (1) proto://<host>/... |
| 630 | * (2) proto://<user>@<host>/... |
| 631 | * (3) proto://<user>:<pass>@<host>/... |
| 632 | */ |
| 633 | proto_end = strstr(url, "://"); |
| 634 | if (!allow_partial_url && (!proto_end || proto_end == url)) { |
| 635 | if (!quiet) |
| 636 | warning(_("url has no scheme: %s"), url); |
| 637 | return -1; |
| 638 | } |
| 639 | cp = proto_end ? proto_end + 3 : url; |
| 640 | at = strchr(cp, '@'); |
| 641 | colon = strchr(cp, ':'); |
| 642 | |
| 643 | /* |
| 644 | * A query or fragment marker before the slash ends the host portion. |
| 645 | * We'll just continue to call this "slash" for simplicity. Notably our |
| 646 | * "trim leading slashes" part won't skip over this part of the path, |
| 647 | * but that's what we'd want. |
| 648 | */ |
| 649 | slash = cp + strcspn(cp, "/?#"); |
| 650 | |
| 651 | if (!at || slash <= at) { |
| 652 | /* Case (1) */ |
| 653 | host = cp; |
| 654 | } |
| 655 | else if (!colon || at <= colon) { |
| 656 | /* Case (2) */ |
| 657 | c->username = url_decode_mem(cp, at - cp); |
| 658 | if (c->username && *c->username) |
| 659 | c->username_from_proto = 1; |
| 660 | host = at + 1; |
| 661 | } else { |
| 662 | /* Case (3) */ |
| 663 | c->username = url_decode_mem(cp, colon - cp); |
| 664 | if (c->username && *c->username) |
| 665 | c->username_from_proto = 1; |
| 666 | c->password = url_decode_mem(colon + 1, at - (colon + 1)); |
| 667 | host = at + 1; |
| 668 | } |
| 669 | |
| 670 | if (proto_end && proto_end - url > 0) |
| 671 | c->protocol = xmemdupz(url, proto_end - url); |
| 672 | if (!allow_partial_url || slash - host > 0) |
| 673 | c->host = url_decode_mem(host, slash - host); |
| 674 | /* Trim leading and trailing slashes from path */ |
| 675 | while (*slash == '/') |
| 676 | slash++; |
| 677 | if (*slash) { |
no test coverage detected