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-2006, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
15 #define HTTP_WANT_SAPI
16 #define HTTP_WANT_NETDB
20 #include "php_output.h"
21 #include "ext/standard/php_string.h"
23 #include "php_http_api.h"
24 #include "php_http_url_api.h"
26 PHP_MINIT_FUNCTION(http_url
)
28 HTTP_LONG_CONSTANT("HTTP_URL_REPLACE", HTTP_URL_REPLACE
);
29 HTTP_LONG_CONSTANT("HTTP_URL_JOIN_PATH", HTTP_URL_JOIN_PATH
);
30 HTTP_LONG_CONSTANT("HTTP_URL_JOIN_QUERY", HTTP_URL_JOIN_QUERY
);
31 HTTP_LONG_CONSTANT("HTTP_URL_STRIP_USER", HTTP_URL_STRIP_USER
);
32 HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PASS", HTTP_URL_STRIP_PASS
);
33 HTTP_LONG_CONSTANT("HTTP_URL_STRIP_AUTH", HTTP_URL_STRIP_AUTH
);
34 HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PORT", HTTP_URL_STRIP_PORT
);
35 HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PATH", HTTP_URL_STRIP_PATH
);
36 HTTP_LONG_CONSTANT("HTTP_URL_STRIP_QUERY", HTTP_URL_STRIP_QUERY
);
37 HTTP_LONG_CONSTANT("HTTP_URL_STRIP_FRAGMENT", HTTP_URL_STRIP_FRAGMENT
);
41 PHP_HTTP_API
char *_http_absolute_url(const char *url TSRMLS_DC
)
43 char *abs
= estrdup(url
);
44 php_url
*purl
= php_url_parse(abs
);
49 http_build_url(0, purl
, NULL
, NULL
, &abs
, NULL
);
52 http_error_ex(HE_WARNING
, HTTP_E_URL
, "Could not parse URL (%s)", url
);
58 /* {{{ void http_build_url(int flags, const php_url *, const php_url *, php_url **, char **, size_t *) */
59 PHP_HTTP_API
void _http_build_url(int flags
, const php_url
*old_url
, const php_url
*new_url
, php_url
**url_ptr
, char **url_str
, size_t *url_len TSRMLS_DC
)
61 #ifdef HTTP_HAVE_NETDB
64 php_url
*url
= ecalloc(1, sizeof(php_url
));
66 #define __URLSET(u,n) \
69 url->n = __URLSET(new_url,n) ? estrdup(new_url->n) : (__URLSET(old_url,n) ? estrdup(old_url->n) : NULL)
71 if (!(flags
& HTTP_URL_STRIP_PORT
)) {
72 url
->port
= (new_url
&&new_url
->port
) ? new_url
->port
: ((old_url
) ? old_url
->port
: 0);
74 if ((!(flags
& HTTP_URL_STRIP_AUTH
)) && (!(flags
& HTTP_URL_STRIP_USER
))) {
77 if ((!(flags
& HTTP_URL_STRIP_AUTH
)) && (!(flags
& HTTP_URL_STRIP_PASS
))) {
84 if (!(flags
& HTTP_URL_STRIP_PATH
)) {
85 if ((flags
& HTTP_URL_JOIN_PATH
) && __URLSET(old_url
, path
) && __URLSET(new_url
, path
) && *new_url
->path
!= '/') {
86 size_t old_path_len
= strlen(old_url
->path
), new_path_len
= strlen(new_url
->path
);
88 url
->path
= ecalloc(1, old_path_len
+ new_path_len
+ 1 + 1);
90 strcat(url
->path
, old_url
->path
);
91 if (url
->path
[old_path_len
- 1] != '/') {
92 php_dirname(url
->path
, old_path_len
);
93 strcat(url
->path
, "/");
95 strcat(url
->path
, new_url
->path
);
100 if (!(flags
& HTTP_URL_STRIP_QUERY
)) {
101 if ((flags
& HTTP_URL_JOIN_QUERY
) && __URLSET(new_url
, query
) && __URLSET(old_url
, query
)) {
102 url
->query
= ecalloc(1, strlen(new_url
->query
) + strlen(old_url
->query
) + 1 + 1);
103 strcat(url
->query
, old_url
->query
);
104 strcat(url
->query
, "&");
105 strcat(url
->query
, new_url
->query
);
110 if (!(flags
& HTTP_URL_STRIP_FRAGMENT
)) {
118 url
->scheme
= estrndup("https", lenof("https"));
121 #ifndef HTTP_HAVE_NETDB
125 url
->scheme
= estrndup("http", lenof("http"));
128 #ifdef HTTP_HAVE_NETDB
130 if ((se
= getservbyport(htons(url
->port
), "tcp")) && se
->s_name
) {
131 url
->scheme
= estrdup(se
->s_name
);
133 url
->scheme
= estrndup("http", lenof("http"));
143 if ((((zhost
= http_get_server_var("HTTP_HOST")) ||
144 (zhost
= http_get_server_var("SERVER_NAME")))) && Z_STRLEN_P(zhost
)) {
145 url
->host
= estrndup(Z_STRVAL_P(zhost
), Z_STRLEN_P(zhost
));
147 url
->host
= estrndup("localhost", lenof("localhost"));
152 if (SG(request_info
).request_uri
&& *SG(request_info
).request_uri
) {
153 const char *q
= strchr(SG(request_info
).request_uri
, '?');
156 url
->path
= estrndup(SG(request_info
).request_uri
, q
- SG(request_info
).request_uri
);
158 url
->path
= estrdup(SG(request_info
).request_uri
);
161 url
->path
= estrndup("/", 1);
163 } else if (*url
->path
!= '/') {
164 if (SG(request_info
).request_uri
&& *SG(request_info
).request_uri
) {
165 const char *q
= strchr(SG(request_info
).request_uri
, '?');
170 uri
= estrndup(SG(request_info
).request_uri
, len
= q
- SG(request_info
).request_uri
);
172 uri
= estrndup(SG(request_info
).request_uri
, len
= strlen(SG(request_info
).request_uri
));
175 php_dirname(uri
, len
);
176 spprintf(&path
, 0, "%s/%s", uri
, url
->path
);
178 STR_SET(url
->path
, path
);
182 spprintf(&uri
, 0, "/%s", url
->path
);
183 STR_SET(url
->path
, uri
);
187 char *ptr
, *end
= url
->path
+ strlen(url
->path
) + 1;
189 for (ptr
= strstr(url
->path
, "/."); ptr
; ptr
= strstr(ptr
, "/.")) {
197 memmove(&ptr
[1], &ptr
[3], end
- &ptr
[3]);
203 while (ptr
!= url
->path
) {
208 memmove(&ptr
[1], pos
, end
- pos
);
216 if ( ((url
->port
== 80) && !strcmp(url
->scheme
, "http"))
217 || ((url
->port
==443) && !strcmp(url
->scheme
, "https"))
218 #ifdef HTTP_HAVE_NETDB
219 || ((se
= getservbyname(url
->scheme
, "tcp")) && se
->s_port
&&
220 (url
->port
== ntohs(se
->s_port
)))
230 *url_str
= emalloc(HTTP_URL_MAXLEN
+ 1);
233 strlcat(*url_str
, url
->scheme
, HTTP_URL_MAXLEN
);
234 strlcat(*url_str
, "://", HTTP_URL_MAXLEN
);
236 if (url
->user
&& *url
->user
) {
237 strlcat(*url_str
, url
->user
, HTTP_URL_MAXLEN
);
238 if (url
->pass
&& *url
->pass
) {
239 strlcat(*url_str
, ":", HTTP_URL_MAXLEN
);
240 strlcat(*url_str
, url
->pass
, HTTP_URL_MAXLEN
);
242 strlcat(*url_str
, "@", HTTP_URL_MAXLEN
);
245 strlcat(*url_str
, url
->host
, HTTP_URL_MAXLEN
);
248 char port_str
[6] = {0};
250 snprintf(port_str
, 5, "%d", (int) url
->port
);
251 strlcat(*url_str
, ":", HTTP_URL_MAXLEN
);
252 strlcat(*url_str
, port_str
, HTTP_URL_MAXLEN
);
255 if (*url
->path
!= '/') {
256 strlcat(*url_str
, "/", HTTP_URL_MAXLEN
);
258 strlcat(*url_str
, url
->path
, HTTP_URL_MAXLEN
);
260 if (url
->query
&& *url
->query
) {
261 strlcat(*url_str
, "?", HTTP_URL_MAXLEN
);
262 strlcat(*url_str
, url
->query
, HTTP_URL_MAXLEN
);
265 if (url
->fragment
&& *url
->fragment
) {
266 strlcat(*url_str
, "#", HTTP_URL_MAXLEN
);
267 strlcat(*url_str
, url
->fragment
, HTTP_URL_MAXLEN
);
270 if (HTTP_URL_MAXLEN
== (len
= strlen(*url_str
))) {
271 http_error(HE_NOTICE
, HTTP_E_URL
, "Length of URL exceeds HTTP_URL_MAXLEN");
286 /* {{{ STATUS http_urlencode_hash_ex(HashTable *, zend_bool, char *, size_t, char **, size_t *) */
287 PHP_HTTP_API STATUS
_http_urlencode_hash_ex(HashTable
*hash
, zend_bool override_argsep
,
288 char *pre_encoded_data
, size_t pre_encoded_len
,
289 char **encoded_data
, size_t *encoded_len TSRMLS_DC
)
293 phpstr
*qstr
= phpstr_new();
295 if (override_argsep
|| !(arg_sep_len
= strlen(arg_sep
= INI_STR("arg_separator.output")))) {
296 arg_sep
= HTTP_URL_ARGSEP
;
297 arg_sep_len
= lenof(HTTP_URL_ARGSEP
);
300 if (pre_encoded_len
&& pre_encoded_data
) {
301 phpstr_append(qstr
, pre_encoded_data
, pre_encoded_len
);
304 if (SUCCESS
!= http_urlencode_hash_recursive(hash
, qstr
, arg_sep
, arg_sep_len
, NULL
, 0)) {
309 phpstr_data(qstr
, encoded_data
, encoded_len
);
316 /* {{{ http_urlencode_hash_recursive */
317 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
)
326 http_error(HE_WARNING
, HTTP_E_INVALID_PARAM
, "Invalid parameters");
329 if (ht
->nApplyCount
> 0) {
333 FOREACH_HASH_KEYLENVAL(pos
, ht
, key
, len
, idx
, data
) {
338 if (!data
|| !*data
) {
343 if (len
&& key
[len
- 1] == '\0') {
346 encoded_key
= php_url_encode(key
, len
, &encoded_len
);
349 encoded_len
= spprintf(&encoded_key
, 0, "%ld", idx
);
353 phpstr_init(&new_prefix
);
354 if (prefix
&& prefix_len
) {
355 phpstr_append(&new_prefix
, prefix
, prefix_len
);
356 phpstr_appends(&new_prefix
, "[");
359 phpstr_append(&new_prefix
, encoded_key
, encoded_len
);
362 if (prefix
&& prefix_len
) {
363 phpstr_appends(&new_prefix
, "]");
365 phpstr_fix(&new_prefix
);
368 if (Z_TYPE_PP(data
) == IS_ARRAY
) {
371 status
= http_urlencode_hash_recursive(Z_ARRVAL_PP(data
), str
, arg_sep
, arg_sep_len
, PHPSTR_VAL(&new_prefix
), PHPSTR_LEN(&new_prefix
));
373 if (SUCCESS
!= status
) {
374 phpstr_dtor(&new_prefix
);
378 zval
*val
= zval_copy(IS_STRING
, *data
);
380 if (PHPSTR_LEN(str
)) {
381 phpstr_append(str
, arg_sep
, arg_sep_len
);
383 phpstr_append(str
, PHPSTR_VAL(&new_prefix
), PHPSTR_LEN(&new_prefix
));
384 phpstr_appends(str
, "=");
386 if (Z_STRLEN_P(val
) && Z_STRVAL_P(val
)) {
390 encoded_val
= php_url_encode(Z_STRVAL_P(val
), Z_STRLEN_P(val
), &encoded_len
);
391 phpstr_append(str
, encoded_val
, encoded_len
);
397 phpstr_dtor(&new_prefix
);
408 * vim600: noet sw=4 ts=4 fdm=marker
409 * vim<600: noet sw=4 ts=4