fix problem when finishing a chunked encoding stream
[m6w6/ext-http] / php_http_info.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: http |
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-2010, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 /* $Id: http_info_api.c 292841 2009-12-31 08:48:57Z mike $ */
14
15 #include "php_http.h"
16
17 PHP_HTTP_API void php_http_info_default_callback(void **nothing, HashTable **headers, php_http_info_t *info TSRMLS_DC)
18 {
19 zval array;
20 (void) nothing;
21
22 INIT_PZVAL_ARRAY(&array, *headers);
23
24 switch (info->type) {
25 case PHP_HTTP_REQUEST:
26 add_assoc_string(&array, "Request Method", PHP_HTTP_INFO(info).request.method, 1);
27 add_assoc_string(&array, "Request Url", PHP_HTTP_INFO(info).request.url, 1);
28 break;
29
30 case PHP_HTTP_RESPONSE:
31 add_assoc_long(&array, "Response Code", (long) PHP_HTTP_INFO(info).response.code);
32 add_assoc_string(&array, "Response Status", PHP_HTTP_INFO(info).response.status, 1);
33 break;
34
35 case PHP_HTTP_NONE:
36 break;
37 }
38 }
39
40 PHP_HTTP_API php_http_info_t *php_http_info_init(php_http_info_t *i TSRMLS_DC)
41 {
42 if (!i) {
43 i = emalloc(sizeof(*i));
44 }
45
46 memset(i, 0, sizeof(*i));
47
48 return i;
49 }
50
51 PHP_HTTP_API void php_http_info_dtor(php_http_info_t *i)
52 {
53 switch (i->type) {
54 case PHP_HTTP_REQUEST:
55 STR_SET(PHP_HTTP_INFO(i).request.method, NULL);
56 STR_SET(PHP_HTTP_INFO(i).request.url, NULL);
57 break;
58
59 case PHP_HTTP_RESPONSE:
60 STR_SET(PHP_HTTP_INFO(i).response.status, NULL);
61 break;
62
63 default:
64 break;
65 }
66 }
67
68 PHP_HTTP_API void php_http_info_free(php_http_info_t **i)
69 {
70 if (*i) {
71 php_http_info_dtor(*i);
72 efree(*i);
73 *i = NULL;
74 }
75 }
76
77 PHP_HTTP_API php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_header TSRMLS_DC)
78 {
79 const char *end, *http;
80 zend_bool free_info = !info;
81
82 /* sane parameter */
83 if ((!pre_header) || (!*pre_header)) {
84 return NULL;
85 }
86
87 /* where's the end of the line */
88 if (!(end = php_http_locate_eol(pre_header, NULL))) {
89 end = pre_header + strlen(pre_header);
90 }
91
92 /* there must be HTTP/1.x in the line */
93 if (!(http = php_http_locate_str(pre_header, end - pre_header, "HTTP/1.", lenof("HTTP/1.")))) {
94 return NULL;
95 }
96
97 info = php_http_info_init(info TSRMLS_CC);
98
99 /* and nothing than SPACE or NUL after HTTP/1.x */
100 if (!php_http_version_parse(&info->http.version, http TSRMLS_CC)
101 || (http[lenof("HTTP/1.1")] && (!PHP_HTTP_IS_CTYPE(space, http[lenof("HTTP/1.1")])))) {
102 if (free_info) {
103 php_http_info_free(&info);
104 }
105 return NULL;
106 }
107
108 #if 0
109 {
110 char *line = estrndup(pre_header, end - pre_header);
111 fprintf(stderr, "http_parse_info('%s')\n", line);
112 efree(line);
113 }
114 #endif
115
116 /* is response */
117 if (pre_header == http) {
118 char *status = NULL;
119 const char *code = http + sizeof("HTTP/1.1");
120
121 info->type = PHP_HTTP_RESPONSE;
122 while (' ' == *code) ++code;
123 if (code && end > code) {
124 PHP_HTTP_INFO(info).response.code = strtol(code, &status, 10);
125 } else {
126 PHP_HTTP_INFO(info).response.code = 0;
127 }
128 if (status && end > status) {
129 while (' ' == *status) ++status;
130 PHP_HTTP_INFO(info).response.status = estrndup(status, end - status);
131 } else {
132 PHP_HTTP_INFO(info).response.status = NULL;
133 }
134
135 return info;
136 }
137
138 /* is request */
139 else if (!http[lenof("HTTP/1.x")] || http[lenof("HTTP/1.x")] == '\r' || http[lenof("HTTP/1.x")] == '\n') {
140 const char *url = strchr(pre_header, ' ');
141
142 info->type = PHP_HTTP_REQUEST;
143 if (url && http > url) {
144 PHP_HTTP_INFO(info).request.method = estrndup(pre_header, url - pre_header);
145 while (' ' == *url) ++url;
146 while (' ' == *(http-1)) --http;
147 if (http > url) {
148 PHP_HTTP_INFO(info).request.url = estrndup(url, http - url);
149 } else {
150 efree(PHP_HTTP_INFO(info).request.method);
151 return NULL;
152 }
153 } else {
154 PHP_HTTP_INFO(info).request.method = NULL;
155 PHP_HTTP_INFO(info).request.url = NULL;
156 }
157
158 return info;
159 }
160
161 /* some darn header containing HTTP/1.x */
162 else {
163 if (free_info) {
164 php_http_info_free(&info);
165 }
166 return NULL;
167 }
168 }
169
170 /*
171 * Local variables:
172 * tab-width: 4
173 * c-basic-offset: 4
174 * End:
175 * vim600: noet sw=4 ts=4 fdm=marker
176 * vim<600: noet sw=4 ts=4
177 */
178