# include <idn2.h>
#endif
#if PHP_HTTP_HAVE_LIBICU
+# include <unicode/uchar.h>
# include <unicode/uidna.h>
#endif
#if PHP_HTTP_HAVE_LIBIDNKIT || PHP_HTTP_HAVE_LIBIDNKIT2
static inline char *localhostname(void)
{
char hostname[1024] = {0};
-
+
#if PHP_WIN32
if (SUCCESS == gethostname(hostname, lenof(hostname))) {
return estrdup(hostname);
if (!(flags & PHP_HTTP_URL_STRIP_PASS)) {
url_copy(pass);
}
-
+
url_copy(host);
-
+
if (!(flags & PHP_HTTP_URL_STRIP_PORT)) {
url(buf)->port = url_isset(new_url, port) ? new_url->port : ((old_url) ? old_url->port : 0);
}
if ((flags & PHP_HTTP_URL_JOIN_PATH) && url_isset(old_url, path) && url_isset(new_url, path) && *new_url->path != '/') {
size_t old_path_len = strlen(old_url->path), new_path_len = strlen(new_url->path);
char *path = ecalloc(1, old_path_len + new_path_len + 1 + 1);
-
+
strcat(path, old_url->path);
if (path[old_path_len - 1] != '/') {
php_dirname(path, old_path_len);
strcat(path, "/");
}
strcat(path, new_url->path);
-
+
url(buf)->path = &buf.data[buf.used];
if (path[0] != '/') {
url_append(&buf, php_http_buffer_append(&buf, "/", 1));
if (!(flags & PHP_HTTP_URL_STRIP_QUERY)) {
if ((flags & PHP_HTTP_URL_JOIN_QUERY) && url_isset(new_url, query) && url_isset(old_url, query)) {
zval qarr, qstr;
-
+
array_init(&qarr);
-
+
ZVAL_STRING(&qstr, old_url->query);
php_http_querystring_update(&qarr, &qstr, NULL);
zval_ptr_dtor(&qstr);
ZVAL_STRING(&qstr, new_url->query);
php_http_querystring_update(&qarr, &qstr, NULL);
zval_ptr_dtor(&qstr);
-
+
ZVAL_NULL(&qstr);
php_http_querystring_update(&qarr, NULL, &qstr);
if (!(flags & PHP_HTTP_URL_STRIP_FRAGMENT)) {
url_copy(fragment);
}
-
+
/* done with copy & combine & strip */
if (flags & PHP_HTTP_URL_FROM_ENV) {
&& url(buf)->path
&& url(buf)->path[0] && url(buf)->path[1]) {
char *ptr, *end = url(buf)->path + strlen(url(buf)->path) + 1;
-
+
for (ptr = strchr(url(buf)->path, '/'); ptr; ptr = strchr(ptr, '/')) {
switch (ptr[1]) {
case '/':
memmove(&ptr[1], &ptr[2], end - &ptr[2]);
break;
-
+
case '.':
switch (ptr[2]) {
case '\0':
url(buf)->port = 0;
}
}
-
+
return url(buf);
}
if (!strct || Z_TYPE_P(strct) == IS_ARRAY) { \
zend_hash_str_update(ht, part, lenof(part), &tmp); \
} else { \
- zend_update_property(Z_OBJCE_P(strct), strct, part, lenof(part), &tmp); \
+ zend_update_property(Z_OBJCE_P(strct), Z_OBJ_P(strct), part, lenof(part), &tmp); \
zval_ptr_dtor(&tmp); \
}
return cpy;
}
-static size_t parse_mb_utf8(unsigned *wc, const char *ptr, const char *end)
+static inline size_t parse_mb_utf8(unsigned *wc, const char *ptr, const char *end)
{
unsigned wchar;
size_t consumed = utf8towc(&wchar, (const unsigned char *) ptr, end - ptr);
}
#if PHP_HTTP_HAVE_WCHAR
-static size_t parse_mb_loc(unsigned *wc, const char *ptr, const char *end)
+static inline size_t parse_mb_loc(unsigned *wc, const char *ptr, const char *end)
{
wchar_t wchar;
size_t consumed = 0;
static const char parse_xdigits[] = "0123456789ABCDEF";
-static size_t parse_mb(struct parse_state *state, parse_mb_what_t what, const char *ptr, const char *end, const char *begin, zend_bool force_silent)
+static inline size_t parse_mb(struct parse_state *state, parse_mb_what_t what, const char *ptr, const char *end, const char *begin, zend_bool force_silent)
{
unsigned wchar;
size_t consumed = 0;
if (what == PARSE_HOSTINFO && (state->flags & PHP_HTTP_URL_PARSE_TOIDN)) {
/* idna */
} else if (state->flags & PHP_HTTP_URL_PARSE_MBUTF8) {
+#if PHP_HTTP_HAVE_LIBICU
+ if (!u_isalnum(wchar)) {
+#else
if (!isualnum(wchar)) {
+#endif
break;
}
#if PHP_HTTP_HAVE_WCHAR
}
#endif
}
- PHP_HTTP_DUFF(consumed, state->buffer[state->offset++] = *ptr++);
+
+ memcpy(&state->buffer[state->offset], ptr, consumed);
+ state->offset += consumed;
} else {
- int i = 0;
-
- PHP_HTTP_DUFF(consumed,
- state->buffer[state->offset++] = '%';
- state->buffer[state->offset++] = parse_xdigits[((unsigned char) ptr[i]) >> 4];
- state->buffer[state->offset++] = parse_xdigits[((unsigned char) ptr[i]) & 0xf];
- ++i;
- );
+ size_t i;
+
+ for (i = 0; i < consumed; ++i) {
+ state->buffer[state->offset++] = '%';
+ state->buffer[state->offset++] = parse_xdigits[((unsigned char) ptr[i]) >> 4];
+ state->buffer[state->offset++] = parse_xdigits[((unsigned char) ptr[i]) & 0xf];
+ }
}
return consumed;
typedef enum { U_ZERO_ERROR = 0 } UErrorCode;
int32_t uidna_IDNToASCII(const UChar *src, int32_t srcLength, UChar *dest, int32_t destCapacity, int32_t options, void *parseError, UErrorCode *status);
# endif
-static ZEND_RESULT_CODE parse_uidn_2003(struct parse_state *state)
+static ZEND_RESULT_CODE parse_uidn_2003(struct parse_state *state, size_t prev_len)
{
- char *host_ptr = state->url.host, ebuf[64] = {0}, *error = NULL;
- uint16_t *uhost_str, ahost_str[256], *ahost_ptr;
+ char ebuf[64] = {0}, *error = NULL;
+ uint16_t *uhost_str, ahost_str[256];
size_t uhost_len, ahost_len;
UErrorCode rc = U_ZERO_ERROR;
# endif
efree(uhost_str);
- if (error > U_ZERO_ERROR) {
+ if (rc > U_ZERO_ERROR) {
goto error;
}
- ahost_ptr = ahost_str;
- PHP_HTTP_DUFF(ahost_len, *host_ptr++ = *ahost_ptr++);
- *host_ptr = '\0';
- state->offset += host_ptr - state->url.host;
+ state->url.host[ahost_len] = '\0';
+ state->offset += ahost_len - prev_len;
+ while (ahost_len--) {
+ state->url.host[ahost_len] = ahost_str[ahost_len];
+ }
return SUCCESS;
#endif
#if PHP_HTTP_HAVE_LIBICU && HAVE_UIDNA_NAMETOASCII_UTF8
-static ZEND_RESULT_CODE parse_uidn_2008(struct parse_state *state)
+static ZEND_RESULT_CODE parse_uidn_2008(struct parse_state *state, size_t prev_len)
{
- char *host_ptr, *error = NULL, ebuf[64] = {0};
+ char *error = NULL, ebuf[64] = {0};
UErrorCode rc = U_ZERO_ERROR;
UIDNAInfo info = UIDNA_INFO_INITIALIZER;
UIDNA *uidna = uidna_openUTS46(UIDNA_ALLOW_UNASSIGNED, &rc);
return FAILURE;
}
- host_ptr = state->url.host;
-
if (state->flags & PHP_HTTP_URL_PARSE_MBUTF8) {
- char ahost_str[256], *ahost_ptr = &ahost_str[0];
- size_t ahost_len = uidna_nameToASCII_UTF8(uidna, host_ptr, -1, ahost_str, sizeof(ahost_str)-1, &info, &rc);
+ char ahost_str[256];
+ size_t ahost_len = uidna_nameToASCII_UTF8(uidna, state->url.host, -1, ahost_str, sizeof(ahost_str)-1, &info, &rc);
if (U_FAILURE(rc) || info.errors) {
goto error;
}
- PHP_HTTP_DUFF(ahost_len, *host_ptr++ = *ahost_ptr++);
+
+ memcpy(state->url.host, ahost_str, ahost_len);
+ state->url.host[ahost_len] = '\0';
+ state->offset += ahost_len - prev_len;
+
#if PHP_HTTP_HAVE_WCHAR
} else if (state->flags & PHP_HTTP_URL_PARSE_MBLOC) {
- uint16_t *uhost_str, whost_str[256], *whost_ptr = &whost_str[0];
+ uint16_t *uhost_str, whost_str[256];
size_t uhost_len, whost_len;
- if (SUCCESS != to_utf16(parse_mb_loc, host_ptr, &uhost_str, &uhost_len)) {
+ if (SUCCESS != to_utf16(parse_mb_loc, state->url.host, &uhost_str, &uhost_len)) {
error = "could not convert to UTF-16";
goto error;
}
whost_len = uidna_nameToASCII(uidna, uhost_str, uhost_len, whost_str, sizeof(whost_str)-1, &info, &rc);
- whost_ptr = whost_str;
efree(uhost_str);
+
if (U_FAILURE(rc) || info.errors) {
goto error;
}
- PHP_HTTP_DUFF(whost_len, *host_ptr++ = *whost_ptr++);
+
+ state->url.host[whost_len] = '\0';
+ state->offset += whost_len - prev_len;
+ while (whost_len--) {
+ state->url.host[whost_len] = whost_str[whost_len];
+ }
#endif
} else {
error = "codepage not specified";
goto error;
}
- *host_ptr = '\0';
- state->offset += host_ptr - state->url.host;
-
uidna_close(uidna);
return SUCCESS;
# if __GNUC__
__attribute__ ((unused))
# endif
-static ZEND_RESULT_CODE parse_kidn(struct parse_state *state)
+static ZEND_RESULT_CODE parse_kidn(struct parse_state *state, size_t prev_len)
{
idn_result_t rc;
#if PHP_HTTP_HAVE_LIBIDNKIT
#elif PHP_HTTP_HAVE_LIBIDNKIT2
int actions = IDN_MAP|IDN_ASCLOWER|IDN_RTCONV|IDN_PROHCHECK|IDN_NFCCHECK|IDN_PREFCHECK|IDN_COMBCHECK|IDN_CTXOLITECHECK|IDN_BIDICHECK|IDN_LOCALCHECK|IDN_IDNCONV|IDN_LENCHECK|IDN_RTCHECK;
#endif
- char ahost_str[256] = {0}, *ahost_ptr = &ahost_str[0], *host_ptr = state->url.host;
+ char ahost_str[256] = {0};
if (state->flags & PHP_HTTP_URL_PARSE_MBLOC) {
#if PHP_HTTP_HAVE_LIBIDNKIT
rc = idn_encodename(actions, state->url.host, ahost_str, 256);
if (rc == idn_success) {
- PHP_HTTP_DUFF(strlen(ahost_str), *host_ptr++ = *ahost_ptr++);
+ size_t ahost_len = strlen(ahost_str);
- *host_ptr = '\0';
- state->offset += host_ptr - state->url.host;
+ memcpy(state->url.host, ahost_str, ahost_len + 1);
+ state->offset += ahost_len - prev_len;
return SUCCESS;
} else {
#endif
#if 0 && PHP_WIN32
-static ZEND_RESULT_CODE parse_widn_2003(struct parse_state *state)
+static ZEND_RESULT_CODE parse_widn_2003(struct parse_state *state, size_t prev_len)
{
char *host_ptr;
- uint16_t *uhost_str, ahost_str[256], *ahost_ptr;
- size_t uhost_len;
+ uint16_t *uhost_str, ahost_str[256];
+ size_t uhost_len, ahost_len;
if (state->flags & PHP_HTTP_URL_PARSE_MBUTF8) {
if (SUCCESS != to_utf16(parse_mb_utf8, state->url.host, &uhost_str, &uhost_len)) {
}
efree(uhost_str);
- host_ptr = state->url.host;
- ahost_ptr = ahost_str;
- PHP_HTTP_DUFF(wcslen(ahost_str), *host_ptr++ = *ahost_ptr++);
-
- *host_ptr = '\0';
- state->offset += host_ptr - state->url.host;
+ ahost_len = wcslen(ahost_str);
+ state->url.host[ahost_len] = '\0';
+ state->offset += ahost_len - prev_len;
+ while (ahost_len--) {
+ state->url.host[ahost_len] = ahost_str[ahost_len];
+ }
return SUCCESS;
}
# endif
) {
#if PHP_HTTP_HAVE_LIBICU && HAVE_UIDNA_NAMETOASCII_UTF8
- return parse_uidn_2008(state);
+ return parse_uidn_2008(state, len);
#elif PHP_HTTP_HAVE_LIBIDN2
return parse_gidn_2008(state, len);
#elif PHP_HTTP_HAVE_LIBIDNKIT2
- return parse_kidn(state);
+ return parse_kidn(state, len);
#endif
}
#endif
#endif
) {
#if HAVE_UIDNA_IDNTOASCII
- return parse_uidn_2003(state);
+ return parse_uidn_2003(state, len);
#elif PHP_HTTP_HAVE_LIBIDN
return parse_gidn_2003(state, len);
#elif PHP_HTTP_HAVE_LIBIDNKIT
- return parse_kidn(state);
+ return parse_kidn(state, len);
#endif
}
#endif
#if 0 && PHP_WIN32
- return parse_widn_2003(state);
+ return parse_widn_2003(state, len);
#endif
#if PHP_HTTP_HAVE_LIBICU && HAVE_UIDNA_NAMETOASCII_UTF8
- return parse_uidn_2008(state);
+ return parse_uidn_2008(state, len);
#elif PHP_HTTP_HAVE_LIBIDN2
return parse_gidn_2008(state, len);
#elif PHP_HTTP_HAVE_LIBIDNKIT2
- return parse_kidn(state);
+ return parse_kidn(state, len);
#elif HAVE_UIDNA_IDNTOASCII
- return parse_uidn_2003(state);
+ return parse_uidn_2003(state, len);
#elif PHP_HTTP_HAVE_LIBIDN
return parse_gidn_2003(state, len);
#elif PHP_HTTP_HAVE_LIBIDNKIT
- return parse_kidn(state);
+ return parse_kidn(state, len);
#endif
return SUCCESS;
state->maxlen = maxlen;
if (!parse_scheme(state)) {
- php_error_docref(NULL, E_WARNING, "Failed to parse URL scheme: '%s'", state->ptr);
+ if (!(flags & PHP_HTTP_URL_SILENT_ERRORS)) {
+ php_error_docref(NULL, E_WARNING, "Failed to parse URL scheme: '%s'", state->ptr);
+ }
efree(state);
return NULL;
}
}
if (!parse_query(state)) {
- php_error_docref(NULL, E_WARNING, "Failed to parse URL query: '%s'", state->ptr);
+ if (!(flags & PHP_HTTP_URL_SILENT_ERRORS)) {
+ php_error_docref(NULL, E_WARNING, "Failed to parse URL query: '%s'", state->ptr);
+ }
efree(state);
return NULL;
}
if (!parse_fragment(state)) {
- php_error_docref(NULL, E_WARNING, "Failed to parse URL fragment: '%s'", state->ptr);
+ if (!(flags & PHP_HTTP_URL_SILENT_ERRORS)) {
+ php_error_docref(NULL, E_WARNING, "Failed to parse URL fragment: '%s'", state->ptr);
+ }
efree(state);
return NULL;
}
flags |= PHP_HTTP_URL_FROM_ENV;
}
- if (flags & PHP_HTTP_URL_SILENT_ERRORS) {
- zend_replace_error_handling(EH_SUPPRESS, NULL, &zeh);
- } else if (flags & PHP_HTTP_URL_IGNORE_ERRORS) {
+ if (flags & (PHP_HTTP_URL_SILENT_ERRORS|PHP_HTTP_URL_IGNORE_ERRORS)) {
zend_replace_error_handling(EH_NORMAL, NULL, &zeh);
} else {
zend_replace_error_handling(EH_THROW, php_http_get_exception_bad_url_class_entry(), &zeh);
php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "z!|l", &new_url, &flags), invalid_arg, return);
- if (flags & PHP_HTTP_URL_SILENT_ERRORS) {
- zend_replace_error_handling(EH_SUPPRESS, NULL, &zeh);
- } else if (flags & PHP_HTTP_URL_IGNORE_ERRORS) {
+ if (flags & (PHP_HTTP_URL_SILENT_ERRORS|PHP_HTTP_URL_IGNORE_ERRORS)) {
zend_replace_error_handling(EH_NORMAL, NULL, &zeh);
} else {
zend_replace_error_handling(EH_THROW, php_http_get_exception_bad_url_class_entry(), &zeh);
if ((old_purl = php_http_url_from_struct(HASH_OF(getThis())))) {
php_http_url_t *res_purl;
- ZVAL_OBJ(return_value, zend_objects_clone_obj(getThis()));
+ ZVAL_OBJ(return_value, zend_objects_clone_obj(Z_OBJ_P(getThis())));
res_purl = php_http_url_mod(old_purl, new_purl, flags);
php_http_url_to_struct(res_purl, return_value);
}
static zend_function_entry php_http_url_methods[] = {
- PHP_ME(HttpUrl, __construct, ai_HttpUrl___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
+ PHP_ME(HttpUrl, __construct, ai_HttpUrl___construct, ZEND_ACC_PUBLIC)
PHP_ME(HttpUrl, mod, ai_HttpUrl_mod, ZEND_ACC_PUBLIC)
PHP_ME(HttpUrl, toString, ai_HttpUrl_toString, ZEND_ACC_PUBLIC)
ZEND_MALIAS(HttpUrl, __toString, toString, ai_HttpUrl_toString, ZEND_ACC_PUBLIC)
#endif
zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("PARSE_TOPCT"), PHP_HTTP_URL_PARSE_TOPCT);
- INIT_NS_CLASS_ENTRY(ce, "http\\Env", "Url", php_http_url_methods);
- php_http_env_url_class_entry = zend_register_internal_class_ex(&ce, php_http_url_class_entry);
-
zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("IGNORE_ERRORS"), PHP_HTTP_URL_IGNORE_ERRORS);
zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("SILENT_ERRORS"), PHP_HTTP_URL_SILENT_ERRORS);
zend_declare_class_constant_long(php_http_url_class_entry, ZEND_STRL("STDFLAGS"), PHP_HTTP_URL_STDFLAGS);
+ INIT_NS_CLASS_ENTRY(ce, "http\\Env", "Url", NULL);
+ php_http_env_url_class_entry = zend_register_internal_class_ex(&ce, php_http_url_class_entry);
+
return SUCCESS;
}