branch off v1 as R_1_7
[m6w6/ext-http] / http_info_api.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$ */
14
15 #include "php_http.h"
16
17 #include "php_http_api.h"
18 #include "php_http_info_api.h"
19
20 PHP_HTTP_API void _http_info_default_callback(void **nothing, HashTable **headers, http_info *info TSRMLS_DC)
21 {
22 zval array;
23
24 INIT_ZARR(array, *headers);
25
26 switch (info->type) {
27 case IS_HTTP_REQUEST:
28 add_assoc_string(&array, "Request Method", HTTP_INFO(info).request.method, 1);
29 add_assoc_string(&array, "Request Url", HTTP_INFO(info).request.url, 1);
30 break;
31
32 case IS_HTTP_RESPONSE:
33 add_assoc_long(&array, "Response Code", (long) HTTP_INFO(info).response.code);
34 if (HTTP_INFO(info).response.status) {
35 add_assoc_string(&array, "Response Status", HTTP_INFO(info).response.status, 1);
36 }
37 break;
38 }
39 }
40
41 PHP_HTTP_API void _http_info_dtor(http_info *i)
42 {
43 switch (i->type) {
44 case IS_HTTP_REQUEST:
45 STR_SET(HTTP_INFO(i).request.method, NULL);
46 STR_SET(HTTP_INFO(i).request.url, NULL);
47 break;
48
49 case IS_HTTP_RESPONSE:
50 STR_SET(HTTP_INFO(i).response.status, NULL);
51 break;
52
53 default:
54 break;
55 }
56 }
57
58 PHP_HTTP_API STATUS _http_info_parse_ex(const char *pre_header, http_info *info, zend_bool silent TSRMLS_DC)
59 {
60 const char *end, *http;
61
62 /* sane parameter */
63 if ((!pre_header) || (!*pre_header)) {
64 return FAILURE;
65 }
66
67 /* where's the end of the line */
68 if (!(end = http_locate_eol(pre_header, NULL))) {
69 end = pre_header + strlen(pre_header);
70 }
71
72 /* there must be HTTP/1.x in the line */
73 if (!(http = http_locate_str(pre_header, end - pre_header, "HTTP/1.", lenof("HTTP/1.")))) {
74 return FAILURE;
75 }
76
77 /* and nothing than SPACE or NUL after HTTP/1.x */
78 if ( (!HTTP_IS_CTYPE(digit, http[lenof("HTTP/1.")])) ||
79 (http[lenof("HTTP/1.1")] && (!HTTP_IS_CTYPE(space, http[lenof("HTTP/1.1")])))) {
80 if (!silent) {
81 http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Invalid HTTP/1.x protocol identification");
82 }
83 return FAILURE;
84 }
85
86 #if 0
87 {
88 char *line = estrndup(pre_header, end - pre_header);
89 fprintf(stderr, "http_parse_info('%s')\n", line);
90 efree(line);
91 }
92 #endif
93
94 info->http.version = zend_strtod(http + lenof("HTTP/"), NULL);
95
96 /* is response */
97 if (pre_header == http) {
98 char *status = NULL;
99 const char *code = http + sizeof("HTTP/1.1");
100
101 info->type = IS_HTTP_RESPONSE;
102 while (' ' == *code) ++code;
103 if (code && end > code) {
104 HTTP_INFO(info).response.code = strtol(code, &status, 10);
105 } else {
106 HTTP_INFO(info).response.code = 0;
107 }
108 if (status && end > status) {
109 while (' ' == *status) ++status;
110 HTTP_INFO(info).response.status = estrndup(status, end - status);
111 } else {
112 HTTP_INFO(info).response.status = NULL;
113 }
114
115 return SUCCESS;
116 }
117
118 /* is request */
119 else if (!http[lenof("HTTP/1.x")] || http[lenof("HTTP/1.x")] == '\r' || http[lenof("HTTP/1.x")] == '\n') {
120 const char *url = strchr(pre_header, ' ');
121
122 info->type = IS_HTTP_REQUEST;
123 if (url && http > url) {
124 HTTP_INFO(info).request.method = estrndup(pre_header, url - pre_header);
125 while (' ' == *url) ++url;
126 while (' ' == *(http-1)) --http;
127 if (http > url) {
128 HTTP_INFO(info).request.url = estrndup(url, http - url);
129 } else {
130 efree(HTTP_INFO(info).request.method);
131 return FAILURE;
132 }
133 } else {
134 HTTP_INFO(info).request.method = NULL;
135 HTTP_INFO(info).request.url = NULL;
136 }
137
138 return SUCCESS;
139 }
140
141 /* some darn header containing HTTP/1.x */
142 else {
143 return FAILURE;
144 }
145 }
146
147 /*
148 * Local variables:
149 * tab-width: 4
150 * c-basic-offset: 4
151 * End:
152 * vim600: noet sw=4 ts=4 fdm=marker
153 * vim<600: noet sw=4 ts=4
154 */
155