- add/update tests
[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-2006, 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 {
28 case IS_HTTP_REQUEST:
29 add_assoc_string(&array, "Request Method", HTTP_INFO(info).request.method, 1);
30 add_assoc_string(&array, "Request Url", HTTP_INFO(info).request.url, 1);
31 break;
32
33 case IS_HTTP_RESPONSE:
34 add_assoc_long(&array, "Response Code", (long) HTTP_INFO(info).response.code);
35 add_assoc_string(&array, "Response Status", HTTP_INFO(info).response.status, 1);
36 break;
37 }
38 }
39
40 PHP_HTTP_API void _http_info_dtor(http_info *info)
41 {
42 http_info_t *i = (http_info_t *) info;
43
44 switch (info->type)
45 {
46 case IS_HTTP_REQUEST:
47 STR_SET(i->request.method, NULL);
48 STR_SET(i->request.url, NULL);
49 break;
50
51 case IS_HTTP_RESPONSE:
52 STR_SET(i->response.status, NULL);
53 break;
54
55 default:
56 break;
57 }
58 }
59
60 PHP_HTTP_API STATUS _http_info_parse_ex(const char *pre_header, http_info *info, zend_bool silent TSRMLS_DC)
61 {
62 const char *end, *http;
63
64 /* sane parameter */
65 if ((!pre_header) || (!*pre_header)) {
66 if (!silent) {
67 http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Empty pre-header HTTP info");
68 }
69 return FAILURE;
70 }
71
72 /* where's the end of the line */
73 if (!(end = http_locate_eol(pre_header, NULL))) {
74 end = pre_header + strlen(pre_header);
75 }
76
77 /* there must be HTTP/1.x in the line
78 * and nothing than SPACE or NUL after HTTP/1.x
79 */
80 if ( (!(http = strstr(pre_header, "HTTP/1."))) ||
81 (!(http < end)) ||
82 (!isdigit(http[lenof("HTTP/1.")])) ||
83 (http[lenof("HTTP/1.1")] && (!isspace(http[lenof("HTTP/1.1")])))) {
84 if (!silent) {
85 http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Invalid or missing HTTP/1.x protocol identification");
86 }
87 return FAILURE;
88 }
89
90 #if 0
91 {
92 char *line = estrndup(pre_header, end - pre_header);
93 fprintf(stderr, "http_parse_info('%s')\n", line);
94 efree(line);
95 }
96 #endif
97
98 info->http.version = atof(http + lenof("HTTP/"));
99
100 /* is response */
101 if (pre_header == http) {
102 char *status = NULL;
103 const char *code = http + sizeof("HTTP/1.1");
104
105 info->type = IS_HTTP_RESPONSE;
106 HTTP_INFO(info).response.code = (code && (end > code)) ? strtol(code, &status, 10) : 0;
107 HTTP_INFO(info).response.status = (status && (end > ++status)) ? estrndup(status, end - status) : ecalloc(1,1);
108
109 return SUCCESS;
110 }
111
112 /* is request */
113 else if (!http[lenof("HTTP/1.x")] || http[lenof("HTTP/1.x")] == '\r' || http[lenof("HTTP/1.x")] == '\n') {
114 const char *url = strchr(pre_header, ' ');
115
116 info->type = IS_HTTP_REQUEST;
117 if (url && http > url) {
118 HTTP_INFO(info).request.method = estrndup(pre_header, url - pre_header);
119 HTTP_INFO(info).request.url = estrndup(url + 1, http - url - 2);
120 } else {
121 HTTP_INFO(info).request.method = ecalloc(1,1);
122 HTTP_INFO(info).request.url = ecalloc(1,1);
123 }
124
125 return SUCCESS;
126 }
127
128 /* some darn header containing HTTP/1.x */
129 else {
130 return FAILURE;
131 }
132 }
133
134
135 /*
136 * Local variables:
137 * tab-width: 4
138 * c-basic-offset: 4
139 * End:
140 * vim600: noet sw=4 ts=4 fdm=marker
141 * vim<600: noet sw=4 ts=4
142 */
143