- unified cache_api function names
[m6w6/ext-http] / http_api.c
1 /*
2 +----------------------------------------------------------------------+
3 | PECL :: http |
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 +----------------------------------------------------------------------+
14 */
15
16 /* $Id$ */
17
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 #endif
21
22 #include <ctype.h>
23
24 #include "php.h"
25
26 #include "php_http.h"
27 #include "php_http_std_defs.h"
28 #include "php_http_api.h"
29 #include "php_http_headers_api.h"
30
31 #ifdef ZEND_ENGINE_2
32 # include "php_http_exception_object.h"
33 #endif
34
35 ZEND_EXTERN_MODULE_GLOBALS(http);
36
37 /* char *pretty_key(char *, size_t, zend_bool, zebd_bool) */
38 char *_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen)
39 {
40 if (key && key_len) {
41 unsigned i, wasalpha;
42 if (wasalpha = isalpha(key[0])) {
43 key[0] = uctitle ? toupper(key[0]) : tolower(key[0]);
44 }
45 for (i = 1; i < key_len; i++) {
46 if (isalpha(key[i])) {
47 key[i] = ((!wasalpha) && uctitle) ? toupper(key[i]) : tolower(key[i]);
48 wasalpha = 1;
49 } else {
50 if (xhyphen && (key[i] == '_')) {
51 key[i] = '-';
52 }
53 wasalpha = 0;
54 }
55 }
56 }
57 return key;
58 }
59 /* }}} */
60
61 /* {{{ void http_error(long, long, char*) */
62 void _http_error_ex(long type, long code, const char *format, ...)
63 {
64 va_list args;
65 TSRMLS_FETCH();
66
67 va_start(args, format);
68 if (type == E_THROW) {
69 #ifdef ZEND_ENGINE_2
70 char *message;
71 vspprintf(&message, 0, format, args);
72 zend_throw_exception(http_exception_get_default(), message, code TSRMLS_CC);
73 #else
74 type = E_WARNING;
75 #endif
76 }
77 if (type != E_THROW) {
78 php_verror(NULL, "", type, format, args TSRMLS_CC);
79 }
80 va_end(args);
81 }
82 /* }}} */
83
84 /* {{{ zval *http_get_server_var_ex(char *, size_t) */
85 PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_size, zend_bool check TSRMLS_DC)
86 {
87 zval **var;
88 if (SUCCESS == zend_hash_find(HTTP_SERVER_VARS, (char *) key, key_size, (void **) &var)) {
89 if (check) {
90 return Z_STRVAL_PP(var) && Z_STRLEN_PP(var) ? *var : NULL;
91 } else {
92 return *var;
93 }
94 }
95 return NULL;
96 }
97 /* }}} */
98
99
100 /* {{{ STATUS http_chunked_decode(char *, size_t, char **, size_t *) */
101 PHP_HTTP_API STATUS _http_chunked_decode(const char *encoded, size_t encoded_len,
102 char **decoded, size_t *decoded_len TSRMLS_DC)
103 {
104 const char *e_ptr;
105 char *d_ptr;
106
107 *decoded_len = 0;
108 *decoded = ecalloc(1, encoded_len);
109 d_ptr = *decoded;
110 e_ptr = encoded;
111
112 while (((e_ptr - encoded) - encoded_len) > 0) {
113 char hex_len[9] = {0};
114 size_t chunk_len = 0;
115 int i = 0;
116
117 /* read in chunk size */
118 while (isxdigit(*e_ptr)) {
119 if (i == 9) {
120 http_error_ex(E_WARNING, HTTP_E_PARSE, "Chunk size is too long: 0x%s...", hex_len);
121 efree(*decoded);
122 return FAILURE;
123 }
124 hex_len[i++] = *e_ptr++;
125 }
126
127 /* reached the end */
128 if (!strcmp(hex_len, "0")) {
129 break;
130 }
131
132 /* new line */
133 if (strncmp(e_ptr, HTTP_CRLF, 2)) {
134 http_error_ex(E_WARNING, HTTP_E_PARSE, "Invalid character (expected 0x0D 0x0A; got: %x %x)", *e_ptr, *(e_ptr + 1));
135 efree(*decoded);
136 return FAILURE;
137 }
138
139 /* hex to long */
140 {
141 char *error = NULL;
142 chunk_len = strtol(hex_len, &error, 16);
143 if (error == hex_len) {
144 http_error_ex(E_WARNING, HTTP_E_PARSE, "Invalid chunk size string: '%s'", hex_len);
145 efree(*decoded);
146 return FAILURE;
147 }
148 }
149
150 memcpy(d_ptr, e_ptr += 2, chunk_len);
151 d_ptr += chunk_len;
152 e_ptr += chunk_len + 2;
153 *decoded_len += chunk_len;
154 }
155
156 return SUCCESS;
157 }
158 /* }}} */
159
160 /* {{{ STATUS http_split_response(zval *, zval *, zval *) */
161 PHP_HTTP_API STATUS _http_split_response(zval *response, zval *headers, zval *body TSRMLS_DC)
162 {
163 char *b = NULL;
164 size_t l = 0;
165 STATUS status = http_split_response_ex(Z_STRVAL_P(response), Z_STRLEN_P(response), Z_ARRVAL_P(headers), &b, &l);
166 ZVAL_STRINGL(body, b, l, 0);
167 return status;
168 }
169 /* }}} */
170
171 /* {{{ STATUS http_split_response(char *, size_t, HashTable *, char **, size_t *) */
172 PHP_HTTP_API STATUS _http_split_response_ex(char *response, size_t response_len,
173 HashTable *headers, char **body, size_t *body_len TSRMLS_DC)
174 {
175 char *header = response, *real_body = NULL;
176
177 while (0 < (response_len - (response - header + 4))) {
178 if ( (*response++ == '\r') &&
179 (*response++ == '\n') &&
180 (*response++ == '\r') &&
181 (*response++ == '\n')) {
182 real_body = response;
183 break;
184 }
185 }
186
187 if (real_body && (*body_len = (response_len - (real_body - header)))) {
188 *body = ecalloc(1, *body_len + 1);
189 memcpy(*body, real_body, *body_len);
190 }
191
192 return http_parse_headers_ex(header, real_body ? response_len - *body_len : response_len, headers, 1);
193 }
194 /* }}} */
195
196 /*
197 * Local variables:
198 * tab-width: 4
199 * c-basic-offset: 4
200 * End:
201 * vim600: noet sw=4 ts=4 fdm=marker
202 * vim<600: noet sw=4 ts=4
203 */
204