1
0

Source for additional projects

-jsoncpp
-lua
-tolua++
-WebServer
-zlib
-iniFile

git-svn-id: http://mc-server.googlecode.com/svn/trunk@4 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
faketruth 2011-10-03 19:25:04 +00:00
parent 386d58b586
commit aafef187ef
178 changed files with 65034 additions and 0 deletions

278
WebServer/Socket.cpp Normal file
View File

@ -0,0 +1,278 @@
/*
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 "../source/cMCLogger.h"
#include "Socket.h"
#include <iostream>
#ifndef _WIN32
#include <cstring>
#include <sys/time.h>
#else
#define MSG_NOSIGNAL (0)
#endif
#ifdef __MAC_NA
#define MSG_NOSIGNAL (0)
#endif
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_(0) {
Start();
// UDP: use SOCK_DGRAM instead of SOCK_STREAM
s_ = socket(AF_INET,SOCK_STREAM,0);
#ifdef _WIN32
if(s_ ==INVALID_SOCKET)
#else
if(s_ < 0)
#endif
{
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;
}
void Socket::Close() {
if( s_ )
{
closesocket(s_);
s_ = 0;
}
}
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;
}
}
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);
#ifdef _WIN32
if(s_ ==INVALID_SOCKET)
#else
if(s_ < 0)
#endif
{
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 new_sock = accept(s_, 0, 0);
#ifdef _WIN32
if(new_sock==INVALID_SOCKET || s_ == 0)
#else
if(new_sock < 0 || s_ == 0)
#endif
{
#ifdef _WIN32
int rc = WSAGetLastError();
if(rc==WSAEWOULDBLOCK) {
return 0; // non-blocking call, no request pending
}
else
#endif
{
//throw "Invalid Socket";
return 0;
}
}
Socket* r = new Socket(new_sock);
return r;
}
SocketClient::SocketClient(const std::string& host, int port) : Socket() {
std::string error;
hostent *he;
if ((he = gethostbyname(host.c_str())) == 0) {
#ifdef _WIN32
error = strerror(errno);
#endif
throw error;
}
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr = *((in_addr *)he->h_addr);
memset(&(addr.sin_zero), 0, 8);
if (::connect(s_, (sockaddr *) &addr, sizeof(sockaddr))) {
#ifdef _WIN32
error = strerror(WSAGetLastError());
#endif
throw error;
}
}
#ifndef _WIN32
struct timeval;
#endif
SocketSelect::SocketSelect(Socket const * const s1, Socket const * const s2, TypeSocket type) {
FD_ZERO(&fds_);
FD_SET(const_cast<Socket*>(s1)->s_,&fds_);
if(s2) {
FD_SET(const_cast<Socket*>(s2)->s_,&fds_);
}
#ifdef _WIN32
TIMEVAL *ptval = 0;
#else
timeval *ptval = 0;
#endif
if (select (0, &fds_, (fd_set*) 0, (fd_set*) 0, ptval) == SOCKET_ERROR)
throw "Error in select";
}
bool SocketSelect::Readable(Socket const* const s) {
if (FD_ISSET(s->s_,&fds_)) return true;
return false;
}

106
WebServer/Socket.h Normal file
View File

@ -0,0 +1,106 @@
/*
Socket.h
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
*/
#ifndef SOCKET_H
#define SOCKET_H
#include "../source/MCSocket.h"
#ifdef _WIN32
#include <winsock2.h>
#endif
#include <string>
enum TypeSocket {BlockingSocket, NonBlockingSocket};
class Socket {
public:
virtual ~Socket();
Socket(const Socket&);
Socket& operator=(Socket&);
std::string ReceiveLine();
std::string ReceiveBytes();
void Close();
// The parameter of SendLine is not a const reference
// because SendLine modifes the std::string passed.
void SendLine (std::string);
// The parameter of SendBytes is a const reference
// because SendBytes does not modify the std::string passed
// (in contrast to SendLine).
void SendBytes(const std::string&);
protected:
friend class SocketServer;
friend class SocketSelect;
Socket(SOCKET s);
Socket();
SOCKET s_;
int* refCounter_;
private:
static void Start();
static void End();
static int nofSockets_;
};
class SocketClient : public Socket {
public:
SocketClient(const std::string& host, int port);
};
class SocketServer : public Socket {
public:
SocketServer(int port, int connections, TypeSocket type=BlockingSocket);
Socket* Accept();
};
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/wsapiref_2tiq.asp
class SocketSelect {
public:
SocketSelect(Socket const * const s1, Socket const * const s2=NULL, TypeSocket type=BlockingSocket);
bool Readable(Socket const * const s);
private:
fd_set fds_;
};
#endif

61
WebServer/StdHelpers.cpp Normal file
View File

