Coverage Report

Created: 2025-11-16 06:23

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 (c) The PHP Group                                          |
4
   +----------------------------------------------------------------------+
5
   | This source file is subject to version 3.01 of the PHP license,      |
6
   | that is bundled with this package in the file LICENSE, and is        |
7
   | available through the world-wide-web at the following url:           |
8
   | https://www.php.net/license/3_01.txt                                 |
9
   | If you did not receive a copy of the PHP license and are unable to   |
10
   | obtain it through the world-wide-web, please send a note to          |
11
   | license@php.net so we can mail you a copy immediately.               |
12
   +----------------------------------------------------------------------+
13
   | Authors: Máté Kocsis <kocsismate@php.net>                            |
14
   +----------------------------------------------------------------------+
15
*/
16
17
#ifdef HAVE_CONFIG_H
18
# include <config.h>
19
#endif
20
21
#include "php.h"
22
#include "Zend/zend_interfaces.h"
23
#include "Zend/zend_exceptions.h"
24
#include "Zend/zend_attributes.h"
25
#include "Zend/zend_enum.h"
26
#include "ext/standard/info.h"
27
28
#include "php_uri.h"
29
#include "uri_parser_whatwg.h"
30
#include "uri_parser_rfc3986.h"
31
#include "uri_parser_php_parse_url.h"
32
#include "php_uri_arginfo.h"
33
#include "uriparser/UriBase.h"
34
35
zend_class_entry *php_uri_ce_rfc3986_uri;
36
zend_class_entry *php_uri_ce_whatwg_url;
37
zend_class_entry *php_uri_ce_comparison_mode;
38
zend_class_entry *php_uri_ce_exception;
39
zend_class_entry *php_uri_ce_error;
40
zend_class_entry *php_uri_ce_invalid_uri_exception;
41
zend_class_entry *php_uri_ce_whatwg_invalid_url_exception;
42
zend_class_entry *php_uri_ce_whatwg_url_validation_error_type;
43
zend_class_entry *php_uri_ce_whatwg_url_validation_error;
44
45
static zend_object_handlers object_handlers_rfc3986_uri;
46
static zend_object_handlers object_handlers_whatwg_uri;
47
48
static const zend_module_dep uri_deps[] = {
49
  ZEND_MOD_REQUIRED("lexbor")
50
  ZEND_MOD_END
51
};
52
53
static zend_array uri_parsers;
54
55
static HashTable *uri_get_debug_properties(php_uri_object *object)
56
0
{
57
0
  const HashTable *std_properties = zend_std_get_properties(&object->std);
58
0
  HashTable *result = zend_array_dup(std_properties);
59
60
0
  const php_uri_parser * const parser = object->parser;
61
0
  void * const uri = object->uri;
62
63
0
  if (UNEXPECTED(uri == NULL)) {
64
0
    return result;
65
0
  }
66
67
0
  zval tmp;
68
0
  if (parser->property_handler.scheme.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
69
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_SCHEME), &tmp);
70
0
  }
71
72
0
  if (parser->property_handler.username.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
73
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_USERNAME), &tmp);
74
0
  }
75
76
0
  if (parser->property_handler.password.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
77
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_PASSWORD), &tmp);
78
0
  }
79
80
0
  if (parser->property_handler.host.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
81
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_HOST), &tmp);
82
0
  }
83
84
0
  if (parser->property_handler.port.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
85
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_PORT), &tmp);
86
0
  }
87
88
0
  if (parser->property_handler.path.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
89
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_PATH), &tmp);
90
0
  }
91
92
0
  if (parser->property_handler.query.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
93
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_QUERY), &tmp);
94
0
  }
95
96
0
  if (parser->property_handler.fragment.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) {
97
0
    zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_FRAGMENT), &tmp);
98
0
  }
99
100
0
  return result;
