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