Skip to content

Commit 12ea97b

Browse files
committed
Try to address comments
1 parent 9b88d13 commit 12ea97b

File tree

6 files changed

+140
-28
lines changed

6 files changed

+140
-28
lines changed

ext/standard/http_fopen_wrapper.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -753,33 +753,32 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
753753

754754
/* auth header if it was specified */
755755
if (((have_header & HTTP_HEADER_AUTH) == 0) && resource->user) {
756-
/* make scratch large enough to hold the whole URL (over-estimate) */
757-
size_t scratch_len = strlen(path) + 1;
758-
char *scratch = emalloc(scratch_len);
756+
smart_str scratch = {0};
759757
zend_string *stmp;
760758

761759
/* decode the strings first */
762760
php_url_decode(ZSTR_VAL(resource->user), ZSTR_LEN(resource->user));
763761

764-
strcpy(scratch, ZSTR_VAL(resource->user));
765-
strcat(scratch, ":");
762+
smart_str_appendl(&scratch, ZSTR_VAL(resource->user), ZSTR_LEN(resource->user));
763+
smart_str_appendc(&scratch, ':');
766764

767765
/* Note: password is optional! */
768766
if (resource->password) {
769767
php_url_decode(ZSTR_VAL(resource->password), ZSTR_LEN(resource->password));
770-
strcat(scratch, ZSTR_VAL(resource->password));
768+
smart_str_appendl(&scratch, ZSTR_VAL(resource->password), ZSTR_LEN(resource->password));
771769
}
772770

773-
stmp = php_base64_encode((unsigned char*)scratch, strlen(scratch));
771+
zend_string *scratch_str = smart_str_extract(&scratch);
772+
stmp = php_base64_encode((unsigned char*)ZSTR_VAL(scratch_str), ZSTR_LEN(scratch_str));
774773

775774
smart_str_appends(&req_buf, "Authorization: Basic ");
776-
smart_str_appends(&req_buf, ZSTR_VAL(stmp));
775+
smart_str_appendl(&req_buf, ZSTR_VAL(stmp), ZSTR_LEN(stmp));
777776
smart_str_appends(&req_buf, "\r\n");
778777

779778
php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, NULL, 0);
780779

781780
zend_string_free(stmp);
782-
efree(scratch);
781+
smart_str_free(&scratch);
783782
}
784783

785784
/* if the user has configured who they are, send a From: line */

ext/standard/url.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -321,12 +321,20 @@ PHPAPI php_url *php_url_parse_ex2(char const *str, size_t length, bool *has_port
321321
return ret;
322322
}
323323