101
0
}
102
103
PHPAPI const php_uri_parser *php_uri_get_parser(zend_string *uri_parser_name)
104
0
{
105
0
  if (uri_parser_name == NULL) {
106
0
    return zend_hash_str_find_ptr(&uri_parsers, PHP_URI_PARSER_PHP_PARSE_URL, sizeof(PHP_URI_PARSER_PHP_PARSE_URL) - 1);
107
0
  }
108
109
0
  return zend_hash_find_ptr(&uri_parsers, uri_parser_name);
110
0
}
111
112
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)
113
0
{
114
0
  void *uri = uri_parser->parse(uri_str, uri_str_len, NULL, NULL, silent);
115
116
0
  if (uri == NULL) {
117
0
    return NULL;
118
0
  }
119
120
0
  php_uri_internal *internal_uri = emalloc(sizeof(*internal_uri));
121
0
  internal_uri->parser = uri_parser;
122
0
  internal_uri->uri = uri;
123
124
0
  return internal_uri;
125
0
}
126
127
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)
128
0
{
129
0
  return internal_uri->parser->property_handler.scheme.read(internal_uri->uri, read_mode, zv);
130
0
}
131
132
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)
133
0
{
134
0
  return internal_uri->parser->property_handler.username.read(internal_uri->uri, read_mode, zv);
135
0
}
136
137
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)
138
0
{
139
0
  return internal_uri->parser->property_handler.password.read(internal_uri->uri, read_mode, zv);
140
0
}
141
142
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)
143
0
{
144
0
  return internal_uri->parser->property_handler.host.read(internal_uri->uri, read_mode, zv);
145
0
}
146
147
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)
148
0
{
149
0
  return internal_uri->parser->property_handler.port.read(internal_uri->uri, read_mode, zv);
150
0
}
151
152
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)
153
0
{
154
0
  return internal_uri->parser->property_handler.path.read(internal_uri->uri, read_mode, zv);
155
0
}
156
157
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)
158
0
{
159
0
  return internal_uri->parser->property_handler.query.read(internal_uri->uri, read_mode, zv);
160
0
}
161
162
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)
163
0
{
164
0
  return internal_uri->parser->property_handler.fragment.read(internal_uri->uri, read_mode, zv);
165
0
}
166
167
ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_free(php_uri_internal *internal_uri)
168
0
{
169
0
  internal_uri->parser->destroy(internal_uri->uri);
170
0
  internal_uri->uri = NULL;
171
0
  internal_uri->parser = NULL;
172
0
  efree(internal_uri);
173
0
}
174
175
ZEND_ATTRIBUTE_NONNULL PHPAPI php_uri *php_uri_parse_to_struct(
176
  const php_uri_parser *uri_parser, const char *uri_str, size_t uri_str_len, php_uri_component_read_mode read_mode, bool silent
177
0
) {
178
0
  php_uri_internal *uri_internal = php_uri_parse(uri_parser, uri_str, uri_str_len, silent);
179
0
  if (uri_internal == NULL) {
180
0
    return NULL;
181
0
  }
182
183
0
  php_uri *uri = ecalloc(1, sizeof(*uri));
184
0
  zval tmp;
185
0
  zend_result result;
186
187
0
  result = php_uri_get_scheme(uri_internal, read_mode, &tmp);
188
0
  if (result == FAILURE) {
189
0
    goto error;
190
0
  }
191
0
  if (Z_TYPE(tmp) == IS_STRING) {
192
0
    uri->scheme = Z_STR(tmp);
193
0
  }
194
195
0
  result = php_uri_get_username(uri_internal, read_mode, &tmp);
196
0
  if (result == FAILURE) {
197
0
    goto error;
198
0
  }
199
0
  if (Z_TYPE(tmp) == IS_STRING) {
200
0
    uri->user = Z_STR(tmp);
201
0
  }
202
203
0
  result = php_uri_get_password(uri_internal, read_mode, &tmp);
204
0
  if (result == FAILURE) {
205
0
    goto error;
206
0
  }
207
0
  if (Z_TYPE(tmp) == IS_STRING) {
208
0
    uri->password = Z_STR(tmp);
209
0
  }
210
211
0
  result = php_uri_get_host(uri_internal, read_mode, &tmp);
212
0
  if (result == FAILURE) {
213
0
    goto error;
214
0
  }
215
0
  if (Z_TYPE(tmp) == IS_STRING) {
216
0
    uri->host = Z_STR(tmp);
217
0
  }
218
219
0
  result = php_uri_get_port(uri_internal, read_mode, &tmp);
220
0
  if (result == FAILURE) {
221
0
    goto error;
222
0
  }
223
0
  if (Z_TYPE(tmp) == IS_LONG) {
224
0
    uri->port = Z_LVAL(tmp);
225
0
  }
226
227
0
  result = php_uri_get_path(uri_internal, read_mode, &tmp);
228
0
  if (result == FAILURE) {
229
0
    goto error;
230
0
  }
231
0
  if (Z_TYPE(tmp) == IS_STRING) {
232
0
    uri->path = Z_STR(tmp);
233
0
  }
234
235
0
  result = php_uri_get_query(uri_internal, read_mode, &tmp);
236
0
  if (result == FAILURE) {
237
0
    goto error;
238
0
  }
239
0
  if (Z_TYPE(tmp) == IS_STRING) {
240
0
    uri->query = Z_STR(tmp);
241
0
  }
242
243
0
  result = php_uri_get_fragment(uri_internal, read_mode, &tmp);
244
0
  if (result == FAILURE) {
245
0
    goto error;
246
0
  }
247
0
  if (Z_TYPE(tmp) == IS_STRING) {
248
0
    uri->fragment = Z_STR(tmp);
249
0
  }
250
251
0
  php_uri_free(uri_internal);
252
253
0
  return uri;
254
255
0
error:
256
0
  php_uri_free(uri_internal);
257
0
  php_uri_struct_free(uri);
258
259
0
  return NULL;
260
0
}
261
262
ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_struct_free(php_uri *uri)
263
0
{
264
0
  if (uri->scheme) {
265
0
    zend_string_release(uri->scheme);
266
0
  }
267
0
  if (uri->user) {
268
0
    zend_string_release(uri->user);
269
0
  }
270
0
  if (uri->password) {
271
0
    zend_string_release(uri->password);
272
0
  }
273
0
  if (uri->host) {
274
0
    zend_string_release(uri->host);
275
0
  }
276
0
  if (uri->path) {
277
0
    zend_string_release(uri->path);
278
0
  }
279
0
  if (uri->query) {
280
0
    zend_string_release(uri->query);
281
0
  }
282
0
  if (uri->fragment) {
283
0
    zend_string_release(uri->fragment);
284
0
  }
285
286
0
  efree(uri);
287
0
}
288
289
/**
290
 * Pass the errors parameter by ref to errors_zv for userland, and frees it if
291
 * it is not not needed anymore.
292
 */
