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 +--------------------------------------------------------------------+
22 #include "php_output.h"
23 #include "ext/standard/url.h"
26 #include "php_http_api.h"
27 #include "php_http_url_api.h"
28 #include "php_http_std_defs.h"
30 #include "phpstr/phpstr.h"
33 # include <winsock2.h>
34 #elif defined(HAVE_NETDB_H)
38 ZEND_EXTERN_MODULE_GLOBALS(http
);
40 /* {{{ char *http_absolute_url(char *) */
41 PHP_HTTP_API
char *_http_absolute_url_ex(
42 const char *url
, size_t url_len
,
43 const char *proto
, size_t proto_len
,
44 const char *host
, size_t host_len
,
45 unsigned port TSRMLS_DC
)
47 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
50 php_url
*purl
= NULL
, furl
;
53 char *scheme
= NULL
, *uri
, *URL
;
55 if ((!url
|| !url_len
) && (
56 (!(url
= SG(request_info
).request_uri
)) ||
57 (!(url_len
= strlen(SG(request_info
).request_uri
))))) {
58 http_error(HE_WARNING
, HTTP_E_RUNTIME
, "Cannot build an absolute URI if supplied URL and REQUEST_URI is empty");
62 URL
= ecalloc(1, HTTP_URI_MAXLEN
+ 1);
63 uri
= estrndup(url
, url_len
);
64 if (!(purl
= php_url_parse(uri
))) {
65 http_error_ex(HE_WARNING
, HTTP_E_URL
, "Could not parse supplied URL: %s", url
);
69 furl
.user
= purl
->user
;
70 furl
.pass
= purl
->pass
;
71 furl
.path
= purl
->path
;
72 furl
.query
= purl
->query
;
73 furl
.fragment
= purl
->fragment
;
75 if (proto
&& proto_len
) {
76 furl
.scheme
= scheme
= estrdup(proto
);
77 } else if (purl
->scheme
) {
78 furl
.scheme
= purl
->scheme
;
79 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
80 } else if (port
&& (se
= getservbyport(port
, "tcp"))) {
81 furl
.scheme
= (scheme
= estrdup(se
->s_name
));
89 } else if (purl
->port
) {
90 furl
.port
= purl
->port
;
91 } else if (strncmp(furl
.scheme
, "http", 4)) {
92 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
93 if (se
= getservbyname(furl
.scheme
, "tcp")) {
94 furl
.port
= se
->s_port
;
98 furl
.port
= (furl
.scheme
[4] == 's') ? 443 : 80;
102 furl
.host
= (char *) host
;
103 } else if (purl
->host
) {
104 furl
.host
= purl
->host
;
105 } else if ( (zhost
= http_get_server_var("HTTP_HOST")) ||
106 (zhost
= http_get_server_var("SERVER_NAME"))) {
107 furl
.host
= Z_STRVAL_P(zhost
);
109 furl
.host
= "localhost";
112 #define HTTP_URI_STRLCATS(URL, full_len, add_string) HTTP_URI_STRLCAT(URL, full_len, add_string, sizeof(add_string)-1)
113 #define HTTP_URI_STRLCATL(URL, full_len, add_string) HTTP_URI_STRLCAT(URL, full_len, add_string, strlen(add_string))
114 #define HTTP_URI_STRLCAT(URL, full_len, add_string, add_len) \
115 if ((full_len += add_len) > HTTP_URI_MAXLEN) { \
116 http_error_ex(HE_NOTICE, HTTP_E_URL, \
117 "Absolute URI would have exceeded max URI length (%d bytes) - " \
118 "tried to add %d bytes ('%s')", \
119 HTTP_URI_MAXLEN, add_len, add_string); \
123 php_url_free(purl); \
127 strcat(URL, add_string); \
130 HTTP_URI_STRLCATL(URL
, full_len
, furl
.scheme
);
131 HTTP_URI_STRLCATS(URL
, full_len
, "://");
134 HTTP_URI_STRLCATL(URL
, full_len
, furl
.user
);
136 HTTP_URI_STRLCATS(URL
, full_len
, ":");
137 HTTP_URI_STRLCATL(URL
, full_len
, furl
.pass
);
139 HTTP_URI_STRLCATS(URL
, full_len
, "@");
142 HTTP_URI_STRLCATL(URL
, full_len
, furl
.host
);
144 if ( (!strcmp(furl
.scheme
, "http") && (furl
.port
!= 80)) ||
145 (!strcmp(furl
.scheme
, "https") && (furl
.port
!= 443))) {
146 char port_string
[8] = {0};
147 snprintf(port_string
, 7, ":%u", furl
.port
);
148 HTTP_URI_STRLCATL(URL
, full_len
, port_string
);
152 if (furl
.path
[0] != '/') {
153 HTTP_URI_STRLCATS(URL
, full_len
, "/");
155 HTTP_URI_STRLCATL(URL
, full_len
, furl
.path
);
157 HTTP_URI_STRLCATS(URL
, full_len
, "/");
161 HTTP_URI_STRLCATS(URL
, full_len
, "?");
162 HTTP_URI_STRLCATL(URL
, full_len
, furl
.query
);
166 HTTP_URI_STRLCATS(URL
, full_len
, "#");
167 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
)
187 phpstr
*qstr
= phpstr_new();
189 if (override_argsep
|| !(arg_sep_len
= strlen(arg_sep
= INI_STR("arg_separator.output")))) {
190 arg_sep
= HTTP_URL_ARGSEP
;
191 arg_sep_len
= lenof(HTTP_URL_ARGSEP
);
194 if (pre_encoded_len
&& pre_encoded_data
) {
195 phpstr_append(qstr
, pre_encoded_data
, pre_encoded_len
);
198 if (SUCCESS
!= http_urlencode_hash_recursive(hash
, qstr
, arg_sep
, arg_sep_len
, NULL
, 0)) {
203 phpstr_data(qstr
, encoded_data
, encoded_len
);
210 /* {{{ http_urlencode_hash_recursive */
211 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(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