Coverage Report

Created: 2026-09-14 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/ext/uri/php_uri.c
Line
Count
Source
1
/*
2
   +----------------------------------------------------------------------+
3
   | Copyright © The PHP Group and Contributors.                          |
4
   +----------------------------------------------------------------------+
5
   | This source file is subject to the Modified BSD License that is      |
6
   | bundled with this package in the file LICENSE, and is available      |
7
   | through the World Wide Web at <https://www.php.net/license/>.        |
8
   |                                                                      |
9
   | SPDX-License-Identifier: BSD-3-Clause                                |
10
   +----------------------------------------------------------------------+
11
   | Authors: Máté Kocsis <kocsismate@php.net>                            |
12
   +----------------------------------------------------------------------+
13
*/
14
15
#ifdef HAVE_CONFIG_H
16
# include <config.h>
17
#endif
18
19
#include "php.h"
20
#include "Zend/zend_interfaces.h"
21
#include "Zend/zend_exceptions.h"
22
#include "ext/standard/info.h"
23
24
#include "php_uri.h"
25
#include "uri_parser_whatwg.h"
26
#include "uri_parser_rfc3986.h"
27
#include "uri_parser_php_parse_url.h"
28
#include "php_uri_arginfo.h"
29
#include "uriparser/Uri.h"
30
31
zend_class_entry *php_uri_ce_rfc3986_uri_builder;
32
zend_class_entry *php_uri_ce_rfc3986_uri;
33
zend_class_entry *php_uri_ce_rfc3986_uri_type;
34
zend_class_entry *php_uri_ce_rfc3986_uri_host_type;
35
zend_class_entry *php_uri_ce_whatwg_url_builder;
36
zend_class_entry *php_uri_ce_whatwg_url;
37
zend_class_entry *php_uri_ce_whatwg_url_percent_encoding_mode;
38
zend_class_entry *php_uri_ce_comparison_mode;
39
zend_class_entry *php_uri_ce_exception;
40
zend_class_entry *php_uri_ce_error;
41
zend_class_entry *php_uri_ce_invalid_uri_exception;
42
zend_class_entry *php_uri_ce_whatwg_url_host_type;
43
zend_class_entry *php_uri_ce_whatwg_invalid_url_exception;
44
zend_class_entry *php_uri_ce_whatwg_url_validation_error_type;
45
zend_class_entry *php_uri_ce_whatwg_url_validation_error;
46
47
static zend_object_handlers object_handlers_rfc3986_uri;
48
static zend_object_handlers object_handlers_whatwg_uri;
49
50
typedef zend_result (*php_uri_component_validator_string)(const zend_string *component);
51
typedef zend_result (*php_uri_component_validator_long)(zend_long component);
52
53
static const zend_module_dep uri_deps[] = {
54
  ZEND_MOD_REQUIRED("lexbor")
55
  ZEND_MOD_END
56
};
57
58
static zend_array uri_parsers;
59
60
static zend_always_inline zval *php_uri_deref(zval *zv)
61
0
{
62
0
  if (UNEXPECTED(Z_TYPE_P(zv) == IS_REFERENCE)) {
63
0
    return Z_REFVAL_P(zv);
64
0
  }
65
66
0
  return zv;
67
0
}
68
69
0
#define Z_RFC3986_URI_PROP_SCHEME_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 0))
70
0
#define Z_RFC3986_URI_PROP_USERINFO_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 1))
71
0
#define Z_RFC3986_URI_PROP_HOST_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 2))
72
0
#define Z_RFC3986_URI_PROP_PORT_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 3))
73
0
#define Z_RFC3986_URI_PROP_PATH_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 4)
74
0
#define Z_RFC3986_URI_PROP_PATH_DEREF_P(zv) php_uri_deref(Z_RFC3986_URI_PROP_PATH_P(zv))
75
0
#define Z_RFC3986_URI_PROP_QUERY_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 5))
76
0
#define Z_RFC3986_URI_PROP_FRAGMENT_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 6))
77
78
0
#define Z_WHATWG_URL_PROP_SCHEME_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 0)
79
0
#define Z_WHATWG_URL_PROP_SCHEME_DEREF_P(zv) php_uri_deref(Z_WHATWG_URL_PROP_SCHEME_P(zv))
80
0
#define Z_WHATWG_URL_PROP_USERNAME_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 1))
81
0
#define Z_WHATWG_URL_PROP_PASSWORD_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 2))
82
0
#define Z_WHATWG_URL_PROP_HOST_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 3))
83
0
#define Z_WHATWG_URL_PROP_PORT_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 4))
84
0
#define Z_WHATWG_URL_PROP_PATH_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 5)
85
0
#define Z_WHATWG_URL_PROP_PATH_DEREF_P(zv) php_uri_deref(Z_WHATWG_URL_PROP_PATH_P(zv))
86
0
#define Z_WHATWG_URL_PROP_QUERY_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 6))
87
0
#define Z_WHATWG_URL_PROP_FRAGMENT_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 7))
88
89
static HashTable *uri_get_debug_properties(php_uri_object *object)
90
0
{
91
0
  const HashTable *std_properties = zend_std_get_properties(&object->std);
92
0
  HashTable *result = zend_array_dup(std_properties);
93
94
0
  const php_uri_parser * const parser = object->parser;
95
0
  void * const uri = object->uri;
96
97
0
  if (UNEXPECTED(uri == NULL)) {
98
0
    return result;
99
0
  }
100
101
0
  zval tmp;
102
0
  if (parser->property_handler.scheme.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
103
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_SCHEME), &tmp);
104
0
  }
105
106
0
  if (parser->property_handler.username.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
107
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_USERNAME), &tmp);
108
0
  }
109
110
0
  if (parser->property_handler.password.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
111
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_PASSWORD), &tmp);
112
0
  }
113
114
0
  if (parser->property_handler.host.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
115
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_HOST), &tmp);
116
0
  }
117
118
0
  if (parser->property_handler.port.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
119
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_PORT), &tmp);
120
0
  }
121
122
0
  if (parser->property_handler.path.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
123
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_PATH), &tmp);
124
0
  }
125
126
0
  if (parser->property_handler.query.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
127
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_QUERY), &tmp);
128
0
  }
129
130
0
  if (parser->property_handler.fragment.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
131
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_FRAGMENT), &tmp);
132
0
  }
133
134
0
  return result;
