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