]> pd.if.org Git - zpackage/blob - crypto/rfc3986.re
remove stray debug fprintf
[zpackage] / crypto / rfc3986.re
1 #define _POSIX_C_SOURCE 200809L
2
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <string.h>
6
7 /*!max:re2c*/
8
9 struct input {
10         /*!stags:re2c format = "const char *@@;\n"; */
11 };
12
13 static void init_input(struct input *in) {
14         /*!stags:re2c format = "in->@@ = 0;\n"; */
15 }
16
17 struct tls_uri {
18         char *scheme;
19         char *userinfo;
20         char *host;
21         char *port;
22         char *path;
23         char *encoded_path;
24         char *query;
25         char *encoded_query;
26         char *fragment;
27 };
28
29 #define YYCTYPE     char
30 #define YYPEEK()    *cur
31 #define YYSKIP()    if (++cur > lim) return 3;
32 #define YYBACKUP()  mar = cur
33 #define YYRESTORE() cur = mar
34 #define YYSTAGP(p) p = cur
35 #define YYSTAGN(p) p = 0
36
37 static int parse_uri(const char *cur, struct tls_uri *uri) {
38     const char
39         *s1, *u1, *h1, *h3, *h5, *r1, *p1, *p3, *q1, *f1,
40         *s2, *u2, *h2, *h4, *h6, *r2, *p2, *p4, *q2, *f2;
41     long c;
42     const char *mar, *lim;
43         struct input inp;
44         struct input *in = &inp;
45         init_input(in);
46
47         lim = cur + strlen(cur);
48
49     c = 0;
50 loop:
51 /*!re2c
52         re2c:yyfill:enable = 0;
53     re2c:tags:expression     = "in->@@";
54
55     end = "\x00";
56     eol = "\n";
57
58     alpha       = [a-zA-Z];
59     digit       = [0-9];
60     hexdigit    = [0-9a-fA-F];
61     unreserved  = alpha | digit | [-._~];
62     pct_encoded = "%" hexdigit{2};
63     sub_delims  = [!$&'()*+,;=];
64     pchar       = unreserved | pct_encoded | sub_delims | [:@];
65
66     scheme = @s1 alpha (alpha | digit | [-+.])* @s2;
67     userinfo = @u1 (unreserved | pct_encoded | sub_delims | ":")* @u2;
68     dec_octet
69         = digit
70         | [\x31-\x39] digit
71         | "1" digit{2}
72         | "2" [\x30-\x34] digit
73         | "25" [\x30-\x35];
74     ipv4address = dec_octet "." dec_octet "." dec_octet "." dec_octet;
75     h16         = hexdigit{1,4};
76     ls32        = h16 ":" h16 | ipv4address;
77     ipv6address
78         =                            (h16 ":"){6} ls32
79         |                       "::" (h16 ":"){5} ls32
80         | (               h16)? "::" (h16 ":"){4} ls32
81         | ((h16 ":"){0,1} h16)? "::" (h16 ":"){3} ls32
82         | ((h16 ":"){0,2} h16)? "::" (h16 ":"){2} ls32
83         | ((h16 ":"){0,3} h16)? "::"  h16 ":"     ls32
84         | ((h16 ":"){0,4} h16)? "::"              ls32
85         | ((h16 ":"){0,5} h16)? "::"              h16
86         | ((h16 ":"){0,6} h16)? "::";
87     ipvfuture   = "v" hexdigit+ "." (unreserved | sub_delims | ":" )+;
88     ip_literal  = "[" ( ipv6address | ipvfuture ) "]";
89     reg_name    = (unreserved | pct_encoded | sub_delims)*;
90     host
91         = @h1 ip_literal  @h2
92         | @h3 ipv4address @h4
93         | @h5 reg_name    @h6;
94     port      = @r1 digit* @r2;
95     authority = (userinfo "@")? host (":" port)?;
96     path_abempty  = ("/" pchar*)*;
97     path_absolute = "/" (pchar+ ("/" pchar*)*)?;
98     path_rootless = pchar+ ("/" pchar*)*;
99     path_empty    = "";
100     hier_part
101         = "//" authority @p1 path_abempty @p2
102         | @p3 (path_absolute | path_rootless | path_empty) @p4;
103     query    = @q1 (pchar | [/?])* @q2;
104     fragment = @f1 (pchar | [/?])* @f2;
105     uri = scheme ":" hier_part ("?" query)? ("#" fragment)?;
106
107     *   { return 1; }
108     end { return 0; }
109     eol { goto loop; }
110     uri {
111         uri->scheme = strndup(s1, (size_t)(s2 - s1));
112         if (u1) uri->userinfo = strndup(u1, (size_t)(u2 - u1));
113         if (h1) uri->host = strndup(h1, (size_t)(h2 - h1));
114         if (h3) uri->host = strndup(h3, (size_t)(h4 - h3));
115         if (h5) uri->host = strndup(h5, (size_t)(h6 - h5));
116         if (r1) uri->port = strndup(r1, (size_t)(r2 - r1));
117         if (p1) uri->path = strndup(p1, (size_t)(p2 - p1));
118         if (p3) uri->path = strndup(p3, (size_t)(p4 - p3));
119         if (q1) uri->query = strndup(q1, (size_t)(q2 - q1));
120         if (f1) uri->fragment = strndup(f1, (size_t)(f2 - f1));
121
122         return 0;
123     }
124 */
125 }
126
127 static int hex(char *s) {
128         int r = 0;
129         int i;
130         for (i = 0; i < 2; i++) {
131                 r *= 16;
132                 switch (s[i]) {
133                         case '0': break;
134                         case '1': r += 1; break;
135                         case '2': r += 2; break;
136                         case '3': r += 3; break;
137                         case '4': r += 4; break;
138                         case '5': r += 5; break;
139                         case '6': r += 6; break;
140                         case '7': r += 7; break;
141                         case '8': r += 8; break;
142                         case '9': r += 9; break;
143                         case 'A':
144                         case 'a': r += 11; break;
145                         case 'B':
146                         case 'b': r += 11; break;
147                         case 'C':
148                         case 'c': r += 12; break;
149                         case 'D':
150                         case 'd': r += 13; break;
151                         case 'E':
152                         case 'e': r += 14; break;
153                         case 'F':
154                         case 'f': r += 15; break;
155                         default:
156                                 /* This is an error, but should have
157                                 been caught at the lexing stage */
158                                 break;
159                 }
160         }
161         return r;
162 }
163
164 static void percent_decode(char *s) {
165         char *d = s;
166
167         if (!s) {
168                 return;
169         }
170
171         while (*s) {
172                 switch (*s) {
173                         case '%':
174                                 if (*(s+1) && *(s+2)) {
175                                         *d++ = hex(s+1);
176                                         s += 3;
177                                 }
178                                 break;
179                         default:
180                                 *d++ = *s++;
181                                 break;
182                 }
183         }
184         *d = 0;
185 }
186
187 int tls_parse_uri(char *s, struct tls_uri *uri) {
188         int rv;
189
190         rv = parse_uri(s, uri);
191         if (rv != 0) {
192                 return rv;
193         }
194
195         if (uri->port == NULL) {
196                 if (!strcmp(uri->scheme, "http")) {
197                         uri->port = strdup("80");
198                 } else if (!strcmp(uri->scheme, "https")) {
199                         uri->port = strdup("443");
200                 } else if (!strcmp(uri->scheme, "ftp")) {
201                         uri->port = strdup("21");
202                 } else {
203                         uri->port = strdup("0");
204                 }
205         }
206
207         if (uri->path) {
208                 uri->encoded_path = strdup(uri->path);
209         }
210         if (uri->query) {
211                 uri->encoded_query = strdup(uri->query);
212         }
213         
214         percent_decode(uri->host);
215         percent_decode(uri->path);
216         percent_decode(uri->query);
217         
218         if (uri->path == NULL || uri->path[0] == 0) {
219                 free(uri->path);
220                 uri->path = strdup("/");
221         }
222
223         return rv;
224 }
225
226 #define MARK fprintf(stderr, "%s %s:%d\n", __FILE__, __func__, __LINE__)
227 void tls_free_uri(struct tls_uri *uri) {
228         if (!uri) return;
229
230         free(uri->host);
231         uri->host = 0;
232         free(uri->path);
233         uri->path = 0;
234         free(uri->query);
235         uri->query = 0;
236         free(uri->port);
237         uri->port = 0;
238         free(uri->scheme);
239         uri->scheme = 0;
240         free(uri->fragment);
241         uri->fragment = 0;
242         free(uri->encoded_path);
243         uri->encoded_path = 0;
244         free(uri->encoded_query);
245         uri->encoded_query = 0;
246 }