Git fork
at reftables-rust 121 lines 2.7 kB view raw
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 */ 15 int alphanumeric, special; 16 alphanumeric = ch > 0 && isalnum(ch); 17 special = ch == '+' || ch == '-' || ch == '.'; 18 return alphanumeric || (!first_flag && special); 19} 20 21int is_url(const char *url) 22{ 23 /* Is "scheme" part reasonable? */ 24 if (!url || !is_urlschemechar(1, *url++)) 25 return 0; 26 while (*url && *url != ':') { 27 if (!is_urlschemechar(0, *url++)) 28 return 0; 29 } 30 /* We've seen "scheme"; we want colon-slash-slash */ 31 return (url[0] == ':' && url[1] == '/' && url[2] == '/'); 32} 33 34static char *url_decode_internal(const char **query, int len, 35 const char *stop_at, struct strbuf *out, 36 int decode_plus) 37{ 38 const char *q = *query; 39 40 while (len) { 41 unsigned char c = *q; 42 43 if (!c) 44 break; 45 if (stop_at && strchr(stop_at, c)) { 46 q++; 47 len--; 48 break; 49 } 50 51 if (c == '%' && (len < 0 || len >= 3)) { 52 int val = hex2chr(q + 1); 53 if (0 < val) { 54 strbuf_addch(out, val); 55 q += 3; 56 len -= 3; 57 continue; 58 } 59 } 60 61 if (decode_plus && c == '+') 62 strbuf_addch(out, ' '); 63 else 64 strbuf_addch(out, c); 65 q++; 66 len--; 67 } 68 *query = q; 69 return strbuf_detach(out, NULL); 70} 71 72char *url_decode(const char *url) 73{ 74 return url_decode_mem(url, strlen(url)); 75} 76 77char *url_decode_mem(const char *url, int len) 78{ 79 struct strbuf out = STRBUF_INIT; 80 const char *colon = memchr(url, ':', len); 81 82 /* Skip protocol part if present */ 83 if (colon && url < colon) { 84 strbuf_add(&out, url, colon - url); 85 len -= colon - url; 86 url = colon; 87 } 88 return url_decode_internal(&url, len, NULL, &out, 0); 89} 90 91char *url_percent_decode(const char *encoded) 92{ 93 struct strbuf out = STRBUF_INIT; 94 return url_decode_internal(&encoded, strlen(encoded), NULL, &out, 0); 95} 96 97char *url_decode_parameter_name(const char **query) 98{ 99 struct strbuf out = STRBUF_INIT; 100 return url_decode_internal(query, -1, "&=", &out, 1); 101} 102 103char *url_decode_parameter_value(const char **query) 104{ 105 struct strbuf out = STRBUF_INIT; 106 return url_decode_internal(query, -1, "&", &out, 1); 107} 108 109void end_url_with_slash(struct strbuf *buf, const char *url) 110{ 111 strbuf_addstr(buf, url); 112 strbuf_complete(buf, '/'); 113} 114 115void str_end_url_with_slash(const char *url, char **dest) 116{ 117 struct strbuf buf = STRBUF_INIT; 118 end_url_with_slash(&buf, url); 119 free(*dest); 120 *dest = strbuf_detach(&buf, NULL); 121}