135
0
}
136
137
PHPAPI const php_uri_parser *php_uri_get_parser(zend_string *uri_parser_name)
138
0
{
139
0
  if (uri_parser_name == NULL) {
140
0
    return zend_hash_str_find_ptr(&uri_parsers, PHP_URI_PARSER_PHP_PARSE_URL, sizeof(PHP_URI_PARSER_PHP_PARSE_URL) - 1);
141
0
  }
142
143
0
  return zend_hash_find_ptr(&uri_parsers, uri_parser_name);
144
0
}
145
146
ZEND_ATTRIBUTE_NONNULL PHPAPI php_uri_internal *php_uri_parse(const php_uri_parser *uri_parser, const char *uri_str, size_t uri_str_len, bool silent)
147
0
{
148
0
  void *uri = uri_parser->parse(uri_str, uri_str_len, NULL, NULL, silent);
149
150
0
  if (uri == NULL) {
151
0
    return NULL;
152
0
  }
153
154
0
  php_uri_internal *internal_uri = emalloc(sizeof(*internal_uri));
155
0
  internal_uri->parser = uri_parser;
156
0
  internal_uri->uri = uri;
157
158
0
  return internal_uri;
159
0
}
160
161
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_scheme(const php_uri_internal *internal_uri, php_uri_component_read_mode read_mode, zval *zv)
162
0
{
163
0
  return internal_uri->parser->property_handler.scheme.read(internal_uri->uri, read_mode, zv);
164
0
}
165
166
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_username(const php_uri_internal *internal_uri, php_uri_component_read_mode read_mode, zval *zv)
167
0
{
168
0
  return internal_uri->parser->property_handler.username.read(internal_uri->uri, read_mode, zv);
169
0
}
170
171
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_password(const php_uri_internal *internal_uri, php_uri_component_read_mode read_mode, zval *zv)
172
0
{
173
0
  return internal_uri->parser->property_handler.password.read(internal_uri->uri, read_mode, zv);
174
0
}
175
176
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_host(const php_uri_internal *internal_uri, php_uri_component_read_mode read_mode, zval *zv)
177
0
{
178
0
  return internal_uri->parser->property_handler.host.read(internal_uri->uri, read_mode, zv);
179
0
}
180
181
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_port(const php_uri_internal *internal_uri, php_uri_component_read_mode read_mode, zval *zv)
182
0
{
183
0
  return internal_uri->parser->property_handler.port.read(internal_uri->uri, read_mode, zv);
184
0
}
185
186
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_path(const php_uri_internal *internal_uri, php_uri_component_read_mode read_mode, zval *zv)
187
0
{
188
0
  return internal_uri->parser->property_handler.path.read(internal_uri->uri, read_mode, zv);
189
0
}
190
191
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_query(const php_uri_internal *internal_uri, php_uri_component_read_mode read_mode, zval *zv)
192
0
{
193
0
  return internal_uri->parser->property_handler.query.read(internal_uri->uri, read_mode, zv);
194
0
}
195
196
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_fragment(const php_uri_internal *internal_uri, php_uri_component_read_mode read_mode, zval *zv)
197
0
{
198
0
  return internal_uri->parser->property_handler.fragment.read(internal_uri->uri, read_mode, zv);
199
0
}
200
201
ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_free(php_uri_internal *internal_uri)
202
0
{
203
0
  internal_uri->parser->destroy(internal_uri->uri);
204
0
  internal_uri->uri = NULL;
205
0
  internal_uri->parser = NULL;
206
0
  efree(internal_uri);
207
0
}
208
209
ZEND_ATTRIBUTE_NONNULL PHPAPI php_uri *php_uri_parse_to_struct(
210
  const php_uri_parser *uri_parser, const char *uri_str, size_t uri_str_len, php_uri_component_read_mode read_mode, bool silent
211
0
) {
212
0
  php_uri_internal *uri_internal = php_uri_parse(uri_parser, uri_str, uri_str_len, silent);
213
0
  if (uri_internal == NULL) {
214
0
    return NULL;
215
0
  }
216
217
0
  php_uri *uri = ecalloc(1, sizeof(*uri));
218
0
  zval tmp;
219
0
  zend_result result;
220
221
0
  result = php_uri_get_scheme(uri_internal, read_mode, &tmp);
222
0
  if (result == FAILURE) {
223
0
    goto error;
224
0
  }
225
0
  if (Z_TYPE(tmp) == IS_STRING) {
226
0
    uri->scheme = Z_STR(tmp);
227
0
  }
228
229
0
  result = php_uri_get_username(uri_internal, read_mode, &tmp);
230
0
  if (result == FAILURE) {
231
0
    goto error;
232
0
  }
233
0
  if (Z_TYPE(tmp) == IS_STRING) {
234
0
    uri->user = Z_STR(tmp);
235
0
  }
236
237
0
  result = php_uri_get_password(uri_internal, read_mode, &tmp);
238
0
  if (result == FAILURE) {
239
0
    goto error;
240
0
  }
241
0
  if (Z_TYPE(tmp) == IS_STRING) {
242
0
    uri->password = Z_STR(tmp);
243
0
  }
244
245
0
  result = php_uri_get_host(uri_internal, read_mode, &tmp);
246
0
  if (result == FAILURE) {
247
0
    goto error;
248
0
  }
249
0
  if (Z_TYPE(tmp) == IS_STRING) {
250
0
    uri->host = Z_STR(tmp);
251
0
  }
252
253
0
  result = php_uri_get_port(uri_internal, read_mode, &tmp);
254
0
  if (result == FAILURE) {
255
0
    goto error;
256
0
  }
257
0
  if (Z_TYPE(tmp) == IS_LONG) {
258
0
    uri->port = Z_LVAL(tmp);
259
0
  }
260
261
0
  result = php_uri_get_path(uri_internal, read_mode, &tmp);
262
0
  if (result == FAILURE) {
263
0
    goto error;
264
0
  }
265
0
  if (Z_TYPE(tmp) == IS_STRING) {
266
0
    uri->path = Z_STR(tmp);
267
0
  }
268
269
0
  result = php_uri_get_query(uri_internal, read_mode, &tmp);
270
0
  if (result == FAILURE) {
271
0
    goto error;
272
0
  }
273
0
  if (Z_TYPE(tmp) == IS_STRING) {
274
0
    uri->query = Z_STR(tmp);
275
0
  }
276
277
0
  result = php_uri_get_fragment(uri_internal, read_mode, &tmp);
278
0
  if (result == FAILURE) {
279
0
    goto error;
280
0
  }
281
0
  if (Z_TYPE(tmp) == IS_STRING) {
282
0
    uri->fragment = Z_STR(tmp);
283
0
  }
284
285
0
  php_uri_free(uri_internal);
286
287
0
  return uri;
288
289
0
error:
290
0
  php_uri_free(uri_internal);
291
0
  php_uri_struct_free(uri);
292
293
0
  return NULL;
294
0
}
295
296
ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_struct_free(php_uri *uri)
297
0
{
298
0
  if (uri->scheme) {
299
0
    zend_string_release(uri->scheme);
300
0
  }
301
0
  if (uri->user) {
302
0
    zend_string_release(uri->user);
303
0
  }
304
0
  if (uri->password) {
305
0
    zend_string_release(uri->password);
306
0
  }
307
0
  if (uri->host) {
308
0
    zend_string_release(uri->host);
309
0
  }
310
0
  if (uri->path) {
311
0
    zend_string_release(uri->path);
312
0
  }
313
0
  if (uri->query) {
314
0
    zend_string_release(uri->query);
315
0
  }
316
0
  if (uri->fragment) {
317
0
    zend_string_release(uri->fragment);
318
0
  }
319
320
0
  efree(uri);
321
0
}
322
323
/**
324
 * Pass the errors parameter by ref to errors_zv for userland, and frees it if
325
 * it is not not needed anymore.
326
 */
327
static zend_result pass_errors_by_ref_and_free(zval *errors_zv, zval *errors)
328
0
{
329
0
  ZEND_ASSERT(Z_TYPE_P(errors) == IS_UNDEF || Z_TYPE_P(errors) == IS_ARRAY);
330
331
  /* There was no error during parsing */
332
0
  if (Z_ISUNDEF_P(errors)) {
333
0
    return SUCCESS;
334
0
  }
335
336
  /* The errors parameter is an array, but the pass-by ref argument stored by
337
   * errors_zv was not passed - the URI implementation either doesn't support
338
   * returning additional error information, or the caller is not interested in it */
339
0
  if (errors_zv == NULL) {
340
0
    zval_ptr_dtor(errors);
341
0
    return SUCCESS;
342
0
  }
343
344
0
  ZEND_TRY_ASSIGN_REF_TMP(errors_zv, errors);
345
0
  if (EG(exception)) {
346
0
    return FAILURE;
347
0
  }
348
349
0
  return SUCCESS;
350
0
}
351
352
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri(
353
    INTERNAL_FUNCTION_PARAMETERS, const zend_string *uri_str, const php_uri_object *base_url_object,
354
    bool should_throw, bool should_update_this_object, zval *errors_zv
355
0
) {
356
357
0
  php_uri_object *uri_object;
358
0
  if (should_update_this_object) {
359
0
    uri_object = Z_URI_OBJECT_P(ZEND_THIS);
360
0
    if (uri_object->uri != NULL) {
361
0
      zend_throw_error(NULL, "Cannot modify readonly object of class %s", ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
362
0
      RETURN_THROWS();
363
0
    }
364
0
  } else {
365
0
    if (EX(func)->common.fn_flags & ZEND_ACC_STATIC) {
366
0
      object_init_ex(return_value, Z_CE_P(ZEND_THIS));
367
0
    } else {
368
0
      object_init_ex(return_value, Z_OBJCE_P(ZEND_THIS));
369
0
    }
370
0
    uri_object = Z_URI_OBJECT_P(return_value);
371
0
  }
372
373
0
  const php_uri_parser *uri_parser = uri_object->parser;
374
375
0
  zval errors;
376
0
  ZVAL_UNDEF(&errors);
377
378
0
  void *base_url = NULL;
379
0
  if (base_url_object != NULL) {
380
0
    ZEND_ASSERT(base_url_object->std.ce == uri_object->std.ce);
381
0
    ZEND_ASSERT(base_url_object->uri != NULL);
382
0
    ZEND_ASSERT(base_url_object->parser == uri_parser);
383
0
    base_url = base_url_object->uri;
384
0
  }
385
386
0
  void *uri = uri_parser->parse(ZSTR_VAL(uri_str), ZSTR_LEN(uri_str), base_url, errors_zv != NULL ? &errors : NULL, !should_throw);
387
0
  if (UNEXPECTED(uri == NULL)) {
388
0
    if (should_throw) {
389
0
      zval_ptr_dtor(&errors);
390
0
      RETURN_THROWS();
391
0
    } else {
392
0
      if (pass_errors_by_ref_and_free(errors_zv, &errors) == FAILURE) {
393
0
        RETURN_THROWS();
394
0
      }
395
0
      zval_ptr_dtor(return_value);
396
0
      RETURN_NULL();
397
0
    }
398
0
  }
399
400
0
  if (pass_errors_by_ref_and_free(errors_zv, &errors) == FAILURE) {
401
0
    uri_parser->destroy(uri);
402
0
    RETURN_THROWS();
403
0
  }
404
405
0
  uri_object->uri = uri;
406
0
}
407
408
static void create_rfc3986_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor)
409
4
{
410
4
  zend_string *uri_str;
411
4
  zend_object *base_url_object = NULL;
412
413
8
  ZEND_PARSE_PARAMETERS_START(1, 2)
414
8
    Z_PARAM_STR(uri_str)
415
0
    Z_PARAM_OPTIONAL
416
0
    Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, php_uri_ce_rfc3986_uri)
