OpenVPN 3 Core Library
Loading...
Searching...
No Matches
htmlskip.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// A state machine to skip extraneous HTML in an
13// HTTP CONNECT proxy response.
14
15// Matches on typical HTML blocks:
16//
17// <!doctype html> ... </html>
18// <html> ... </html>
19//
20// Notes:
21// 1. Case insensitive
22// 2. </html> can be followed by CR/LF chars
23
24#ifndef OPENVPN_HTTP_HTMLSKIP_H
25#define OPENVPN_HTTP_HTMLSKIP_H
26
28
29namespace openvpn::HTTP {
30
32{
33 public:
40
42 : state(INITIAL),
43 residual(64, 0),
44 bytes(0)
45 {
46 }
47
48 Status add(unsigned char c)
49 {
50 bool retain = false;
51
52 ++bytes;
53 switch (state)
54 {
55 case INITIAL:
56 retain = true;
57 if (c == '<')
58 state = O_OPEN;
59 else
60 state = FAIL;
61 break;
62 case O_OPEN:
63 retain = true;
64 if (c == '!')
65 state = O_BANG;
66 else if (c == 'h' || c == 'H')
68 else
69 state = FAIL;
70 break;
71 case O_BANG:
72 retain = true;
73 if (c == 'd' || c == 'D')
75 else
76 state = FAIL;
77 break;
78 case O_DOCTYPE_D:
79 retain = true;
80 if (c == 'o' || c == 'O')
82 else
83 state = FAIL;
84 break;
85 case O_DOCTYPE_O:
86 retain = true;
87 if (c == 'c' || c == 'C')
89 else
90 state = FAIL;
91 break;
92 case O_DOCTYPE_C:
93 retain = true;
94 if (c == 't' || c == 'T')
96 else
97 state = FAIL;
98 break;
99 case O_DOCTYPE_T:
100 retain = true;
101 if (c == 'y' || c == 'Y')
103 else
104 state = FAIL;
105 break;
106 case O_DOCTYPE_Y:
107 retain = true;
108 if (c == 'p' || c == 'P')
110 else
111 state = FAIL;
112 break;
113 case O_DOCTYPE_P:
114 retain = true;
115 if (c == 'e' || c == 'E')
117 else
118 state = FAIL;
119 break;
120 case O_DOCTYPE_SPACE:
121 retain = true;
122 if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
123 break;
124 else if (c == 'h' || c == 'H')
125 state = O_HTML_H;
126 else
127 state = FAIL;
128 break;
129 case O_HTML_H:
130 retain = true;
131 if (c == 't' || c == 'T')
132 state = O_HTML_T;
133 else
134 state = FAIL;
135 break;
136 case O_HTML_T:
137 retain = true;
138 if (c == 'm' || c == 'M')
139 state = O_HTML_M;
140 else
141 state = FAIL;
142 break;
143 case O_HTML_M:
144 if (c == 'l' || c == 'L')
145 {
146 state = CONTENT;
148 }
149 else
150 {
151 state = FAIL;
152 retain = true;
153 }
154 break;
155 case CONTENT:
156 if (c == '<')
157 state = C_OPEN;
158 break;
159 case C_OPEN:
160 if (c == '/')
161 state = C_SLASH;
162 else
163 state = CONTENT;
164 break;
165 case C_SLASH:
166 if (c == 'h' || c == 'H')
167 state = C_HTML_H;
168 else
169 state = CONTENT;
170 break;
171 case C_HTML_H:
172 if (c == 't' || c == 'T')
173 state = C_HTML_T;
174 else
175 state = CONTENT;
176 break;
177 case C_HTML_T:
178 if (c == 'm' || c == 'M')
179 state = C_HTML_M;
180 else
181 state = CONTENT;
182 break;
183 case C_HTML_M:
184 if (c == 'l' || c == 'L')
185 state = C_HTML_L;
186 else
187 state = CONTENT;
188 break;
189 case C_HTML_L:
190 if (c == '>')
191 state = C_CRLF;
192 else
193 state = CONTENT;
194 break;
195 case C_CRLF:
196 if (!(c == '\n' || c == '\r'))
197 {
200 state = DONE;
201 }
202 break;
203 default:
204 retain = true;
205 break;
206 }
207
208 if (retain)
210
211 switch (state)
212 {
213 case DONE:
214 return MATCH;
215 case FAIL:
216 return NOMATCH;
217 default:
218 return PENDING;
219 }
220 }
221
223 {
224 if (residual.size() <= buf.offset())
225 {
227 }
228 else
229 {
230 BufferAllocated newbuf(residual.size() + buf.size(), 0);
231 newbuf.write(residual.c_data(), residual.size());
232 newbuf.write(buf.c_data(), buf.size());
233 buf.move(newbuf);
234 }
235 }
236
237 unsigned long n_bytes() const
238 {
239 return bytes;
240 }
241
242 private:
269
272 unsigned long bytes;
273};
274
275} // namespace openvpn::HTTP
276
277#endif
void move(BufferAllocatedType< T_ > &other)
Moves the contents of another BufferAllocatedType object into this object.
Definition buffer.hpp:1756
const T * c_data() const
Returns a const pointer to the start of the buffer.
Definition buffer.hpp:1177
void push_back(const T &value)
Append a T object to the end of the array, resizing the array if necessary.
Definition buffer.hpp:1465
void prepend(const T *data, const size_t size)
Prepend data to the buffer.
Definition buffer.hpp:1558
size_t size() const
Returns the size of the buffer in T objects.
Definition buffer.hpp:1225
void write(const T *data, const size_t size)
Write data to the buffer.
Definition buffer.hpp:1546
size_t offset() const
Returns the current offset (headroom) into the buffer.
Definition buffer.hpp:1201
void reset_content()
Resets the content of the buffer.
Definition buffer.hpp:1159
BufferAllocated residual
Definition htmlskip.hpp:271
unsigned long n_bytes() const
Definition htmlskip.hpp:237
void get_residual(BufferAllocated &buf) const
Definition htmlskip.hpp:222
Status add(unsigned char c)
Definition htmlskip.hpp:48