324+
static void parse_url_decode_component(zval *zv, uri_component_read_mode_t read_mode)
325+
{
326+
if (read_mode == URI_COMPONENT_READ_NORMALIZED_ASCII || read_mode == URI_COMPONENT_READ_NORMALIZED_UNICODE) {
327+
php_url_decode(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
328+
}
329+
}
330+
324331
static zend_result parse_url_read_scheme(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval)
325332
{
326333
php_url *parse_url_uri = internal_uri->uri;
327334

328335
if (parse_url_uri->scheme) {
329336
ZVAL_STR_COPY(retval, parse_url_uri->scheme);
337+
parse_url_decode_component(retval, read_mode);
330338
} else {
331339
ZVAL_NULL(retval);
332340
}
@@ -340,6 +348,7 @@ static zend_result parse_url_read_username(const uri_internal_t *internal_uri, u
340348

341349
if (parse_url_uri->user) {
342350
ZVAL_STR_COPY(retval, parse_url_uri->user);
351+
parse_url_decode_component(retval, read_mode);
343352
} else {
344353
ZVAL_NULL(retval);
345354
}
@@ -353,6 +362,7 @@ static zend_result parse_url_read_password(const uri_internal_t *internal_uri, u
353362

354363
if (parse_url_uri->pass) {
355364
ZVAL_STR_COPY(retval, parse_url_uri->pass);
365+
parse_url_decode_component(retval, read_mode);
356366
} else {
357367
ZVAL_NULL(retval);
358368
}
@@ -366,6 +376,7 @@ static zend_result parse_url_read_host(const uri_internal_t *internal_uri, uri_c
366376

367377
if (parse_url_uri->host) {
368378
ZVAL_STR_COPY(retval, parse_url_uri->host);
379+
parse_url_decode_component(retval, read_mode);
369380
} else {
370381
ZVAL_NULL(retval);
371382
}
@@ -379,6 +390,7 @@ static zend_result parse_url_read_port(const uri_internal_t *internal_uri, uri_c
379390

380391
if (parse_url_uri->port) {
381392
ZVAL_LONG(retval, parse_url_uri->port);
393+
parse_url_decode_component(retval, read_mode);
382394
} else {
383395
ZVAL_NULL(retval);
384396
}
@@ -392,6 +404,7 @@ static zend_result parse_url_read_path(const uri_internal_t *internal_uri, uri_c
392404

393405
if (parse_url_uri->path) {
394406
ZVAL_STR_COPY(retval, parse_url_uri->path);
407+
parse_url_decode_component(retval, read_mode);
395408
} else {
396409
ZVAL_NULL(retval);
397410
}
@@ -405,6 +418,7 @@ static zend_result parse_url_read_query(const uri_internal_t *internal_uri, uri_
405418

406419
if (parse_url_uri->query) {
407420
ZVAL_STR_COPY(retval, parse_url_uri->query);
421+
parse_url_decode_component(retval, read_mode);
408422
} else {
409423
ZVAL_NULL(retval);
410424
}
@@ -418,18 +432,14 @@ static zend_result parse_url_read_fragment(const uri_internal_t *internal_uri, u
418432

419433
if (parse_url_uri->fragment) {
420434
ZVAL_STR_COPY(retval, parse_url_uri->fragment);
435+
parse_url_decode_component(retval, read_mode);
421436
} else {
422437
ZVAL_NULL(retval);
423438
}
424439

425440
return SUCCESS;
426441
}
427442

428-
static void *parse_url_clone_uri(void *uri)
429-
{
430-
ZEND_UNREACHABLE();
431-
}
432-
433443
static void throw_invalid_uri_exception(void)
434444
{
435445
zend_throw_exception(uri_invalid_uri_exception_ce, "The specified URI is malformed", 0);
@@ -447,16 +457,11 @@ static void *parse_url_parse_uri(const char *uri_str, size_t uri_str_len, const
447457
return url;
448458
}
449459

450-
static zend_string *parse_url_uri_to_string(void *uri, uri_recomposition_mode_t recomposition_mode, bool exclude_fragment)
451-
{
452-
ZEND_UNREACHABLE();
453-
}
454-
455460
const uri_handler_t parse_url_uri_handler = {
456461
.name = URI_PARSER_PHP,
457462
.parse_uri = parse_url_parse_uri,
458-
.clone_uri = parse_url_clone_uri,
459-
.uri_to_string = parse_url_uri_to_string,
463+
.clone_uri = NULL,
464+
.uri_to_string = NULL,
460465
.free_uri = parse_url_free_uri,
461466
{
462467
.scheme = {.read_func = parse_url_read_scheme, .write_func = NULL},

ext/uri/php_uri.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,11 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_get_property(const uri_interna
136136
return FAILURE;
137137
}
138138

139-
return property_handler->read_func(internal_uri, read_mode, zv);
139+
zend_result result = property_handler->read_func(internal_uri, read_mode, zv);
140+
141+
ZEND_ASSERT((Z_TYPE_P(zv) == IS_STRING && GC_REFCOUNT(Z_STR_P(zv)) == 2) || Z_TYPE_P(zv) == IS_NULL || Z_TYPE_P(zv) == IS_LONG);
142+
143+
return result;
140144
}
141145

142146
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_scheme(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv)
@@ -1015,10 +1019,10 @@ zend_result uri_handler_register(const uri_handler_t *uri_handler)
10151019
{
10161020
zend_string *key = zend_string_init_interned(uri_handler->name, strlen(uri_handler->name), 1);
10171021

1018-
ZEND_ASSERT(uri_handler->name != NULL);
1022+
ZEND_ASSERT(uri_handler->name != NULL && (strlen(uri_handler->name) > 0 || strcmp(uri_handler->name, URI_PARSER_PHP) == 0));
10191023
ZEND_ASSERT(uri_handler->parse_uri != NULL);
1020-
ZEND_ASSERT(uri_handler->clone_uri != NULL);
1021-
ZEND_ASSERT(uri_handler->uri_to_string != NULL);
1024+
ZEND_ASSERT(uri_handler->clone_uri != NULL || strcmp(uri_handler->name, URI_PARSER_PHP) == 0);
1025+
ZEND_ASSERT(uri_handler->uri_to_string != NULL || strcmp(uri_handler->name, URI_PARSER_PHP) == 0);
10221026
ZEND_ASSERT(uri_handler->free_uri != NULL);
10231027

10241028
zend_result result = zend_hash_add_ptr(&uri_handlers, key, (void *) uri_handler) != NULL ? SUCCESS : FAILURE;

ext/uri/php_uri.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,84 @@ typedef struct php_uri {
3535

3636
PHPAPI uri_handler_t *php_uri_get_handler(const zend_string *uri_handler_name);
3737
ZEND_ATTRIBUTE_NONNULL PHPAPI uri_internal_t *php_uri_parse(const uri_handler_t *uri_handler, const char *uri_str, size_t uri_str_len, bool silent);
38+
/**
39+
* Passes the scheme component as a new string or null to the zv zval in case of success.
40+
*
41+
* @param internal_uri The input struct
42+
* @param read_mode
43+
* @param zv The output parameter
44+
* @return SUCCESS in case of success, FAILURE otherwise.
45+
*/
3846
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_scheme(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
47+
/**
48+
* Passes the username component as a new string or null to the zv zval in case of success.
49+
*
50+
* @param internal_uri The input struct
51+
* @param read_mode
52+
* @param zv The output parameter
53+
* @return SUCCESS in case of success, FAILURE otherwise.
54+
*/
3955
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_username(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
56+
/**
57+
* Passes the password component as a new string or null to the zv zval in case of success.
58+
*
59+
* @param internal_uri The input struct
60+
* @param read_mode
61+
* @param zv The output parameter
62+
* @return SUCCESS in case of success, FAILURE otherwise.
63+
*/
4064
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_password(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
65+
/**
66+
* Passes the host component as a new string or null to the zv zval in case of success.
67+
*
68+
* @param internal_uri The input struct
69+
* @param read_mode
70+
* @param zv The output parameter
71+
* @return SUCCESS in case of success, FAILURE otherwise.
72+
*/
4173
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_host(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
74+
/**
75+
* Passes the port component as a long or null to the zv zval in case of success.
76+
*
77+
* @param internal_uri The input struct
78+
* @param read_mode
79+
* @param zv The output parameter
80+
* @return SUCCESS in case of success, FAILURE otherwise.
81+
*/
4282
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_port(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
83+
/**
84+
* Passes the path component as a new string to the zv zval in case of success.
85+
*
86+
* @param internal_uri The input struct
87+
* @param read_mode
88+
* @param zv The output parameter
89+
* @return SUCCESS in case of success, FAILURE otherwise.
90+
*/
4391
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_path(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
92+
/**
93+
* Passes the query component as a new string to the zv zval in case of success.
94+
*
95+
* @param internal_uri The input struct
96+
* @param read_mode
97+
* @param zv The output parameter
98+
* @return SUCCESS in case of success, FAILURE otherwise.
99+
*/
44100
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_query(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
101+
/**
102+
* Passes the fragment component as a new string to the zv zval in case of success.
103+
*
104+
* @param internal_uri The input struct
105+
* @param read_mode
106+
* @param zv The output parameter
107+
* @return SUCCESS in case of success, FAILURE otherwise.
108+
*/
45109
ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_fragment(const uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *zv);
46110
ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_free(uri_internal_t *internal_uri);
111+
/**
112+
* Returns a new php_uri containing the URI fields.
113+
*
114+
* @return the php_uri in case of success, NULL otherwise
115+
*/
47116
ZEND_ATTRIBUTE_NONNULL PHPAPI php_uri *php_uri_parse_to_struct(
48117
const uri_handler_t *uri_handler, const char *uri_str, size_t uri_str_len, uri_component_read_mode_t read_mode, bool silent
49118
);

ext/uri/php_uri_common.h

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ typedef struct uri_property_handlers_t {
7676
} uri_property_handlers_t;
7777

7878
typedef struct uri_handler_t {
79+
/**
80+
* Name (usually the FQCN) of the URI handler.
81+
*/
7982
const char *name;
8083

8184
/**
@@ -93,10 +96,43 @@ typedef struct uri_handler_t {
9396
*
9497
* If the silent parameter is true, a Uri\InvalidUriException instance must be thrown.
9598
* If the parameter is false, the possible errors should be handled by the caller.
99+
*
100+
* @param uri_str The input string
101+
* @param uri_str_len Length of the input string
102+
* @param base_url The base URI if reference resolution should be performed, otherwise NULL
103+
* @param errors An out parameter that stores additional error information
104+
* @param silent Whether to throw a Uri\InvalidUriException in case of failure
96105
*/
97106
void *(*parse_uri)(const char *uri_str, size_t uri_str_len, const void *base_url, zval *errors, bool silent);
107+
/**
108+
* Clone a URI to a new URI.
109+
*
110+
* A deep-clone must be performed that copies all pointer members to a new memory address.
111+
* @param uri The input URI
112+
* @return The copied URI
113+
*/
98114
void *(*clone_uri)(void *uri);
115+
/**
116+
* Recomposes a URI as a string according to the recomposition_mode and exclude_fragment parameters.
117+
* The return value must not be persistent.
118+
*
119+
* Recomposition_mode can be one of the following:
120+
* - URI_RECOMPOSITION_RAW_ASCII: Recomposes the raw, non-normalized variant of the URI as a string that may contain only ASCII characters
121+
* - URI_RECOMPOSITION_RAW_UNICODE: Recomposes the raw, non-normalized variant of the URI as a string that may contain UNICODE codepoints
122+
* - URI_RECOMPOSITION_NORMALIZED_ASCII: Recomposes the normalized variant of the URI as a string that may contain only ASCII characters
123+
* - URI_RECOMPOSITION_NORMALIZED_UNICODE: Recomposes the normalized variant of the URI as a string that may contain UNICODE codepoints
124+
*
125+
* @param uri The input URI
126+
* @param recomposition_mode The type of recomposition
127+
* @param exclude_fragment Whether the fragment component should be part of the recomposed URI
128+
* @return The recomposed URI as a non-persistent zend_string
129+
*/
99130
zend_string *(*uri_to_string)(void *uri, uri_recomposition_mode_t recomposition_mode, bool exclude_fragment);
131+
/**
132+
* Frees the provided URI.
133+
*
134+
* @param uri The input URI
135+
*/
100136
void (*free_uri)(void *uri);
101137

102138
const uri_property_handlers_t property_handlers;
@@ -125,7 +161,7 @@ static inline uri_internal_t *uri_internal_from_obj(const zend_object *object) {
125161

126162
#define URI_PARSER_RFC3986 "Uri\\Rfc3986\\Uri"
127163
#define URI_PARSER_WHATWG "Uri\\WhatWg\\Url"
128-
#define URI_PARSER_PHP "parse_url"
164+
#define URI_PARSER_PHP ""
129165
#define URI_SERIALIZED_PROPERTY_NAME "uri"
130166

131167
zend_result uri_handler_register(const uri_handler_t *uri_handler);

ext/uri/php_uriparser.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,8 +352,7 @@ void *uriparser_parse_uri(const char *uri_str, size_t uri_str_len, const void *b
352352
return uriparser_parse_uri_ex(uri_str, uri_str_len, base_url, silent);
353353
}
354354

355-
/* TODO make the clone handler accept a flag to distinguish between clone() calls and withers.
356-
* When calling a wither successfully, the normalized URI is surely invalidated, therefore
355+
/* When calling a wither successfully, the normalized URI is surely invalidated, therefore
357356
* it doesn't make sense to copy it. In case of failure, an exception is thrown, and the URI object
358357
* is discarded altogether. */
359358
ZEND_ATTRIBUTE_NONNULL static void *uriparser_clone_uri(void *uri)

0 commit comments

Comments
 (0)