2 +--------------------------------------------------------------------+
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 +--------------------------------------------------------------------+
13 #include "php_http_api.h"
15 php_http_info_t
*php_http_info_init(php_http_info_t
*i
)
18 i
= emalloc(sizeof(*i
));
21 memset(i
, 0, sizeof(*i
));
26 void php_http_info_dtor(php_http_info_t
*i
)
29 case PHP_HTTP_REQUEST
:
30 PTR_SET(PHP_HTTP_INFO(i
).request
.method
, NULL
);
31 PTR_SET(PHP_HTTP_INFO(i
).request
.url
, NULL
);
34 case PHP_HTTP_RESPONSE
:
35 PTR_SET(PHP_HTTP_INFO(i
).response
.status
, NULL
);
43 void php_http_info_free(php_http_info_t
**i
)
46 php_http_info_dtor(*i
);
52 php_http_info_t
*php_http_info_parse(php_http_info_t
*info
, const char *pre_header
)
54 const char *end
, *http
, *off
;
55 zend_bool free_info
= !info
;
58 if ((!pre_header
) || (!*pre_header
)) {
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
);
67 /* there must be HTTP/1.x in the line */
68 if (!(http
= php_http_locate_str(pre_header
, end
- pre_header
, "HTTP/", lenof("HTTP/")))) {
72 info
= php_http_info_init(info
);
74 if (!php_http_version_parse(&info
->http
.version
, http
)) {
76 php_http_info_free(&info
);
81 /* clumsy fix for changed libcurl behaviour in 7.49.1, see https://github.com/curl/curl/issues/888 */
82 off
= &http
[lenof("HTTP/X")];
83 if (info
->http
.version
.major
< 2) {
87 /* and nothing than SPACE or NUL after HTTP/X(.x) */
88 if (*off
&& (!PHP_HTTP_IS_CTYPE(space
, *off
))) {
90 php_http_info_free(&info
);
97 char *line
= estrndup(pre_header
, end
- pre_header
);
98 fprintf(stderr
, "http_parse_info('%s')\n", line
);
104 if (pre_header
== http
) {
105 const char *status
= NULL
, *code
= off
;
107 info
->type
= PHP_HTTP_RESPONSE
;
108 while (code
< end
&& ' ' == *code
) ++code
;
110 /* rfc7230#3.1.2 The status-code element is a 3-digit integer code */
111 PHP_HTTP_INFO(info
).response
.code
= 100*(*code
++ - '0');
112 PHP_HTTP_INFO(info
).response
.code
+= 10*(*code
++ - '0');
113 PHP_HTTP_INFO(info
).response
.code
+= *code
++ - '0';
114 if (PHP_HTTP_INFO(info
).response
.code
< 100 || PHP_HTTP_INFO(info
).response
.code
> 599) {
116 php_http_info_free(&info
);
122 PHP_HTTP_INFO(info
).response
.code
= 0;
124 if (status
&& end
> status
) {
125 while (' ' == *status
) ++status
;
126 PHP_HTTP_INFO(info
).response
.status
= estrndup(status
, end
- status
);
128 PHP_HTTP_INFO(info
).response
.status
= NULL
;
135 else if (*(http
- 1) == ' ' && (!*off
|| *off
== '\r' || *off
== '\n')) {
136 const char *url
= strchr(pre_header
, ' ');
138 info
->type
= PHP_HTTP_REQUEST
;
139 if (url
&& http
> url
) {
140 size_t url_len
= url
- pre_header
;
142 PHP_HTTP_INFO(info
).request
.method
= estrndup(pre_header
, url_len
);
144 while (' ' == *url
) ++url
;
145 while (' ' == *(http
-1)) --http
;
148 /* CONNECT presents an authority only */
149 if (strcasecmp(PHP_HTTP_INFO(info
).request
.method
, "CONNECT")) {
150 PHP_HTTP_INFO(info
).request
.url
= php_http_url_parse(url
, http
- url
, PHP_HTTP_URL_STDFLAGS
);
152 PHP_HTTP_INFO(info
).request
.url
= php_http_url_parse_authority(url
, http
- url
, PHP_HTTP_URL_STDFLAGS
);
154 if (!PHP_HTTP_INFO(info
).request
.url
) {
155 PTR_SET(PHP_HTTP_INFO(info
).request
.method
, NULL
);
159 PTR_SET(PHP_HTTP_INFO(info
).request
.method
, NULL
);
163 PHP_HTTP_INFO(info
).request
.method
= NULL
;
164 PHP_HTTP_INFO(info
).request
.url
= NULL
;
170 /* some darn header containing HTTP/X(.x) */
173 php_http_info_free(&info
);
184 * vim600: noet sw=4 ts=4 fdm=marker
185 * vim<600: noet sw=4 ts=4