names changing )
[m6w6/ext-http] / php_http_info.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-2013, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #include "php_http_api.h"
14
15 PHP_HTTP_API php_http_info_t *php_http_info_init(php_http_info_t *i TSRMLS_DC)
16 {
17 if (!i) {
18 i = emalloc(sizeof(*i));
19 }
20
21 memset(i, 0, sizeof(*i));
22
23 return i;
24 }
25
26 PHP_HTTP_API void php_http_info_dtor(php_http_info_t *i)
27 {
28 switch (i->type) {
29 case PHP_HTTP_REQUEST:
30 STR_SET(PHP_HTTP_INFO(i).request.method, NULL);
31 STR_SET(PHP_HTTP_INFO(i).request.url, NULL);
32 break;
33
34 case PHP_HTTP_RESPONSE:
35 STR_SET(PHP_HTTP_INFO(i).response.status, NULL);
36 break;
37
38 default:
39 break;
40 }
41 }
42
43 PHP_HTTP_API void php_http_info_free(php_http_info_t **i)
44 {
45 if (*i) {
46 php_http_info_dtor(*i);
47 efree(*i);
48 *i = NULL;
49 }
50 }
51
52 PHP_HTTP_API php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_header TSRMLS_DC)
53 {
54 const char *end, *http;
55 zend_bool free_info = !info;
56
57 /* sane parameter */
58 if ((!pre_header) || (!*pre_header)) {
59 return NULL;
60 }
61
62 /* where's the end of the line */
63 if (!(end = php_http_locate_eol(pre_header, NULL))) {
64 end = pre_header + strlen(pre_header);
65 }
66
67 /* there must be HTTP/1.x in the line */
68 if (!(http = php_http_locate_str(pre_header, end - pre_header, "HTTP/1.", lenof("HTTP/1.")))) {
69 return NULL;
70 }
71
72 info = php_http_info_init(info TSRMLS_CC);
73
74 /* and nothing than SPACE or NUL after HTTP/1.x */
75 if (!php_http_version_parse(&info->http.version, http TSRMLS_CC)
76 || (http[lenof("HTTP/1.1")] && (!PHP_HTTP_IS_CTYPE(space, http[lenof("HTTP/1.1")])))) {
77 if (free_info) {
78 php_http_info_free(&info);
79 }
80 return NULL;
81 }
82
83 #if 0
84 {
85 char *line = estrndup(pre_header, end - pre_header);
86 fprintf(stderr, "http_parse_info('%s')\n", line);
87 efree(line);
88 }
89 #endif
90
91 /* is response */
92 if (pre_header == http) {
93 char *status = NULL;
94 const char *code = http + sizeof("HTTP/1.1");
95
96 info->type = PHP_HTTP_RESPONSE;
97 while (' ' == *code) ++code;
98 if (code && end > code) {
99 PHP_HTTP_INFO(info).response.code = strtol(code, &status, 10);
100 } else {
101 PHP_HTTP_INFO(info).response.code = 0;
102 }
103 if (status && end > status) {
104 while (' ' == *status) ++status;
105 PHP_HTTP_INFO(info).response.status = estrndup(status, end - status);
106 } else {
107 PHP_HTTP_INFO(info).response.status = NULL;
108 }
109
110 return info;
111 }
112
113 /* is request */
114 else if (*(http - 1) == ' ' && (!http[lenof("HTTP/1.x")] || http[lenof("HTTP/1.x")] == '\r' || http[lenof("HTTP/1.x")] == '\n')) {
115 const char *url = strchr(pre_header, ' ');
116
117 info->type = PHP_HTTP_REQUEST;
118 if (url && http > url) {
119 PHP_HTTP_INFO(info).request.method = estrndup(pre_header, url - pre_header);
120 while (' ' == *url) ++url;
121 while (' ' == *(http-1)) --http;
122 if (http > url) {
123 PHP_HTTP_INFO(info).request.url = estrndup(url, http - url);
124 } else {
125 STR_SET(PHP_HTTP_INFO(info).request.method, NULL);
126 return NULL;
127 }
128 } else {
129 PHP_HTTP_INFO(info).request.method = NULL;
130 PHP_HTTP_INFO(info).request.url = NULL;
131 }
132
133 return info;
134 }
135
136 /* some darn header containing HTTP/1.x */
137 else {
138 if (free_info) {
139 php_http_info_free(&info);
140 }
141 return NULL;
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