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 +----------------------------------------------------------------------+
23 # include <winsock2.h>
24 #elif defined(HAVE_NETDB_H)
30 #include "php_output.h"
31 #include "ext/standard/url.h"
35 #include "phpstr/phpstr.h"
38 #include "php_http_api.h"
39 #include "php_http_url_api.h"
40 #include "php_http_std_defs.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 php_error_docref(NULL TSRMLS_CC
, E_WARNING
,
63 "Cannot build an absolute URI if supplied URL and REQUEST_URI is empty");
67 if (!(purl
= php_url_parse((char *) url
))) {
68 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not parse supplied 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 php_error_docref(NULL TSRMLS_CC, E_NOTICE, \
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); \
129 strcat(URL, add_string); \
132 HTTP_URI_STRLCATL(URL
, full_len
, furl
.scheme
);
133 HTTP_URI_STRLCATS(URL
, full_len
, "://");
136 HTTP_URI_STRLCATL(URL
, full_len
, furl
.user
);
138 HTTP_URI_STRLCATS(URL
, full_len
, ":");
139 HTTP_URI_STRLCATL(URL
, full_len
, furl
.pass
);
141 HTTP_URI_STRLCATS(URL
, full_len
, "@");
144 HTTP_URI_STRLCATL(URL
, full_len
, furl
.host
);
146 if ( (!strcmp(furl
.scheme
, "http") && (furl
.port
!= 80)) ||
147 (!strcmp(furl
.scheme
, "https") && (furl
.port
!= 443))) {
148 char port_string
[8] = {0};
149 snprintf(port_string
, 7, ":%u", furl
.port
);
150 HTTP_URI_STRLCATL(URL
, full_len
, port_string
);
154 if (furl
.path
[0] != '/') {
155 HTTP_URI_STRLCATS(URL
, full_len
, "/");
157 HTTP_URI_STRLCATL(URL
, full_len
, furl
.path
);
159 HTTP_URI_STRLCATS(URL
, full_len
, "/");
163 HTTP_URI_STRLCATS(URL
, full_len
, "?");
164 HTTP_URI_STRLCATL(URL
, full_len
, furl
.query
);
168 HTTP_URI_STRLCATS(URL
, full_len
, "#");
169 HTTP_URI_STRLCATL(URL
, full_len
, furl
.fragment
);
181 /* {{{ STATUS http_urlencode_hash_ex(HashTable *, zend_bool, char *, size_t, char **, size_t *) */
182 PHP_HTTP_API STATUS
_http_urlencode_hash_ex(HashTable
*hash
, zend_bool override_argsep
,
183 char *pre_encoded_data
, size_t pre_encoded_len
,
184 char **encoded_data
, size_t *encoded_len TSRMLS_DC
)
187 phpstr
*qstr
= phpstr_new();
189 if (override_argsep
|| !strlen(arg_sep
= INI_STR("arg_separator.output"))) {
190 arg_sep
= 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_implementation(hash
, qstr
, arg_sep
)) {
198 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Couldn't encode query data");
203 phpstr_data(qstr
, encoded_data
, encoded_len
);
210 /* {{{ http_urlencode_hash_implementation
211 Original Author: Sara Golemon <pollita@php.net> */
212 PHP_HTTP_API STATUS
_http_urlencode_hash_implementation_ex(
213 HashTable
*ht
, phpstr
*formstr
, char *arg_sep
,
214 const char *num_prefix
, int num_prefix_len
,
215 const char *key_prefix
, int key_prefix_len
,
216 const char *key_suffix
, int key_suffix_len
,
217 zval
*type TSRMLS_DC
)
219 char *key
= NULL
, *ekey
, *newprefix
, *p
;
220 int arg_sep_len
, key_len
, ekey_len
, key_type
, newprefix_len
;
222 zval
**zdata
= NULL
, *copyzval
;
224 if (!ht
|| !formstr
) {
228 if (ht
->nApplyCount
> 0) {
229 /* Prevent recursion */
233 if (!arg_sep
|| !strlen(arg_sep
)) {
234 arg_sep
= HTTP_URL_ARGSEP
;
236 arg_sep_len
= strlen(arg_sep
);
238 for (zend_hash_internal_pointer_reset(ht
);
239 (key_type
= zend_hash_get_current_key_ex(ht
, &key
, &key_len
, &idx
, 0, NULL
)) != HASH_KEY_NON_EXISTANT
;
240 zend_hash_move_forward(ht
)
242 if (key_type
== HASH_KEY_IS_STRING
&& key_len
&& key
[key_len
-1] == '\0') {
243 /* We don't want that trailing NULL */
248 /* handling for private & protected object properties */
249 if (key
&& *key
== '\0' && type
!= NULL
) {
252 zend_object
*zobj
= zend_objects_get_address(type TSRMLS_CC
);
253 if (zend_check_property_access(zobj
, key TSRMLS_CC
) != SUCCESS
) {
254 /* private or protected property access outside of the class */
257 zend_unmangle_property_name(key
, &tmp
, &key
);
258 key_len
= strlen(key
);
262 if (zend_hash_get_current_data_ex(ht
, (void **)&zdata
, NULL
) == FAILURE
|| !zdata
|| !(*zdata
)) {
263 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Error traversing form data array.");
266 if (Z_TYPE_PP(zdata
) == IS_ARRAY
|| Z_TYPE_PP(zdata
) == IS_OBJECT
) {
267 if (key_type
== HASH_KEY_IS_STRING
) {
268 ekey
= php_url_encode(key
, key_len
, &ekey_len
);
269 newprefix_len
= key_suffix_len
+ ekey_len
+ key_prefix_len
+ 1;
270 newprefix
= emalloc(newprefix_len
+ 1);
274 memcpy(p
, key_prefix
, key_prefix_len
);
278 memcpy(p
, ekey
, ekey_len
);
283 memcpy(p
, key_suffix
, key_suffix_len
);
290 /* Is an integer key */
291 ekey_len
= spprintf(&ekey
, 12, "%ld", idx
);
292 newprefix_len
= key_prefix_len
+ num_prefix_len
+ ekey_len
+ key_suffix_len
+ 1;
293 newprefix
= emalloc(newprefix_len
+ 1);
297 memcpy(p
, key_prefix
, key_prefix_len
);
301 memcpy(p
, num_prefix
, num_prefix_len
);
304 memcpy(p
, ekey
, ekey_len
);
309 memcpy(p
, key_suffix
, key_suffix_len
);
316 http_urlencode_hash_implementation_ex(HASH_OF(*zdata
), formstr
, arg_sep
,
317 NULL
, 0, newprefix
, newprefix_len
, "]", 1, (Z_TYPE_PP(zdata
) == IS_OBJECT
? *zdata
: NULL
));
320 } else if (Z_TYPE_PP(zdata
) == IS_NULL
|| Z_TYPE_PP(zdata
) == IS_RESOURCE
) {
321 /* Skip these types */
325 phpstr_append(formstr
, arg_sep
, arg_sep_len
);
327 /* Simple key=value */
328 phpstr_append(formstr
, key_prefix
, key_prefix_len
);
329 if (key_type
== HASH_KEY_IS_STRING
) {
330 ekey
= php_url_encode(key
, key_len
, &ekey_len
);
331 phpstr_append(formstr
, ekey
, ekey_len
);
336 phpstr_append(formstr
, num_prefix
, num_prefix_len
);
338 ekey_len
= spprintf(&ekey
, 12, "%ld", idx
);
339 phpstr_append(formstr
, ekey
, ekey_len
);
342 phpstr_append(formstr
, key_suffix
, key_suffix_len
);
343 phpstr_appends(formstr
, "=");
344 switch (Z_TYPE_PP(zdata
)) {
346 ekey
= php_url_encode(Z_STRVAL_PP(zdata
), Z_STRLEN_PP(zdata
), &ekey_len
);
350 ekey_len
= spprintf(&ekey
, 12, "%ld", Z_LVAL_PP(zdata
));
353 ekey_len
= spprintf(&ekey
, 48, "%.*G", (int) EG(precision
), Z_DVAL_PP(zdata
));
356 /* fall back on convert to string */
357 MAKE_STD_ZVAL(copyzval
);
359 zval_copy_ctor(copyzval
);
360 convert_to_string_ex(©zval
);
361 ekey
= php_url_encode(Z_STRVAL_P(copyzval
), Z_STRLEN_P(copyzval
), &ekey_len
);
362 zval_ptr_dtor(©zval
);
364 phpstr_append(formstr
, ekey
, ekey_len
);
378 * vim600: noet sw=4 ts=4 fdm=marker
379 * vim<600: noet sw=4 ts=4