2 +--------------------------------------------------------------------+
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2004-2005, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
19 #define HTTP_WANT_NETDB
24 #include "php_output.h"
25 #include "ext/standard/url.h"
27 #include "php_http_api.h"
28 #include "php_http_url_api.h"
30 ZEND_EXTERN_MODULE_GLOBALS(http
);
32 /* {{{ char *http_absolute_url(char *) */
33 PHP_HTTP_API
char *_http_absolute_url_ex(
34 const char *url
, size_t url_len
,
35 const char *proto
, size_t proto_len
,
36 const char *host
, size_t host_len
,
37 unsigned port TSRMLS_DC
)
39 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
42 php_url
*purl
= NULL
, furl
;
45 char *scheme
= NULL
, *uri
, *URL
;
47 if ((!url
|| !url_len
) && (
48 (!(url
= SG(request_info
).request_uri
)) ||
49 (!(url_len
= strlen(SG(request_info
).request_uri
))))) {
50 http_error(HE_WARNING
, HTTP_E_RUNTIME
, "Cannot build an absolute URI if supplied URL and REQUEST_URI is empty");
54 uri
= estrndup(url
, url_len
);
55 if (!(purl
= php_url_parse(uri
))) {
57 http_error_ex(HE_WARNING
, HTTP_E_URL
, "Could not parse supplied URL: %s", url
);
61 URL
= ecalloc(1, HTTP_URI_MAXLEN
+ 1);
63 furl
.user
= purl
->user
;
64 furl
.pass
= purl
->pass
;
65 furl
.path
= purl
->path
;
66 furl
.query
= purl
->query
;
67 furl
.fragment
= purl
->fragment
;
69 if (proto
&& proto_len
) {
70 furl
.scheme
= scheme
= estrdup(proto
);
71 } else if (purl
->scheme
) {
72 furl
.scheme
= purl
->scheme
;
73 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
74 } else if (port
&& (se
= getservbyport(htons(port
), "tcp"))) {
75 furl
.scheme
= (scheme
= estrdup(se
->s_name
));
83 } else if (purl
->port
) {
84 furl
.port
= purl
->port
;
85 } else if (strncmp(furl
.scheme
, "http", 4)) {
86 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
87 if ((se
= getservbyname(furl
.scheme
, "tcp"))) {
88 furl
.port
= ntohs(se
->s_port
);
93 furl
.port
= (furl
.scheme
[4] == 's') ? 443 : 80;
96 if (host
&& host_len
) {
97 furl
.host
= (char *) host
;
98 } else if (purl
->host
) {
99 furl
.host
= purl
->host
;
100 } else if ( (zhost
= http_get_server_var("HTTP_HOST")) ||
101 (zhost
= http_get_server_var("SERVER_NAME"))) {
102 furl
.host
= Z_STRVAL_P(zhost
);
104 furl
.host
= "localhost";
107 #define HTTP_URI_STRLCATS(URL, full_len, add_string) HTTP_URI_STRLCAT(URL, full_len, add_string, sizeof(add_string)-1)
108 #define HTTP_URI_STRLCATL(URL, full_len, add_string) HTTP_URI_STRLCAT(URL, full_len, add_string, strlen(add_string))
109 #define HTTP_URI_STRLCAT(URL, full_len, add_string, add_len) \
110 if ((full_len += add_len) > HTTP_URI_MAXLEN) { \
111 http_error_ex(HE_NOTICE, HTTP_E_URL, \
112 "Absolute URI would have exceeded max URI length (%d bytes) - " \
113 "tried to add %d bytes ('%s')", \
114 HTTP_URI_MAXLEN, add_len, add_string); \
118 php_url_free(purl); \
122 strcat(URL, add_string); \
125 HTTP_URI_STRLCATL(URL
, full_len
, furl
.scheme
);
126 HTTP_URI_STRLCATS(URL
, full_len
, "://");
129 HTTP_URI_STRLCATL(URL
, full_len
, furl
.user
);
131 HTTP_URI_STRLCATS(URL
, full_len
, ":");
132 HTTP_URI_STRLCATL(URL
, full_len
, furl
.pass
);
134 HTTP_URI_STRLCATS(URL
, full_len
, "@");
137 HTTP_URI_STRLCATL(URL
, full_len
, furl
.host
);
139 if (( (!strcmp(furl
.scheme
, "http") && (furl
.port
!= 80)) ||
140 (!strcmp(furl
.scheme
, "https") && (furl
.port
!= 443))
141 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
142 || ((!(se
= getservbyname(furl
.scheme
, "tcp"))) || (ntohs(se
->s_port
) != furl
.port
))
145 char port_string
[8] = {0};
146 snprintf(port_string
, 7, ":%u", furl
.port
);
147 HTTP_URI_STRLCATL(URL
, full_len
, port_string
);
151 if (furl
.path
[0] != '/') {
152 HTTP_URI_STRLCATS(URL
, full_len
, "/");
154 HTTP_URI_STRLCATL(URL
, full_len
, furl
.path
);
156 HTTP_URI_STRLCATS(URL
, full_len
, "/");
160 HTTP_URI_STRLCATS(URL
, full_len
, "?");
161 HTTP_URI_STRLCATL(URL
, full_len
, furl
.query
);
165 HTTP_URI_STRLCATS(URL
, full_len
, "#");
166 HTTP_URI_STRLCATL(URL
, full_len
, furl
.fragment
);
179 /* {{{ STATUS http_urlencode_hash_ex(HashTable *, zend_bool, char *, size_t, char **, size_t *) */
180 PHP_HTTP_API STATUS
_http_urlencode_hash_ex(HashTable
*hash
, zend_bool override_argsep
,
181 char *pre_encoded_data
, size_t pre_encoded_len
,
182 char **encoded_data
, size_t *encoded_len TSRMLS_DC
)
186 phpstr
*qstr
= phpstr_new();
188 if (override_argsep
|| !(arg_sep_len
= strlen(arg_sep
= INI_STR("arg_separator.output")))) {
189 arg_sep
= HTTP_URL_ARGSEP
;
190 arg_sep_len
= lenof(HTTP_URL_ARGSEP
);
193 if (pre_encoded_len
&& pre_encoded_data
) {
194 phpstr_append(qstr
, pre_encoded_data
, pre_encoded_len
);
197 if (SUCCESS
!= http_urlencode_hash_recursive(hash
, qstr
, arg_sep
, arg_sep_len
, NULL
, 0)) {
202 phpstr_data(qstr
, encoded_data
, encoded_len
);
209 /* {{{ http_urlencode_hash_recursive */
210 PHP_HTTP_API STATUS
_http_urlencode_hash_recursive(HashTable
*ht
, phpstr
*str
, const char *arg_sep
, size_t arg_sep_len
, const char *prefix
, size_t prefix_len TSRMLS_DC
)
219 http_error(HE_WARNING
, HTTP_E_INVALID_PARAM
, "Invalid parameters");
222 if (ht
->nApplyCount
> 0) {
226 FOREACH_HASH_KEYLENVAL(pos
, ht
, key
, len
, idx
, data
) {
231 if (!data
|| !*data
) {
236 if (len
&& key
[len
- 1] == '\0') {
239 encoded_key
= php_url_encode(key
, len
, &encoded_len
);
242 encoded_len
= spprintf(&encoded_key
, 0, "%ld", idx
);
246 phpstr_init(&new_prefix
);
247 if (prefix
&& prefix_len
) {
248 phpstr_append(&new_prefix
, prefix
, prefix_len
);
249 phpstr_appends(&new_prefix
, "[");
252 phpstr_append(&new_prefix
, encoded_key
, encoded_len
);
255 if (prefix
&& prefix_len
) {
256 phpstr_appends(&new_prefix
, "]");
258 phpstr_fix(&new_prefix
);
261 if (Z_TYPE_PP(data
) == IS_ARRAY
) {
264 status
= http_urlencode_hash_recursive(Z_ARRVAL_PP(data
), str
, arg_sep
, arg_sep_len
, PHPSTR_VAL(&new_prefix
), PHPSTR_LEN(&new_prefix
));
266 if (SUCCESS
!= status
) {
267 phpstr_dtor(&new_prefix
);
273 zval
*cpy
, *val
= convert_to_type_ex(IS_STRING
, *data
, &cpy
);
275 if (PHPSTR_LEN(str
)) {
276 phpstr_append(str
, arg_sep
, arg_sep_len
);
278 phpstr_append(str
, PHPSTR_VAL(&new_prefix
), PHPSTR_LEN(&new_prefix
));
279 phpstr_appends(str
, "=");
281 encoded_val
= php_url_encode(Z_STRVAL_P(val
), Z_STRLEN_P(val
), &encoded_len
);
282 phpstr_append(str
, encoded_val
, encoded_len
);
290 phpstr_dtor(&new_prefix
);
301 * vim600: noet sw=4 ts=4 fdm=marker
302 * vim<600: noet sw=4 ts=4