1 // distribution boxbackup-0.11_trunk_2979 (svn version: 2979)
2 // Box Backup, http://www.boxbackup.org/
3 //
4 // Copyright (c) 2003-2010, Ben Summers and contributors.
5 // All rights reserved.
6 //
7 // Note that this project uses mixed licensing. Any file with this license
8 // attached, or where the code LICENSE-DUAL appears on the first line, falls
9 // under this license. See the file COPYING.txt for more information.
10 //
11 // This file is dual licensed. You may use and distribute it providing that you
12 // comply EITHER with the terms of the BSD license, OR the GPL license. It is
13 // not necessary to comply with both licenses, only one.
14 //
15 // The BSD license option follows:
16 //
17 // Redistribution and use in source and binary forms, with or without
18 // modification, are permitted provided that the following conditions are met:
19 //
20 // 1. Redistributions of source code must retain the above copyright
21 //    notice, this list of conditions and the following disclaimer.
22 //
23 // 2. Redistributions in binary form must reproduce the above copyright
24 //    notice, this list of conditions and the following disclaimer in the
25 //    documentation and/or other materials provided with the distribution.
26 //
27 // 3. Neither the name of the Box Backup nor the names of its contributors may
28 //    be used to endorse or promote products derived from this software without
29 //    specific prior written permission.
30 //
31 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
32 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
35 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 //
42 // [http://en.wikipedia.org/wiki/BSD_licenses#3-clause_license_.28.22New_BSD_License.22.29]
43 //
44 // The GPL license option follows:
45 //
46 // This program is free software; you can redistribute it and/or
47 // modify it under the terms of the GNU General Public License
48 // as published by the Free Software Foundation; either version 2
49 // of the License, or (at your option) any later version.
50 //
51 // This program is distributed in the hope that it will be useful,
52 // but WITHOUT ANY WARRANTY; without even the implied warranty of
53 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
54 // GNU General Public License for more details.
55 //
56 // You should have received a copy of the GNU General Public License
57 // along with this program; if not, write to the Free Software
58 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
59 //
60 // [http://www.gnu.org/licenses/old-licenses/gpl-2.0.html#SEC4]
61 // --------------------------------------------------------------------------
62 //
63 // File
64 //		Name:    HTTPRequest.h
65 //		Purpose: Request object for HTTP connections
66 //		Created: 26/3/04
67 //
68 // --------------------------------------------------------------------------
69 
70 #ifndef HTTPREQUEST__H
71 #define HTTPREQUEST__H
72 
73 #include <string>
74 #include <map>
75 
76 #include "CollectInBufferStream.h"
77 
78 class HTTPResponse;
79 class IOStream;
80 class IOStreamGetLine;
81 
82 // --------------------------------------------------------------------------
83 //
84 // Class
85 //		Name:    HTTPRequest
86 //		Purpose: Request object for HTTP connections
87 //		Created: 26/3/04
88 //
89 // --------------------------------------------------------------------------
90 class HTTPRequest : public CollectInBufferStream
91 {
92 public:
93 	enum Method
94 	{
95 		Method_UNINITIALISED = -1,
96 		Method_UNKNOWN = 0,
97 		Method_GET = 1,
98 		Method_HEAD = 2,
99 		Method_POST = 3,
100 		Method_PUT = 4
101 	};
102 
103 	HTTPRequest();
104 	HTTPRequest(enum Method method, const std::string& rURI);
105 	~HTTPRequest();
106 private:
107 	// no copying
108 	HTTPRequest(const HTTPRequest &);
109 	HTTPRequest &operator=(const HTTPRequest &);
110 public:
111 	typedef std::multimap<std::string, std::string> Query_t;
112 	typedef Query_t::value_type QueryEn_t;
113 	typedef std::pair<std::string, std::string> Header;
114 
115 	enum
116 	{
117 		HTTPVersion__MajorMultiplier = 1000,
118 		HTTPVersion_0_9 = 9,
119 		HTTPVersion_1_0 = 1000,
120 		HTTPVersion_1_1 = 1001
121 	};
122 
123 	bool Receive(IOStreamGetLine &rGetLine, int Timeout);
124 	bool Send(IOStream &rStream, int Timeout, bool ExpectContinue = false);
125 	void SendWithStream(IOStream &rStreamToSendTo, int Timeout,
126 		IOStream* pStreamToSend, HTTPResponse& rResponse);
127 	void ReadContent(IOStream& rStreamToWriteTo);
128 
129 	typedef std::map<std::string, std::string> CookieJar_t;
130 
131 	// --------------------------------------------------------------------------
132 	//
133 	// Function
134 	//		Name:    HTTPResponse::Get*()
135 	//		Purpose: Various Get accessors
136 	//		Created: 26/3/04
137 	//
138 	// --------------------------------------------------------------------------
GetMethod()139 	enum Method GetMethod() const {return mMethod;}
GetRequestURI()140 	const std::string &GetRequestURI() const {return mRequestURI;}
141 
142 	// Note: the HTTPRequest generates and parses the Host: header
143 	// Do not attempt to set one yourself with AddHeader().
GetHostName()144 	const std::string &GetHostName() const {return mHostName;}
SetHostName(const std::string & rHostName)145 	void SetHostName(const std::string& rHostName)
146 	{
147 		mHostName = rHostName;
148 	}
149 
GetHostPort()150 	const int GetHostPort() const {return mHostPort;}
GetQueryString()151 	const std::string &GetQueryString() const {return mQueryString;}
GetHTTPVersion()152 	int GetHTTPVersion() const {return mHTTPVersion;}
GetQuery()153 	const Query_t &GetQuery() const {return mQuery;}
GetContentLength()154 	int GetContentLength() const {return mContentLength;}
GetContentType()155 	const std::string &GetContentType() const {return mContentType;}
GetCookies()156 	const CookieJar_t *GetCookies() const {return mpCookies;} // WARNING: May return NULL
157 	bool GetCookie(const char *CookieName, std::string &rValueOut) const;
158 	const std::string &GetCookie(const char *CookieName) const;
GetHeader(const std::string & rName,std::string * pValueOut)159 	bool GetHeader(const std::string& rName, std::string* pValueOut) const
160 	{
161 		std::string header = ToLowerCase(rName);
162 
163 		for (std::vector<Header>::const_iterator
164 			i  = mExtraHeaders.begin();
165 			i != mExtraHeaders.end(); i++)
166 		{
167 			if (i->first == header)
168 			{
169 				*pValueOut = i->second;
170 				return true;
171 			}
172 		}
173 
174 		return false;
175 	}
GetHeaders()176 	std::vector<Header> GetHeaders() { return mExtraHeaders; }
177 
178 	// --------------------------------------------------------------------------
179 	//
180 	// Function
181 	//		Name:    HTTPRequest::GetClientKeepAliveRequested()
182 	//		Purpose: Returns true if the client requested that the connection
183 	//				 should be kept open for further requests.
184 	//		Created: 22/12/04
185 	//
186 	// --------------------------------------------------------------------------
GetClientKeepAliveRequested()187 	bool GetClientKeepAliveRequested() const {return mClientKeepAliveRequested;}
SetClientKeepAliveRequested(bool keepAlive)188 	void SetClientKeepAliveRequested(bool keepAlive)
189 	{
190 		mClientKeepAliveRequested = keepAlive;
191 	}
192 
AddHeader(const std::string & rName,const std::string & rValue)193 	void AddHeader(const std::string& rName, const std::string& rValue)
194 	{
195 		mExtraHeaders.push_back(Header(ToLowerCase(rName), rValue));
196 	}
IsExpectingContinue()197 	bool IsExpectingContinue() const { return mExpectContinue; }
GetVerb()198 	const char* GetVerb() const
199 	{
200 		if (!mHttpVerb.empty())
201 		{
202 			return mHttpVerb.c_str();
203 		}
204 		switch (mMethod)
205 		{
206 			case Method_UNINITIALISED: return "Uninitialized";
207 			case Method_UNKNOWN: return "Unknown";
208 			case Method_GET: return "GET";
209 			case Method_HEAD: return "HEAD";
210 			case Method_POST: return "POST";
211 			case Method_PUT: return "PUT";
212 		}
213 		return "Bad";
214 	}
215 
216 private:
217 	void ParseHeaders(IOStreamGetLine &rGetLine, int Timeout);
218 	void ParseCookies(const std::string &rHeader, int DataStarts);
219 
220 	enum Method mMethod;
221 	std::string mRequestURI;
222 	std::string mHostName;
223 	int mHostPort;
224 	std::string mQueryString;
225 	int mHTTPVersion;
226 	Query_t mQuery;
227 	int mContentLength;
228 	std::string mContentType;
229 	CookieJar_t *mpCookies;
230 	bool mClientKeepAliveRequested;
231 	std::vector<Header> mExtraHeaders;
232 	bool mExpectContinue;
233 	IOStream* mpStreamToReadFrom;
234 	std::string mHttpVerb;
235 
ToLowerCase(const std::string & rInput)236 	std::string ToLowerCase(const std::string& rInput) const
237 	{
238 		std::string output = rInput;
239 		for (std::string::iterator c = output.begin();
240 			c != output.end(); c++)
241 		{
242 			*c = tolower(*c);
243 		}
244 		return output;
245 	}
246 };
247 
248 #endif // HTTPREQUEST__H
249 
250