git
/
url.c
121 строка · 2.6 Кб
1#include "git-compat-util.h"2#include "hex-ll.h"3#include "strbuf.h"4#include "url.h"5
6int is_urlschemechar(int first_flag, int ch)7{
8/*9* The set of valid URL schemes, as per STD66 (RFC3986) is
10* '[A-Za-z][A-Za-z0-9+.-]*'. But use slightly looser check
11* of '[A-Za-z0-9][A-Za-z0-9+.-]*' because earlier version
12* of check used '[A-Za-z0-9]+' so not to break any remote
13* helpers.
14*/
15int alphanumeric, special;16alphanumeric = ch > 0 && isalnum(ch);17special = ch == '+' || ch == '-' || ch == '.';18return alphanumeric || (!first_flag && special);19}
20
21int is_url(const char *url)22{
23/* Is "scheme" part reasonable? */24if (!url || !is_urlschemechar(1, *url++))25return 0;26while (*url && *url != ':') {27if (!is_urlschemechar(0, *url++))28return 0;29}30/* We've seen "scheme"; we want colon-slash-slash */31return (url[0] == ':' && url[1] == '/' && url[2] == '/');32}
33
34static char *url_decode_internal(const char **query, int len,35const char *stop_at, struct strbuf *out,36int decode_plus)37{
38const char *q = *query;39
40while (len) {41unsigned char c = *q;42
43if (!c)44break;45if (stop_at && strchr(stop_at, c)) {46q++;47len--;48break;49}50
51if (c == '%' && (len < 0 || len >= 3)) {52int val = hex2chr(q + 1);53if (0 < val) {54strbuf_addch(out, val);55q += 3;56len -= 3;57continue;58}59}60
61if (decode_plus && c == '+')62strbuf_addch(out, ' ');63else64strbuf_addch(out, c);65q++;66len--;67}68*query = q;69return strbuf_detach(out, NULL);70}
71
72char *url_decode(const char *url)73{
74return url_decode_mem(url, strlen(url));75}
76
77char *url_decode_mem(const char *url, int len)78{
79struct strbuf out = STRBUF_INIT;80const char *colon = memchr(url, ':', len);81
82/* Skip protocol part if present */83if (colon && url < colon) {84strbuf_add(&out, url, colon - url);85len -= colon - url;86url = colon;87}88return url_decode_internal(&url, len, NULL, &out, 0);89}
90
91char *url_percent_decode(const char *encoded)92{
93struct strbuf out = STRBUF_INIT;94return url_decode_internal(&encoded, strlen(encoded), NULL, &out, 0);95}
96
97char *url_decode_parameter_name(const char **query)98{
99struct strbuf out = STRBUF_INIT;100return url_decode_internal(query, -1, "&=", &out, 1);101}
102
103char *url_decode_parameter_value(const char **query)104{
105struct strbuf out = STRBUF_INIT;106return url_decode_internal(query, -1, "&", &out, 1);107}
108
109void end_url_with_slash(struct strbuf *buf, const char *url)110{
111strbuf_addstr(buf, url);112strbuf_complete(buf, '/');113}
114
115void str_end_url_with_slash(const char *url, char **dest)116{
117struct strbuf buf = STRBUF_INIT;118end_url_with_slash(&buf, url);119free(*dest);120*dest = strbuf_detach(&buf, NULL);121}
122