Blob


1 /*
2 * Copyright (c) 2022 Omar Polo <op@omarpolo.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
17 #include <err.h>
18 #include <errno.h>
19 #include <stdio.h>
20 #include <string.h>
22 #include "iri.h"
24 static int
25 resolve(const char *base, const char *ref, const char *expected)
26 {
27 static struct iri i;
28 char buf[512];
30 if (iri_parse(base, ref, &i) == -1) {
31 fprintf(stderr, "FAIL resolve(\"%s\", \"%s\") %s\n", base, ref,
32 strerror(errno));
33 return (1);
34 }
36 if (iri_unparse(&i, buf, sizeof(buf)) == -1) {
37 fprintf(stderr, "FAIL resolve(\"%s\", \"%s\") %s\n", base, ref,
38 strerror(errno));
39 return (1);
40 }
42 if (strcmp(buf, expected) != 0) {
43 fprintf(stderr, "FAIL resolve(\"%s\", \"%s\")\n", base, ref);
44 fprintf(stderr, "got:\t%s\n", buf);
45 fprintf(stderr, "want:\t%s\n", expected);
46 return (1);
47 }
49 fprintf(stderr, "OK resolve(\"%s\", \"%s\") -> %s\n", base, ref,
50 expected);
51 return (0);
52 }
54 int
55 main(void)
56 {
57 const char *base = "http://a/b/c/d;p?q";
58 int ret = 0;
60 ret |= resolve(base, "g:h", "g:h");
61 ret |= resolve(base, "g", "http://a/b/c/g");
62 ret |= resolve(base, "./g", "http://a/b/c/g");
63 ret |= resolve(base, "g/", "http://a/b/c/g/");
64 ret |= resolve(base, "/g", "http://a/g");
66 /*
67 * the RFC says "http://g" but we always normalize an
68 * empty path to "/" if there is an authority.
69 */
70 ret |= resolve(base, "//g", "http://g/");
72 ret |= resolve(base, "?y", "http://a/b/c/d;p?y");
73 ret |= resolve(base, "g?y", "http://a/b/c/g?y");
74 ret |= resolve(base, "#s", "http://a/b/c/d;p?q#s");
75 ret |= resolve(base, "g#s", "http://a/b/c/g#s");
76 ret |= resolve(base, "g?y#s", "http://a/b/c/g?y#s");
77 ret |= resolve(base, ";x", "http://a/b/c/;x");
78 ret |= resolve(base, "g;x", "http://a/b/c/g;x");
79 ret |= resolve(base, "g;x?y#s", "http://a/b/c/g;x?y#s");
80 ret |= resolve(base, "", "http://a/b/c/d;p?q");
81 ret |= resolve(base, ".", "http://a/b/c/");
82 ret |= resolve(base, "./", "http://a/b/c/");
83 ret |= resolve(base, "..", "http://a/b/");
84 ret |= resolve(base, "../", "http://a/b/");
85 ret |= resolve(base, "../g", "http://a/b/g");
86 ret |= resolve(base, "../..", "http://a/");
87 ret |= resolve(base, "../../", "http://a/");
88 ret |= resolve(base, "../../g", "http://a/g");
90 ret |= resolve(base, "../../../g", "http://a/g");
91 ret |= resolve(base, "../../../../g", "http://a/g");
92 ret |= resolve(base, "/./g", "http://a/g");
93 ret |= resolve(base, "/../g", "http://a/g");
94 ret |= resolve(base, "g.", "http://a/b/c/g.");
95 ret |= resolve(base, ".g", "http://a/b/c/.g");
96 ret |= resolve(base, "g..", "http://a/b/c/g..");
97 ret |= resolve(base, "..g", "http://a/b/c/..g");
99 ret |= resolve(base, "./../g", "http://a/b/g");
100 ret |= resolve(base, "./g/.", "http://a/b/c/g/");
101 ret |= resolve(base, "g/./h", "http://a/b/c/g/h");
102 ret |= resolve(base, "g/../h", "http://a/b/c/h");
103 ret |= resolve(base, "g;x=1/./y", "http://a/b/c/g;x=1/y");
104 ret |= resolve(base, "g;x=1/../y", "http://a/b/c/y");
106 ret |= resolve(base, "g?y/./x", "http://a/b/c/g?y/./x");
107 ret |= resolve(base, "g?y/../x", "http://a/b/c/g?y/../x");
108 ret |= resolve(base, "g#s/./x", "http://a/b/c/g#s/./x");
109 ret |= resolve(base, "g#s/../x", "http://a/b/c/g#s/../x");
111 ret |= resolve(base, "http:g", "http:g");
113 return (ret);