293
static zend_result pass_errors_by_ref_and_free(zval *errors_zv, zval *errors)
294
0
{
295
0
  ZEND_ASSERT(Z_TYPE_P(errors) == IS_UNDEF || Z_TYPE_P(errors) == IS_ARRAY);
296
297
  /* There was no error during parsing */
298
0
  if (Z_ISUNDEF_P(errors)) {
299
0
    return SUCCESS;
300
0
  }
301
302
  /* The errors parameter is an array, but the pass-by ref argument stored by
303
   * errors_zv was not passed - the URI implementation either doesn't support
304
   * returning additional error information, or the caller is not interested in it */
305
0
  if (errors_zv == NULL) {
306
0
    zval_ptr_dtor(errors);
307
0
    return SUCCESS;
308
0
  }
309
310
0
  ZEND_TRY_ASSIGN_REF_TMP(errors_zv, errors);
311
0
  if (EG(exception)) {
312
0
    return FAILURE;
313
0
  }
314
315
0
  return SUCCESS;
316
0
}
317
318
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri(
319
    INTERNAL_FUNCTION_PARAMETERS, const zend_string *uri_str, const php_uri_object *base_url_object,
320
    bool should_throw, bool should_update_this_object, zval *errors_zv
321
0
) {
322
323
0
  php_uri_object *uri_object;
324
0
  if (should_update_this_object) {
325
0
    uri_object = Z_URI_OBJECT_P(ZEND_THIS);
326
0
    if (uri_object->uri != NULL) {
327
0
      zend_throw_error(NULL, "Cannot modify readonly object of class %s", ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
328
0
      RETURN_THROWS();
329
0
    }
330
0
  } else {
331
0
    if (EX(func)->common.fn_flags & ZEND_ACC_STATIC) {
332
0
      object_init_ex(return_value, Z_CE_P(ZEND_THIS));
333
0
    } else {
334
0
      object_init_ex(return_value, Z_OBJCE_P(ZEND_THIS));
335
0
    }
336
0
    uri_object = Z_URI_OBJECT_P(return_value);
337
0
  }
338
339
0
  const php_uri_parser *uri_parser = uri_object->parser;
340
341
0
  zval errors;
342
0
  ZVAL_UNDEF(&errors);
343
344
0
  void *base_url = NULL;
345
0
  if (base_url_object != NULL) {
346
0
    ZEND_ASSERT(base_url_object->std.ce == uri_object->std.ce);
347
0
    ZEND_ASSERT(base_url_object->uri != NULL);
348
0
    ZEND_ASSERT(base_url_object->parser == uri_parser);
349
0
    base_url = base_url_object->uri;
350
0
  }
351
352
0
  void *uri = uri_parser->parse(ZSTR_VAL(uri_str), ZSTR_LEN(uri_str), base_url, errors_zv != NULL ? &errors : NULL, !should_throw);
353
0
  if (UNEXPECTED(uri == NULL)) {
354
0
    if (should_throw) {
355
0
      zval_ptr_dtor(&errors);
356
0
      RETURN_THROWS();
357
0
    } else {
358
0
      if (pass_errors_by_ref_and_free(errors_zv, &errors) == FAILURE) {
359
0
        RETURN_THROWS();
360
0
      }
361
0
      zval_ptr_dtor(return_value);
362
0
      RETURN_NULL();
363
0
    }
364
0
  }
365
366
0
  if (pass_errors_by_ref_and_free(errors_zv, &errors) == FAILURE) {
367
0
    uri_parser->destroy(uri);
368
0
    RETURN_THROWS();
369
0
  }
370
371
0
  uri_object->uri = uri;
372
0
}
373
374
static void create_rfc3986_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor)
375
5
{
376
5
  zend_string *uri_str;
377
5
  zend_object *base_url_object = NULL;
378
379
10
  ZEND_PARSE_PARAMETERS_START(1, 2)
380
10
    Z_PARAM_PATH_STR(uri_str)
381
0
    Z_PARAM_OPTIONAL
382
0
    Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, php_uri_ce_rfc3986_uri)
383
5
  ZEND_PARSE_PARAMETERS_END();
384
385
0
  php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU,
386
0
    uri_str, base_url_object ? php_uri_object_from_obj(base_url_object) : NULL, is_constructor, is_constructor, NULL);
387
0
}
388
389
static bool is_list_of_whatwg_validation_errors(const HashTable *array)
390
0
{
391
0
  if (!zend_array_is_list(array)) {
392
0
    return false;
393
0
  }
394
395
0
  ZEND_HASH_FOREACH_VAL(array, zval *val) {
396
    /* Do not allow references as they may change types after checking. */
397
398
0
    if (Z_TYPE_P(val) != IS_OBJECT) {
399
0
      return false;
400
0
    }
401
402
0
    if (!instanceof_function(Z_OBJCE_P(val), php_uri_ce_whatwg_url_validation_error)) {
403
0
      return false;
404
0
    }
405
0
  } ZEND_HASH_FOREACH_END();
406
407
0
  return true;
408
0
}
409
410
PHP_METHOD(Uri_Rfc3986_Uri, parse)
411
0
{
412
0
  create_rfc3986_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
413
0
}
414
415
PHP_METHOD(Uri_Rfc3986_Uri, __construct)
416
5
{
417
5
  create_rfc3986_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
418
5
}
419
420
PHP_METHOD(Uri_WhatWg_InvalidUrlException, __construct)
421
5
{
422
5
  zend_string *message = NULL;
423
5
  zval *errors = NULL;
424
5
  zend_long code = 0;
425
5
  zval *previous = NULL;
426
427
15
  ZEND_PARSE_PARAMETERS_START(0, 4)
428
15
    Z_PARAM_OPTIONAL
429
15
    Z_PARAM_STR(message)
430
0
    Z_PARAM_ARRAY(errors)
431
0
    Z_PARAM_LONG(code)
432
0
    Z_PARAM_OBJECT_OF_CLASS_OR_NULL(previous, zend_ce_throwable)
433
5
  ZEND_PARSE_PARAMETERS_END();
434
435
5
  if (zend_update_exception_properties(INTERNAL_FUNCTION_PARAM_PASSTHRU, message, code, previous) == FAILURE) {
436
0
    RETURN_THROWS();
437
0
  }
438
439
5
  if (errors == NULL) {
440
5
    zval tmp;
441
5
    ZVAL_EMPTY_ARRAY(&tmp);
442
5
    zend_update_property(php_uri_ce_whatwg_invalid_url_exception, Z_OBJ_P(ZEND_THIS), ZEND_STRL("errors"), &tmp);
443
5
  } else {
444
0
    if (!is_list_of_whatwg_validation_errors(Z_ARR_P(errors))) {
445
0
      zend_argument_value_error(2, "must be a list of %s", ZSTR_VAL(php_uri_ce_whatwg_url_validation_error->name));
446
0
      RETURN_THROWS();
447
0
    }
448
449
0
    zend_update_property(php_uri_ce_whatwg_invalid_url_exception, Z_OBJ_P(ZEND_THIS), ZEND_STRL("errors"), errors);
450
0
  }
451
5
  if (EG(exception)) {
452
0
    RETURN_THROWS();
453
0
  }
454
5
}
455
456
PHP_METHOD(Uri_WhatWg_UrlValidationError, __construct)
457
5
{
458
5
  zend_string *context;
459
5
  zval *type;
460
5
  bool failure;
461
462
10
  ZEND_PARSE_PARAMETERS_START(3, 3)
463
10
    Z_PARAM_STR(context)
464
0
    Z_PARAM_OBJECT_OF_CLASS(type, php_uri_ce_whatwg_url_validation_error_type)
465
0
    Z_PARAM_BOOL(failure)
466
5
  ZEND_PARSE_PARAMETERS_END();
467
468
0
  zend_update_property_str(php_uri_ce_whatwg_url_validation_error, Z_OBJ_P(ZEND_THIS), ZEND_STRL("context"), context);
469
0
  if (EG(exception)) {
470
0
    RETURN_THROWS();
471
0
  }
472
473
0
  zend_update_property_ex(php_uri_ce_whatwg_url_validation_error, Z_OBJ_P(ZEND_THIS), ZSTR_KNOWN(ZEND_STR_TYPE), type);
474
0
  if (EG(exception)) {
475
0
    RETURN_THROWS();
476
0
  }
477
478
0
  zval failure_zv;
479
0
  ZVAL_BOOL(&failure_zv, failure);
480
0
  zend_update_property(php_uri_ce_whatwg_url_validation_error, Z_OBJ_P(ZEND_THIS), ZEND_STRL("failure"), &failure_zv);
481
0
  if (EG(exception)) {
482
0
    RETURN_THROWS();
483
0
  }
484
0
}
485
486
static void create_whatwg_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor)
487
5
{
488
5
  zend_string *uri_str;
489
5
  zend_object *base_url_object = NULL;
490
5
  zval *errors = NULL;
491
492
10
  ZEND_PARSE_PARAMETERS_START(1, 3)
493
10
    Z_PARAM_PATH_STR(uri_str)
494
0
    Z_PARAM_OPTIONAL
495
0
    Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, php_uri_ce_whatwg_url)
