- remove dbg code
[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 #include "php_http_send_api.h"
31
32 #ifdef ZEND_ENGINE_2
33 # include "php_http_exception_object.h"
34 #endif
35
36 ZEND_EXTERN_MODULE_GLOBALS(http);
37
38 /* char *pretty_key(char *, size_t, zend_bool, zebd_bool) */
39 char *_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen)
40 {
41 if (key && key_len) {
42 unsigned i, wasalpha;
43 if (wasalpha = isalpha(key[0])) {
44 key[0] = uctitle ? toupper(key[0]) : tolower(key[0]);
45 }
46 for (i = 1; i < key_len; i++) {
47 if (isalpha(key[i])) {
48 key[i] = ((!wasalpha) && uctitle) ? toupper(key[i]) : tolower(key[i]);
49 wasalpha = 1;
50 } else {
51 if (xhyphen && (key[i] == '_')) {
52 key[i] = '-';
53 }
54 wasalpha = 0;
55 }
56 }
57 }
58 return key;
59 }
60 /* }}} */
61
62 /* {{{ void http_error(long, long, char*) */
63 void _http_error_ex(long type, long code, const char *format, ...)
64 {
65 va_list args;
66 TSRMLS_FETCH();
67
68 va_start(args, format);
69 if (type == E_THROW) {
70 #ifdef ZEND_ENGINE_2
71 char *message;
72 vspprintf(&message, 0, format, args);
73 zend_throw_exception(http_exception_get_default(), message, code TSRMLS_CC);
74 #else
75 type = E_WARNING;
76 #endif
77 }
78 if (type != E_THROW) {
79 php_verror(NULL, "", type, format, args TSRMLS_CC);
80 }
81 va_end(args);
82 }
83 /* }}} */
84
85 /* {{{ STATUS http_exit(int, char*) */
86 STATUS _http_exit_ex(int status, char *header, zend_bool free_header TSRMLS_DC)
87 {
88 if (SUCCESS != http_send_status_header(status, header)) {
89 http_error_ex(E_WARNING, HTTP_E_HEADER, "Failed to exit with status/header: %d - %s", status, header ? header : "");
90 if (free_header && header) {
91 efree(header);
92 }
93 return FAILURE;
94 }
95 if (free_header && header) {
96 efree(header);
97 }
98 zend_bailout();
99 /* fake */
100 return SUCCESS;
101 }
102 /* }}} */
103
104 /* {{{ STATUS http_check_method(char *) */
105 STATUS _http_check_method_ex(const char *method, const char *methods)
106 {
107 const char *found;
108
109 if ( (found = strstr(methods, method)) &&
110 (found == method || !isalpha(found[-1])) &&
111 (!isalpha(found[strlen(method) + 1]))) {
112 return SUCCESS;
113 }
114 return FAILURE;
115 }
116 /* }}} */
117
118 /* {{{ zval *http_get_server_var_ex(char *, size_t) */
119 PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_size, zend_bool check TSRMLS_DC)
120 {
121 zval **var;
122 if (SUCCESS == zend_hash_find(HTTP_SERVER_VARS, (char *) key, key_size, (void **) &var)) {
123 if (check) {
124 return Z_STRVAL_PP(var) && Z_STRLEN_PP(var) ? *var : NULL;
125 } else {
126 return *var;
127 }
128 }
129 return NULL;
130 }
131 /* }}} */
132
133
134 /* {{{ char *http_chunked_decode(char *, size_t, char **, size_t *) */
135 PHP_HTTP_API const char *_http_chunked_decode(const char *encoded, size_t encoded_len,
136 char **decoded, size_t *decoded_len TSRMLS_DC)
137 {
138 const char *e_ptr;
139 char *d_ptr;
140
141 *decoded_len = 0;
142 *decoded = ecalloc(1, encoded_len);
143 d_ptr = *decoded;
144 e_ptr = encoded;
145
146 while (((e_ptr - encoded) - encoded_len) > 0) {
147 char hex_len[9] = {0};
148 size_t chunk_len = 0;
149 int i = 0;
150
151 /* read in chunk size */
152 while (isxdigit(*e_ptr)) {
153 if (i == 9) {
154 http_error_ex(E_WARNING, HTTP_E_PARSE, "Chunk size is too long: 0x%s...", hex_len);
155 efree(*decoded);
156 return NULL;
157 }
158 hex_len[i++] = *e_ptr++;
159 }
160
161 /* hex to long */
162 {
163 char *error = NULL;
164 chunk_len = strtol(hex_len, &error, 16);
165 if (error == hex_len) {
166 http_error_ex(E_WARNING, HTTP_E_PARSE, "Invalid chunk size string: '%s'", hex_len);
167 efree(*decoded);
168 return NULL;
169 }
170 }
171
172 /* reached the end */
173 if (!chunk_len) {
174 break;
175 }
176
177 /* new line */
178 if (strncmp(e_ptr, HTTP_CRLF, 2)) {
179 http_error_ex(E_WARNING, HTTP_E_PARSE,
180 "Invalid character (expected 0x0D 0x0A; got: 0x%x 0x%x)", *e_ptr, *(e_ptr + 1));
181 efree(*decoded);
182 return NULL;
183 }
184
185 memcpy(d_ptr, e_ptr += 2, chunk_len);
186 d_ptr += chunk_len;
187 e_ptr += chunk_len + 2;
188 *decoded_len += chunk_len;
189 }
190
191 return e_ptr;
192 }
193 /* }}} */
194
195 /* {{{ STATUS http_split_response(zval *, zval *, zval *) */
196 PHP_HTTP_API STATUS _http_split_response(zval *response, zval *headers, zval *body TSRMLS_DC)
197 {
198 char *b = NULL;
199 size_t l = 0;
200 STATUS status = http_split_response_ex(Z_STRVAL_P(response), Z_STRLEN_P(response), Z_ARRVAL_P(headers), &b, &l);
201 ZVAL_STRINGL(body, b, l, 0);
202 return status;
203 }
204 /* }}} */
205
206 /* {{{ STATUS http_split_response(char *, size_t, HashTable *, char **, size_t *) */
207 PHP_HTTP_API STATUS _http_split_response_ex(char *response, size_t response_len,
208 HashTable *headers, char **body, size_t *body_len TSRMLS_DC)
209 {
210 char *header = response, *real_body = NULL;
211
212 while (0 < (response_len - (response - header + 4))) {
213 if ( (*response++ == '\r') &&
214 (*response++ == '\n') &&
215 (*response++ == '\r') &&
216 (*response++ == '\n')) {
217 real_body = response;
218 break;
219 }
220 }
221
222 if (real_body && (*body_len = (response_len - (real_body - header)))) {
223 *body = ecalloc(1, *body_len + 1);
224 memcpy(*body, real_body, *body_len);
225 }
226
227 return http_parse_headers_ex(header, headers, 1);
228 }
229 /* }}} */
230
231 /*
232 * Local variables:
233 * tab-width: 4
234 * c-basic-offset: 4
235 * End:
236 * vim600: noet sw=4 ts=4 fdm=marker
237 * vim<600: noet sw=4 ts=4
238 */
239