📄 webserver.cpp
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net )
//
//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., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "stdafx.h"
#include "emule.h"
#include "OtherFunctions.h"
#include <zlib/zlib.h>
#include "SearchDlg.h"
#include "SearchParams.h"
#include "WebServer.h"
#include "ED2KLink.h"
#include "MD5Sum.h"
#include "SearchList.h"
#include <locale.h>
#include "HTRichEditCtrl.h"
#include "KademliaWnd.h"
#include "KadContactListCtrl.h"
#include "KadSearchListCtrl.h"
#include "UploadQueue.h"
#include "DownloadQueue.h"
#include "WebSocket.h"
#include "ServerList.h"
#include "SharedFileList.h"
#include "emuledlg.h"
#include "ServerWnd.h"
#include "Sockets.h"
#include "Server.h"
#include "TransferWnd.h"
#include "PartFile.h"
#include "UpDownClient.h"
#include "StatisticsDlg.h"
#include "Kademlia/Kademlia/Kademlia.h"
#include "Kademlia/Net/KademliaUDPListener.h"
#include "Exceptions.h"
#include "Opcodes.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define HTTPInit _T("Server: eMule\r\nConnection: close\r\nContent-Type: text/html\r\n")
#define HTTPInitGZ _T("Server: eMule\r\nConnection: close\r\nContent-Type: text/html\r\nContent-Encoding: gzip\r\n")
#define WEB_SERVER_TEMPLATES_VERSION 5
CWebServer::CWebServer(void)
{
m_Params.bShowUploadQueue = false;
m_Params.DownloadSort = DOWN_SORT_NAME;
m_Params.bDownloadSortReverse = false;
m_Params.ServerSort = SERVER_SORT_NAME;
m_Params.bServerSortReverse = false;
m_Params.SharedSort = SHARED_SORT_NAME;
m_Params.bSharedSortReverse = false;
m_Params.sLastModified=_T("");
m_Params.sETag=_T("");
m_iSearchSortby=3;
m_bSearchAsc=0;
m_bServerWorking = false;
}
void CWebServer::ReloadTemplates()
{
CString sPrevLocale(_tsetlocale(LC_TIME,NULL));
_tsetlocale(LC_TIME, _T("English"));
CTime t = GetCurrentTime();
m_Params.sLastModified = t.FormatGmt(_T("%a, %d %b %Y %H:%M:%S GMT"));
m_Params.sETag = MD5Sum(m_Params.sLastModified).GetHash();
_tsetlocale(LC_TIME, sPrevLocale);
CString sFile;
if (thePrefs.GetTemplate()==_T("") || thePrefs.GetTemplate().MakeLower()==_T("emule.tmpl"))
sFile= thePrefs.GetAppDir() + CString(_T("eMule.tmpl"));
else sFile=thePrefs.GetTemplate();
CStdioFile file;
if(file.Open(sFile, CFile::modeRead|CFile::typeText|CFile::shareDenyWrite))
{
CString sAll;
for(;;)
{
CString sLine;
if(!file.ReadString(sLine))
break;
sAll += sLine + _T("\n");
}
file.Close();
CString sVersion = _LoadTemplate(sAll,_T("TMPL_VERSION"));
long lVersion = _tstol(sVersion);
if(lVersion < WEB_SERVER_TEMPLATES_VERSION)
{
if(m_bServerWorking)
AddLogLine(true,GetResString(IDS_WS_ERR_LOADTEMPLATE),sFile);
}
else
{
m_Templates.sHeader = _LoadTemplate(sAll,_T("TMPL_HEADER_KAD"));
m_Templates.sHeaderMetaRefresh = _LoadTemplate(sAll,_T("TMPL_HEADER_META_REFRESH"));
m_Templates.sHeaderStylesheet = _LoadTemplate(sAll,_T("TMPL_HEADER_STYLESHEET"));
m_Templates.sFooter = _LoadTemplate(sAll,_T("TMPL_FOOTER"));
m_Templates.sServerList = _LoadTemplate(sAll,_T("TMPL_SERVER_LIST"));
m_Templates.sServerLine = _LoadTemplate(sAll,_T("TMPL_SERVER_LINE"));
m_Templates.sTransferImages = _LoadTemplate(sAll,_T("TMPL_TRANSFER_IMAGES"));
m_Templates.sTransferList = _LoadTemplate(sAll,_T("TMPL_TRANSFER_LIST"));
m_Templates.sTransferDownHeader = _LoadTemplate(sAll,_T("TMPL_TRANSFER_DOWN_HEADER"));
m_Templates.sTransferDownFooter = _LoadTemplate(sAll,_T("TMPL_TRANSFER_DOWN_FOOTER"));
m_Templates.sTransferDownLine = _LoadTemplate(sAll,_T("TMPL_TRANSFER_DOWN_LINE"));
m_Templates.sTransferDownLineGood = _LoadTemplate(sAll,_T("TMPL_TRANSFER_DOWN_LINE_GOOD"));
m_Templates.sTransferUpHeader = _LoadTemplate(sAll,_T("TMPL_TRANSFER_UP_HEADER"));
m_Templates.sTransferUpFooter = _LoadTemplate(sAll,_T("TMPL_TRANSFER_UP_FOOTER"));
m_Templates.sTransferUpLine = _LoadTemplate(sAll,_T("TMPL_TRANSFER_UP_LINE"));
m_Templates.sTransferUpQueueShow = _LoadTemplate(sAll,_T("TMPL_TRANSFER_UP_QUEUE_SHOW"));
m_Templates.sTransferUpQueueHide = _LoadTemplate(sAll,_T("TMPL_TRANSFER_UP_QUEUE_HIDE"));
m_Templates.sTransferUpQueueLine = _LoadTemplate(sAll,_T("TMPL_TRANSFER_UP_QUEUE_LINE"));
m_Templates.sTransferBadLink = _LoadTemplate(sAll,_T("TMPL_TRANSFER_BAD_LINK"));
m_Templates.sDownloadLink = _LoadTemplate(sAll,_T("TMPL_DOWNLOAD_LINK"));
m_Templates.sSharedList = _LoadTemplate(sAll,_T("TMPL_SHARED_LIST"));
m_Templates.sSharedLine = _LoadTemplate(sAll,_T("TMPL_SHARED_LINE"));
m_Templates.sSharedLineChanged = _LoadTemplate(sAll,_T("TMPL_SHARED_LINE_CHANGED"));
m_Templates.sGraphs = _LoadTemplate(sAll,_T("TMPL_GRAPHS"));
m_Templates.sLog = _LoadTemplate(sAll,_T("TMPL_LOG"));
m_Templates.sServerInfo = _LoadTemplate(sAll,_T("TMPL_SERVERINFO"));
m_Templates.sDebugLog = _LoadTemplate(sAll,_T("TMPL_DEBUGLOG"));
m_Templates.sStats = _LoadTemplate(sAll,_T("TMPL_STATS"));
m_Templates.sPreferences = _LoadTemplate(sAll,_T("TMPL_PREFERENCES_KAD"));
m_Templates.sLogin = _LoadTemplate(sAll,_T("TMPL_LOGIN"));
m_Templates.sConnectedServer = _LoadTemplate(sAll,_T("TMPL_CONNECTED_SERVER"));
m_Templates.sAddServerBox = _LoadTemplate(sAll,_T("TMPL_ADDSERVERBOX"));
m_Templates.sWebSearch = _LoadTemplate(sAll,_T("TMPL_WEBSEARCH"));
m_Templates.sSearch = _LoadTemplate(sAll,_T("TMPL_SEARCH_KAD"));
m_Templates.iProgressbarWidth=_tstoi(_LoadTemplate(sAll,_T("PROGRESSBARWIDTH")));
m_Templates.sSearchHeader = _LoadTemplate(sAll,_T("TMPL_SEARCH_RESULT_HEADER"));
m_Templates.sSearchResultLine = _LoadTemplate(sAll,_T("TMPL_SEARCH_RESULT_LINE"));
m_Templates.sProgressbarImgs = _LoadTemplate(sAll,_T("PROGRESSBARIMGS"));
m_Templates.sProgressbarImgsPercent = _LoadTemplate(sAll,_T("PROGRESSBARPERCENTIMG"));
m_Templates.sClearCompleted = _LoadTemplate(sAll,_T("TMPL_TRANSFER_DOWN_CLEARBUTTON"));
m_Templates.sCatArrow= _LoadTemplate(sAll,_T("TMPL_CATARROW"));
m_Templates.sBootstrapLine= _LoadTemplate(sAll,_T("TMPL_BOOTSTRAPLINE"));
m_Templates.sKad= _LoadTemplate(sAll,_T("TMPL_KADDLG"));
m_Templates.sProgressbarImgsPercent.Replace(_T("[PROGRESSGIFNAME]"),_T("%s"));
m_Templates.sProgressbarImgsPercent.Replace(_T("[PROGRESSGIFINTERNAL]"),_T("%i"));
m_Templates.sProgressbarImgs.Replace(_T("[PROGRESSGIFNAME]"),_T("%s"));
m_Templates.sProgressbarImgs.Replace(_T("[PROGRESSGIFINTERNAL]"),_T("%i"));
}
}
else
if(m_bServerWorking)
AddLogLine(true,GetResString(IDS_WEB_ERR_CANTLOAD), sFile);
}
CWebServer::~CWebServer(void)
{
if (m_bServerWorking) StopSockets();
}
CString CWebServer::_LoadTemplate(CString sAll, CString sTemplateName)
{
CString sRet = _T("");
int nStart = sAll.Find(_T("<--") + sTemplateName + _T("-->"));
int nEnd = sAll.Find(_T("<--") + sTemplateName + _T("_END-->"));
if(nStart != -1 && nEnd != -1 && nStart<nEnd)
{
nStart += sTemplateName.GetLength() + 7;
sRet = sAll.Mid(nStart, nEnd - nStart - 1);
} else{
if (sTemplateName==_T("TMPL_VERSION"))
AddLogLine(true,GetResString(IDS_WS_ERR_LOADTEMPLATE),sTemplateName);
if (thePrefs.GetVerbose() && nStart==-1)
AddDebugLogLine(false,GetResString(IDS_WEB_ERR_CANTLOAD),sTemplateName);
}
return sRet;
}
void CWebServer::RestartServer() { //Cax2 - restarts the server with the new port settings
StopSockets();
if (m_bServerWorking)
StartSockets(this);
}
void CWebServer::StartServer(void)
{
if(m_bServerWorking != thePrefs.GetWSIsEnabled())
m_bServerWorking = thePrefs.GetWSIsEnabled();
else
return;
if (m_bServerWorking) {
ReloadTemplates();
StartSockets(this);
} else StopSockets();
if(thePrefs.GetWSIsEnabled())
AddLogLine(false,_T("%s: %s"),_GetPlainResString(IDS_PW_WS), _GetPlainResString(IDS_ENABLED));
else
AddLogLine(false,_T("%s: %s"),_GetPlainResString(IDS_PW_WS), _GetPlainResString(IDS_DISABLED));
}
void CWebServer::_RemoveServer(CString sIP, int nPort)
{
CServer* server=theApp.serverlist->GetServerByAddress(sIP.GetBuffer() ,nPort);
if (server!=NULL) theApp.emuledlg->SendMessage(WEB_REMOVE_SERVER, (WPARAM)server, NULL);
}
void CWebServer::_SetSharedFilePriority(CString hash, uint8 priority)
{
CKnownFile* cur_file;
uchar fileid[16];
if (hash.GetLength()!=32 || !DecodeBase16(hash.GetBuffer(),hash.GetLength(),fileid,ARRSIZE(fileid)))
return;
cur_file=theApp.sharedfiles->GetFileByID(fileid);
if (cur_file==0) return;
if(priority >= 0 && priority < 5)
{
cur_file->SetAutoUpPriority(false);
cur_file->SetUpPriority(priority);
}
else if(priority == 5)// && cur_file->IsPartFile())
{
cur_file->SetAutoUpPriority(true);
cur_file->UpdateAutoUpPriority();
}
}
void CWebServer::AddStatsLine(UpDown line)
{
m_Params.PointsForWeb.Add(line);
if(m_Params.PointsForWeb.GetCount() > WEB_GRAPH_WIDTH)
m_Params.PointsForWeb.RemoveAt(0);
}
__inline void PlainString(CString& rstr, bool noquot)
{
rstr.Replace(_T("&"), _T("&"));
rstr.Replace(_T("<"), _T("<"));
rstr.Replace(_T(">"), _T(">"));
rstr.Replace(_T("\""), _T("""));
if(noquot)
{
rstr.Replace(_T("'"), _T("\\'"));
rstr.Replace(_T("\n"), _T("\\n"));
}
}
CString CWebServer::_SpecialChars(CString str)
{
PlainString(str,false);
return str;
}
void CWebServer::_ConnectToServer(CString sIP, int nPort)
{
CServer* server=NULL;
if (!sIP.IsEmpty()) server=theApp.serverlist->GetServerByAddress(sIP.GetBuffer(),nPort);
theApp.emuledlg->SendMessage(WEB_CONNECT_TO_SERVER, (WPARAM)server, NULL);
}
void CWebServer::ProcessFileReq(ThreadData Data) {
CWebServer *pThis = (CWebServer *)Data.pThis;
if (pThis == NULL) return;
CString filename=Data.sURL;
CString contenttype;
if (filename.Right(4).MakeLower()==_T(".gif")) contenttype=_T("Content-Type: image/gif\r\n");
else if (filename.Right(4).MakeLower()==_T(".jpg") || filename.Right(5).MakeLower()==_T(".jpeg")) contenttype=_T("Content-Type: image/jpg\r\n");
else if (filename.Right(4).MakeLower()==_T(".bmp")) contenttype=_T("Content-Type: image/bmp\r\n");
else if (filename.Right(4).MakeLower()==_T(".png")) contenttype=_T("Content-Type: image/png\r\n");
//DonQ - additional filetypes
else if (filename.Right(4).MakeLower()==_T(".ico")) contenttype=_T("Content-Type: image/x-icon\r\n");
else if (filename.Right(4).MakeLower()==_T(".css")) contenttype=_T("Content-Type: text/css\r\n");
else if (filename.Right(3).MakeLower()==_T(".js")) contenttype=_T("Content-Type: text/javascript\r\n");
contenttype += _T("Last-Modified: ") + pThis->m_Params.sLastModified + _T("\r\n") + _T("ETag: ") + pThis->m_Params.sETag + _T("\r\n");
filename.Replace(_T('/'),_T('\\'));
if (filename.GetAt(0)==_T('\\')) filename.Delete(0);
filename=thePrefs.GetWebServerDir()+filename;
CFile file;
if(file.Open(filename, CFile::modeRead|CFile::shareDenyWrite|CFile::typeBinary))
{
USES_CONVERSION;
char* buffer=new char[file.GetLength()];
int size=file.Read(buffer,file.GetLength());
file.Close();
Data.pSocket->SendContent(T2CA(contenttype), buffer, size);
delete[] buffer;
}
}
void CWebServer::ProcessURL(ThreadData Data)
{
CWebServer *pThis = (CWebServer *)Data.pThis;
if(pThis == NULL)
return;
//////////////////////////////////////////////////////////////////////////
// Here we are in real trouble! We are accessing the entire emule main thread
// data without any syncronization!! Either we use the message pump for emuledlg
// or use some hundreds of critical sections... For now, an exception handler
// shoul avoid the worse things.
//////////////////////////////////////////////////////////////////////////
CoInitialize(NULL);
try{
USES_CONVERSION;
bool isUseGzip = thePrefs.GetWebUseGzip();
CString Out = _T("");
CString OutE = _T(""); // List Entry Templates
CString OutE2 = _T("");
CString OutS = _T(""); // ServerStatus Templates
TCHAR *gzipOut = NULL;
long gzipLen=0;
CString HTTPProcessData = _T("");
CString HTTPTemp = _T("");
//char HTTPTempC[100] = _T("");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -