Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tag: v1.7.4.1
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 142 lines (124 sloc) 3.023 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
#include "cache.h"

int is_urlschemechar(int first_flag, int ch)
{
/*
* The set of valid URL schemes, as per STD66 (RFC3986) is
* '[A-Za-z][A-Za-z0-9+.-]*'. But use sightly looser check
* of '[A-Za-z0-9][A-Za-z0-9+.-]*' because earlier version
* of check used '[A-Za-z0-9]+' so not to break any remote
* helpers.
*/
int alphanumeric, special;
alphanumeric = ch > 0 && isalnum(ch);
special = ch == '+' || ch == '-' || ch == '.';
return alphanumeric || (!first_flag && special);
}

int is_url(const char *url)
{
const char *url2, *first_slash;

if (!url)
return 0;
url2 = url;
first_slash = strchr(url, '/');

/* Input with no slash at all or slash first can't be URL. */
if (!first_slash || first_slash == url)
return 0;
/* Character before must be : and next must be /. */
if (first_slash[-1] != ':' || first_slash[1] != '/')
return 0;
/* There must be something before the :// */
if (first_slash == url + 1)
return 0;
/*
* Check all characters up to first slash - 1. Only alphanum
* is allowed.
*/
url2 = url;
while (url2 < first_slash - 1) {
if (!is_urlschemechar(url2 == url, (unsigned char)*url2))
return 0;
url2++;
}

/* Valid enough. */
return 1;
}

static int url_decode_char(const char *q)
{
int i;
unsigned char val = 0;
for (i = 0; i < 2; i++) {
unsigned char c = *q++;
val <<= 4;
if (c >= '0' && c <= '9')
val += c - '0';
else if (c >= 'a' && c <= 'f')
val += c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
val += c - 'A' + 10;
else
return -1;
}
return val;
}

static char *url_decode_internal(const char **query, const char *stop_at,
struct strbuf *out, int decode_plus)
{
const char *q = *query;

do {
unsigned char c = *q;

if (!c)
break;
if (stop_at && strchr(stop_at, c)) {
q++;
break;
}

if (c == '%') {
int val = url_decode_char(q + 1);
if (0 <= val) {
strbuf_addch(out, val);
q += 3;
continue;
}
}

if (decode_plus && c == '+')
strbuf_addch(out, ' ');
else
strbuf_addch(out, c);
q++;
} while (1);
*query = q;
return strbuf_detach(out, NULL);
}

char *url_decode(const char *url)
{
struct strbuf out = STRBUF_INIT;
const char *colon = strchr(url, ':');

/* Skip protocol part if present */
if (colon && url < colon) {
strbuf_add(&out, url, colon - url);
url = colon;
}
return url_decode_internal(&url, NULL, &out, 0);
}

char *url_decode_parameter_name(const char **query)
{
struct strbuf out = STRBUF_INIT;
return url_decode_internal(query, "&=", &out, 1);
}

char *url_decode_parameter_value(const char **query)
{
struct strbuf out = STRBUF_INIT;
return url_decode_internal(query, "&", &out, 1);
}

void end_url_with_slash(struct strbuf *buf, const char *url)
{
strbuf_addstr(buf, url);
if (buf->len && buf->buf[buf->len - 1] != '/')
strbuf_addstr(buf, "/");
}

void str_end_url_with_slash(const char *url, char **dest) {
struct strbuf buf = STRBUF_INIT;
end_url_with_slash(&buf, url);
free(*dest);
*dest = strbuf_detach(&buf, NULL);
}
Something went wrong with that request. Please try again.