···99#include "dir.h"
1010#include "refs.h"
1111#include "branch.h"
1212+#include "url.h"
12131314/* rsync support */
1415···871872 return S_ISREG(buf.st_mode);
872873}
873874874874-static int isurlschemechar(int first_flag, int ch)
875875-{
876876- /*
877877- * The set of valid URL schemes, as per STD66 (RFC3986) is
878878- * '[A-Za-z][A-Za-z0-9+.-]*'. But use sightly looser check
879879- * of '[A-Za-z0-9][A-Za-z0-9+.-]*' because earlier version
880880- * of check used '[A-Za-z0-9]+' so not to break any remote
881881- * helpers.
882882- */
883883- int alphanumeric, special;
884884- alphanumeric = ch > 0 && isalnum(ch);
885885- special = ch == '+' || ch == '-' || ch == '.';
886886- return alphanumeric || (!first_flag && special);
887887-}
888888-889889-static int is_url(const char *url)
890890-{
891891- const char *url2, *first_slash;
892892-893893- if (!url)
894894- return 0;
895895- url2 = url;
896896- first_slash = strchr(url, '/');
897897-898898- /* Input with no slash at all or slash first can't be URL. */
899899- if (!first_slash || first_slash == url)
900900- return 0;
901901- /* Character before must be : and next must be /. */
902902- if (first_slash[-1] != ':' || first_slash[1] != '/')
903903- return 0;
904904- /* There must be something before the :// */
905905- if (first_slash == url + 1)
906906- return 0;
907907- /*
908908- * Check all characters up to first slash - 1. Only alphanum
909909- * is allowed.
910910- */
911911- url2 = url;
912912- while (url2 < first_slash - 1) {
913913- if (!isurlschemechar(url2 == url, (unsigned char)*url2))
914914- return 0;
915915- url2++;
916916- }
917917-918918- /* Valid enough. */
919919- return 1;
920920-}
921921-922875static int external_specification_len(const char *url)
923876{
924877 return strchr(url, ':') - url;
···946899 if (url) {
947900 const char *p = url;
948901949949- while (isurlschemechar(p == url, *p))
902902+ while (is_urlschemechar(p == url, *p))
950903 p++;
951904 if (!prefixcmp(p, "::"))
952905 helper = xstrndup(url, p - url);
+118
url.c
···11+#include "cache.h"
22+33+int is_urlschemechar(int first_flag, int ch)
44+{
55+ /*
66+ * The set of valid URL schemes, as per STD66 (RFC3986) is
77+ * '[A-Za-z][A-Za-z0-9+.-]*'. But use sightly looser check
88+ * of '[A-Za-z0-9][A-Za-z0-9+.-]*' because earlier version
99+ * of check used '[A-Za-z0-9]+' so not to break any remote
1010+ * helpers.
1111+ */
1212+ int alphanumeric, special;
1313+ alphanumeric = ch > 0 && isalnum(ch);
1414+ special = ch == '+' || ch == '-' || ch == '.';
1515+ return alphanumeric || (!first_flag && special);
1616+}
1717+1818+int is_url(const char *url)
1919+{
2020+ const char *url2, *first_slash;
2121+2222+ if (!url)
2323+ return 0;
2424+ url2 = url;
2525+ first_slash = strchr(url, '/');
2626+2727+ /* Input with no slash at all or slash first can't be URL. */
2828+ if (!first_slash || first_slash == url)
2929+ return 0;
3030+ /* Character before must be : and next must be /. */
3131+ if (first_slash[-1] != ':' || first_slash[1] != '/')
3232+ return 0;
3333+ /* There must be something before the :// */
3434+ if (first_slash == url + 1)
3535+ return 0;
3636+ /*
3737+ * Check all characters up to first slash - 1. Only alphanum
3838+ * is allowed.
3939+ */
4040+ url2 = url;
4141+ while (url2 < first_slash - 1) {
4242+ if (!is_urlschemechar(url2 == url, (unsigned char)*url2))
4343+ return 0;
4444+ url2++;
4545+ }
4646+4747+ /* Valid enough. */
4848+ return 1;
4949+}
5050+5151+static int url_decode_char(const char *q)
5252+{
5353+ int i;
5454+ unsigned char val = 0;
5555+ for (i = 0; i < 2; i++) {
5656+ unsigned char c = *q++;
5757+ val <<= 4;
5858+ if (c >= '0' && c <= '9')
5959+ val += c - '0';
6060+ else if (c >= 'a' && c <= 'f')
6161+ val += c - 'a' + 10;
6262+ else if (c >= 'A' && c <= 'F')
6363+ val += c - 'A' + 10;
6464+ else
6565+ return -1;
6666+ }
6767+ return val;
6868+}
6969+7070+static char *url_decode_internal(const char **query, const char *stop_at)
7171+{
7272+ const char *q = *query;
7373+ struct strbuf out;
7474+7575+ strbuf_init(&out, 16);
7676+ do {
7777+ unsigned char c = *q;
7878+7979+ if (!c)
8080+ break;
8181+ if (stop_at && strchr(stop_at, c)) {
8282+ q++;
8383+ break;
8484+ }
8585+8686+ if (c == '%') {
8787+ int val = url_decode_char(q + 1);
8888+ if (0 <= val) {
8989+ strbuf_addch(&out, val);
9090+ q += 3;
9191+ continue;
9292+ }
9393+ }
9494+9595+ if (c == '+')
9696+ strbuf_addch(&out, ' ');
9797+ else
9898+ strbuf_addch(&out, c);
9999+ q++;
100100+ } while (1);
101101+ *query = q;
102102+ return strbuf_detach(&out, NULL);
103103+}
104104+105105+char *url_decode(const char *url)
106106+{
107107+ return url_decode_internal(&url, NULL);
108108+}
109109+110110+char *url_decode_parameter_name(const char **query)
111111+{
112112+ return url_decode_internal(query, "&=");
113113+}
114114+115115+char *url_decode_parameter_value(const char **query)
116116+{
117117+ return url_decode_internal(query, "&");
118118+}