Coverage Report

Created: 2025-06-13 06:43

/src/php-src/ext/uri/php_uri_common.c
Line
Count
Source (jump to first uncovered line)
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
#include "php.h"
18
#include "Zend/zend_interfaces.h"
19
#include "Zend/zend_exceptions.h"
20
#include "php_uri_common.h"
21
22
const uri_property_handler_t *uri_property_handler_from_internal_uri(const uri_internal_t *internal_uri, uri_property_name_t property_name)
23
0
{
24
0
  switch (property_name) {
25
0
    case URI_PROPERTY_NAME_SCHEME:
26
0
      return &internal_uri->handler->property_handlers.scheme;
27
0
    case URI_PROPERTY_NAME_USERNAME:
28
0
      return &internal_uri->handler->property_handlers.username;
29
0
    case URI_PROPERTY_NAME_PASSWORD:
30
0
      return &internal_uri->handler->property_handlers.password;
31
0
    case URI_PROPERTY_NAME_HOST:
32
0
      return &internal_uri->handler->property_handlers.host;
33
0
    case URI_PROPERTY_NAME_PORT:
34
0
      return &internal_uri->handler->property_handlers.port;
35
0
    case URI_PROPERTY_NAME_PATH:
36
0
      return &internal_uri->handler->property_handlers.path;
37
0
    case URI_PROPERTY_NAME_QUERY:
38
0
      return &internal_uri->handler->property_handlers.query;
39
0
    case URI_PROPERTY_NAME_FRAGMENT:
40
0
      return &internal_uri->handler->property_handlers.fragment;
41
0
    EMPTY_SWITCH_DEFAULT_CASE()
42
0
  }
43
0
}
44
45
static zend_string *get_known_string_by_property_name(uri_property_name_t property_name)
46
0
{
47
0
  switch (property_name) {
48
0
    case URI_PROPERTY_NAME_SCHEME:
49
0
      return ZSTR_KNOWN(ZEND_STR_SCHEME);
50
0
    case URI_PROPERTY_NAME_USERNAME:
51
0
      return ZSTR_KNOWN(ZEND_STR_USERNAME);
52
0
    case URI_PROPERTY_NAME_PASSWORD:
53
0
      return ZSTR_KNOWN(ZEND_STR_PASSWORD);
54
0
    case URI_PROPERTY_NAME_HOST:
55
0
      return ZSTR_KNOWN(ZEND_STR_HOST);
56
0
    case URI_PROPERTY_NAME_PORT:
57
0
      return ZSTR_KNOWN(ZEND_STR_PORT);
58
0
    case URI_PROPERTY_NAME_PATH:
59
0
      return ZSTR_KNOWN(ZEND_STR_PATH);
60
0
    case URI_PROPERTY_NAME_QUERY:
61
0
      return ZSTR_KNOWN(ZEND_STR_QUERY);
62
0
    case URI_PROPERTY_NAME_FRAGMENT:
63
0
      return ZSTR_KNOWN(ZEND_STR_FRAGMENT);
64
0
    EMPTY_SWITCH_DEFAULT_CASE()
65
0
  }
66
0
}
67
68
void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name, uri_component_read_mode_t component_read_mode)
69
0
{
70
0
  ZEND_PARSE_PARAMETERS_NONE();
71
72
0
  uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS);
73
0
  URI_ASSERT_INITIALIZATION(internal_uri);
74
75
0
  const uri_property_handler_t *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name);
76
0
  ZEND_ASSERT(property_handler != NULL);
77
78
0
  if (UNEXPECTED(property_handler->read_func(internal_uri, component_read_mode, return_value) == FAILURE)) {
79
0
    zend_throw_error(NULL, "%s::$%s property cannot be retrieved", ZSTR_VAL(Z_OBJ_P(ZEND_THIS)->ce->name),
80
0
      ZSTR_VAL(get_known_string_by_property_name(property_name)));
81
0
    RETURN_THROWS();
82
0
  }
83
0
}
84
85
static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name, zval *property_zv)
86
0
{
87
0
  uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS);
88
0
  URI_ASSERT_INITIALIZATION(internal_uri);
89
90
0
  const uri_property_handler_t *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name);
91
0
  ZEND_ASSERT(property_handler != NULL);
92
93
0
  zend_object *new_object = uri_clone_obj_handler(Z_OBJ_P(ZEND_THIS));
94
0
  if (UNEXPECTED(EG(exception) != NULL)) {
95
0
    zend_object_release(new_object);
96
0
    RETURN_THROWS();
97
0
  }
98
99
0
  uri_internal_t *new_internal_uri = uri_internal_from_obj(new_object);
100
0
  URI_ASSERT_INITIALIZATION(new_internal_uri);
101
0
  if (property_handler->write_func == NULL) {
102
0
    zend_readonly_property_modification_error_ex(ZSTR_VAL(Z_OBJ_P(ZEND_THIS)->ce->name),
103
0
      ZSTR_VAL(get_known_string_by_property_name(property_name)));
104
0
    zend_object_release(new_object);
105
0
    RETURN_THROWS();
106
0
  }
107
108
0
  zval errors;
109
0
  ZVAL_UNDEF(&errors);
110
0
  if (property_handler->write_func(new_internal_uri, property_zv, &errors) == FAILURE) {
111
0
    zval_ptr_dtor(&errors);
112
0
    zend_object_release(new_object);
113
0
    RETURN_THROWS();
114
0
  }
115
116
0
  ZEND_ASSERT(Z_ISUNDEF(errors));
117
0
  RETVAL_OBJ(new_object);
118
0
}
119
120
void uri_write_component_str(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name)
121
0
{
122
0
  zend_string *value;
123
124
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
125
0
    Z_PARAM_PATH_STR(value)
126
0
  ZEND_PARSE_PARAMETERS_END();
127
128
0
  zval zv;
129
0
  ZVAL_STR(&zv, value);
130
131
0
  uri_write_component_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv);
132
0
}
133
134
void uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name)
135
0
{
136
0
  zend_string *value;
137
138
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
139
0
    Z_PARAM_PATH_STR_OR_NULL(value)
140
0
  ZEND_PARSE_PARAMETERS_END();
141
142
0
  zval zv;
143
0
  if (value == NULL) {
144
0
    ZVAL_NULL(&zv);
145
0
  } else {
146
0
    ZVAL_STR(&zv, value);
147
0
  }
148
149
0
  uri_write_component_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv);
150
0
}
151
152
void uri_write_component_long_or_null(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name)
153
0
{
154
0
  zend_long value;
155
0
  bool value_is_null;
156
157
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
158
0
    Z_PARAM_LONG_OR_NULL(value, value_is_null)
159
0
  ZEND_PARSE_PARAMETERS_END();
160
161
0
  zval zv;
162
0
  if (value_is_null) {
163
0
    ZVAL_NULL(&zv);
164
0
  } else {
165
0
    ZVAL_LONG(&zv, value);
166
0
  }
167
168
0
  uri_write_component_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv);
169
0
}