Showing
13 changed files
with
773 additions
and
0 deletions
.gitignore
0 → 100644
.gitmodules
0 → 100644
Tracer.h
0 → 100644
1 | +/* | ||
2 | + Tracer.h | ||
3 | + | ||
4 | + Copyright (C) 2002-2004 René Nyffenegger | ||
5 | + | ||
6 | + This source code is provided 'as-is', without any express or implied | ||
7 | + warranty. In no event will the author be held liable for any damages | ||
8 | + arising from the use of this software. | ||
9 | + | ||
10 | + Permission is granted to anyone to use this software for any purpose, | ||
11 | + including commercial applications, and to alter it and redistribute it | ||
12 | + freely, subject to the following restrictions: | ||
13 | + | ||
14 | + 1. The origin of this source code must not be misrepresented; you must not | ||
15 | + claim that you wrote the original source code. If you use this source code | ||
16 | + in a product, an acknowledgment in the product documentation would be | ||
17 | + appreciated but is not required. | ||
18 | + | ||
19 | + 2. Altered source versions must be plainly marked as such, and must not be | ||
20 | + misrepresented as being the original source code. | ||
21 | + | ||
22 | + 3. This notice may not be removed or altered from any source distribution. | ||
23 | + | ||
24 | + René Nyffenegger rene.nyffenegger@adp-gmbh.ch | ||
25 | +*/ | ||
26 | + | ||
27 | +#ifndef __TRACER_H__ | ||
28 | +#define __TRACER_H__ | ||
29 | + | ||
30 | +#ifdef DO_TRACE | ||
31 | + | ||
32 | +#include <string> | ||
33 | +#include <sstream> | ||
34 | +#include <windows.h> | ||
35 | + | ||
36 | +#define StartTrace(x) TraceFunc_::StartTrace_(x) | ||
37 | +#define Trace(x) dummy_____for_trace_func______.Trace_(x) | ||
38 | +#define Trace2(x,y) dummy_____for_trace_func______.Trace_(x,y) | ||
39 | +#define TraceFunc(x) TraceFunc_ dummy_____for_trace_func______(x) | ||
40 | +#define TraceFunc2(x,y) TraceFunc_ dummy_____for_trace_func______(x,y) | ||
41 | + | ||
42 | +class TraceFunc_ { | ||
43 | + std::string func_name_; | ||
44 | + public: | ||
45 | + TraceFunc_(std::string const&); | ||
46 | + TraceFunc_(std::string const&, std::string const&); | ||
47 | + ~TraceFunc_(); | ||
48 | + | ||
49 | + static void StartTrace_(std::string const& file_name); | ||
50 | + | ||
51 | + template <typename T> | ||
52 | + void Trace_(T const& t) { | ||
53 | + DWORD d; | ||
54 | + std::string indent_s; | ||
55 | + std::stringstream s; | ||
56 | + | ||
57 | + s << t; | ||
58 | + | ||
59 | + for (int i=0; i< indent; i++) indent_s += " "; | ||
60 | + | ||
61 | + ::WriteFile(trace_file_,indent_s.c_str(), indent_s.size(), &d, 0); | ||
62 | + ::WriteFile(trace_file_, s.str().c_str(), s.str().size() ,&d, 0); | ||
63 | + ::WriteFile(trace_file_,"\x0a",1,&d,0); | ||
64 | + } | ||
65 | + | ||
66 | + template <class T, class U> | ||
67 | + void Trace_(T const& t, U const& u) { | ||
68 | + DWORD d; | ||
69 | + std::string indent_s; | ||
70 | + std::stringstream s; | ||
71 | + | ||
72 | + s << t; | ||
73 | + s << u; | ||
74 | + | ||
75 | + for (int i=0; i< indent; i++) indent_s += " "; | ||
76 | + | ||
77 | + ::WriteFile(trace_file_,indent_s.c_str(), indent_s.size(), &d, 0); | ||
78 | + ::WriteFile(trace_file_, s.str().c_str(), s.str().size() ,&d, 0); | ||
79 | + ::WriteFile(trace_file_,"\x0a",1,&d,0); | ||
80 | + } | ||
81 | + | ||
82 | + static int indent; | ||
83 | + static HANDLE trace_file_; | ||
84 | +}; | ||
85 | + | ||
86 | +#else | ||
87 | + | ||
88 | +#define StartTrace(x) | ||
89 | +#define Trace(x) | ||
90 | +#define Trace2(x,y) | ||
91 | +#define TraceFunc(x) | ||
92 | +#define TraceFunc2(x,y) | ||
93 | + | ||
94 | + | ||
95 | +#endif // DO_TRACE | ||
96 | + | ||
97 | +#endif // __TRACER_H__ | ||
98 | + |
UrlHelper.cpp
0 → 100644
1 | +/* | ||
2 | + UrlHelper.cpp | ||
3 | + | ||
4 | + Copyright (C) 2002-2004 René Nyffenegger | ||
5 | + | ||
6 | + This source code is provided 'as-is', without any express or implied | ||
7 | + warranty. In no event will the author be held liable for any damages | ||
8 | + arising from the use of this software. | ||
9 | + | ||
10 | + Permission is granted to anyone to use this software for any purpose, | ||
11 | + including commercial applications, and to alter it and redistribute it | ||
12 | + freely, subject to the following restrictions: | ||
13 | + | ||
14 | + 1. The origin of this source code must not be misrepresented; you must not | ||
15 | + claim that you wrote the original source code. If you use this source code | ||
16 | + in a product, an acknowledgment in the product documentation would be | ||
17 | + appreciated but is not required. | ||
18 | + | ||
19 | + 2. Altered source versions must be plainly marked as such, and must not be | ||
20 | + misrepresented as being the original source code. | ||
21 | + | ||
22 | + 3. This notice may not be removed or altered from any source distribution. | ||
23 | + | ||
24 | + René Nyffenegger rene.nyffenegger@adp-gmbh.ch | ||
25 | +*/ | ||
26 | + | ||
27 | + | ||
28 | +#include "UrlHelper.h" | ||
29 | +#include "Tracer.h" | ||
30 | +#include "stdHelpers.h" | ||
31 | + | ||
32 | +#include <windows.h> | ||
33 | +#include <sstream> | ||
34 | +#include <iostream> | ||
35 | + | ||
36 | +bool RemoveProtocolFromUrl(std::string const& url, std::string& protocol, std::string& rest) { | ||
37 | + TraceFunc("RemoveProtocolFromUrl"); | ||
38 | + Trace(std::string("url='")+url+"'"); | ||
39 | + std::string::size_type pos_colon = url.find(":"); | ||
40 | + | ||
41 | + if (pos_colon == std::string::npos) { | ||
42 | + rest = url; | ||
43 | + return false; | ||
44 | + } | ||
45 | + | ||
46 | + if (url.size() < pos_colon + 2) { | ||
47 | + rest = url; | ||
48 | + return false; | ||
49 | + } | ||
50 | + | ||
51 | + if (url[pos_colon+1] != '/' || | ||
52 | + url[pos_colon+2] != '/') { | ||
53 | + rest = url; | ||
54 | + return false; | ||
55 | + } | ||
56 | + | ||
57 | + protocol = url.substr(0,pos_colon); | ||
58 | + rest = url.substr(3+pos_colon); // Skipping three characters ( '://' ) | ||
59 | + | ||
60 | + return true; | ||
61 | +} | ||
62 | + | ||
63 | +void SplitGetReq(std::string get_req, std::string& path, std::map<std::string, std::string>& params) { | ||
64 | + TraceFunc("SplitGetReq"); | ||
65 | + | ||
66 | + // Remove trailing newlines | ||
67 | + if (get_req[get_req.size()-1] == '\x0d' || | ||
68 | + get_req[get_req.size()-1] == '\x0a') | ||
69 | + get_req=get_req.substr(0, get_req.size()-1); | ||
70 | + | ||
71 | + if (get_req[get_req.size()-1] == '\x0d' || | ||
72 | + get_req[get_req.size()-1] == '\x0a') | ||
73 | + get_req=get_req.substr(0, get_req.size()-1); | ||
74 | + | ||
75 | + // Remove potential Trailing HTTP/1.x | ||
76 | + if (get_req.size() > 7) { | ||
77 | + if (get_req.substr(get_req.size()-8, 7) == "HTTP/1.") { | ||
78 | + get_req=get_req.substr(0, get_req.size()-9); | ||
79 | + } | ||
80 | + } | ||
81 | + | ||
82 | + std::string::size_type qm = get_req.find("?"); | ||
83 | + if (qm != std::string::npos) { | ||
84 | + std::string url_params = get_req.substr(qm+1); | ||
85 | + | ||
86 | + path = get_req.substr(0, qm); | ||
87 | + | ||
88 | + // Appending a '&' so that there are as many '&' as name-value pairs. | ||
89 | + // It makes it easier to split the url for name value pairs, he he he | ||
90 | + url_params += "&"; | ||
91 | + | ||
92 | + std::string::size_type next_amp = url_params.find("&"); | ||
93 | + | ||
94 | + while (next_amp != std::string::npos) { | ||
95 | + std::string name_value = url_params.substr(0,next_amp); | ||
96 | + url_params = url_params.substr(next_amp+1); | ||
97 | + next_amp = url_params.find("&"); | ||
98 | + | ||
99 | + std::string::size_type pos_equal = name_value.find("="); | ||
100 | + | ||
101 | + std::string nam = name_value.substr(0,pos_equal); | ||
102 | + std::string val = name_value.substr(pos_equal+1); | ||
103 | + | ||
104 | + std::string::size_type pos_plus; | ||
105 | + while ( (pos_plus = val.find("+")) != std::string::npos ) { | ||
106 | + val.replace(pos_plus, 1, " "); | ||
107 | + } | ||
108 | + | ||
109 | + // Replacing %xy notation | ||
110 | + std::string::size_type pos_hex = 0; | ||
111 | + while ( (pos_hex = val.find("%", pos_hex)) != std::string::npos ) { | ||
112 | + std::stringstream h; | ||
113 | + h << val.substr(pos_hex+1, 2); | ||
114 | + h << std::hex; | ||
115 | + | ||
116 | + int i; | ||
117 | + h>>i; | ||
118 | + | ||
119 | + std::stringstream f; | ||
120 | + f << static_cast<char>(i); | ||
121 | + std::string s; | ||
122 | + f >> s; | ||
123 | + | ||
124 | + val.replace(pos_hex, 3, s); | ||
125 | + pos_hex ++; | ||
126 | + } | ||
127 | + | ||
128 | + params.insert(std::map<std::string,std::string>::value_type(nam, val)); | ||
129 | + } | ||
130 | + } | ||
131 | + else { | ||
132 | + path = get_req; | ||
133 | + } | ||
134 | +} | ||
135 | + | ||
136 | +void SplitUrl(std::string const& url, std::string& protocol, std::string& server, std::string& path) { | ||
137 | + TraceFunc("SplitUrl"); | ||
138 | + RemoveProtocolFromUrl(url, protocol, server); | ||
139 | + | ||
140 | + if (protocol == "http") { | ||
141 | + std::string::size_type pos_slash = server.find("/"); | ||
142 | + | ||
143 | + if (pos_slash != std::string::npos) { | ||
144 | + Trace("slash found"); | ||
145 | + path = server.substr(pos_slash); | ||
146 | + server = server.substr(0, pos_slash); | ||
147 | + } | ||
148 | + else { | ||
149 | + Trace("slash not found"); | ||
150 | + path = "/"; | ||
151 | + } | ||
152 | + } | ||
153 | + else if (protocol == "file") { | ||
154 | + path = ReplaceInStr(server, "\\", "/"); | ||
155 | + server = ""; | ||
156 | + } | ||
157 | + else { | ||
158 | + std::cerr << "unknown protocol in SplitUrl: '" << protocol << "'" << std::endl; | ||
159 | + } | ||
160 | +} |
UrlHelper.h
0 → 100644
1 | +/* | ||
2 | + UrlHelper.h | ||
3 | + | ||
4 | + Copyright (C) 2002-2004 René Nyffenegger | ||
5 | + | ||
6 | + This source code is provided 'as-is', without any express or implied | ||
7 | + warranty. In no event will the author be held liable for any damages | ||
8 | + arising from the use of this software. | ||
9 | + | ||
10 | + Permission is granted to anyone to use this software for any purpose, | ||
11 | + including commercial applications, and to alter it and redistribute it | ||
12 | + freely, subject to the following restrictions: | ||
13 | + | ||
14 | + 1. The origin of this source code must not be misrepresented; you must not | ||
15 | + claim that you wrote the original source code. If you use this source code | ||
16 | + in a product, an acknowledgment in the product documentation would be | ||
17 | + appreciated but is not required. | ||
18 | + | ||
19 | + 2. Altered source versions must be plainly marked as such, and must not be | ||
20 | + misrepresented as being the original source code. | ||
21 | + | ||
22 | + 3. This notice may not be removed or altered from any source distribution. | ||
23 | + | ||
24 | + René Nyffenegger rene.nyffenegger@adp-gmbh.ch | ||
25 | +*/ | ||
26 | +#ifndef __URL_HELPER_H__ | ||
27 | +#define __URL_HELPER_H__ | ||
28 | + | ||
29 | +#include <string> | ||
30 | +#include <map> | ||
31 | + | ||
32 | +void SplitUrl (std::string const& url, std::string& protocol, std::string& server, std::string& path); | ||
33 | +bool RemoveProtocolFromUrl(std::string const& url, std::string& protocol, std::string& rest); | ||
34 | + | ||
35 | +void SplitGetReq (std::string et_req, std::string& path, std::map<std::string, std::string>& params); | ||
36 | + | ||
37 | + | ||
38 | +#endif |
compile.mingw.bat
0 → 100644
1 | + | ||
2 | +rem set INC_DIR_SOCKET=socket\src | ||
3 | +rem set GCC_FLAGS=-I %INC_DIR_SOCKET% | ||
4 | + | ||
5 | +g++ -I socket\src -I base64 -c webserver.cpp | ||
6 | +g++ -I socket\src -c main.cpp | ||
7 | +g++ -c stdHelpers.cpp | ||
8 | +g++ -c UrlHelper.cpp | ||
9 | +g++ -I socket\src -c socket\src\Socket.cpp -o Socket.o | ||
10 | +g++ -c base64\base64.cpp -o base64.o | ||
11 | + | ||
12 | + | ||
13 | +g++ webserver.o base64.o main.o stdHelpers.o UrlHelper.o Socket.o -lwsock32 -o WebServer.exe |
main.cpp
0 → 100644
1 | +#include "webserver.h" | ||
2 | +#include "Socket.h" | ||
3 | + | ||
4 | +void Request_Handler(webserver::http_request* r) { | ||
5 | + Socket s = *(r->s_); | ||
6 | + | ||
7 | + std::string title; | ||
8 | + std::string body; | ||
9 | + std::string bgcolor="#ffffff"; | ||
10 | + std::string links = | ||
11 | + "<p><a href='/red'>red</a> " | ||
12 | + "<br><a href='/blue'>blue</a> " | ||
13 | + "<br><a href='/form'>form</a> " | ||
14 | + "<br><a href='/auth'>authentication example</a> [use <b>rene</b> as username and <b>secretGarden</b> as password" | ||
15 | + "<br><a href='/header'>show some HTTP header details</a> " | ||
16 | + ; | ||
17 | + | ||
18 | + if(r->path_ == "/") { | ||
19 | + title = "Web Server Example"; | ||
20 | + body = "<h1>Welcome to Rene's Web Server</h1>" | ||
21 | + "I wonder what you're going to click" + links; | ||
22 | + } | ||
23 | + else if (r->path_ == "/red") { | ||
24 | + bgcolor = "#ff4444"; | ||
25 | + title = "You chose red"; | ||
26 | + body = "<h1>Red</h1>" + links; | ||
27 | + } | ||
28 | + else if (r->path_ == "/blue") { | ||
29 | + bgcolor = "#4444ff"; | ||
30 | + title = "You chose blue"; | ||
31 | + body = "<h1>Blue</h1>" + links; | ||
32 | + } | ||
33 | + else if (r->path_ == "/form") { | ||
34 | + title = "Fill a form"; | ||
35 | + | ||
36 | + body = "<h1>Fill a form</h1>"; | ||
37 | + body += "<form action='/form'>" | ||
38 | + "<table>" | ||
39 | + "<tr><td>Field 1</td><td><input name=field_1></td></tr>" | ||
40 | + "<tr><td>Field 2</td><td><input name=field_2></td></tr>" | ||
41 | + "<tr><td>Field 3</td><td><input name=field_3></td></tr>" | ||
42 | + "</table>" | ||
43 | + "<input type=submit></form>"; | ||
44 | + | ||
45 | + | ||
46 | + for (std::map<std::string, std::string>::const_iterator i = r->params_.begin(); | ||
47 | + i != r->params_.end(); | ||
48 | + i++) { | ||
49 | + | ||
50 | + body += "<br>" + i->first + " = " + i->second; | ||
51 | + } | ||
52 | + | ||
53 | + | ||
54 | + body += "<hr>" + links; | ||
55 | + | ||
56 | + } | ||
57 | + else if (r->path_ == "/auth") { | ||
58 | + if (r->authentication_given_) { | ||
59 | + if (r->username_ == "rene" && r->password_ == "secretGarden") { | ||
60 | + body = "<h1>Successfully authenticated</h1>" + links; | ||
61 | + } | ||
62 | + else { | ||
63 | + body = "<h1>Wrong username or password</h1>" + links; | ||
64 | + r->auth_realm_ = "Private Stuff"; | ||
65 | + } | ||
66 | + } | ||
67 | + else { | ||
68 | + r->auth_realm_ = "Private Stuff"; | ||
69 | + } | ||
70 | + } | ||
71 | + else if (r->path_ == "/header") { | ||
72 | + title = "some HTTP header details"; | ||
73 | + body = std::string ("<table>") + | ||
74 | + "<tr><td>Accept:</td><td>" + r->accept_ + "</td></tr>" + | ||
75 | + "<tr><td>Accept-Encoding:</td><td>" + r->accept_encoding_ + "</td></tr>" + | ||
76 | + "<tr><td>Accept-Language:</td><td>" + r->accept_language_ + "</td></tr>" + | ||
77 | + "<tr><td>User-Agent:</td><td>" + r->user_agent_ + "</td></tr>" + | ||
78 | + "</table>" + | ||
79 | + links; | ||
80 | + } | ||
81 | + else { | ||
82 | + r->status_ = "404 Not Found"; | ||
83 | + title = "Wrong URL"; | ||
84 | + body = "<h1>Wrong URL</h1>"; | ||
85 | + body += "Path is : >" + r->path_ + "<"; | ||
86 | + } | ||
87 | + | ||
88 | + r->answer_ = "<html><head><title>"; | ||
89 | + r->answer_ += title; | ||
90 | + r->answer_ += "</title></head><body bgcolor='" + bgcolor + "'>"; | ||
91 | + r->answer_ += body; | ||
92 | + r->answer_ += "</body></html>"; | ||
93 | +} | ||
94 | + | ||
95 | +int main() { | ||
96 | + webserver(8080, Request_Handler); | ||
97 | +} |
stdHelpers.cpp
0 → 100644
1 | +/* | ||
2 | + stdHelpers.cpp | ||
3 | + | ||
4 | + Copyright (C) 2002-2004 René Nyffenegger | ||
5 | + | ||
6 | + This source code is provided 'as-is', without any express or implied | ||
7 | + warranty. In no event will the author be held liable for any damages | ||
8 | + arising from the use of this software. | ||
9 | + | ||
10 | + Permission is granted to anyone to use this software for any purpose, | ||
11 | + including commercial applications, and to alter it and redistribute it | ||
12 | + freely, subject to the following restrictions: | ||
13 | + | ||
14 | + 1. The origin of this source code must not be misrepresented; you must not | ||
15 | + claim that you wrote the original source code. If you use this source code | ||
16 | + in a product, an acknowledgment in the product documentation would be | ||
17 | + appreciated but is not required. | ||
18 | + | ||
19 | + 2. Altered source versions must be plainly marked as such, and must not be | ||
20 | + misrepresented as being the original source code. | ||
21 | + | ||
22 | + 3. This notice may not be removed or altered from any source distribution. | ||
23 | + | ||
24 | + René Nyffenegger rene.nyffenegger@adp-gmbh.ch | ||
25 | +*/ | ||
26 | + | ||
27 | +#include "stdHelpers.h" | ||
28 | +#include <algorithm> | ||
29 | +#include <cctype> | ||
30 | + | ||
31 | +std::string ReplaceInStr(const std::string& in, const std::string& search_for, const std::string& replace_with) { | ||
32 | + std::string ret = in; | ||
33 | + | ||
34 | + std::string::size_type pos = ret.find(search_for); | ||
35 | + | ||
36 | + while (pos != std::string::npos) { | ||
37 | + ret = ret.replace(pos, search_for.size(), replace_with); | ||
38 | + pos = pos - search_for.size() + replace_with.size() + 1; | ||
39 | + pos = ret.find(search_for, pos); | ||
40 | + } | ||
41 | + | ||
42 | + return ret; | ||
43 | +} | ||
44 | + | ||
45 | +// std:toupper and std::tolower are overloaded. Well... | ||
46 | +// http://gcc.gnu.org/ml/libstdc++/2002-11/msg00180.html | ||
47 | +char toLower_ (char c) { return std::tolower(c); } | ||
48 | +char toUpper_ (char c) { return std::toupper(c); } | ||
49 | + | ||
50 | +void ToUpper(std::string& s) { | ||
51 | + std::transform(s.begin(), s.end(), s.begin(),toUpper_); | ||
52 | +} | ||
53 | + | ||
54 | +void ToLower(std::string& s) { | ||
55 | + std::transform(s.begin(), s.end(), s.begin(),toLower_); | ||
56 | +} |
stdHelpers.h
0 → 100644
1 | +/* | ||
2 | + stdHelpers.h | ||
3 | + | ||
4 | + Copyright (C) 2002-2005 René Nyffenegger | ||
5 | + | ||
6 | + This source code is provided 'as-is', without any express or implied | ||
7 | + warranty. In no event will the author be held liable for any damages | ||
8 | + arising from the use of this software. | ||
9 | + | ||
10 | + Permission is granted to anyone to use this software for any purpose, | ||
11 | + including commercial applications, and to alter it and redistribute it | ||
12 | + freely, subject to the following restrictions: | ||
13 | + | ||
14 | + 1. The origin of this source code must not be misrepresented; you must not | ||
15 | + claim that you wrote the original source code. If you use this source code | ||
16 | + in a product, an acknowledgment in the product documentation would be | ||
17 | + appreciated but is not required. | ||
18 | + | ||
19 | + 2. Altered source versions must be plainly marked as such, and must not be | ||
20 | + misrepresented as being the original source code. | ||
21 | + | ||
22 | + 3. This notice may not be removed or altered from any source distribution. | ||
23 | + | ||
24 | + René Nyffenegger rene.nyffenegger@adp-gmbh.ch | ||
25 | +*/ | ||
26 | + | ||
27 | +#ifndef STDHELPERS_H__ | ||
28 | +#define STDHELPERS_H__ | ||
29 | + | ||
30 | +#include <string> | ||
31 | +#include <sstream> | ||
32 | + | ||
33 | +std::string ReplaceInStr(const std::string& in, const std::string& search_for, const std::string& replace_with); | ||
34 | + | ||
35 | +void ToUpper(std::string& s); | ||
36 | +void ToLower(std::string& s); | ||
37 | + | ||
38 | +template <class T> | ||
39 | +T To(std::string const& s) { | ||
40 | + T ret; | ||
41 | + | ||
42 | + std::stringstream stream; | ||
43 | + stream << s; | ||
44 | + stream >> ret; | ||
45 | + | ||
46 | + return ret; | ||
47 | +} | ||
48 | + | ||
49 | +template<class T> | ||
50 | +std::string StringFrom(T const& t) { | ||
51 | + std::string ret; | ||
52 | + | ||
53 | + std::stringstream stream; | ||
54 | + stream << t; | ||
55 | + stream >> ret; | ||
56 | + | ||
57 | + return ret; | ||
58 | +} | ||
59 | + | ||
60 | +#endif |
webserver.cpp
0 → 100644
1 | +/* | ||
2 | + WebServer.cpp | ||
3 | + | ||
4 | + Copyright (C) 2003-2004 René Nyffenegger | ||
5 | + | ||
6 | + This source code is provided 'as-is', without any express or implied | ||
7 | + warranty. In no event will the author be held liable for any damages | ||
8 | + arising from the use of this software. | ||
9 | + | ||
10 | + Permission is granted to anyone to use this software for any purpose, | ||
11 | + including commercial applications, and to alter it and redistribute it | ||
12 | + freely, subject to the following restrictions: | ||
13 | + | ||
14 | + 1. The origin of this source code must not be misrepresented; you must not | ||
15 | + claim that you wrote the original source code. If you use this source code | ||
16 | + in a product, an acknowledgment in the product documentation would be | ||
17 | + appreciated but is not required. | ||
18 | + | ||
19 | + 2. Altered source versions must be plainly marked as such, and must not be | ||
20 | + misrepresented as being the original source code. | ||
21 | + | ||
22 | + 3. This notice may not be removed or altered from any source distribution. | ||
23 | + | ||
24 | + René Nyffenegger rene.nyffenegger@adp-gmbh.ch | ||
25 | + | ||
26 | + Thanks to Tom Lynn who pointed out an error in this source code. | ||
27 | +*/ | ||
28 | + | ||
29 | +#include <ctime> | ||
30 | +#include <process.h> | ||
31 | +#include <iostream> | ||
32 | +#include <string> | ||
33 | +#include <map> | ||
34 | +#include <sstream> | ||
35 | +//<process.h> | ||
36 | + | ||
37 | + | ||
38 | +#include "webserver.h" | ||
39 | +#include "socket.h" | ||
40 | +#include "UrlHelper.h" | ||
41 | +#include "base64.h" | ||
42 | + | ||
43 | +webserver::request_func webserver::request_func_=0; | ||
44 | + | ||
45 | +unsigned webserver::Request(void* ptr_s) { | ||
46 | + Socket s = *(reinterpret_cast<Socket*>(ptr_s)); | ||
47 | + | ||
48 | + std::string line = s.ReceiveLine(); | ||
49 | + if (line.empty()) { | ||
50 | + return 1; | ||
51 | + } | ||
52 | + | ||
53 | + http_request req; | ||
54 | + | ||
55 | + if (line.find("GET") == 0) { | ||
56 | + req.method_="GET"; | ||
57 | + } | ||
58 | + else if (line.find("POST") == 0) { | ||
59 | + req.method_="POST"; | ||
60 | + } | ||
61 | + | ||
62 | + std::string path; | ||
63 | + std::map<std::string, std::string> params; | ||
64 | + | ||
65 | + size_t posStartPath = line.find_first_not_of(" ",3); | ||
66 | + | ||
67 | + SplitGetReq(line.substr(posStartPath), path, params); | ||
68 | + | ||
69 | + req.status_ = "202 OK"; | ||
70 | + req.s_ = &s; | ||
71 | + req.path_ = path; | ||
72 | + req.params_ = params; | ||
73 | + | ||
74 | + static const std::string authorization = "Authorization: Basic "; | ||
75 | + static const std::string accept = "Accept: " ; | ||
76 | + static const std::string accept_language = "Accept-Language: " ; | ||
77 | + static const std::string accept_encoding = "Accept-Encoding: " ; | ||
78 | + static const std::string user_agent = "User-Agent: " ; | ||
79 | + | ||
80 | + while(1) { | ||
81 | + line=s.ReceiveLine(); | ||
82 | + | ||
83 | + if (line.empty()) break; | ||
84 | + | ||
85 | + unsigned int pos_cr_lf = line.find_first_of("\x0a\x0d"); | ||
86 | + if (pos_cr_lf == 0) break; | ||
87 | + | ||
88 | + line = line.substr(0,pos_cr_lf); | ||
89 | + | ||
90 | + if (line.substr(0, authorization.size()) == authorization) { | ||
91 | + req.authentication_given_ = true; | ||
92 | + std::string encoded = line.substr(authorization.size()); | ||
93 | + std::string decoded = base64_decode(encoded); | ||
94 | + | ||
95 | + unsigned int pos_colon = decoded.find(":"); | ||
96 | + | ||
97 | + req.username_ = decoded.substr(0, pos_colon); | ||
98 | + req.password_ = decoded.substr(pos_colon+1 ); | ||
99 | + } | ||
100 | + else if (line.substr(0, accept.size()) == accept) { | ||
101 | + req.accept_ = line.substr(accept.size()); | ||
102 | + } | ||
103 | + else if (line.substr(0, accept_language.size()) == accept_language) { | ||
104 | + req.accept_language_ = line.substr(accept_language.size()); | ||
105 | + } | ||
106 | + else if (line.substr(0, accept_encoding.size()) == accept_encoding) { | ||
107 | + req.accept_encoding_ = line.substr(accept_encoding.size()); | ||
108 | + } | ||
109 | + else if (line.substr(0, user_agent.size()) == user_agent) { | ||
110 | + req.user_agent_ = line.substr(user_agent.size()); | ||
111 | + } | ||
112 | + } | ||
113 | + | ||
114 | + request_func_(&req); | ||
115 | + | ||
116 | + std::stringstream str_str; | ||
117 | + str_str << req.answer_.size(); | ||
118 | + | ||
119 | + time_t ltime; | ||
120 | + time(<ime); | ||
121 | + tm* gmt= gmtime(<ime); | ||
122 | + | ||
123 | + static std::string const serverName = "RenesWebserver (Windows)"; | ||
124 | + | ||
125 | + char* asctime_remove_nl = asctime(gmt); | ||
126 | + asctime_remove_nl[24] = 0; | ||
127 | + | ||
128 | + s.SendBytes("HTTP/1.1 "); | ||
129 | + | ||
130 | + if (! req.auth_realm_.empty() ) { | ||
131 | + s.SendLine("401 Unauthorized"); | ||
132 | + s.SendBytes("WWW-Authenticate: Basic Realm=\""); | ||
133 | + s.SendBytes(req.auth_realm_); | ||
134 | + s.SendLine("\""); | ||
135 | + } | ||
136 | + else { | ||
137 | + s.SendLine(req.status_); | ||
138 | + } | ||
139 | + s.SendLine(std::string("Date: ") + asctime_remove_nl + " GMT"); | ||
140 | + s.SendLine(std::string("Server: ") +serverName); | ||
141 | + s.SendLine("Connection: close"); | ||
142 | + s.SendLine("Content-Type: text/html; charset=ISO-8859-1"); | ||
143 | + s.SendLine("Content-Length: " + str_str.str()); | ||
144 | + s.SendLine(""); | ||
145 | + s.SendLine(req.answer_); | ||
146 | + | ||
147 | + s.Close(); | ||
148 | + | ||
149 | + | ||
150 | + return 0; | ||
151 | +} | ||
152 | + | ||
153 | +webserver::webserver(unsigned int port_to_listen, request_func r) { | ||
154 | + SocketServer in(port_to_listen,5); | ||
155 | + | ||
156 | + request_func_ = r; | ||
157 | + | ||
158 | + while (1) { | ||
159 | + Socket* ptr_s=in.Accept(); | ||
160 | + | ||
161 | + unsigned ret; | ||
162 | + _beginthreadex(0,0,Request,(void*) ptr_s,0,&ret); | ||
163 | + } | ||
164 | +} |
webserver.h
0 → 100644
1 | +/* | ||
2 | + WebServer.h | ||
3 | + | ||
4 | + Copyright (C) 2003-2004 René Nyffenegger | ||
5 | + | ||
6 | + This source code is provided 'as-is', without any express or implied | ||
7 | + warranty. In no event will the author be held liable for any damages | ||
8 | + arising from the use of this software. | ||
9 | + | ||
10 | + Permission is granted to anyone to use this software for any purpose, | ||
11 | + including commercial applications, and to alter it and redistribute it | ||
12 | + freely, subject to the following restrictions: | ||
13 | + | ||
14 | + 1. The origin of this source code must not be misrepresented; you must not | ||
15 | + claim that you wrote the original source code. If you use this source code | ||
16 | + in a product, an acknowledgment in the product documentation would be | ||
17 | + appreciated but is not required. | ||
18 | + | ||
19 | + 2. Altered source versions must be plainly marked as such, and must not be | ||
20 | + misrepresented as being the original source code. | ||
21 | + | ||
22 | + 3. This notice may not be removed or altered from any source distribution. | ||
23 | + | ||
24 | + René Nyffenegger rene.nyffenegger@adp-gmbh.ch | ||
25 | + | ||
26 | +*/ | ||
27 | + | ||
28 | +#include <string> | ||
29 | +#include <map> | ||
30 | + | ||
31 | +class Socket; | ||
32 | + | ||
33 | +class webserver { | ||
34 | + public: | ||
35 | + struct http_request { | ||
36 | + | ||
37 | + http_request() : authentication_given_(false) {} | ||
38 | + | ||
39 | + Socket* s_; | ||
40 | + std::string method_; | ||
41 | + std::string path_; | ||
42 | + std::map<std::string, std::string> params_; | ||
43 | + | ||
44 | + std::string accept_; | ||
45 | + std::string accept_language_; | ||
46 | + std::string accept_encoding_; | ||
47 | + std::string user_agent_; | ||
48 | + | ||
49 | + /* status_: used to transmit server's error status, such as | ||
50 | + o 202 OK | ||
51 | + o 404 Not Found | ||
52 | + and so on */ | ||
53 | + std::string status_; | ||
54 | + | ||
55 | + /* auth_realm_: allows to set the basic realm for an authentication, | ||
56 | + no need to additionally set status_ if set */ | ||
57 | + std::string auth_realm_; | ||
58 | + | ||
59 | + std::string answer_; | ||
60 | + | ||
61 | + /* authentication_given_ is true when the user has entered a username and password. | ||
62 | + These can then be read from username_ and password_ */ | ||
63 | + bool authentication_given_; | ||
64 | + std::string username_; | ||
65 | + std::string password_; | ||
66 | + }; | ||
67 | + | ||
68 | + typedef void (*request_func) (http_request*); | ||
69 | + webserver(unsigned int port_to_listen, request_func); | ||
70 | + | ||
71 | + | ||
72 | + private: | ||
73 | + static unsigned __stdcall Request(void*); | ||
74 | + static request_func request_func_; | ||
75 | +}; | ||
76 | + |
-
Please register or login to post a comment