@ -0,0 +1,61 @@
/*
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 "StdHelpers.h"
#include <algorithm>
#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_);
}

65
WebServer/StdHelpers.h Normal file
View File

@ -0,0 +1,65 @@
/*
stdHelpers.h
Copyright (C) 2002-2005 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
*/
#ifndef STDHELPERS_H__
#define STDHELPERS_H__
#include <string>
#include <sstream>
std::string ReplaceInStr(const std::string& in, const std::string& search_for, const std::string& replace_with);
void ToUpper(std::string& s);
void ToLower(std::string& s);
template <class T>
T To(std::string const& s) {
T ret;
std::stringstream stream;
stream << s;
stream >> ret;
return ret;
}
template<class T>
std::string StringFrom(T const& t) {
std::string ret;
std::stringstream stream;
stream << t;
stream >> ret;
return ret;
}
#endif

113
WebServer/Tracer.h Normal file
View File

@ -0,0 +1,113 @@
/*
Tracer.h
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.
The most current version of Tracer.h can be found at
http://www.adp-gmbh.ch/cpp/common/Tracer.html
René Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/
/*
Note on point 2:
THIS IS NOT THE ORIGINAL SOURCE1!!1!!!~!!~`1ONE!!`1
*/
#ifndef TRACER_H__
#define TRACER_H__
#ifdef DO_TRACE
#include <string>
#include <sstream>
#include <windows.h>
#define StartTrace(x) TraceFunc_::StartTrace_(x)
#define Trace(x) dummy_____for_trace_func______.Trace_(x)
#define Trace2(x,y) dummy_____for_trace_func______.Trace_(x,y)
#define TraceFunc(x) TraceFunc_ dummy_____for_trace_func______(x)
#define TraceFunc2(x,y) TraceFunc_ dummy_____for_trace_func______(x,y)
class TraceFunc_ {
std::string func_name_;
public:
/*
Calling TraceFunc_ indents the output until the enclosing scope ( {...} )
is left.
*/
TraceFunc_(std::string const&);
TraceFunc_(std::string const&, std::string const& something);
~TraceFunc_();
/*
Creates the trace output file named by filename.
Must be called before any other tracing function.
Use the StartTrace macro for it.
*/
static void StartTrace_(std::string const& filename);
template <class T>
void Trace_(T const& t) {
DWORD d;
std::string indent_s;
std::stringstream s;
s << t;
for (int i=0; i< indent; i++) indent_s += " ";
::WriteFile(trace_file_,indent_s.c_str(), indent_s.size(), &d, 0);
::WriteFile(trace_file_, s.str().c_str(), s.str().size() ,&d, 0);
::WriteFile(trace_file_,"\x0a",1,&d,0);
}
template <class T, class U>
void Trace_(T const& t, U const& u) {
std::string indent_s;
std::stringstream s;
s << t;
s << u;
Trace_(s.str());
}
static int indent;
/* trace_file_ is a HANDLE for the file in which the traced output goes.
The file is opened (that is, created) by calling StartTrace_.
Better yet, use the StartTrace macro
to create the file.
*/
static HANDLE trace_file_;
};
#else
#define StartTrace(x)
#define Trace(x)
#define Trace2(x,y)
#define TraceFunc(x)
#define TraceFunc2(x,y)
#endif
#endif // TRACER_H__

167
WebServer/UrlHelper.cpp Normal file
View File

@ -0,0 +1,167 @@
/*
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 "UrlHelper.h"
#include "Tracer.h"
#include "StdHelpers.h"
#ifdef _WIN32
#include <windows.h>
#endif
#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;
}
}

42
WebServer/UrlHelper.h Normal file
View File

@ -0,0 +1,42 @@
/*
UrlHelper.h
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
*/
#ifndef __URL_HELPER_H__
#define __URL_HELPER_H__
#include <string>
#include <map>
void SplitUrl (std::string const& url, std::string& protocol, std::string& server, std::string& path);
bool RemoveProtocolFromUrl(std::string const& url, std::string& protocol, std::string& rest);
void SplitGetReq (std::string et_req, std::string& path, std::map<std::string, std::string>& params);
#endif

226
WebServer/WebServer.cpp Normal file
View File