496
0
    Z_PARAM_ZVAL(errors)
497
5
  ZEND_PARSE_PARAMETERS_END();
498
499
0
  php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU,
500
0
    uri_str, base_url_object ? php_uri_object_from_obj(base_url_object) : NULL, is_constructor, is_constructor, errors);
501
0
}
502
503
PHP_METHOD(Uri_WhatWg_Url, parse)
504
0
{
505
0
  create_whatwg_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
506
0
}
507
508
PHP_METHOD(Uri_WhatWg_Url, __construct)
509
5
{
510
5
  create_whatwg_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
511
5
}
512
513
PHP_METHOD(Uri_Rfc3986_Uri, getScheme)
514
0
{
515
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
516
0
}
517
518
PHP_METHOD(Uri_Rfc3986_Uri, getRawScheme)
519
0
{
520
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME, PHP_URI_COMPONENT_READ_MODE_RAW);
521
0
}
522
523
PHP_METHOD(Uri_Rfc3986_Uri, withScheme)
524
0
{
525
0
  php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME);
526
0
}
527
528
static void rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAMETERS, php_uri_component_read_mode read_mode)
529
0
{
530
0
  ZEND_PARSE_PARAMETERS_NONE();
531
532
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
533
0
  ZEND_ASSERT(uri_object->uri != NULL);
534
535
0
  if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_read(uri_object->uri, read_mode, return_value) == FAILURE)) {
536
0
    zend_throw_error(NULL, "The userinfo component cannot be retrieved");
537
0
    RETURN_THROWS();
538
0
  }
539
0
}
540
541
PHP_METHOD(Uri_Rfc3986_Uri, getUserInfo)
542
0
{
543
0
  rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
544
0
}
545
546
PHP_METHOD(Uri_Rfc3986_Uri, getRawUserInfo)
547
0
{
548
0
  rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_COMPONENT_READ_MODE_RAW);
549
0
}
550
551
PHP_METHOD(Uri_Rfc3986_Uri, withUserInfo)
552
0
{
553
0
  zend_string *value;
554
555
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
556
0
    Z_PARAM_PATH_STR_OR_NULL(value)
557
0
  ZEND_PARSE_PARAMETERS_END();
558
559
0
  zval zv;
560
0
  if (value == NULL) {
561
0
    ZVAL_NULL(&zv);
562
0
  } else {
563
0
    ZVAL_STR(&zv, value);
564
0
  }
565
566
0
  php_uri_object *old_uri_object = php_uri_object_from_obj(Z_OBJ_P(ZEND_THIS));
567
0
  ZEND_ASSERT(old_uri_object->uri != NULL);
568
569
0
  zend_object *new_object = old_uri_object->std.handlers->clone_obj(&old_uri_object->std);
570
0
  if (new_object == NULL) {
571
0
    RETURN_THROWS();
572
0
  }
573
574
  /* Assign the object early. The engine will take care of destruction in
575
   * case of an exception being thrown. */
576
0
  RETVAL_OBJ(new_object);
577
578
0
  php_uri_object *new_uri_object = php_uri_object_from_obj(new_object);
579
0
  ZEND_ASSERT(new_uri_object->uri != NULL);
580
581
0
  if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_write(new_uri_object->uri, &zv, NULL) == FAILURE)) {
582
0
    RETURN_THROWS();
583
0
  }
584
0
}
585
586
PHP_METHOD(Uri_Rfc3986_Uri, getUsername)
587
0
{
588
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_USERNAME, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
589
0
}
590
591
PHP_METHOD(Uri_Rfc3986_Uri, getRawUsername)
592
0
{
593
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_USERNAME, PHP_URI_COMPONENT_READ_MODE_RAW);
594
0
}
595
596
PHP_METHOD(Uri_Rfc3986_Uri, getPassword)
597
0
{
598
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PASSWORD, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
599
0
}
600
601
PHP_METHOD(Uri_Rfc3986_Uri, getRawPassword)
602
0
{
603
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PASSWORD, PHP_URI_COMPONENT_READ_MODE_RAW);
604
0
}
605
606
PHP_METHOD(Uri_Rfc3986_Uri, getHost)
607
0
{
608
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
609
0
}
610
611
PHP_METHOD(Uri_Rfc3986_Uri, getRawHost)
612
0
{
613
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_RAW);
614
0
}
615
616
PHP_METHOD(Uri_Rfc3986_Uri, withHost)
617
0
{
618
0
  php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST);
