|
21 | 21 | #include "Zend/zend_exceptions.h"
|
22 | 22 |
|
23 | 23 | static void uriparser_free_uri(void *uri);
|
24 |
| -static void throw_invalid_uri_exception(void); |
25 | 24 |
|
26 | 25 | static void *uriparser_malloc(UriMemoryManager *memory_manager, size_t size)
|
27 | 26 | {
|
@@ -293,51 +292,59 @@ static uriparser_uris_t *uriparser_create_uris(void)
|
293 | 292 | return uriparser_uris;
|
294 | 293 | }
|
295 | 294 |
|
296 |
| -static void throw_invalid_uri_exception(void) |
297 |
| -{ |
298 |
| - zend_throw_exception(uri_invalid_uri_exception_ce, "The specified URI is malformed", 0); |
299 |
| -} |
300 |
| - |
301 |
| -#define PARSE_URI(dest_uri, uri_str, uriparser_uris, silent) \ |
302 |
| - do { \ |
303 |
| - if (ZSTR_LEN(uri_str) == 0 || \ |
304 |
| - uriParseSingleUriExMmA(dest_uri, ZSTR_VAL(uri_str), ZSTR_VAL(uri_str) + ZSTR_LEN(uri_str), NULL, mm) != URI_SUCCESS \ |
305 |
| - ) { \ |
306 |
| - efree(uriparser_uris); \ |
307 |
| - if (!silent) { \ |
308 |
| - throw_invalid_uri_exception(); \ |
309 |
| - } \ |
310 |
| - return NULL; \ |
311 |
| - } \ |
312 |
| - } while (0) |
313 |
| - |
314 | 295 | void *uriparser_parse_uri_ex(const zend_string *uri_str, const uriparser_uris_t *uriparser_base_urls, bool silent)
|
315 | 296 | {
|
316 |
| - uriparser_uris_t *uriparser_uris = uriparser_create_uris(); |
| 297 | + UriUriA uri = {0}; |
317 | 298 |
|
318 |
| - if (uriparser_base_urls == NULL) { |
319 |
| - PARSE_URI(&uriparser_uris->uri, uri_str, uriparser_uris, silent); |
320 |
| - uriMakeOwnerMmA(&uriparser_uris->uri, mm); |
321 |
| - } else { |
322 |
| - UriUriA uri; |
| 299 | + /* Parse the URI. */ |
| 300 | + if (uriParseSingleUriExMmA(&uri, ZSTR_VAL(uri_str), ZSTR_VAL(uri_str) + ZSTR_LEN(uri_str), NULL, mm) != URI_SUCCESS) { |
| 301 | + if (!silent) { |
| 302 | + zend_throw_exception(uri_invalid_uri_exception_ce, "The specified URI is malformed", 0); |
| 303 | + } |
323 | 304 |
|
324 |
| - PARSE_URI(&uri, uri_str, uriparser_uris, silent); |
| 305 | + goto fail; |
| 306 | + } |
325 | 307 |
|
326 |
| - if (uriAddBaseUriExMmA(&uriparser_uris->uri, &uri, &uriparser_base_urls->uri, URI_RESOLVE_STRICTLY, mm) != URI_SUCCESS) { |
327 |
| - efree(uriparser_uris); |
328 |
| - uriFreeUriMembersMmA(&uri, mm); |
| 308 | + if (uriparser_base_urls != NULL) { |
| 309 | + UriUriA tmp = {0}; |
| 310 | + |
| 311 | + /* Combine the parsed URI with the base URI and store the result in 'tmp', |
| 312 | + * since the target and source URLs must be distinct. */ |
| 313 | + int result = uriAddBaseUriExMmA(&tmp, &uri, &uriparser_base_urls->uri, URI_RESOLVE_STRICTLY, mm); |
| 314 | + if (result != URI_SUCCESS) { |
329 | 315 | if (!silent) {
|
330 |
| - throw_invalid_uri_exception(); |
| 316 | + switch (result) { |
| 317 | + case URI_ERROR_ADDBASE_REL_BASE: |
| 318 | + zend_throw_exception(uri_invalid_uri_exception_ce, "The specified base URI must be absolute", 0); |
| 319 | + break; |
| 320 | + default: |
| 321 | + /* This should be unreachable in practice. */ |
| 322 | + zend_throw_exception(uri_invalid_uri_exception_ce, "Failed to resolve the specified URI against the base URI", 0); |
| 323 | + break; |
| 324 | + } |
331 | 325 | }
|
332 | 326 |
|
333 |
| - return NULL; |
| 327 | + goto fail; |
334 | 328 | }
|
335 | 329 |
|
336 |
| - uriMakeOwnerMmA(&uriparser_uris->uri, mm); |
| 330 | + /* Store the combined URI back into 'uri'. */ |
337 | 331 | uriFreeUriMembersMmA(&uri, mm);
|
| 332 | + uri = tmp; |
338 | 333 | }
|
339 | 334 |
|
| 335 | + /* Make the resulting URI independent of the 'uri_str'. */ |
| 336 | + uriMakeOwnerMmA(&uri, mm); |
| 337 | + |
| 338 | + uriparser_uris_t *uriparser_uris = uriparser_create_uris(); |
| 339 | + uriparser_uris->uri = uri; |
| 340 | + |
340 | 341 | return uriparser_uris;
|
| 342 | + |
| 343 | + fail: |
| 344 | + |
| 345 | + uriFreeUriMembersMmA(&uri, mm); |
| 346 | + |
| 347 | + return NULL; |
341 | 348 | }
|
342 | 349 |
|
343 | 350 | void *uriparser_parse_uri(const zend_string *uri_str, const void *base_url, zval *errors, bool silent)
|
|
0 commit comments