1 /* Copyright 2009,2010 Ryan Dahl <ry@tinyclouds.org>
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 */
21 /* modified by Moriyoshi Koizumi <moriyoshi@php.net> to make it fit to PHP source tree. */
22 #ifndef php_http_parser_h
23 #define php_http_parser_h
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27
28
29 #include <sys/types.h>
30 #if defined(_WIN32) && !defined(__MINGW32__)
31 # include <windows.h>
32 # include "config.w32.h"
33 #else
34 # include "php_config.h"
35 #endif
36
37 #include "php_stdint.h"
38
39 /* Compile with -DPHP_HTTP_PARSER_STRICT=0 to make less checks, but run
40 * faster
41 */
42 #ifndef PHP_HTTP_PARSER_STRICT
43 # define PHP_HTTP_PARSER_STRICT 1
44 #else
45 # define PHP_HTTP_PARSER_STRICT 0
46 #endif
47
48
49 /* Maximium header size allowed */
50 #define PHP_HTTP_MAX_HEADER_SIZE (80*1024)
51
52
53 typedef struct php_http_parser php_http_parser;
54 typedef struct php_http_parser_settings php_http_parser_settings;
55
56
57 /* Callbacks should return non-zero to indicate an error. The parser will
58 * then halt execution.
59 *
60 * The one exception is on_headers_complete. In a PHP_HTTP_RESPONSE parser
61 * returning '1' from on_headers_complete will tell the parser that it
62 * should not expect a body. This is used when receiving a response to a
63 * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
64 * chunked' headers that indicate the presence of a body.
65 *
66 * http_data_cb does not return data chunks. It will be call arbitrarally
67 * many times for each string. E.G. you might get 10 callbacks for "on_path"
68 * each providing just a few characters more data.
69 */
70 typedef int (*php_http_data_cb) (php_http_parser*, const char *at, size_t length);
71 typedef int (*php_http_cb) (php_http_parser*);
72
73
74 /* Request Methods */
75 enum php_http_method
76 { PHP_HTTP_DELETE = 0
77 , PHP_HTTP_GET
78 , PHP_HTTP_HEAD
79 , PHP_HTTP_POST
80 , PHP_HTTP_PUT
81 , PHP_HTTP_PATCH
82 /* pathological */
83 , PHP_HTTP_CONNECT
84 , PHP_HTTP_OPTIONS
85 , PHP_HTTP_TRACE
86 /* webdav */
87 , PHP_HTTP_COPY
88 , PHP_HTTP_LOCK
89 , PHP_HTTP_MKCOL
90 , PHP_HTTP_MOVE
91 , PHP_HTTP_MKCALENDAR
92 , PHP_HTTP_PROPFIND
93 , PHP_HTTP_PROPPATCH
94 , PHP_HTTP_SEARCH
95 , PHP_HTTP_UNLOCK
96 /* subversion */
97 , PHP_HTTP_REPORT
98 , PHP_HTTP_MKACTIVITY
99 , PHP_HTTP_CHECKOUT
100 , PHP_HTTP_MERGE
101 /* upnp */
102 , PHP_HTTP_MSEARCH
103 , PHP_HTTP_NOTIFY
104 , PHP_HTTP_SUBSCRIBE
105 , PHP_HTTP_UNSUBSCRIBE
106 /* unknown, not implemented */
107 , PHP_HTTP_NOT_IMPLEMENTED
108 };
109
110
111 enum php_http_parser_type { PHP_HTTP_REQUEST, PHP_HTTP_RESPONSE, PHP_HTTP_BOTH };
112
113
114 struct php_http_parser {
115 /** PRIVATE **/
116 unsigned char type : 2;
117 unsigned char flags : 6;
118 unsigned char state;
119 unsigned char header_state;
120 unsigned char index;
121
122 uint32_t nread;
123 ssize_t content_length;
124
125 /** READ-ONLY **/
126 unsigned short http_major;
127 unsigned short http_minor;
128 unsigned short status_code; /* responses only */
129 unsigned char method; /* requests only */
130
131 /* 1 = Upgrade header was present and the parser has exited because of that.
132 * 0 = No upgrade header present.
133 * Should be checked when http_parser_execute() returns in addition to
134 * error checking.
135 */
136 char upgrade;
137
138 /** PUBLIC **/
139 void *data; /* A pointer to get hook to the "connection" or "socket" object */
140 };
141
142
143 struct php_http_parser_settings {
144 php_http_cb on_message_begin;
145 php_http_data_cb on_path;
146 php_http_data_cb on_query_string;
147 php_http_data_cb on_url;
148 php_http_data_cb on_fragment;
149 php_http_data_cb on_header_field;
150 php_http_data_cb on_header_value;
151 php_http_cb on_headers_complete;
152 php_http_data_cb on_body;
153 php_http_cb on_message_complete;
154 };
155
156
157 void php_http_parser_init(php_http_parser *parser, enum php_http_parser_type type);
158
159
160 size_t php_http_parser_execute(php_http_parser *parser,
161 const php_http_parser_settings *settings,
162 const char *data,
163 size_t len);
164
165
166 /* If php_http_should_keep_alive() in the on_headers_complete or
167 * on_message_complete callback returns true, then this will be should be
168 * the last message on the connection.
169 * If you are the server, respond with the "Connection: close" header.
170 * If you are the client, close the connection.
171 */
172 int php_http_should_keep_alive(php_http_parser *parser);
173
174 /* Returns a string version of the HTTP method. */
175 const char *php_http_method_str(enum php_http_method);
176
177 #ifdef __cplusplus
178 }
179 #endif
180 #endif