📄 webserver.cpp
字号:
//// This file is part of the aMule Project.//// Copyright (c) 2003-2008 Kry ( elkry@sourceforge.net / http://www.amule.org )// Copyright (c) 2003-2008 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//#include <cmath> // Needed for cos, M_PI#include <string> // Do_not_auto_remove (g++-4.0.1)#include <wx/datetime.h>//-------------------------------------------------------------------#include <wx/tokenzr.h> // for wxTokenizer#include <wx/wfstream.h>#include <ec/cpp/ECFileConfig.h> // Needed for CECFileConfig#include <ec/cpp/ECSpecialTags.h>#include <common/MD5Sum.h>#include <common/Format.h> // Needed for CFormat//-------------------------------------------------------------------#include "WebSocket.h" // Needed for StopSockets()#include "Color.h" // Needed for COLORREF and RGB()#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("&")); str.Replace(wxT("<"),wxT("<")); str.Replace(wxT(">"),wxT(">")); str.Replace(wxT("\""),wxT(""")); 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); m_dec_str[i] = wxString::Format(wxT("%c"), i); }}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]); } size_t n = str.Len(); std::vector<char> buffer(n + 1); for (size_t i = 0; i < n; ++i) { buffer[i] = str[i]; } buffer[n] = 0; // Mark the end of the string str = UTF82unicode(&buffer[0]);}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; }}BEGIN_EVENT_TABLE(CWebServerBase, wxEvtHandler) EVT_SOCKET(ID_WEBLISTENSOCKET_EVENT, CWebServerBase::OnWebSocketServerEvent) EVT_SOCKET(ID_WEBCLIENTSOCKET_ENENT, CWebServerBase::OnWebSocketEvent)END_EVENT_TABLE()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; // // 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 m_upnpEnabled = webInterface->m_UPnPWebServerEnabled; m_upnpTCPPort = webInterface->m_UPnPTCPPort;}//sends output to web interfacevoid CWebServerBase::Print(const wxString &s){ webInterface->Show(s);}void CWebServerBase::StartServer(){#ifdef ENABLE_UPNP if (m_upnpEnabled) { m_upnpMappings.resize(1); m_upnpMappings[0] = CUPnPPortMapping( webInterface->m_WebserverPort, "TCP", true, "aMule TCP Webserver Socket"); m_upnp = new CUPnPControlPoint(m_upnpTCPPort); m_upnp->AddPortMappings(m_upnpMappings); }#endif wxIPV4address addr; addr.AnyAddress(); addr.Service(webInterface->m_WebserverPort); m_webserver_socket = new wxSocketServer(addr, wxSOCKET_REUSEADDR); m_webserver_socket->SetEventHandler(*this, ID_WEBLISTENSOCKET_EVENT); m_webserver_socket->SetNotify(wxSOCKET_CONNECTION_FLAG); m_webserver_socket->Notify(true); if (!m_webserver_socket->Ok()) { delete m_webserver_socket; m_webserver_socket = 0; }}void CWebServerBase::StopServer(){ if ( m_webserver_socket ) { delete m_webserver_socket; }#ifdef ENABLE_UPNP if (m_upnpEnabled) { m_upnp->DeletePortMappings(m_upnpMappings); delete m_upnp; }#endif}void CWebServerBase::OnWebSocketServerEvent(wxSocketEvent& WXUNUSED(event)){ CWebSocket *client = new CWebSocket(this); if ( m_webserver_socket->AcceptWith(*client, false) ) { webInterface->Show(_("web client connection accepted\n")); } else { delete client; webInterface->Show(_("ERROR: can not accept web client connection\n")); }}void CWebServerBase::OnWebSocketEvent(wxSocketEvent& event){ CWebSocket *socket = dynamic_cast<CWebSocket *>(event.GetSocket()); wxCHECK_RET(socket, wxT("Socket event with a NULL socket!")); switch(event.GetSocketEvent()) { case wxSOCKET_LOST: socket->OnLost(); break; case wxSOCKET_INPUT: socket->OnInput(); break; case wxSOCKET_OUTPUT: socket->OnOutput(); break; case wxSOCKET_CONNECTION: break; default: wxFAIL; break; }}void CScriptWebServer::ProcessImgFileReq(ThreadData Data){ webInterface->DebugShow(wxT("**** imgrequest: ") + Data.sURL + wxT("\n")); wxMutexLocker lock(m_mutexChildren); 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.parsedURL.File()).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 (img && (session->m_loggedin || 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") ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -