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_UNLOCK
95 /* subversion */
96 , PHP_HTTP_REPORT
97 , PHP_HTTP_MKACTIVITY
98 , PHP_HTTP_CHECKOUT
99 , PHP_HTTP_MERGE
100 /* upnp */
101 , PHP_HTTP_MSEARCH
102 , PHP_HTTP_NOTIFY
103 , PHP_HTTP_SUBSCRIBE
104 , PHP_HTTP_UNSUBSCRIBE
105 /* unknown, not implemented */
106 , PHP_HTTP_NOT_IMPLEMENTED
107 };
108
109
110 enum php_http_parser_type { PHP_HTTP_REQUEST, PHP_HTTP_RESPONSE, PHP_HTTP_BOTH };
111
112
113 struct php_http_parser {
114 /** PRIVATE **/
115 unsigned char type : 2;
116 unsigned char flags : 6;
117 unsigned char state;
118 unsigned char header_state;
119 unsigned char index;
120
121 uint32_t nread;
122 ssize_t content_length;
123
124 /** READ-ONLY **/
125 unsigned short http_major;
126 unsigned short http_minor;
127 unsigned short status_code; /* responses only */
128 unsigned char method; /* requests only */
129
130 /* 1 = Upgrade header was present and the parser has exited because of that.
131 * 0 = No upgrade header present.
132 * Should be checked when http_parser_execute() returns in addition to
133 * error checking.
134 */
135 char upgrade;
136
137 /** PUBLIC **/
138 void *data; /* A pointer to get hook to the "connection" or "socket" object */
139 };
140
141
142 struct php_http_parser_settings {
143 php_http_cb on_message_begin;
144 php_http_data_cb on_path;
145 php_http_data_cb on_query_string;
146 php_http_data_cb on_url;
147 php_http_data_cb on_fragment;
148 php_http_data_cb on_header_field;
149 php_http_data_cb on_header_value;
150 php_http_cb on_headers_complete;
151 php_http_data_cb on_body;
152 php_http_cb on_message_complete;
153 };
154
155
156 void php_http_parser_init(php_http_parser *parser, enum php_http_parser_type type);
157
158
159 size_t php_http_parser_execute(php_http_parser *parser,
160 const php_http_parser_settings *settings,
161 const char *data,
162 size_t len);
163
164
165 /* If php_http_should_keep_alive() in the on_headers_complete or
166 * on_message_complete callback returns true, then this will be should be
167 * the last message on the connection.
168 * If you are the server, respond with the "Connection: close" header.
169 * If you are the client, close the connection.
170 */
171 int php_http_should_keep_alive(php_http_parser *parser);
172
173 /* Returns a string version of the HTTP method. */
174 const char *php_http_method_str(enum php_http_method);
175
176 #ifdef __cplusplus
177 }
178 #endif
179 #endif