@@ -202,10 +202,8 @@ ZEND_ATTRIBUTE_NONNULL static const char *fill_errors(zval *errors)
202202 return fill_errors_inner (Z_ARRVAL_P (errors ));
203203}
204204
205- static void throw_invalid_url_exception_during_write (zval * errors , const char * component )
205+ static void throw_invalid_url_exception_with_reason (zval * errors , const char * component , const char * reason , zval * err )
206206{
207- zval err ;
208- const char * reason = fill_errors (& err );
209207 zend_object * exception = zend_throw_exception_ex (
210208 php_uri_ce_whatwg_invalid_url_exception ,
211209 0 ,
@@ -215,15 +213,23 @@ static void throw_invalid_url_exception_during_write(zval *errors, const char *c
215213 reason ? reason : "" ,
216214 reason ? ")" : ""
217215 );
218- zend_update_property (exception -> ce , exception , ZEND_STRL ("errors" ), & err );
216+ zend_update_property (exception -> ce , exception , ZEND_STRL ("errors" ), err );
219217 if (errors ) {
220218 zval_ptr_dtor (errors );
221- ZVAL_COPY_VALUE (errors , & err );
219+ ZVAL_COPY_VALUE (errors , err );
222220 } else {
223- zval_ptr_dtor (& err );
221+ zval_ptr_dtor (err );
224222 }
225223}
226224
225+ static void throw_invalid_url_exception_during_write (zval * errors , const char * component )
226+ {
227+ zval err ;
228+ const char * reason = fill_errors (& err );
229+
230+ throw_invalid_url_exception_with_reason (errors , component , reason , & err );
231+ }
232+
227233static lxb_status_t serialize_to_smart_str_callback (const lxb_char_t * data , const size_t length , void * ctx )
228234{
229235 smart_str * uri_str = ctx ;
@@ -948,27 +954,174 @@ ZEND_ATTRIBUTE_NONNULL static lxb_url_scheme_type_t php_uri_parser_whatwg_get_sp
948954 return LXB_URL_SCHEMEL_TYPE__UNDEF ;
949955}
950956
951- ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_errors (zval * errors )
957+ ZEND_ATTRIBUTE_NONNULL const char * php_uri_parser_whatwg_build_errors (zval * errors )
952958{
953959 size_t log_len ;
954960
955961 if (lexbor_parser .log == NULL || (log_len = lexbor_plog_length (lexbor_parser .log )) == 0 ) {
956- return ;
962+ return NULL ;
957963 }
958964
959965 if (Z_TYPE_P (errors ) != IS_ARRAY ) {
960966 zval_ptr_dtor (errors );
961967 array_init_size (errors , log_len );
962968 }
963969
964- fill_errors_inner (Z_ARRVAL_P (errors ));
970+ return fill_errors_inner (Z_ARRVAL_P (errors ));
971+ }
972+
973+ ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_errors_and_throw (const lxb_status_t status , const char * component , zval * errors )
974+ {
975+ zval err ;
976+ ZVAL_UNDEF (& err );
977+
978+ const char * reason = php_uri_parser_whatwg_build_errors (& err );
979+
980+ if (status != LXB_STATUS_OK ) {
981+ throw_invalid_url_exception_with_reason (errors , component , reason , & err );
982+ }
983+ }
984+
985+ ZEND_ATTRIBUTE_NONNULL_ARGS (1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) lxb_url_t * php_uri_parser_whatwg_resolve_reference_from_zval (
986+ lxb_url_t * lexbor_base_url , const zval * scheme , const zval * username , const zval * password ,
987+ const zval * host , const zval * port , const zval * path , const zval * query , const zval * fragment ,
988+ zval * errors_zv
989+ ) {
990+ lxb_status_t status ;
991+ zval errors ;
992+ ZVAL_UNDEF (& errors );
993+
994+ lxb_url_t * lexbor_url = php_uri_parser_whatwg_clone (lexbor_base_url );
995+ if (Z_TYPE_P (username ) == IS_STRING ) {
996+ status = lxb_url_parse_basic (& lexbor_parser , lexbor_url , lexbor_base_url ,
997+ (lxb_char_t * ) Z_STRVAL_P (username ), Z_STRLEN_P (username ),
998+ LXB_URL_STATE_AUTHORITY_STATE , LXB_ENCODING_AUTO
999+ );
1000+ php_uri_parser_whatwg_build_errors_and_throw (status , "username" , & errors );
1001+ if (status != LXB_STATUS_OK ) {
1002+ goto failure ;
1003+ }
1004+ }
1005+
1006+ if (Z_TYPE_P (password ) == IS_STRING ) {
1007+ status = lxb_url_parse_basic (& lexbor_parser , lexbor_url , lexbor_base_url ,
1008+ (lxb_char_t * ) Z_STRVAL_P (password ), Z_STRLEN_P (password ),
1009+ LXB_URL_STATE_AUTHORITY_STATE , LXB_ENCODING_AUTO
1010+ );
1011+ php_uri_parser_whatwg_build_errors_and_throw (status , "password" , & errors );
1012+ if (status != LXB_STATUS_OK ) {
1013+ goto failure ;
1014+ }
1015+ }
1016+
1017+ if (Z_TYPE_P (host ) == IS_STRING ) {
1018+ lxb_url_host_set_empty (& lexbor_url -> host , & lexbor_mraw );
1019+ status = lxb_url_parse_basic (& lexbor_parser , lexbor_url , lexbor_base_url ,
1020+ (lxb_char_t * ) Z_STRVAL_P (host ), Z_STRLEN_P (host ),
1021+ LXB_URL_STATE_HOST_STATE , LXB_ENCODING_AUTO
1022+ );
1023+ php_uri_parser_whatwg_build_errors_and_throw (status , "host" , & errors );
1024+ if (status != LXB_STATUS_OK ) {
1025+ goto failure ;
1026+ }
1027+ }
1028+
1029+ if (Z_TYPE_P (port ) == IS_LONG ) {
1030+ lexbor_str_t port_str = {0 };
1031+ zval_long_or_null_to_lexbor_str (port , & port_str );
1032+
1033+ status = lxb_url_parse_basic (& lexbor_parser , lexbor_url , lexbor_base_url ,
1034+ port_str .data , port_str .length , LXB_URL_STATE_PORT_STATE , LXB_ENCODING_AUTO
1035+ );
1036+ php_uri_parser_whatwg_build_errors_and_throw (status , "port" , & errors );
1037+ if (status != LXB_STATUS_OK ) {
1038+ goto failure ;
1039+ }
1040+ }
1041+
1042+ if (Z_TYPE_P (path ) == IS_STRING && Z_STRLEN_P (path ) > 0 ) {
1043+ lxb_url_path_set_null (lexbor_url );
1044+ status = lxb_url_parse_basic (& lexbor_parser , lexbor_url , lexbor_base_url ,
1045+ (lxb_char_t * ) Z_STRVAL_P (path ), Z_STRLEN_P (path ),
1046+ lexbor_base_url -> path .opaque ? LXB_URL_STATE_NO_SCHEME_STATE : LXB_URL_STATE_PATH_START_STATE , LXB_ENCODING_AUTO
1047+ );
1048+ php_uri_parser_whatwg_build_errors_and_throw (status , "path" , & errors );
1049+ if (status != LXB_STATUS_OK ) {
1050+ goto failure ;
1051+ }
1052+ } else if (lexbor_base_url -> path .str .data != NULL ) {
1053+ zval zv ;
1054+ ZVAL_NULL (& zv );
1055+ const zend_result result = php_uri_parser_whatwg_query_write (lexbor_url , & zv , NULL );
1056+ php_uri_parser_whatwg_build_errors (& errors );
1057+ if (result == FAILURE ) {
1058+ goto failure ;
1059+ }
1060+ }
1061+
1062+ if (Z_TYPE_P (query ) == IS_STRING ) {
1063+ status = lxb_url_parse_basic (& lexbor_parser , lexbor_url , lexbor_base_url ,
1064+ (lxb_char_t * ) Z_STRVAL_P (query ), Z_STRLEN_P (query ),
1065+ LXB_URL_STATE_QUERY_STATE , LXB_ENCODING_AUTO
1066+ );
1067+ php_uri_parser_whatwg_build_errors_and_throw (status , "query" , & errors );
1068+ if (status != LXB_STATUS_OK ) {
1069+ goto failure ;
1070+ }
1071+ } else if (lexbor_base_url -> query .data != NULL ) {
1072+ zval zv ;
1073+ ZVAL_NULL (& zv );
1074+ const zend_result result = php_uri_parser_whatwg_query_write (lexbor_url , & zv , NULL );
1075+ php_uri_parser_whatwg_build_errors (& errors );
1076+ if (result == FAILURE ) {
1077+ goto failure ;
1078+ }
1079+ }
1080+
1081+ if (Z_TYPE_P (fragment ) == IS_STRING ) {
1082+ status = lxb_url_parse_basic (& lexbor_parser , lexbor_url , lexbor_base_url ,
1083+ (lxb_char_t * ) Z_STRVAL_P (fragment ), Z_STRLEN_P (fragment ),
1084+ LXB_URL_STATE_FRAGMENT_STATE , LXB_ENCODING_AUTO
1085+ );
1086+ php_uri_parser_whatwg_build_errors_and_throw (status , "fragment" , & errors );
1087+ if (status != LXB_STATUS_OK ) {
1088+ goto failure ;
1089+ }
1090+ } else if (lexbor_base_url -> fragment .data != NULL ) {
1091+ zval zv ;
1092+ ZVAL_NULL (& zv );
1093+ const zend_result result = php_uri_parser_whatwg_fragment_write (lexbor_url , & zv , NULL );
1094+ php_uri_parser_whatwg_build_errors (& errors );
1095+ if (result == FAILURE ) {
1096+ goto failure ;
1097+ }
1098+ }
1099+
1100+ if (php_uri_pass_errors_by_ref_and_free (errors_zv , & errors ) == FAILURE ) {
1101+ goto failure ;
1102+ }
1103+
1104+ return lexbor_url ;
1105+
1106+ failure :
1107+ zval_ptr_dtor (& errors );
1108+ lxb_url_destroy (lexbor_url );
1109+ return NULL ;
9651110}
9661111
9671112ZEND_ATTRIBUTE_NONNULL_ARGS (2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) lxb_url_t * php_uri_parser_whatwg_build_from_zval (
9681113 lxb_url_t * lexbor_base_url , const zval * scheme , const zval * username , const zval * password ,
9691114 const zval * host , const zval * port , const zval * path , const zval * query , const zval * fragment ,
9701115 zval * errors_zv
9711116) {
1117+ lxb_url_parser_clean (& lexbor_parser );
1118+
1119+ if (lexbor_base_url != NULL && Z_TYPE_P (scheme ) == IS_STRING && Z_STRLEN_P (scheme ) == 0 ) {
1120+ return php_uri_parser_whatwg_resolve_reference_from_zval (
1121+ lexbor_base_url , scheme , username , password , host , port , path , query , fragment , errors_zv
1122+ );
1123+ }
1124+
9721125 if (Z_TYPE_P (host ) == IS_NULL ||
9731126 Z_STRLEN_P (host ) == 0 ||
9741127 php_uri_parser_whatwg_get_special_scheme (Z_STR_P (scheme )) == LXB_URL_SCHEMEL_TYPE_FILE
@@ -989,8 +1142,6 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh
9891142 }
9901143 }
9911144
992- lxb_url_parser_clean (& lexbor_parser );
993-
9941145 lxb_url_t * lexbor_url = lexbor_mraw_calloc (lexbor_parser .mraw , sizeof (* lexbor_url ));
9951146 if (lexbor_url == NULL ) {
9961147 zend_throw_exception (php_uri_ce_whatwg_invalid_url_exception , "Memory allocation error" , 0 );
@@ -1061,16 +1212,11 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh
10611212 goto failure ;
10621213 }
10631214
1064- if (lexbor_base_url != NULL ) {
1065- /* TODO */
1066- }
1067-
10681215 if (php_uri_pass_errors_by_ref_and_free (errors_zv , & errors ) == FAILURE ) {
10691216 goto failure ;
10701217 }
10711218
10721219 return lexbor_url ;
1073-
10741220failure :
10751221 zval_ptr_dtor (& errors );
10761222 lxb_url_destroy (lexbor_url );
0 commit comments