619
0
}
620
621
PHP_METHOD(Uri_Rfc3986_Uri, getPort)
622
0
{
623
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PORT, PHP_URI_COMPONENT_READ_MODE_RAW);
624
0
}
625
626
PHP_METHOD(Uri_Rfc3986_Uri, withPort)
627
0
{
628
0
  php_uri_property_write_long_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PORT);
629
0
}
630
631
PHP_METHOD(Uri_Rfc3986_Uri, getPath)
632
0
{
633
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PATH, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
634
0
}
635
636
PHP_METHOD(Uri_Rfc3986_Uri, getRawPath)
637
0
{
638
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PATH, PHP_URI_COMPONENT_READ_MODE_RAW);
639
0
}
640
641
PHP_METHOD(Uri_Rfc3986_Uri, withPath)
642
0
{
643
0
  php_uri_property_write_str_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PATH);
644
0
}
645
646
PHP_METHOD(Uri_Rfc3986_Uri, getQuery)
647
0
{
648
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_QUERY, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
649
0
}
650
651
PHP_METHOD(Uri_Rfc3986_Uri, getRawQuery)
652
0
{
653
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_QUERY, PHP_URI_COMPONENT_READ_MODE_RAW);
654
0
}
655
656
PHP_METHOD(Uri_Rfc3986_Uri, withQuery)
657
0
{
658
0
  php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_QUERY);
659
0
}
660
661
PHP_METHOD(Uri_Rfc3986_Uri, getFragment)
662
0
{
663
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
664
0
}
665
666
PHP_METHOD(Uri_Rfc3986_Uri, getRawFragment)
667
0
{
668
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT, PHP_URI_COMPONENT_READ_MODE_RAW);
669
0
}
670
671
PHP_METHOD(Uri_Rfc3986_Uri, withFragment)
672
0
{
673
0
  php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT);
674
0
}
675
676
static void throw_cannot_recompose_uri_to_string(php_uri_object *object)
677
0
{
678
0
  zend_throw_exception_ex(php_uri_ce_error, 0, "Cannot recompose %s to a string", ZSTR_VAL(object->std.ce->name));
679
0
}
680
681
static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, php_uri_object *that_object, zend_object *comparison_mode)
682
0
{
683
0
  php_uri_object *this_object = Z_URI_OBJECT_P(ZEND_THIS);
684
0
  ZEND_ASSERT(this_object->uri != NULL);
685
0
  ZEND_ASSERT(that_object->uri != NULL);
686
687
0
  if (this_object->std.ce != that_object->std.ce &&
688
0
    !instanceof_function(this_object->std.ce, that_object->std.ce) &&
689
0
    !instanceof_function(that_object->std.ce, this_object->std.ce)
690
0
  ) {
691
0
    RETURN_FALSE;
692
0
  }
693
694
0
  bool exclude_fragment = true;
695
0
  if (comparison_mode) {
696
0
    zval *case_name = zend_enum_fetch_case_name(comparison_mode);
697
0
    exclude_fragment = zend_string_equals_literal(Z_STR_P(case_name), "ExcludeFragment");
698
0
  }
699
700
0
  zend_string *this_str = this_object->parser->to_string(
701
0
    this_object->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, exclude_fragment);
702
0
  if (this_str == NULL) {
703
0
    throw_cannot_recompose_uri_to_string(this_object);
704
0
    RETURN_THROWS();
705
0
  }
706
707
0
  zend_string *that_str = that_object->parser->to_string(
708
0
    that_object->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, exclude_fragment);
709
0
  if (that_str == NULL) {
710
0
    zend_string_release(this_str);
711
0
    throw_cannot_recompose_uri_to_string(that_object);
712
0
    RETURN_THROWS();
713
0
  }
714
715
0
  RETVAL_BOOL(zend_string_equals(this_str, that_str));
716
717
0
  zend_string_release(this_str);
718
0
  zend_string_release(that_str);
719
0
}
720
721
PHP_METHOD(Uri_Rfc3986_Uri, equals)
722
0
{
723
0
  zend_object *that_object;
724
0
  zend_object *comparison_mode = NULL;
725
726
0
  ZEND_PARSE_PARAMETERS_START(1, 2)
727
0
    Z_PARAM_OBJ_OF_CLASS(that_object, php_uri_ce_rfc3986_uri)
728
0
    Z_PARAM_OPTIONAL
729
0
    Z_PARAM_OBJ_OF_CLASS(comparison_mode, php_uri_ce_comparison_mode)
730
0
  ZEND_PARSE_PARAMETERS_END();
731
732
0
  uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_uri_object_from_obj(that_object), comparison_mode);
733
0
}
734
735
PHP_METHOD(Uri_Rfc3986_Uri, toRawString)
736
0
{
737
0
  ZEND_PARSE_PARAMETERS_NONE();
738
739
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
740
0
  ZEND_ASSERT(uri_object->uri != NULL);
741
742
0
  zend_string *uri_str = uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false);
743
0
  if (uri_str == NULL) {
744
0
    throw_cannot_recompose_uri_to_string(uri_object);
745
0
    RETURN_THROWS();
746
0
  }
747
748
0
  RETURN_STR(uri_str);
749
0
}
750
751
PHP_METHOD(Uri_Rfc3986_Uri, toString)
752
0
{
753
0
  ZEND_PARSE_PARAMETERS_NONE();
754
755
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
756
0
  ZEND_ASSERT(uri_object->uri != NULL);
757
758
0
  zend_string *uri_str = uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, false);
759
0
  if (uri_str == NULL) {
760
0
    throw_cannot_recompose_uri_to_string(uri_object);
761
0
    RETURN_THROWS();
762
0
  }
763
764
0
  RETURN_STR(uri_str);
765
0
}
766
767
PHP_METHOD(Uri_Rfc3986_Uri, resolve)
768
0
{
769
0
  zend_string *uri_str;
770
771
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
772
0
    Z_PARAM_PATH_STR(uri_str)
773
0
  ZEND_PARSE_PARAMETERS_END();
774
775
0
  php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU,
776
0
    uri_str, Z_URI_OBJECT_P(ZEND_THIS), true, false, NULL);
