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 +----------------------------------------------------------------------+
24 #include "php_output.h"
25 #include "ext/standard/url.h"
29 #include "phpstr/phpstr.h"
32 #include "php_http_api.h"
33 #include "php_http_url_api.h"
34 #include "php_http_std_defs.h"
37 # include <winsock2.h>
38 #elif defined(HAVE_NETDB_H)
42 ZEND_EXTERN_MODULE_GLOBALS(http
);
44 /* {{{ char *http_absolute_url(char *) */
45 PHP_HTTP_API
char *_http_absolute_url_ex(
46 const char *url
, size_t url_len
,
47 const char *proto
, size_t proto_len
,
48 const char *host
, size_t host_len
,
49 unsigned port TSRMLS_DC
)
51 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
54 php_url
*purl
, furl
= {NULL
};
57 char *scheme
= NULL
, *URL
= ecalloc(1, HTTP_URI_MAXLEN
+ 1);
59 if ((!url
|| !url_len
) && (
60 (!(url
= SG(request_info
).request_uri
)) ||
61 (!(url_len
= strlen(SG(request_info
).request_uri
))))) {
62 http_error(E_WARNING
, HTTP_E_PARAM
, "Cannot build an absolute URI if supplied URL and REQUEST_URI is empty");
66 if (!(purl
= php_url_parse((char *) url
))) {
67 http_error_ex(E_WARNING
, HTTP_E_PARSE
, "Could not parse supplied URL: %s", url
);
71 furl
.user
= purl
->user
;
72 furl
.pass
= purl
->pass
;
73 furl
.path
= purl
->path
;
74 furl
.query
= purl
->query
;
75 furl
.fragment
= purl
->fragment
;
77 if (proto
&& proto_len
) {
78 furl
.scheme
= scheme
= estrdup(proto
);
79 } else if (purl
->scheme
) {
80 furl
.scheme
= purl
->scheme
;
81 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
82 } else if (port
&& (se
= getservbyport(port
, "tcp"))) {
83 furl
.scheme
= (scheme
= estrdup(se
->s_name
));
91 } else if (purl
->port
) {
92 furl
.port
= purl
->port
;
93 } else if (strncmp(furl
.scheme
, "http", 4)) {
94 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
95 if (se
= getservbyname(furl
.scheme
, "tcp")) {
96 furl
.port
= se
->s_port
;
100 furl
.port
= (furl
.scheme
[4] == 's') ? 443 : 80;
104 furl
.host
= (char *) host
;
105 } else if (purl
->host
) {
106 furl
.host
= purl
->host
;
107 } else if ( (zhost
= http_get_server_var("HTTP_HOST")) ||
108 (zhost
= http_get_server_var("SERVER_NAME"))) {
109 furl
.host
= Z_STRVAL_P(zhost
);
111 furl
.host
= "localhost";
114 #define HTTP_URI_STRLCATS(URL, full_len, add_string) HTTP_URI_STRLCAT(URL, full_len, add_string, sizeof(add_string)-1)
115 #define HTTP_URI_STRLCATL(URL, full_len, add_string) HTTP_URI_STRLCAT(URL, full_len, add_string, strlen(add_string))
116 #define HTTP_URI_STRLCAT(URL, full_len, add_string, add_len) \
117 if ((full_len += add_len) > HTTP_URI_MAXLEN) { \
118 http_error_ex(E_NOTICE, HTTP_E_URL, \
119 "Absolute URI would have exceeded max URI length (%d bytes) - " \
120 "tried to add %d bytes ('%s')", \
121 HTTP_URI_MAXLEN, add_len, add_string); \
125 php_url_free(purl); \
128 strcat(URL, add_string); \
131 HTTP_URI_STRLCATL(URL
, full_len
, furl
.scheme
);
132 HTTP_URI_STRLCATS(URL
, full_len
, "://");
135 HTTP_URI_STRLCATL(URL
, full_len
, furl
.user
);
137 HTTP_URI_STRLCATS(URL
, full_len
, ":");
138 HTTP_URI_STRLCATL(URL
, full_len
, furl
.pass
);
140 HTTP_URI_STRLCATS(URL
, full_len
, "@");
143 HTTP_URI_STRLCATL(URL
, full_len
, furl
.host
);
145 if ( (!strcmp(furl
.scheme
, "http") && (furl
.port
!= 80)) ||
146 (!strcmp(furl
.scheme
, "https") && (furl
.port
!= 443))) {
147 char port_string
[8] = {0};
148 snprintf(port_string
, 7, ":%u", furl
.port
);
149 HTTP_URI_STRLCATL(URL
, full_len
, port_string
);
153 if (furl
.path
[0] != '/') {
154 HTTP_URI_STRLCATS(URL
, full_len
, "/");
156 HTTP_URI_STRLCATL(URL
, full_len
, furl
.path
);
158 HTTP_URI_STRLCATS(URL
, full_len
, "/");
162 HTTP_URI_STRLCATS(URL
, full_len
, "?");
163 HTTP_URI_STRLCATL(URL
, full_len
, furl
.query
);
167 HTTP_URI_STRLCATS(URL
, full_len
, "#");
168 HTTP_URI_STRLCATL(URL
, full_len
, furl
.fragment
);
180 /* {{{ STATUS http_urlencode_hash_ex(HashTable *, zend_bool, char *, size_t, char **, size_t *) */
181 PHP_HTTP_API STATUS
_http_urlencode_hash_ex(HashTable
*hash
, zend_bool override_argsep
,
182 char *pre_encoded_data
, size_t pre_encoded_len
,
183 char **encoded_data
, size_t *encoded_len TSRMLS_DC
)
186 phpstr
*qstr
= phpstr_new();
188 if (override_argsep
|| !strlen(arg_sep
= INI_STR("arg_separator.output"))) {
189 arg_sep
= HTTP_URL_ARGSEP
;
192 if (pre_encoded_len
&& pre_encoded_data
) {
193 phpstr_append(qstr
, pre_encoded_data
, pre_encoded_len
);
196 if (SUCCESS
!= http_urlencode_hash_implementation(hash
, qstr
, arg_sep
)) {
201 phpstr_data(qstr
, encoded_data
, encoded_len
);
208 /* {{{ http_urlencode_hash_implementation
209 Original Author: Sara Golemon <pollita@php.net> */
210 PHP_HTTP_API STATUS
_http_urlencode_hash_implementation_ex(
211 HashTable
*ht
, phpstr
*formstr
, char *arg_sep
,
212 const char *num_prefix
, int num_prefix_len
,
213 const char *key_prefix
, int key_prefix_len
,
214 const char *key_suffix
, int key_suffix_len
,
215 zval
*type TSRMLS_DC
)
217 char *key
= NULL
, *ekey
, *newprefix
, *p
;
218 int arg_sep_len
, key_len
, ekey_len
, key_type
, newprefix_len
;
220 zval
**zdata
= NULL
, *copyzval
;
222 if (!ht
|| !formstr
) {
223 http_error(E_WARNING
, HTTP_E_PARAM
, "Invalid parameters");
227 if (ht
->nApplyCount
> 0) {
228 /* Prevent recursion */
232 if (!arg_sep
|| !strlen(arg_sep
)) {
233 arg_sep
= HTTP_URL_ARGSEP
;
235 arg_sep_len
= strlen(arg_sep
);
237 for (zend_hash_internal_pointer_reset(ht
);
238 (key_type
= zend_hash_get_current_key_ex(ht
, &key
, &key_len
, &idx
, 0, NULL
)) != HASH_KEY_NON_EXISTANT
;
239 zend_hash_move_forward(ht
)
241 if (key_type
== HASH_KEY_IS_STRING
&& key_len
&& key
[key_len
-1] == '\0') {
242 /* We don't want that trailing NULL */
247 /* handling for private & protected object properties */
248 if (key
&& *key
== '\0' && type
!= NULL
) {
251 zend_object
*zobj
= zend_objects_get_address(type TSRMLS_CC
);
252 if (zend_check_property_access(zobj
, key TSRMLS_CC
) != SUCCESS
) {
253 /* private or protected property access outside of the class */
256 zend_unmangle_property_name(key
, &tmp
, &key
);
257 key_len
= strlen(key
);
261 if (zend_hash_get_current_data_ex(ht
, (void **)&zdata
, NULL
) == FAILURE
|| !zdata
|| !(*zdata
)) {
262 http_error(E_WARNING
, HTTP_E_ENCODE
, "Error traversing form data array.");
265 if (Z_TYPE_PP(zdata
) == IS_ARRAY
|| Z_TYPE_PP(zdata
) == IS_OBJECT
) {
266 if (key_type
== HASH_KEY_IS_STRING
) {
267 ekey
= php_url_encode(key
, key_len
, &ekey_len
);
268 newprefix_len
= key_suffix_len
+ ekey_len
+ key_prefix_len
+ 1;
269 newprefix
= emalloc(newprefix_len
+ 1);
273 memcpy(p
, key_prefix
, key_prefix_len
);
277 memcpy(p
, ekey
, ekey_len
);
282 memcpy(p
, key_suffix
, key_suffix_len
);
289 /* Is an integer key */
290 ekey_len
= spprintf(&ekey
, 12, "%ld", idx
);
291 newprefix_len
= key_prefix_len
+ num_prefix_len
+ ekey_len
+ key_suffix_len
+ 1;
292 newprefix
= emalloc(newprefix_len
+ 1);
296 memcpy(p
, key_prefix
, key_prefix_len
);
300 memcpy(p
, num_prefix
, num_prefix_len
);
303 memcpy(p
, ekey
, ekey_len
);
308 memcpy(p
, key_suffix
, key_suffix_len
);
315 http_urlencode_hash_implementation_ex(HASH_OF(*zdata
), formstr
, arg_sep
,
316 NULL
, 0, newprefix
, newprefix_len
, "]", 1, (Z_TYPE_PP(zdata
) == IS_OBJECT
? *zdata
: NULL
));
319 } else if (Z_TYPE_PP(zdata
) == IS_NULL
|| Z_TYPE_PP(zdata
) == IS_RESOURCE
) {
320 /* Skip these types */
324 phpstr_append(formstr
, arg_sep
, arg_sep_len
);
326 /* Simple key=value */
327 phpstr_append(formstr
, key_prefix
, key_prefix_len
);
328 if (key_type
== HASH_KEY_IS_STRING
) {
329 ekey
= php_url_encode(key
, key_len
, &ekey_len
);
330 phpstr_append(formstr
, ekey
, ekey_len
);
335 phpstr_append(formstr
, num_prefix
, num_prefix_len
);
337 ekey_len
= spprintf(&ekey
, 12, "%ld", idx
);
338 phpstr_append(formstr
, ekey
, ekey_len
);
341 phpstr_append(formstr
, key_suffix
, key_suffix_len
);
342 phpstr_appends(formstr
, "=");
343 switch (Z_TYPE_PP(zdata
)) {
345 ekey
= php_url_encode(Z_STRVAL_PP(zdata
), Z_STRLEN_PP(zdata
), &ekey_len
);
349 ekey_len
= spprintf(&ekey
, 12, "%ld", Z_LVAL_PP(zdata
));
352 ekey_len
= spprintf(&ekey
, 48, "%.*G", (int) EG(precision
), Z_DVAL_PP(zdata
));
355 /* fall back on convert to string */
356 MAKE_STD_ZVAL(copyzval
);
358 zval_copy_ctor(copyzval
);
359 convert_to_string_ex(©zval
);
360 ekey
= php_url_encode(Z_STRVAL_P(copyzval
), Z_STRLEN_P(copyzval
), &ekey_len
);
361 zval_ptr_dtor(©zval
);
363 phpstr_append(formstr
, ekey
, ekey_len
);
377 * vim600: noet sw=4 ts=4 fdm=marker
378 * vim<600: noet sw=4 ts=4