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 URL
= ecalloc(1, HTTP_URI_MAXLEN
+ 1);
55 uri
= estrndup(url
, url_len
);
56 if (!(purl
= php_url_parse(uri
))) {
57 http_error_ex(HE_WARNING
, HTTP_E_URL
, "Could not parse supplied URL: %s", url
);
61 furl
.user
= purl
->user
;
62 furl
.pass
= purl
->pass
;
63 furl
.path
= purl
->path
;
64 furl
.query
= purl
->query
;
65 furl
.fragment
= purl
->fragment
;
67 if (proto
&& proto_len
) {
68 furl
.scheme
= scheme
= estrdup(proto
);
69 } else if (purl
->scheme
) {
70 furl
.scheme
= purl
->scheme
;
71 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
72 } else if (port
&& (se
= getservbyport(htons(port
), "tcp"))) {
73 furl
.scheme
= (scheme
= estrdup(se
->s_name
));
81 } else if (purl
->port
) {
82 furl
.port
= purl
->port
;
83 } else if (strncmp(furl
.scheme
, "http", 4)) {
84 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
85 if ((se
= getservbyname(furl
.scheme
, "tcp"))) {
86 furl
.port
= ntohs(se
->s_port
);
90 furl
.port
= (furl
.scheme
[4] == 's') ? 443 : 80;
93 if (host
&& host_len
) {
94 furl
.host
= (char *) host
;
95 } else if (purl
->host
) {
96 furl
.host
= purl
->host
;
97 } else if ( (zhost
= http_get_server_var("HTTP_HOST")) ||
98 (zhost
= http_get_server_var("SERVER_NAME"))) {
99 furl
.host
= Z_STRVAL_P(zhost
);
101 furl
.host
= "localhost";
104 #define HTTP_URI_STRLCATS(URL, full_len, add_string) HTTP_URI_STRLCAT(URL, full_len, add_string, sizeof(add_string)-1)
105 #define HTTP_URI_STRLCATL(URL, full_len, add_string) HTTP_URI_STRLCAT(URL, full_len, add_string, strlen(add_string))
106 #define HTTP_URI_STRLCAT(URL, full_len, add_string, add_len) \
107 if ((full_len += add_len) > HTTP_URI_MAXLEN) { \
108 http_error_ex(HE_NOTICE, HTTP_E_URL, \
109 "Absolute URI would have exceeded max URI length (%d bytes) - " \
110 "tried to add %d bytes ('%s')", \
111 HTTP_URI_MAXLEN, add_len, add_string); \
115 php_url_free(purl); \
119 strcat(URL, add_string); \
122 HTTP_URI_STRLCATL(URL
, full_len
, furl
.scheme
);
123 HTTP_URI_STRLCATS(URL
, full_len
, "://");
126 HTTP_URI_STRLCATL(URL
, full_len
, furl
.user
);
128 HTTP_URI_STRLCATS(URL
, full_len
, ":");
129 HTTP_URI_STRLCATL(URL
, full_len
, furl
.pass
);
131 HTTP_URI_STRLCATS(URL
, full_len
, "@");
134 HTTP_URI_STRLCATL(URL
, full_len
, furl
.host
);
136 if ( (!strcmp(furl
.scheme
, "http") && (furl
.port
!= 80)) ||
137 (!strcmp(furl
.scheme
, "https") && (furl
.port
!= 443))
138 #if defined(PHP_WIN32) || defined(HAVE_NETDB_H)
139 || ((!(se
= getservbyname(furl
.scheme
, "tcp"))) || (ntohs(se
->s_port
) != furl
.port
))
142 char port_string
[8] = {0};
143 snprintf(port_string
, 7, ":%u", furl
.port
);
144 HTTP_URI_STRLCATL(URL
, full_len
, port_string
);
148 if (furl
.path
[0] != '/') {
149 HTTP_URI_STRLCATS(URL
, full_len
, "/");
151 HTTP_URI_STRLCATL(URL
, full_len
, furl
.path
);
153 HTTP_URI_STRLCATS(URL
, full_len
, "/");
157 HTTP_URI_STRLCATS(URL
, full_len
, "?");
158 HTTP_URI_STRLCATL(URL
, full_len
, furl
.query
);
162 HTTP_URI_STRLCATS(URL
, full_len
, "#");
163 HTTP_URI_STRLCATL(URL
, full_len
, furl
.fragment
);
176 /* {{{ STATUS http_urlencode_hash_ex(HashTable *, zend_bool, char *, size_t, char **, size_t *) */
177 PHP_HTTP_API STATUS
_http_urlencode_hash_ex(HashTable
*hash
, zend_bool override_argsep
,
178 char *pre_encoded_data
, size_t pre_encoded_len
,
179 char **encoded_data
, size_t *encoded_len TSRMLS_DC
)
183 phpstr
*qstr
= phpstr_new();
185 if (override_argsep
|| !(arg_sep_len
= strlen(arg_sep
= INI_STR("arg_separator.output")))) {
186 arg_sep
= HTTP_URL_ARGSEP
;
187 arg_sep_len
= lenof(HTTP_URL_ARGSEP
);
190 if (pre_encoded_len
&& pre_encoded_data
) {
191 phpstr_append(qstr
, pre_encoded_data
, pre_encoded_len
);
194 if (SUCCESS
!= http_urlencode_hash_recursive(hash
, qstr
, arg_sep
, arg_sep_len
, NULL
, 0)) {
199 phpstr_data(qstr
, encoded_data
, encoded_len
);
206 /* {{{ http_urlencode_hash_recursive */
207 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
)
216 http_error(HE_WARNING
, HTTP_E_INVALID_PARAM
, "Invalid parameters");
219 if (ht
->nApplyCount
> 0) {
223 FOREACH_HASH_KEYLENVAL(pos
, ht
, key
, len
, idx
, data
) {
228 if (!data
|| !*data
) {
233 if (len
&& key
[len
- 1] == '\0') {
236 encoded_key
= php_url_encode(key
, len
, &encoded_len
);
239 encoded_len
= spprintf(&encoded_key
, 0, "%ld", idx
);
243 phpstr_init(&new_prefix
);
244 if (prefix
&& prefix_len
) {
245 phpstr_append(&new_prefix
, prefix
, prefix_len
);
246 phpstr_appends(&new_prefix
, "[");
249 phpstr_append(&new_prefix
, encoded_key
, encoded_len
);
252 if (prefix
&& prefix_len
) {
253 phpstr_appends(&new_prefix
, "]");
255 phpstr_fix(&new_prefix
);
258 if (Z_TYPE_PP(data
) == IS_ARRAY
) {
261 status
= http_urlencode_hash_recursive(Z_ARRVAL_PP(data
), str
, arg_sep
, arg_sep_len
, PHPSTR_VAL(&new_prefix
), PHPSTR_LEN(&new_prefix
));
263 if (SUCCESS
!= status
) {
264 phpstr_dtor(&new_prefix
);
270 zval
*cpy
, *val
= convert_to_type_ex(IS_STRING
, *data
, &cpy
);
272 if (PHPSTR_LEN(str
)) {
273 phpstr_append(str
, arg_sep
, arg_sep_len
);
275 phpstr_append(str
, PHPSTR_VAL(&new_prefix
), PHPSTR_LEN(&new_prefix
));
276 phpstr_appends(str
, "=");
278 encoded_val
= php_url_encode(Z_STRVAL_P(val
), Z_STRLEN_P(val
), &encoded_len
);
279 phpstr_append(str
, encoded_val
, encoded_len
);
287 phpstr_dtor(&new_prefix
);
298 * vim600: noet sw=4 ts=4 fdm=marker
299 * vim<600: noet sw=4 ts=4