1 /**
2  **	\file HttpRequest.cpp
3  **	\date  2007-10-05
4  **	\author grymse@alhem.net
5 **/
6 /*
7 Copyright (C) 2007-2011  Anders Hedstrom
8 
9 This library is made available under the terms of the GNU GPL, with
10 the additional exemption that compiling, linking, and/or using OpenSSL
11 is allowed.
12 
13 If you would like to use this library in a closed-source application,
14 a separate license agreement is available. For information about
15 the closed-source license agreement for the C++ sockets library,
16 please visit http://www.alhem.net/Sockets/license.html and/or
17 email license@alhem.net.
18 
19 This program is free software; you can redistribute it and/or
20 modify it under the terms of the GNU General Public License
21 as published by the Free Software Foundation; either version 2
22 of the License, or (at your option) any later version.
23 
24 This program is distributed in the hope that it will be useful,
25 but WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27 GNU General Public License for more details.
28 
29 You should have received a copy of the GNU General Public License
30 along with this program; if not, write to the Free Software
31 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
32 */
33 #ifdef _MSC_VER
34 #pragma warning(disable:4786)
35 #endif
36 #include "HttpRequest.h"
37 #include "MemFile.h"
38 #include "HttpdForm.h"
39 #include "HttpdCookies.h"
40 #include "Parse.h"
41 #include "Exception.h"
42 #ifdef MACOSX
43 #include <crt_externs.h>
44 #define environ (*_NSGetEnviron())
45 #endif
46 
47 #ifdef SOCKETS_NAMESPACE
48 namespace SOCKETS_NAMESPACE {
49 #endif
50 
51 extern char**environ;
52 
53 #ifdef _DEBUG
54 #define DEB(x) x; fflush(stderr);
55 #else
56 #define DEB(x)
57 #endif
58 
59 
60 // --------------------------------------------------------------------------------------
HttpRequest()61 HttpRequest::HttpRequest() : HttpTransaction()
62 , m_server_port(0)
63 , m_is_ssl(false)
64 , m_body_file(NULL)
65 , m_form(NULL)
66 {
67 }
68 
69 
70 // --------------------------------------------------------------------------------------
71 #ifndef _WIN32
HttpRequest(FILE * fil)72 HttpRequest::HttpRequest(FILE *fil) : HttpTransaction()
73 , m_server_port(0)
74 , m_is_ssl(false)
75 , m_body_file(NULL)
76 , m_form(NULL)
77 {
78 	int i = 0;
79 DEB(	std::cout << "Initialize HttpRequest from cgi...\n";)
80 	while (environ[i] && *environ[i])
81 	{
82 		Parse pa(environ[i], "=");
83 		std::string key = pa.getword();
84 		std::string value = pa.getrest();
85 		if (key == "REQUEST_METHOD")
86 			m_method = value;
87 		else
88 		if (key == "SERVER_PROTOCOL")
89 			m_protocol = value;
90 		else
91 		if (key == "PATH_INFO")
92 			m_req_uri = value;
93 		else
94 		if (key == "REMOTE_ADDR")
95 			m_remote_addr = value;
96 		else
97 		if (key == "REMOTE_HOST")
98 			m_remote_host = value;
99 		else
100 		if (key == "SERVER_NAME")
101 			m_server_name = value;
102 		else
103 		if (key == "SERVER_PORT")
104 			m_server_port = atoi(value.c_str());
105 		else
106 		if (key.size() > 5 && key.substr(0, 5) == "HTTP_")
107 		{
108 			key = key.substr(5);
109 			for (size_t pos = 0; pos < key.size(); pos++)
110 			{
111 				if (key[pos] == '_')
112 					key[pos] = '-';
113 				else
114 				if (key[pos] >= 'A' && key[pos] <= 'Z')
115 					key[pos] |= 32;
116 			}
117 DEB(			std::cout << " http header '" << key << "' == '" << value << "\n";)
118 			SetHeader(key, value);
119 		}
120 		++i;
121 	}
122 DEB(	std::cout << " setup http form\n";)
123 	m_form = std::auto_ptr<HttpdForm>(new HttpdForm(fil));
124 }
125 #endif
126 
127 
128 // --------------------------------------------------------------------------------------
HttpRequest(const HttpRequest & src)129 HttpRequest::HttpRequest(const HttpRequest& src) : HttpTransaction(src)
130 , m_method(src.m_method)
131 , m_protocol(src.m_protocol)
132 , m_req_uri(src.m_req_uri)
133 , m_remote_addr(src.m_remote_addr)
134 , m_remote_host(src.m_remote_host)
135 , m_server_name(src.m_server_name)
136 , m_server_port(src.m_server_port)
137 , m_is_ssl(src.m_is_ssl)
138 , m_attribute(src.m_attribute)
139 , m_null(src.m_null)
140 , m_body_file(src.m_body_file)
141 , m_form(src.m_form)
142 , m_cookies(src.m_cookies)
143 , m_cookie(src.m_cookie)
144 {
145 }
146 
147 
148 // --------------------------------------------------------------------------------------
~HttpRequest()149 HttpRequest::~HttpRequest()
150 {
151 }
152 
153 
154 // --------------------------------------------------------------------------------------
operator =(const HttpRequest & src)155 HttpRequest& HttpRequest::operator=(const HttpRequest& src)
156 {
157 	m_method = src.m_method;
158 	m_protocol = src.m_protocol;
159 	m_req_uri = src.m_req_uri;
160 	m_remote_addr = src.m_remote_addr;
161 	m_remote_host = src.m_remote_host;
162 	m_server_name = src.m_server_name;
163 	m_server_port = src.m_server_port;
164 	m_is_ssl = src.m_is_ssl;
165 	m_attribute = src.m_attribute;
166 	m_null = src.m_null;
167 	m_body_file = src.m_body_file;
168 	m_form = src.m_form;
169 	m_cookies = src.m_cookies;
170 	m_cookie = src.m_cookie;
171 
172 	HttpTransaction::operator=(src);
173 
174 	return *this;
175 }
176 
177 
178 // --------------------------------------------------------------------------------------
SetHttpMethod(const std::string & value)179 void HttpRequest::SetHttpMethod(const std::string& value)
180 {
181 	m_method = value;
182 }
183 
184 
HttpMethod() const185 const std::string& HttpRequest::HttpMethod() const
186 {
187 	return m_method;
188 }
189 
190 
191 
192 // --------------------------------------------------------------------------------------
SetHttpVersion(const std::string & value)193 void HttpRequest::SetHttpVersion(const std::string& value)
194 {
195 	m_protocol = value;
196 }
197 
198 
HttpVersion() const199 const std::string& HttpRequest::HttpVersion() const
200 {
201 	return m_protocol;
202 }
203 
204 
205 
206 // --------------------------------------------------------------------------------------
SetUri(const std::string & value)207 void HttpRequest::SetUri(const std::string& value)
208 {
209 	m_req_uri = value;
210 }
211 
212 
Uri() const213 const std::string& HttpRequest::Uri() const
214 {
215 	return m_req_uri;
216 }
217 
218 
219 
220 // --------------------------------------------------------------------------------------
SetRemoteAddr(const std::string & value)221 void HttpRequest::SetRemoteAddr(const std::string& value)
222 {
223 	m_remote_addr = value;
224 }
225 
226 
RemoteAddr() const227 const std::string& HttpRequest::RemoteAddr() const
228 {
229 	return m_remote_addr;
230 }
231 
232 
233 
234 // --------------------------------------------------------------------------------------
SetRemoteHost(const std::string & value)235 void HttpRequest::SetRemoteHost(const std::string& value)
236 {
237 	m_remote_host = value;
238 }
239 
240 
RemoteHost() const241 const std::string& HttpRequest::RemoteHost() const
242 {
243 	return m_remote_host;
244 }
245 
246 
247 
248 // --------------------------------------------------------------------------------------
SetServerName(const std::string & value)249 void HttpRequest::SetServerName(const std::string& value)
250 {
251 	m_server_name = value;
252 }
253 
254 
ServerName() const255 const std::string& HttpRequest::ServerName() const
256 {
257 	return m_server_name;
258 }
259 
260 
261 
262 // --------------------------------------------------------------------------------------
SetServerPort(int value)263 void HttpRequest::SetServerPort(int value)
264 {
265 	m_server_port = value;
266 }
267 
268 
ServerPort() const269 int HttpRequest::ServerPort() const
270 {
271 	return m_server_port;
272 }
273 
274 
275 
276 // --------------------------------------------------------------------------------------
SetIsSsl(bool value)277 void HttpRequest::SetIsSsl(bool value)
278 {
279 	m_is_ssl = value;
280 }
281 
282 
IsSsl() const283 bool HttpRequest::IsSsl() const
284 {
285 	return m_is_ssl;
286 }
287 
288 
289 
290 // --------------------------------------------------------------------------------------
SetAttribute(const std::string & key,const std::string & value)291 void HttpRequest::SetAttribute(const std::string& key, const std::string& value)
292 {
293 	m_attribute[key] = value;
294 }
295 
296 
SetAttribute(const std::string & key,long value)297 void HttpRequest::SetAttribute(const std::string& key, long value)
298 {
299 	m_attribute[key] = Utility::l2string(value);
300 }
301 
302 
Attribute(const std::string & key) const303 const std::string& HttpRequest::Attribute(const std::string& key) const
304 {
305 	Utility::ncmap<std::string>::const_iterator it;
306 	if ( (it = m_attribute.find(key)) != m_attribute.end())
307 		return it -> second;
308 	return m_null;
309 }
310 
311 
312 // --------------------------------------------------------------------------------------
Attributes() const313 const Utility::ncmap<std::string>& HttpRequest::Attributes() const
314 {
315 	return m_attribute;
316 }
317 
318 
319 // --------------------------------------------------------------------------------------
AddCookie(const std::string & str)320 void HttpRequest::AddCookie(const std::string& str)
321 {
322 	m_cookies.add( str );
323 	Parse pa(str, ";");
324 	std::string lstr = pa.getword();
325 	while (!lstr.empty())
326 	{
327 		Parse pa2(lstr, "=");
328 		std::string name = pa2.getword();
329 		m_cookie[name] = lstr;
330 DEB(fprintf(stderr, " *** AddCookie '%s' = '%s'\n", name.c_str(), lstr.c_str());)
331 		lstr = pa.getword();
332 	}
333 }
334 
335 
336 // --------------------------------------------------------------------------------------
InitBody(size_t sz)337 void HttpRequest::InitBody( size_t sz )
338 {
339 	if (!m_body_file.get())
340 		m_body_file = std::auto_ptr<IFile>(new MemFile);
341 DEB(	else
342 		fprintf(stderr, "Body data file already opened\n");)
343 }
344 
345 
346 // --------------------------------------------------------------------------------------
Write(const char * buf,size_t sz)347 void HttpRequest::Write( const char *buf, size_t sz )
348 {
349 	if (m_body_file.get())
350 		m_body_file -> fwrite(buf, 1, sz);
351 DEB(	else
352 		fprintf(stderr, "Write: Body data file not open\n");)
353 }
354 
355 
356 // --------------------------------------------------------------------------------------
CloseBody()357 void HttpRequest::CloseBody()
358 {
359 	if (m_body_file.get())
360 		m_body_file -> fclose();
361 DEB(	else
362 		fprintf(stderr, "CloseBody: File not open\n");)
363 }
364 
365 
366 // --------------------------------------------------------------------------------------
ParseBody()367 void HttpRequest::ParseBody()
368 {
369 	Utility::ncmap<std::string>::const_iterator it;
370 	if ( (it = m_attribute.find("query_string")) != m_attribute.end())
371 	{
372 		std::string qs = it -> second;
373 		m_form = std::auto_ptr<HttpdForm>(new HttpdForm( qs, qs.size() ));
374 	}
375 	else
376 	if (m_body_file.get())
377 	{
378 		m_form = std::auto_ptr<HttpdForm>(new HttpdForm( m_body_file.get(), ContentType(), ContentLength() ));
379 	}
380 	else
381 	{
382 		// dummy
383 		m_form = std::auto_ptr<HttpdForm>(new HttpdForm( "", 0 ));
384 	}
385 }
386 
387 
388 // --------------------------------------------------------------------------------------
Form() const389 const HttpdForm& HttpRequest::Form() const
390 {
391 	if (!m_form.get())
392 		throw Exception("Form not available");
393 	return *m_form;
394 }
395 
396 
397 // --------------------------------------------------------------------------------------
Cookies() const398 const HttpdCookies& HttpRequest::Cookies() const
399 {
400 	return m_cookies;
401 }
402 
403 
404 // --------------------------------------------------------------------------------------
Reset()405 void HttpRequest::Reset()
406 {
407 	HttpTransaction::Reset();
408 	m_method = "";
409 	m_protocol = "";
410 	m_req_uri = "";
411 	m_remote_addr = "";
412 	m_remote_host = "";
413 	m_server_name = "";
414 	m_server_port = 0;
415 	m_is_ssl = false;
416 	while (!m_attribute.empty())
417 	{
418 		m_attribute.erase(m_attribute.begin());
419 	}
420 	m_body_file = std::auto_ptr<IFile>(NULL);
421 	m_form = std::auto_ptr<HttpdForm>(NULL);
422 	m_cookies.Reset();
423 	while (!m_cookie.empty())
424 	{
425 		m_cookie.erase(m_cookie.begin());
426 	}
427 }
428 
429 
430 #ifdef SOCKETS_NAMESPACE
431 } // namespace SOCKETS_NAMESPACE {
432 #endif
433 
434 
435