@ -0,0 +1,226 @@
/*
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 <ctime>
#ifdef _WIN32
#include <process.h>
#endif
#include <iostream>
#include <string>
#include <map>
#include <sstream>
#include "WebServer.h"
#include "Socket.h"
#include "UrlHelper.h"
#include "base64.h"
#include "cEvent.h"
webserver::request_func webserver::request_func_=0;
#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;
if (line.find("GET") == 0) {
req.method_="GET";
}
else if (line.find("POST") == 0) {
req.method_="POST";
}
std::string path;
std::map<std::string, std::string> params;
size_t posStartPath = line.find_first_not_of(" ",3);
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: " ;
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());
}
}
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();
delete s;
return 0;
}
void webserver::Stop()
{
m_bStop = true;
m_Socket->Close();
m_Event->Wait();
}
void webserver::Begin()
{
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;
}
// unused variable 'ret'
//_beginthreadex(0,0,Request,(void*) ptr_s,0,&ret);
// Thanks to Frank M. Hoffmann for fixing a HANDLE leak
#ifdef _WIN32
unsigned ret;
HANDLE hHandle = reinterpret_cast<HANDLE>(_beginthreadex(0,0,Request,(void*) ptr_s,0,&ret));
CloseHandle(hHandle);
#else
pthread_t* hHandle = new pthread_t;
pthread_create( hHandle, NULL, Request, ptr_s);
#endif
}
m_Event->Set();
}
webserver::webserver(unsigned int port_to_listen, request_func r) {
m_Socket = new SocketServer(port_to_listen,1);
request_func_ = r;
m_Event = new cEvent();
}
webserver::~webserver()
{
delete m_Socket;
delete m_Event;
}

95
WebServer/WebServer.h Normal file
View File

@ -0,0 +1,95 @@
/*
WebServer.h
Copyright (C) 2003-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 <string>
#include <map>
class cEvent;
class Socket;
class SocketServer;
class webserver {
public:
struct http_request {
http_request()
: s_( 0 )
, authentication_given_(false)
{}
Socket* s_;
std::string method_;
std::string path_;
std::map<std::string, std::string> params_;
std::string accept_;
std::string accept_language_;
std::string accept_encoding_;
std::string user_agent_;
/* status_: used to transmit server's error status, such as
o 202 OK
o 404 Not Found
and so on */
std::string status_;
/* auth_realm_: allows to set the basic realm for an authentication,
no need to additionally set status_ if set */
std::string auth_realm_;
std::string answer_;
/* authentication_given_ is true when the user has entered a username and password.
These can then be read from username_ and password_ */
bool authentication_given_;
std::string username_;
std::string password_;
};
typedef void (*request_func) (http_request*);
webserver(unsigned int port_to_listen, request_func);
~webserver();
void Begin();
void Stop();
private:
bool m_bStop;
#ifdef _WIN32
static unsigned __stdcall Request(void*);
#else
static void* Request(void*);
#endif
static request_func request_func_;
cEvent* m_Event;
SocketServer* m_Socket;
};

96
WebServer/base64.cpp Normal file
View File

@ -0,0 +1,96 @@
#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;
}

4
WebServer/base64.h Normal file
View File

@ -0,0 +1,4 @@
#include <string>
std::string base64_encode(unsigned char const* , unsigned int len);
std::string base64_decode(std::string const& s);

112
WebServer/cEvent.cpp Normal file
View File

@ -0,0 +1,112 @@
#include "cEvent.h"
#include "../source/cMCLogger.h"
#ifdef _WIN32
#include <Windows.h>
#else
#include <semaphore.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h> // sprintf()
#endif
cEvent::cEvent( 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 cEvent: 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, "cEvent%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 cEvent. (%i)", errno);
}
}
#endif
}
cEvent::~cEvent()
{
#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, "cEvent%p", &HandlePtr );
// LOG("Closing event: %s", c_Str );
// LOG("Sem ptr: %p", HandlePtr );
if( sem_close( HandlePtr ) != 0 )
{
LOG("ERROR: Could not close cEvent. (%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 cEvent::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 cEvent. (%i)", errno);
}
}
#endif
}
void cEvent::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 cEvent. (%i)", errno);
}
#endif
}

18
WebServer/cEvent.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
class cEvent
{
public:
cEvent( unsigned int a_NumEvents = 1 );
~cEvent();
void Wait();
void Set(unsigned int a_EventNum = 0);
private:
unsigned int m_NumEvents;
void* m_Handle; // HANDLE[] pointer
#ifndef _WIN32
bool m_bNamed;
#endif
};

507
iniFile/iniFile.cpp Normal file
View File

@ -0,0 +1,507 @@
// IniFile.cpp: Implementation of the CIniFile class.
// Written by: Adam Clauss
// Email: cabadam@houston.rr.com
// You may use this class/code as you wish in your programs. Feel free to distribute it, and
// email suggested changes to me.
//
// Rewritten by: Shane Hill
// Date: 21/08/2001
// Email: Shane.Hill@dsto.defence.gov.au
// Reason: Remove dependancy on MFC. Code should compile on any
// platform.
//////////////////////////////////////////////////////////////////////
/*
!! MODIFIED BY FAKETRUTH !!
*/
// C++ Includes
#include <iostream>
#include <fstream>
#include <strstream>
using namespace std;
// C Includes
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
// Local Includes
#include "iniFile.h"
#if defined(WIN32)
#define iniEOL endl
#else
#define iniEOL '\r' << endl
#endif
#ifndef _WIN32
#define sprintf_s(buffer, buffer_size, stringbuffer, ...) (sprintf(buffer, stringbuffer, __VA_ARGS__))
#define vsprintf_s(buffer, stringbuffer, ...) (vsprintf(buffer, stringbuffer, __VA_ARGS__))
#define sscanf_s(buffer, stringbuffer, ...) (sscanf(buffer, stringbuffer, __VA_ARGS__))
#endif
cIniFile::cIniFile( const string iniPath)
{
Path( iniPath);
caseInsensitive = true;
}
bool cIniFile::ReadFile()
{
// Normally you would use ifstream, but the SGI CC compiler has
// a few bugs with ifstream. So ... fstream used.
fstream f;