417
4
  ZEND_PARSE_PARAMETERS_END();
418
419
0
  php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU,
420
0
    uri_str, base_url_object ? php_uri_object_from_obj(base_url_object) : NULL, is_constructor, is_constructor, NULL);
421
0
}
422
423
static bool is_list_of_whatwg_validation_errors(const HashTable *array)
424
0
{
425
0
  if (!zend_array_is_list(array)) {
426
0
    return false;
427
0
  }
428
429
0
  ZEND_HASH_FOREACH_VAL(array, zval *val) {
430
    /* Do not allow references as they may change types after checking. */
431
432
0
    if (Z_TYPE_P(val) != IS_OBJECT) {
433
0
      return false;
434
0
    }
435
436
0
    if (!instanceof_function(Z_OBJCE_P(val), php_uri_ce_whatwg_url_validation_error)) {
437
0
      return false;
438
0
    }
439
0
  } ZEND_HASH_FOREACH_END();
440
441
0
  return true;
442
0
}
443
444
PHP_METHOD(Uri_Rfc3986_Uri, parse)
445
0
{
446
0
  create_rfc3986_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
447
0
}
448
449
PHP_METHOD(Uri_Rfc3986_Uri, __construct)
450
4
{
451
4
  create_rfc3986_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
452
4
}
453
454
PHP_METHOD(Uri_WhatWg_InvalidUrlException, __construct)
455
4
{
456
4
  zend_string *message = NULL;
457
4
  zval *errors = NULL;
458
4
  zend_long code = 0;
459
4
  zval *previous = NULL;
460
461
12
  ZEND_PARSE_PARAMETERS_START(0, 4)
462
12
    Z_PARAM_OPTIONAL
463
12
    Z_PARAM_STR(message)
464
0
    Z_PARAM_ARRAY(errors)
465
0
    Z_PARAM_LONG(code)
466
0
    Z_PARAM_OBJECT_OF_CLASS_OR_NULL(previous, zend_ce_throwable)
467
4
  ZEND_PARSE_PARAMETERS_END();
468
469
4
  if (zend_update_exception_properties(INTERNAL_FUNCTION_PARAM_PASSTHRU, message, code, previous) == FAILURE) {
470
0
    RETURN_THROWS();
471
0
  }
472
473
4
  if (errors == NULL) {
474
4
    zval tmp;
475
4
    ZVAL_EMPTY_ARRAY(&tmp);
476
4
    zend_update_property(php_uri_ce_whatwg_invalid_url_exception, Z_OBJ_P(ZEND_THIS), ZEND_STRL("errors"), &tmp);
477
4
  } else {
478
0
    if (!is_list_of_whatwg_validation_errors(Z_ARR_P(errors))) {
479
0
      zend_argument_value_error(2, "must be a list of %s", ZSTR_VAL(php_uri_ce_whatwg_url_validation_error->name));
480
0
      RETURN_THROWS();
481
0
    }
482
483
0
    zend_update_property(php_uri_ce_whatwg_invalid_url_exception, Z_OBJ_P(ZEND_THIS), ZEND_STRL("errors"), errors);
484
0
  }
485
4
  if (EG(exception)) {
486
0
    RETURN_THROWS();
487
0
  }
488
4
}
489
490
PHP_METHOD(Uri_WhatWg_UrlValidationError, __construct)
491
4
{
492
4
  zend_string *context;
493
4
  zval *type;
494
4
  bool failure;
495
496
8
  ZEND_PARSE_PARAMETERS_START(3, 3)
497
8
    Z_PARAM_STR(context)
498
0
    Z_PARAM_OBJECT_OF_CLASS(type, php_uri_ce_whatwg_url_validation_error_type)
499
0
    Z_PARAM_BOOL(failure)
500
4
  ZEND_PARSE_PARAMETERS_END();
501
502
0
  zend_update_property_str(php_uri_ce_whatwg_url_validation_error, Z_OBJ_P(ZEND_THIS), ZEND_STRL("context"), context);
503
0
  if (EG(exception)) {
504
0
    RETURN_THROWS();
505
0
  }
506
507
0
  zend_update_property_ex(php_uri_ce_whatwg_url_validation_error, Z_OBJ_P(ZEND_THIS), ZSTR_KNOWN(ZEND_STR_TYPE), type);
508
0
  if (EG(exception)) {
509
0
    RETURN_THROWS();
510
0
  }
511
512
0
  zval failure_zv;
513
0
  ZVAL_BOOL(&failure_zv, failure);
514
0
  zend_update_property(php_uri_ce_whatwg_url_validation_error, Z_OBJ_P(ZEND_THIS), ZEND_STRL("failure"), &failure_zv);
515
0
  if (EG(exception)) {
516
0
    RETURN_THROWS();
517
0
  }
518
0
}
519
520
static void create_whatwg_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor)
521
4
{
522
4
  zend_string *uri_str;
523
4
  zend_object *base_url_object = NULL;
524
4
  zval *errors = NULL;
525
526
8
  ZEND_PARSE_PARAMETERS_START(1, 3)
527
8
    Z_PARAM_STR(uri_str)
528
0
    Z_PARAM_OPTIONAL
529
0
    Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, php_uri_ce_whatwg_url)
530
0
    Z_PARAM_ZVAL(errors)
531
4
  ZEND_PARSE_PARAMETERS_END();
532
533
0
  php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU,
534
0
    uri_str, base_url_object ? php_uri_object_from_obj(base_url_object) : NULL, is_constructor, is_constructor, errors);
535
0
}
536
537
PHP_METHOD(Uri_WhatWg_Url, parse)
538
0
{
539
0
  create_whatwg_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
540
0
}
541
542
PHP_METHOD(Uri_WhatWg_Url, __construct)
543
4
{
544
4
  create_whatwg_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
545
4
}
546
547
PHP_METHOD(Uri_Rfc3986_Uri, getUriType)
548
0
{
549
0
  ZEND_PARSE_PARAMETERS_NONE();
550
551
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
552
0
  ZEND_ASSERT(uri_object->uri != NULL);
553
554
0
  php_uri_parser_rfc3986_uri_type_read(uri_object->uri, return_value);
555
0
}
556
557
PHP_METHOD(Uri_Rfc3986_Uri, getScheme)
558
0
{
559
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
560
0
}
561
562
PHP_METHOD(Uri_Rfc3986_Uri, getRawScheme)
563
0
{
564
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME, PHP_URI_COMPONENT_READ_MODE_RAW);
565
0
}
566
567
PHP_METHOD(Uri_Rfc3986_Uri, withScheme)
568
0
{
569
0
  php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME);
570
0
}
571
572
static void rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAMETERS, php_uri_component_read_mode read_mode)
573
0
{
574
0
  ZEND_PARSE_PARAMETERS_NONE();
575
576
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
577
0
  ZEND_ASSERT(uri_object->uri != NULL);
578
579
0
  if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_read(uri_object->uri, read_mode, return_value) == FAILURE)) {
580
0
    zend_throw_error(NULL, "The userinfo component cannot be retrieved");
581
0
    RETURN_THROWS();
582
0
  }
583
0
}
584
585
PHP_METHOD(Uri_Rfc3986_Uri, getUserInfo)
586
0
{
587
0
  rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
588
0
}
589
590
PHP_METHOD(Uri_Rfc3986_Uri, getRawUserInfo)
591
0
{
592
0
  rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_COMPONENT_READ_MODE_RAW);
593
0
}
594
595
PHP_METHOD(Uri_Rfc3986_Uri, withUserInfo)
596
0
{
597
0
  zend_string *value;
598
599
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
600
0
    Z_PARAM_STR_OR_NULL(value)
601
0
  ZEND_PARSE_PARAMETERS_END();
602
603
0
  zval zv;
604
0
  if (value == NULL) {
605
0
    ZVAL_NULL(&zv);
606
0
  } else {
607
0
    ZVAL_STR(&zv, value);
608
0
  }
609
610
0
  php_uri_object *old_uri_object = php_uri_object_from_obj(Z_OBJ_P(ZEND_THIS));
611
0
  ZEND_ASSERT(old_uri_object->uri != NULL);
612
613
0
  zend_object *new_object = old_uri_object->std.handlers->clone_obj(&old_uri_object->std);
614
0
  if (new_object == NULL) {
615
0
    RETURN_THROWS();
616
0
  }
617
618
  /* Assign the object early. The engine will take care of destruction in
619
   * case of an exception being thrown. */
620
0
  RETVAL_OBJ(new_object);
621
622
0
  php_uri_object *new_uri_object = php_uri_object_from_obj(new_object);
623
0
  ZEND_ASSERT(new_uri_object->uri != NULL);
624
625
0
  if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_write(new_uri_object->uri, &zv, NULL) == FAILURE)) {
626
0
    RETURN_THROWS();
627
0
  }