777
0
}
778
779
PHP_METHOD(Uri_Rfc3986_Uri, __serialize)
780
0
{
781
0
  ZEND_PARSE_PARAMETERS_NONE();
782
783
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
784
0
  ZEND_ASSERT(uri_object->uri != NULL);
785
786
  /* Serialize state: "uri" key in the first array */
787
0
  zend_string *uri_str = uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false);
788
0
  if (uri_str == NULL) {
789
0
    throw_cannot_recompose_uri_to_string(uri_object);
790
0
    RETURN_THROWS();
791
0
  }
792
0
  zval tmp;
793
0
  ZVAL_STR(&tmp, uri_str);
794
795
0
  array_init(return_value);
796
797
0
  zval arr;
798
0
  array_init(&arr);
799
0
  zend_hash_str_add_new(Z_ARRVAL(arr), PHP_URI_SERIALIZE_URI_FIELD_NAME, sizeof(PHP_URI_SERIALIZE_URI_FIELD_NAME) - 1, &tmp);
800
0
  zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr);
801
802
  /* Serialize regular properties: second array */
803
0
  ZVAL_EMPTY_ARRAY(&arr);
804
0
  zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr);
805
0
}
806
807
static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS)
808
1
{
809
1
  HashTable *data;
810
811
3
  ZEND_PARSE_PARAMETERS_START(1, 1)
812
4
    Z_PARAM_ARRAY_HT(data)
813
1
  ZEND_PARSE_PARAMETERS_END();
814
815
1
  php_uri_object *uri_object = php_uri_object_from_obj(Z_OBJ_P(ZEND_THIS));
816
1
  if (uri_object->uri != NULL) {
817
    /* Intentionally throw two exceptions for proper chaining. */
818
0
    zend_throw_error(NULL, "Cannot modify readonly object of class %s", ZSTR_VAL(uri_object->std.ce->name));
819
0
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
820
0
    RETURN_THROWS();
821
0
  }
822
823
  /* Verify the expected number of elements, this implicitly ensures that no additional elements are present. */
824
1
  if (zend_hash_num_elements(data) != 2) {
825
1
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
826
1
    RETURN_THROWS();
827
1
  }
828
829
  /* Unserialize state: "uri" key in the first array */
830
0
  zval *arr = zend_hash_index_find(data, 0);
831
0
  if (arr == NULL || Z_TYPE_P(arr) != IS_ARRAY) {
832
0
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
833
0
    RETURN_THROWS();
834
0
  }
835
836
  /* Verify the expected number of elements inside the first array, this implicitly ensures that no additional elements are present. */
837
0
  if (zend_hash_num_elements(Z_ARRVAL_P(arr)) != 1) {
838
0
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
839
0
    RETURN_THROWS();
840
0
  }
841
842
0
  zval *uri_zv = zend_hash_str_find(Z_ARRVAL_P(arr), ZEND_STRL(PHP_URI_SERIALIZE_URI_FIELD_NAME));
843
0
  if (uri_zv == NULL || Z_TYPE_P(uri_zv) != IS_STRING) {
844
0
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
845
0
    RETURN_THROWS();
846
0
  }
847
848
0
  uri_object->uri = uri_object->parser->parse(Z_STRVAL_P(uri_zv), Z_STRLEN_P(uri_zv), NULL, NULL, true);
849
0
  if (uri_object->uri == NULL) {
850
0
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
851
0
    RETURN_THROWS();
852
0
  }
853
854
  /* Unserialize regular properties: second array */
855
0
  arr = zend_hash_index_find(data, 1);
856
0
  if (arr == NULL || Z_TYPE_P(arr) != IS_ARRAY) {
857
0
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
858
0
    RETURN_THROWS();
859
0
  }
860
861
  /* Verify that there is no regular property in the second array, because the URI classes have no properties and they are final. */
862
0
  if (zend_hash_num_elements(Z_ARRVAL_P(arr)) > 0) {
863
0
    zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(uri_object->std.ce->name));
864
0
    RETURN_THROWS();
865
0
  }
866
0
}
867
868
PHP_METHOD(Uri_Rfc3986_Uri, __unserialize)
869
0
{
870
0
  uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU);
871
0
}
872
873
PHP_METHOD(Uri_Rfc3986_Uri, __debugInfo)
874
0
{
875
0
  ZEND_PARSE_PARAMETERS_NONE();
876
877
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
878
879
0
  RETURN_ARR(uri_get_debug_properties(uri_object));
880
0
}
881
882
PHP_METHOD(Uri_WhatWg_Url, getScheme)
883
0
{
884
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
885
0
}
886
887
PHP_METHOD(Uri_WhatWg_Url, withScheme)
888
0
{
889
0
  php_uri_property_write_str_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME);
890
0
}
891
892
PHP_METHOD(Uri_WhatWg_Url, withUsername)
893
0
{
894
0
  php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_USERNAME);
895
0
}
896
897
PHP_METHOD(Uri_WhatWg_Url, withPassword)
898
0
{
899
0
  php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PASSWORD);
900
0
}
901
902
PHP_METHOD(Uri_WhatWg_Url, getAsciiHost)
903
0
{
904
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII);
905
0
}
906
907
PHP_METHOD(Uri_WhatWg_Url, getUnicodeHost)
908
0
{
909
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE);
910
0
}
911
912
PHP_METHOD(Uri_WhatWg_Url, getFragment)
913
0
{
914
0
  php_uri_property_read_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE);
915
0
}
916
917
PHP_METHOD(Uri_WhatWg_Url, equals)
918
0
{
919
0
  zend_object *that_object;
920
0
  zend_object *comparison_mode = NULL;
921
922
0
  ZEND_PARSE_PARAMETERS_START(1, 2)
923
0
    Z_PARAM_OBJ_OF_CLASS(that_object, php_uri_ce_whatwg_url)
924
0
    Z_PARAM_OPTIONAL
925
0
    Z_PARAM_OBJ_OF_CLASS(comparison_mode, php_uri_ce_comparison_mode)
926
0
  ZEND_PARSE_PARAMETERS_END();
927
928
0
  uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_uri_object_from_obj(that_object), comparison_mode);
