2020
2121#include "php.h"
2222#include "Zend/zend_interfaces.h"
23+ #include "Zend/zend_exceptions.h"
2324#include "main/php_ini.h"
2425
2526#include "php_uri.h"
@@ -33,6 +34,8 @@ zend_class_entry *rfc3986_uri_ce;
3334zend_object_handlers rfc3986_uri_object_handlers ;
3435zend_class_entry * whatwg_uri_ce ;
3536zend_object_handlers whatwg_uri_object_handlers ;
37+ zend_class_entry * uri_exception_ce ;
38+ zend_class_entry * invalid_uri_exception_ce ;
3639zend_class_entry * whatwg_error_ce ;
3740
3841static zend_array uri_handlers ;
@@ -98,7 +101,7 @@ PHPAPI uri_handler_t *php_uri_get_handler(const zend_string *uri_handler_name)
98101 return uri_handler_by_name (ZSTR_VAL (uri_handler_name ), ZSTR_LEN (uri_handler_name ));
99102}
100103
101- PHPAPI uri_internal_t * php_uri_parse (const uri_handler_t * uri_handler , zend_string * uri_str )
104+ PHPAPI uri_internal_t * php_uri_parse (const uri_handler_t * uri_handler , zend_string * uri_str , zval * errors )
102105{
103106 ZEND_ASSERT (uri_handler != NULL );
104107
@@ -108,7 +111,7 @@ PHPAPI uri_internal_t *php_uri_parse(const uri_handler_t *uri_handler, zend_stri
108111
109112 uri_internal_t * internal_uri = emalloc (sizeof (uri_internal_t ));
110113 internal_uri -> handler = uri_handler ;
111- internal_uri -> uri = uri_handler -> parse_uri (uri_str , NULL , NULL );
114+ internal_uri -> uri = uri_handler -> parse_uri (uri_str , NULL , errors );
112115
113116 if (UNEXPECTED (internal_uri -> uri == NULL )) {
114117 efree (internal_uri );
@@ -178,32 +181,46 @@ PHPAPI void php_uri_free(uri_internal_t *internal_uri)
178181
179182PHP_METHOD (Uri_WhatWgError , __construct )
180183{
181- zend_string * position ;
184+ zend_string * uri , * position ;
182185 zend_long error ;
183186
184- ZEND_PARSE_PARAMETERS_START (2 , 2 )
187+ ZEND_PARSE_PARAMETERS_START (3 , 3 )
188+ Z_PARAM_STR (uri )
185189 Z_PARAM_STR (position )
186190 Z_PARAM_LONG (error )
187191 ZEND_PARSE_PARAMETERS_END ();
188192
193+ zend_update_property_str (whatwg_error_ce , Z_OBJ_P (ZEND_THIS ), "uri ", sizeof(" uri ") - 1, uri);
189194 zend_update_property_str (whatwg_error_ce , Z_OBJ_P (ZEND_THIS ), "position" , sizeof ("position" ) - 1 , position );
190195 zend_update_property_long (whatwg_error_ce , Z_OBJ_P (ZEND_THIS ), "error" , sizeof ("error" ) - 1 , error );
191196}
192197
193198PHPAPI void php_uri_instantiate_uri (
194199 INTERNAL_FUNCTION_PARAMETERS , const uri_handler_t * handler , const zend_string * uri_str , const zend_string * base_url_str ,
195- zval * errors , bool is_constructor
200+ bool is_constructor , bool return_errors
196201) {
197- void * uri = handler -> parse_uri (uri_str , base_url_str , errors );
202+ zval errors ;
203+ ZVAL_UNDEF (& errors );
204+
205+ void * uri = handler -> parse_uri (uri_str , base_url_str , & errors );
198206 if (UNEXPECTED (uri == NULL )) {
199207 if (is_constructor ) {
200- zend_argument_value_error (1 , "must be a valid URI" );
208+ throw_invalid_uri_exception (& errors );
209+ zval_ptr_dtor (& errors );
201210 RETURN_THROWS ();
202211 } else {
212+ if (return_errors && Z_TYPE (errors ) == IS_ARRAY ) {
213+ RETURN_ZVAL (& errors , false, false);
214+ }
215+
216+ zval_ptr_dtor (& errors );
217+
203218 RETURN_NULL ();
204219 }
205220 }
206221
222+ ZEND_ASSERT (Z_TYPE (errors ) == IS_UNDEF );
223+
207224 if (!is_constructor ) {
208225 object_init_ex (return_value , handler -> get_uri_ce ());
209226 }
@@ -233,7 +250,7 @@ static void create_rfc3986_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor
233250 RETURN_THROWS ();
234251 }
235252
236- php_uri_instantiate_uri (INTERNAL_FUNCTION_PARAM_PASSTHRU , & uriparser_uri_handler , uri_str , base_url_str , NULL , is_constructor );
253+ php_uri_instantiate_uri (INTERNAL_FUNCTION_PARAM_PASSTHRU , & uriparser_uri_handler , uri_str , base_url_str , is_constructor , false );
237254}
238255
239256PHP_METHOD (Uri_Rfc3986Uri , create )
@@ -249,13 +266,11 @@ PHP_METHOD(Uri_Rfc3986Uri, __construct)
249266static void create_whatwg_uri (INTERNAL_FUNCTION_PARAMETERS , bool is_constructor )
250267{
251268 zend_string * uri_str , * base_url_str = NULL ;
252- zval * errors = NULL ;
253269
254- ZEND_PARSE_PARAMETERS_START (1 , 3 )
270+ ZEND_PARSE_PARAMETERS_START (1 , 2 )
255271 Z_PARAM_PATH_STR (uri_str )
256272 Z_PARAM_OPTIONAL
257273 Z_PARAM_PATH_STR_OR_NULL (base_url_str )
258- Z_PARAM_ZVAL (errors )
259274 ZEND_PARSE_PARAMETERS_END ();
260275
261276 if (ZSTR_LEN (uri_str ) == 0 ) {
@@ -268,7 +283,7 @@ static void create_whatwg_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor)
268283 RETURN_THROWS ();
269284 }
270285
271- php_uri_instantiate_uri (INTERNAL_FUNCTION_PARAM_PASSTHRU , & lexbor_uri_handler , uri_str , base_url_str , errors , is_constructor );
286+ php_uri_instantiate_uri (INTERNAL_FUNCTION_PARAM_PASSTHRU , & lexbor_uri_handler , uri_str , base_url_str , is_constructor , true );
272287}
273288
274289PHP_METHOD (Uri_WhatWgUri , create )
@@ -412,15 +427,21 @@ PHP_METHOD(Uri_Rfc3986Uri, __unserialize)
412427 zend_object * object = Z_OBJ_P (ZEND_THIS );
413428 uri_internal_t * internal_uri = uri_internal_from_obj (object );
414429
415- /*if (!php_date_initialize_from_hash(&dateobj, myht)) {
416- zend_throw_error(NULL, "Invalid serialization data for DateTime object");
417- RETURN_THROWS();
418- }*/
419-
420430 zend_string * str = zend_string_init ("https://example.com" , sizeof ("https://example.com" ) - 1 , false);
421431
432+ zval errors ;
433+ ZVAL_UNDEF (& errors );
434+
422435 internal_uri -> handler = uri_handler_by_name ("rfc3986" , sizeof ("rfc3986" ) - 1 );
423- internal_uri -> uri = internal_uri -> handler -> parse_uri (str , NULL , NULL );
436+ internal_uri -> uri = internal_uri -> handler -> parse_uri (str , NULL , & errors );
437+ if (internal_uri -> uri == NULL ) {
438+ throw_invalid_uri_exception (& errors );
439+ zval_ptr_dtor (& errors );
440+ zend_string_release (str );
441+ RETURN_THROWS ();
442+ }
443+ ZEND_ASSERT (Z_TYPE (errors ) == IS_UNDEF );
444+ //zend_string_release(str); TODO Fix memory leak
424445
425446 uri_restore_custom_properties (object , internal_uri , ht );
426447}
@@ -436,15 +457,21 @@ PHP_METHOD(Uri_WhatWgUri, __unserialize)
436457 zend_object * object = Z_OBJ_P (ZEND_THIS );
437458 uri_internal_t * internal_uri = uri_internal_from_obj (object );
438459
439- /*if (!php_date_initialize_from_hash(&dateobj, myht)) {
440- zend_throw_error(NULL, "Invalid serialization data for DateTime object");
441- RETURN_THROWS();
442- }*/
443-
444460 zend_string * str = zend_string_init ("https://example.com" , sizeof ("https://example.com" ) - 1 , false);
445461
462+ zval errors ;
463+ ZVAL_UNDEF (& errors );
464+
446465 internal_uri -> handler = uri_handler_by_name ("whatwg" , sizeof ("whatwg" ) - 1 );
447- internal_uri -> uri = internal_uri -> handler -> parse_uri (str , NULL , NULL );
466+ internal_uri -> uri = internal_uri -> handler -> parse_uri (str , NULL , & errors );
467+ if (internal_uri -> uri == NULL ) {
468+ throw_invalid_uri_exception (& errors );
469+ zval_ptr_dtor (& errors );
470+ zend_string_release (str );
471+ RETURN_THROWS ();
472+ }
473+ ZEND_ASSERT (Z_TYPE (errors ) == IS_UNDEF );
474+ //zend_string_release(str); TODO Fix memory leak
448475
449476 uri_restore_custom_properties (object , internal_uri , ht );
450477}
@@ -663,6 +690,8 @@ void uri_register_symbols(void)
663690 whatwg_uri_ce = register_class_Uri_WhatWgUri (uri_interface_ce );
664691 php_uri_implementation_set_object_handlers (whatwg_uri_ce , & whatwg_uri_object_handlers );
665692
693+ uri_exception_ce = register_class_Uri_UriException (zend_ce_exception );
694+ invalid_uri_exception_ce = register_class_Uri_InvalidUriException (uri_exception_ce );
666695 whatwg_error_ce = register_class_Uri_WhatWgError ();
667696}
668697
0 commit comments