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,6 +47,9 @@ 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 bool (* php_uri_string_component_validator )(const zend_string * component );
51+ typedef bool (* php_uri_long_component_validator )(zend_long component );
52+
4953static const zend_module_dep uri_deps [] = {
5054 ZEND_MOD_REQUIRED ("lexbor" )
5155 ZEND_MOD_END
@@ -1044,6 +1048,199 @@ PHP_METHOD(Uri_WhatWg_Url, __debugInfo)
10441048 RETURN_ARR (uri_get_debug_properties (uri_object ));
10451049}
10461050
1051+ PHP_METHOD (Uri_Rfc3986_UriBuilder , __construct )
1052+ {
1053+ ZEND_PARSE_PARAMETERS_NONE ();
1054+ }
1055+
1056+ PHP_METHOD (Uri_Rfc3986_UriBuilder , reset )
1057+ {
1058+ ZEND_PARSE_PARAMETERS_NONE ();
1059+
1060+ zend_update_property_null (php_uri_ce_rfc3986_uri_builder , Z_OBJ_P (ZEND_THIS ), ZEND_STRL ("scheme "));
1061+ zend_update_property_null (php_uri_ce_rfc3986_uri_builder , Z_OBJ_P (ZEND_THIS ), ZEND_STRL ("userinfo "));
1062+ zend_update_property_null (php_uri_ce_rfc3986_uri_builder , Z_OBJ_P (ZEND_THIS ), ZEND_STRL ("host "));
1063+ zend_update_property_stringl (php_uri_ce_rfc3986_uri_builder , Z_OBJ_P (ZEND_THIS ), ZEND_STRL ("path "), "", 0 );
1064+ zend_update_property_null (php_uri_ce_rfc3986_uri_builder , Z_OBJ_P (ZEND_THIS ), ZEND_STRL ("query "));
1065+ zend_update_property_null (php_uri_ce_rfc3986_uri_builder , Z_OBJ_P (ZEND_THIS ), ZEND_STRL ("fragment "));
1066+
1067+ RETVAL_COPY (ZEND_THIS );
1068+ }
1069+
1070+ ZEND_ATTRIBUTE_NONNULL static void php_uri_builder_set_component_string (
1071+ INTERNAL_FUNCTION_PARAMETERS , const char * name , size_t name_length ,
1072+ const php_uri_string_component_validator validator
1073+ ) {
1074+ zend_string * component ;
1075+
1076+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
1077+ Z_PARAM_STR (component )
1078+ ZEND_PARSE_PARAMETERS_END ();
1079+
1080+ if (!validator (component )) {
1081+ zend_throw_exception_ex (php_uri_ce_invalid_uri_exception , 0 , "The specified %s is malformed ", name );
1082+ RETURN_THROWS ();
1083+ }
1084+
1085+ zend_update_property_str (Z_OBJCE_P (ZEND_THIS ), Z_OBJ_P (ZEND_THIS ), name , name_length , component );
1086+
1087+ RETVAL_COPY (ZEND_THIS );
1088+ }
1089+
1090+ ZEND_ATTRIBUTE_NONNULL static void php_uri_builder_set_component_string_or_null (
1091+ INTERNAL_FUNCTION_PARAMETERS , const char * name , size_t name_length ,
1092+ const php_uri_string_component_validator validator
1093+ ) {
1094+ zend_string * component ;
1095+
1096+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
1097+ Z_PARAM_STR_OR_NULL (component )
1098+ ZEND_PARSE_PARAMETERS_END ();
1099+
1100+ if (component == NULL) {
1101+ zend_update_property_null (Z_OBJCE_P (ZEND_THIS ), Z_OBJ_P (ZEND_THIS ), name , name_length );
1102+ } else {
1103+ if (!validator (component )) {
1104+ zend_throw_exception_ex (php_uri_ce_invalid_uri_exception , 0 , "The specified %s is malformed ", name );
1105+ RETURN_THROWS ();
1106+ }
1107+
1108+ zend_update_property_str (Z_OBJCE_P (ZEND_THIS ), Z_OBJ_P (ZEND_THIS ), name , name_length , component );
1109+ }
1110+
1111+ RETVAL_COPY (ZEND_THIS );
1112+ }
1113+
1114+ ZEND_ATTRIBUTE_NONNULL_ARGS (1 ) static void php_uri_builder_set_component_long_or_null (
1115+ INTERNAL_FUNCTION_PARAMETERS , const char * name , size_t name_length ,
1116+ const php_uri_long_component_validator validator
1117+ ) {
1118+ zend_long component ;
1119+ bool component_is_null ;
1120+
1121+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
1122+ Z_PARAM_LONG_OR_NULL (component , component_is_null )
1123+ ZEND_PARSE_PARAMETERS_END ();
1124+
1125+ if (component_is_null ) {
1126+ zend_update_property_null (Z_OBJCE_P (ZEND_THIS ), Z_OBJ_P (ZEND_THIS ), name , name_length );
1127+ } else {
1128+ if (!validator (component )) {
1129+ zend_throw_exception_ex (php_uri_ce_invalid_uri_exception , 0 , "The specified %s is malformed" , name );
1130+ RETURN_THROWS ();
1131+ }
1132+
1133+ zend_update_property_long (Z_OBJCE_P (ZEND_THIS ), Z_OBJ_P (ZEND_THIS ), name , name_length , component );
1134+ }
1135+
1136+ RETVAL_COPY (ZEND_THIS );
1137+ }
1138+
1139+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setScheme )
1140+ {
1141+ php_uri_builder_set_component_string_or_null (
1142+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1143+ ZEND_STRL ("scheme" ),
1144+ php_uri_parser_rfc3986_validate_scheme
1145+ );
1146+ }
1147+
1148+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setUserInfo )
1149+ {
1150+ php_uri_builder_set_component_string_or_null (
1151+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1152+ ZEND_STRL ("userinfo" ),
1153+ php_uri_parser_rfc3986_validate_userinfo
1154+ );
1155+ }
1156+
1157+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setHost )
1158+ {
1159+ php_uri_builder_set_component_string_or_null (
1160+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1161+ ZEND_STRL ("host" ),
1162+ php_uri_parser_rfc3986_validate_host
1163+ );
1164+ }
1165+
1166+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setPort )
1167+ {
1168+ php_uri_builder_set_component_long_or_null (
1169+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1170+ ZEND_STRL ("port" ),
1171+ php_uri_parser_rfc3986_validate_port
1172+ );
1173+ }
1174+
1175+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setPath )
1176+ {
1177+ php_uri_builder_set_component_string (
1178+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1179+ ZEND_STRL ("path" ),
1180+ php_uri_parser_rfc3986_validate_path
1181+ );
1182+ }
1183+
1184+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setQuery )
1185+ {
1186+ php_uri_builder_set_component_string_or_null (
1187+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1188+ ZEND_STRL ("query" ),
1189+ php_uri_parser_rfc3986_validate_query
1190+ );
1191+ }
1192+
1193+ PHP_METHOD (Uri_Rfc3986_UriBuilder , setFragment )
1194+ {
1195+ php_uri_builder_set_component_string_or_null (
1196+ INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1197+ ZEND_STRL ("fragment" ),
1198+ php_uri_parser_rfc3986_validate_fragment
1199+ );
1200+ }
1201+
1202+ PHP_METHOD (Uri_Rfc3986_UriBuilder , build )
1203+ {
1204+ zval * base_url = NULL ;
1205+
1206+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
1207+ Z_PARAM_OPTIONAL
1208+ Z_PARAM_OBJECT_OF_CLASS_OR_NULL (base_url , php_uri_ce_rfc3986_uri )
1209+ ZEND_PARSE_PARAMETERS_END ();
1210+
1211+ zend_object * obj = Z_OBJ_P (ZEND_THIS );
1212+ zval tmp ;
1213+
1214+ const zval * scheme = zend_read_property (obj -> ce , obj , ZEND_STRL ("scheme" ), false, & tmp );
1215+ const zval * userinfo = zend_read_property (obj -> ce , obj , ZEND_STRL ("userinfo" ), false, & tmp );
1216+ const zval * host = zend_read_property (obj -> ce , obj , ZEND_STRL ("host" ), false, & tmp );
1217+ const zval * port = zend_read_property (obj -> ce , obj , ZEND_STRL ("port" ), false, & tmp );
1218+ const zval * path = zend_read_property (obj -> ce , obj , ZEND_STRL ("path" ), false, & tmp );
1219+ const zval * query = zend_read_property (obj -> ce , obj , ZEND_STRL ("query" ), false, & tmp );
1220+ const zval * fragment = zend_read_property (obj -> ce , obj , ZEND_STRL ("fragment" ), false, & tmp );
1221+
1222+ zend_string * uri_str = php_uri_parser_rfc3986_recompose_from_zval (scheme , userinfo , host , port , path , query , fragment );
1223+ if (uri_str == NULL ) {
1224+ RETURN_THROWS ();
1225+ }
1226+
1227+ php_uri_parser_rfc3986_uris * base_uri = NULL ;
1228+ if (base_url != NULL ) {
1229+ base_uri = Z_URI_OBJECT_P (base_url )-> uri ;
1230+ }
1231+
1232+ php_uri_parser_rfc3986_uris * uri = php_uri_parser_rfc3986_parse_ex (ZSTR_VAL (uri_str ), ZSTR_LEN (uri_str ), base_uri , false);
1233+ zend_string_release (uri_str );
1234+ if (uri == NULL ) {
1235+ RETURN_THROWS ();
1236+ }
1237+
1238+ object_init_ex (return_value , php_uri_ce_rfc3986_uri );
1239+ php_uri_object * uri_object = Z_URI_OBJECT_P (return_value );
1240+ uri_object -> parser = & php_uri_parser_rfc3986 ;
1241+ uri_object -> uri = uri ;
1242+ }
1243+
10471244PHPAPI php_uri_object * php_uri_object_create (zend_class_entry * class_type , const php_uri_parser * parser )
10481245{
10491246 php_uri_object * uri_object = zend_object_alloc (sizeof (* uri_object ), class_type );
@@ -1113,6 +1310,8 @@ PHPAPI zend_result php_uri_parser_register(const php_uri_parser *uri_parser)
11131310
11141311static PHP_MINIT_FUNCTION (uri )
11151312{
1313+ php_uri_ce_rfc3986_uri_builder = register_class_Uri_Rfc3986_UriBuilder ();
1314+
11161315 php_uri_ce_rfc3986_uri = register_class_Uri_Rfc3986_Uri ();
11171316 php_uri_ce_rfc3986_uri -> create_object = php_uri_object_create_rfc3986 ;
11181317 php_uri_ce_rfc3986_uri -> default_object_handlers = & object_handlers_rfc3986_uri ;
0 commit comments