1 #define _POSIX_C_SOURCE 200809L
10 /*!stags:re2c format = "const char *@@;\n"; */
13 static void init_input(struct input *in) {
14 /*!stags:re2c format = "in->@@ = 0;\n"; */
29 #define YYSKIP() if (++cur > lim) return 3;
30 #define YYBACKUP() mar = cur
31 #define YYRESTORE() cur = mar
32 #define YYSTAGP(p) p = cur
33 #define YYSTAGN(p) p = 0
35 static int parse_uri(const char *cur, struct tls_uri *uri) {
37 *s1, *u1, *h1, *h3, *h5, *r1, *p1, *p3, *q1, *f1,
38 *s2, *u2, *h2, *h4, *h6, *r2, *p2, *p4, *q2, *f2;
40 const char *mar, *lim;
42 struct input *in = &inp;
45 lim = cur + strlen(cur);
50 re2c:yyfill:enable = 0;
51 re2c:tags:expression = "in->@@";
58 hexdigit = [0-9a-fA-F];
59 unreserved = alpha | digit | [-._~];
60 pct_encoded = "%" hexdigit{2};
61 sub_delims = [!$&'()*+,;=];
62 pchar = unreserved | pct_encoded | sub_delims | [:@];
64 scheme = @s1 alpha (alpha | digit | [-+.])* @s2;
65 userinfo = @u1 (unreserved | pct_encoded | sub_delims | ":")* @u2;
70 | "2" [\x30-\x34] digit
72 ipv4address = dec_octet "." dec_octet "." dec_octet "." dec_octet;
74 ls32 = h16 ":" h16 | ipv4address;
77 | "::" (h16 ":"){5} ls32
78 | ( h16)? "::" (h16 ":"){4} ls32
79 | ((h16 ":"){0,1} h16)? "::" (h16 ":"){3} ls32
80 | ((h16 ":"){0,2} h16)? "::" (h16 ":"){2} ls32
81 | ((h16 ":"){0,3} h16)? "::" h16 ":" ls32
82 | ((h16 ":"){0,4} h16)? "::" ls32
83 | ((h16 ":"){0,5} h16)? "::" h16
84 | ((h16 ":"){0,6} h16)? "::";
85 ipvfuture = "v" hexdigit+ "." (unreserved | sub_delims | ":" )+;
86 ip_literal = "[" ( ipv6address | ipvfuture ) "]";
87 reg_name = (unreserved | pct_encoded | sub_delims)*;
92 port = @r1 digit* @r2;
93 authority = (userinfo "@")? host (":" port)?;
94 path_abempty = ("/" pchar*)*;
95 path_absolute = "/" (pchar+ ("/" pchar*)*)?;
96 path_rootless = pchar+ ("/" pchar*)*;
99 = "//" authority @p1 path_abempty @p2
100 | @p3 (path_absolute | path_rootless | path_empty) @p4;
101 query = @q1 (pchar | [/?])* @q2;
102 fragment = @f1 (pchar | [/?])* @f2;
103 uri = scheme ":" hier_part ("?" query)? ("#" fragment)?;
109 uri->scheme = strndup(s1, (size_t)(s2 - s1));
110 if (u1) uri->userinfo = strndup(u1, (size_t)(u2 - u1));
111 if (h1) uri->host = strndup(h1, (size_t)(h2 - h1));
112 if (h3) uri->host = strndup(h3, (size_t)(h4 - h3));
113 if (h5) uri->host = strndup(h5, (size_t)(h6 - h5));
114 if (r1) uri->port = strndup(r1, (size_t)(r2 - r1));
115 if (p1) uri->path = strndup(p1, (size_t)(p2 - p1));
116 if (p3) uri->path = strndup(p3, (size_t)(p4 - p3));
117 if (q1) uri->query = strndup(q1, (size_t)(q2 - q1));
118 if (f1) uri->fragment = strndup(f1, (size_t)(f2 - f1));
125 static int hex(char *s) {
128 for (i = 0; i < 2; i++) {
132 case '1': r += 1; break;
133 case '2': r += 2; break;
134 case '3': r += 3; break;
135 case '4': r += 4; break;
136 case '5': r += 5; break;
137 case '6': r += 6; break;
138 case '7': r += 7; break;
139 case '8': r += 8; break;
140 case '9': r += 9; break;
142 case 'a': r += 11; break;
144 case 'b': r += 11; break;
146 case 'c': r += 12; break;
148 case 'd': r += 13; break;
150 case 'e': r += 14; break;
152 case 'f': r += 15; break;
154 /* This is an error, but should have
155 been caught at the lexing stage */
162 static void percent_decode(char *s) {
172 if (*(s+1) && *(s+2)) {
185 int tls_parse_uri(char *s, struct tls_uri *uri) {
188 rv = parse_uri(s, uri);
193 if (uri->port == NULL) {
194 if (!strcmp(uri->scheme, "http")) {
195 uri->port = strdup("80");
196 } else if (!strcmp(uri->scheme, "https")) {
197 uri->port = strdup("443");
198 } else if (!strcmp(uri->scheme, "ftp")) {
199 uri->port = strdup("21");
201 uri->port = strdup("0");
205 percent_decode(uri->host);
206 percent_decode(uri->path);
207 percent_decode(uri->query);
210 if (uri->path == NULL || uri->path[0] == 0) {
212 uri->path = strdup("/");
218 void tls_free_uri(struct tls_uri *uri) {