628
0
}
629
630
PHP_METHOD(Uri_Rfc3986_Uri, getUsername)
631
0
{
632
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_USERNAME, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
633
0
}
634
635
PHP_METHOD(Uri_Rfc3986_Uri, getRawUsername)
636
0
{
637
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_USERNAME, PHP_URI_COMPONENT_READ_MODE_RAW);
638
0
}
639
640
PHP_METHOD(Uri_Rfc3986_Uri, getPassword)
641
0
{
642
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PASSWORD, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
643
0
}
644
645
PHP_METHOD(Uri_Rfc3986_Uri, getRawPassword)
646
0
{
647
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PASSWORD, PHP_URI_COMPONENT_READ_MODE_RAW);
648
0
}
649
650
PHP_METHOD(Uri_Rfc3986_Uri, getHost)
651
0
{
652
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
653
0
}
654
655
PHP_METHOD(Uri_Rfc3986_Uri, getRawHost)
656
0
{
657
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_RAW);
658
0
}
659
660
PHP_METHOD(Uri_Rfc3986_Uri, getHostType)
661
0
{
662
0
  ZEND_PARSE_PARAMETERS_NONE();
663
664
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
665
0
  ZEND_ASSERT(uri_object->uri != NULL);
666
667
0
  php_uri_parser_rfc3986_host_type_read(uri_object->uri, return_value);
668
0
}
669
670
PHP_METHOD(Uri_Rfc3986_Uri, withHost)
671
0
{
672
0
  php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST);
673
0
}
674
675
PHP_METHOD(Uri_Rfc3986_Uri, getPort)
676
0
{
677
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PORT, PHP_URI_COMPONENT_READ_MODE_RAW);
678
0
}
679
680
PHP_METHOD(Uri_Rfc3986_Uri, withPort)
681
0
{
682
0
  php_uri_property_write_long_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PORT);
683
0
}
684
685
PHP_METHOD(Uri_Rfc3986_Uri, getPath)
686
0
{
687
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PATH, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
688
0
}
689
690
PHP_METHOD(Uri_Rfc3986_Uri, getRawPath)
691
0
{
692
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PATH, PHP_URI_COMPONENT_READ_MODE_RAW);
693
0
}
694
695
PHP_METHOD(Uri_Rfc3986_Uri, withPath)
696
0
{
697
0
  php_uri_property_write_str_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PATH);
698
0
}
699
700
PHP_METHOD(Uri_Rfc3986_Uri, getQuery)
701
0
{
702
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_QUERY, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
703
0
}
704
705
PHP_METHOD(Uri_Rfc3986_Uri, getRawQuery)
706
0
{
707
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_QUERY, PHP_URI_COMPONENT_READ_MODE_RAW);
708
0
}
709
710
PHP_METHOD(Uri_Rfc3986_Uri, withQuery)
711
0
{
712
0
  php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_QUERY);
713
0
}
714
715
PHP_METHOD(Uri_Rfc3986_Uri, getFragment)
716
0
{
717
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
718
0
}
719
720
PHP_METHOD(Uri_Rfc3986_Uri, getRawFragment)
721
0
{
722
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT, PHP_URI_COMPONENT_READ_MODE_RAW);
723
0
}
724
725
PHP_METHOD(Uri_Rfc3986_Uri, withFragment)
726
0
{
727
0
  php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT);
728
0
}
729
730
static void throw_cannot_recompose_uri_to_string(php_uri_object *object)
731
0
{
732
0
  zend_throw_exception_ex(php_uri_ce_error, 0, "Cannot recompose %s to a string", ZSTR_VAL(object->std.ce->name));
733
0
}
734
735
static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, php_uri_object *that_object, zend_enum_Uri_UriComparisonMode comparison_mode)
736
0
{
737
0
  php_uri_object *this_object = Z_URI_OBJECT_P(ZEND_THIS);
738
0
  ZEND_ASSERT(this_object->uri != NULL);
739
0
  ZEND_ASSERT(that_object->uri != NULL);
740
741
0
  if (this_object->std.ce != that_object->std.ce &&
742
0
    !instanceof_function(this_object->std.ce, that_object->std.ce) &&
743
0
    !instanceof_function(that_object->std.ce, this_object->std.ce)
744
0
  ) {
745
0
    RETURN_FALSE;
746
0
  }
747
748
0
  bool exclude_fragment = comparison_mode == ZEND_ENUM_Uri_UriComparisonMode_ExcludeFragment;
749
750
0
  zend_string *this_str = this_object->parser->to_string(
751
0
    this_object->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, exclude_fragment);
752
0
  if (this_str == NULL) {
753
0
    throw_cannot_recompose_uri_to_string(this_object);
754
0
    RETURN_THROWS();
755
0
  }
756
757
0
  zend_string *that_str = that_object->parser->to_string(
758
0
    that_object->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, exclude_fragment);
759
0
  if (that_str == NULL) {
760
0
    zend_string_release(this_str);
761
0
    throw_cannot_recompose_uri_to_string(that_object);
762
0
    RETURN_THROWS();
763
0
  }
764
765
0
  RETVAL_BOOL(zend_string_equals(this_str, that_str));
766
767
0
  zend_string_release(this_str);
768
0
  zend_string_release(that_str);
769
0
}
770
771
PHP_METHOD(Uri_Rfc3986_Uri, equals)
772
0
{
773
0
  zend_object *that_object;
774
0
  zend_enum_Uri_UriComparisonMode comparison_mode = ZEND_ENUM_Uri_UriComparisonMode_ExcludeFragment;
775
776
0
  ZEND_PARSE_PARAMETERS_START(1, 2)
777
0
    Z_PARAM_OBJ_OF_CLASS(that_object, php_uri_ce_rfc3986_uri)
778
0
    Z_PARAM_OPTIONAL
779
0
    Z_PARAM_ENUM(comparison_mode, php_uri_ce_comparison_mode)
780
0
  ZEND_PARSE_PARAMETERS_END();
781
782
0
  uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_uri_object_from_obj(that_object), comparison_mode);
783
0
}
784
785
PHP_METHOD(Uri_Rfc3986_Uri, toRawString)
786
0
{
787
0
  ZEND_PARSE_PARAMETERS_NONE();
788
789
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
790
0
  ZEND_ASSERT(uri_object->uri != NULL);
791
792
0
  zend_string *uri_str = uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false);
793
0
  if (uri_str == NULL) {
794
0
    throw_cannot_recompose_uri_to_string(uri_object);
795
0
    RETURN_THROWS();
796
0
  }
797
798
0
  RETURN_STR(uri_str);
799
0
}
800
801
PHP_METHOD(Uri_Rfc3986_Uri, toString)
802
0
{
803
0
  ZEND_PARSE_PARAMETERS_NONE();
804
805
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
806
0
  ZEND_ASSERT(uri_object->uri != NULL);
807
808
0
  zend_string *uri_str = uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, false);
809
0
  if (uri_str == NULL) {
810
0
    throw_cannot_recompose_uri_to_string(uri_object);
811
0
    RETURN_THROWS();
812
0
  }
813
814
0
  RETURN_STR(uri_str);
815
0
}
816
817
PHP_METHOD(Uri_Rfc3986_Uri, resolve)
818
0
{
819
0
  zend_string *uri_str;
820
821
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
822
0
    Z_PARAM_STR(uri_str)
823
0
  ZEND_PARSE_PARAMETERS_END();
824
825
0
  php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU,
826
0
    uri_str, Z_URI_OBJECT_P(ZEND_THIS), true, false, NULL);
827
0
}
828
829
PHP_METHOD(Uri_Rfc3986_Uri, __serialize)
830
0
{
831
0
  ZEND_PARSE_PARAMETERS_NONE();
832
833
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
834
0
  ZEND_ASSERT(uri_object->uri != NULL);
835
836
  /* Serialize state: "uri" key in the first array */
837
0
  zend_string *uri_str = uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false);
838
0
  if (uri_str == NULL) {
839
0
    throw_cannot_recompose_uri_to_string(uri_object);
840
0
    RETURN_THROWS();
841
0
  }
842
0
  zval tmp;
843
0
  ZVAL_STR(&tmp, uri_str);
844
845
0
  array_init(return_value);
846
847
0
  zval arr;
848
0
  array_init(&arr);
849
0
  zend_hash_str_add_new(Z_ARRVAL(arr), PHP_URI_SERIALIZE_URI_FIELD_NAME, sizeof(PHP_URI_SERIALIZE_URI_FIELD_NAME) - 1, &tmp);
850
0
  zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr);
851
852
  /* Serialize regular properties: second array */
853
0
  ZVAL_EMPTY_ARRAY(&arr);
854
0
  zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr);
