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