webserver.cpp

来自「wxWidgets写的电驴」· C++ 代码 · 共 1,963 行 · 第 1/4 页

CPP
1,963
字号
//// This file is part of the aMule Project.//// Copyright (c) 2003-2006 Kry ( elkry@sourceforge.net / http://www.amule.org )// Copyright (c) 2003-2006 aMule Team ( admin@amule.org / http://www.amule.org )// Copyright (c) 2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )//// Any parts of this program derived from the xMule, lMule or eMule project,// or contributed by third-party developers are copyrighted by their// respective authors.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA//#ifdef HAVE_CONFIG_H	#include "config.h"		// Needed for VERSION#endif#include <cstdlib>#include <cstdio>#include <cstring>#include <cctype>#include <cstdlib>#include <cmath> // Needed for cos, M_PI#include <string>#include "WebServer.h"//-------------------------------------------------------------------#include <wx/arrimpl.cpp>	// this is a magic incantation which must be done!#include <wx/tokenzr.h>		// for wxTokenizer#include <wx/txtstrm.h>#include <wx/wfstream.h>#include <wx/filename.h>#include <ec/ECFileConfig.h>	// Needed for CECFileConfig#include <ec/ECSpecialTags.h>#include <ec/ECCodes.h>#include <common/MD5Sum.h>#include <common/Format.h>		// Needed for CFormat//-------------------------------------------------------------------#include "GetTickCount.h"	// Needed for GetTickCount#include "OtherStructs.h"	// Needed for TransferredData#include "OtherFunctions.h"	// Needed for atoll, ED2KFT_*#include "NetworkFunctions.h"	// Needed for StringIPtoUint32#include "Types.h"#include "WebSocket.h"		// Needed for StopSockets()#include "Color.h"		// Needed for COLORREF and RGB()#include "ArchSpecific.h"	// Needed for ENDIAN_NTOHL()#include "php_syntree.h"#include "php_core_lib.h"//-------------------------------------------------------------------inline void set_rgb_color_val(unsigned char *start, uint32 val, unsigned char mod){	unsigned char r = val, g = val >> 8, b = val >> 16;	start[0] = ( r > mod ) ? (r - mod) : 1;	start[1] = ( g > mod ) ? (g - mod) : 1;	start[2] = ( b > mod ) ? (b - mod) : 1;}wxString _SpecialChars(wxString str) {	str.Replace(wxT("&"),wxT("&amp;"));	str.Replace(wxT("<"),wxT("&lt;"));	str.Replace(wxT(">"),wxT("&gt;"));	str.Replace(wxT("\""),wxT("&quot;"));	return str;}uint8 GetHigherPrio(uint32 prio, bool autoprio){	if (autoprio) {		return PR_LOW;	} else {		switch (prio) {			case PR_LOW: return PR_NORMAL;			case PR_NORMAL: return PR_HIGH;			case PR_HIGH: return PR_AUTO;			case PR_AUTO: return PR_LOW;			default: return PR_AUTO;		}	}}uint8 GetHigherPrioShared(uint32 prio, bool autoprio){	if (autoprio) {		return PR_VERYLOW;	} else {		switch (prio) {			case PR_VERYLOW: return PR_LOW;			case PR_LOW: return PR_NORMAL;			case PR_NORMAL: return PR_HIGH;			case PR_HIGH: return PR_VERYHIGH;			case PR_VERYHIGH: return PR_POWERSHARE;			case PR_POWERSHARE: return PR_AUTO;			case PR_AUTO: return PR_VERYLOW;			default: return PR_AUTO;		}	}}uint8 GetLowerPrio(uint32 prio, bool autoprio){	if (autoprio) {		return PR_HIGH;	} else {		switch (prio) {			case PR_LOW: return PR_AUTO;			case PR_NORMAL: return PR_LOW;			case PR_HIGH: return PR_NORMAL;			case PR_AUTO: return PR_HIGH;			default: return PR_AUTO;		}	}}uint8 GetLowerPrioShared(uint32 prio, bool autoprio){	if (autoprio) {		return PR_POWERSHARE;	} else {		switch (prio) {			case PR_VERYLOW: return PR_AUTO;			case PR_LOW: return PR_VERYLOW;			case PR_NORMAL: return PR_LOW;			case PR_HIGH: return PR_NORMAL;			case PR_VERYHIGH: return PR_HIGH;			case PR_POWERSHARE: return PR_VERYHIGH;			case PR_AUTO: return PR_POWERSHARE;			default: return PR_AUTO;		}	}}/* * Url string decoder and parser */CUrlDecodeTable::CUrlDecodeTable(){	for (int i = 0 ; i < 256 ; i++) {		char fromReplace[4];		// decode URL		snprintf(fromReplace, sizeof(fromReplace), "%%%02x", i);		m_enc_l_str[i] = char2unicode(fromReplace);		snprintf(fromReplace, sizeof(fromReplace), "%%%02X", i);		m_enc_u_str[i] = char2unicode(fromReplace);		char toReplace[2] = {(char)i, 0};	// decode URL		m_dec_str[i] = char2unicode(toReplace);	}}void CUrlDecodeTable::DecodeString(wxString &str){	str.Replace(wxT("+"), wxT(" "));	for (int i = 0 ; i < 256 ; i++) {		str.Replace(m_enc_l_str[i], m_dec_str[i]);		str.Replace(m_enc_u_str[i], m_dec_str[i]);	}}CUrlDecodeTable*	CUrlDecodeTable::ms_instance;wxCriticalSection	CUrlDecodeTable::ms_instance_guard;CUrlDecodeTable* CUrlDecodeTable::GetInstance(){	wxCriticalSectionLocker lock(ms_instance_guard);	if (ms_instance == NULL) {		ms_instance = new CUrlDecodeTable();	}	return ms_instance;}CParsedUrl::CParsedUrl(const wxString &url){	if ( url.Find('/') != -1 ) {		m_path = url.BeforeFirst('/');		m_file = url.AfterFirst('/');	}	if ( url.Find('?') != -1 ) {		m_file.Truncate(m_file.Find('?'));				wxString params = url.AfterFirst('?');				wxStringTokenizer tkz(params, wxT("&"));		while ( tkz.HasMoreTokens() ) {	    	wxString param_val = tkz.GetNextToken();	    	wxString key = param_val.BeforeFirst('=');	    	wxString val = param_val.AfterFirst('=');	    	CUrlDecodeTable::GetInstance()->DecodeString(val);	    	if ( m_params.count(key) ) {	    		m_params[key] = m_params[key] + wxT("|") + val;	    	} else {	    		m_params[key] = val;	    	}		}    }}void CParsedUrl::ConvertParams(std::map<std::string, std::string> &dst){	for(std::map<wxString, wxString>::iterator i = m_params.begin(); i != m_params.end(); i++) {		std::string key(unicode2char(i->first)), value(unicode2char(i->second));		dst[key] = value;	}}CWebServerBase::CWebServerBase(CamulewebApp *webApp, const wxString& templateDir) :	m_ServersInfo(webApp), m_SharedFileInfo(webApp), m_DownloadFileInfo(webApp, &m_ImageLib),	m_UploadsInfo(webApp), m_SearchInfo(webApp), m_Stats(500, webApp),	m_ImageLib(templateDir){	webInterface = webApp;	m_mutexChildren = new wxMutex();		//	// Init stat graphs#ifdef WITH_LIBPNG	m_ImageLib.AddImage(new CDynStatisticImage(200, true, m_Stats.DownloadSpeed()),		wxT("/amule_stats_download.png"));	m_ImageLib.AddImage(new CDynStatisticImage(200, true, m_Stats.UploadSpeed()),		wxT("/amule_stats_upload.png"));	m_ImageLib.AddImage(new CDynStatisticImage(200, false, m_Stats.ConnCount()),		wxT("/amule_stats_conncount.png"));	m_ImageLib.AddImage(new CDynStatisticImage(200, false, m_Stats.KadCount()),		wxT("/amule_stats_kad.png"));#endif}//sends output to web interfacevoid CWebServerBase::Print(const wxString &s){	webInterface->Show(s);}//returns web server listening portlong CWebServerBase::GetWSPrefs(void){	CECPacket req(EC_OP_GET_PREFERENCES);	req.AddTag(CECTag(EC_TAG_SELECT_PREFS, (uint32)EC_PREFS_REMOTECONTROLS));	const CECPacket *reply = webInterface->SendRecvMsg_v2(&req);	if (!reply) {		return -1;	}	// we have selected only the webserver preferences	const CECTag *wsprefs = reply->GetTagByIndexSafe(0);	const CECTag *tag = wsprefs->GetTagByName(EC_TAG_WEBSERVER_PORT);	long int wsport = tag ? (long int)tag->GetInt16Data() : -1;	if (webInterface->m_LoadSettingsFromAmule) {		webInterface->m_AdminPass = wsprefs->GetTagByNameSafe(EC_TAG_PASSWD_HASH)->GetMD4Data();		const CECTag *webserverGuest = wsprefs->GetTagByName(EC_TAG_WEBSERVER_GUEST);		if (webserverGuest) {			webInterface->m_AllowGuest = true;			webInterface->m_GuestPass = webserverGuest->GetTagByNameSafe(EC_TAG_PASSWD_HASH)->GetMD4Data();		} else {			webInterface->m_AllowGuest = false;		}		// we only need to check the presence of this tag		webInterface->m_UseGzip = wsprefs->GetTagByName(EC_TAG_WEBSERVER_USEGZIP) != NULL;			const CECTag *webserverRefresh = wsprefs->GetTagByName(EC_TAG_WEBSERVER_REFRESH);		if (webserverRefresh) {			webInterface->m_PageRefresh = webserverRefresh->GetInt32Data();		} else {			webInterface->m_PageRefresh = 120;		}	}	delete reply;	return wsport;}void CScriptWebServer::ProcessImgFileReq(ThreadData Data){	webInterface->DebugShow(wxT("**** imgrequest: ") + Data.sURL + wxT("\n"));	const CSession* session = CheckLoggedin(Data);	// To prevent access to non-template images, we disallow use of paths in filenames.	wxString imgName = wxFileName::GetPathSeparator() + wxFileName(Data.sURL).GetFullName();	CAnyImage *img = m_ImageLib.GetImage(imgName);		// Only static images are available to visitors, in order to prevent	// information leakage, but still allowing images on the login page.	if (session->m_loggedin or dynamic_cast<CFileImage*>(img)) {		int img_size = 0;		unsigned char* img_data = img->RequestData(img_size);		// This unicode2char is ok.		Data.pSocket->SendContent(unicode2char(img->GetHTTP()), img_data, img_size);	} else if (not session->m_loggedin) {		webInterface->DebugShow(wxT("**** imgrequest: failed, not logged in\n"));		ProcessURL(Data);	} else {		webInterface->DebugShow(wxT("**** imgrequest: failed\n"));	}}// send EC request and discard outputvoid CWebServerBase::Send_Discard_V2_Request(CECPacket *request){	const CECPacket *reply = webInterface->SendRecvMsg_v2(request);	const CECTag *tag = NULL;	if (reply) {		if ( reply->GetOpCode() == EC_OP_STRINGS ) {			for(int i = 0; i < reply->GetTagCount(); ++i) {				if (	(tag = reply->GetTagByIndex(i)) &&					(tag->GetTagName() == EC_TAG_STRING)) {					webInterface->Show(tag->GetStringData());				}			}		} else if (reply->GetOpCode() == EC_OP_FAILED) {			if (	reply->GetTagCount() &&				(tag = reply->GetTagByIndex(0)) ) {				webInterface->Show(					CFormat(_("Request failed with the following error: %s.")) %					wxString(wxGetTranslation(tag->GetStringData())));			} else {				webInterface->Show(_("Request failed with an unknown error."));			}		}		delete reply;	}}//// Command interface//void CWebServerBase::Send_SharedFile_Cmd(wxString file_hash, wxString cmd, uint32 opt_arg){	CECPacket *ec_cmd = 0;	CMD4Hash fileHash;	wxCHECK2(fileHash.Decode(file_hash), /* Do nothing. */ );		CECTag hashtag(EC_TAG_KNOWNFILE, fileHash);	if (cmd == wxT("prio")) {		ec_cmd = new CECPacket(EC_OP_SHARED_SET_PRIO);		hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, (uint8)opt_arg));	} else if ( cmd == wxT("prioup") ) {		SharedFile *file = m_SharedFileInfo.GetByID(fileHash);		if ( file ) {			ec_cmd = new CECPacket(EC_OP_SHARED_SET_PRIO);			hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,				GetHigherPrioShared(file->nFilePriority, file->bFileAutoPriority)));		}	} else if ( cmd == wxT("priodown") ) {		SharedFile *file = m_SharedFileInfo.GetByID(fileHash);		if ( file ) {			ec_cmd = new CECPacket(EC_OP_SHARED_SET_PRIO);			hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,				GetLowerPrioShared(file->nFilePriority, file->bFileAutoPriority)));		}	}		if ( ec_cmd ) {		ec_cmd->AddTag(hashtag);		Send_Discard_V2_Request(ec_cmd);		delete ec_cmd;	}}void CWebServerBase::Send_ReloadSharedFile_Cmd(){	CECPacket ec_cmd(EC_OP_SHAREDFILES_RELOAD);	Send_Discard_V2_Request(&ec_cmd);}void CWebServerBase::Send_DownloadFile_Cmd(wxString file_hash, wxString cmd, uint32 opt_arg){	CECPacket *ec_cmd = 0;	CMD4Hash fileHash;	wxCHECK2(fileHash.Decode(file_hash), /* Do nothing. */ );		CECTag hashtag(EC_TAG_PARTFILE, fileHash);	if (cmd == wxT("pause")) {		ec_cmd = new CECPacket(EC_OP_PARTFILE_PAUSE);	} else if (cmd == wxT("resume")) {		ec_cmd = new CECPacket(EC_OP_PARTFILE_RESUME);	} else if (cmd == wxT("cancel")) {		ec_cmd = new CECPacket(EC_OP_PARTFILE_DELETE);	} else if (cmd == wxT("prio")) {		ec_cmd = new CECPacket(EC_OP_PARTFILE_PRIO_SET);		hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, (uint8)opt_arg));	} else if (cmd == wxT("prioup")) {		DownloadFile *file = m_DownloadFileInfo.GetByID(fileHash);		if ( file ) {			ec_cmd = new CECPacket(EC_OP_PARTFILE_PRIO_SET);			hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,				GetHigherPrio(file->lFilePrio, file->bFileAutoPriority)));		}	} else if (cmd == wxT("priodown")) {		DownloadFile *file = m_DownloadFileInfo.GetByID(fileHash);		if ( file ) {			ec_cmd = new CECPacket(EC_OP_PARTFILE_PRIO_SET);			hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,				GetLowerPrio(file->lFilePrio, file->bFileAutoPriority)));		}	}	if ( ec_cmd ) {		ec_cmd->AddTag(hashtag);		Send_Discard_V2_Request(ec_cmd);		delete ec_cmd;	}}void CWebServerBase::Send_DownloadSearchFile_Cmd(wxString file_hash, uint8 cat){	CMD4Hash fileHash;	wxCHECK2(fileHash.Decode(file_hash), /* Do nothing. */ );		CECPacket ec_cmd(EC_OP_DOWNLOAD_SEARCH_RESULT);	CECTag link_tag(EC_TAG_KNOWNFILE, fileHash);	link_tag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));	ec_cmd.AddTag(link_tag);	Send_Discard_V2_Request(&ec_cmd);}void CWebServerBase::Send_AddServer_Cmd(wxString addr, wxString port, wxString name){	CECPacket ec_cmd(EC_OP_SERVER_ADD);	addr.Trim();	port.Trim();		CECTag srv_tag(EC_TAG_SERVER, addr + wxT(":") + port);	srv_tag.AddTag(CECTag(EC_TAG_SERVER_ADDRESS, addr + wxT(":") + port));	srv_tag.AddTag(CECTag(EC_TAG_SERVER_NAME, name));		ec_cmd.AddTag(srv_tag);		Send_Discard_V2_Request(&ec_cmd);}void CWebServerBase::Send_Server_Cmd(uint32 ip, uint16 port, wxString cmd){	CECPacket *ec_cmd = 0;	if ( cmd == wxT("connect") ) {		ec_cmd = new CECPacket(EC_OP_SERVER_CONNECT);	} else if ( cmd == wxT("remove") ) {		ec_cmd = new CECPacket(EC_OP_SERVER_REMOVE);	} else if ( cmd == wxT("disconnect") ) {		ec_cmd = new CECPacket(EC_OP_SERVER_DISCONNECT);	}	if ( ec_cmd && ip ) {		ec_cmd->AddTag(CECTag(EC_TAG_SERVER, EC_IPv4_t(ip, port)));		Send_Discard_V2_Request(ec_cmd);		delete ec_cmd;	}}void CWebServerBase::Send_Search_Cmd(wxString search, wxString extention, wxString type,	EC_SEARCH_TYPE search_type, uint32 avail, uint32 min_size, uint32 max_size){	CECPacket search_req(EC_OP_SEARCH_START);	search_req.AddTag(CEC_Search_Tag (search, search_type,		type, extention, avail, min_size, max_size));	Send_Discard_V2_Request(&search_req);}bool CWebServerBase::Send_DownloadEd2k_Cmd(wxString link, uint8 cat){	CECPacket req(EC_OP_ED2K_LINK);	CECTag link_tag(EC_TAG_STRING, link);	link_tag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));	req.AddTag(link_tag);	const CECPacket *response = webInterface->SendRecvMsg_v2(&req);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?