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