summaryrefslogtreecommitdiffstats
path: root/WebServer
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--WebServer/Globals.cpp20
-rw-r--r--WebServer/Socket.cpp744
-rw-r--r--WebServer/StdHelpers.cpp124
-rw-r--r--WebServer/UrlHelper.cpp330
-rw-r--r--WebServer/WebServer.cpp994
-rw-r--r--WebServer/base64.cpp198
-rw-r--r--WebServer/cEvents.cpp250
7 files changed, 1330 insertions, 1330 deletions
diff --git a/WebServer/Globals.cpp b/WebServer/Globals.cpp
index 2c60fd698..13c6ae709 100644
--- a/WebServer/Globals.cpp
+++ b/WebServer/Globals.cpp
@@ -1,10 +1,10 @@
-
-// Globals.cpp
-
-// This file is used for precompiled header generation in MSVC environments
-
-#include "Globals.h"
-
-
-
-
+
+// Globals.cpp
+
+// This file is used for precompiled header generation in MSVC environments
+
+#include "Globals.h"
+
+
+
+
diff --git a/WebServer/Socket.cpp b/WebServer/Socket.cpp
index 430461fe8..2dde93b22 100644
--- a/WebServer/Socket.cpp
+++ b/WebServer/Socket.cpp
@@ -1,372 +1,372 @@
-/*
- Socket.cpp
-
- Copyright (C) 2002-2004 René Nyffenegger
-
- This source code is provided 'as-is', without any express or implied
- warranty. In no event will the author be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this source code must not be misrepresented; you must not
- claim that you wrote the original source code. If you use this source code
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original source code.
-
- 3. This notice may not be removed or altered from any source distribution.
-
- René Nyffenegger rene.nyffenegger@adp-gmbh.ch
-*/
-
-/*
- Note on point 2:
- THIS IS NOT THE ORIGINAL SOURCE1!!1!!!~!!~`1ONE!!`1
-*/
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "Socket.h"
-#include <iostream>
-
-#ifndef _WIN32
- #include <cstring>
- #include <sys/time.h>
- #include <unistd.h>
- #define SD_SEND 0x01
-#else
- #define MSG_NOSIGNAL (0)
-#endif
-
-#ifdef __MAC_NA
- #define MSG_NOSIGNAL (0)
-#endif
-
-#ifndef MSG_NOSIGNAL
- #define MSG_NOSIGNAL 0
-#endif // MSG_NOSIGNAL
-
-using namespace std;
-
-int Socket::nofSockets_= 0;
-
-
-
-
-
-void Socket::Start()
-{
- #ifdef _WIN32
- if (!nofSockets_)
- {
- WSADATA info;
- if (WSAStartup(MAKEWORD(2,0), &info))
- {
- throw "Could not start WSA";
- }
- }
- #endif
- ++nofSockets_;
-}
-
-
-
-
-
-void Socket::End()
-{
-#ifdef _WIN32
- WSACleanup();
-#endif
-}
-
-
-
-
-
-Socket::Socket() :
- s_(INVALID_SOCKET)
-{
- Start();
- // UDP: use SOCK_DGRAM instead of SOCK_STREAM
- s_ = socket(AF_INET,SOCK_STREAM,0);
-
- if (!IsValid())
- {
- throw "INVALID_SOCKET";
- }
-
- refCounter_ = new int(1);
-}
-
-
-
-
-
-Socket::Socket(SOCKET s) : s_(s)
-{
- Start();
- refCounter_ = new int(1);
-};
-
-
-
-
-
-Socket::~Socket()
-{
- if (! --(*refCounter_))
- {
- Close();
- delete refCounter_;
- }
-
- --nofSockets_;
- if (!nofSockets_)
- {
- End();
- }
-}
-
-
-
-
-
-Socket::Socket(const Socket& o)
-{
- refCounter_=o.refCounter_;
- (*refCounter_)++;
- s_ =o.s_;
-
- nofSockets_++;
-}
-
-
-
-
-
-Socket& Socket::operator=(Socket& o)
-{
- (*o.refCounter_)++;
-
- refCounter_ = o.refCounter_;
- s_ = o.s_;
-
- nofSockets_++;
-
- return *this;
-}
-
-
-
-
-
-bool Socket::IsValid(void) const
-{
- #ifdef _WIN32
- return (s_ != INVALID_SOCKET);
- #else
- return (s_ >= 0);
- #endif
-}
-
-
-
-
-
-void Socket::Close( bool a_WaitSend /* = false */ )
-{
- if (IsValid())
- {
- if (a_WaitSend)
- {
- assert( shutdown(s_, SD_SEND ) == 0 );
- char c;
- while( recv(s_, &c, 1, 0 ) > 0 )
- {}
- }
-
- #ifndef _WIN32
- // Linux needs to shut the socket down first, otherwise the socket keeps blocking accept() and select() calls!
- // Ref.: http://forum.mc-server.org/showthread.php?tid=344
- if (shutdown(s_, SHUT_RDWR) != 0)
- {
- LOGWARN("Error on shutting down socket %d", s_);
- }
- #endif // _WIN32
-
- closesocket(s_);
-
- s_ = INVALID_SOCKET;
- }
-}
-
-
-
-
-
-std::string Socket::ReceiveLine()
-{
- std::string ret;
- while (1)
- {
- char r;
-
- if (recv(s_, &r, 1, 0) <= 0 )
- {
- return "";
- }
- ret += r;
- if (r == '\n') return ret;
- }
-}
-
-
-
-
-
-std::string Socket::ReceiveBytes( unsigned int a_Length )
-{
- std::string ret;
- while( ret.size() < a_Length )
- {
- char r;
-
- if (recv(s_, &r, 1, 0) <= 0 )
- {
- return "";
- }
- ret += r;
- }
- return ret;
-}
-
-
-
-
-
-void Socket::SendLine(std::string s)
-{
- s += '\n';
- if( send(s_,s.c_str(),s.length(),MSG_NOSIGNAL) <= 0 )
- {
- //printf("SendLine Socket error!! \n" );
- Close();
- }
-}
-
-
-
-
-
-void Socket::SendBytes(const std::string& s)
-{
- if( send(s_,s.c_str(),s.length(), MSG_NOSIGNAL) <= 0 )
- {
- //printf("SendBytes Socket error!! \n" );
- Close();
- }
-}
-
-
-
-
-
-SocketServer::SocketServer(int port, int connections, TypeSocket type)
-{
- sockaddr_in sa;
-
- memset(&sa, 0, sizeof(sa));
-
- sa.sin_family = PF_INET;
- sa.sin_port = htons(port);
- s_ = socket(AF_INET, SOCK_STREAM, 0);
-
- if (!IsValid())
- {
- LOG("WebServer: INVALID_SOCKET");
- }
-
- if(type==NonBlockingSocket)
- {
- return;
- }
-
- #ifdef _WIN32
- char yes = 1;
- #else
- int yes = 1;
- #endif
-
- if (setsockopt(s_,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1)
- {
- LOG("WebServer: setsockopt == -1");
- return;
- }
-
- /* bind the socket to the internet address */
- if (bind(s_, (sockaddr *)&sa, sizeof(sockaddr_in)) == SOCKET_ERROR)
- {
- closesocket(s_);
- LOG("WebServer: INVALID_SOCKET");
- }
-
- listen(s_, connections);
-}
-
-
-
-
-
-Socket* SocketServer::Accept()
-{
- Socket * r = new Socket(accept(s_, 0, 0));
- if (!r->IsValid())
- {
- delete r;
- r = NULL;
- }
-
- return r;
-}
-
-
-
-
-
-SocketSelect::SocketSelect(Socket const * const s1, Socket const * const s2, TypeSocket type)
-{
- FD_ZERO(&fds_);
- SOCKET Highest = s1->s_;
- FD_SET(const_cast<Socket*>(s1)->s_,&fds_);
- if(s2)
- {
- FD_SET(const_cast<Socket*>(s2)->s_,&fds_);
- if (s2->s_ > Highest)
- {
- Highest = s2->s_;
- }
- }
- if (select(Highest + 1, &fds_, NULL, NULL, NULL) == SOCKET_ERROR)
- {
- throw "Error in select";
- }
-}
-
-
-
-
-
-bool SocketSelect::Readable(Socket const* const s)
-{
- return (FD_ISSET(s->s_,&fds_) != 0);
-}
-
-
-
-
+/*
+ Socket.cpp
+
+ Copyright (C) 2002-2004 René Nyffenegger
+
+ This source code is provided 'as-is', without any express or implied
+ warranty. In no event will the author be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this source code must not be misrepresented; you must not
+ claim that you wrote the original source code. If you use this source code
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original source code.
+
+ 3. This notice may not be removed or altered from any source distribution.
+
+ René Nyffenegger rene.nyffenegger@adp-gmbh.ch
+*/
+
+/*
+ Note on point 2:
+ THIS IS NOT THE ORIGINAL SOURCE1!!1!!!~!!~`1ONE!!`1
+*/
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Socket.h"
+#include <iostream>
+
+#ifndef _WIN32
+ #include <cstring>
+ #include <sys/time.h>
+ #include <unistd.h>
+ #define SD_SEND 0x01
+#else
+ #define MSG_NOSIGNAL (0)
+#endif
+
+#ifdef __MAC_NA
+ #define MSG_NOSIGNAL (0)
+#endif
+
+#ifndef MSG_NOSIGNAL
+ #define MSG_NOSIGNAL 0
+#endif // MSG_NOSIGNAL
+
+using namespace std;
+
+int Socket::nofSockets_= 0;
+
+
+
+
+
+void Socket::Start()
+{
+ #ifdef _WIN32
+ if (!nofSockets_)
+ {
+ WSADATA info;
+ if (WSAStartup(MAKEWORD(2,0), &info))
+ {
+ throw "Could not start WSA";
+ }
+ }
+ #endif
+ ++nofSockets_;
+}
+
+
+
+
+
+void Socket::End()
+{
+#ifdef _WIN32
+ WSACleanup();
+#endif
+}
+
+
+
+
+
+Socket::Socket() :
+ s_(INVALID_SOCKET)
+{
+ Start();
+ // UDP: use SOCK_DGRAM instead of SOCK_STREAM
+ s_ = socket(AF_INET,SOCK_STREAM,0);
+
+ if (!IsValid())
+ {
+ throw "INVALID_SOCKET";
+ }
+
+ refCounter_ = new int(1);
+}
+
+
+
+
+
+Socket::Socket(SOCKET s) : s_(s)
+{
+ Start();
+ refCounter_ = new int(1);
+};
+
+
+
+
+
+Socket::~Socket()
+{
+ if (! --(*refCounter_))
+ {
+ Close();
+ delete refCounter_;
+ }
+
+ --nofSockets_;
+ if (!nofSockets_)
+ {
+ End();
+ }
+}
+
+
+
+
+
+Socket::Socket(const Socket& o)
+{
+ refCounter_=o.refCounter_;
+ (*refCounter_)++;
+ s_ =o.s_;
+
+ nofSockets_++;
+}
+
+
+
+
+
+Socket& Socket::operator=(Socket& o)
+{
+ (*o.refCounter_)++;
+
+ refCounter_ = o.refCounter_;
+ s_ = o.s_;
+
+ nofSockets_++;
+
+ return *this;
+}
+
+
+
+
+
+bool Socket::IsValid(void) const
+{
+ #ifdef _WIN32
+ return (s_ != INVALID_SOCKET);
+ #else
+ return (s_ >= 0);
+ #endif
+}
+
+
+
+
+
+void Socket::Close( bool a_WaitSend /* = false */ )
+{
+ if (IsValid())
+ {
+ if (a_WaitSend)
+ {
+ assert( shutdown(s_, SD_SEND ) == 0 );
+ char c;
+ while( recv(s_, &c, 1, 0 ) > 0 )
+ {}
+ }
+
+ #ifndef _WIN32
+ // Linux needs to shut the socket down first, otherwise the socket keeps blocking accept() and select() calls!
+ // Ref.: http://forum.mc-server.org/showthread.php?tid=344
+ if (shutdown(s_, SHUT_RDWR) != 0)
+ {
+ LOGWARN("Error on shutting down socket %d", s_);
+ }
+ #endif // _WIN32
+
+ closesocket(s_);
+
+ s_ = INVALID_SOCKET;
+ }
+}
+
+
+
+
+
+std::string Socket::ReceiveLine()
+{
+ std::string ret;
+ while (1)
+ {
+ char r;
+
+ if (recv(s_, &r, 1, 0) <= 0 )
+ {
+ return "";
+ }
+ ret += r;
+ if (r == '\n') return ret;
+ }
+}
+
+
+
+
+
+std::string Socket::ReceiveBytes( unsigned int a_Length )
+{
+ std::string ret;
+ while( ret.size() < a_Length )
+ {
+ char r;
+
+ if (recv(s_, &r, 1, 0) <= 0 )
+ {
+ return "";
+ }
+ ret += r;
+ }
+ return ret;
+}
+
+
+
+
+
+void Socket::SendLine(std::string s)
+{
+ s += '\n';
+ if( send(s_,s.c_str(),s.length(),MSG_NOSIGNAL) <= 0 )
+ {
+ //printf("SendLine Socket error!! \n" );
+ Close();
+ }
+}
+
+
+
+
+
+void Socket::SendBytes(const std::string& s)
+{
+ if( send(s_,s.c_str(),s.length(), MSG_NOSIGNAL) <= 0 )
+ {
+ //printf("SendBytes Socket error!! \n" );
+ Close();
+ }
+}
+
+
+
+
+
+SocketServer::SocketServer(int port, int connections, TypeSocket type)
+{
+ sockaddr_in sa;
+
+ memset(&sa, 0, sizeof(sa));
+
+ sa.sin_family = PF_INET;
+ sa.sin_port = htons(port);
+ s_ = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (!IsValid())
+ {
+ LOG("WebServer: INVALID_SOCKET");
+ }
+
+ if(type==NonBlockingSocket)
+ {
+ return;
+ }
+
+ #ifdef _WIN32
+ char yes = 1;
+ #else
+ int yes = 1;
+ #endif
+
+ if (setsockopt(s_,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1)
+ {
+ LOG("WebServer: setsockopt == -1");
+ return;
+ }
+
+ /* bind the socket to the internet address */
+ if (bind(s_, (sockaddr *)&sa, sizeof(sockaddr_in)) == SOCKET_ERROR)
+ {
+ closesocket(s_);
+ LOG("WebServer: INVALID_SOCKET");
+ }
+
+ listen(s_, connections);
+}
+
+
+
+
+
+Socket* SocketServer::Accept()
+{
+ Socket * r = new Socket(accept(s_, 0, 0));
+ if (!r->IsValid())
+ {
+ delete r;
+ r = NULL;
+ }
+
+ return r;
+}
+
+
+
+
+
+SocketSelect::SocketSelect(Socket const * const s1, Socket const * const s2, TypeSocket type)
+{
+ FD_ZERO(&fds_);
+ SOCKET Highest = s1->s_;
+ FD_SET(const_cast<Socket*>(s1)->s_,&fds_);
+ if(s2)
+ {
+ FD_SET(const_cast<Socket*>(s2)->s_,&fds_);
+ if (s2->s_ > Highest)
+ {
+ Highest = s2->s_;
+ }
+ }
+ if (select(Highest + 1, &fds_, NULL, NULL, NULL) == SOCKET_ERROR)
+ {
+ throw "Error in select";
+ }
+}
+
+
+
+
+
+bool SocketSelect::Readable(Socket const* const s)
+{
+ return (FD_ISSET(s->s_,&fds_) != 0);
+}
+
+
+
+
diff --git a/WebServer/StdHelpers.cpp b/WebServer/StdHelpers.cpp
index f858c0bc4..63e48a7d2 100644
--- a/WebServer/StdHelpers.cpp
+++ b/WebServer/StdHelpers.cpp
@@ -1,62 +1,62 @@
-/*
- stdHelpers.cpp
-
- Copyright (C) 2002-2004 René Nyffenegger
-
- This source code is provided 'as-is', without any express or implied
- warranty. In no event will the author be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this source code must not be misrepresented; you must not
- claim that you wrote the original source code. If you use this source code
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original source code.
-
- 3. This notice may not be removed or altered from any source distribution.
-
- René Nyffenegger rene.nyffenegger@adp-gmbh.ch
-*/
-
-/*
- Note on point 2:
- THIS IS NOT THE ORIGINAL SOURCE1!!1!!!~!!~`1ONE!!`1
-*/
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "StdHelpers.h"
-#include <cctype>
-
-std::string ReplaceInStr(const std::string& in, const std::string& search_for, const std::string& replace_with) {
- std::string ret = in;
-
- std::string::size_type pos = ret.find(search_for);
-
- while (pos != std::string::npos) {
- ret = ret.replace(pos, search_for.size(), replace_with);
- pos = pos - search_for.size() + replace_with.size() + 1;
- pos = ret.find(search_for, pos);
- }
-
- return ret;
-}
-
-// std:toupper and std::tolower are overloaded. Well...
-// http://gcc.gnu.org/ml/libstdc++/2002-11/msg00180.html
-char toLower_ (char c) { return std::tolower(c); }
-char toUpper_ (char c) { return std::toupper(c); }
-
-void ToUpper(std::string& s) {
- std::transform(s.begin(), s.end(), s.begin(),toUpper_);
-}
-
-void ToLower(std::string& s) {
- std::transform(s.begin(), s.end(), s.begin(),toLower_);
-}
+/*
+ stdHelpers.cpp
+
+ Copyright (C) 2002-2004 René Nyffenegger
+
+ This source code is provided 'as-is', without any express or implied
+ warranty. In no event will the author be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this source code must not be misrepresented; you must not
+ claim that you wrote the original source code. If you use this source code
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original source code.
+
+ 3. This notice may not be removed or altered from any source distribution.
+
+ René Nyffenegger rene.nyffenegger@adp-gmbh.ch
+*/
+
+/*
+ Note on point 2:
+ THIS IS NOT THE ORIGINAL SOURCE1!!1!!!~!!~`1ONE!!`1
+*/
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "StdHelpers.h"
+#include <cctype>
+
+std::string ReplaceInStr(const std::string& in, const std::string& search_for, const std::string& replace_with) {
+ std::string ret = in;
+
+ std::string::size_type pos = ret.find(search_for);
+
+ while (pos != std::string::npos) {
+ ret = ret.replace(pos, search_for.size(), replace_with);
+ pos = pos - search_for.size() + replace_with.size() + 1;
+ pos = ret.find(search_for, pos);
+ }
+
+ return ret;
+}
+
+// std:toupper and std::tolower are overloaded. Well...
+// http://gcc.gnu.org/ml/libstdc++/2002-11/msg00180.html
+char toLower_ (char c) { return std::tolower(c); }
+char toUpper_ (char c) { return std::toupper(c); }
+
+void ToUpper(std::string& s) {
+ std::transform(s.begin(), s.end(), s.begin(),toUpper_);
+}
+
+void ToLower(std::string& s) {
+ std::transform(s.begin(), s.end(), s.begin(),toLower_);
+}
diff --git a/WebServer/UrlHelper.cpp b/WebServer/UrlHelper.cpp
index 44f1166fd..e0a67687b 100644
--- a/WebServer/UrlHelper.cpp
+++ b/WebServer/UrlHelper.cpp
@@ -1,165 +1,165 @@
-/*
- UrlHelper.cpp
-
- Copyright (C) 2002-2004 René Nyffenegger
-
- This source code is provided 'as-is', without any express or implied
- warranty. In no event will the author be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this source code must not be misrepresented; you must not
- claim that you wrote the original source code. If you use this source code
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original source code.
-
- 3. This notice may not be removed or altered from any source distribution.
-
- René Nyffenegger rene.nyffenegger@adp-gmbh.ch
-*/
-
-/*
- Note on point 2:
- THIS IS NOT THE ORIGINAL SOURCE1!!1!!!~!!~`1ONE!!`1
-*/
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "UrlHelper.h"
-#include "Tracer.h"
-#include "StdHelpers.h"
-
-#include <sstream>
-#include <iostream>
-
-bool RemoveProtocolFromUrl(std::string const& url, std::string& protocol, std::string& rest) {
- TraceFunc("RemoveProtocolFromUrl");
- Trace(std::string("url='")+url+"'");
- std::string::size_type pos_colon = url.find(":");
-
- if (pos_colon == std::string::npos) {
- rest = url;
- return false;
- }
-
- if (url.size() < pos_colon + 2) {
- rest = url;
- return false;
- }
-
- if (url[pos_colon+1] != '/' ||
- url[pos_colon+2] != '/') {
- rest = url;
- return false;
- }
-
- protocol = url.substr(0,pos_colon);
- rest = url.substr(3+pos_colon); // Skipping three characters ( '://' )
-
- return true;
-}
-
-void SplitGetReq(std::string get_req, std::string& path, std::map<std::string, std::string>& params) {
- TraceFunc("SplitGetReq");
-
- // Remove trailing newlines
- if (get_req[get_req.size()-1] == '\x0d' ||
- get_req[get_req.size()-1] == '\x0a')
- get_req=get_req.substr(0, get_req.size()-1);
-
- if (get_req[get_req.size()-1] == '\x0d' ||
- get_req[get_req.size()-1] == '\x0a')
- get_req=get_req.substr(0, get_req.size()-1);
-
- // Remove potential Trailing HTTP/1.x
- if (get_req.size() > 7) {
- if (get_req.substr(get_req.size()-8, 7) == "HTTP/1.") {
- get_req=get_req.substr(0, get_req.size()-9);
- }
- }
-
- std::string::size_type qm = get_req.find("?");
- if (qm != std::string::npos) {
- std::string url_params = get_req.substr(qm+1);
-
- path = get_req.substr(0, qm);
-
- // Appending a '&' so that there are as many '&' as name-value pairs.
- // It makes it easier to split the url for name value pairs, he he he
- url_params += "&";
-
- std::string::size_type next_amp = url_params.find("&");
-
- while (next_amp != std::string::npos) {
- std::string name_value = url_params.substr(0,next_amp);
- url_params = url_params.substr(next_amp+1);
- next_amp = url_params.find("&");
-
- std::string::size_type pos_equal = name_value.find("=");
-
- std::string nam = name_value.substr(0,pos_equal);
- std::string val = name_value.substr(pos_equal+1);
-
- std::string::size_type pos_plus;
- while ( (pos_plus = val.find("+")) != std::string::npos ) {
- val.replace(pos_plus, 1, " ");
- }
-
- // Replacing %xy notation
- std::string::size_type pos_hex = 0;
- while ( (pos_hex = val.find("%", pos_hex)) != std::string::npos ) {
- std::stringstream h;
- h << val.substr(pos_hex+1, 2);
- h << std::hex;
-
- int i;
- h>>i;
-
- std::stringstream f;
- f << static_cast<char>(i);
- std::string s;
- f >> s;
-
- val.replace(pos_hex, 3, s);
- pos_hex ++;
- }
-
- params.insert(std::map<std::string,std::string>::value_type(nam, val));
- }
- }
- else {
- path = get_req;
- }
-}
-
-void SplitUrl(std::string const& url, std::string& protocol, std::string& server, std::string& path) {
- TraceFunc("SplitUrl");
- RemoveProtocolFromUrl(url, protocol, server);
-
- if (protocol == "http") {
- std::string::size_type pos_slash = server.find("/");
-
- if (pos_slash != std::string::npos) {
- Trace("slash found");
- path = server.substr(pos_slash);
- server = server.substr(0, pos_slash);
- }
- else {
- Trace("slash not found");
- path = "/";
- }
- }
- else if (protocol == "file") {
- path = ReplaceInStr(server, "\\", "/");
- server = "";
- }
- else {
- std::cerr << "unknown protocol in SplitUrl: '" << protocol << "'" << std::endl;
- }
-}
+/*
+ UrlHelper.cpp
+
+ Copyright (C) 2002-2004 René Nyffenegger
+
+ This source code is provided 'as-is', without any express or implied
+ warranty. In no event will the author be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this source code must not be misrepresented; you must not
+ claim that you wrote the original source code. If you use this source code
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original source code.
+
+ 3. This notice may not be removed or altered from any source distribution.
+
+ René Nyffenegger rene.nyffenegger@adp-gmbh.ch
+*/
+
+/*
+ Note on point 2:
+ THIS IS NOT THE ORIGINAL SOURCE1!!1!!!~!!~`1ONE!!`1
+*/
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "UrlHelper.h"
+#include "Tracer.h"
+#include "StdHelpers.h"
+
+#include <sstream>
+#include <iostream>
+
+bool RemoveProtocolFromUrl(std::string const& url, std::string& protocol, std::string& rest) {
+ TraceFunc("RemoveProtocolFromUrl");
+ Trace(std::string("url='")+url+"'");
+ std::string::size_type pos_colon = url.find(":");
+
+ if (pos_colon == std::string::npos) {
+ rest = url;
+ return false;
+ }
+
+ if (url.size() < pos_colon + 2) {
+ rest = url;
+ return false;
+ }
+
+ if (url[pos_colon+1] != '/' ||
+ url[pos_colon+2] != '/') {
+ rest = url;
+ return false;
+ }
+
+ protocol = url.substr(0,pos_colon);
+ rest = url.substr(3+pos_colon); // Skipping three characters ( '://' )
+
+ return true;
+}
+
+void SplitGetReq(std::string get_req, std::string& path, std::map<std::string, std::string>& params) {
+ TraceFunc("SplitGetReq");
+
+ // Remove trailing newlines
+ if (get_req[get_req.size()-1] == '\x0d' ||
+ get_req[get_req.size()-1] == '\x0a')
+ get_req=get_req.substr(0, get_req.size()-1);
+
+ if (get_req[get_req.size()-1] == '\x0d' ||
+ get_req[get_req.size()-1] == '\x0a')
+ get_req=get_req.substr(0, get_req.size()-1);
+
+ // Remove potential Trailing HTTP/1.x
+ if (get_req.size() > 7) {
+ if (get_req.substr(get_req.size()-8, 7) == "HTTP/1.") {
+ get_req=get_req.substr(0, get_req.size()-9);
+ }
+ }
+
+ std::string::size_type qm = get_req.find("?");
+ if (qm != std::string::npos) {
+ std::string url_params = get_req.substr(qm+1);
+
+ path = get_req.substr(0, qm);
+
+ // Appending a '&' so that there are as many '&' as name-value pairs.
+ // It makes it easier to split the url for name value pairs, he he he
+ url_params += "&";
+
+ std::string::size_type next_amp = url_params.find("&");
+
+ while (next_amp != std::string::npos) {
+ std::string name_value = url_params.substr(0,next_amp);
+ url_params = url_params.substr(next_amp+1);
+ next_amp = url_params.find("&");
+
+ std::string::size_type pos_equal = name_value.find("=");
+
+ std::string nam = name_value.substr(0,pos_equal);
+ std::string val = name_value.substr(pos_equal+1);
+
+ std::string::size_type pos_plus;
+ while ( (pos_plus = val.find("+")) != std::string::npos ) {
+ val.replace(pos_plus, 1, " ");
+ }
+
+ // Replacing %xy notation
+ std::string::size_type pos_hex = 0;
+ while ( (pos_hex = val.find("%", pos_hex)) != std::string::npos ) {
+ std::stringstream h;
+ h << val.substr(pos_hex+1, 2);
+ h << std::hex;
+
+ int i;
+ h>>i;
+
+ std::stringstream f;
+ f << static_cast<char>(i);
+ std::string s;
+ f >> s;
+
+ val.replace(pos_hex, 3, s);
+ pos_hex ++;
+ }
+
+ params.insert(std::map<std::string,std::string>::value_type(nam, val));
+ }
+ }
+ else {
+ path = get_req;
+ }
+}
+
+void SplitUrl(std::string const& url, std::string& protocol, std::string& server, std::string& path) {
+ TraceFunc("SplitUrl");
+ RemoveProtocolFromUrl(url, protocol, server);
+
+ if (protocol == "http") {
+ std::string::size_type pos_slash = server.find("/");
+
+ if (pos_slash != std::string::npos) {
+ Trace("slash found");
+ path = server.substr(pos_slash);
+ server = server.substr(0, pos_slash);
+ }
+ else {
+ Trace("slash not found");
+ path = "/";
+ }
+ }
+ else if (protocol == "file") {
+ path = ReplaceInStr(server, "\\", "/");
+ server = "";
+ }
+ else {
+ std::cerr << "unknown protocol in SplitUrl: '" << protocol << "'" << std::endl;
+ }
+}
diff --git a/WebServer/WebServer.cpp b/WebServer/WebServer.cpp
index 8be690bd1..089be4352 100644
--- a/WebServer/WebServer.cpp
+++ b/WebServer/WebServer.cpp
@@ -1,497 +1,497 @@
-/*
- WebServer.cpp
-
- Copyright (C) 2003-2007 René Nyffenegger
-
- This source code is provided 'as-is', without any express or implied
- warranty. In no event will the author be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this source code must not be misrepresented; you must not
- claim that you wrote the original source code. If you use this source code
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original source code.
-
- 3. This notice may not be removed or altered from any source distribution.
-
- René Nyffenegger rene.nyffenegger@adp-gmbh.ch
-
- Thanks to Tom Lynn who pointed out an error in this source code.
-*/
-
-/*
- Note on point 2:
- THIS IS NOT THE ORIGINAL SOURCE1!!1!!!~!!~`1ONE!!`1
-*/
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include <ctime>
-#ifdef _WIN32
- #include <process.h>
-#endif
-#include <iostream>
-#include <sstream>
-
-
-#include "WebServer.h"
-#include "cEvents.h"
-#include "Socket.h"
-#include "UrlHelper.h"
-#include "base64.h"
-
-
-
-
-
-webserver::request_func webserver::request_func_ = NULL;
-
-
-
-
-
-static std::string EatLine( std::string& a_String )
-{
- std::string RetVal = "";
- unsigned int StringSize = a_String.size();
- const char* c = a_String.c_str();
-
- for( unsigned int i = 0; i < StringSize; ++i, ++c)
- {
- if( *c == '\n' )
- {
- RetVal += *c;
-// ++i; ++c;
-// if( i < StringSize )
-// {
-// if( *c == '\r' )
-// {
-// RetVal += *c;
-// }
-// }
- break;
- }
- RetVal += *c;
- }
- a_String = a_String.substr( RetVal.size() );
- return RetVal;
-}
-
-
-
-
-
-// Turns
-// "blabla my string with \"quotes\"!"
-// into
-// blabla my string with "quotes"!
-static std::string GetQuotedString( const std::string& a_String )
-{
- std::string RetVal;
-
- bool bGotFirstQuote = false;
- bool bIgnoreNext = false;
- unsigned int StrLen = a_String.size();
- for( unsigned int i = 0; i < StrLen; ++i )
- {
- if( bIgnoreNext == false )
- {
- if( a_String[i] == '\"' )
- {
- if( bGotFirstQuote == false )
- {
- bGotFirstQuote = true;
- }
- else
- {
- break;
- }
- continue;
- }
- else if( a_String[i] == '\\' ) // Escape character
- {
- bIgnoreNext = true;
- continue;
- }
- }
- RetVal.push_back( a_String[i] );
- bIgnoreNext = false;
- }
-
- return RetVal;
-}
-
-
-
-
-
-void ParseMultipartFormData( webserver::http_request& req, Socket* s)
-{
- static const std::string multipart_form_data = "multipart/form-data";
- if(req.content_type_.substr(0, multipart_form_data.size()) == multipart_form_data) // Difficult data... :(
- {
- AStringVector ContentTypeData = StringSplit( req.content_type_, "; " );
-
- std::string boundary;
- // Find boundary
- for( unsigned int i = 0; i < ContentTypeData.size(); ++i )
- {
- static const std::string boundary_ = "boundary=";
- if( ContentTypeData[i].substr(0, boundary_.size()) == boundary_ ) // Found boundary
- {
- boundary = ContentTypeData[i].substr( boundary_.size() );
- }
- }
-
- //LOGINFO("Boundary: %s", boundary.c_str() );
- std::string boundary_start = "--" + boundary;
- std::string boundary_end = boundary_start + "--";
-
- std::string Content = s->ReceiveBytes( req.content_length_ );
-
- //printf("Total content: \n%s\n", Content.c_str() );
-
- // Should start with boundary!
- std::string line = EatLine( Content );
- if( line.substr(0, boundary_start.size() ) != boundary_start )
- {
- // Something was wrong! :(
- Content.clear();
- }
-
- while( !Content.empty() )
- {
- webserver::formdata FormData;
-
- static const std::string content_disposition = "Content-Disposition: ";
- static const std::string content_type = "Content-Type: ";
-
- std::string f_disposition;
-
- while( 1 )
- {
- std::string line = EatLine( Content );
- if( line.empty() )
- break;
-
- unsigned int pos_cr_lf = line.find_first_of("\x0a\x0d");
- if (pos_cr_lf == 0) break; // Empty line, indicates end of mime thingy
-
- if( line.substr(0, content_disposition.size() ) == content_disposition )
- {
- f_disposition = line.substr(content_disposition.size());
- LOGINFO("Disposition: %s", f_disposition.c_str() );
- }
- else if( line.substr(0, content_type.size() ) == content_type )
- {
- FormData.content_type_ = line.substr(content_type.size());
- }
-
- //LOGINFO("Got line: '%s'", line.c_str() );
- }
-
- // Check if we got the proper headers
- if( !f_disposition.empty() )
- {
- static const std::string disp_name = "name=";
- static const std::string disp_filename = "filename=";
-
- // Parse the disposition
- AStringVector DispositionData = StringSplit( f_disposition, "; " );
- for( unsigned int i = 0; i < DispositionData.size(); ++i )
- {
- if( DispositionData[i].substr(0, disp_name.size()) == disp_name )
- {
- FormData.name_ = GetQuotedString( DispositionData[i].substr(disp_name.size()) );
- }
- else if( DispositionData[i].substr(0, disp_filename.size()) == disp_filename )
- {
- FormData.filename_ = GetQuotedString( DispositionData[i].substr(disp_filename.size()) );
- }
- }
-
- std::string ContentValue;
- // Parse until boundary_end is found
- while( 1 )
- {
- std::string line = EatLine( Content );
- if( line.empty() )
- break;
-
- if( line.substr(0, boundary_end.size() ) == boundary_end )
- {
- break;
- }
- else if( line.substr(0, boundary_start.size() ) == boundary_start )
- {
- break;
- }
- ContentValue.append( line.c_str(), line.size() );
- }
-
-
- FormData.value_ = ContentValue;
- }
-
- req.multipart_formdata_.push_back( FormData );
- }
- }
-}
-
-
-
-
-
-#ifdef _WIN32
-unsigned webserver::Request(void* ptr_s)
-#else
-void* webserver::Request(void* ptr_s)
-#endif
-{
- Socket* s = (reinterpret_cast<Socket*>(ptr_s));
-
- std::string line = s->ReceiveLine();
- if (line.empty())
- {
- s->Close();
- delete s;
- return 0;
- }
-
- http_request req;
- std::string path;
- std::map<std::string, std::string> params;
- size_t posStartPath = 0;
-
- if (line.find("GET") == 0)
- {
- req.method_="GET";
- posStartPath = line.find_first_not_of(" ",3);
- }
- else if (line.find("POST") == 0)
- {
- req.method_="POST";
- posStartPath = line.find_first_not_of(" ",4);
- }
-
- SplitGetReq(line.substr(posStartPath), path, params);
-
- req.status_ = "202 OK";
- req.s_ = s;
- req.path_ = path;
- req.params_ = params;
-
- static const std::string authorization = "Authorization: Basic ";
- static const std::string accept = "Accept: " ;
- static const std::string accept_language = "Accept-Language: " ;
- static const std::string accept_encoding = "Accept-Encoding: " ;
- static const std::string user_agent = "User-Agent: " ;
- static const std::string content_length = "Content-Length: " ;
- static const std::string content_type = "Content-Type: " ;
-
- while(1)
- {
- line=s->ReceiveLine();
- if (line.empty())
- {
- break;
- }
-
- unsigned int pos_cr_lf = line.find_first_of("\x0a\x0d");
- if (pos_cr_lf == 0) break;
-
- line = line.substr(0,pos_cr_lf);
-
- if (line.substr(0, authorization.size()) == authorization)
- {
- req.authentication_given_ = true;
- std::string encoded = line.substr(authorization.size());
- std::string decoded = base64_decode(encoded);
-
- unsigned int pos_colon = decoded.find(":");
-
- req.username_ = decoded.substr(0, pos_colon);
- req.password_ = decoded.substr(pos_colon+1 );
- }
- else if (line.substr(0, accept.size()) == accept)
- {
- req.accept_ = line.substr(accept.size());
- }
- else if (line.substr(0, accept_language.size()) == accept_language)
- {
- req.accept_language_ = line.substr(accept_language.size());
- }
- else if (line.substr(0, accept_encoding.size()) == accept_encoding)
- {
- req.accept_encoding_ = line.substr(accept_encoding.size());
- }
- else if (line.substr(0, user_agent.size()) == user_agent)
- {
- req.user_agent_ = line.substr(user_agent.size());
- }
- else if (line.substr(0, content_length.size()) == content_length)
- {
- req.content_length_ = atoi( line.substr(content_length.size()).c_str() );
- }
- else if (line.substr(0, content_type.size()) == content_type)
- {
- req.content_type_ = line.substr(content_type.size());
- }
- }
-
- if( (req.method_.compare("POST") == 0) && (req.content_length_ > 0) )
- {
- // The only content type we can parse at the moment, the default HTML post data
- if( req.content_type_.compare( "application/x-www-form-urlencoded" ) == 0 )
- {
- std::string Content = s->ReceiveBytes( req.content_length_ );
- Content.insert( 0, "/ ?" ); // Little hack, inserts dummy URL so that SplitGetReq() can work with this content
-
- std::string dummy;
- std::map<std::string, std::string> post_params;
- SplitGetReq(Content, dummy, post_params);
-
- req.params_post_ = post_params;
- }
- else
- {
- ParseMultipartFormData( req, s );
- }
- }
-
- request_func_(&req);
-
- std::stringstream str_str;
- str_str << req.answer_.size();
-
- time_t ltime;
- time(&ltime);
- tm* gmt= gmtime(&ltime);
-
-#ifdef _WIN32
- static std::string const serverName = "MCServerWebAdmin (Windows)";
-#elif __APPLE__
- static std::string const serverName = "MCServerWebAdmin (MacOSX)";
-#else
- static std::string const serverName = "MCServerWebAdmin (Linux)";
-#endif
-
-
- char* asctime_remove_nl = std::asctime(gmt);
- asctime_remove_nl[24] = 0;
-
- s->SendBytes("HTTP/1.1 ");
-
- if (! req.auth_realm_.empty() )
- {
- s->SendLine("401 Unauthorized");
- s->SendBytes("WWW-Authenticate: Basic Realm=\"");
- s->SendBytes(req.auth_realm_);
- s->SendLine("\"");
- }
- else
- {
- s->SendLine(req.status_);
- }
- s->SendLine(std::string("Date: ") + asctime_remove_nl + " GMT");
- s->SendLine(std::string("Server: ") +serverName);
- s->SendLine("Connection: close");
- s->SendLine("Content-Type: text/html; charset=ISO-8859-1");
- s->SendLine("Content-Length: " + str_str.str());
- s->SendLine("");
- s->SendLine(req.answer_);
-
- s->Close( true ); // true = wait for all data to be sent before closing
- delete s;
-
-
- return 0;
-}
-
-
-
-
-
-void webserver::Stop()
-{
- m_bStop = true;
- m_Socket->Close();
- m_Events->Wait();
-}
-
-
-
-
-
-bool webserver::Begin()
-{
- if (!m_Socket->IsValid())
- {
- LOGINFO("WebAdmin: The server socket is invalid. Terminating WebAdmin.");
- return false;
- }
- m_bStop = false;
- while ( !m_bStop )
- {
- Socket * ptr_s = m_Socket->Accept();
- if (m_bStop)
- {
- if (ptr_s != 0)
- {
- ptr_s->Close();
- delete ptr_s;
- }
- break;
- }
- if (ptr_s == NULL)
- {
- LOGINFO("WebAdmin: Accepted socket is NULL. Terminating WebAdmin to avoid busywait.");
- return false;
- }
-
- #ifdef _WIN32
- unsigned ret;
- HANDLE hHandle = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, Request, (void *)ptr_s, 0, &ret));
- CloseHandle(hHandle);
- #else
- // Mattes: TODO: this handle probably leaks!
- pthread_t * hHandle = new pthread_t;
- pthread_create( hHandle, NULL, Request, ptr_s);
- #endif
- }
- m_Events->Set();
- return true;
-}
-
-
-
-
-
-webserver::webserver(unsigned int port_to_listen, request_func r)
-{
- m_Socket = new SocketServer(port_to_listen, 1);
-
- request_func_ = r;
- m_Events = new cEvents();
-}
-
-
-
-
-
-webserver::~webserver()
-{
- delete m_Socket;
- delete m_Events;
-}
-
-
-
-
+/*
+ WebServer.cpp
+
+ Copyright (C) 2003-2007 René Nyffenegger
+
+ This source code is provided 'as-is', without any express or implied
+ warranty. In no event will the author be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this source code must not be misrepresented; you must not
+ claim that you wrote the original source code. If you use this source code
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original source code.
+
+ 3. This notice may not be removed or altered from any source distribution.
+
+ René Nyffenegger rene.nyffenegger@adp-gmbh.ch
+
+ Thanks to Tom Lynn who pointed out an error in this source code.
+*/
+
+/*
+ Note on point 2:
+ THIS IS NOT THE ORIGINAL SOURCE1!!1!!!~!!~`1ONE!!`1
+*/
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include <ctime>
+#ifdef _WIN32
+ #include <process.h>
+#endif
+#include <iostream>
+#include <sstream>
+
+
+#include "WebServer.h"
+#include "cEvents.h"
+#include "Socket.h"
+#include "UrlHelper.h"
+#include "base64.h"
+
+
+
+
+
+webserver::request_func webserver::request_func_ = NULL;
+
+
+
+
+
+static std::string EatLine( std::string& a_String )
+{
+ std::string RetVal = "";
+ unsigned int StringSize = a_String.size();
+ const char* c = a_String.c_str();
+
+ for( unsigned int i = 0; i < StringSize; ++i, ++c)
+ {
+ if( *c == '\n' )
+ {
+ RetVal += *c;
+// ++i; ++c;
+// if( i < StringSize )
+// {
+// if( *c == '\r' )
+// {
+// RetVal += *c;
+// }
+// }
+ break;
+ }
+ RetVal += *c;
+ }
+ a_String = a_String.substr( RetVal.size() );
+ return RetVal;
+}
+
+
+
+
+
+// Turns
+// "blabla my string with \"quotes\"!"
+// into
+// blabla my string with "quotes"!
+static std::string GetQuotedString( const std::string& a_String )
+{
+ std::string RetVal;
+
+ bool bGotFirstQuote = false;
+ bool bIgnoreNext = false;
+ unsigned int StrLen = a_String.size();
+ for( unsigned int i = 0; i < StrLen; ++i )
+ {
+ if( bIgnoreNext == false )
+ {
+ if( a_String[i] == '\"' )
+ {
+ if( bGotFirstQuote == false )
+ {
+ bGotFirstQuote = true;
+ }
+ else
+ {
+ break;
+ }
+ continue;
+ }
+ else if( a_String[i] == '\\' ) // Escape character
+ {
+ bIgnoreNext = true;
+ continue;
+ }
+ }
+ RetVal.push_back( a_String[i] );
+ bIgnoreNext = false;
+ }
+
+ return RetVal;
+}
+
+
+
+
+
+void ParseMultipartFormData( webserver::http_request& req, Socket* s)
+{
+ static const std::string multipart_form_data = "multipart/form-data";
+ if(req.content_type_.substr(0, multipart_form_data.size()) == multipart_form_data) // Difficult data... :(
+ {
+ AStringVector ContentTypeData = StringSplit( req.content_type_, "; " );
+
+ std::string boundary;
+ // Find boundary
+ for( unsigned int i = 0; i < ContentTypeData.size(); ++i )
+ {
+ static const std::string boundary_ = "boundary=";
+ if( ContentTypeData[i].substr(0, boundary_.size()) == boundary_ ) // Found boundary
+ {
+ boundary = ContentTypeData[i].substr( boundary_.size() );
+ }
+ }
+
+ //LOGINFO("Boundary: %s", boundary.c_str() );
+ std::string boundary_start = "--" + boundary;
+ std::string boundary_end = boundary_start + "--";
+
+ std::string Content = s->ReceiveBytes( req.content_length_ );
+
+ //printf("Total content: \n%s\n", Content.c_str() );
+
+ // Should start with boundary!
+ std::string line = EatLine( Content );
+ if( line.substr(0, boundary_start.size() ) != boundary_start )
+ {
+ // Something was wrong! :(
+ Content.clear();
+ }
+
+ while( !Content.empty() )
+ {
+ webserver::formdata FormData;
+
+ static const std::string content_disposition = "Content-Disposition: ";
+ static const std::string content_type = "Content-Type: ";
+
+ std::string f_disposition;
+
+ while( 1 )
+ {
+ std::string line = EatLine( Content );
+ if( line.empty() )
+ break;
+
+ unsigned int pos_cr_lf = line.find_first_of("\x0a\x0d");
+ if (pos_cr_lf == 0) break; // Empty line, indicates end of mime thingy
+
+ if( line.substr(0, content_disposition.size() ) == content_disposition )
+ {
+ f_disposition = line.substr(content_disposition.size());
+ LOGINFO("Disposition: %s", f_disposition.c_str() );
+ }
+ else if( line.substr(0, content_type.size() ) == content_type )
+ {
+ FormData.content_type_ = line.substr(content_type.size());
+ }
+
+ //LOGINFO("Got line: '%s'", line.c_str() );
+ }
+
+ // Check if we got the proper headers
+ if( !f_disposition.empty() )
+ {
+ static const std::string disp_name = "name=";
+ static const std::string disp_filename = "filename=";
+
+ // Parse the disposition
+ AStringVector DispositionData = StringSplit( f_disposition, "; " );
+ for( unsigned int i = 0; i < DispositionData.size(); ++i )
+ {
+ if( DispositionData[i].substr(0, disp_name.size()) == disp_name )
+ {
+ FormData.name_ = GetQuotedString( DispositionData[i].substr(disp_name.size()) );
+ }
+ else if( DispositionData[i].substr(0, disp_filename.size()) == disp_filename )
+ {
+ FormData.filename_ = GetQuotedString( DispositionData[i].substr(disp_filename.size()) );
+ }
+ }
+
+ std::string ContentValue;
+ // Parse until boundary_end is found
+ while( 1 )
+ {
+ std::string line = EatLine( Content );
+ if( line.empty() )
+ break;
+
+ if( line.substr(0, boundary_end.size() ) == boundary_end )
+ {
+ break;
+ }
+ else if( line.substr(0, boundary_start.size() ) == boundary_start )
+ {
+ break;
+ }
+ ContentValue.append( line.c_str(), line.size() );
+ }
+
+
+ FormData.value_ = ContentValue;
+ }
+
+ req.multipart_formdata_.push_back( FormData );
+ }
+ }
+}
+
+
+
+
+
+#ifdef _WIN32
+unsigned webserver::Request(void* ptr_s)
+#else
+void* webserver::Request(void* ptr_s)
+#endif
+{
+ Socket* s = (reinterpret_cast<Socket*>(ptr_s));
+
+ std::string line = s->ReceiveLine();
+ if (line.empty())
+ {
+ s->Close();
+ delete s;
+ return 0;
+ }
+
+ http_request req;
+ std::string path;
+ std::map<std::string, std::string> params;
+ size_t posStartPath = 0;
+
+ if (line.find("GET") == 0)
+ {
+ req.method_="GET";
+ posStartPath = line.find_first_not_of(" ",3);
+ }
+ else if (line.find("POST") == 0)
+ {
+ req.method_="POST";
+ posStartPath = line.find_first_not_of(" ",4);
+ }
+
+ SplitGetReq(line.substr(posStartPath), path, params);
+
+ req.status_ = "202 OK";
+ req.s_ = s;
+ req.path_ = path;
+ req.params_ = params;
+
+ static const std::string authorization = "Authorization: Basic ";
+ static const std::string accept = "Accept: " ;
+ static const std::string accept_language = "Accept-Language: " ;
+ static const std::string accept_encoding = "Accept-Encoding: " ;
+ static const std::string user_agent = "User-Agent: " ;
+ static const std::string content_length = "Content-Length: " ;
+ static const std::string content_type = "Content-Type: " ;
+
+ while(1)
+ {
+ line=s->ReceiveLine();
+ if (line.empty())
+ {
+ break;
+ }
+
+ unsigned int pos_cr_lf = line.find_first_of("\x0a\x0d");
+ if (pos_cr_lf == 0) break;
+
+ line = line.substr(0,pos_cr_lf);
+
+ if (line.substr(0, authorization.size()) == authorization)
+ {
+ req.authentication_given_ = true;
+ std::string encoded = line.substr(authorization.size());
+ std::string decoded = base64_decode(encoded);
+
+ unsigned int pos_colon = decoded.find(":");
+
+ req.username_ = decoded.substr(0, pos_colon);
+ req.password_ = decoded.substr(pos_colon+1 );
+ }
+ else if (line.substr(0, accept.size()) == accept)
+ {
+ req.accept_ = line.substr(accept.size());
+ }
+ else if (line.substr(0, accept_language.size()) == accept_language)
+ {
+ req.accept_language_ = line.substr(accept_language.size());
+ }
+ else if (line.substr(0, accept_encoding.size()) == accept_encoding)
+ {
+ req.accept_encoding_ = line.substr(accept_encoding.size());
+ }
+ else if (line.substr(0, user_agent.size()) == user_agent)
+ {
+ req.user_agent_ = line.substr(user_agent.size());
+ }
+ else if (line.substr(0, content_length.size()) == content_length)
+ {
+ req.content_length_ = atoi( line.substr(content_length.size()).c_str() );
+ }
+ else if (line.substr(0, content_type.size()) == content_type)
+ {
+ req.content_type_ = line.substr(content_type.size());
+ }
+ }
+
+ if( (req.method_.compare("POST") == 0) && (req.content_length_ > 0) )
+ {
+ // The only content type we can parse at the moment, the default HTML post data
+ if( req.content_type_.compare( "application/x-www-form-urlencoded" ) == 0 )
+ {
+ std::string Content = s->ReceiveBytes( req.content_length_ );
+ Content.insert( 0, "/ ?" ); // Little hack, inserts dummy URL so that SplitGetReq() can work with this content
+
+ std::string dummy;
+ std::map<std::string, std::string> post_params;
+ SplitGetReq(Content, dummy, post_params);
+
+ req.params_post_ = post_params;
+ }
+ else
+ {
+ ParseMultipartFormData( req, s );
+ }
+ }
+
+ request_func_(&req);
+
+ std::stringstream str_str;
+ str_str << req.answer_.size();
+
+ time_t ltime;
+ time(&ltime);
+ tm* gmt= gmtime(&ltime);
+
+#ifdef _WIN32
+ static std::string const serverName = "MCServerWebAdmin (Windows)";
+#elif __APPLE__
+ static std::string const serverName = "MCServerWebAdmin (MacOSX)";
+#else
+ static std::string const serverName = "MCServerWebAdmin (Linux)";
+#endif
+
+
+ char* asctime_remove_nl = std::asctime(gmt);
+ asctime_remove_nl[24] = 0;
+
+ s->SendBytes("HTTP/1.1 ");
+
+ if (! req.auth_realm_.empty() )
+ {
+ s->SendLine("401 Unauthorized");
+ s->SendBytes("WWW-Authenticate: Basic Realm=\"");
+ s->SendBytes(req.auth_realm_);
+ s->SendLine("\"");
+ }
+ else
+ {
+ s->SendLine(req.status_);
+ }
+ s->SendLine(std::string("Date: ") + asctime_remove_nl + " GMT");
+ s->SendLine(std::string("Server: ") +serverName);
+ s->SendLine("Connection: close");
+ s->SendLine("Content-Type: text/html; charset=ISO-8859-1");
+ s->SendLine("Content-Length: " + str_str.str());
+ s->SendLine("");
+ s->SendLine(req.answer_);
+
+ s->Close( true ); // true = wait for all data to be sent before closing
+ delete s;
+
+
+ return 0;
+}
+
+
+
+
+
+void webserver::Stop()
+{
+ m_bStop = true;
+ m_Socket->Close();
+ m_Events->Wait();
+}
+
+
+
+
+
+bool webserver::Begin()
+{
+ if (!m_Socket->IsValid())
+ {
+ LOGINFO("WebAdmin: The server socket is invalid. Terminating WebAdmin.");
+ return false;
+ }
+ m_bStop = false;
+ while ( !m_bStop )
+ {
+ Socket * ptr_s = m_Socket->Accept();
+ if (m_bStop)
+ {
+ if (ptr_s != 0)
+ {
+ ptr_s->Close();
+ delete ptr_s;
+ }
+ break;
+ }
+ if (ptr_s == NULL)
+ {
+ LOGINFO("WebAdmin: Accepted socket is NULL. Terminating WebAdmin to avoid busywait.");
+ return false;
+ }
+
+ #ifdef _WIN32
+ unsigned ret;
+ HANDLE hHandle = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, Request, (void *)ptr_s, 0, &ret));
+ CloseHandle(hHandle);
+ #else
+ // Mattes: TODO: this handle probably leaks!
+ pthread_t * hHandle = new pthread_t;
+ pthread_create( hHandle, NULL, Request, ptr_s);
+ #endif
+ }
+ m_Events->Set();
+ return true;
+}
+
+
+
+
+
+webserver::webserver(unsigned int port_to_listen, request_func r)
+{
+ m_Socket = new SocketServer(port_to_listen, 1);
+
+ request_func_ = r;
+ m_Events = new cEvents();
+}
+
+
+
+
+
+webserver::~webserver()
+{
+ delete m_Socket;
+ delete m_Events;
+}
+
+
+
+
diff --git a/WebServer/base64.cpp b/WebServer/base64.cpp
index 72cd7cd59..4c19b600b 100644
--- a/WebServer/base64.cpp
+++ b/WebServer/base64.cpp
@@ -1,99 +1,99 @@
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "base64.h"
-#include <iostream>
-
-static const std::string base64_chars =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/";
-
-
-static inline bool is_base64(unsigned char c) {
- return (isalnum(c) || (c == '+') || (c == '/'));
-}
-
-std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
- std::string ret;
- int i = 0;
- int j = 0;
- unsigned char char_array_3[3];
- unsigned char char_array_4[4];
-
- while (in_len--) {
- char_array_3[i++] = *(bytes_to_encode++);
- if (i == 3) {
- char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
- char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
- char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
- char_array_4[3] = char_array_3[2] & 0x3f;
-
- for(i = 0; (i <4) ; i++)
- ret += base64_chars[char_array_4[i]];
- i = 0;
- }
- }
-
- if (i)
- {
- for(j = i; j < 3; j++)
- char_array_3[j] = '\0';
-
- char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
- char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
- char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
- char_array_4[3] = char_array_3[2] & 0x3f;
-
- for (j = 0; (j < i + 1); j++)
- ret += base64_chars[char_array_4[j]];
-
- while((i++ < 3))
- ret += '=';
-
- }
-
- return ret;
-
-}
-
-std::string base64_decode(std::string const& encoded_string) {
- int in_len = encoded_string.size();
- int i = 0;
- int j = 0;
- int in_ = 0;
- unsigned char char_array_4[4], char_array_3[3];
- std::string ret;
-
- while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
- char_array_4[i++] = encoded_string[in_]; in_++;
- if (i ==4) {
- for (i = 0; i <4; i++)
- char_array_4[i] = base64_chars.find(char_array_4[i]);
-
- char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
- char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
- char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
-
- for (i = 0; (i < 3); i++)
- ret += char_array_3[i];
- i = 0;
- }
- }
-
- if (i) {
- for (j = i; j <4; j++)
- char_array_4[j] = 0;
-
- for (j = 0; j <4; j++)
- char_array_4[j] = base64_chars.find(char_array_4[j]);
-
- char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
- char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
- char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
-
- for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
- }
-
- return ret;
-}
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "base64.h"
+#include <iostream>
+
+static const std::string base64_chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+
+static inline bool is_base64(unsigned char c) {
+ return (isalnum(c) || (c == '+') || (c == '/'));
+}
+
+std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
+ std::string ret;
+ int i = 0;
+ int j = 0;
+ unsigned char char_array_3[3];
+ unsigned char char_array_4[4];
+
+ while (in_len--) {
+ char_array_3[i++] = *(bytes_to_encode++);
+ if (i == 3) {
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+
+ for(i = 0; (i <4) ; i++)
+ ret += base64_chars[char_array_4[i]];
+ i = 0;
+ }
+ }
+
+ if (i)
+ {
+ for(j = i; j < 3; j++)
+ char_array_3[j] = '\0';
+
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+
+ for (j = 0; (j < i + 1); j++)
+ ret += base64_chars[char_array_4[j]];
+
+ while((i++ < 3))
+ ret += '=';
+
+ }
+
+ return ret;
+
+}
+
+std::string base64_decode(std::string const& encoded_string) {
+ int in_len = encoded_string.size();
+ int i = 0;
+ int j = 0;
+ int in_ = 0;
+ unsigned char char_array_4[4], char_array_3[3];
+ std::string ret;
+
+ while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
+ char_array_4[i++] = encoded_string[in_]; in_++;
+ if (i ==4) {
+ for (i = 0; i <4; i++)
+ char_array_4[i] = base64_chars.find(char_array_4[i]);
+
+ char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+ char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+ char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+ for (i = 0; (i < 3); i++)
+ ret += char_array_3[i];
+ i = 0;
+ }
+ }
+
+ if (i) {
+ for (j = i; j <4; j++)
+ char_array_4[j] = 0;
+
+ for (j = 0; j <4; j++)
+ char_array_4[j] = base64_chars.find(char_array_4[j]);
+
+ char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+ char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+ char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+ for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
+ }
+
+ return ret;
+}
diff --git a/WebServer/cEvents.cpp b/WebServer/cEvents.cpp
index 4c9fa8775..a00a0e817 100644
--- a/WebServer/cEvents.cpp
+++ b/WebServer/cEvents.cpp
@@ -1,125 +1,125 @@
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "cEvents.h"
-
-
-
-
-
-cEvents::cEvents( unsigned int a_NumEvents /* = 1 */ )
- : m_NumEvents( a_NumEvents )
-#ifndef _WIN32
- , m_bNamed( false )
-#endif
-{
- if( m_NumEvents < 1 ) m_NumEvents = 1;
-
-#ifdef _WIN32
- m_Handle = new HANDLE[ m_NumEvents ];
- for( unsigned int i = 0; i < m_NumEvents; i++)
- {
- ((HANDLE*)m_Handle)[i] = CreateEvent( 0, FALSE, FALSE, 0 );
- }
-#else
- m_Handle = new sem_t*[ m_NumEvents ];
- for( unsigned int i = 0; i < m_NumEvents; i++)
- {
-
- sem_t* & HandlePtr = ((sem_t**)m_Handle)[i];
- HandlePtr = new sem_t;
-
- if( sem_init( HandlePtr, 0, 0 ) )
- {
- LOG("WARNING cEvents: Could not create unnamed semaphore, fallback to named.");
- m_bNamed = true;
- delete HandlePtr; // named semaphores return their own address
-
- char c_Str[32];
- sprintf( c_Str, "cEvents%p", &HandlePtr );
- HandlePtr = sem_open( c_Str, O_CREAT, 777, 0 );
- if( HandlePtr == SEM_FAILED )
- LOG("ERROR: Could not create Event. (%i)", errno);
- else
- if( sem_unlink( c_Str ) != 0 )
- LOG("ERROR: Could not unlink cEvents. (%i)", errno);
- }
- }
-#endif
-}
-
-
-
-
-
-cEvents::~cEvents()
-{
-#ifdef _WIN32
- for( unsigned int i = 0; i < m_NumEvents; i++ )
- {
- CloseHandle( ((HANDLE*)m_Handle)[i] );
- }
- delete [] (HANDLE*)m_Handle;
-#else
- for( unsigned int i = 0; i < m_NumEvents; i++ )
- {
- if( m_bNamed )
- {
- sem_t* & HandlePtr = ((sem_t**)m_Handle)[i];
- char c_Str[32];
- sprintf( c_Str, "cEvents%p", &HandlePtr );
- // LOG("Closing event: %s", c_Str );
- // LOG("Sem ptr: %p", HandlePtr );
- if( sem_close( HandlePtr ) != 0 )
- {
- LOG("ERROR: Could not close cEvents. (%i)", errno);
- }
- }
- else
- {
- sem_destroy( ((sem_t**)m_Handle)[i] );
- delete ((sem_t**)m_Handle)[i];
- }
- }
- delete [] (sem_t**)m_Handle; m_Handle = 0;
-#endif
-}
-
-
-
-
-
-void cEvents::Wait()
-{
-#ifdef _WIN32
- WaitForMultipleObjects( m_NumEvents, (HANDLE*)m_Handle, true, INFINITE );
-#else
- for(unsigned int i = 0; i < m_NumEvents; i++)
- {
- if( sem_wait( ((sem_t**)m_Handle)[i] ) != 0 )
- {
- LOG("ERROR: Could not wait for cEvents. (%i)", errno);
- }
- }
-#endif
-}
-
-
-
-
-
-void cEvents::Set(unsigned int a_EventNum /* = 0 */)
-{
-#ifdef _WIN32
- SetEvent( ((HANDLE*)m_Handle)[a_EventNum] );
-#else
- if( sem_post( ((sem_t**)m_Handle)[a_EventNum] ) != 0 )
- {
- LOG("ERROR: Could not set cEvents. (%i)", errno);
- }
-#endif
-}
-
-
-
-
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "cEvents.h"
+
+
+
+
+
+cEvents::cEvents( unsigned int a_NumEvents /* = 1 */ )
+ : m_NumEvents( a_NumEvents )
+#ifndef _WIN32
+ , m_bNamed( false )
+#endif
+{
+ if( m_NumEvents < 1 ) m_NumEvents = 1;
+
+#ifdef _WIN32
+ m_Handle = new HANDLE[ m_NumEvents ];
+ for( unsigned int i = 0; i < m_NumEvents; i++)
+ {
+ ((HANDLE*)m_Handle)[i] = CreateEvent( 0, FALSE, FALSE, 0 );
+ }
+#else
+ m_Handle = new sem_t*[ m_NumEvents ];
+ for( unsigned int i = 0; i < m_NumEvents; i++)
+ {
+
+ sem_t* & HandlePtr = ((sem_t**)m_Handle)[i];
+ HandlePtr = new sem_t;
+
+ if( sem_init( HandlePtr, 0, 0 ) )
+ {
+ LOG("WARNING cEvents: Could not create unnamed semaphore, fallback to named.");
+ m_bNamed = true;
+ delete HandlePtr; // named semaphores return their own address
+
+ char c_Str[32];
+ sprintf( c_Str, "cEvents%p", &HandlePtr );
+ HandlePtr = sem_open( c_Str, O_CREAT, 777, 0 );
+ if( HandlePtr == SEM_FAILED )
+ LOG("ERROR: Could not create Event. (%i)", errno);
+ else
+ if( sem_unlink( c_Str ) != 0 )
+ LOG("ERROR: Could not unlink cEvents. (%i)", errno);
+ }
+ }
+#endif
+}
+
+
+
+
+
+cEvents::~cEvents()
+{
+#ifdef _WIN32
+ for( unsigned int i = 0; i < m_NumEvents; i++ )
+ {
+ CloseHandle( ((HANDLE*)m_Handle)[i] );
+ }
+ delete [] (HANDLE*)m_Handle;
+#else
+ for( unsigned int i = 0; i < m_NumEvents; i++ )
+ {
+ if( m_bNamed )
+ {
+ sem_t* & HandlePtr = ((sem_t**)m_Handle)[i];
+ char c_Str[32];
+ sprintf( c_Str, "cEvents%p", &HandlePtr );
+ // LOG("Closing event: %s", c_Str );
+ // LOG("Sem ptr: %p", HandlePtr );
+ if( sem_close( HandlePtr ) != 0 )
+ {
+ LOG("ERROR: Could not close cEvents. (%i)", errno);
+ }
+ }
+ else
+ {
+ sem_destroy( ((sem_t**)m_Handle)[i] );
+ delete ((sem_t**)m_Handle)[i];
+ }
+ }
+ delete [] (sem_t**)m_Handle; m_Handle = 0;
+#endif
+}
+
+
+
+
+
+void cEvents::Wait()
+{
+#ifdef _WIN32
+ WaitForMultipleObjects( m_NumEvents, (HANDLE*)m_Handle, true, INFINITE );
+#else
+ for(unsigned int i = 0; i < m_NumEvents; i++)
+ {
+ if( sem_wait( ((sem_t**)m_Handle)[i] ) != 0 )
+ {
+ LOG("ERROR: Could not wait for cEvents. (%i)", errno);
+ }
+ }
+#endif
+}
+
+
+
+
+
+void cEvents::Set(unsigned int a_EventNum /* = 0 */)
+{
+#ifdef _WIN32
+ SetEvent( ((HANDLE*)m_Handle)[a_EventNum] );
+#else
+ if( sem_post( ((sem_t**)m_Handle)[a_EventNum] ) != 0 )
+ {
+ LOG("ERROR: Could not set cEvents. (%i)", errno);
+ }
+#endif
+}
+
+
+
+