5 int is_urlschemechar(int first_flag
, int ch
)
8 * The set of valid URL schemes, as per STD66 (RFC3986) is
9 * '[A-Za-z][A-Za-z0-9+.-]*'. But use slightly looser check
10 * of '[A-Za-z0-9][A-Za-z0-9+.-]*' because earlier version
11 * of check used '[A-Za-z0-9]+' so not to break any remote
14 int alphanumeric
, special
;
15 alphanumeric
= ch
> 0 && isalnum(ch
);
16 special
= ch
== '+' || ch
== '-' || ch
== '.';
17 return alphanumeric
|| (!first_flag
&& special
);
20 int is_url(const char *url
)
22 /* Is "scheme" part reasonable? */
23 if (!url
|| !is_urlschemechar(1, *url
++))
25 while (*url
&& *url
!= ':') {
26 if (!is_urlschemechar(0, *url
++))
29 /* We've seen "scheme"; we want colon-slash-slash */
30 return (url
[0] == ':' && url
[1] == '/' && url
[2] == '/');
33 static char *url_decode_internal(const char **query
, int len
,
34 const char *stop_at
, struct strbuf
*out
,
37 const char *q
= *query
;
44 if (stop_at
&& strchr(stop_at
, c
)) {
50 if (c
== '%' && (len
< 0 || len
>= 3)) {
51 int val
= hex2chr(q
+ 1);
53 strbuf_addch(out
, val
);
60 if (decode_plus
&& c
== '+')
61 strbuf_addch(out
, ' ');
68 return strbuf_detach(out
, NULL
);
71 char *url_decode(const char *url
)
73 return url_decode_mem(url
, strlen(url
));
76 char *url_decode_mem(const char *url
, int len
)
78 struct strbuf out
= STRBUF_INIT
;
79 const char *colon
= memchr(url
, ':', len
);
81 /* Skip protocol part if present */
82 if (colon
&& url
< colon
) {
83 strbuf_add(&out
, url
, colon
- url
);
87 return url_decode_internal(&url
, len
, NULL
, &out
, 0);
90 char *url_percent_decode(const char *encoded
)
92 struct strbuf out
= STRBUF_INIT
;
93 return url_decode_internal(&encoded
, strlen(encoded
), NULL
, &out
, 0);
96 char *url_decode_parameter_name(const char **query
)
98 struct strbuf out
= STRBUF_INIT
;
99 return url_decode_internal(query
, -1, "&=", &out
, 1);
102 char *url_decode_parameter_value(const char **query
)
104 struct strbuf out
= STRBUF_INIT
;
105 return url_decode_internal(query
, -1, "&", &out
, 1);
108 void end_url_with_slash(struct strbuf
*buf
, const char *url
)
110 strbuf_addstr(buf
, url
);
111 strbuf_complete(buf
, '/');
114 void str_end_url_with_slash(const char *url
, char **dest
)
116 struct strbuf buf
= STRBUF_INIT
;
117 end_url_with_slash(&buf
, url
);
119 *dest
= strbuf_detach(&buf
, NULL
);