Mercurial > embed
comparison uriparser/src/UriShorten.c @ 60:a2be1eba7adb
uriparser: import 0.8.5, close #878 @10m
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 13 Jul 2018 10:50:43 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
59:e5880f2798a1 | 60:a2be1eba7adb |
---|---|
1 /* | |
2 * uriparser - RFC 3986 URI parsing library | |
3 * | |
4 * Copyright (C) 2007, Weijia Song <songweijia@gmail.com> | |
5 * Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org> | |
6 * All rights reserved. | |
7 * | |
8 * Redistribution and use in source and binary forms, with or without | |
9 * modification, are permitted provided that the following conditions | |
10 * are met: | |
11 * | |
12 * * Redistributions of source code must retain the above | |
13 * copyright notice, this list of conditions and the following | |
14 * disclaimer. | |
15 * | |
16 * * Redistributions in binary form must reproduce the above | |
17 * copyright notice, this list of conditions and the following | |
18 * disclaimer in the documentation and/or other materials | |
19 * provided with the distribution. | |
20 * | |
21 * * Neither the name of the <ORGANIZATION> nor the names of its | |
22 * contributors may be used to endorse or promote products | |
23 * derived from this software without specific prior written | |
24 * permission. | |
25 * | |
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
29 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
30 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
32 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
37 * OF THE POSSIBILITY OF SUCH DAMAGE. | |
38 */ | |
39 | |
40 /* What encodings are enabled? */ | |
41 #include <uriparser/UriDefsConfig.h> | |
42 #if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) | |
43 /* Include SELF twice */ | |
44 # ifdef URI_ENABLE_ANSI | |
45 # define URI_PASS_ANSI 1 | |
46 # include "UriShorten.c" | |
47 # undef URI_PASS_ANSI | |
48 # endif | |
49 # ifdef URI_ENABLE_UNICODE | |
50 # define URI_PASS_UNICODE 1 | |
51 # include "UriShorten.c" | |
52 # undef URI_PASS_UNICODE | |
53 # endif | |
54 #else | |
55 # ifdef URI_PASS_ANSI | |
56 # include <uriparser/UriDefsAnsi.h> | |
57 # else | |
58 # include <uriparser/UriDefsUnicode.h> | |
59 # include <wchar.h> | |
60 # endif | |
61 | |
62 | |
63 | |
64 #ifndef URI_DOXYGEN | |
65 # include <uriparser/Uri.h> | |
66 # include "UriCommon.h" | |
67 #endif | |
68 | |
69 | |
70 | |
71 static URI_INLINE UriBool URI_FUNC(AppendSegment)(URI_TYPE(Uri) * uri, | |
72 const URI_CHAR * first, const URI_CHAR * afterLast) { | |
73 /* Create segment */ | |
74 URI_TYPE(PathSegment) * segment = malloc(1 * sizeof(URI_TYPE(PathSegment))); | |
75 if (segment == NULL) { | |
76 return URI_FALSE; /* Raises malloc error */ | |
77 } | |
78 segment->next = NULL; | |
79 segment->text.first = first; | |
80 segment->text.afterLast = afterLast; | |
81 | |
82 /* Put into chain */ | |
83 if (uri->pathTail == NULL) { | |
84 uri->pathHead = segment; | |
85 } else { | |
86 uri->pathTail->next = segment; | |
87 } | |
88 uri->pathTail = segment; | |
89 | |
90 return URI_TRUE; | |
91 } | |
92 | |
93 | |
94 | |
95 static URI_INLINE UriBool URI_FUNC(EqualsAuthority)(const URI_TYPE(Uri) * first, | |
96 const URI_TYPE(Uri) * second) { | |
97 /* IPv4 */ | |
98 if (first->hostData.ip4 != NULL) { | |
99 return ((second->hostData.ip4 != NULL) | |
100 && !memcmp(first->hostData.ip4->data, | |
101 second->hostData.ip4->data, 4)) ? URI_TRUE : URI_FALSE; | |
102 } | |
103 | |
104 /* IPv6 */ | |
105 if (first->hostData.ip6 != NULL) { | |
106 return ((second->hostData.ip6 != NULL) | |
107 && !memcmp(first->hostData.ip6->data, | |
108 second->hostData.ip6->data, 16)) ? URI_TRUE : URI_FALSE; | |
109 } | |
110 | |
111 /* IPvFuture */ | |
112 if (first->hostData.ipFuture.first != NULL) { | |
113 return ((second->hostData.ipFuture.first != NULL) | |
114 && !URI_STRNCMP(first->hostData.ipFuture.first, | |
115 second->hostData.ipFuture.first, | |
116 first->hostData.ipFuture.afterLast | |
117 - first->hostData.ipFuture.first)) | |
118 ? URI_TRUE : URI_FALSE; | |
119 } | |
120 | |
121 if (first->hostText.first != NULL) { | |
122 return ((second->hostText.first != NULL) | |
123 && !URI_STRNCMP(first->hostText.first, | |
124 second->hostText.first, | |
125 first->hostText.afterLast | |
126 - first->hostText.first)) ? URI_TRUE : URI_FALSE; | |
127 } | |
128 | |
129 return (second->hostText.first == NULL); | |
130 } | |
131 | |
132 | |
133 | |
134 static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest, | |
135 const URI_TYPE(Uri) * absSource, | |
136 const URI_TYPE(Uri) * absBase, | |
137 UriBool domainRootMode) { | |
138 if (dest == NULL) { | |
139 return URI_ERROR_NULL; | |
140 } | |
141 URI_FUNC(ResetUri)(dest); | |
142 | |
143 if ((absSource == NULL) || (absBase == NULL)) { | |
144 return URI_ERROR_NULL; | |
145 } | |
146 | |
147 /* absBase absolute? */ | |
148 if (absBase->scheme.first == NULL) { | |
149 return URI_ERROR_REMOVEBASE_REL_BASE; | |
150 } | |
151 | |
152 /* absSource absolute? */ | |
153 if (absSource->scheme.first == NULL) { | |
154 return URI_ERROR_REMOVEBASE_REL_SOURCE; | |
155 } | |
156 | |
157 /* [01/50] if (A.scheme != Base.scheme) then */ | |
158 if (URI_STRNCMP(absSource->scheme.first, absBase->scheme.first, | |
159 absSource->scheme.afterLast - absSource->scheme.first)) { | |
160 /* [02/50] T.scheme = A.scheme; */ | |
161 dest->scheme = absSource->scheme; | |
162 /* [03/50] T.authority = A.authority; */ | |
163 if (!URI_FUNC(CopyAuthority)(dest, absSource)) { | |
164 return URI_ERROR_MALLOC; | |
165 } | |
166 /* [04/50] T.path = A.path; */ | |
167 if (!URI_FUNC(CopyPath)(dest, absSource)) { | |
168 return URI_ERROR_MALLOC; | |
169 } | |
170 /* [05/50] else */ | |
171 } else { | |
172 /* [06/50] undef(T.scheme); */ | |
173 /* NOOP */ | |
174 /* [07/50] if (A.authority != Base.authority) then */ | |
175 if (!URI_FUNC(EqualsAuthority)(absSource, absBase)) { | |
176 /* [08/50] T.authority = A.authority; */ | |
177 if (!URI_FUNC(CopyAuthority)(dest, absSource)) { | |
178 return URI_ERROR_MALLOC; | |
179 } | |
180 /* [09/50] T.path = A.path; */ | |
181 if (!URI_FUNC(CopyPath)(dest, absSource)) { | |
182 return URI_ERROR_MALLOC; | |
183 } | |
184 /* [10/50] else */ | |
185 } else { | |
186 /* [11/50] if domainRootMode then */ | |
187 if (domainRootMode == URI_TRUE) { | |
188 /* [12/50] undef(T.authority); */ | |
189 /* NOOP */ | |
190 /* [13/50] if (first(A.path) == "") then */ | |
191 /* GROUPED */ | |
192 /* [14/50] T.path = "/." + A.path; */ | |
193 /* GROUPED */ | |
194 /* [15/50] else */ | |
195 /* GROUPED */ | |
196 /* [16/50] T.path = A.path; */ | |
197 /* GROUPED */ | |
198 /* [17/50] endif; */ | |
199 if (!URI_FUNC(CopyPath)(dest, absSource)) { | |
200 return URI_ERROR_MALLOC; | |
201 } | |
202 dest->absolutePath = URI_TRUE; | |
203 | |
204 if (!URI_FUNC(FixAmbiguity)(dest)) { | |
205 return URI_ERROR_MALLOC; | |
206 } | |
207 /* [18/50] else */ | |
208 } else { | |
209 const URI_TYPE(PathSegment) * sourceSeg = absSource->pathHead; | |
210 const URI_TYPE(PathSegment) * baseSeg = absBase->pathHead; | |
211 /* [19/50] bool pathNaked = true; */ | |
212 UriBool pathNaked = URI_TRUE; | |
213 /* [20/50] undef(last(Base.path)); */ | |
214 /* NOOP */ | |
215 /* [21/50] T.path = ""; */ | |
216 dest->absolutePath = URI_FALSE; | |
217 /* [22/50] while (first(A.path) == first(Base.path)) do */ | |
218 while ((sourceSeg != NULL) && (baseSeg != NULL) | |
219 && !URI_STRNCMP(sourceSeg->text.first, baseSeg->text.first, | |
220 sourceSeg->text.afterLast - sourceSeg->text.first) | |
221 && !((sourceSeg->text.first == sourceSeg->text.afterLast) | |
222 && ((sourceSeg->next == NULL) != (baseSeg->next == NULL)))) { | |
223 /* [23/50] A.path++; */ | |
224 sourceSeg = sourceSeg->next; | |
225 /* [24/50] Base.path++; */ | |
226 baseSeg = baseSeg->next; | |
227 /* [25/50] endwhile; */ | |
228 } | |
229 /* [26/50] while defined(first(Base.path)) do */ | |
230 while ((baseSeg != NULL) && (baseSeg->next != NULL)) { | |
231 /* [27/50] Base.path++; */ | |
232 baseSeg = baseSeg->next; | |
233 /* [28/50] T.path += "../"; */ | |
234 if (!URI_FUNC(AppendSegment)(dest, URI_FUNC(ConstParent), | |
235 URI_FUNC(ConstParent) + 2)) { | |
236 return URI_ERROR_MALLOC; | |
237 } | |
238 /* [29/50] pathNaked = false; */ | |
239 pathNaked = URI_FALSE; | |
240 /* [30/50] endwhile; */ | |
241 } | |
242 /* [31/50] while defined(first(A.path)) do */ | |
243 while (sourceSeg != NULL) { | |
244 /* [32/50] if pathNaked then */ | |
245 if (pathNaked == URI_TRUE) { | |
246 /* [33/50] if (first(A.path) contains ":") then */ | |
247 UriBool containsColon = URI_FALSE; | |
248 const URI_CHAR * ch = sourceSeg->text.first; | |
249 for (; ch < sourceSeg->text.afterLast; ch++) { | |
250 if (*ch == _UT(':')) { | |
251 containsColon = URI_TRUE; | |
252 break; | |
253 } | |
254 } | |
255 | |
256 if (containsColon) { | |
257 /* [34/50] T.path += "./"; */ | |
258 if (!URI_FUNC(AppendSegment)(dest, URI_FUNC(ConstPwd), | |
259 URI_FUNC(ConstPwd) + 1)) { | |
260 return URI_ERROR_MALLOC; | |
261 } | |
262 /* [35/50] elseif (first(A.path) == "") then */ | |
263 } else if (sourceSeg->text.first == sourceSeg->text.afterLast) { | |
264 /* [36/50] T.path += "/."; */ | |
265 if (!URI_FUNC(AppendSegment)(dest, URI_FUNC(ConstPwd), | |
266 URI_FUNC(ConstPwd) + 1)) { | |
267 return URI_ERROR_MALLOC; | |
268 } | |
269 /* [37/50] endif; */ | |
270 } | |
271 /* [38/50] endif; */ | |
272 } | |
273 /* [39/50] T.path += first(A.path); */ | |
274 if (!URI_FUNC(AppendSegment)(dest, sourceSeg->text.first, | |
275 sourceSeg->text.afterLast)) { | |
276 return URI_ERROR_MALLOC; | |
277 } | |
278 /* [40/50] pathNaked = false; */ | |
279 pathNaked = URI_FALSE; | |
280 /* [41/50] A.path++; */ | |
281 sourceSeg = sourceSeg->next; | |
282 /* [42/50] if defined(first(A.path)) then */ | |
283 /* NOOP */ | |
284 /* [43/50] T.path += + "/"; */ | |
285 /* NOOP */ | |
286 /* [44/50] endif; */ | |
287 /* NOOP */ | |
288 /* [45/50] endwhile; */ | |
289 } | |
290 /* [46/50] endif; */ | |
291 } | |
292 /* [47/50] endif; */ | |
293 } | |
294 /* [48/50] endif; */ | |
295 } | |
296 /* [49/50] T.query = A.query; */ | |
297 dest->query = absSource->query; | |
298 /* [50/50] T.fragment = A.fragment; */ | |
299 dest->fragment = absSource->fragment; | |
300 | |
301 return URI_SUCCESS; | |
302 } | |
303 | |
304 | |
305 | |
306 int URI_FUNC(RemoveBaseUri)(URI_TYPE(Uri) * dest, | |
307 const URI_TYPE(Uri) * absSource, | |
308 const URI_TYPE(Uri) * absBase, | |
309 UriBool domainRootMode) { | |
310 const int res = URI_FUNC(RemoveBaseUriImpl)(dest, absSource, | |
311 absBase, domainRootMode); | |
312 if ((res != URI_SUCCESS) && (dest != NULL)) { | |
313 URI_FUNC(FreeUriMembers)(dest); | |
314 } | |
315 return res; | |
316 } | |
317 | |
318 | |
319 | |
320 #endif |