855
0
}
856
857
static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS)
858
8
{
859
8
  HashTable *data;
860
861
24
  ZEND_PARSE_PARAMETERS_START(1, 1)
862
32
    Z_PARAM_ARRAY_HT(data)
863
8
  ZEND_PARSE_PARAMETERS_END();
864
865
8
  php_uri_object *uri_object = php_uri_object_from_obj(Z_OBJ_P(ZEND_THIS));
866
8
  if (uri_object->uri != NULL) {
867
    /* Intentionally throw two exceptions for proper chaining. */
868
0
    zend_throw_error(NULL, "Cannot modify readonly object of class %s", ZSTR_VAL(uri_object->std.ce->name));
869
0
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
870
0
    RETURN_THROWS();
871
0
  }
872
873
  /* Verify the expected number of elements, this implicitly ensures that no additional elements are present. */
874
8
  if (zend_hash_num_elements(data) != 2) {
875
6
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
876
6
    RETURN_THROWS();
877
6
  }
878
879
  /* Unserialize state: "uri" key in the first array */
880
2
  zval *arr = zend_hash_index_find(data, 0);
881
2
  if (arr == NULL || Z_TYPE_P(arr) != IS_ARRAY) {
882
2
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
883
2
    RETURN_THROWS();
884
2
  }
885
886
  /* Verify the expected number of elements inside the first array, this implicitly ensures that no additional elements are present. */
887
0
  if (zend_hash_num_elements(Z_ARRVAL_P(arr)) != 1) {
888
0
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
889
0
    RETURN_THROWS();
890
0
  }
891
892
0
  zval *uri_zv = zend_hash_str_find(Z_ARRVAL_P(arr), ZEND_STRL(PHP_URI_SERIALIZE_URI_FIELD_NAME));
893
0
  if (uri_zv == NULL || Z_TYPE_P(uri_zv) != IS_STRING) {
894
0
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
895
0
    RETURN_THROWS();
896
0
  }
897
898
0
  uri_object->uri = uri_object->parser->parse(Z_STRVAL_P(uri_zv), Z_STRLEN_P(uri_zv), NULL, NULL, true);
899
0
  if (uri_object->uri == NULL) {
900
0
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
901
0
    RETURN_THROWS();
902
0
  }
903
904
  /* Unserialize regular properties: second array */
905
0
  arr = zend_hash_index_find(data, 1);
906
0
  if (arr == NULL || Z_TYPE_P(arr) != IS_ARRAY) {
907
0
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
908
0
    RETURN_THROWS();
909
0
  }
910
911
  /* Verify that there is no regular property in the second array, because the URI classes have no properties and they are final. */
912
0
  if (zend_hash_num_elements(Z_ARRVAL_P(arr)) > 0) {
913
0
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
914
0
    RETURN_THROWS();
915
0
  }
916
0
}
917
918
PHP_METHOD(Uri_Rfc3986_Uri, __unserialize)
919
2
{
920
2
  uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU);
921
2
}
922
923
PHP_METHOD(Uri_Rfc3986_Uri, __debugInfo)
924
0
{
925
0
  ZEND_PARSE_PARAMETERS_NONE();
926
927
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
928
929
0
  RETURN_ARR(uri_get_debug_properties(uri_object));
930
0
}
931
932
PHP_METHOD(Uri_WhatWg_Url, getScheme)
933
0
{
934
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
935
0
}
936
937
PHP_METHOD(Uri_WhatWg_Url, withScheme)
938
0
{
939
0
  php_uri_property_write_str_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME);
940
0
}
941
942
PHP_METHOD(Uri_WhatWg_Url, isSpecialScheme)
943
0
{
944
0
  ZEND_PARSE_PARAMETERS_NONE();
945
946
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
947
0
  ZEND_ASSERT(uri_object->uri != NULL);
948
949
0
  RETVAL_BOOL(php_uri_parser_whatwg_is_special(uri_object->uri));
950
0
}
951
952
PHP_METHOD(Uri_WhatWg_Url, withUsername)
953
0
{
954
0
  php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_USERNAME);
955
0
}
956
957
PHP_METHOD(Uri_WhatWg_Url, withPassword)
958
0
{
959
0
  php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PASSWORD);
960
0
}
961
962
PHP_METHOD(Uri_WhatWg_Url, getAsciiHost)
963
0
{
964
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
965
0
}
966
967
PHP_METHOD(Uri_WhatWg_Url, getUnicodeHost)
968
0
{
969
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE);
970
0
}
971
972
PHP_METHOD(Uri_WhatWg_Url, getHostType)
973
0
{
974
0
  ZEND_PARSE_PARAMETERS_NONE();
975
976
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
977
0
  ZEND_ASSERT(uri_object->uri != NULL);
978
979
0
  php_uri_parser_whatwg_host_type_read(uri_object->uri, return_value);
980
0
}
981
982
PHP_METHOD(Uri_WhatWg_Url, equals)
983
0
{
984
0
  zend_object *that_object;
985
0
  zend_enum_Uri_UriComparisonMode comparison_mode = ZEND_ENUM_Uri_UriComparisonMode_ExcludeFragment;
986
987
0
  ZEND_PARSE_PARAMETERS_START(1, 2)
988
0
    Z_PARAM_OBJ_OF_CLASS(that_object, php_uri_ce_whatwg_url)
989
0
    Z_PARAM_OPTIONAL
990
0
    Z_PARAM_ENUM(comparison_mode, php_uri_ce_comparison_mode)
991
0
  ZEND_PARSE_PARAMETERS_END();
992
993
0
  uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_uri_object_from_obj(that_object), comparison_mode);
994
0
}
995
996
PHP_METHOD(Uri_WhatWg_Url, toUnicodeString)
997
0
{
998
0
  ZEND_PARSE_PARAMETERS_NONE();
999
1000
0
  zend_object *this_object = Z_OBJ_P(ZEND_THIS);
1001
0
  php_uri_object *uri_object = php_uri_object_from_obj(this_object);
1002
0
  ZEND_ASSERT(uri_object->uri != NULL);
1003
1004
0
  RETURN_STR(uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_UNICODE, false));
1005
0
}
1006
1007
PHP_METHOD(Uri_WhatWg_Url, toAsciiString)
1008
0
{
1009
0
  ZEND_PARSE_PARAMETERS_NONE();
1010
1011
0
  zend_object *this_object = Z_OBJ_P(ZEND_THIS);
1012
0
  php_uri_object *uri_object = php_uri_object_from_obj(this_object);
1013
0
  ZEND_ASSERT(uri_object->uri != NULL);
1014
1015
0
  RETURN_STR(uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false));
1016
0
}
1017
1018
PHP_METHOD(Uri_WhatWg_Url, resolve)
1019
0
{
1020
0
  zend_string *uri_str;
1021
0
  zval *errors = NULL;
1022
1023
0
  ZEND_PARSE_PARAMETERS_START(1, 2)
1024
0
    Z_PARAM_STR(uri_str)
1025
0
    Z_PARAM_OPTIONAL
1026
0
    Z_PARAM_ZVAL(errors)
1027
0
  ZEND_PARSE_PARAMETERS_END();
1028
1029
0
  php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU,
1030
0
    uri_str, Z_URI_OBJECT_P(ZEND_THIS), true, false, errors);
1031
0
}
1032
1033
PHP_METHOD(Uri_WhatWg_Url, __serialize)
1034
0
{
1035
0
  ZEND_PARSE_PARAMETERS_NONE();
1036
1037
0
  php_uri_object *this_object = Z_URI_OBJECT_P(ZEND_THIS);
1038
0
  ZEND_ASSERT(this_object->uri != NULL);
1039
1040
  /* Serialize state: "uri" key in the first array */
1041
0
  zend_string *uri_str = this_object->parser->to_string(this_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false);
1042
0
  if (uri_str == NULL) {
1043
0
    throw_cannot_recompose_uri_to_string(this_object);
1044
0
    RETURN_THROWS();
1045
0
  }
1046
0
  zval tmp;
1047
0
  ZVAL_STR(&tmp, uri_str);
1048
1049
0
  array_init(return_value);
1050
1051
0
  zval arr;
1052
0
  array_init(&arr);
1053
0
  zend_hash_str_add_new(Z_ARRVAL(arr), ZEND_STRL(PHP_URI_SERIALIZE_URI_FIELD_NAME), &tmp);
1054
0
  zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr);
1055
1056
  /* Serialize regular properties: second array */
1057
0
  ZVAL_EMPTY_ARRAY(&arr);
1058
0
  zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr);
1059
0
}
1060
1061
PHP_METHOD(Uri_WhatWg_Url, __unserialize)
1062
6
{
1063
6
  uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU);