929
0
}
930
931
PHP_METHOD(Uri_WhatWg_Url, toUnicodeString)
932
0
{
933
0
  ZEND_PARSE_PARAMETERS_NONE();
934
935
0
  zend_object *this_object = Z_OBJ_P(ZEND_THIS);
936
0
  php_uri_object *uri_object = php_uri_object_from_obj(this_object);
937
0
  ZEND_ASSERT(uri_object->uri != NULL);
938
939
0
  RETURN_STR(uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_UNICODE, false));
940
0
}
941
942
PHP_METHOD(Uri_WhatWg_Url, toAsciiString)
943
0
{
944
0
  ZEND_PARSE_PARAMETERS_NONE();
945
946
0
  zend_object *this_object = Z_OBJ_P(ZEND_THIS);
947
0
  php_uri_object *uri_object = php_uri_object_from_obj(this_object);
948
0
  ZEND_ASSERT(uri_object->uri != NULL);
949
950
0
  RETURN_STR(uri_object->parser->to_string(uri_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false));
951
0
}
952
953
PHP_METHOD(Uri_WhatWg_Url, resolve)
954
0
{
955
0
  zend_string *uri_str;
956
0
  zval *errors = NULL;
957
958
0
  ZEND_PARSE_PARAMETERS_START(1, 2)
959
0
    Z_PARAM_PATH_STR(uri_str)
960
0
    Z_PARAM_OPTIONAL
961
0
    Z_PARAM_ZVAL(errors)
962
0
  ZEND_PARSE_PARAMETERS_END();
963
964
0
  php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU,
965
0
    uri_str, Z_URI_OBJECT_P(ZEND_THIS), true, false, errors);
966
0
}
967
968
PHP_METHOD(Uri_WhatWg_Url, __serialize)
969
0
{
970
0
  ZEND_PARSE_PARAMETERS_NONE();
971
972
0
  php_uri_object *this_object = Z_URI_OBJECT_P(ZEND_THIS);
973
0
  ZEND_ASSERT(this_object->uri != NULL);
974
975
  /* Serialize state: "uri" key in the first array */
976
0
  zend_string *uri_str = this_object->parser->to_string(this_object->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false);
977
0
  if (uri_str == NULL) {
978
0
    throw_cannot_recompose_uri_to_string(this_object);
979
0
    RETURN_THROWS();
980
0
  }
981
0
  zval tmp;
982
0
  ZVAL_STR(&tmp, uri_str);
983
984
0
  array_init(return_value);
985
986
0
  zval arr;
987
0
  array_init(&arr);
988
0
  zend_hash_str_add_new(Z_ARRVAL(arr), ZEND_STRL(PHP_URI_SERIALIZE_URI_FIELD_NAME), &tmp);
989
0
  zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr);
990
991
  /* Serialize regular properties: second array */
992
0
  ZVAL_EMPTY_ARRAY(&arr);
993
0
  zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr);
994
0
}
995
996
PHP_METHOD(Uri_WhatWg_Url, __unserialize)
997
1
{
998
1
  uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU);
