3030#include "php_uri_arginfo.h"
3131#include "uriparser/Uri.h"
3232
33+ zend_class_entry * php_uri_ce_rfc3986_uri_builder ;
3334zend_class_entry * php_uri_ce_rfc3986_uri ;
3435zend_class_entry * php_uri_ce_rfc3986_uri_type ;
3536zend_class_entry * php_uri_ce_rfc3986_uri_host_type ;
@@ -46,13 +47,33 @@ zend_class_entry *php_uri_ce_whatwg_url_validation_error;
4647static zend_object_handlers object_handlers_rfc3986_uri ;
4748static zend_object_handlers object_handlers_whatwg_uri ;
4849
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+
4953static const zend_module_dep uri_deps [] = {
5054 ZEND_MOD_REQUIRED ("lexbor" )
5155 ZEND_MOD_END
5256};
5357
5458static zend_array uri_parsers ;
5559
60+ static zend_always_inline zval * php_uri_deref (zval * zv )
61+ {
62+ if (UNEXPECTED (Z_TYPE_P (zv ) == IS_REFERENCE )) {
63+ return Z_REFVAL_P (zv );
64+ }
65+
66+ return zv ;
67+ }
68+
69+ #define Z_RFC3986_URI_PROP_SCHEME_P (zv ) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 0))
70+ #define Z_RFC3986_URI_PROP_USERINFO_P (zv ) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 1))
71+ #define Z_RFC3986_URI_PROP_HOST_P (zv ) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 2))
72+ #define Z_RFC3986_URI_PROP_PORT_P (zv ) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 3))
73+ #define Z_RFC3986_URI_PROP_PATH_P (zv ) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 4))
74+ #define Z_RFC3986_URI_PROP_QUERY_P (zv ) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 5))
75+ #define Z_RFC3986_URI_PROP_FRAGMENT_P (zv ) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 6))
76+
5677static HashTable * uri_get_debug_properties (php_uri_object * object )
5778{
5879 const HashTable * std_properties = zend_std_get_properties (& object -> std );
@@ -1044,6 +1065,186 @@ PHP_METHOD(Uri_WhatWg_Url, __debugInfo)
10441065 RETURN_ARR (uri_get_debug_properties (uri_object ));
10451066}
10461067
1068+ PHP_METHOD (Uri_Rfc3986_UriBuilder , reset )
1069+ {
1070+ ZEND_PARSE_PARAMETERS_NONE ();
1071+
1072+ convert_to_null (Z_RFC3986_URI_PROP_SCHEME_P (ZEND_THIS ));
1073+ convert_to_null (Z_RFC3986_URI_PROP_USERINFO_P (ZEND_THIS ));
1074+ convert_to_null (Z_RFC3986_URI_PROP_HOST_P (ZEND_THIS ));
1075+ convert_to_null (Z_RFC3986_URI_PROP_PORT_P (ZEND_THIS ));
1076+ zval_ptr_dtor (Z_RFC3986_URI_PROP_PATH_P (ZEND_THIS ));
1077+ ZVAL_EMPTY_STRING (Z_RFC3986_URI_PROP_PATH_P (ZEND_THIS ));
1078+ convert_to_null (Z_RFC3986_URI_PROP_QUERY_P (ZEND_THIS ));
1079+ convert_to_null (Z_RFC3986_URI_PROP_FRAGMENT_P (ZEND_THIS ));
1080+
1081+ RETVAL_COPY (ZEND_THIS );
1082+ }
1083+
1084+ ZEND_ATTRIBUTE_NONNULL static void php_uri_builder_set_component_string (
1085+ INTERNAL_FUNCTION_PARAMETERS , const char * name , const size_t name_length ,
1086+ const php_uri_component_validator_string validator
1087+ ) {
1088+ zend_string * component ;
1089+
1090+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
1091+ Z_PARAM_STR (component )
1092+ ZEND_PARSE_PARAMETERS_END ();
1093+
1094+ if (validator (component ) == FAILURE ) {
1095+ RETURN_THROWS ();
1096+ }
1097+
1098+ zend_update_property_str (Z_OBJCE_P (ZEND_THIS ), Z_OBJ_P (ZEND_THIS ), name , name_length , component );
1099+
1100+ RETVAL_COPY (ZEND_THIS );
1101+ }
1102+
1103+ ZEND_ATTRIBUTE_NONNULL static void php_uri_builder_set_component_string_or_null (
1104+ INTERNAL_FUNCTION_PARAMETERS , const char * name , const size_t name_length ,
1105+ const php_uri_component_validator_string validator
1106+ ) {
1107+ zend_string * component ;
1108+
1109+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
1110+ Z_PARAM_STR_OR_NULL (component )
1111+ ZEND_PARSE_PARAMETERS_END ();
1112+
1113+ if (component == NULL ) {
1114+ zend_update_property_null (Z_OBJCE_P (ZEND_THIS ), Z_OBJ_P (ZEND_THIS ), name , name_length );
1115+ } else {
1116+ if (validator (component ) == FAILURE ) {
1117+ RETURN_THROWS ();
1118+ }
1119+
1120+ zend_update_property_str (Z_OBJCE_P (ZEND_THIS ), Z_OBJ_P (ZEND_THIS ), name , name_length , component );
1121+ }
1122+
1123+ RETVAL_COPY (ZEND_THIS );
1124+ }
1125+
1126+ ZEND_ATTRIBUTE_NONNULL_ARGS (1 ) static void php_uri_builder_set_component_long_or_null (
1127+ INTERNAL_FUNCTION_PARAMETERS , const char * name , const size_t name_length ,
1128+ const php_uri_component_validator_long validator
1129+ ) {
1130+ zend_long component ;
1131+ bool component_is_null ;
1132+
1133+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
1134+ Z_PARAM_LONG_OR_NULL (component , component_is_null )
1135+ ZEND_PARSE_PARAMETERS_END ();
1136+
1137+ if (component_is_null ) {
1138+ zend_update_property_null (Z_OBJCE_P (ZEND_THIS ), Z_OBJ_P (ZEND_THIS ), name , name_length );
1139+ } else {
1140+ if (validator (component ) == FAILURE ) {
1141+ RETURN_THROWS ();
1142+ }
1143+
1144+ zend_update_property_long (Z_OBJCE_P (ZEND_THIS ), Z_OBJ_P (ZEND_THIS ), name , name_length , component );
1145+ }
1146+
1147+ RETVAL_COPY (ZEND_THIS );
1148+ }
1149+
1150+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setScheme )
1151+ {
1152+ php_uri_builder_set_component_string_or_null (
1153+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1154+ ZEND_STRL ("scheme" ),
1155+ php_uri_parser_rfc3986_validate_scheme
1156+ );
1157+ }
1158+
1159+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setUserInfo )
1160+ {
1161+ php_uri_builder_set_component_string_or_null (
1162+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1163+ ZEND_STRL ("userinfo" ),
1164+ php_uri_parser_rfc3986_validate_userinfo
1165+ );
1166+ }
1167+
1168+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setHost )
1169+ {
1170+ php_uri_builder_set_component_string_or_null (
1171+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1172+ ZEND_STRL ("host" ),
1173+ php_uri_parser_rfc3986_validate_host
1174+ );
1175+ }
1176+
1177+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setPort )
1178+ {
1179+ php_uri_builder_set_component_long_or_null (
1180+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1181+ ZEND_STRL ("port" ),
1182+ php_uri_parser_rfc3986_validate_port
1183+ );
1184+ }
1185+
1186+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setPath )
1187+ {
1188+ php_uri_builder_set_component_string (
1189+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1190+ ZEND_STRL ("path" ),
1191+ php_uri_parser_rfc3986_validate_path
1192+ );
1193+ }
1194+
1195+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setQuery )
1196+ {
1197+ php_uri_builder_set_component_string_or_null (
1198+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1199+ ZEND_STRL ("query" ),
1200+ php_uri_parser_rfc3986_validate_query
1201+ );
1202+ }
1203+
1204+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setFragment )
1205+ {
1206+ php_uri_builder_set_component_string_or_null (
1207+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1208+ ZEND_STRL ("fragment" ),
1209+ php_uri_parser_rfc3986_validate_fragment
1210+ );
1211+ }
1212+
1213+ PHP_METHOD (Uri_Rfc3986_UriBuilder , build )
1214+ {
1215+ zval * base_url = NULL ;
1216+
1217+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
1218+ Z_PARAM_OPTIONAL
1219+ Z_PARAM_OBJECT_OF_CLASS_OR_NULL (base_url , php_uri_ce_rfc3986_uri )
1220+ ZEND_PARSE_PARAMETERS_END ();
1221+
1222+ const zval * scheme = Z_RFC3986_URI_PROP_SCHEME_P (ZEND_THIS );
1223+ const zval * userinfo = Z_RFC3986_URI_PROP_USERINFO_P (ZEND_THIS );
1224+ const zval * host = Z_RFC3986_URI_PROP_HOST_P (ZEND_THIS );
1225+ const zval * port = Z_RFC3986_URI_PROP_PORT_P (ZEND_THIS );
1226+ const zval * path = Z_RFC3986_URI_PROP_PATH_P (ZEND_THIS );
1227+ const zval * query = Z_RFC3986_URI_PROP_QUERY_P (ZEND_THIS );
1228+ const zval * fragment = Z_RFC3986_URI_PROP_FRAGMENT_P (ZEND_THIS );
1229+
1230+ php_uri_parser_rfc3986_uris * base_uris = NULL ;
1231+ if (base_url != NULL ) {
1232+ base_uris = Z_URI_OBJECT_P (base_url )-> uri ;
1233+ }
1234+
1235+ php_uri_parser_rfc3986_uris * uriparser_uris = php_uri_parser_rfc3986_build_from_zval (
1236+ base_uris , scheme , userinfo , host , port , path , query , fragment
1237+ );
1238+ if (uriparser_uris == NULL ) {
1239+ RETURN_THROWS ();
1240+ }
1241+
1242+ object_init_ex (return_value , php_uri_ce_rfc3986_uri );
1243+ php_uri_object * uri_object = Z_URI_OBJECT_P (return_value );
1244+ uri_object -> parser = & php_uri_parser_rfc3986 ;
1245+ uri_object -> uri = uriparser_uris ;
1246+ }
1247+
10471248PHPAPI php_uri_object * php_uri_object_create (zend_class_entry * class_type , const php_uri_parser * parser )
10481249{
10491250 php_uri_object * uri_object = zend_object_alloc (sizeof (* uri_object ), class_type );
@@ -1113,6 +1314,8 @@ PHPAPI zend_result php_uri_parser_register(const php_uri_parser *uri_parser)
11131314
11141315static PHP_MINIT_FUNCTION (uri )
11151316{
1317+ php_uri_ce_rfc3986_uri_builder = register_class_Uri_Rfc3986_UriBuilder ();
1318+
11161319 php_uri_ce_rfc3986_uri = register_class_Uri_Rfc3986_Uri ();
11171320 php_uri_ce_rfc3986_uri -> create_object = php_uri_object_create_rfc3986 ;
11181321 php_uri_ce_rfc3986_uri -> default_object_handlers = & object_handlers_rfc3986_uri ;
0 commit comments