2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.0 of the PHP license, that |
6 | is bundled with this package in the file LICENSE, and is available |
7 | through the world-wide-web at http://www.php.net/license/3_0.txt. |
8 | If you did not receive a copy of the PHP license and are unable to |
9 | obtain it through the world-wide-web, please send a note to |
10 | license@php.net so we can mail you a copy immediately. |
11 +----------------------------------------------------------------------+
12 | Copyright (c) 2004-2005 Michael Wallner <mike@php.net> |
13 +----------------------------------------------------------------------+
25 #include "php_output.h"
26 #include "ext/standard/url.h"
29 #include "php_http_api.h"
30 #include "php_http_url_api.h"
31 #include "php_http_std_defs.h"
33 #include "phpstr/phpstr.h"
36 # include <winsock2.h>
37 #elif defined(HAVE_NETDB_H)
41 ZEND_EXTERN_MODULE_GLOBALS(http
);
43 /* {{{ char *http_absolute_url(char *) */
44 PHP_HTTP_API
char *_http_absolute_url_ex(
45 const char *url
, size_t url_len
,
46 const char *proto
, size_t proto_len
,
47 const char *host
, size_t host_len
,
48 unsigned port TSRMLS_DC
)
50 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
53 php_url
*purl
= NULL
, furl
;
56 char *scheme
= NULL
, *uri
, *URL
;
58 if ((!url
|| !url_len
) && (
59 (!(url
= SG(request_info
).request_uri
)) ||
60 (!(url_len
= strlen(SG(request_info
).request_uri
))))) {
61 http_error(HE_WARNING
, HTTP_E_RUNTIME
, "Cannot build an absolute URI if supplied URL and REQUEST_URI is empty");
65 URL
= ecalloc(1, HTTP_URI_MAXLEN
+ 1);
66 uri
= estrndup(url
, url_len
);
67 if (!(purl
= php_url_parse(uri
))) {
68 http_error_ex(HE_WARNING
, HTTP_E_URL
, "Could not parse supplied URL: %s", url
);
72 furl
.user
= purl
->user
;
73 furl
.pass
= purl
->pass
;
74 furl
.path
= purl
->path
;
75 furl
.query
= purl
->query
;
76 furl
.fragment
= purl
->fragment
;
78 if (proto
&& proto_len
) {
79 furl
.scheme
= scheme
= estrdup(proto
);
80 } else if (purl
->scheme
) {
81 furl
.scheme
= purl
->scheme
;
82 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
83 } else if (port
&& (se
= getservbyport(port
, "tcp"))) {
84 furl
.scheme
= (scheme
= estrdup(se
->s_name
));
92 } else if (purl
->port
) {
93 furl
.port
= purl
->port
;
94 } else if (strncmp(furl
.scheme
, "http", 4)) {
95 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
96 if (se
= getservbyname(furl
.scheme
, "tcp")) {
97 furl
.port
= se
->s_port
;
101 furl
.port
= (furl
.scheme
[4] == 's') ? 443 : 80;
105 furl
.host
= (char *) host
;
106 } else if (purl
->host
) {
107 furl
.host
= purl
->host
;
108 } else if ( (zhost
= http_get_server_var("HTTP_HOST")) ||
109 (zhost
= http_get_server_var("SERVER_NAME"))) {
110 furl
.host
= Z_STRVAL_P(zhost
);
112 furl
.host
= "localhost";
115 #define HTTP_URI_STRLCATS(URL, full_len, add_string) HTTP_URI_STRLCAT(URL, full_len, add_string, sizeof(add_string)-1)
116 #define HTTP_URI_STRLCATL(URL, full_len, add_string) HTTP_URI_STRLCAT(URL, full_len, add_string, strlen(add_string))
117 #define HTTP_URI_STRLCAT(URL, full_len, add_string, add_len) \
118 if ((full_len += add_len) > HTTP_URI_MAXLEN) { \
119 http_error_ex(HE_NOTICE, HTTP_E_URL, \
120 "Absolute URI would have exceeded max URI length (%d bytes) - " \
121 "tried to add %d bytes ('%s')", \
122 HTTP_URI_MAXLEN, add_len, add_string); \
126 php_url_free(purl); \
130 strcat(URL, add_string); \
133 HTTP_URI_STRLCATL(URL
, full_len
, furl
.scheme
);
134 HTTP_URI_STRLCATS(URL
, full_len
, "://");
137 HTTP_URI_STRLCATL(URL
, full_len
, furl
.user
);
139 HTTP_URI_STRLCATS(URL
, full_len
, ":");
140 HTTP_URI_STRLCATL(URL
, full_len
, furl
.pass
);
142 HTTP_URI_STRLCATS(URL
, full_len
, "@");
145 HTTP_URI_STRLCATL(URL
, full_len
, furl
.host
);
147 if ( (!strcmp(furl
.scheme
, "http") && (furl
.port
!= 80)) ||
148 (!strcmp(furl
.scheme
, "https") && (furl
.port
!= 443))) {
149 char port_string
[8] = {0};
150 snprintf(port_string
, 7, ":%u", furl
.port
);
151 HTTP_URI_STRLCATL(URL
, full_len
, port_string
);
155 if (furl
.path
[0] != '/') {
156 HTTP_URI_STRLCATS(URL
, full_len
, "/");
158 HTTP_URI_STRLCATL(URL
, full_len
, furl
.path
);
160 HTTP_URI_STRLCATS(URL
, full_len
, "/");
164 HTTP_URI_STRLCATS(URL
, full_len
, "?");
165 HTTP_URI_STRLCATL(URL
, full_len
, furl
.query
);
169 HTTP_URI_STRLCATS(URL
, full_len
, "#");
170 HTTP_URI_STRLCATL(URL
, full_len
, furl
.fragment
);
183 /* {{{ STATUS http_urlencode_hash_ex(HashTable *, zend_bool, char *, size_t, char **, size_t *) */
184 PHP_HTTP_API STATUS
_http_urlencode_hash_ex(HashTable
*hash
, zend_bool override_argsep
,
185 char *pre_encoded_data
, size_t pre_encoded_len
,
186 char **encoded_data
, size_t *encoded_len TSRMLS_DC
)
189 phpstr
*qstr
= phpstr_new();
191 if (override_argsep
|| !strlen(arg_sep
= INI_STR("arg_separator.output"))) {
192 arg_sep
= HTTP_URL_ARGSEP
;
195 if (pre_encoded_len
&& pre_encoded_data
) {
196 phpstr_append(qstr
, pre_encoded_data
, pre_encoded_len
);
199 if (SUCCESS
!= http_urlencode_hash_implementation(hash
, qstr
, arg_sep
)) {
204 phpstr_data(qstr
, encoded_data
, encoded_len
);
211 /* {{{ http_urlencode_hash_implementation
212 Original Author: Sara Golemon <pollita@php.net> */
213 PHP_HTTP_API STATUS
_http_urlencode_hash_implementation_ex(
214 HashTable
*ht
, phpstr
*formstr
, char *arg_sep
,
215 const char *num_prefix
, int num_prefix_len
,
216 const char *key_prefix
, int key_prefix_len
,
217 const char *key_suffix
, int key_suffix_len
,
218 zval
*type TSRMLS_DC
)
220 char *key
= NULL
, *ekey
, *newprefix
, *p
;
221 int arg_sep_len
, key_len
, ekey_len
, key_type
, newprefix_len
;
223 zval
**zdata
= NULL
, *copyzval
;
225 if (!ht
|| !formstr
) {
226 http_error(HE_WARNING
, HTTP_E_INVALID_PARAM
, "Invalid parameters");
230 if (ht
->nApplyCount
> 0) {
231 /* Prevent recursion */
235 if (!arg_sep
|| !strlen(arg_sep
)) {
236 arg_sep
= HTTP_URL_ARGSEP
;
238 arg_sep_len
= strlen(arg_sep
);
240 for (zend_hash_internal_pointer_reset(ht
);
241 (key_type
= zend_hash_get_current_key_ex(ht
, &key
, &key_len
, &idx
, 0, NULL
)) != HASH_KEY_NON_EXISTANT
;
242 zend_hash_move_forward(ht
)
244 if (key_type
== HASH_KEY_IS_STRING
&& key_len
&& key
[key_len
-1] == '\0') {
245 /* We don't want that trailing NULL */
250 /* handling for private & protected object properties */
251 if (key
&& *key
== '\0' && type
!= NULL
) {
254 zend_object
*zobj
= zend_objects_get_address(type TSRMLS_CC
);
255 if (zend_check_property_access(zobj
, key TSRMLS_CC
) != SUCCESS
) {
256 /* private or protected property access outside of the class */
259 zend_unmangle_property_name(key
, &tmp
, &key
);
260 key_len
= strlen(key
);
264 if (zend_hash_get_current_data_ex(ht
, (void **)&zdata
, NULL
) == FAILURE
|| !zdata
|| !(*zdata
)) {
265 http_error(HE_WARNING
, HTTP_E_ENCODING
, "Error traversing form data array.");
268 if (Z_TYPE_PP(zdata
) == IS_ARRAY
|| Z_TYPE_PP(zdata
) == IS_OBJECT
) {
269 if (key_type
== HASH_KEY_IS_STRING
) {
270 ekey
= php_url_encode(key
, key_len
, &ekey_len
);
271 newprefix_len
= key_suffix_len
+ ekey_len
+ key_prefix_len
+ 1;
272 newprefix
= emalloc(newprefix_len
+ 1);
276 memcpy(p
, key_prefix
, key_prefix_len
);
280 memcpy(p
, ekey
, ekey_len
);
285 memcpy(p
, key_suffix
, key_suffix_len
);
292 /* Is an integer key */
293 ekey_len
= spprintf(&ekey
, 12, "%ld", idx
);
294 newprefix_len
= key_prefix_len
+ num_prefix_len
+ ekey_len
+ key_suffix_len
+ 1;
295 newprefix
= emalloc(newprefix_len
+ 1);
299 memcpy(p
, key_prefix
, key_prefix_len
);
303 memcpy(p
, num_prefix
, num_prefix_len
);
306 memcpy(p
, ekey
, ekey_len
);
311 memcpy(p
, key_suffix
, key_suffix_len
);
318 http_urlencode_hash_implementation_ex(HASH_OF(*zdata
), formstr
, arg_sep
,
319 NULL
, 0, newprefix
, newprefix_len
, "]", 1, (Z_TYPE_PP(zdata
) == IS_OBJECT
? *zdata
: NULL
));
322 } else if (Z_TYPE_PP(zdata
) == IS_NULL
|| Z_TYPE_PP(zdata
) == IS_RESOURCE
) {
323 /* Skip these types */
327 phpstr_append(formstr
, arg_sep
, arg_sep_len
);
329 /* Simple key=value */
330 phpstr_append(formstr
, key_prefix
, key_prefix_len
);
331 if (key_type
== HASH_KEY_IS_STRING
) {
332 ekey
= php_url_encode(key
, key_len
, &ekey_len
);
333 phpstr_append(formstr
, ekey
, ekey_len
);
338 phpstr_append(formstr
, num_prefix
, num_prefix_len
);
340 ekey_len
= spprintf(&ekey
, 12, "%ld", idx
);
341 phpstr_append(formstr
, ekey
, ekey_len
);
344 phpstr_append(formstr
, key_suffix
, key_suffix_len
);
345 phpstr_appends(formstr
, "=");
346 switch (Z_TYPE_PP(zdata
)) {
348 ekey
= php_url_encode(Z_STRVAL_PP(zdata
), Z_STRLEN_PP(zdata
), &ekey_len
);
352 ekey_len
= spprintf(&ekey
, 12, "%ld", Z_LVAL_PP(zdata
));
355 ekey_len
= spprintf(&ekey
, 48, "%.*G", (int) EG(precision
), Z_DVAL_PP(zdata
));
358 /* fall back on convert to string */
359 MAKE_STD_ZVAL(copyzval
);
361 zval_copy_ctor(copyzval
);
362 convert_to_string_ex(©zval
);
363 ekey
= php_url_encode(Z_STRVAL_P(copyzval
), Z_STRLEN_P(copyzval
), &ekey_len
);
364 zval_ptr_dtor(©zval
);
366 phpstr_append(formstr
, ekey
, ekey_len
);
380 * vim600: noet sw=4 ts=4 fdm=marker
381 * vim<600: noet sw=4 ts=4