999
1
}
1000
1001
PHP_METHOD(Uri_WhatWg_Url, __debugInfo)
1002
0
{
1003
0
  ZEND_PARSE_PARAMETERS_NONE();
1004
1005
0
  php_uri_object *uri_object = Z_URI_OBJECT_P(ZEND_THIS);
1006
1007
0
  RETURN_ARR(uri_get_debug_properties(uri_object));
1008
0
}
1009
1010
PHPAPI php_uri_object *php_uri_object_create(zend_class_entry *class_type, const php_uri_parser *parser)
1011
21
{
1012
21
  php_uri_object *uri_object = zend_object_alloc(sizeof(*uri_object), class_type);
1013
1014
21
  zend_object_std_init(&uri_object->std, class_type);
1015
21
  object_properties_init(&uri_object->std, class_type);
1016
1017
21
  uri_object->parser = parser;
1018
21
  uri_object->uri = NULL;
1019
1020
21
  return uri_object;
1021
21
}
1022
1023
static zend_object *php_uri_object_create_rfc3986(zend_class_entry *ce)
1024
5
{
1025
5
  return &php_uri_object_create(ce, &php_uri_parser_rfc3986)->std;
1026
5
}
1027
1028
static zend_object *php_uri_object_create_whatwg(zend_class_entry *ce)
1029
16
{
1030
16
  return &php_uri_object_create(ce, &php_uri_parser_whatwg)->std;
1031
16
}
1032
1033
PHPAPI void php_uri_object_handler_free(zend_object *object)
1034
21
{
1035
21
  php_uri_object *uri_object = php_uri_object_from_obj(object);
1036
1037
21
  uri_object->parser->destroy(uri_object->uri);
1038
21
  zend_object_std_dtor(&uri_object->std);
1039
21
}
1040
1041
PHPAPI zend_object *php_uri_object_handler_clone(zend_object *object)
1042
0
{
1043
0
  php_uri_object *uri_object = php_uri_object_from_obj(object);
1044
1045
0
  ZEND_ASSERT(uri_object->uri != NULL);
1046
1047
0
  php_uri_object *new_uri_object = php_uri_object_from_obj(object->ce->create_object(object->ce));
1048
0
  ZEND_ASSERT(new_uri_object->parser == uri_object->parser);
1049
1050
0
  void *uri = uri_object->parser->clone(uri_object->uri);
1051
0
  ZEND_ASSERT(uri != NULL);
1052
1053
0
  new_uri_object->uri = uri;
1054
1055
0
  zend_objects_clone_members(&new_uri_object->std, &uri_object->std);
1056
1057
0
  return &new_uri_object->std;
1058
0
}
1059
1060
PHPAPI zend_result php_uri_parser_register(const php_uri_parser *uri_parser)
1061
48
{
1062
48
  zend_string *key = zend_string_init_interned(uri_parser->name, strlen(uri_parser->name), true);
1063
1064
48
  ZEND_ASSERT(uri_parser->name != NULL);
1065
48
  ZEND_ASSERT(uri_parser->parse != NULL);
1066
48
  ZEND_ASSERT(uri_parser->clone != NULL || strcmp(uri_parser->name, PHP_URI_PARSER_PHP_PARSE_URL) == 0);
1067
48
  ZEND_ASSERT(uri_parser->to_string != NULL || strcmp(uri_parser->name, PHP_URI_PARSER_PHP_PARSE_URL) == 0);
1068
48
  ZEND_ASSERT(uri_parser->destroy != NULL);
1069
1070
48
  zend_result result = zend_hash_add_ptr(&uri_parsers, key, (void *) uri_parser) != NULL ? SUCCESS : FAILURE;
1071
1072
48
  zend_string_release_ex(key, true);
1073
1074
48
  return result;
1075
48
}
1076
1077
static PHP_MINIT_FUNCTION(uri)
1078
16
{
1079
16
  php_uri_ce_rfc3986_uri = register_class_Uri_Rfc3986_Uri();
1080
16
  php_uri_ce_rfc3986_uri->create_object = php_uri_object_create_rfc3986;
1081
16
  php_uri_ce_rfc3986_uri->default_object_handlers = &object_handlers_rfc3986_uri;
1082
16
  memcpy(&object_handlers_rfc3986_uri, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1083
16
  object_handlers_rfc3986_uri.offset = XtOffsetOf(php_uri_object, std);
1084
16
  object_handlers_rfc3986_uri.free_obj = php_uri_object_handler_free;
1085
16
  object_handlers_rfc3986_uri.clone_obj = php_uri_object_handler_clone;
1086
1087
16
  php_uri_ce_whatwg_url = register_class_Uri_WhatWg_Url();
1088
16
  php_uri_ce_whatwg_url->create_object = php_uri_object_create_whatwg;
1089
16
  php_uri_ce_whatwg_url->default_object_handlers = &object_handlers_whatwg_uri;
1090
16
  memcpy(&object_handlers_whatwg_uri, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1091
16
  object_handlers_whatwg_uri.offset = XtOffsetOf(php_uri_object, std);
1092
16
  object_handlers_whatwg_uri.free_obj = php_uri_object_handler_free;
1093
16
  object_handlers_whatwg_uri.clone_obj = php_uri_object_handler_clone;
1094
1095
16
  php_uri_ce_comparison_mode = register_class_Uri_UriComparisonMode();
1096
16
  php_uri_ce_exception = register_class_Uri_UriException(zend_ce_exception);
1097
16
  php_uri_ce_error = register_class_Uri_UriError(zend_ce_error);
1098
16
  php_uri_ce_invalid_uri_exception = register_class_Uri_InvalidUriException(php_uri_ce_exception);
1099
16
  php_uri_ce_whatwg_invalid_url_exception = register_class_Uri_WhatWg_InvalidUrlException(php_uri_ce_invalid_uri_exception);
1100
16
  php_uri_ce_whatwg_url_validation_error = register_class_Uri_WhatWg_UrlValidationError();
1101
16
  php_uri_ce_whatwg_url_validation_error_type = register_class_Uri_WhatWg_UrlValidationErrorType();
1102
1103
16
  zend_hash_init(&uri_parsers, 4, NULL, NULL, true);
1104
1105
16
  if (php_uri_parser_register(&php_uri_parser_rfc3986) == FAILURE) {
1106
0
    return FAILURE;
1107
0
  }
1108
1109
16
  if (php_uri_parser_register(&php_uri_parser_whatwg) == FAILURE) {
1110
0
    return FAILURE;
1111
0
  }
1112
1113
16
  if (php_uri_parser_register(&php_uri_parser_php_parse_url) == FAILURE) {
1114
0
    return FAILURE;
1115
0
  }
1116
1117
16
  return SUCCESS;
1118
16
}
1119
1120
static PHP_MINFO_FUNCTION(uri)
1121
8
{
1122
8
  php_info_print_table_start();
1123
8
  php_info_print_table_row(2, "URI support", "active");
1124
8
#ifdef URI_STATIC_BUILD
1125
8
  php_info_print_table_row(2, "uriparser bundled version", URI_VER_ANSI);
1126
#else
1127
  php_info_print_table_row(2, "uriparser compiled version", URI_VER_ANSI);
1128
  php_info_print_table_row(2, "uriparser loaded version", uriBaseRuntimeVersionA());
1129
#endif
1130
8
  php_info_print_table_end();
1131
8
}
1132
1133
static PHP_MSHUTDOWN_FUNCTION(uri)
1134
0
{
1135
0
  zend_hash_destroy(&uri_parsers);
1136
1137
0
  return SUCCESS;
1138
0
}
1139
1140
PHP_RINIT_FUNCTION(uri)
1141
247k
{
1142
247k
  if (PHP_RINIT(uri_parser_whatwg)(INIT_FUNC_ARGS_PASSTHRU) == FAILURE) {
1143
0
    return FAILURE;
1144
0
  }
1145
1146
247k
  return SUCCESS;
1147
247k
}
1148
1149
ZEND_MODULE_POST_ZEND_DEACTIVATE_D(uri)
1150
247k
{
1151
247k
  if (ZEND_MODULE_POST_ZEND_DEACTIVATE_N(uri_parser_whatwg)() == FAILURE) {
1152
0
    return FAILURE;
1153
0
  }
1154
1155
247k
  return SUCCESS;
1156
247k
}
1157
1158
zend_module_entry uri_module_entry = {
1159
  STANDARD_MODULE_HEADER_EX, NULL,
1160
  uri_deps,
1161
  "uri",                          /* Extension name */
1162
  NULL,                           /* zend_function_entry */
1163
  PHP_MINIT(uri),                 /* PHP_MINIT - Module initialization */
1164
  PHP_MSHUTDOWN(uri),             /* PHP_MSHUTDOWN - Module shutdown */
1165
  PHP_RINIT(uri),                 /* PHP_RINIT - Request initialization */
1166
  NULL,                           /* PHP_RSHUTDOWN - Request shutdown */
1167
  PHP_MINFO(uri),                 /* PHP_MINFO - Module info */
1168
  PHP_VERSION,                    /* Version */
1169
  NO_MODULE_GLOBALS,
1170
  ZEND_MODULE_POST_ZEND_DEACTIVATE_N(uri),
1171
  STANDARD_MODULE_PROPERTIES_EX
1172
};