1064
6
}
1065
1066
PHP_METHOD(Uri_WhatWg_Url, __debugInfo)
1067
0
{
1068
0
  ZEND_PARSE_PARAMETERS_NONE();
1069
1070
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
1071
1072
0
  RETURN_ARR(uri_get_debug_properties(uri_object));
1073
0
}
1074
1075
PHP_FUNCTION(Uri_WhatWg_url_percent_encode)
1076
0
{
1077
0
  zend_string *input;
1078
0
  zend_enum_Uri_WhatWg_UrlPercentEncodingMode mode;
1079
1080
0
  ZEND_PARSE_PARAMETERS_START(2, 2)
1081
0
    Z_PARAM_STR(input)
1082
0
    Z_PARAM_ENUM(mode, php_uri_ce_whatwg_url_percent_encoding_mode)
1083
0
  ZEND_PARSE_PARAMETERS_END();
1084
1085
0
  zend_string *str;
1086
1087
0
  switch (mode) {
1088
0
    case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Username:
1089
0
      ZEND_FALLTHROUGH;
1090
0
    case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Password:
1091
0
      str = php_uri_parser_whatwg_userinfo_percent_encode(ZSTR_VAL(input), ZSTR_LEN(input));
1092
0
      break;
1093
0
    case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_OpaqueHost:
1094
0
      str = php_uri_parser_whatwg_opaque_host_percent_encode(ZSTR_VAL(input), ZSTR_LEN(input));
1095
0
      break;
1096
0
    case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Path:
1097
0
      str = php_uri_parser_whatwg_path_percent_encode(ZSTR_VAL(input), ZSTR_LEN(input));
1098
0
      break;
1099
0
    case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_OpaquePath:
1100
0
      str = php_uri_parser_whatwg_opaque_path_percent_encode(ZSTR_VAL(input), ZSTR_LEN(input));
1101
0
      break;
1102
0
    case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_PathSegment:
1103
0
      str = php_uri_parser_whatwg_path_segment_percent_encode(ZSTR_VAL(input), ZSTR_LEN(input));
1104
0
      break;
1105
0
    case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Query:
1106
0
      str = php_uri_parser_whatwg_query_percent_encode(ZSTR_VAL(input), ZSTR_LEN(input));
1107
0
      break;
1108
0
    case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_SpecialQuery:
1109
0
      str = php_uri_parser_whatwg_special_query_percent_encode(ZSTR_VAL(input), ZSTR_LEN(input));
1110
0
      break;
1111
0
    case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_FormQuery:
1112
0
      str = php_uri_parser_whatwg_form_query_percent_encode(ZSTR_VAL(input), ZSTR_LEN(input));
1113
0
      break;
1114
0
    case ZEND_ENUM_Uri_WhatWg_UrlPercentEncodingMode_Fragment:
1115
0
      str = php_uri_parser_whatwg_fragment_percent_encode(ZSTR_VAL(input), ZSTR_LEN(input));
1116
0
      break;
1117
0
    default: ZEND_UNREACHABLE();
1118
0
  }
1119
1120
  /* This should be unreachable in practice, as str is null only due to memory errors. */
1121
0
  if (str == NULL) {
1122
0
    zend_throw_exception(php_uri_ce_error, "Cannot percent-encode input", 0);
1123
0
    RETURN_THROWS();
1124
0
  }
1125
1126
0
  RETURN_NEW_STR(str);
1127
0
}
1128
1129
PHP_METHOD(Uri_Rfc3986_UriBuilder, reset)
1130
0
{
1131
0
  ZEND_PARSE_PARAMETERS_NONE();
1132
1133
0
  zend_object *object = Z_OBJ_P(ZEND_THIS);
1134
0
  zval *property = object->properties_table;
1135
0
  const zval *end = property + object->ce->default_properties_count;
1136
1137
0
  while (property != end) {
1138
0
    zend_object_dtor_property(object, property);
1139
0
    ZVAL_NULL(property);
1140
0
    property++;
1141
0
  }
1142
1143
0
  ZVAL_EMPTY_STRING(Z_RFC3986_URI_PROP_PATH_P(ZEND_THIS));
1144
1145
0
  RETVAL_COPY(ZEND_THIS);
1146
0
}
1147
1148
ZEND_ATTRIBUTE_NONNULL static void php_uri_builder_set_component_string(
1149
  INTERNAL_FUNCTION_PARAMETERS, const char *name, const size_t name_length,
1150
  const php_uri_component_validator_string validator
1151
0
) {
1152
0
  zend_string *component;
1153
1154
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
1155
0
    Z_PARAM_STR(component)
1156
0
  ZEND_PARSE_PARAMETERS_END();
1157
1158
0
  if (validator(component) == FAILURE) {
1159
0
    RETURN_THROWS();
1160
0
  }
1161
1162
0
  zend_update_property_str(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), name, name_length, component);
1163
1164
0
  RETVAL_COPY(ZEND_THIS);
1165
0
}
1166
1167
ZEND_ATTRIBUTE_NONNULL static void php_uri_builder_set_component_string_or_null(
1168
  INTERNAL_FUNCTION_PARAMETERS, const char *name, const size_t name_length,
1169
  const php_uri_component_validator_string validator
1170
0
) {
1171
0
  zend_string *component;
1172
1173
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
1174
0
    Z_PARAM_STR_OR_NULL(component)
1175
0
  ZEND_PARSE_PARAMETERS_END();
1176
1177
0
  if (component == NULL) {
1178
0
    zend_update_property_null(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), name, name_length);
1179
0
  } else {
1180
0
    if (validator(component) == FAILURE) {
1181
0
      RETURN_THROWS();
1182
0
    }
1183
1184
0
    zend_update_property_str(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), name, name_length, component);
1185
0
  }
1186
1187
0
  RETVAL_COPY(ZEND_THIS);
1188
0
}
1189
1190
ZEND_ATTRIBUTE_NONNULL_ARGS(1) static void php_uri_builder_set_component_long_or_null(
1191
  INTERNAL_FUNCTION_PARAMETERS, const char *name, const size_t name_length,
1192
  const php_uri_component_validator_long validator
1193
0
) {
1194
0
  zend_long component;
1195
0
  bool component_is_null;
1196
1197
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
1198
0
    Z_PARAM_LONG_OR_NULL(component, component_is_null)
1199
0
  ZEND_PARSE_PARAMETERS_END();
1200
1201
0
  if (component_is_null) {
1202
0
    zend_update_property_null(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), name, name_length);
1203
0
  } else {
1204
0
    if (validator(component) == FAILURE) {
1205
0
      RETURN_THROWS();
1206
0
    }
1207
1208
0
    zend_update_property_long(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), name, name_length, component);
1209
0
  }
1210
1211
0
  RETVAL_COPY(ZEND_THIS);
