1 /* Generated by re2c 1.2.1 on Wed Apr 1 00:57:32 2020 */
2 #line 1 "src/net/URL.re"
3 /*
4 * Copyright (C) Tildeslash Ltd. All rights reserved.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * In addition, as a special exception, the copyright holders give
18 * permission to link the code of portions of this program with the
19 * OpenSSL library under certain conditions as described in each
20 * individual source file, and distribute linked combinations
21 * including the two.
22 *
23 * You must obey the GNU General Public License in all respects
24 * for all of the code used other than OpenSSL.
25 */
26
27
28 #include "Config.h"
29
30 #include <stdio.h>
31 #include <stdarg.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <limits.h>
35
36 #include "URL.h"
37
38
39 /**
40 * Implementation of the URL interface. The scanner handle
41 * ISO Latin 1 or UTF-8 encoded url's transparently.
42 *
43 * @file
44 */
45
46
47 /* ----------------------------------------------------------- Definitions */
48
49
50 typedef struct param_t {
51 char *name;
52 char *value;
53 struct param_t *next;
54 } *param_t;
55
56 #define T URL_T
57 struct URL_S {
58 int ip6;
59 int port;
60 char *ref;
61 char *path;
62 char *host;
63 char *user;
64 char *qptr;
65 char *query;
66 char *portStr;
67 char *protocol;
68 char *password;
69 char *toString;
70 param_t params;
71 char **paramNames;
72 uchar_t *data;
73 uchar_t *buffer;
74 uchar_t *marker, *ctx, *limit, *token;
75 /* Keep the above align with zild URL_T */
76 };
77
78 /* Unsafe URL characters: [00-1F, 7F-FF] <>\"#%}{|\\^[] ` */
79 static const uchar_t urlunsafe[256] = {
80 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
81 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
82 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
84 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
85 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
86 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
87 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1,
88 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
89 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
90 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
91 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
92 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
93 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
94 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
95 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
96 };
97
98 #define UNKNOWN_PORT -1
99 #define YYCURSOR U->buffer
100 #define YYLIMIT U->limit
101 #define YYTOKEN U->token
102 #define SET_PROTOCOL(PORT) *(YYCURSOR-3)=0; U->protocol=U->token; U->port=PORT; goto authority
103
104
105 /* ------------------------------------------------------- Private methods */
106
107
_parseURL(T U)108 static bool _parseURL(T U) {
109 param_t param = NULL;
110 #line 127 "src/net/URL.re"
111
112 proto:
113 if (YYCURSOR >= YYLIMIT)
114 return false;
115 YYTOKEN = YYCURSOR;
116
117 #line 118 "<stdout>"
118 {
119 unsigned char yych;
120 static const unsigned char yybm[] = {
121 0, 0, 0, 0, 0, 0, 0, 0,
122 0, 0, 0, 0, 0, 0, 0, 0,
123 0, 0, 0, 0, 0, 0, 0, 0,
124 0, 0, 0, 0, 0, 0, 0, 0,
125 0, 0, 0, 0, 0, 0, 0, 0,
126 0, 0, 0, 0, 0, 0, 0, 0,
127 128, 128, 128, 128, 128, 128, 128, 128,
128 128, 128, 0, 0, 0, 0, 0, 0,
129 0, 128, 128, 128, 128, 128, 128, 128,
130 128, 128, 128, 128, 128, 128, 128, 128,
131 128, 128, 128, 128, 128, 128, 128, 128,
132 128, 128, 128, 0, 0, 0, 0, 0,
133 0, 128, 128, 128, 128, 128, 128, 128,
134 128, 128, 128, 128, 128, 128, 128, 128,
135 128, 128, 128, 128, 128, 128, 128, 128,
136 128, 128, 128, 0, 0, 0, 0, 0,
137 0, 0, 0, 0, 0, 0, 0, 0,
138 0, 0, 0, 0, 0, 0, 0, 0,
139 0, 0, 0, 0, 0, 0, 0, 0,
140 0, 0, 0, 0, 0, 0, 0, 0,
141 0, 0, 0, 0, 0, 0, 0, 0,
142 0, 0, 0, 0, 0, 0, 0, 0,
143 0, 0, 0, 0, 0, 0, 0, 0,
144 0, 0, 0, 0, 0, 0, 0, 0,
145 0, 0, 0, 0, 0, 0, 0, 0,
146 0, 0, 0, 0, 0, 0, 0, 0,
147 0, 0, 0, 0, 0, 0, 0, 0,
148 0, 0, 0, 0, 0, 0, 0, 0,
149 0, 0, 0, 0, 0, 0, 0, 0,
150 0, 0, 0, 0, 0, 0, 0, 0,
151 0, 0, 0, 0, 0, 0, 0, 0,
152 0, 0, 0, 0, 0, 0, 0, 0,
153 };
154 yych = *U->buffer;
155 if (yych <= '@') {
156 if (yych <= '\r') {
157 if (yych <= 0x08) goto yy2;
158 if (yych <= '\n') goto yy4;
159 if (yych >= '\r') goto yy4;
160 } else {
161 if (yych <= ' ') {
162 if (yych >= ' ') goto yy4;
163 } else {
164 if (yych <= '/') goto yy2;
165 if (yych <= '9') goto yy6;
166 }
167 }
168 } else {
169 if (yych <= 'm') {
170 if (yych <= 'Z') goto yy6;
171 if (yych <= '`') goto yy2;
172 if (yych <= 'l') goto yy6;
173 goto yy7;
174 } else {
175 if (yych <= 'o') {
176 if (yych <= 'n') goto yy6;
177 goto yy8;
178 } else {
179 if (yych <= 'p') goto yy9;
180 if (yych <= 'z') goto yy6;
181 }
182 }
183 }
184 yy2:
185 ++U->buffer;
186 yy3:
187 #line 154 "src/net/URL.re"
188 {
189 goto proto;
190 }
191 #line 192 "<stdout>"
192 yy4:
193 ++U->buffer;
194 #line 134 "src/net/URL.re"
195 {
196 goto proto;
197 }
198 #line 199 "<stdout>"
199 yy6:
200 yych = *(U->marker = ++U->buffer);
201 if (yych <= '@') {
202 if (yych <= '/') goto yy3;
203 if (yych <= ':') goto yy11;
204 goto yy3;
205 } else {
206 if (yych <= 'Z') goto yy11;
207 if (yych <= '`') goto yy3;
208 if (yych <= 'z') goto yy11;
209 goto yy3;
210 }
211 yy7:
212 yych = *(U->marker = ++U->buffer);
213 if (yych <= 'Z') {
214 if (yych <= '/') goto yy3;
215 if (yych <= ':') goto yy11;
216 if (yych <= '@') goto yy3;
217 goto yy11;
218 } else {
219 if (yych <= 'x') {
220 if (yych <= '`') goto yy3;
221 goto yy11;
222 } else {
223 if (yych <= 'y') goto yy14;
224 if (yych <= 'z') goto yy11;
225 goto yy3;
226 }
227 }
228 yy8:
229 yych = *(U->marker = ++U->buffer);
230 if (yych <= 'Z') {
231 if (yych <= '/') goto yy3;
232 if (yych <= ':') goto yy11;
233 if (yych <= '@') goto yy3;
234 goto yy11;
235 } else {
236 if (yych <= 'q') {
237 if (yych <= '`') goto yy3;
238 goto yy11;
239 } else {
240 if (yych <= 'r') goto yy15;
241 if (yych <= 'z') goto yy11;
242 goto yy3;
243 }
244 }
245 yy9:
246 yych = *(U->marker = ++U->buffer);
247 if (yych <= 'Z') {
248 if (yych <= '/') goto yy3;
249 if (yych <= ':') goto yy11;
250 if (yych <= '@') goto yy3;
251 goto yy11;
252 } else {
253 if (yych <= 'n') {
254 if (yych <= '`') goto yy3;
255 goto yy11;
256 } else {
257 if (yych <= 'o') goto yy16;
258 if (yych <= 'z') goto yy11;
259 goto yy3;
260 }
261 }
262 yy10:
263 yych = *++U->buffer;
264 yy11:
265 if (yybm[0+yych] & 128) {
266 goto yy10;
267 }
268 if (yych <= '/') goto yy12;
269 if (yych <= ':') goto yy13;
270 yy12:
271 U->buffer = U->marker;
272 goto yy3;
273 yy13:
274 yych = *++U->buffer;
275 if (yych == '/') goto yy17;
276 goto yy12;
277 yy14:
278 yych = *++U->buffer;
279 if (yych == 's') goto yy18;
280 goto yy11;
281 yy15:
282 yych = *++U->buffer;
283 if (yych == 'a') goto yy19;
284 goto yy11;
285 yy16:
286 yych = *++U->buffer;
287 if (yych == 's') goto yy20;
288 goto yy11;
289 yy17:
290 yych = *++U->buffer;
291 if (yych == '/') goto yy21;
292 goto yy12;
293 yy18:
294 yych = *++U->buffer;
295 if (yych == 'q') goto yy23;
296 goto yy11;
297 yy19:
298 yych = *++U->buffer;
299 if (yych == 'c') goto yy24;
300 goto yy11;
301 yy20:
302 yych = *++U->buffer;
303 if (yych == 't') goto yy25;
304 goto yy11;
305 yy21:
306 ++U->buffer;
307 #line 150 "src/net/URL.re"
308 {
309 SET_PROTOCOL(UNKNOWN_PORT);
310 }
311 #line 312 "<stdout>"
312 yy23:
313 yych = *++U->buffer;
314 if (yych == 'l') goto yy26;
315 goto yy11;
316 yy24:
317 yych = *++U->buffer;
318 if (yych == 'l') goto yy27;
319 goto yy11;
320 yy25:
321 yych = *++U->buffer;
322 if (yych == 'g') goto yy28;
323 goto yy11;
324 yy26:
325 yych = *++U->buffer;
326 if (yych == ':') goto yy29;
327 goto yy11;
328 yy27:
329 yych = *++U->buffer;
330 if (yych == 'e') goto yy30;
331 goto yy11;
332 yy28:
333 yych = *++U->buffer;
334 if (yych == 'r') goto yy31;
335 goto yy11;
336 yy29:
337 yych = *++U->buffer;
338 if (yych == '/') goto yy32;
339 goto yy12;
340 yy30:
341 yych = *++U->buffer;
342 if (yych == ':') goto yy33;
343 goto yy11;
344 yy31:
345 yych = *++U->buffer;
346 if (yych == 'e') goto yy34;
347 goto yy11;
348 yy32:
349 yych = *++U->buffer;
350 if (yych == '/') goto yy35;
351 goto yy12;
352 yy33:
353 yych = *++U->buffer;
354 if (yych == '/') goto yy37;
355 goto yy12;
356 yy34:
357 yych = *++U->buffer;
358 if (yych == 's') goto yy38;
359 goto yy11;
360 yy35:
361 ++U->buffer;
362 #line 138 "src/net/URL.re"
363 {
364 SET_PROTOCOL(MYSQL_DEFAULT_PORT);
365 }
366 #line 367 "<stdout>"
367 yy37:
368 yych = *++U->buffer;
369 if (yych == '/') goto yy39;
370 goto yy12;
371 yy38:
372 yych = *++U->buffer;
373 if (yych == 'q') goto yy41;
374 goto yy11;
375 yy39:
376 ++U->buffer;
377 #line 146 "src/net/URL.re"
378 {
379 SET_PROTOCOL(ORACLE_DEFAULT_PORT);
380 }
381 #line 382 "<stdout>"
382 yy41:
383 yych = *++U->buffer;
384 if (yych != 'l') goto yy11;
385 yych = *++U->buffer;
386 if (yych != ':') goto yy11;
387 yych = *++U->buffer;
388 if (yych != '/') goto yy12;
389 yych = *++U->buffer;
390 if (yych != '/') goto yy12;
391 ++U->buffer;
392 #line 142 "src/net/URL.re"
393 {
394 SET_PROTOCOL(POSTGRESQL_DEFAULT_PORT);
395 }
396 #line 397 "<stdout>"
397 }
398 #line 157 "src/net/URL.re"
399
400 authority:
401 if (YYCURSOR >= YYLIMIT)
402 return true;
403 YYTOKEN = YYCURSOR;
404
405 #line 406 "<stdout>"
406 {
407 unsigned char yych;
408 unsigned int yyaccept = 0;
409 static const unsigned char yybm[] = {
410 0, 0, 0, 0, 0, 0, 0, 0,
411 0, 0, 0, 0, 0, 0, 0, 0,
412 0, 0, 0, 0, 0, 0, 0, 0,
413 0, 0, 0, 0, 0, 0, 0, 0,
414 16, 56, 56, 16, 56, 184, 56, 56,
415 56, 56, 56, 56, 56, 60, 56, 56,
416 252, 252, 252, 252, 252, 252, 252, 252,
417 252, 252, 184, 16, 56, 56, 56, 16,
418 32, 188, 188, 188, 188, 188, 188, 188,
419 188, 188, 188, 188, 188, 188, 188, 188,
420 188, 188, 188, 188, 188, 188, 188, 188,
421 188, 188, 188, 32, 56, 32, 56, 56,
422 56, 188, 188, 188, 188, 188, 188, 188,
423 188, 188, 188, 188, 188, 188, 188, 188,
424 188, 188, 188, 188, 188, 188, 188, 188,
425 188, 188, 188, 56, 56, 56, 56, 56,
426 56, 56, 56, 56, 56, 56, 56, 56,
427 56, 56, 56, 56, 56, 56, 56, 56,
428 56, 56, 56, 56, 56, 56, 56, 56,
429 56, 56, 56, 56, 56, 56, 56, 56,
430 56, 56, 56, 56, 56, 56, 56, 56,
431 56, 56, 56, 56, 56, 56, 56, 56,
432 56, 56, 56, 56, 56, 56, 56, 56,
433 56, 56, 56, 56, 56, 56, 56, 56,
434 56, 56, 56, 56, 56, 56, 56, 56,
435 56, 56, 56, 56, 56, 56, 56, 56,
436 56, 56, 56, 56, 56, 56, 56, 56,
437 56, 56, 56, 56, 56, 56, 56, 56,
438 56, 56, 56, 56, 56, 56, 56, 56,
439 56, 56, 56, 56, 56, 56, 56, 56,
440 56, 56, 56, 56, 56, 56, 56, 56,
441 56, 56, 56, 56, 56, 56, 56, 56,
442 };
443 yych = *U->buffer;
444 if (yybm[0+yych] & 4) {
445 goto yy55;
446 }
447 if (yych <= '.') {
448 if (yych <= '\f') {
449 if (yych <= 0x08) goto yy49;
450 if (yych <= '\n') goto yy51;
451 } else {
452 if (yych <= '\r') goto yy51;
453 if (yych <= 0x1F) goto yy49;
454 if (yych <= ' ') goto yy53;
455 goto yy54;
456 }
457 } else {
458 if (yych <= '@') {
459 if (yych <= '/') goto yy58;
460 if (yych <= ':') goto yy61;
461 if (yych <= '?') goto yy54;
462 } else {
463 if (yych <= '[') goto yy62;
464 if (yych != ']') goto yy54;
465 }
466 }
467 yy49:
468 ++U->buffer;
469 yy50:
470 #line 209 "src/net/URL.re"
471 {
472 return true;
473 }
474 #line 475 "<stdout>"
475 yy51:
476 ++U->buffer;
477 yy52:
478 #line 164 "src/net/URL.re"
479 {
480 goto authority;
481 }
482 #line 483 "<stdout>"
483 yy53:
484 yyaccept = 0;
485 yych = *(U->marker = ++U->buffer);
486 if (yych <= '[') {
487 if (yych <= 0x1F) goto yy52;
488 if (yych <= 'Z') goto yy64;
489 goto yy52;
490 } else {
491 if (yych == ']') goto yy52;
492 goto yy64;
493 }
494 yy54:
495 yyaccept = 1;
496 yych = *(U->marker = ++U->buffer);
497 if (yych <= '[') {
498 if (yych <= 0x1F) goto yy50;
499 if (yych <= 'Z') goto yy64;
500 goto yy50;
501 } else {
502 if (yych == ']') goto yy50;
503 goto yy64;
504 }
505 yy55:
506 yyaccept = 2;
507 yych = *(U->marker = ++U->buffer);
508 if (yybm[0+yych] & 4) {
509 goto yy55;
510 }
511 if (yych <= '?') {
512 if (yych <= 0x1F) goto yy57;
513 if (yych <= ',') goto yy63;
514 if (yych <= '.') goto yy68;
515 goto yy63;
516 } else {
517 if (yych <= '[') {
518 if (yych <= '@') goto yy66;
519 } else {
520 if (yych != ']') goto yy63;
521 }
522 }
523 yy57:
524 #line 186 "src/net/URL.re"
525 {
526 U->host = Str_ndup(YYTOKEN, (int)(YYCURSOR - YYTOKEN));
527 goto authority;
528 }
529 #line 530 "<stdout>"
530 yy58:
531 yyaccept = 3;
532 yych = *(U->marker = ++U->buffer);
533 if (yybm[0+yych] & 8) {
534 goto yy58;
535 }
536 if (yych <= 0x1F) goto yy60;
537 if (yych <= ';') goto yy63;
538 if (yych <= '?') goto yy69;
539 if (yych <= '@') goto yy71;
540 goto yy72;
541 yy60:
542 #line 197 "src/net/URL.re"
543 {
544 *YYCURSOR = 0;
545 U->path = URL_unescape(YYTOKEN);
546 return true;
547 }
548 #line 549 "<stdout>"
549 yy61:
550 yyaccept = 1;
551 yych = *(U->marker = ++U->buffer);
552 if (yybm[0+yych] & 64) {
553 goto yy74;
554 }
555 if (yych <= '[') {
556 if (yych <= 0x1F) goto yy50;
557 if (yych <= 'Z') goto yy64;
558 goto yy50;
559 } else {
560 if (yych == ']') goto yy50;
561 goto yy64;
562 }
563 yy62:
564 yyaccept = 1;
565 yych = *(U->marker = ++U->buffer);
566 if (yybm[0+yych] & 128) {
567 goto yy77;
568 }
569 goto yy50;
570 yy63:
571 yych = *++U->buffer;
572 yy64:
573 if (yybm[0+yych] & 16) {
574 goto yy63;
575 }
576 if (yych <= 0x1F) goto yy65;
577 if (yych <= '@') goto yy66;
578 yy65:
579 U->buffer = U->marker;
580 if (yyaccept <= 2) {
581 if (yyaccept <= 1) {
582 if (yyaccept == 0) {
583 goto yy52;
584 } else {
585 goto yy50;
586 }
587 } else {
588 goto yy57;
589 }
590 } else {
591 if (yyaccept <= 4) {
592 if (yyaccept == 3) {
593 goto yy60;
594 } else {
595 goto yy70;
596 }
597 } else {
598 goto yy76;
599 }
600 }
601 yy66:
602 ++U->buffer;
603 yy67:
604 #line 168 "src/net/URL.re"
605 {
606 *(YYCURSOR - 1) = 0;
607 U->user = YYTOKEN;
608 char *p = strchr(U->user, ':');
609 if (p) {
610 *(p++) = 0;
611 U->password = URL_unescape(p);
612 }
613 URL_unescape(U->user);
614 goto authority;
615 }
616 #line 617 "<stdout>"
617 yy68:
618 yych = *++U->buffer;
619 if (yybm[0+yych] & 4) {
620 goto yy55;
621 }
622 if (yych <= '@') {
623 if (yych <= 0x1F) goto yy65;
624 if (yych <= '?') goto yy63;
625 goto yy66;
626 } else {
627 if (yych == '\\') goto yy63;
628 if (yych <= ']') goto yy65;
629 goto yy63;
630 }
631 yy69:
632 yyaccept = 4;
633 yych = *(U->marker = ++U->buffer);
634 if (yych <= '[') {
635 if (yych <= 0x1F) goto yy70;
636 if (yych <= 'Z') goto yy64;
637 } else {
638 if (yych != ']') goto yy64;
639 }
640 yy70:
641 #line 203 "src/net/URL.re"
642 {
643 *(YYCURSOR-1) = 0;
644 U->path = URL_unescape(YYTOKEN);
645 goto query;
646 }
647 #line 648 "<stdout>"
648 yy71:
649 yych = *++U->buffer;
650 if (yych <= '#') {
651 if (yych <= ' ') goto yy67;
652 if (yych <= '"') goto yy73;
653 goto yy67;
654 } else {
655 if (yych == ';') goto yy67;
656 goto yy73;
657 }
658 yy72:
659 yych = *++U->buffer;
660 yy73:
661 if (yybm[0+yych] & 32) {
662 goto yy72;
663 }
664 if (yych <= ';') goto yy60;
665 goto yy79;
666 yy74:
667 yyaccept = 5;
668 yych = *(U->marker = ++U->buffer);
669 if (yybm[0+yych] & 64) {
670 goto yy74;
671 }
672 if (yych <= 'Z') {
673 if (yych <= 0x1F) goto yy76;
674 if (yych == '@') goto yy66;
675 goto yy63;
676 } else {
677 if (yych == '\\') goto yy63;
678 if (yych >= '^') goto yy63;
679 }
680 yy76:
681 #line 191 "src/net/URL.re"
682 {
683 U->portStr = YYTOKEN + 1; // read past ':'
684 U->port = Str_parseInt(U->portStr);
685 goto authority;
686 }
687 #line 688 "<stdout>"
688 yy77:
689 yych = *++U->buffer;
690 if (yybm[0+yych] & 128) {
691 goto yy77;
692 }
693 if (yych == ']') goto yy80;
694 goto yy65;
695 yy79:
696 ++U->buffer;
697 goto yy70;
698 yy80:
699 ++U->buffer;
700 #line 180 "src/net/URL.re"
701 {
702 U->ip6 = true;
703 U->host = Str_ndup(YYTOKEN + 1, (int)(YYCURSOR - YYTOKEN - 2));
704 goto authority;
705 }
706 #line 707 "<stdout>"
707 }
708 #line 212 "src/net/URL.re"
709
710 query:
711 if (YYCURSOR >= YYLIMIT)
712 return true;
713 YYTOKEN = YYCURSOR;
714
715 #line 716 "<stdout>"
716 {
717 unsigned char yych;
718 static const unsigned char yybm[] = {
719 0, 0, 0, 0, 0, 0, 0, 0,
720 0, 0, 0, 0, 0, 0, 0, 0,
721 0, 0, 0, 0, 0, 0, 0, 0,
722 0, 0, 0, 0, 0, 0, 0, 0,
723 128, 128, 128, 0, 128, 128, 128, 128,
724 128, 128, 128, 128, 128, 128, 128, 128,
725 128, 128, 128, 128, 128, 128, 128, 128,
726 128, 128, 128, 128, 128, 128, 128, 128,
727 128, 128, 128, 128, 128, 128, 128, 128,
728 128, 128, 128, 128, 128, 128, 128, 128,
729 128, 128, 128, 128, 128, 128, 128, 128,
730 128, 128, 128, 128, 128, 128, 128, 128,
731 128, 128, 128, 128, 128, 128, 128, 128,
732 128, 128, 128, 128, 128, 128, 128, 128,
733 128, 128, 128, 128, 128, 128, 128, 128,
734 128, 128, 128, 128, 128, 128, 128, 128,
735 128, 128, 128, 128, 128, 128, 128, 128,
736 128, 128, 128, 128, 128, 128, 128, 128,
737 128, 128, 128, 128, 128, 128, 128, 128,
738 128, 128, 128, 128, 128, 128, 128, 128,
739 128, 128, 128, 128, 128, 128, 128, 128,
740 128, 128, 128, 128, 128, 128, 128, 128,
741 128, 128, 128, 128, 128, 128, 128, 128,
742 128, 128, 128, 128, 128, 128, 128, 128,
743 128, 128, 128, 128, 128, 128, 128, 128,
744 128, 128, 128, 128, 128, 128, 128, 128,
745 128, 128, 128, 128, 128, 128, 128, 128,
746 128, 128, 128, 128, 128, 128, 128, 128,
747 128, 128, 128, 128, 128, 128, 128, 128,
748 128, 128, 128, 128, 128, 128, 128, 128,
749 128, 128, 128, 128, 128, 128, 128, 128,
750 128, 128, 128, 128, 128, 128, 128, 128,
751 };
752 yych = *U->buffer;
753 if (yybm[0+yych] & 128) {
754 goto yy86;
755 }
756 ++U->buffer;
757 #line 226 "src/net/URL.re"
758 {
759 return true;
760 }
761 #line 762 "<stdout>"
762 yy86:
763 yych = *++U->buffer;
764 if (yybm[0+yych] & 128) {
765 goto yy86;
766 }
767 #line 219 "src/net/URL.re"
768 {
769 *YYCURSOR = 0;
770 U->query = Str_ndup(YYTOKEN, (int)(YYCURSOR - YYTOKEN));
771 YYCURSOR = YYTOKEN; // backtrack to start of query string after terminating it and
772 goto params;
773 }
774 #line 775 "<stdout>"
775 }
776 #line 229 "src/net/URL.re"
777
778 params:
779 if (YYCURSOR >= YYLIMIT)
780 return true;
781 YYTOKEN = YYCURSOR;
782
783 #line 784 "<stdout>"
784 {
785 unsigned char yych;
786 static const unsigned char yybm[] = {
787 0, 0, 0, 0, 0, 0, 0, 0,
788 0, 0, 0, 0, 0, 0, 0, 0,
789 0, 0, 0, 0, 0, 0, 0, 0,
790 0, 0, 0, 0, 0, 0, 0, 0,
791 64, 192, 192, 192, 192, 192, 128, 192,
792 192, 192, 192, 192, 192, 192, 192, 192,
793 192, 192, 192, 192, 192, 192, 192, 192,
794 192, 192, 192, 192, 192, 64, 192, 192,
795 192, 192, 192, 192, 192, 192, 192, 192,
796 192, 192, 192, 192, 192, 192, 192, 192,
797 192, 192, 192, 192, 192, 192, 192, 192,
798 192, 192, 192, 192, 192, 192, 192, 192,
799 192, 192, 192, 192, 192, 192, 192, 192,
800 192, 192, 192, 192, 192, 192, 192, 192,
801 192, 192, 192, 192, 192, 192, 192, 192,
802 192, 192, 192, 192, 192, 192, 192, 192,
803 192, 192, 192, 192, 192, 192, 192, 192,
804 192, 192, 192, 192, 192, 192, 192, 192,
805 192, 192, 192, 192, 192, 192, 192, 192,
806 192, 192, 192, 192, 192, 192, 192, 192,
807 192, 192, 192, 192, 192, 192, 192, 192,
808 192, 192, 192, 192, 192, 192, 192, 192,
809 192, 192, 192, 192, 192, 192, 192, 192,
810 192, 192, 192, 192, 192, 192, 192, 192,
811 192, 192, 192, 192, 192, 192, 192, 192,
812 192, 192, 192, 192, 192, 192, 192, 192,
813 192, 192, 192, 192, 192, 192, 192, 192,
814 192, 192, 192, 192, 192, 192, 192, 192,
815 192, 192, 192, 192, 192, 192, 192, 192,
816 192, 192, 192, 192, 192, 192, 192, 192,
817 192, 192, 192, 192, 192, 192, 192, 192,
818 192, 192, 192, 192, 192, 192, 192, 192,
819 };
820 yych = *U->buffer;
821 if (yych <= ' ') goto yy91;
822 if (yych == '=') goto yy94;
823 goto yy93;
824 yy91:
825 ++U->buffer;
826 yy92:
827 #line 254 "src/net/URL.re"
828 {
829 return true;
830 }
831 #line 832 "<stdout>"
832 yy93:
833 yych = *(U->marker = ++U->buffer);
834 if (yych <= ' ') goto yy92;
835 goto yy98;
836 yy94:
837 yych = *++U->buffer;
838 if (yybm[0+yych] & 64) {
839 goto yy94;
840 }
841 if (yych >= ' ') goto yy102;
842 yy96:
843 #line 244 "src/net/URL.re"
844 {
845 *YYTOKEN++ = 0;
846 if (*(YYCURSOR - 1) == '&')
847 *(YYCURSOR - 1) = 0;
848 if (! param) // format error
849 return true;
850 param->value = URL_unescape(YYTOKEN);
851 goto params;
852 }
853 #line 854 "<stdout>"
854 yy97:
855 yych = *++U->buffer;
856 yy98:
857 if (yybm[0+yych] & 128) {
858 goto yy97;
859 }
860 if (yych >= '!') goto yy100;
861 U->buffer = U->marker;
862 goto yy92;
863 yy100:
864 ++U->buffer;
865 U->buffer -= 1;
866 #line 236 "src/net/URL.re"
867 {
868 NEW(param);
869 param->name = YYTOKEN;
870 param->next = U->params;
871 U->params = param;
872 goto params;
873 }
874 #line 875 "<stdout>"
875 yy102:
876 ++U->buffer;
877 goto yy96;
878 }
879 #line 257 "src/net/URL.re"
880
881 return false;
882 }
883
884
_x2b(uchar_t * x)885 static inline int _x2b(uchar_t *x) {
886 register int b;
887 b = ((x[0] >= 'A') ? ((x[0] & 0xdf) - 'A')+10 : (x[0] - '0'));
888 b *= 16;
889 b += (x[1] >= 'A' ? ((x[1] & 0xdf) - 'A')+10 : (x[1] - '0'));
890 return b;
891 }
892
893
_b2x(uchar_t b,uchar_t * x)894 static inline uchar_t *_b2x(uchar_t b, uchar_t *x) {
895 static const char _b2x_table[] = "0123456789ABCDEF";
896 *x++ = '%';
897 *x++ = _b2x_table[b >> 4];
898 *x = _b2x_table[b & 0xf];
899 return x;
900 }
901
902
_freeParams(param_t p)903 static void _freeParams(param_t p) {
904 for (param_t q = NULL; p; p = q) {
905 q = p->next;
906 FREE(p);
907 }
908 }
909
910
_ctor(uchar_t * data)911 static T _ctor(uchar_t *data) {
912 T U;
913 NEW(U);
914 U->data = data;
915 YYCURSOR = U->data;
916 U->port = UNKNOWN_PORT;
917 YYLIMIT = U->data + strlen(U->data);
918 if (! _parseURL(U))
919 URL_free(&U);
920 return U;
921 }
922
923
924 /* -------------------------------------------------------- Public methods */
925
926
URL_new(const char * url)927 T URL_new(const char *url) {
928 if (STR_UNDEF(url))
929 return NULL;
930 Exception_init();
931 return _ctor((uchar_t*)Str_dup(url));
932 }
933
934
URL_create(const char * url,...)935 T URL_create(const char *url, ...) {
936 if (STR_UNDEF(url))
937 return NULL;
938 Exception_init();
939 va_list ap;
940 va_start(ap, url);
941 T U = _ctor((uchar_t*)Str_vcat(url, ap));
942 va_end(ap);
943 return U;
944 }
945
URL_free(T * U)946 void URL_free(T *U) {
947 assert(U && *U);
948 _freeParams((*U)->params);
949 FREE((*U)->paramNames);
950 FREE((*U)->toString);
951 FREE((*U)->query);
952 FREE((*U)->data);
953 FREE((*U)->host);
954 FREE(*U);
955 }
956
957
958 /* ------------------------------------------------------------ Properties */
959
960
URL_getProtocol(T U)961 const char *URL_getProtocol(T U) {
962 assert(U);
963 return U->protocol;
964 }
965
966
URL_getUser(T U)967 const char *URL_getUser(T U) {
968 assert(U);
969 return U->user;
970 }
971
972
URL_getPassword(T U)973 const char *URL_getPassword(T U) {
974 assert(U);
975 return U->password;
976 }
977
978
URL_getHost(T U)979 const char *URL_getHost(T U) {
980 assert(U);
981 return U->host;
982 }
983
984
URL_getPort(T U)985 int URL_getPort(T U) {
986 assert(U);
987 return U->port;
988 }
989
990
URL_getPath(T U)991 const char *URL_getPath(T U) {
992 assert(U);
993 return U->path;
994 }
995
996
URL_getQueryString(T U)997 const char *URL_getQueryString(T U) {
998 assert(U);
999 return U->query;
1000 }
1001
1002
URL_getParameterNames(T U)1003 const char **URL_getParameterNames(T U) {
1004 assert(U);
1005 if (U->params && (U->paramNames == NULL)) {
1006 param_t p;
1007 int i = 0, len = 0;
1008 for (p = U->params; p; p = p->next) len++;
1009 U->paramNames = ALLOC((len + 1) * sizeof *(U->paramNames));
1010 for (p = U->params; p; p = p->next)
1011 U->paramNames[i++] = p->name;
1012 U->paramNames[i] = NULL;
1013 }
1014 return (const char **)U->paramNames;
1015 }
1016
1017
URL_getParameter(T U,const char * name)1018 const char *URL_getParameter(T U, const char *name) {
1019 assert(U);
1020 assert(name);
1021 for (param_t p = U->params; p; p = p->next) {
1022 if (Str_isByteEqual(p->name, name))
1023 return p->value;
1024 }
1025 return NULL;
1026 }
1027
1028
1029 /* ---------------------------------------------------------------- Public */
1030
1031
URL_toString(T U)1032 const char *URL_toString(T U) {
1033 assert(U);
1034 if (! U->toString) {
1035 uchar_t port[11] = {};
1036 if (U->portStr) // port seen in URL
1037 snprintf(port, 10, ":%d", U->port);
1038 U->toString = Str_cat("%s://%s%s%s%s%s%s%s%s%s%s%s",
1039 U->protocol,
1040 U->user ? U->user : "",
1041 U->password ? ":" : "",
1042 U->password ? U->password : "",
1043 U->user ? "@" : "",
1044 U->ip6 ? "[" : "",
1045 U->host ? U->host : "",
1046 U->ip6 ? "]" : "",
1047 port,
1048 U->path ? U->path : "",
1049 U->query ? "?" : "",
1050 U->query ? U->query : "");
1051 }
1052 return U->toString;
1053 }
1054
1055
1056 /* --------------------------------------------------------- Class methods */
1057
1058
URL_unescape(char * url)1059 char *URL_unescape(char *url) {
1060 if (STR_DEF(url)) {
1061 register int x, y;
1062 for (x = 0, y = 0; url[y]; x++, y++) {
1063 if ((url[x] = url[y]) == '+')
1064 url[x] = ' ';
1065 else if (url[x] == '%') {
1066 if (! (url[y + 1] && url[y + 2]))
1067 break;
1068 url[x] = _x2b(url + y + 1);
1069 y += 2;
1070 }
1071 }
1072 url[x] = 0;
1073 }
1074 return url;
1075 }
1076
1077
URL_escape(const char * url)1078 char *URL_escape(const char *url) {
1079 char *escaped = 0;
1080 if (url) {
1081 char *p;
1082 int i, n;
1083 for (n = i = 0; url[i]; i++)
1084 if (urlunsafe[(unsigned char)(url[i])])
1085 n += 2;
1086 p = escaped = ALLOC(i + n + 1);
1087 for (; *url; url++, p++) {
1088 if (urlunsafe[(unsigned char)(*p = *url)])
1089 p = _b2x(*url, p);
1090 }
1091 *p = 0;
1092 }
1093 return escaped;
1094 }
1095
1096