Blame


1 5546fdd5 2022-12-23 op /*
2 5546fdd5 2022-12-23 op * Copyright (c) 2022 Omar Polo <op@omarpolo.com>
3 5546fdd5 2022-12-23 op *
4 5546fdd5 2022-12-23 op * Permission to use, copy, modify, and distribute this software for any
5 5546fdd5 2022-12-23 op * purpose with or without fee is hereby granted, provided that the above
6 5546fdd5 2022-12-23 op * copyright notice and this permission notice appear in all copies.
7 5546fdd5 2022-12-23 op *
8 5546fdd5 2022-12-23 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 5546fdd5 2022-12-23 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 5546fdd5 2022-12-23 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 5546fdd5 2022-12-23 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 5546fdd5 2022-12-23 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 5546fdd5 2022-12-23 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 5546fdd5 2022-12-23 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 5546fdd5 2022-12-23 op */
16 5546fdd5 2022-12-23 op
17 5546fdd5 2022-12-23 op #include <ctype.h>
18 5546fdd5 2022-12-23 op #include <stdint.h>
19 5546fdd5 2022-12-23 op #include <stdlib.h>
20 5546fdd5 2022-12-23 op #include <string.h>
21 5546fdd5 2022-12-23 op
22 5546fdd5 2022-12-23 op #include "iri.h"
23 5546fdd5 2022-12-23 op
24 5546fdd5 2022-12-23 op /* TODO: URI -> IRI. accept IRI but emit always URI */
25 5546fdd5 2022-12-23 op
26 5546fdd5 2022-12-23 op static inline int
27 5546fdd5 2022-12-23 op cpstr(const char *start, const char *till, char *buf, size_t len)
28 5546fdd5 2022-12-23 op {
29 5546fdd5 2022-12-23 op size_t slen = till - start;
30 5546fdd5 2022-12-23 op
31 5546fdd5 2022-12-23 op if (slen + 1 >= len)
32 5546fdd5 2022-12-23 op return (-1);
33 5546fdd5 2022-12-23 op memcpy(buf, start, slen);
34 5546fdd5 2022-12-23 op buf[slen] = '\0';
35 5546fdd5 2022-12-23 op return (0);
36 5546fdd5 2022-12-23 op }
37 5546fdd5 2022-12-23 op
38 5546fdd5 2022-12-23 op static inline int
39 5546fdd5 2022-12-23 op unreserved(int c)
40 5546fdd5 2022-12-23 op {
41 5546fdd5 2022-12-23 op return (isalnum((unsigned char)c) ||
42 5546fdd5 2022-12-23 op c == '-' ||
43 5546fdd5 2022-12-23 op c == '.' ||
44 5546fdd5 2022-12-23 op c == '_' ||
45 5546fdd5 2022-12-23 op c == '~');
46 5546fdd5 2022-12-23 op }
47 5546fdd5 2022-12-23 op
48 5546fdd5 2022-12-23 op static inline int
49 5546fdd5 2022-12-23 op pctenc(const char *s)
50 5546fdd5 2022-12-23 op {
51 5546fdd5 2022-12-23 op const char *t = s;
52 5546fdd5 2022-12-23 op
53 5546fdd5 2022-12-23 op return (t[0] == '%' &&
54 5546fdd5 2022-12-23 op isxdigit((unsigned char)t[1]) &&
55 5546fdd5 2022-12-23 op isxdigit((unsigned char)t[2]));
56 5546fdd5 2022-12-23 op }
57 5546fdd5 2022-12-23 op
58 5546fdd5 2022-12-23 op static inline int
59 5546fdd5 2022-12-23 op sub_delims(int c)
60 5546fdd5 2022-12-23 op {
61 5546fdd5 2022-12-23 op return (c == '!' || c == '$' || c == '&' || c == '\'' ||
62 5546fdd5 2022-12-23 op c == '(' || c == ')' || c == '*' || c == '+' || c == ',' ||
63 5546fdd5 2022-12-23 op c == ';' || c == '=');
64 5546fdd5 2022-12-23 op }
65 5546fdd5 2022-12-23 op
66 5546fdd5 2022-12-23 op static inline const char *
67 5546fdd5 2022-12-23 op advance_pchar(const char *s)
68 5546fdd5 2022-12-23 op {
69 5546fdd5 2022-12-23 op if (unreserved(*s) || sub_delims(*s) || *s == ':' || *s == '@')
70 5546fdd5 2022-12-23 op return (s + 1);
71 5546fdd5 2022-12-23 op if (pctenc(s))
72 5546fdd5 2022-12-23 op return (s + 3);
73 5546fdd5 2022-12-23 op return (NULL);
74 5546fdd5 2022-12-23 op }
75 5546fdd5 2022-12-23 op
76 5546fdd5 2022-12-23 op static inline const char *
77 5546fdd5 2022-12-23 op advance_segment(const char *s)
78 5546fdd5 2022-12-23 op {
79 5546fdd5 2022-12-23 op const char *t = s;
80 5546fdd5 2022-12-23 op
81 5546fdd5 2022-12-23 op while ((t = advance_pchar(s)) != NULL)
82 5546fdd5 2022-12-23 op s = t;
83 5546fdd5 2022-12-23 op return (s);
84 5546fdd5 2022-12-23 op }
85 5546fdd5 2022-12-23 op
86 5546fdd5 2022-12-23 op static inline const char *
87 5546fdd5 2022-12-23 op advance_segment_nz(const char *s)
88 5546fdd5 2022-12-23 op {
89 5546fdd5 2022-12-23 op const char *t;
90 5546fdd5 2022-12-23 op
91 5546fdd5 2022-12-23 op if ((t = advance_pchar(s)) == NULL)
92 5546fdd5 2022-12-23 op return (NULL);
93 5546fdd5 2022-12-23 op return (advance_segment(t));
94 5546fdd5 2022-12-23 op }
95 5546fdd5 2022-12-23 op
96 5546fdd5 2022-12-23 op static inline const char *
97 5546fdd5 2022-12-23 op advance_segment_nz_nc(const char *s)
98 5546fdd5 2022-12-23 op {
99 5546fdd5 2022-12-23 op const char *t = s;
100 5546fdd5 2022-12-23 op
101 5546fdd5 2022-12-23 op for (;;) {
102 5546fdd5 2022-12-23 op if (unreserved(*t) || sub_delims(*t) || *t == '@')
103 5546fdd5 2022-12-23 op t++;
104 5546fdd5 2022-12-23 op else if (pctenc(t))
105 5546fdd5 2022-12-23 op t += 3;
106 5546fdd5 2022-12-23 op else
107 5546fdd5 2022-12-23 op break;
108 5546fdd5 2022-12-23 op }
109 5546fdd5 2022-12-23 op
110 5546fdd5 2022-12-23 op return (t != s ? t : NULL);
111 5546fdd5 2022-12-23 op }
112 5546fdd5 2022-12-23 op
113 5546fdd5 2022-12-23 op static const char *
114 5546fdd5 2022-12-23 op parse_scheme(const char *s, struct iri *iri)
115 5546fdd5 2022-12-23 op {
116 5546fdd5 2022-12-23 op const char *t = s;
117 5546fdd5 2022-12-23 op
118 5546fdd5 2022-12-23 op if (!isalpha((unsigned char)*t))
119 5546fdd5 2022-12-23 op return (NULL);
120 5546fdd5 2022-12-23 op
121 5546fdd5 2022-12-23 op while (isalnum((unsigned char)*t) ||
122 5546fdd5 2022-12-23 op *t == '+' ||
123 5546fdd5 2022-12-23 op *t == '-' ||
124 5546fdd5 2022-12-23 op *t == '.')
125 5546fdd5 2022-12-23 op t++;
126 5546fdd5 2022-12-23 op
127 5546fdd5 2022-12-23 op if (cpstr(s, t, iri->iri_scheme, sizeof(iri->iri_scheme)) == -1)
128 5546fdd5 2022-12-23 op return (NULL);
129 5546fdd5 2022-12-23 op
130 5546fdd5 2022-12-23 op iri->iri_flags |= IH_SCHEME;
131 5546fdd5 2022-12-23 op return (t);
132 5546fdd5 2022-12-23 op }
133 5546fdd5 2022-12-23 op
134 5546fdd5 2022-12-23 op /* userinfo is always optional */
135 5546fdd5 2022-12-23 op static const char *
136 5546fdd5 2022-12-23 op parse_uinfo(const char *s, struct iri *iri)
137 5546fdd5 2022-12-23 op {
138 5546fdd5 2022-12-23 op const char *t = s;
139 5546fdd5 2022-12-23 op
140 5546fdd5 2022-12-23 op for (;;) {
141 5546fdd5 2022-12-23 op if (unreserved(*t) || sub_delims(*t) || *t == ':')
142 5546fdd5 2022-12-23 op t++;
143 5546fdd5 2022-12-23 op else if (pctenc(t))
144 5546fdd5 2022-12-23 op t += 3;
145 5546fdd5 2022-12-23 op else
146 5546fdd5 2022-12-23 op break;
147 5546fdd5 2022-12-23 op }
148 5546fdd5 2022-12-23 op
149 5546fdd5 2022-12-23 op if (*t != '@')
150 5546fdd5 2022-12-23 op return (s);
151 5546fdd5 2022-12-23 op
152 5546fdd5 2022-12-23 op if (cpstr(s, t, iri->iri_uinfo, sizeof(iri->iri_uinfo)) == -1)
153 5546fdd5 2022-12-23 op return (NULL);
154 5546fdd5 2022-12-23 op iri->iri_flags |= IH_UINFO;
155 5546fdd5 2022-12-23 op return (t + 1);
156 5546fdd5 2022-12-23 op }
157 5546fdd5 2022-12-23 op
158 5546fdd5 2022-12-23 op static const char *
159 5546fdd5 2022-12-23 op parse_host(const char *s, struct iri *iri)
160 5546fdd5 2022-12-23 op {
161 5546fdd5 2022-12-23 op const char *t = s;
162 5546fdd5 2022-12-23 op
163 5546fdd5 2022-12-23 op /*
164 5546fdd5 2022-12-23 op * cheating a bit by relaxing and merging the rule for
165 5546fdd5 2022-12-23 op * IPv6address and IPvFuture and by merging IPv4address and
166 5546fdd5 2022-12-23 op * reg-name.
167 5546fdd5 2022-12-23 op */
168 5546fdd5 2022-12-23 op
169 5546fdd5 2022-12-23 op if (*t == '[') {
170 5546fdd5 2022-12-23 op while (*t && *t != ']')
171 5546fdd5 2022-12-23 op ++t;
172 5546fdd5 2022-12-23 op if (*t == '\0')
173 5546fdd5 2022-12-23 op return (NULL);
174 5546fdd5 2022-12-23 op t++;
175 5546fdd5 2022-12-23 op if (cpstr(s, t, iri->iri_host, sizeof(iri->iri_host)) == -1)
176 5546fdd5 2022-12-23 op return (NULL);
177 5546fdd5 2022-12-23 op iri->iri_flags |= IH_HOST;
178 5546fdd5 2022-12-23 op return (t);
179 5546fdd5 2022-12-23 op }
180 5546fdd5 2022-12-23 op
181 5546fdd5 2022-12-23 op for (;;) {
182 5546fdd5 2022-12-23 op if (unreserved(*t) || sub_delims(*t))
183 5546fdd5 2022-12-23 op t++;
184 5546fdd5 2022-12-23 op else if (pctenc(t))
185 5546fdd5 2022-12-23 op t += 3;
186 5546fdd5 2022-12-23 op else
187 5546fdd5 2022-12-23 op break;
188 5546fdd5 2022-12-23 op }
189 5546fdd5 2022-12-23 op
190 5546fdd5 2022-12-23 op if (cpstr(s, t, iri->iri_host, sizeof(iri->iri_host)) == -1)
191 5546fdd5 2022-12-23 op return (NULL);
192 5546fdd5 2022-12-23 op iri->iri_flags |= IH_HOST;
193 5546fdd5 2022-12-23 op return (t);
194 5546fdd5 2022-12-23 op }
195 5546fdd5 2022-12-23 op
196 5546fdd5 2022-12-23 op static const char *
197 5546fdd5 2022-12-23 op parse_port(const char *s, struct iri *iri)
198 5546fdd5 2022-12-23 op {
199 5546fdd5 2022-12-23 op const char *t = s;
200 5546fdd5 2022-12-23 op const char *errstr;
201 5546fdd5 2022-12-23 op
202 5546fdd5 2022-12-23 op while (isdigit((unsigned char)*t))
203 5546fdd5 2022-12-23 op t++;
204 5546fdd5 2022-12-23 op if (cpstr(s, t, iri->iri_portstr, sizeof(iri->iri_portstr)) == -1)
205 5546fdd5 2022-12-23 op return (NULL);
206 5546fdd5 2022-12-23 op iri->iri_port = strtonum(iri->iri_portstr, 1, UINT16_MAX, &errstr);
207 5546fdd5 2022-12-23 op if (errstr)
208 5546fdd5 2022-12-23 op return (NULL);
209 5546fdd5 2022-12-23 op iri->iri_flags |= IH_PORT;
210 5546fdd5 2022-12-23 op return (t);
211 5546fdd5 2022-12-23 op }
212 5546fdd5 2022-12-23 op
213 5546fdd5 2022-12-23 op static const char *
214 5546fdd5 2022-12-23 op parse_authority(const char *s, struct iri *iri)
215 5546fdd5 2022-12-23 op {
216 5546fdd5 2022-12-23 op const char *t;
217 5546fdd5 2022-12-23 op
218 5546fdd5 2022-12-23 op if ((t = parse_uinfo(s, iri)) == NULL)
219 5546fdd5 2022-12-23 op return (NULL);
220 5546fdd5 2022-12-23 op
221 5546fdd5 2022-12-23 op if ((t = parse_host(t, iri)) == NULL)
222 5546fdd5 2022-12-23 op return (NULL);
223 5546fdd5 2022-12-23 op
224 5546fdd5 2022-12-23 op if (*t == ':')
225 5546fdd5 2022-12-23 op return (parse_port(t, iri));
226 5546fdd5 2022-12-23 op
227 5546fdd5 2022-12-23 op return (t);
228 5546fdd5 2022-12-23 op }
229 5546fdd5 2022-12-23 op
230 5546fdd5 2022-12-23 op static const char *
231 5546fdd5 2022-12-23 op parse_path_abempty(const char *s, struct iri *iri)
232 5546fdd5 2022-12-23 op {
233 5546fdd5 2022-12-23 op const char *t = s;
234 5546fdd5 2022-12-23 op
235 5546fdd5 2022-12-23 op while (*t == '/')
236 5546fdd5 2022-12-23 op t = advance_segment(t + 1);
237 5546fdd5 2022-12-23 op
238 5546fdd5 2022-12-23 op if (cpstr(s, t, iri->iri_path, sizeof(iri->iri_path)) == -1)
239 5546fdd5 2022-12-23 op return (NULL);
240 5546fdd5 2022-12-23 op iri->iri_flags |= IH_PATH;
241 5546fdd5 2022-12-23 op return (t);
242 5546fdd5 2022-12-23 op }
243 5546fdd5 2022-12-23 op
244 5546fdd5 2022-12-23 op static const char *
245 5546fdd5 2022-12-23 op parse_path_absolute(const char *s, struct iri *iri)
246 5546fdd5 2022-12-23 op {
247 5546fdd5 2022-12-23 op const char *t;
248 5546fdd5 2022-12-23 op
249 5546fdd5 2022-12-23 op if (*s != '/')
250 5546fdd5 2022-12-23 op return (NULL);
251 5546fdd5 2022-12-23 op
252 5546fdd5 2022-12-23 op if ((t = advance_segment_nz(s + 1)) == NULL)
253 5546fdd5 2022-12-23 op return (s + 1);
254 5546fdd5 2022-12-23 op
255 5546fdd5 2022-12-23 op while (*t == '/')
256 5546fdd5 2022-12-23 op t = advance_segment(t + 1);
257 5546fdd5 2022-12-23 op
258 5546fdd5 2022-12-23 op if (cpstr(s, t, iri->iri_path, sizeof(iri->iri_path)) == -1)
259 5546fdd5 2022-12-23 op return (NULL);
260 5546fdd5 2022-12-23 op iri->iri_flags |= IH_PATH;
261 5546fdd5 2022-12-23 op return (t);
262 5546fdd5 2022-12-23 op }
263 5546fdd5 2022-12-23 op
264 5546fdd5 2022-12-23 op static const char *
265 5546fdd5 2022-12-23 op parse_path_rootless(const char *s, struct iri *iri)
266 5546fdd5 2022-12-23 op {
267 5546fdd5 2022-12-23 op const char *t;
268 5546fdd5 2022-12-23 op
269 5546fdd5 2022-12-23 op if ((t = advance_segment_nz(s)) == NULL)
270 5546fdd5 2022-12-23 op return (NULL);
271 5546fdd5 2022-12-23 op
272 5546fdd5 2022-12-23 op while (*t == '/')
273 5546fdd5 2022-12-23 op t = advance_segment(t + 1);
274 5546fdd5 2022-12-23 op
275 5546fdd5 2022-12-23 op if (cpstr(s, t, iri->iri_path, sizeof(iri->iri_path)) == -1)
276 5546fdd5 2022-12-23 op return (NULL);
277 5546fdd5 2022-12-23 op iri->iri_flags |= IH_PATH;
278 5546fdd5 2022-12-23 op return (t);
279 5546fdd5 2022-12-23 op }
280 5546fdd5 2022-12-23 op
281 5546fdd5 2022-12-23 op static const char *
282 5546fdd5 2022-12-23 op parse_path_noscheme(const char *s, struct iri *iri)
283 5546fdd5 2022-12-23 op {
284 5546fdd5 2022-12-23 op const char *t;
285 5546fdd5 2022-12-23 op
286 5546fdd5 2022-12-23 op if ((t = advance_segment_nz_nc(s)) == NULL)
287 5546fdd5 2022-12-23 op return (NULL);
288 5546fdd5 2022-12-23 op
289 5546fdd5 2022-12-23 op while (*t == '/')
290 5546fdd5 2022-12-23 op t = advance_segment(t + 1);
291 5546fdd5 2022-12-23 op
292 5546fdd5 2022-12-23 op if (cpstr(s, t, iri->iri_path, sizeof(iri->iri_path)) == -1)
293 5546fdd5 2022-12-23 op return (NULL);
294 5546fdd5 2022-12-23 op iri->iri_flags |= IH_PATH;
295 5546fdd5 2022-12-23 op return (t);
296 5546fdd5 2022-12-23 op }
297 5546fdd5 2022-12-23 op
298 5546fdd5 2022-12-23 op static const char *
299 5546fdd5 2022-12-23 op parse_path_empty(const char *s, struct iri *iri)
300 5546fdd5 2022-12-23 op {
301 5546fdd5 2022-12-23 op iri->iri_path[0] = '\0';
302 5546fdd5 2022-12-23 op iri->iri_flags |= IH_PATH;
303 5546fdd5 2022-12-23 op return (s);
304 5546fdd5 2022-12-23 op }
305 5546fdd5 2022-12-23 op
306 5546fdd5 2022-12-23 op static const char *
307 5546fdd5 2022-12-23 op parse_hier(const char *s, struct iri *iri)
308 5546fdd5 2022-12-23 op {
309 5546fdd5 2022-12-23 op const char *t;
310 5546fdd5 2022-12-23 op
311 5546fdd5 2022-12-23 op if (!strncmp(s, "//", 2)) {
312 5546fdd5 2022-12-23 op if ((t = parse_authority(s + 2, iri)) == NULL)
313 5546fdd5 2022-12-23 op return (NULL);
314 5546fdd5 2022-12-23 op return (parse_path_abempty(t, iri));
315 5546fdd5 2022-12-23 op }
316 5546fdd5 2022-12-23 op
317 5546fdd5 2022-12-23 op if ((t = parse_path_absolute(s, iri)) != NULL)
318 5546fdd5 2022-12-23 op return (t);
319 5546fdd5 2022-12-23 op
320 5546fdd5 2022-12-23 op if ((t = parse_path_rootless(s, iri)) != NULL)
321 5546fdd5 2022-12-23 op return (t);
322 5546fdd5 2022-12-23 op
323 5546fdd5 2022-12-23 op return (parse_path_empty(s, iri));
324 5546fdd5 2022-12-23 op }
325 5546fdd5 2022-12-23 op
326 5546fdd5 2022-12-23 op static const char *
327 5546fdd5 2022-12-23 op parse_relative(const char *s, struct iri *iri)
328 5546fdd5 2022-12-23 op {
329 5546fdd5 2022-12-23 op const char *t = s;
330 5546fdd5 2022-12-23 op
331 5546fdd5 2022-12-23 op if (!strncmp(s, "//", 2)) {
332 5546fdd5 2022-12-23 op if ((t = parse_authority(s + 2, iri)) == NULL)
333 5546fdd5 2022-12-23 op return (NULL);
334 5546fdd5 2022-12-23 op return (parse_path_abempty(t, iri));
335 5546fdd5 2022-12-23 op }
336 5546fdd5 2022-12-23 op
337 5546fdd5 2022-12-23 op if ((t = parse_path_absolute(s, iri)) != NULL)
338 5546fdd5 2022-12-23 op return (t);
339 5546fdd5 2022-12-23 op
340 5546fdd5 2022-12-23 op if ((t = parse_path_noscheme(s, iri)) != NULL)
341 5546fdd5 2022-12-23 op return (t);
342 5546fdd5 2022-12-23 op
343 5546fdd5 2022-12-23 op return (parse_path_empty(s, iri));
344 5546fdd5 2022-12-23 op }
345 5546fdd5 2022-12-23 op
346 5546fdd5 2022-12-23 op static const char *
347 5546fdd5 2022-12-23 op parse_query(const char *s, struct iri *iri)
348 5546fdd5 2022-12-23 op {
349 5546fdd5 2022-12-23 op const char *n, *t = s;
350 5546fdd5 2022-12-23 op
351 5546fdd5 2022-12-23 op for (;;) {
352 5546fdd5 2022-12-23 op if ((n = advance_pchar(t)) != NULL)
353 5546fdd5 2022-12-23 op t = n;
354 5546fdd5 2022-12-23 op else if (*t == '/' || *t == '?')
355 5546fdd5 2022-12-23 op t++;
356 5546fdd5 2022-12-23 op else
357 5546fdd5 2022-12-23 op break;
358 5546fdd5 2022-12-23 op }
359 5546fdd5 2022-12-23 op
360 5546fdd5 2022-12-23 op if (cpstr(s, t, iri->iri_query, sizeof(iri->iri_query)) == -1)
361 5546fdd5 2022-12-23 op return (NULL);
362 5546fdd5 2022-12-23 op iri->iri_flags |= IH_QUERY;
363 5546fdd5 2022-12-23 op return (t);
364 5546fdd5 2022-12-23 op }
365 5546fdd5 2022-12-23 op
366 5546fdd5 2022-12-23 op static int
367 5546fdd5 2022-12-23 op parse_uri(const char *s, struct iri *iri)
368 5546fdd5 2022-12-23 op {
369 5546fdd5 2022-12-23 op if ((s = parse_scheme(s, iri)) == NULL)
370 5546fdd5 2022-12-23 op return (-1);
371 5546fdd5 2022-12-23 op
372 5546fdd5 2022-12-23 op if (*s != ':')
373 5546fdd5 2022-12-23 op return (-1);
374 5546fdd5 2022-12-23 op
375 5546fdd5 2022-12-23 op if ((s = parse_hier(s + 1, iri)) == NULL)
376 5546fdd5 2022-12-23 op return (-1);
377 5546fdd5 2022-12-23 op
378 5546fdd5 2022-12-23 op if (*s == '?' && (s = parse_query(s + 1, iri)) == NULL)
379 5546fdd5 2022-12-23 op return (-1);
380 5546fdd5 2022-12-23 op
381 5546fdd5 2022-12-23 op /* skip fragments */
382 5546fdd5 2022-12-23 op if (*s == '#' || *s == '\0')
383 5546fdd5 2022-12-23 op return (0);
384 5546fdd5 2022-12-23 op
385 5546fdd5 2022-12-23 op return (-1);
386 5546fdd5 2022-12-23 op }
387 5546fdd5 2022-12-23 op
388 5546fdd5 2022-12-23 op static int
389 5546fdd5 2022-12-23 op parse_relative_ref(const char *s, struct iri *iri)
390 5546fdd5 2022-12-23 op {
391 5546fdd5 2022-12-23 op if ((s = parse_relative(s, iri)) == NULL)
392 5546fdd5 2022-12-23 op return (-1);
393 5546fdd5 2022-12-23 op
394 5546fdd5 2022-12-23 op if (*s == '?' && (s = parse_query(s + 1, iri)) == NULL)
395 5546fdd5 2022-12-23 op return (-1);
396 5546fdd5 2022-12-23 op
397 5546fdd5 2022-12-23 op /* skip fragments */
398 5546fdd5 2022-12-23 op if (*s == '#' || *s == '\0')
399 5546fdd5 2022-12-23 op return (0);
400 5546fdd5 2022-12-23 op
401 5546fdd5 2022-12-23 op return (-1);
402 5546fdd5 2022-12-23 op }
403 5546fdd5 2022-12-23 op
404 5546fdd5 2022-12-23 op static int
405 5546fdd5 2022-12-23 op parse(const char *s, struct iri *iri)
406 5546fdd5 2022-12-23 op {
407 5546fdd5 2022-12-23 op iri->iri_flags = 0;
408 5546fdd5 2022-12-23 op
409 5546fdd5 2022-12-23 op if (s == NULL)
410 5546fdd5 2022-12-23 op return (0);
411 5546fdd5 2022-12-23 op
412 5546fdd5 2022-12-23 op if (parse_uri(s, iri) == -1) {
413 5546fdd5 2022-12-23 op iri->iri_flags = 0;
414 5546fdd5 2022-12-23 op if (parse_relative_ref(s, iri) == -1)
415 5546fdd5 2022-12-23 op return (-1);
416 5546fdd5 2022-12-23 op }
417 5546fdd5 2022-12-23 op
418 5546fdd5 2022-12-23 op return (0);
419 5546fdd5 2022-12-23 op }
420 5546fdd5 2022-12-23 op
421 5546fdd5 2022-12-23 op static void
422 5546fdd5 2022-12-23 op cpfields(struct iri *dest, const struct iri *src, int flags)
423 5546fdd5 2022-12-23 op {
424 5546fdd5 2022-12-23 op if (flags & IH_SCHEME) {
425 5546fdd5 2022-12-23 op dest->iri_flags |= IH_SCHEME;
426 5546fdd5 2022-12-23 op if (src->iri_flags & IH_SCHEME)
427 5546fdd5 2022-12-23 op memcpy(dest->iri_scheme, src->iri_scheme,
428 5546fdd5 2022-12-23 op sizeof(dest->iri_scheme));
429 5546fdd5 2022-12-23 op }
430 5546fdd5 2022-12-23 op if (flags & IH_UINFO) {
431 5546fdd5 2022-12-23 op dest->iri_flags |= IH_UINFO;
432 5546fdd5 2022-12-23 op if (src->iri_flags & IH_UINFO)
433 5546fdd5 2022-12-23 op memcpy(dest->iri_uinfo, src->iri_uinfo,
434 5546fdd5 2022-12-23 op sizeof(dest->iri_uinfo));
435 5546fdd5 2022-12-23 op }
436 5546fdd5 2022-12-23 op if (flags & IH_HOST) {
437 5546fdd5 2022-12-23 op dest->iri_flags |= IH_HOST;
438 5546fdd5 2022-12-23 op if (src->iri_flags & IH_HOST)
439 5546fdd5 2022-12-23 op memcpy(dest->iri_host, src->iri_host,
440 5546fdd5 2022-12-23 op sizeof(dest->iri_host));
441 5546fdd5 2022-12-23 op }
442 5546fdd5 2022-12-23 op if (flags & IH_PORT) {
443 5546fdd5 2022-12-23 op dest->iri_flags |= IH_PORT;
444 5546fdd5 2022-12-23 op if (src->iri_flags & IH_PORT)
445 5546fdd5 2022-12-23 op dest->iri_port = src->iri_port;
446 5546fdd5 2022-12-23 op }
447 5546fdd5 2022-12-23 op if (flags & IH_PATH) {
448 5546fdd5 2022-12-23 op dest->iri_flags |= IH_PATH;
449 5546fdd5 2022-12-23 op if (src->iri_flags & IH_PATH)
450 5546fdd5 2022-12-23 op memcpy(dest->iri_path, src->iri_path,
451 5546fdd5 2022-12-23 op sizeof(dest->iri_path));
452 5546fdd5 2022-12-23 op }
453 5546fdd5 2022-12-23 op if (flags & IH_QUERY) {
454 5546fdd5 2022-12-23 op dest->iri_flags |= IH_QUERY;
455 5546fdd5 2022-12-23 op if (src->iri_flags & IH_QUERY)
456 5546fdd5 2022-12-23 op memcpy(dest->iri_query, src->iri_query,
457 5546fdd5 2022-12-23 op sizeof(dest->iri_query));
458 5546fdd5 2022-12-23 op }
459 5546fdd5 2022-12-23 op }
460 5546fdd5 2022-12-23 op
461 5546fdd5 2022-12-23 op static inline void
462 5546fdd5 2022-12-23 op remove_dot_segments(struct iri *iri)
463 5546fdd5 2022-12-23 op {
464 5546fdd5 2022-12-23 op /* TODO: fixup iri->iri_path */
465 5546fdd5 2022-12-23 op return;
466 5546fdd5 2022-12-23 op }
467 5546fdd5 2022-12-23 op
468 5546fdd5 2022-12-23 op static inline void
469 5546fdd5 2022-12-23 op mergepath(char *out, size_t len, const char *a, const char *b)
470 5546fdd5 2022-12-23 op {
471 5546fdd5 2022-12-23 op /* TODO: compute into out path `b' resolved from `a' */
472 5546fdd5 2022-12-23 op memset(out, 0, len);
473 5546fdd5 2022-12-23 op return;
474 5546fdd5 2022-12-23 op }
475 5546fdd5 2022-12-23 op
476 5546fdd5 2022-12-23 op int
477 5546fdd5 2022-12-23 op iri_parse(const char *base, const char *str, struct iri *iri)
478 5546fdd5 2022-12-23 op {
479 5546fdd5 2022-12-23 op static struct iri ibase, iparsed;
480 5546fdd5 2022-12-23 op
481 5546fdd5 2022-12-23 op memset(iri, 0, sizeof(*iri));
482 5546fdd5 2022-12-23 op
483 5546fdd5 2022-12-23 op if (base == NULL) {
484 5546fdd5 2022-12-23 op ibase.iri_flags = 0;
485 5546fdd5 2022-12-23 op if (parse_uri(str, &iparsed) == -1)
486 5546fdd5 2022-12-23 op return (-1);
487 5546fdd5 2022-12-23 op } else {
488 5546fdd5 2022-12-23 op if (parse_uri(base, &ibase) == -1)
489 5546fdd5 2022-12-23 op return (-1);
490 5546fdd5 2022-12-23 op if (parse(str, &iparsed) == -1)
491 5546fdd5 2022-12-23 op return (-1);
492 5546fdd5 2022-12-23 op }
493 5546fdd5 2022-12-23 op
494 5546fdd5 2022-12-23 op if (iparsed.iri_flags & IH_SCHEME) {
495 5546fdd5 2022-12-23 op cpfields(iri, &iparsed, iparsed.iri_flags);
496 5546fdd5 2022-12-23 op remove_dot_segments(iri);
497 5546fdd5 2022-12-23 op return (0);
498 5546fdd5 2022-12-23 op }
499 5546fdd5 2022-12-23 op
500 5546fdd5 2022-12-23 op /* if fragments are supported, copy iparsed fragment to iri */
501 5546fdd5 2022-12-23 op
502 5546fdd5 2022-12-23 op cpfields(iri, &ibase, IH_SCHEME);
503 5546fdd5 2022-12-23 op
504 5546fdd5 2022-12-23 op if (iparsed.iri_flags & IH_HOST) {
505 5546fdd5 2022-12-23 op cpfields(iri, &iparsed, IH_AUTHORITY|IH_PATH|IH_QUERY);
506 5546fdd5 2022-12-23 op remove_dot_segments(iri);
507 5546fdd5 2022-12-23 op return (0);
508 5546fdd5 2022-12-23 op }
509 5546fdd5 2022-12-23 op
510 5546fdd5 2022-12-23 op cpfields(iri, &ibase, IH_AUTHORITY);
511 5546fdd5 2022-12-23 op
512 5546fdd5 2022-12-23 op if ((iparsed.iri_flags & IH_PATH) && *iparsed.iri_path == '\0') {
513 5546fdd5 2022-12-23 op cpfields(iri, &ibase, IH_PATH);
514 5546fdd5 2022-12-23 op if (iparsed.iri_flags & IH_QUERY)
515 5546fdd5 2022-12-23 op cpfields(iri, &iparsed, IH_QUERY);
516 5546fdd5 2022-12-23 op else
517 5546fdd5 2022-12-23 op cpfields(iri, &ibase, IH_QUERY);
518 5546fdd5 2022-12-23 op return (0);
519 5546fdd5 2022-12-23 op }
520 5546fdd5 2022-12-23 op
521 5546fdd5 2022-12-23 op cpfields(iri, &iparsed, IH_QUERY);
522 5546fdd5 2022-12-23 op if ((iparsed.iri_flags & IH_PATH) && !strcmp(iparsed.iri_path, "/"))
523 5546fdd5 2022-12-23 op cpfields(iri, &iparsed, IH_PATH);
524 5546fdd5 2022-12-23 op else {
525 5546fdd5 2022-12-23 op if (!(ibase.iri_flags & IH_PATH))
526 5546fdd5 2022-12-23 op ibase.iri_path[0] = '\0';
527 5546fdd5 2022-12-23 op if (!(iparsed.iri_flags & IH_PATH))
528 5546fdd5 2022-12-23 op iparsed.iri_path[0] = '\0';
529 5546fdd5 2022-12-23 op mergepath(iri->iri_path, sizeof(iri->iri_path),
530 5546fdd5 2022-12-23 op ibase.iri_path, iparsed.iri_path);
531 5546fdd5 2022-12-23 op }
532 5546fdd5 2022-12-23 op remove_dot_segments(iri);
533 5546fdd5 2022-12-23 op cpfields(iri, &ibase, IH_QUERY);
534 5546fdd5 2022-12-23 op return (0);
535 5546fdd5 2022-12-23 op }
536 5546fdd5 2022-12-23 op
537 5546fdd5 2022-12-23 op int
538 5546fdd5 2022-12-23 op iri_unparse(const struct iri *iri, char *buf, size_t buflen)
539 5546fdd5 2022-12-23 op {
540 5546fdd5 2022-12-23 op memset(buf, 0, buflen);
541 5546fdd5 2022-12-23 op return (-1);
542 5546fdd5 2022-12-23 op }
543 5546fdd5 2022-12-23 op
544 5546fdd5 2022-12-23 op int
545 5546fdd5 2022-12-23 op iri_human(const struct iri *iri, char *buf, size_t buflen)
546 5546fdd5 2022-12-23 op {
547 5546fdd5 2022-12-23 op memset(buf, 0, buflen);
548 5546fdd5 2022-12-23 op return (-1);
549 5546fdd5 2022-12-23 op }
550 5546fdd5 2022-12-23 op
551 5546fdd5 2022-12-23 op int
552 5546fdd5 2022-12-23 op iri_setquery(struct iri *iri, const char *text)
553 5546fdd5 2022-12-23 op {
554 5546fdd5 2022-12-23 op return (-1);
555 5546fdd5 2022-12-23 op }