2 +----------------------------------------------------------------------+
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 +----------------------------------------------------------------------+
24 #include "php_http_std_defs.h"
25 #include "php_http_message_api.h"
26 #include "php_http_headers_api.h"
28 #include "phpstr/phpstr.h"
30 PHP_HTTP_API http_message
*_http_message_init_ex(http_message
*message
, http_message_type type
)
33 message
= ecalloc(1, sizeof(http_message
));
37 message
->nested
= NULL
;
38 phpstr_init(&message
->body
);
39 zend_hash_init(&message
->hdrs
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
44 PHP_HTTP_API http_message
*_http_message_parse_ex(http_message
*msg
, char *message
, size_t message_length
, zend_bool dup TSRMLS_DC
)
47 size_t header_length
= 0;
48 zend_bool free_msg
= msg
? 0 : 1;
50 if (message_length
< HTTP_MSG_MIN_SIZE
) {
58 msg
= http_message_init(msg
);
59 msg
->len
= message_length
;
60 msg
->raw
= dup
? estrndup(message
, message_length
) : message
;
62 if (body
= strstr(message
, HTTP_CRLF HTTP_CRLF
)) {
63 body
+= lenof(HTTP_CRLF HTTP_CRLF
);
64 header_length
= body
- message
;
66 header_length
= message_length
;
69 if (SUCCESS
!= http_parse_headers_cb(message
, header_length
, &msg
->hdrs
, 1, http_message_parse_headers_callback
, (void **) &msg
)) {
71 http_message_free(msg
);
77 phpstr_from_string_ex(PHPSTR(msg
), body
, message_length
- header_length
);
83 PHP_HTTP_API
void _http_message_parse_headers_callback(void **message
, char *http_line
, size_t line_length
, HashTable
**headers TSRMLS_DC
)
85 http_message
*old
= (http_message
*) *message
;
88 if (old
->type
|| zend_hash_num_elements(&old
->hdrs
) || PHPSTR_LEN(old
)) {
89 new = http_message_new();
93 *headers
= &new->hdrs
;
99 if (!strncmp(http_line
, "HTTP/1.", lenof("HTTP/1."))) {
100 new->type
= HTTP_MSG_RESPONSE
;
101 new->info
.response
.http_version
= atof(http_line
+ lenof("HTTP/"));
102 new->info
.response
.status
= atoi(http_line
+ lenof("HTTP/1.1 "));
105 if (!strncmp(http_line
+ line_length
- lenof("HTTP/1.1"), "HTTP/1.", lenof("HTTP/1."))) {
106 const char *method_sep_uri
= strchr(http_line
, ' ');
108 new->type
= HTTP_MSG_REQUEST
;
109 new->info
.request
.http_version
= atof(http_line
+ line_length
- lenof("1.1"));
110 new->info
.request
.method
= estrndup(http_line
, method_sep_uri
- http_line
);
111 new->info
.request
.URI
= estrndup(method_sep_uri
+ 1, http_line
+ line_length
- method_sep_uri
- 1 - lenof(" HTTP/1.1"));
115 PHP_HTTP_API
void _http_message_tostring(http_message
*msg
, char **string
, size_t *length
)
122 phpstr_init_ex(&str
, msg
->len
, 1);
123 /* set sane alloc size */
128 case HTTP_MSG_REQUEST
:
129 phpstr_appendf(&str
, "%s %s HTTP/%1.1f" HTTP_CRLF
,
130 msg
->info
.request
.method
,
131 msg
->info
.request
.URI
,
132 msg
->info
.request
.http_version
);
135 case HTTP_MSG_RESPONSE
:
136 phpstr_appendf(&str
, "HTTP/%1.1f %d" HTTP_CRLF
,
137 msg
->info
.response
.http_version
,
138 msg
->info
.response
.status
);
142 FOREACH_HASH_KEYVAL(&msg
->hdrs
, key
, idx
, header
) {
144 zval
**single_header
;
146 switch (Z_TYPE_PP(header
))
149 phpstr_appendf(&str
, "%s: %s" HTTP_CRLF
, key
, Z_STRVAL_PP(header
));
153 FOREACH_VAL(*header
, single_header
) {
154 phpstr_appendf(&str
, "%s: %s" HTTP_CRLF
, key
, Z_STRVAL_PP(single_header
));
163 phpstr_appends(&str
, HTTP_CRLF
);
164 phpstr_append(&str
, PHPSTR_VAL(msg
), PHPSTR_LEN(msg
));
166 data
= phpstr_data(&str
, string
, length
);
174 PHP_HTTP_API
void _http_message_dtor(http_message
*message
)
177 zend_hash_destroy(&message
->hdrs
);
178 phpstr_dtor(PHPSTR(message
));
183 if (message
->type
== HTTP_MSG_REQUEST
) {
184 if (message
->info
.request
.method
) {
185 efree(message
->info
.request
.method
);
186 message
->info
.request
.method
= NULL
;
188 if (message
->info
.request
.URI
) {
189 efree(message
->info
.request
.URI
);
190 message
->info
.request
.URI
= NULL
;
196 PHP_HTTP_API
void _http_message_free(http_message
*message
)
199 if (message
->nested
) {
200 http_message_free(message
->nested
);
202 http_message_dtor(message
);
212 * vim600: noet sw=4 ts=4 fdm=marker
213 * vim<600: noet sw=4 ts=4