- missing includes
[m6w6/ext-http] / http_message_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 "php.h"
23 #include "php_http.h"
24 #include "php_http_std_defs.h"
25 #include "php_http_message_api.h"
26 #include "php_http_headers_api.h"
27
28 #include "phpstr/phpstr.h"
29
30 PHP_HTTP_API void _http_message_dtor(http_message *message)
31 {
32 if (message) {
33 zend_hash_destroy(&message->hdrs);
34 phpstr_dtor(PHPSTR(message));
35 if (message->dup && message->raw.dup) {
36 efree(message->raw.dup);
37 }
38 if (message->type == HTTP_MSG_REQUEST) {
39 if (message->info.request.method) {
40 efree(message->info.request.method);
41 }
42 if (message->info.request.URI) {
43 efree(message->info.request.URI);
44 }
45 }
46 }
47 }
48
49 PHP_HTTP_API void _http_message_free(http_message *message)
50 {
51 if (message) {
52 if (message->nested) {
53 http_message_free(message->nested);
54 }
55 http_message_dtor(message);
56 efree(message);
57 }
58 }
59
60 PHP_HTTP_API http_message *_http_message_init_ex(http_message *message, http_message_type type)
61 {
62 if (!message) {
63 message = ecalloc(1, sizeof(http_message));
64 }
65
66 message->type = type;
67 message->nested = NULL;
68 phpstr_init(&message->body);
69 zend_hash_init(&message->hdrs, 0, NULL, ZVAL_PTR_DTOR, 0);
70
71 return message;
72 }
73
74 PHP_HTTP_API http_message *_http_message_parse_ex(const char *message, size_t length, zend_bool dup TSRMLS_DC)
75 {
76 const char *message_start = message, *body = NULL;
77 size_t message_length = length, header_length = 0;
78 http_message *msg;
79
80 if (length < HTTP_MSG_MIN_SIZE) {
81 return NULL;
82 }
83 if (!message) {
84 return NULL;
85 }
86
87 if (!(message_start = strstr(message, HTTP_CRLF))) {
88 return NULL;
89 }
90
91 msg = http_message_init();
92
93 // response
94 if (!strncmp(message, "HTTP/1.", lenof("HTTP/1."))) {
95 msg->type = HTTP_MSG_RESPONSE;
96 msg->info.response.http_version = atof(message + lenof("HTTP/"));
97 msg->info.response.status = atoi(message + lenof("HTTP/1.1 "));
98 } else
99 // request
100 if (!strncmp(message_start - lenof("HTTP/1.1"), "HTTP/1.", lenof("HTTP/1."))) {
101 const char *method_sep_uri = strchr(message, ' ');
102
103 msg->type = HTTP_MSG_REQUEST;
104 msg->info.request.http_version = atof(message_start - lenof("1.1"));
105 msg->info.request.method = estrndup(message, method_sep_uri - message);
106 msg->info.request.URI = estrndup(method_sep_uri + 1, message_start - method_sep_uri - 1 - lenof(" HTTP/1.1"));
107 } else {
108 http_message_free(msg);
109 return NULL;
110 }
111
112 message_start += lenof(HTTP_CRLF);
113 message_length -= message_start - message;
114
115 if (msg->dup = dup) {
116 msg->len = length;
117 msg->raw.dup = estrndup(message, length);
118 } else {
119 msg->len = length;
120 msg->raw.ptr = message;
121 }
122
123 if (body = strstr(message_start, HTTP_CRLF HTTP_CRLF)) {
124 body += lenof(HTTP_CRLF HTTP_CRLF);
125 header_length = body - message_start;
126 phpstr_from_string_ex(PHPSTR(msg), body, message_length - header_length);
127 } else {
128 header_length = message_length;
129 }
130
131 if (SUCCESS != http_parse_headers_ex(message_start, header_length, &msg->hdrs, 1)) {
132 http_message_free(msg);
133 return NULL;
134 }
135 return msg;
136 }
137
138 PHP_HTTP_API void _http_message_tostring(http_message *msg, char **string, size_t *length)
139 {
140 phpstr str;
141 char *key, *data;
142 ulong idx;
143 zval **header;
144
145 phpstr_init_ex(&str, msg->len, 1);
146
147 switch (msg->type)
148 {
149 case HTTP_MSG_REQUEST:
150 phpstr_appendf(&str, "%s %s HTTP/%1.1f" HTTP_CRLF,
151 msg->info.request.method,
152 msg->info.request.URI,
153 msg->info.request.http_version);
154 break;
155
156 case HTTP_MSG_RESPONSE:
157 phpstr_appendf(&str, "HTTP/%1.1f %d" HTTP_CRLF,
158 msg->info.response.http_version,
159 msg->info.response.status);
160 break;
161 }
162
163 FOREACH_HASH_KEYVAL(&msg->hdrs, key, idx, header) {
164 if (key) {
165 phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key, Z_STRVAL_PP(header));
166 key = NULL;
167 }
168 }
169
170 phpstr_appends(&str, HTTP_CRLF);
171 phpstr_append(&str, msg->body.data, msg->body.used);
172 phpstr_fix(&str);
173
174 data = phpstr_data(&str, string, length);
175 if (!string) {
176 efree(data);
177 }
178
179 phpstr_dtor(&str);
180 }