1212
0
}
1213
1214
PHP_METHOD(Uri_Rfc3986_UriBuilder, setScheme)
1215
0
{
1216
0
  php_uri_builder_set_component_string_or_null(
1217
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1218
0
    ZEND_STRL("scheme"),
1219
0
    php_uri_parser_rfc3986_scheme_validate
1220
0
  );
1221
0
}
1222
1223
PHP_METHOD(Uri_Rfc3986_UriBuilder, setUserInfo)
1224
0
{
1225
0
  php_uri_builder_set_component_string_or_null(
1226
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1227
0
    ZEND_STRL("userinfo"),
1228
0
    php_uri_parser_rfc3986_userinfo_validate
1229
0
  );
1230
0
}
1231
1232
PHP_METHOD(Uri_Rfc3986_UriBuilder, setHost)
1233
0
{
1234
0
  php_uri_builder_set_component_string_or_null(
1235
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1236
0
    ZEND_STRL("host"),
1237
0
    php_uri_parser_rfc3986_host_validate
1238
0
  );
1239
0
}
1240
1241
PHP_METHOD(Uri_Rfc3986_UriBuilder, setPort)
1242
0
{
1243
0
  php_uri_builder_set_component_long_or_null(
1244
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1245
0
    ZEND_STRL("port"),
1246
0
    php_uri_parser_rfc3986_port_validate
1247
0
  );
1248
0
}
1249
1250
PHP_METHOD(Uri_Rfc3986_UriBuilder, setPath)
1251
0
{
1252
0
  php_uri_builder_set_component_string(
1253
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1254
0
    ZEND_STRL("path"),
1255
0
    php_uri_parser_rfc3986_path_validate
1256
0
  );
1257
0
}
1258
1259
PHP_METHOD(Uri_Rfc3986_UriBuilder, setQuery)
1260
0
{
1261
0
  php_uri_builder_set_component_string_or_null(
1262
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1263
0
    ZEND_STRL("query"),
1264
0
    php_uri_parser_rfc3986_query_validate
1265
0
  );
1266
0
}
1267
1268
PHP_METHOD(Uri_Rfc3986_UriBuilder, setFragment)
1269
0
{
1270
0
  php_uri_builder_set_component_string_or_null(
1271
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1272
0
    ZEND_STRL("fragment"),
1273
0
    php_uri_parser_rfc3986_fragment_validate
1274
0
  );
1275
0
}
1276
1277
PHP_METHOD(Uri_Rfc3986_UriBuilder, build)
1278
0
{
1279
0
  zval *base_url = NULL;
1280
1281
0
  ZEND_PARSE_PARAMETERS_START(0, 1)
1282
0
    Z_PARAM_OPTIONAL
1283
0
    Z_PARAM_OBJECT_OF_CLASS_OR_NULL(base_url, php_uri_ce_rfc3986_uri)
1284
0
  ZEND_PARSE_PARAMETERS_END();
1285
1286
0
  const zval *scheme = Z_RFC3986_URI_PROP_SCHEME_DEREF_P(ZEND_THIS);
1287
0
  const zval *userinfo = Z_RFC3986_URI_PROP_USERINFO_DEREF_P(ZEND_THIS);
1288
0
  const zval *host = Z_RFC3986_URI_PROP_HOST_DEREF_P(ZEND_THIS);
1289
0
  const zval *port = Z_RFC3986_URI_PROP_PORT_DEREF_P(ZEND_THIS);
1290
0
  const zval *path = Z_RFC3986_URI_PROP_PATH_DEREF_P(ZEND_THIS);
1291
0
  const zval *query = Z_RFC3986_URI_PROP_QUERY_DEREF_P(ZEND_THIS);
1292
0
  const zval *fragment = Z_RFC3986_URI_PROP_FRAGMENT_DEREF_P(ZEND_THIS);
1293
1294
0
  php_uri_parser_rfc3986_uris *base_uris = NULL;
1295
0
  if (base_url != NULL) {
1296
0
    base_uris = Z_URI_OBJECT_P(base_url)->uri;
1297
0
  }
1298
1299
0
  php_uri_parser_rfc3986_uris *uriparser_uris = php_uri_parser_rfc3986_build_from_zval(
1300
0
    base_uris, scheme, userinfo, host, port, path, query, fragment
1301
0
  );
1302
0
  if (uriparser_uris == NULL) {
1303
0
    RETURN_THROWS();
1304
0
  }
1305
1306
0
  object_init_ex(return_value, php_uri_ce_rfc3986_uri);
1307
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(return_value);
1308
0
  uri_object->parser = &php_uri_parser_rfc3986;
1309
0
  uri_object->uri = uriparser_uris;
1310
0
}
1311
1312
PHP_METHOD(Uri_WhatWg_UrlBuilder, reset)
1313
0
{
1314
0
  ZEND_PARSE_PARAMETERS_NONE();
1315
1316
0
  zend_object *object = Z_OBJ_P(ZEND_THIS);
1317
0
  zval *property = object->properties_table;
1318
0
  const zval *end = property + object->ce->default_properties_count;
1319
1320
0
  while (property != end) {
1321
0
    zend_object_dtor_property(object, property);
1322
0
    ZVAL_NULL(property);
1323
0
    property++;
1324
0
  }
1325
1326
0
  ZVAL_EMPTY_STRING(Z_WHATWG_URL_PROP_SCHEME_P(ZEND_THIS));
1327
0
  ZVAL_EMPTY_STRING(Z_WHATWG_URL_PROP_PATH_P(ZEND_THIS));
1328
1329
0
  RETVAL_COPY(ZEND_THIS);
1330
0
}
1331
1332
PHP_METHOD(Uri_WhatWg_UrlBuilder, setScheme)
1333
0
{
1334
0
  php_uri_builder_set_component_string(
1335
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1336
0
    ZEND_STRL("scheme"),
1337
0
    php_uri_parser_whatwg_scheme_validate
1338
0
  );
1339
0
}
1340
1341
PHP_METHOD(Uri_WhatWg_UrlBuilder, setUsername)
1342
0
{
1343
0
  php_uri_builder_set_component_string_or_null(
1344
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1345
0
    ZEND_STRL("username"),
1346
0
    php_uri_parser_whatwg_none_validate
1347
0
  );
1348
0
}
1349
1350
PHP_METHOD(Uri_WhatWg_UrlBuilder, setPassword)
1351
0
{
1352
0
  php_uri_builder_set_component_string_or_null(
1353
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1354
0
    ZEND_STRL("password"),
1355
0
    php_uri_parser_whatwg_none_validate
1356
0
  );
1357
0
}
1358
1359
PHP_METHOD(Uri_WhatWg_UrlBuilder, setHost)
1360
0
{
1361
0
  php_uri_builder_set_component_string_or_null(
1362
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1363
0
    ZEND_STRL("host"),
1364
0
    php_uri_parser_whatwg_host_validate
1365
0
  );
1366
0
}
1367
1368
PHP_METHOD(Uri_WhatWg_UrlBuilder, setPort)
1369
0
{
1370
0
  php_uri_builder_set_component_long_or_null(
1371
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1372
0
    ZEND_STRL("port"),
1373
0
    php_uri_parser_whatwg_port_validate
1374
0
  );
1375
0
}
1376
1377
PHP_METHOD(Uri_WhatWg_UrlBuilder, setPath)
1378
0
{
1379
0
  php_uri_builder_set_component_string(
1380
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1381
0
    ZEND_STRL("path"),
1382
0
    php_uri_parser_whatwg_none_validate
1383
0
  );
1384
0
}
1385
1386
PHP_METHOD(Uri_WhatWg_UrlBuilder, setQuery)
1387
0
{
1388
0
  php_uri_builder_set_component_string_or_null(
1389
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1390
0
    ZEND_STRL("query"),
1391
0
    php_uri_parser_whatwg_none_validate
1392
0
  );
1393
0
}
1394
1395
PHP_METHOD(Uri_WhatWg_UrlBuilder, setFragment)
1396
0
{
1397
0
  php_uri_builder_set_component_string_or_null(
1398
0
    INTERNAL_FUNCTION_PARAM_PASSTHRU,
1399
0
    ZEND_STRL("fragment"),
1400
0
    php_uri_parser_whatwg_none_validate
1401
0
  );
1402
0
}
1403
1404
PHP_METHOD(Uri_WhatWg_UrlBuilder, build)
1405
0
{
1406
0
  zval *base_url_zv = NULL;
1407
0
  zval *errors = NULL;
1408
1409
0
  ZEND_PARSE_PARAMETERS_START(0, 2)
1410
0
    Z_PARAM_OPTIONAL
1411
0
    Z_PARAM_OBJECT_OF_CLASS_OR_NULL(base_url_zv, php_uri_ce_whatwg_url)
1412
0
    Z_PARAM_ZVAL(errors)
1413
0
  ZEND_PARSE_PARAMETERS_END();
1414
1415
0
  const zval *scheme = Z_WHATWG_URL_PROP_SCHEME_DEREF_P(ZEND_THIS);
1416
0
  const zval *username = Z_WHATWG_URL_PROP_USERNAME_DEREF_P(ZEND_THIS);
1417
0
  const zval *password = Z_WHATWG_URL_PROP_PASSWORD_DEREF_P(ZEND_THIS);
1418
0
  const zval *host = Z_WHATWG_URL_PROP_HOST_DEREF_P(ZEND_THIS);
1419
0
  const zval *port = Z_WHATWG_URL_PROP_PORT_DEREF_P(ZEND_THIS);
1420
0
  const zval *path = Z_WHATWG_URL_PROP_PATH_DEREF_P(ZEND_THIS);
1421
0
  const zval *query = Z_WHATWG_URL_PROP_QUERY_DEREF_P(ZEND_THIS);
1422
0
  const zval *fragment = Z_WHATWG_URL_PROP_FRAGMENT_DEREF_P(ZEND_THIS);
1423
1424
0
  lxb_url_t *base_url = NULL;
1425
0
  if (base_url_zv != NULL) {
1426
0
    zend_argument_error(NULL, 1, "is not supported yet, and therefore, null must be passed");
1427
0
    RETURN_THROWS();
1428
0
    base_url = Z_URI_OBJECT_P(base_url_zv)->uri;
1429
0
  }
1430
1431
0
  lxb_url_t *lexbor_url = php_uri_parser_whatwg_build_from_zval(
1432
0
    base_url, scheme, username, password, host, port, path, query, fragment,
1433
0
    errors
1434
0
  );
1435
0
  if (lexbor_url == NULL) {
1436
0
    RETURN_THROWS();
1437
0
  }
1438
1439
0
  object_init_ex(return_value, php_uri_ce_whatwg_url);
1440
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(return_value);
1441
0
  uri_object->parser = &php_uri_parser_whatwg;
1442
0
  uri_object->uri = lexbor_url;
1443
0
}
1444
1445
PHPAPI php_uri_object *php_uri_object_create(zend_class_entry *class_type, const php_uri_parser *parser)
1446
83
{
1447
83
  php_uri_object *uri_object = zend_object_alloc(sizeof(*uri_object), class_type);
1448
1449
83
  zend_object_std_init(&uri_object->std, class_type);
1450
83
  object_properties_init(&uri_object->std, class_type);
1451
1452
83
  uri_object->parser = parser;
1453
83
  uri_object->uri = NULL;
1454
1455
83
  return uri_object;
1456
83
}
1457
1458
static zend_object *php_uri_object_create_rfc3986(zend_class_entry *ce)
1459
6
{
1460
6
  return &php_uri_object_create(ce, &php_uri_parser_rfc3986)->std;
1461
6
}
1462
1463
static zend_object *php_uri_object_create_whatwg(zend_class_entry *ce)
1464
77
{
1465
77
  return &php_uri_object_create(ce, &php_uri_parser_whatwg)->std;
1466
77
}
1467
1468
PHPAPI void php_uri_object_handler_free(zend_object *object)
1469
83
{
1470
83
  php_uri_object *uri_object = php_uri_object_from_obj(object);
1471
1472
83
  uri_object->parser->destroy(uri_object->uri);
1473
83
  zend_object_std_dtor(&uri_object->std);
1474
83
}
1475
1476
PHPAPI zend_object *php_uri_object_handler_clone(zend_object *object)
1477
0
{
1478
0
  const php_uri_object *uri_object = php_uri_object_from_obj(object);
1479
1480
0
  ZEND_ASSERT(uri_object->uri != NULL);
1481
1482
0
  php_uri_object *new_uri_object = php_uri_object_from_obj(object->ce->create_object(object->ce));
1483
0
  ZEND_ASSERT(new_uri_object->parser == uri_object->parser);
1484
1485
0
  void *uri = uri_object->parser->clone(uri_object->uri);
1486
0
  ZEND_ASSERT(uri != NULL);
1487
1488
0
  new_uri_object->uri = uri;
1489
1490
0
  zend_objects_clone_members(&new_uri_object->std, &uri_object->std);
1491
1492
0
  return &new_uri_object->std;
1493
0
}
1494
1495
PHPAPI zend_result php_uri_parser_register(const php_uri_parser *uri_parser)
1496
48
{
1497
48
  zend_string *key = zend_string_init_interned(uri_parser->name, strlen(uri_parser->name), true);
1498
1499
48
  ZEND_ASSERT(uri_parser->name != NULL);
1500
48
  ZEND_ASSERT(uri_parser->parse != NULL);
1501
48
  ZEND_ASSERT(uri_parser->clone != NULL || strcmp(uri_parser->name, PHP_URI_PARSER_PHP_PARSE_URL) == 0);
1502
48
  ZEND_ASSERT(uri_parser->to_string != NULL || strcmp(uri_parser->name, PHP_URI_PARSER_PHP_PARSE_URL) == 0);
1503
48
  ZEND_ASSERT(uri_parser->destroy != NULL);
1504
1505
48
  zend_result result = zend_hash_add_ptr(&uri_parsers, key, (void *) uri_parser) != NULL ? SUCCESS : FAILURE;
1506
1507
48
  zend_string_release_ex(key, true);
1508
1509
48
  return result;
1510
48
}
1511
1512
static PHP_MINIT_FUNCTION(uri)
1513
16
{
1514
16
  php_uri_ce_rfc3986_uri_builder = register_class_Uri_Rfc3986_UriBuilder();
1515
1516
16
  php_uri_ce_rfc3986_uri = register_class_Uri_Rfc3986_Uri();
1517
16
  php_uri_ce_rfc3986_uri->create_object = php_uri_object_create_rfc3986;
1518
16
  php_uri_ce_rfc3986_uri->default_object_handlers = &object_handlers_rfc3986_uri;
1519
16
  memcpy(&object_handlers_rfc3986_uri, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1520
16
  object_handlers_rfc3986_uri.offset = offsetof(php_uri_object, std);
1521
16
  object_handlers_rfc3986_uri.free_obj = php_uri_object_handler_free;
1522
16
  object_handlers_rfc3986_uri.clone_obj = php_uri_object_handler_clone;
1523
1524
16
  php_uri_ce_rfc3986_uri_type = register_class_Uri_Rfc3986_UriType();
1525
16
  php_uri_ce_rfc3986_uri_host_type = register_class_Uri_Rfc3986_UriHostType();
1526
1527
16
  php_uri_ce_whatwg_url_builder = register_class_Uri_WhatWg_UrlBuilder();
1528
1529
16
  php_uri_ce_whatwg_url = register_class_Uri_WhatWg_Url();
1530
16
  php_uri_ce_whatwg_url->create_object = php_uri_object_create_whatwg;
1531
16
  php_uri_ce_whatwg_url->default_object_handlers = &object_handlers_whatwg_uri;
1532
16
  memcpy(&object_handlers_whatwg_uri, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1533
16
  object_handlers_whatwg_uri.offset = offsetof(php_uri_object, std);
1534
16
  object_handlers_whatwg_uri.free_obj = php_uri_object_handler_free;
1535
16
  object_handlers_whatwg_uri.clone_obj = php_uri_object_handler_clone;
1536
1537
16
  php_uri_ce_whatwg_url_percent_encoding_mode = register_class_Uri_WhatWg_UrlPercentEncodingMode();
1538
1539
16
  php_uri_ce_comparison_mode = register_class_Uri_UriComparisonMode();
1540
16
  php_uri_ce_exception = register_class_Uri_UriException(zend_ce_exception);
1541
16
  php_uri_ce_error = register_class_Uri_UriError(zend_ce_error);
1542
16
  php_uri_ce_invalid_uri_exception = register_class_Uri_InvalidUriException(php_uri_ce_exception);
1543
16
  php_uri_ce_whatwg_invalid_url_exception = register_class_Uri_WhatWg_InvalidUrlException(php_uri_ce_invalid_uri_exception);
1544
16
  php_uri_ce_whatwg_url_host_type = register_class_Uri_WhatWg_UrlHostType();
1545
16
  php_uri_ce_whatwg_url_validation_error = register_class_Uri_WhatWg_UrlValidationError();
1546
16
  php_uri_ce_whatwg_url_validation_error_type = register_class_Uri_WhatWg_UrlValidationErrorType();
1547
1548
16
  zend_hash_init(&uri_parsers, 4, NULL, NULL, true);
1549
1550
16
  if (php_uri_parser_register(&php_uri_parser_rfc3986) == FAILURE) {
1551
0
    return FAILURE;
1552
0
  }
1553
1554
16
  if (php_uri_parser_register(&php_uri_parser_whatwg) == FAILURE) {
1555
0
    return FAILURE;
1556
0
  }
1557
1558
16
  if (php_uri_parser_register(&php_uri_parser_php_parse_url) == FAILURE) {
1559
0
    return FAILURE;
1560
0
  }
1561
1562
16
  return SUCCESS;
1563
16
}
1564
1565
static PHP_MINFO_FUNCTION(uri)
1566
8
{
1567
8
  php_info_print_table_start();
1568
8
  php_info_print_table_row(2, "URI support", "active");
1569
8
#ifdef URI_STATIC_BUILD
1570
8
  php_info_print_table_row(2, "uriparser bundled version", URI_VER_ANSI);
1571
#else
1572
  php_info_print_table_row(2, "uriparser compiled version", URI_VER_ANSI);
1573
  php_info_print_table_row(2, "uriparser loaded version", uriBaseRuntimeVersionA());
1574
#endif
1575
8
  php_info_print_table_end();
1576
8
}
1577
1578
static PHP_MSHUTDOWN_FUNCTION(uri)
1579
0
{
1580
0
  zend_hash_destroy(&uri_parsers);
1581
1582
0
  return SUCCESS;
1583
0
}
1584
1585
PHP_RINIT_FUNCTION(uri)
1586
295k
{
1587
295k
  if (PHP_RINIT(uri_parser_whatwg)(INIT_FUNC_ARGS_PASSTHRU) == FAILURE) {
1588
0
    return FAILURE;
1589
0
  }
1590
1591
295k
  return SUCCESS;
1592
295k
}
1593
1594
ZEND_MODULE_POST_ZEND_DEACTIVATE_D(uri)
1595
295k
{
1596
295k
  if (ZEND_MODULE_POST_ZEND_DEACTIVATE_N(uri_parser_whatwg)() == FAILURE) {
1597
0
    return FAILURE;
1598
0
  }
1599
1600
295k
  return SUCCESS;
1601
295k
}
1602
1603
zend_module_entry uri_module_entry = {
1604
  STANDARD_MODULE_HEADER_EX, NULL,
1605
  uri_deps,
1606
  "uri",                                     /* Extension name */
1607
  ext_functions,                                   /* zend_function_entry */
1608
  PHP_MINIT(uri),                 /* PHP_MINIT - Module initialization */
1609
  PHP_MSHUTDOWN(uri),           /* PHP_MSHUTDOWN - Module shutdown */
1610
  PHP_RINIT(uri),                 /* PHP_RINIT - Request initialization */
1611
  NULL,                         /* PHP_RSHUTDOWN - Request shutdown */
1612
  PHP_MINFO(uri),                                  /* PHP_MINFO - Module info */
1613
  PHP_VERSION,                              /* Version */
1614
  NO_MODULE_GLOBALS,
1615
  ZEND_MODULE_POST_ZEND_DEACTIVATE_N(uri),
1616
  STANDARD_MODULE_PROPERTIES_EX
1617
};