// This file is a part of the xMule Project.
//
// Copyright (c) 2004 Theodore R. Smith (hopeseekr@xmule.ws / http://www.xmule.ws/)
// DSA-1024 Fingerprint: 10A0 6372 9092 85A2 BB7F 907B CB8B 654B E33B F1ED
//
// 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.

#ifdef PRECOMP
#	include "xmule-headers.h"
#else
#	include "DownloadQueue.h"
#	include "ED2KLink.h"
#	include "MD5Sum.h"
#	include "Preferences.h"
#	include "resource.h"
#	include "server.h"
#	include "ServerList.h"
#	include "ServerWnd.h"
#	include "SharedFileList.h"
#	include "StatisticsDlg.h"
#	include "UploadQueue.h"
#	include "WebServer.h"
#	include "wintypes.h"
#	include "XBMDraw.h"
#	include "xmule.h"
#	include "xmuleDlg.h"
#endif

#include <stdlib.h>
#include <sys/socket.h>

#include <wx/filename.h>
#include <wx/txtstrm.h>
#include <wx/wfstream.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;

#define new DEBUG_NEW
#endif

#define HTTPInit "Server: xMule\r\nPragma: no-cache\r\nExpires: 0\r\nCache-Control: no-cache, no-store, must-revalidate\r\nConnection: close\r\nContent-Type: text/html\r\n"
#define HTTPInitGZ "Server: xMule\r\nPragma: no-cache\r\nExpires: 0\r\nCache-Control: no-cache, no-store, must-revalidate\r\nConnection: close\r\nContent-Type: text/html\r\nContent-Encoding: gzip\r\n"

#define WEB_SERVER_TEMPLATES_VERSION	2

static int dwThread = 0;

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;
    //GetCurrentThreadId();:
    dwThread = 0;
    m_bServerWorking = false;
}

void CWebServer::ReloadTemplates()
{
    wxString sFile = theApp.glob_prefs->GetAppDir() + wxString("xMule.tmpl");
    //CStdioFile file;
    //if(file.Open(sFile, CFile::modeRead|CFile::typeText))
    //{
    wxFileInputStream input(sFile);
    if (input.Ok())
    {
        wxTextInputStream file(input);
        wxString sAll;
        while (!input.Eof())
        {
            wxString sLine;
            sLine = file.ReadString();
            sAll += sLine + "\n";
        }
        //file.Close();
        // it'll get closed sometime..
        wxString sVersion = _LoadTemplate(sAll, "TMPL_VERSION");
        long lVersion = atol(sVersion);
        if (lVersion < WEB_SERVER_TEMPLATES_VERSION)
        {
            //if(m_bServerWorking)
            //theApp.xmuledlg->AddLogLine(true,GetResString(IDS_WS_ERR_LOADTEMPLATE),sFile);
        }
        else
        {
            m_Templates.sHeader = _LoadTemplate(sAll, "TMPL_HEADER");
            m_Templates.sHeaderMetaRefresh = _LoadTemplate(sAll, "TMPL_HEADER_META_REFRESH");
            m_Templates.sHeaderStylesheet = _LoadTemplate(sAll, "TMPL_HEADER_STYLESHEET");
            m_Templates.sFooter = _LoadTemplate(sAll, "TMPL_FOOTER");
            m_Templates.sServerList = _LoadTemplate(sAll, "TMPL_SERVER_LIST");
            m_Templates.sServerLine = _LoadTemplate(sAll, "TMPL_SERVER_LINE");
            m_Templates.sTransferImages = _LoadTemplate(sAll, "TMPL_TRANSFER_IMAGES");
            m_Templates.sTransferList = _LoadTemplate(sAll, "TMPL_TRANSFER_LIST");
            m_Templates.sTransferDownHeader = _LoadTemplate(sAll, "TMPL_TRANSFER_DOWN_HEADER");
            m_Templates.sTransferDownFooter = _LoadTemplate(sAll, "TMPL_TRANSFER_DOWN_FOOTER");
            m_Templates.sTransferDownLine = _LoadTemplate(sAll, "TMPL_TRANSFER_DOWN_LINE");
            m_Templates.sTransferDownLineGood = _LoadTemplate(sAll, "TMPL_TRANSFER_DOWN_LINE_GOOD");
            m_Templates.sTransferUpHeader = _LoadTemplate(sAll, "TMPL_TRANSFER_UP_HEADER");
            m_Templates.sTransferUpFooter = _LoadTemplate(sAll, "TMPL_TRANSFER_UP_FOOTER");
            m_Templates.sTransferUpLine = _LoadTemplate(sAll, "TMPL_TRANSFER_UP_LINE");
            m_Templates.sTransferUpQueueShow = _LoadTemplate(sAll, "TMPL_TRANSFER_UP_QUEUE_SHOW");
            m_Templates.sTransferUpQueueHide = _LoadTemplate(sAll, "TMPL_TRANSFER_UP_QUEUE_HIDE");
            m_Templates.sTransferUpQueueLine = _LoadTemplate(sAll, "TMPL_TRANSFER_UP_QUEUE_LINE");
            m_Templates.sTransferBadLink = _LoadTemplate(sAll, "TMPL_TRANSFER_BAD_LINK");
            m_Templates.sDownloadLink = _LoadTemplate(sAll, "TMPL_DOWNLOAD_LINK");
            m_Templates.sSharedList = _LoadTemplate(sAll, "TMPL_SHARED_LIST");
            m_Templates.sSharedLine = _LoadTemplate(sAll, "TMPL_SHARED_LINE");
            m_Templates.sSharedLineChanged = _LoadTemplate(sAll, "TMPL_SHARED_LINE_CHANGED");
            m_Templates.sGraphs = _LoadTemplate(sAll, "TMPL_GRAPHS");
            m_Templates.sLog = _LoadTemplate(sAll, "TMPL_LOG");
            m_Templates.sServerInfo = _LoadTemplate(sAll, "TMPL_SERVERINFO");
            m_Templates.sDebugLog = _LoadTemplate(sAll, "TMPL_DEBUGLOG");
            m_Templates.sStats = _LoadTemplate(sAll, "TMPL_STATS");
            m_Templates.sPreferences = _LoadTemplate(sAll, "TMPL_PREFERENCES");
            m_Templates.sLogin = _LoadTemplate(sAll, "TMPL_LOGIN");
            m_Templates.sConnectedServer = _LoadTemplate(sAll, "TMPL_CONNECTED_SERVER");
            m_Templates.sAddServerBox = _LoadTemplate(sAll, "TMPL_ADDSERVERBOX");
            m_Templates.sWebSearch = _LoadTemplate(sAll, "TMPL_WEBSEARCH");
            m_Templates.iProgressbarWidth = atoi(_LoadTemplate(sAll, "PROGRESSBARWIDTH"));
            m_Templates.sResDir = _LoadTemplate(sAll, "RESSOURCES_PATH");
        }
    }
    //else
    //if(m_bServerWorking)
    //theApp.xmuledlg->AddLogLine(true,GetResString(IDS_WEB_ERR_CANTLOAD), sFile);
}

CWebServer::~CWebServer(void)
{
    if (m_bServerWorking) StopSockets();
}

wxString CWebServer::_LoadTemplate(wxString sAll, wxString sTemplateName)
{
    wxString sRet = "";
    int nStart = sAll.Find("<--" + sTemplateName + "-->");
    int nEnd = sAll.Find("<--" + sTemplateName + "_END-->");
    if (nStart != - 1 &&nEnd != - 1)
    {
        nStart += sTemplateName.Length() + 7;
        sRet = sAll.Mid(nStart, nEnd - nStart - 1);
    }
    if (sRet.IsEmpty())
    {
        if (sTemplateName == "TMPL_VERSION")
        theApp.xmuledlg->AddLogLine(true, "Can't find template version number!\nPlease replace xMule.tmpl with a newer version!");
        theApp.xmuledlg->AddDebugLogLine(false, "Failed to load template " + sTemplateName);
    }
    return sRet;
}

void CWebServer::StartServer(void)
{
    if (m_bServerWorking != theApp.glob_prefs->GetWSIsEnabled())
    m_bServerWorking = theApp.glob_prefs->GetWSIsEnabled();
    else
    return;
    if (m_bServerWorking)
    {
        ReloadTemplates();
        StartSockets(this);
    }
    else StopSockets();
    if (theApp.glob_prefs->GetWSIsEnabled())
    theApp.xmuledlg->AddLogLine(false, "%s: %s", _GetPlainResString(IDS_PW_WS) .GetData(), _GetPlainResString(IDS_ENABLED) .GetData());
    else
    theApp.xmuledlg->AddLogLine(false, "%s: %s", _GetPlainResString(IDS_PW_WS) .GetData(), _GetPlainResString(IDS_DISABLED) .GetData());
}

void CWebServer::_RemoveServer(wxString sIP)
{
    CServer *server = theApp.serverlist->GetServerByAddress((char *) sIP.GetData(), 0);
    //if (server!=NULL) theApp.xmuledlg->SendMessage(WEB_REMOVE_SERVER, (WPARAM)server, NULL);
}

void CWebServer::_SetSharedFilePriority(wxString hash, uint8_t priority)
{
    CKnownFile *cur_file;
    unsigned char fileid[16];
    DecodeBase16(hash.GetData(), hash.Length(), fileid);
    cur_file = theApp.sharedfiles->GetFileByID(fileid);
    if (cur_file == 0) return;
    if (priority < 5)
    {
        //arning implementation still old one..
        //cur_file->SetAutoUpPriority(false);
        //cur_file->SetUpPriority(priority);
        // && cur_file->IsPartFile()):
    }
    else if(priority == 5)
    {
        //arning implementation still old one..
        //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)
    {
        delete m_Params.PointsForWeb[0];
        m_Params.PointsForWeb.RemoveAt(0);
    }
}

wxString CWebServer::_SpecialChars(wxString str)
{
    str.Replace("&", "&amp;");
    str.Replace("<", "&lt;");
    str.Replace(">", "&gt;");
    str.Replace("\"", "&quot;");
    return str;
}

void CWebServer::_ConnectToServer(wxString sIP)
{
#if 0
    CServer *server = theApp.serverlist->GetServerByAddress(sIP.GetBuffer(), 0);
    if (server != NULL) theApp.xmuledlg->SendMessage(WEB_CONNECT_TO_SERVER, (WPARAM) server, NULL);
#endif
}

void CWebServer::ProcessImgFileReq(ThreadData Data)
{
    wxString filename = Data.sURL;
    wxString contenttype;
    printf("inc. fname=%s\n", filename.GetData());
    if (filename.Right(4) .MakeLower() == ".gif") contenttype = "Content-Type: image/gif\r\n";
    else if(filename.Right(4) .MakeLower() == ".jpg" || filename.Right(5) .MakeLower() == ".jpeg") contenttype = "Content-Type: image/jpg\r\n";
    else if(filename.Right(4) .MakeLower() == ".bmp") contenttype = "Content-Type: image/bmp\r\n";
    else if(filename.Right(4) .MakeLower() == ".png") contenttype = "Content-Type: image/png";
    filename = filename.Right(filename.Length() - 1);
    //filename.Replace("/","\\");
    filename = wxString(theApp.glob_prefs->GetAppDir()) + "webserver/" + filename;
    printf("**** imgrequest: %s\n", filename.GetData());
    wxFileInputStream *fis = new wxFileInputStream(filename);
    if (fis->Ok())
    {
        fis->SeekI(0, wxFromEnd);
        off_t koko = fis->TellI();
        fis->SeekI(0, wxFromStart);
        char *buffer = new char[koko];
        fis->Read((void *) buffer, koko);
        Data.pSocket->SendContent((char *) contenttype.GetData(), (void *) buffer, fis->LastRead());
        delete fis;
        delete buffer;
    }
#if 0
    CFile file;
    if (file.Open(filename, CFile::modeRead |CFile::typeBinary))
    {
        char *buffer = new char[file.GetLength() ];
        int size = file.Read(buffer, file.GetLength());
        file.Close();
        Data.pSocket->SendContent(contenttype, buffer, size);
        delete[] buffer;
    }
#endif
}

void CWebServer::ProcessStyleFileReq(ThreadData Data)
{
    wxString filename = Data.sURL;
    wxString contenttype;
    printf("inc. fname=%s\n", filename.GetData());
    contenttype = "Content-Type: text/css\r\n";
    filename = filename.Right(filename.Length() - 1);
    //filename.Replace("/","\\");
    filename = wxString(theApp.glob_prefs->GetAppDir()) + "webserver/" + filename;
    printf("**** cssrequest: %s\n", filename.GetData());
    wxFileInputStream *fis = new wxFileInputStream(filename);
    if (fis->Ok())
    {
        fis->SeekI(0, wxFromEnd);
        off_t koko = fis->TellI();
        fis->SeekI(0, wxFromStart);
        char *buffer = new char[koko];
        fis->Read((void *) buffer, koko);
        Data.pSocket->SendContent((char *) contenttype.GetData(), (void *) buffer, fis->LastRead());
        delete fis;
        delete buffer;
    }
#if 0
    CFile file;
    if (file.Open(filename, CFile::modeRead |CFile::typeBinary))
    {
        char *buffer = new char[file.GetLength() ];
        int size = file.Read(buffer, file.GetLength());
        file.Close();
        Data.pSocket->SendContent(contenttype, buffer, size);
        delete[] buffer;
    }
#endif
}

void CWebServer::ProcessURL(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return;
#if 0
    SetThreadLocale(theApp.glob_prefs->GetLanguageID());
    CoInitialize(NULL);
#endif
    bool isUseGzip = theApp.glob_prefs->GetWebUseGzip();
    wxString Out = "";
    // List Entry Templates:
    wxString OutE = "";
    wxString OutE2 = "";
    // ServerStatus Templates:
    wxString OutS = "";
    TCHAR *gzipOut = NULL;
    long gzipLen = 0;
    wxString HTTPProcessData = "";
    wxString HTTPTemp = "";
    //char	HTTPTempC[100] = "";
    srand(time(NULL));
    long lSession = 0;
    if (_ParseURL(Data.sURL, "ses") != "")
    lSession = atol(_ParseURL(Data.sURL, "ses"));
    // WE CANT TOUCH THE MAIN THREAD'S GUI!!!
    if (_ParseURL(Data.sURL, "w") == "password")
    {
        wxString test = MD5Sum(_ParseURL(Data.sURL, "p")) .GetHash();
        printf("*** testing PW: %s == %s\n",
        MD5Sum(_ParseURL(Data.sURL, "p")) .GetHash() .GetData(),
        theApp.glob_prefs->GetWSPass() .GetData());
        if (MD5Sum(_ParseURL(Data.sURL, "p")) .GetHash() == theApp.glob_prefs->GetWSPass())
        {
                        Session *ses = new Session();;
            ses->admin = true;
            //CTime::GetCurrentTime();:
            ses->startTime = time(NULL);
            ses->lSession = lSession = rand() *10000L + rand();
            pThis->m_Params.Sessions.Add(ses);
            //theApp.xmuledlg->serverwnd->UpdateMyInfo();
            //theApp.xmuledlg->AddLogLine(true,GetResString(IDS_WEB_ADMINLOGIN));
        }
        else if(theApp.glob_prefs->GetWSIsLowUserEnabled() &&theApp.glob_prefs->GetWSLowPass() != "" &&MD5Sum(_ParseURL(Data.sURL, "p")) .GetHash() == theApp.glob_prefs->GetWSLowPass())
        {
            Session *ses = new Session();
            ses->admin = false;
            //CTime::GetCurrentTime();:
            ses->startTime = time(NULL);
            ses->lSession = lSession = rand() *10000L + rand();
            pThis->m_Params.Sessions.Add(ses);
            //theApp.xmuledlg->serverwnd->UpdateMyInfo();
            //theApp.xmuledlg->AddLogLine(true,GetResString(IDS_WEB_GUESTLOGIN));
        }
        else
        {
            //theApp.xmuledlg->AddLogLine(true,GetResString(IDS_WEB_BADLOGINATTEMPT));
        }
        // [Julien]:
        isUseGzip = false;
    }
    wxString sSession;
    sSession.Printf("%ld", lSession);
    if (_ParseURL(Data.sURL, "w") == "logout")
    _RemoveSession(Data, lSession);
    if (_IsLoggedIn(Data, lSession))
    {
        Out += _GetHeader(Data, lSession);
        wxString sPage = _ParseURL(Data.sURL, "w");
        printf("***** logged in, getting page %s\n", sPage.GetData());
        printf("***** session is %s\n", sSession.GetData());
        if (sPage == "server")
        {
            Out += _GetServerList(Data);
        }
        else
        if (sPage == "download")
        {
            Out += _GetDownloadLink(Data);
        }
        else
        if (sPage == "shared")
        {
            Out += _GetSharedFilesList(Data);
        }
        else
        if (sPage == "transfer")
        {
            Out += _GetTransferList(Data);
        }
        else
        if (sPage == "websearch")
        {
            Out += _GetWebSearch(Data);
        }
        else
        if (sPage == "search")
        {
            Out += _GetSearch(Data);
        }
        else
        if (sPage == "graphs")
        {
            Out += _GetGraphs(Data);
        }
        else
        if (sPage == "log")
        {
            Out += _GetLog(Data);
        }
        if (sPage == "sinfo")
        {
            Out += _GetServerInfo(Data);
        }
        if (sPage == "debuglog")
        {
            Out += _GetDebugLog(Data);
        }
        if (sPage == "stats")
        {
            Out += _GetStats(Data);
        }
        if (sPage == "options")
        {
            Out += _GetPreferences(Data);
        }
        Out += _GetFooter(Data);
        if (sPage == "")
        isUseGzip = false;
        if (isUseGzip)
        {
            bool bOk = false;
            try
            {
                uLongf destLen = Out.Length() + 1024;
                gzipOut = new TCHAR[destLen];
                if (_GzipCompress((Bytef *) gzipOut, &destLen, (const Bytef *)(TCHAR *) Out.GetData(), Out.Length(), Z_DEFAULT_COMPRESSION) == Z_OK)
                {
                    bOk = true;
                    gzipLen = destLen;
                }
            }
            catch(...)
            {
            }
            if (!bOk)
            {
                isUseGzip = false;
                if (gzipOut != NULL)
                {
                    delete[] gzipOut;
                    gzipOut = NULL;
                }
            }
        }
    }
    else
    {
        isUseGzip = false;
        Out += _GetLoginScreen(Data);
    }
    // send answer ...
    if (!isUseGzip)
    {
        Data.pSocket->SendContent(HTTPInit, Out, Out.Length());
    }
    else
    {
        Data.pSocket->SendContent(HTTPInitGZ, gzipOut, gzipLen);
    }
    if (gzipOut != NULL)
    delete[] gzipOut;
}

wxString CWebServer::_ParseURL(wxString URL, wxString fieldname)
{
    wxString value = "";
    wxString Parameter = "";
    // decode URL:
    char fromReplace[4] = "";
    // decode URL:
    char toReplace[2] = "";
    int i = 0;
    int findPos = - 1;
    int findLength = 0;
    printf("*** parsing url %s ::field %s\n", URL.GetData(), fieldname.GetData());
    if (URL.Find("?") > - 1)
    {
        Parameter = URL.Mid(URL.Find("?") + 1, URL.Length() - URL.Find("?") - 1);
        // search the fieldname beginning / middle and strip the rest...
        if (Parameter.Find(fieldname + "=") == 0)
        {
            findPos = 0;
            findLength = fieldname.Length() + 1;
        }
        if (Parameter.Find("&" + fieldname + "=") > - 1)
        {
            findPos = Parameter.Find("&" + fieldname + "=");
            findLength = fieldname.Length() + 2;
        }
        if (findPos > - 1)
        {
            Parameter = Parameter.Mid(findPos + findLength, Parameter.Length());
            if (Parameter.Find("&") > - 1)
            {
                Parameter = Parameter.Mid(0, Parameter.Find("&"));
            }
            value = Parameter;
            // decode value ...
            value.Replace("+", " ");
            for (i = 0 ; i <= 255 ; i++)
            {
                sprintf(fromReplace, "%%%02x", i);
                toReplace[0] = (char) i;
                toReplace[1] = 0;
                value.Replace(fromReplace, toReplace);
                sprintf(fromReplace, "%%%02X", i);
                value.Replace(fromReplace, toReplace);
            }
        }
    }
    printf("*** URL parsed. returning %s\n", value.GetData());
    return value;
}

wxString CWebServer::_GetHeader(ThreadData Data, long lSession)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession;
    sSession.Printf("%ld", lSession);
    wxString Out = pThis->m_Templates.sHeader;
    Out.Replace("[CharSet]", _GetWebCharSet());
    if (theApp.glob_prefs->GetWebPageRefresh() != 0)
    {
        wxString sPage = _ParseURL(Data.sURL, "w");
        if ((sPage == "transfer") ||
        (sPage == "server") ||
        (sPage == "graphs") ||
        (sPage == "log") ||
        (sPage == "sinfo") ||
        (sPage == "debuglog") ||
        (sPage == "stats"))
        {
            wxString sT = pThis->m_Templates.sHeaderMetaRefresh;
            wxString sRefresh;
            sRefresh.Printf("%d", theApp.glob_prefs->GetWebPageRefresh());
            sT.Replace("[RefreshVal]", sRefresh);
            sT.Replace("[wCommand]", _ParseURL(Data.sURL, "w"));
            Out.Replace("[HeaderMeta]", sT);
        }
    }
    Out.Replace("[Session]", sSession);
    printf("*** replaced session with %s\n", sSession.GetData());
    // In case there are no meta:
    Out.Replace("[HeaderMeta]", "");
    Out.Replace("[xMuleAppName]", "xMule");
    Out.Replace("[version]", CURRENT_VERSION_LONG);
    Out.Replace("[StyleSheet]", pThis->m_Templates.sHeaderStylesheet);
    Out.Replace("[WebControl]", _GetPlainResString(IDS_WEB_CONTROL));
    Out.Replace("[Transfer]", _GetPlainResString(IDS_CD_TRANS));
    Out.Replace("[Server]", _GetPlainResString(IDS_SV_SERVERLIST));
    Out.Replace("[Shared]", _GetPlainResString(IDS_SHAREDFILES));
    Out.Replace("[Download]", _GetPlainResString(IDS_SW_LINK));
    Out.Replace("[Graphs]", _GetPlainResString(IDS_GRAPHS));
    Out.Replace("[Log]", _GetPlainResString(IDS_SV_LOG));
    Out.Replace("[ServerInfo]", _GetPlainResString(IDS_SV_SERVERINFO));
    Out.Replace("[DebugLog]", _GetPlainResString(IDS_SV_DEBUGLOG));
    Out.Replace("[Stats]", _GetPlainResString(IDS_SF_STATISTICS));
    Out.Replace("[Options]", _GetPlainResString(IDS_EM_PREFS));
    Out.Replace("[Logout]", _GetPlainResString(IDS_WEB_LOGOUT));
    char HTTPTempC[100] = "";
    wxString sConnected = "";
    if (theApp.serverconnect->IsConnected())
    {
        if (!theApp.serverconnect->IsLowID())
        sConnected = _GetPlainResString(IDS_CONNECTED);
        else
        sConnected = _GetPlainResString(IDS_CONNECTED) + " (" + _GetPlainResString(IDS_IDLOW) + ")";
        CServer *cur_server = theApp.serverconnect->GetCurrentServer();
        sConnected += ": " + wxString(cur_server->GetListName());
        sprintf(HTTPTempC, "%i ", cur_server->GetUsers());
        sConnected += " [" + wxString(HTTPTempC) + _GetPlainResString(IDS_LUSERS) + "]";
    }
    else if(theApp.serverconnect->IsConnecting())
    {
        sConnected = _GetPlainResString(IDS_CONNECTING);
    }
    else
    {
        sConnected = _GetPlainResString(IDS_DISCONNECTED);
        if (IsSessionAdmin(Data, sSession)) sConnected += " (<small><a href=\"/?ses=" + sSession + "&w=server&c=connect\">" + _GetPlainResString(IDS_CONNECTTOANYSERVER) + "</a></small>)";
    }
    Out.Replace("[Connected]", "<b>" + _GetPlainResString(IDS_PW_CONNECTION) + ":</b> " + sConnected);
    sprintf(HTTPTempC, _GetPlainResString(IDS_UPDOWNSMALL), (float) theApp.uploadqueue->GetDatarate() /1024, (float) theApp.downloadqueue->GetDatarate() /1024);
    wxString sLimits;
    // EC 25-12-2003
    wxString MaxUpload;
    wxString MaxDownload;
    MaxUpload.Printf("%i", theApp.glob_prefs->GetMaxUpload());
    MaxDownload.Printf("%i", theApp.glob_prefs->GetMaxDownload());
    if (MaxUpload == "65535") MaxUpload = GetResString(IDS_PW_UNLIMITED);
    if (MaxDownload == "65535") MaxDownload = GetResString(IDS_PW_UNLIMITED);
    sLimits.Printf("%s/%s", MaxUpload.GetData(), MaxDownload.GetData());
    // EC Ends
    Out.Replace("[Speed]", "<b>" + _GetPlainResString(IDS_DL_SPEED) + ":</b> " + wxString(HTTPTempC) + "<small> (" + _GetPlainResString(IDS_PW_CON_LIMITFRM) + ": " + sLimits + ")</small>");
    return Out;
}

wxString CWebServer::_GetFooter(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    return pThis->m_Templates.sFooter;
}

wxString CWebServer::_GetServerList(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession = _ParseURL(Data.sURL, "ses");
    wxString sAddServerBox = "";
    wxString sCmd = _ParseURL(Data.sURL, "c");
    if (sCmd == "connect" &&IsSessionAdmin(Data, sSession))
    {
        wxString sIP = _ParseURL(Data.sURL, "ip");
        if (sIP.IsEmpty())
        {
            //theApp.xmuledlg->SendMessage(WM_COMMAND, MP_CONNECT);
            wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED, MP_CONNECT);
            wxPostEvent(theApp.xmuledlg, evt);
        }
        else
        _ConnectToServer(sIP);
    }
    else if(sCmd == "disconnect" &&IsSessionAdmin(Data, sSession))
    {
        //theApp.xmuledlg->SendMessage(WM_COMMAND, MP_DISCONNECT);
        wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED, MP_DISCONNECT);
        wxPostEvent(theApp.xmuledlg, evt);
    }
    else if(sCmd == "remove" &&IsSessionAdmin(Data, sSession))
    {
        wxString sIP = _ParseURL(Data.sURL, "ip");
        if (!sIP.IsEmpty())
        _RemoveServer(sIP);
    }
    else if(sCmd == "options")
    {
        sAddServerBox = _GetAddServerBox(Data);
    }
    wxString sSort = _ParseURL(Data.sURL, "sort");
    if (sSort != "")
    {
        if (sSort == "name")
        pThis->m_Params.ServerSort = SERVER_SORT_NAME;
        else
        if (sSort == "description")
        pThis->m_Params.ServerSort = SERVER_SORT_DESCRIPTION;
        else
        if (sSort == "ip")
        pThis->m_Params.ServerSort = SERVER_SORT_IP;
        else
        if (sSort == "users")
        pThis->m_Params.ServerSort = SERVER_SORT_USERS;
        else
        if (sSort == "files")
        pThis->m_Params.ServerSort = SERVER_SORT_FILES;
        if (_ParseURL(Data.sURL, "sortreverse") == "")
        pThis->m_Params.bServerSortReverse = false;
    }
    if (_ParseURL(Data.sURL, "sortreverse") != "")
    {
        pThis->m_Params.bServerSortReverse = (_ParseURL(Data.sURL, "sortreverse") == "true");
    }
    wxString sServerSortRev;
    if (pThis->m_Params.bServerSortReverse)
    sServerSortRev = "false";
    else
    sServerSortRev = "true";
    wxString Out = pThis->m_Templates.sServerList;
    Out.Replace("[ConnectedServerData]", _GetConnectedServer(Data));
    Out.Replace("[AddServerBox]", sAddServerBox);
    Out.Replace("[Session]", sSession);
    if (pThis->m_Params.ServerSort == SERVER_SORT_NAME)
    Out.Replace("[SortName]", "&sortreverse=" + sServerSortRev);
    else
    Out.Replace("[SortName]", "");
    if (pThis->m_Params.ServerSort == SERVER_SORT_DESCRIPTION)
    Out.Replace("[SortDescription]", "&sortreverse=" + sServerSortRev);
    else
    Out.Replace("[SortDescription]", "");
    if (pThis->m_Params.ServerSort == SERVER_SORT_IP)
    Out.Replace("[SortIP]", "&sortreverse=" + sServerSortRev);
    else
    Out.Replace("[SortIP]", "");
    if (pThis->m_Params.ServerSort == SERVER_SORT_USERS)
    Out.Replace("[SortUsers]", "&sortreverse=" + sServerSortRev);
    else
    Out.Replace("[SortUsers]", "");
    if (pThis->m_Params.ServerSort == SERVER_SORT_FILES)
    Out.Replace("[SortFiles]", "&sortreverse=" + sServerSortRev);
    else
    Out.Replace("[SortFiles]", "");
    Out.Replace("[ServerList]", _GetPlainResString(IDS_SV_SERVERLIST));
    Out.Replace("[Servername]", _GetPlainResString(IDS_SL_SERVERNAME));
    Out.Replace("[Description]", _GetPlainResString(IDS_DESCRIPTION));
    Out.Replace("[Address]", _GetPlainResString(IDS_IP));
    Out.Replace("[Connect]", _GetPlainResString(IDS_IRC_CONNECT));
    Out.Replace("[Users]", _GetPlainResString(IDS_LUSERS));
    Out.Replace("[Files]", _GetPlainResString(IDS_LFILES));
    //Out.Replace("[Actions]", _GetPlainResString(IDS_WEB_ACTIONS));
    wxString OutE = pThis->m_Templates.sServerLine;
    OutE.Replace("[Connect]", _GetPlainResString(IDS_IRC_CONNECT));
    OutE.Replace("[RemoveServer]", _GetPlainResString(IDS_REMOVETHIS));
    //OutE.Replace("[ConfirmRemove]", _GetPlainResString(IDS_WEB_CONFIRM_REMOVE_SERVER));
    CArray < ServerEntry *, ServerEntry *> ServerArray;
    // Populating array
    for (uint32_t sc = 0 ; sc < theApp.serverlist->GetServerCount() ; sc++)
    {
        CServer *cur_file = theApp.serverlist->GetServerAt(sc);
        ServerEntry *Entry = new ServerEntry;
        Entry->sServerName = _SpecialChars(cur_file->GetListName());
        Entry->sServerDescription = _SpecialChars(cur_file->GetDescription());
        Entry->nServerPort = cur_file->GetPort();
        Entry->sServerIP = cur_file->GetAddress();
        Entry->nServerUsers = cur_file->GetUsers();
        Entry->nServerMaxUsers = cur_file->GetMaxUsers();
        Entry->nServerFiles = cur_file->GetFiles();
        ServerArray.Add(Entry);
    }
    // Sorting (simple bubble sort, we don't have tons of data here)
    bool bSorted = true;
    for (int nMax = 0 ; bSorted &&nMax < ServerArray.GetCount() *2 ; nMax++)
    {
        bSorted = false;
        for (int i = 0 ; i < ServerArray.GetCount() - 1 ; i++)
        {
            bool bSwap = false;
            switch (pThis->m_Params.ServerSort)
            {
            case SERVER_SORT_NAME:
                bSwap = ServerArray[i]->sServerName.CmpNoCase(ServerArray[i + 1]->sServerName) > 0;
                break;
            case SERVER_SORT_DESCRIPTION:
                bSwap = ServerArray[i]->sServerDescription.CmpNoCase(ServerArray[i + 1]->sServerDescription) < 0;
                break;
            case SERVER_SORT_IP:
                bSwap = ServerArray[i]->sServerIP.CmpNoCase(ServerArray[i + 1]->sServerIP) > 0;
                break;
            case SERVER_SORT_USERS:
                bSwap = ServerArray[i]->nServerUsers < ServerArray[i + 1]->nServerUsers;
                break;
            case SERVER_SORT_FILES:
                bSwap = ServerArray[i]->nServerFiles < ServerArray[i + 1]->nServerFiles;
                break;
            }
            if (pThis->m_Params.bServerSortReverse)
            {
                bSwap =!bSwap;
            }
            if (bSwap)
            {
                bSorted = true;
                ServerEntry *TmpEntry = ServerArray[i];
                ServerArray[i] = ServerArray[i + 1];
                ServerArray[i + 1] = TmpEntry;
            }
        }
    }
    // Displaying
    wxString sList = "";
    for (int i = 0 ; i < ServerArray.GetCount() ; i++)
    {
        // Copy Entry Line to Temp:
        wxString HTTPProcessData = OutE;
        HTTPProcessData.Replace("[1]", ServerArray[i]->sServerName);
        HTTPProcessData.Replace("[2]", ServerArray[i]->sServerDescription);
        wxString sPort;
        sPort.Printf(":%d", ServerArray[i]->nServerPort);
        HTTPProcessData.Replace("[3]", ServerArray[i]->sServerIP + sPort);
        wxString sT;
        if (ServerArray[i]->nServerUsers > 0)
        {
            if (ServerArray[i]->nServerMaxUsers > 0)
            sT.Printf("%d (%d)", ServerArray[i]->nServerUsers, ServerArray[i]->nServerMaxUsers);
            else
            sT.Printf("%d", ServerArray[i]->nServerUsers);
        }
        HTTPProcessData.Replace("[4]", sT);
        sT = "";
        if (ServerArray[i]->nServerFiles > 0)
        sT.Printf("%d", ServerArray[i]->nServerFiles);
        HTTPProcessData.Replace("[5]", sT);
        HTTPProcessData.Replace("[6]", IsSessionAdmin(Data, sSession) ? wxString("/?ses=" + sSession + "&w=server&c=connect&ip=" + ServerArray[i]->sServerIP): GetPermissionDenied());
        HTTPProcessData.Replace("[LinkRemove]", IsSessionAdmin(Data, sSession) ?wxString("/?ses=" + sSession + "&w=server&c=remove&ip=" + ServerArray[i]->sServerIP): GetPermissionDenied());
        sList += HTTPProcessData;
    }
    Out.Replace("[ServersList]", sList);
    return Out;
}

wxString CWebServer::_GetTransferList(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession = _ParseURL(Data.sURL, "ses");
    wxString Out = "";
    if (_ParseURL(Data.sURL, "c") != "" &&IsSessionAdmin(Data, sSession))
    {
        wxString HTTPTemp = _ParseURL(Data.sURL, "c");
        if (HTTPTemp.Right(1) != "/")
        HTTPTemp += "/";
        try
        {
            CED2KLink *pLink = CED2KLink::CreateLinkFromUrl(HTTPTemp);
            if (pLink->GetKind() == CED2KLink::kFile)
            theApp.downloadqueue->AddFileLinkToDownload(pLink->GetFileLink());
            else
            throw wxString("bad link");
            delete pLink;
        }
        catch(wxString error)
        {
            char HTTPTempC[100] = "";
            sprintf(HTTPTempC, _GetPlainResString(IDS_ERR_INVALIDLINK), error.GetData());
            Out += pThis->m_Templates.sTransferBadLink;
            Out.Replace("[InvalidLink]", HTTPTempC);
            Out.Replace("[Link]", HTTPTemp);
        }
    }
    if (_ParseURL(Data.sURL, "op") != "" &&
    _ParseURL(Data.sURL, "file") != "")
    {
        unsigned char FileHash[16];
        _GetFileHash(_ParseURL(Data.sURL, "file"), FileHash);
        CPartFile *found_file = NULL;
        for (int fx = 0 ; fx < theApp.downloadqueue->GetFileCount() ; fx++)
        {
            CPartFile *cur_file = theApp.downloadqueue->GetFileByIndex(fx);
            bool bGood = true;
            for (int i = 0 ; i < 16 ; i++)
            {
                if (cur_file->GetFileHash() [i] != FileHash[i])
                {
                    bGood = false;
                    break;
                }
            }
            if (bGood)
            {
                found_file = cur_file;
                break;
            }
        }
        if (_ParseURL(Data.sURL, "op") == "pause" &&IsSessionAdmin(Data, sSession))
        {
            if (found_file)
            found_file->PauseFile();
        }
        else if(_ParseURL(Data.sURL, "op") == "resume" &&IsSessionAdmin(Data, sSession))
        {
            if (found_file)
            found_file->ResumeFile();
        }
        else if(_ParseURL(Data.sURL, "op") == "cancel" &&IsSessionAdmin(Data, sSession))
        {
            if (found_file)
            found_file->DeleteFile();
        }
    }
    if (_ParseURL(Data.sURL, "sort") != "")
    {
        if (_ParseURL(Data.sURL, "sort") == "name")
        pThis->m_Params.DownloadSort = DOWN_SORT_NAME;
        else
        if (_ParseURL(Data.sURL, "sort") == "size")
        pThis->m_Params.DownloadSort = DOWN_SORT_SIZE;
        else
        if (_ParseURL(Data.sURL, "sort") == "transferred")
        pThis->m_Params.DownloadSort = DOWN_SORT_TRANSFERRED;
        else
        if (_ParseURL(Data.sURL, "sort") == "speed")
        pThis->m_Params.DownloadSort = DOWN_SORT_SPEED;
        else
        if (_ParseURL(Data.sURL, "sort") == "progress")
        pThis->m_Params.DownloadSort = DOWN_SORT_PROGRESS;
        if (_ParseURL(Data.sURL, "sortreverse") == "")
        pThis->m_Params.bDownloadSortReverse = false;
    }
    if (_ParseURL(Data.sURL, "sortreverse") != "")
    {
        pThis->m_Params.bDownloadSortReverse = (_ParseURL(Data.sURL, "sortreverse") == "true");
    }
    if (_ParseURL(Data.sURL, "showuploadqueue") == "true")
    {
        pThis->m_Params.bShowUploadQueue = true;
    }
    if (_ParseURL(Data.sURL, "showuploadqueue") == "false")
    {
        pThis->m_Params.bShowUploadQueue = false;
    }
    wxString sDownloadSortRev;
    if (pThis->m_Params.bDownloadSortReverse)
    sDownloadSortRev = "false";
    else
    sDownloadSortRev = "true";
    Out += pThis->m_Templates.sTransferImages;
    Out += pThis->m_Templates.sTransferList;
    Out.Replace("[DownloadHeader]", pThis->m_Templates.sTransferDownHeader);
    Out.Replace("[DownloadFooter]", pThis->m_Templates.sTransferDownFooter);
    Out.Replace("[UploadHeader]", pThis->m_Templates.sTransferUpHeader);
    Out.Replace("[UploadFooter]", pThis->m_Templates.sTransferUpFooter);
    Out.Replace("[Session]", sSession);
    if (pThis->m_Params.DownloadSort == DOWN_SORT_NAME)
    Out.Replace("[SortName]", "&sortreverse=" + sDownloadSortRev);
    else
    Out.Replace("[SortName]", "");
    if (pThis->m_Params.DownloadSort == DOWN_SORT_SIZE)
    Out.Replace("[SortSize]", "&sortreverse=" + sDownloadSortRev);
    else
    Out.Replace("[SortSize]", "");
    if (pThis->m_Params.DownloadSort == DOWN_SORT_TRANSFERRED)
    Out.Replace("[SortTransferred]", "&sortreverse=" + sDownloadSortRev);
    else
    Out.Replace("[SortTransferred]", "");
    if (pThis->m_Params.DownloadSort == DOWN_SORT_SPEED)
    Out.Replace("[SortSpeed]", "&sortreverse=" + sDownloadSortRev);
    else
    Out.Replace("[SortSpeed]", "");
    if (pThis->m_Params.DownloadSort == DOWN_SORT_PROGRESS)
    Out.Replace("[SortProgress]", "&sortreverse=" + sDownloadSortRev);
    else
    Out.Replace("[SortProgress]", "");
    Out.Replace("[DownloadList]", _GetPlainResString(IDS_TW_DOWNLOADS));
    Out.Replace("[Filename]", _GetPlainResString(IDS_DL_FILENAME));
    Out.Replace("[Size]", _GetPlainResString(IDS_DL_SIZE));
    Out.Replace("[Transferred]", _GetPlainResString(IDS_DL_TRANSF));
    Out.Replace("[Progress]", _GetPlainResString(IDS_DL_PROGRESS));
    Out.Replace("[Speed]", _GetPlainResString(IDS_DL_SPEED));
    Out.Replace("[Sources]", _GetPlainResString(IDS_DL_SOURCES));
    Out.Replace("[Actions]", _GetPlainResString(IDS_WEB_ACTIONS));
    Out.Replace("[UploadList]", _GetPlainResString(IDS_PW_CON_UPLBL));
    Out.Replace("[User]", _GetPlainResString(IDS_QL_USERNAME));
    Out.Replace("[TotalDown]", _GetPlainResString(IDS_INFLST_USER_TOTALDOWNLOAD));
    Out.Replace("[TotalUp]", _GetPlainResString(IDS_INFLST_USER_TOTALUPLOAD));
    wxString OutE = pThis->m_Templates.sTransferDownLine;
    wxString OutE2 = pThis->m_Templates.sTransferDownLineGood;
    float fTotalSize = 0, fTotalTransferred = 0, fTotalSpeed = 0;
    CArray < DownloadFiles *, DownloadFiles *> FilesArray;
    // Populating array
    for (int fx = 0 ; fx < theApp.downloadqueue->GetFileCount() ; fx++)
    {
        CPartFile *cur_file = theApp.downloadqueue->GetFileByIndex(fx);
        DownloadFiles *dFile = new DownloadFiles;
        dFile->sFileName = _SpecialChars(cur_file->GetFileName());
        dFile->lFileSize = cur_file->GetFileSize();
        dFile->lFileTransferred = cur_file->GetTransfered();
        dFile->lFileSpeed = cur_file->GetDatarate();
        dFile->nFileStatus = cur_file->GetStatus();
        dFile->sFileStatus = cur_file->getPartfileStatus();
        dFile->sFileHash = EncodeBase16(cur_file->GetFileHash(), 16);
        dFile->lSourceCount = cur_file->GetSourceCount();
        dFile->lNotCurrentSourceCount = cur_file->GetNotCurrentSourcesCount();
        dFile->lTransferringSourceCount = cur_file->GetTransferingSrcCount();
        if (theApp.serverconnect->IsConnected() && !theApp.serverconnect->IsLowID())
        dFile->sED2kLink = theApp.CreateED2kSourceLink(cur_file);
        else
        dFile->sED2kLink = theApp.CreateED2kLink(cur_file);
        dFile->sFileInfo = _SpecialChars(cur_file->GetDownloadFileInfo());
        FilesArray.Add(dFile);
    }
    // Sorting (simple bubble sort, we don't have tons of data here)
    bool bSorted = true;
    for (int nMax = 0 ; bSorted &&nMax < FilesArray.GetCount() *2 ; nMax++)
    {
        bSorted = false;
        for (int i = 0 ; i < FilesArray.GetCount() - 1 ; i++)
        {
            bool bSwap = false;
            switch (pThis->m_Params.DownloadSort)
            {
            case DOWN_SORT_NAME:
                bSwap = FilesArray[i]->sFileName.CmpNoCase(FilesArray[i + 1]->sFileName) > 0;
                break;
            case DOWN_SORT_SIZE:
                bSwap = FilesArray[i]->lFileSize < FilesArray[i + 1]->lFileSize;
                break;
            case DOWN_SORT_TRANSFERRED:
                bSwap = FilesArray[i]->lFileTransferred < FilesArray[i + 1]->lFileTransferred;
                break;
            case DOWN_SORT_SPEED:
                bSwap = FilesArray[i]->lFileSpeed < FilesArray[i + 1]->lFileSpeed;
                break;
            case DOWN_SORT_PROGRESS:
                {
                    int nPercent1 = 0, nPercent2 = 0;
                    if (FilesArray[i]->lFileSize > 0)
                    {
                        float fS = FilesArray[i]->lFileSize, fT = FilesArray[i]->lFileTransferred;
                        nPercent1 = abs((int)((fT *100.0) / fS));
                    }
                    if (FilesArray[i + 1]->lFileSize > 0)
                    {
                        float fS = FilesArray[i + 1]->lFileSize, fT = FilesArray[i + 1]->lFileTransferred;
                        nPercent2 = abs((int)((fT *100.0) / fS));
                    }
                    bSwap = nPercent1 < nPercent2;
                }
            }
            if (pThis->m_Params.bDownloadSortReverse)
            {
                bSwap =!bSwap;
            }
            if (bSwap)
            {
                bSorted = true;
                DownloadFiles *TmpFile = FilesArray[i];
                FilesArray[i] = FilesArray[i + 1];
                FilesArray[i + 1] = TmpFile;
            }
        }
    }
    // Displaying
    wxString sDownList = "";
    wxString HTTPTemp;
    for (int i = 0 ; i < FilesArray.GetCount() ; i++)
    {
        wxString JSfileinfo = FilesArray[i]->sFileInfo;
        JSfileinfo.Replace("\n", "\\n");
        wxString sActions = "<acronym title=\"" + FilesArray[i]->sFileStatus + "\"><a href=\"javascript:alert(\'" + JSfileinfo + "')\"><img src=\"l_info.gif\" alt=\"" + FilesArray[i]->sFileStatus + "\"></a></acronym> ";
        wxString sED2kLink;
        sED2kLink.Printf("<acronym title=\"[Ed2klink]\"><a href=\"" + FilesArray[i]->sED2kLink + "\"><img src=\"l_ed2klink.gif\" alt=\"[Ed2klink]\"></a></acronym> ");
        sED2kLink.Replace("[Ed2klink]", _GetPlainResString(IDS_SW_LINK));
        sActions += sED2kLink;
        bool bCanBeDeleted = true;
        switch (FilesArray[i]->nFileStatus)
        {
        case PS_COMPLETING:
        case PS_COMPLETE:
            bCanBeDeleted = false;
            break;
        case PS_HASHING:
        case PS_WAITINGFORHASH:
        case PS_ERROR:
            break;
        case PS_PAUSED:
            {
                wxString sResume;
                sResume.Printf("<acronym title=\"[Resume]\"><a href=\"[Link]\"><img src=\"l_resume.gif\" alt=\"[Resume]\"></a></acronym> ");
                sResume.Replace("[Link]", IsSessionAdmin(Data, sSession) ?wxString("/?ses=" + sSession + "&w=transfer&op=resume&file=" + FilesArray[i]->sFileHash): GetPermissionDenied());
                sActions += sResume;
            }
            break;
            // waiting or downloading:
        default:
            {
                wxString sPause;
                sPause.Printf("<acronym title=\"[Pause]\"><a href=\"[Link]\"><img src=\"l_pause.gif\" alt=\"[Pause]\"></a></acronym> ");
                sPause.Replace("[Link]", IsSessionAdmin(Data, sSession) ?wxString("/?ses=" + sSession + "&w=transfer&op=pause&file=" + FilesArray[i]->sFileHash): GetPermissionDenied());
                sActions += sPause;
            }
            break;
        }
        if (bCanBeDeleted)
        {
            wxString sCancel;
            sCancel.Printf("<acronym title=\"[Cancel]\"><a href=\"[Link]\" onclick=\"return confirm(\'[ConfirmCancel]\')\"><img src=\"l_cancel.gif\" alt=\"[Cancel]\"></a></acronym> ");
            sCancel.Replace("[Link]", IsSessionAdmin(Data, sSession) ?wxString("/?ses=" + sSession + "&w=transfer&op=cancel&file=" + FilesArray[i]->sFileHash): GetPermissionDenied());
            sActions += sCancel;
        }
        sActions.Replace("[Resume]", _GetPlainResString(IDS_DL_RESUME));
        sActions.Replace("[Pause]", _GetPlainResString(IDS_DL_PAUSE));
        sActions.Replace("[Cancel]", _GetPlainResString(IDS_MAIN_BTN_CANCEL));
        sActions.Replace("[ConfirmCancel]", _GetPlainResString(IDS_Q_CANCELDL2, true));
        wxString HTTPProcessData;
        // if downloading, draw in other color
        if (FilesArray[i]->lFileSpeed > 0)
        HTTPProcessData = OutE2;
        else
        HTTPProcessData = OutE;
        if (FilesArray[i]->sFileName.Length() > SHORT_FILENAME_LENGTH)
        HTTPProcessData.Replace("[ShortFileName]", FilesArray[i]->sFileName.Left(SHORT_FILENAME_LENGTH) + "...");
        else
        HTTPProcessData.Replace("[ShortFileName]", FilesArray[i]->sFileName);
        HTTPProcessData.Replace("[FileInfo]", FilesArray[i]->sFileInfo);
        fTotalSize += FilesArray[i]->lFileSize;
        HTTPProcessData.Replace("[2]", CastItoXBytes(FilesArray[i]->lFileSize));
        if (FilesArray[i]->lFileTransferred > 0)
        {
            fTotalTransferred += FilesArray[i]->lFileTransferred;
            HTTPProcessData.Replace("[3]", CastItoXBytes(FilesArray[i]->lFileTransferred));
        }
        else
        HTTPProcessData.Replace("[3]", "-");
        HTTPProcessData.Replace("[DownloadBar]", _GetDownloadGraph(Data, FilesArray[i]->sFileHash));
        if (FilesArray[i]->lFileSpeed > 0.0f)
        {
            fTotalSpeed += FilesArray[i]->lFileSpeed;
            HTTPTemp.Printf("%8.2f %s", FilesArray[i]->lFileSpeed/1024.0, _GetPlainResString(IDS_KBYTESEC) .GetData());
            HTTPProcessData.Replace("[4]", HTTPTemp);
        }
        else
        HTTPProcessData.Replace("[4]", "-");
        if (FilesArray[i]->lSourceCount > 0)
        {
            HTTPTemp.Printf("%8i/%8i (%i)",
            FilesArray[i]->lSourceCount - FilesArray[i]->lNotCurrentSourceCount,
            FilesArray[i]->lSourceCount,
            FilesArray[i]->lTransferringSourceCount);
            HTTPProcessData.Replace("[5]", HTTPTemp);
        }
        else
        HTTPProcessData.Replace("[5]", "-");
        HTTPProcessData.Replace("[6]", sActions);
        sDownList += HTTPProcessData;
    }
    // clear the array
    for (int qq = 0 ; qq < FilesArray.GetCount() ; qq++)
    {
        delete FilesArray[qq];
    }
    Out.Replace("[DownloadFilesList]", sDownList);
    Out.Replace("[TotalDownSize]", CastItoXBytes((long long) fTotalSize));
    Out.Replace("[TotalDownTransferred]", CastItoXBytes((long long) fTotalTransferred));
    HTTPTemp.Printf("%8.2f %s", fTotalSpeed/1024.0, _GetPlainResString(IDS_KBYTESEC) .GetData());
    Out.Replace("[TotalDownSpeed]", HTTPTemp);
    OutE = pThis->m_Templates.sTransferUpLine;
    HTTPTemp.Printf("%i", pThis->m_Templates.iProgressbarWidth);
    Out.Replace("[PROGRESSBARWIDTHVAL]", HTTPTemp);
    fTotalSize = 0;
    fTotalTransferred = 0;
    fTotalSpeed = 0;
    wxString sUpList = "";
    for (POSITION pos = theApp.uploadqueue->GetFirstFromUploadList() ;
    pos != 0 ; theApp.uploadqueue->GetNextFromUploadList(pos))
    {
        CUpDownClient *cur_client = theApp.uploadqueue->GetQueueClientAt(pos);
        wxString HTTPProcessData = OutE;
        HTTPProcessData.Replace("[1]", _SpecialChars(cur_client->GetUserName()));
        HTTPProcessData.Replace("[FileInfo]", _SpecialChars(cur_client->GetUploadFileInfo()));
        //arning this will need totally new PartFile and Knownfile to work
#if 0
        CKnownFile *file = theApp.sharedfiles->GetFileByID(cur_client->GetUploadFileID());
        if (file)
        HTTPProcessData.Replace("[2]", _SpecialChars(wxString(file->GetFileName())));
        else
        HTTPProcessData.Replace("[2]", _GetPlainResString(IDS_REQ_UNKNOWNFILE));
#endif
        fTotalSize += cur_client->GetTransferedDown();
        fTotalTransferred += cur_client->GetTransferedUp();
        wxString HTTPTemp;
        HTTPTemp.Printf("%s / %s", CastItoXBytes(cur_client->GetTransferedDown()) .GetData(), CastItoXBytes(cur_client->GetTransferedUp()) .GetData());
        HTTPProcessData.Replace("[3]", HTTPTemp);
        fTotalSpeed += cur_client->GetDatarate();
        HTTPTemp.Printf("%8.2f " + _GetPlainResString(IDS_KBYTESEC), cur_client->GetDatarate() /1024.0);
        HTTPProcessData.Replace("[4]", HTTPTemp);
        sUpList += HTTPProcessData;
    }
    Out.Replace("[UploadFilesList]", sUpList);
    HTTPTemp.Printf("%s / %s", CastItoXBytes((long long) fTotalSize) .GetData(), CastItoXBytes((long long) fTotalTransferred) .GetData());
    Out.Replace("[TotalUpTransferred]", HTTPTemp);
    HTTPTemp.Printf("%8.2f " + _GetPlainResString(IDS_KBYTESEC), fTotalSpeed/1024.0);
    Out.Replace("[TotalUpSpeed]", HTTPTemp);
    if (pThis->m_Params.bShowUploadQueue)
    {
        Out.Replace("[UploadQueue]", pThis->m_Templates.sTransferUpQueueShow);
        Out.Replace("[UploadQueueList]", _GetPlainResString(IDS_ONQUEUE));
        Out.Replace("[UserNameTitle]", _GetPlainResString(IDS_QL_USERNAME));
        Out.Replace("[FileNameTitle]", _GetPlainResString(IDS_DL_FILENAME));
        Out.Replace("[ScoreTitle]", _GetPlainResString(IDS_SCORE));
        Out.Replace("[BannedTitle]", _GetPlainResString(IDS_BANNED));
        OutE = pThis->m_Templates.sTransferUpQueueLine;
        // Replace [xx]
        wxString sQueue = "";
        for (POSITION pos = theApp.uploadqueue->GetFirstFromWaitingList() ; pos != 0 ; theApp.uploadqueue->GetNextFromWaitingList(pos))
        {
            CUpDownClient *cur_client = theApp.uploadqueue->GetWaitClientAt(pos);
            wxString HTTPProcessData;
            char HTTPTempC[100] = "";
            HTTPProcessData = OutE;
            HTTPProcessData.Replace("[UserName]", _SpecialChars(cur_client->GetUserName()));
            if (cur_client->GetDownloadFile())
            HTTPProcessData.Replace("[FileName]", _SpecialChars(cur_client->GetDownloadFile()->GetFileName()));
            else
            HTTPProcessData.Replace("[FileName]", "?");
            sprintf(HTTPTempC, "%i", cur_client->GetScore(false));
            wxString HTTPTemp = HTTPTempC;
            HTTPProcessData.Replace("[Score]", HTTPTemp);
            if (cur_client->IsBanned())
            HTTPProcessData.Replace("[Banned]", _GetPlainResString(IDS_YES));
            else
            HTTPProcessData.Replace("[Banned]", _GetPlainResString(IDS_NO));
            sQueue += HTTPProcessData;
        }
        Out.Replace("[QueueList]", sQueue);
    }
    else
    {
        Out.Replace("[UploadQueue]", pThis->m_Templates.sTransferUpQueueHide);
    }
    Out.Replace("[ShowQueue]", _GetPlainResString(IDS_WEB_SHOW_UPLOAD_QUEUE));
    Out.Replace("[HideQueue]", _GetPlainResString(IDS_WEB_HIDE_UPLOAD_QUEUE));
    Out.Replace("[Session]", sSession);
    return Out;
}

wxString CWebServer::_GetDownloadLink(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession = _ParseURL(Data.sURL, "ses");
    if (!IsSessionAdmin(Data, sSession)) return "";
    wxString Out = pThis->m_Templates.sDownloadLink;
    Out.Replace("[Download]", _GetPlainResString(IDS_SW_DOWNLOAD));
    Out.Replace("[Ed2klink]", _GetPlainResString(IDS_SW_LINK));
    Out.Replace("[Start]", _GetPlainResString(IDS_SW_START));
    Out.Replace("[Session]", sSession);
    return Out;
}

wxString CWebServer::_GetSharedFilesList(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    wxString sSession = _ParseURL(Data.sURL, "ses");
    if (pThis == NULL)
    return "";
    if (_ParseURL(Data.sURL, "sort") != "")
    {
        if (_ParseURL(Data.sURL, "sort") == "name")
        pThis->m_Params.SharedSort = SHARED_SORT_NAME;
        else
        if (_ParseURL(Data.sURL, "sort") == "size")
        pThis->m_Params.SharedSort = SHARED_SORT_SIZE;
        else
        if (_ParseURL(Data.sURL, "sort") == "transferred")
        pThis->m_Params.SharedSort = SHARED_SORT_TRANSFERRED;
        else
        if (_ParseURL(Data.sURL, "sort") == "alltimetransferred")
        pThis->m_Params.SharedSort = SHARED_SORT_ALL_TIME_TRANSFERRED;
        else
        if (_ParseURL(Data.sURL, "sort") == "requests")
        pThis->m_Params.SharedSort = SHARED_SORT_REQUESTS;
        else
        if (_ParseURL(Data.sURL, "sort") == "alltimerequests")
        pThis->m_Params.SharedSort = SHARED_SORT_ALL_TIME_REQUESTS;
        else
        if (_ParseURL(Data.sURL, "sort") == "accepts")
        pThis->m_Params.SharedSort = SHARED_SORT_ACCEPTS;
        else
        if (_ParseURL(Data.sURL, "sort") == "alltimeaccepts")
        pThis->m_Params.SharedSort = SHARED_SORT_ALL_TIME_ACCEPTS;
        else
        if (_ParseURL(Data.sURL, "sort") == "priority")
        pThis->m_Params.SharedSort = SHARED_SORT_PRIORITY;
        if (_ParseURL(Data.sURL, "sortreverse") == "")
        pThis->m_Params.bSharedSortReverse = false;
    }
    if (_ParseURL(Data.sURL, "sortreverse") != "")
    pThis->m_Params.bSharedSortReverse = (_ParseURL(Data.sURL, "sortreverse") == "true");
    if (_ParseURL(Data.sURL, "hash") != "" &&_ParseURL(Data.sURL, "setpriority") != "" &&IsSessionAdmin(Data, sSession))
    _SetSharedFilePriority(_ParseURL(Data.sURL, "hash"), atoi(_ParseURL(Data.sURL, "setpriority")));
    if (_ParseURL(Data.sURL, "reload") == "true")
    {
        //theApp.xmuledlg->SendMessage(WEB_SHARED_FILES_RELOAD);
        //arning wxPostEvent here
    }
    wxString sSharedSortRev;
    if (pThis->m_Params.bSharedSortReverse)
    sSharedSortRev = "false";
    else
    sSharedSortRev = "true";
    //Name sorting link
    wxString Out = pThis->m_Templates.sSharedList;
    if (pThis->m_Params.SharedSort == SHARED_SORT_NAME)
    Out.Replace("[SortName]", "sort=name&sortreverse=" + sSharedSortRev);
    else
    Out.Replace("[SortName]", "sort=name");
    //Size sorting Link
    if (pThis->m_Params.SharedSort == SHARED_SORT_SIZE)
    Out.Replace("[SortSize]", "sort=size&sortreverse=" + sSharedSortRev);
    else
    Out.Replace("[SortSize]", "sort=size");
    //Priority sorting Link
    if (pThis->m_Params.SharedSort == SHARED_SORT_PRIORITY)
    Out.Replace("[SortPriority]", "sort=priority&sortreverse=" + sSharedSortRev);
    else
    Out.Replace("[SortPriority]", "sort=priority");
    //Transferred sorting link
    if (pThis->m_Params.SharedSort == SHARED_SORT_TRANSFERRED)
    {
        if (pThis->m_Params.bSharedSortReverse)
        Out.Replace("[SortTransferred]", "sort=alltimetransferred&sortreverse=" + sSharedSortRev);
        else
        Out.Replace("[SortTransferred]", "sort=transferred&sortreverse=" + sSharedSortRev);
    }
    else
    if (pThis->m_Params.SharedSort == SHARED_SORT_ALL_TIME_TRANSFERRED)
    {
        if (pThis->m_Params.bSharedSortReverse)
        Out.Replace("[SortTransferred]", "sort=transferred&sortreverse=" + sSharedSortRev);
        else
        Out.Replace("[SortTransferred]", "sort=alltimetransferred&sortreverse=" + sSharedSortRev);
    }
    else
    Out.Replace("[SortTransferred]", "&sort=transferred&sortreverse=false");
    //Request sorting link
    if (pThis->m_Params.SharedSort == SHARED_SORT_REQUESTS)
    {
        if (pThis->m_Params.bSharedSortReverse)
        Out.Replace("[SortRequests]", "sort=alltimerequests&sortreverse=" + sSharedSortRev);
        else
        Out.Replace("[SortRequests]", "sort=requests&sortreverse=" + sSharedSortRev);
    }
    else
    if (pThis->m_Params.SharedSort == SHARED_SORT_ALL_TIME_REQUESTS)
    {
        if (pThis->m_Params.bSharedSortReverse)
        Out.Replace("[SortRequests]", "sort=requests&sortreverse=" + sSharedSortRev);
        else
        Out.Replace("[SortRequests]", "sort=alltimerequests&sortreverse=" + sSharedSortRev);
    }
    else
    Out.Replace("[SortRequests]", "&sort=requests&sortreverse=false");
    //Accepts sorting link
    if (pThis->m_Params.SharedSort == SHARED_SORT_ACCEPTS)
    {
        if (pThis->m_Params.bSharedSortReverse)
        Out.Replace("[SortAccepts]", "sort=alltimeaccepts&sortreverse=" + sSharedSortRev);
        else
        Out.Replace("[SortAccepts]", "sort=accepts&sortreverse=" + sSharedSortRev);
    }
    else
    if (pThis->m_Params.SharedSort == SHARED_SORT_ALL_TIME_ACCEPTS)
    {
        if (pThis->m_Params.bSharedSortReverse)
        Out.Replace("[SortAccepts]", "sort=accepts&sortreverse=" + sSharedSortRev);
        else
        Out.Replace("[SortAccepts]", "sort=alltimeaccepts&sortreverse=" + sSharedSortRev);
    }
    else
    Out.Replace("[SortAccepts]", "&sort=accepts&sortreverse=false");
    if (_ParseURL(Data.sURL, "reload") == "true")
    {
        //arning logtext is private
        //_SpecialChars(theApp.xmuledlg->logtext);	//Pick-up last line of the log:
        wxString resultlog = "";
        //resultlog = resultlog.TrimRight('\n');
        //resultlog = resultlog.Mid(resultlog.ReverseFind('\n'));
        Out.Replace("[Message]", resultlog);
    }
    else
    Out.Replace("[Message]", "");
    Out.Replace("[Filename]", _GetPlainResString(IDS_DL_FILENAME));
    Out.Replace("[Priority]", _GetPlainResString(IDS_PRIORITY));
    Out.Replace("[FileTransferred]", _GetPlainResString(IDS_SF_TRANSFERRED));
    Out.Replace("[FileRequests]", _GetPlainResString(IDS_SF_REQUESTS));
    Out.Replace("[FileAccepts]", _GetPlainResString(IDS_SF_ACCEPTS));
    Out.Replace("[Size]", _GetPlainResString(IDS_DL_SIZE));
    Out.Replace("[Ed2klink]", _GetPlainResString(IDS_SW_LINK));
    Out.Replace("[Reload]", _GetPlainResString(IDS_SF_RELOAD));
    Out.Replace("[Session]", sSession);
    wxString OutE = pThis->m_Templates.sSharedLine;
    OutE.Replace("[Ed2klink]", _GetPlainResString(IDS_SW_LINK));
    OutE.Replace("[PriorityUp]", _GetPlainResString(IDS_PRIORITY_UP));
    OutE.Replace("[PriorityDown]", _GetPlainResString(IDS_PRIORITY_DOWN));
    wxString OutE2 = pThis->m_Templates.sSharedLineChanged;
    OutE.Replace("[Ed2klink]", _GetPlainResString(IDS_SW_LINK));
    OutE.Replace("[PriorityUp]", _GetPlainResString(IDS_PRIORITY_UP));
    OutE.Replace("[PriorityUp]", _GetPlainResString(IDS_PRIORITY_DOWN));
    CArray < SharedFiles *, SharedFiles *> SharedArray;
    // Populating array
    for (int ix = 0 ; ix < theApp.sharedfiles->GetCount() ; ix++)
    {
        CCKey bufKey;
        CKnownFile *cur_file;
        // m_Files_map.GetNextAssoc(pos,bufKey,cur_file);:
        cur_file = theApp.sharedfiles->GetFileByIndex(ix);
        SharedFiles *dFile = new SharedFiles();
        dFile->sFileName = _SpecialChars(cur_file->GetFileName());
        dFile->lFileSize = cur_file->GetFileSize();
        if (theApp.serverconnect->IsConnected())
        dFile->sED2kLink = theApp.CreateED2kSourceLink(cur_file);
        else
        dFile->sED2kLink = theApp.CreateED2kLink(cur_file);
        dFile->nFileTransferred = cur_file->statistic.GetTransfered();
        dFile->nFileAllTimeTransferred = cur_file->statistic.GetAllTimeTransfered();
        dFile->nFileRequests = cur_file->statistic.GetRequests();
        dFile->nFileAllTimeRequests = cur_file->statistic.GetAllTimeRequests();
        dFile->nFileAccepts = cur_file->statistic.GetAccepts();
        dFile->nFileAllTimeAccepts = cur_file->statistic.GetAllTimeAccepts();
        dFile->sFileHash = EncodeBase16(cur_file->GetFileHash(), 16);
        //arning Wonder what IsAutoUpPriority is.. needs newer knownfile to work
#if 0
        if (cur_file->IsAutoUpPriority())
        {
            if (cur_file->GetUpPriority() == PR_NORMAL)
            dFile->sFilePriority = _GetPlainResString(IDS_PRIOAUTONORMAL);
            else if(cur_file->GetUpPriority() == PR_HIGH)
            dFile->sFilePriority = _GetPlainResString(IDS_PRIOAUTOHIGH);
            else if(cur_file->GetUpPriority() == PR_VERYHIGH)
            dFile->sFilePriority = _GetPlainResString(IDS_PRIOAUTORELEASE);
        }
        else
        {
            if (cur_file->GetUpPriority() == PR_VERYLOW)
            dFile->sFilePriority = _GetPlainResString(IDS_PRIOVERYLOW);
            else if(cur_file->GetUpPriority() == PR_LOW)
            dFile->sFilePriority = _GetPlainResString(IDS_PRIOLOW);
            else if(cur_file->GetUpPriority() == PR_NORMAL)
            dFile->sFilePriority = _GetPlainResString(IDS_PRIONORMAL);
            else if(cur_file->GetUpPriority() == PR_HIGH)
            dFile->sFilePriority = _GetPlainResString(IDS_PRIOHIGH);
            else if(cur_file->GetUpPriority() == PR_VERYHIGH)
            dFile->sFilePriority = _GetPlainResString(IDS_PRIORELEASE);
        }
        dFile->nFilePriority = cur_file->GetUpPriority();
        dFile->bFileAutoPriority = cur_file->IsAutoUpPriority();
#endif
        SharedArray.Add(dFile);
    }
    // Sorting (simple bubble sort, we don't have tons of data here)
    bool bSorted = true;
    for (int nMax = 0 ; bSorted &&nMax < SharedArray.GetCount() *2 ; nMax++)
    {
        bSorted = false;
        for (int i = 0 ; i < SharedArray.GetCount() - 1 ; i++)
        {
            bool bSwap = false;
            switch (pThis->m_Params.SharedSort)
            {
            case SHARED_SORT_NAME:
                bSwap = SharedArray[i]->sFileName.CmpNoCase(SharedArray[i + 1]->sFileName) > 0;
                break;
            case SHARED_SORT_SIZE:
                bSwap = SharedArray[i]->lFileSize < SharedArray[i + 1]->lFileSize;
                break;
            case SHARED_SORT_TRANSFERRED:
                bSwap = SharedArray[i]->nFileTransferred < SharedArray[i + 1]->nFileTransferred;
                break;
            case SHARED_SORT_ALL_TIME_TRANSFERRED:
                bSwap = SharedArray[i]->nFileAllTimeTransferred < SharedArray[i + 1]->nFileAllTimeTransferred;
                break;
            case SHARED_SORT_REQUESTS:
                bSwap = SharedArray[i]->nFileRequests < SharedArray[i + 1]->nFileRequests;
                break;
            case SHARED_SORT_ALL_TIME_REQUESTS:
                bSwap = SharedArray[i]->nFileAllTimeRequests < SharedArray[i + 1]->nFileAllTimeRequests;
                break;
            case SHARED_SORT_ACCEPTS:
                bSwap = SharedArray[i]->nFileAccepts < SharedArray[i + 1]->nFileAccepts;
                break;
            case SHARED_SORT_ALL_TIME_ACCEPTS:
                bSwap = SharedArray[i]->nFileAllTimeAccepts < SharedArray[i + 1]->nFileAllTimeAccepts;
                break;
            case SHARED_SORT_PRIORITY:
                //Very low priority is define equal to 4 ! Must adapte sorting code
                if (SharedArray[i]->nFilePriority == 4)
                {
                    if (SharedArray[i + 1]->nFilePriority == 4)
                    bSwap = false;
                    else
                    bSwap = true;
                }
                else
                if (SharedArray[i + 1]->nFilePriority == 4)
                {
                    if (SharedArray[i]->nFilePriority == 4)
                    bSwap = true;
                    else
                    bSwap = false;
                }
                else
                bSwap = SharedArray[i]->nFilePriority < SharedArray[i + 1]->nFilePriority;
                break;
            }
            if (pThis->m_Params.bSharedSortReverse)
            {
                bSwap =!bSwap;
            }
            if (bSwap)
            {
                bSorted = true;
                SharedFiles *TmpFile = SharedArray[i];
                SharedArray[i] = SharedArray[i + 1];
                SharedArray[i + 1] = TmpFile;
            }
        }
    }
    // Displaying
    wxString sSharedList = "";
    for (int i = 0 ; i < SharedArray.GetCount() ; i++)
    {
        char HTTPTempC[100] = "";
        wxString HTTPProcessData;
        if (SharedArray[i]->sFileHash == _ParseURL(Data.sURL, "hash"))
        HTTPProcessData = OutE2;
        else
        HTTPProcessData = OutE;
        HTTPProcessData.Replace("[FileName]", _SpecialChars(SharedArray[i]->sFileName));
        if (SharedArray[i]->sFileName.Length() > SHORT_FILENAME_LENGTH)
        HTTPProcessData.Replace("[ShortFileName]", _SpecialChars(SharedArray[i]->sFileName.Left(SHORT_FILENAME_LENGTH)) + "...");
        else
        HTTPProcessData.Replace("[ShortFileName]", _SpecialChars(SharedArray[i]->sFileName));
        sprintf(HTTPTempC, "%s", CastItoXBytes(SharedArray[i]->lFileSize) .GetData());
        HTTPProcessData.Replace("[FileSize]", wxString(HTTPTempC));
        HTTPProcessData.Replace("[FileLink]", SharedArray[i]->sED2kLink);
        sprintf(HTTPTempC, "%s %s", CastItoXBytes(SharedArray[i]->nFileTransferred) .GetData(), _GetPlainResString(IDS_MBYTES) .GetData());
        HTTPProcessData.Replace("[FileTransferred]", wxString(HTTPTempC));
        sprintf(HTTPTempC, "%s %s ", CastItoXBytes(SharedArray[i]->nFileAllTimeTransferred) .GetData(), _GetPlainResString(IDS_MBYTES) .GetData());
        HTTPProcessData.Replace("[FileAllTimeTransferred]", wxString(HTTPTempC));
        sprintf(HTTPTempC, "%i", SharedArray[i]->nFileRequests);
        HTTPProcessData.Replace("[FileRequests]", wxString(HTTPTempC));
        sprintf(HTTPTempC, "%i", SharedArray[i]->nFileAllTimeRequests);
        HTTPProcessData.Replace("[FileAllTimeRequests]", wxString(HTTPTempC));
        sprintf(HTTPTempC, "%i", SharedArray[i]->nFileAccepts);
        HTTPProcessData.Replace("[FileAccepts]", wxString(HTTPTempC));
        sprintf(HTTPTempC, "%i", SharedArray[i]->nFileAllTimeAccepts);
        HTTPProcessData.Replace("[FileAllTimeAccepts]", wxString(HTTPTempC));
        HTTPProcessData.Replace("[Priority]", SharedArray[i]->sFilePriority);
        HTTPProcessData.Replace("[FileHash]", SharedArray[i]->sFileHash);
        uint8_t upperpriority, lesserpriority;
        if (SharedArray[i]->nFilePriority == 4)
        {
            upperpriority = 0;
            lesserpriority = 4;
        }
        else
        if (SharedArray[i]->nFilePriority == 0)
        {
            upperpriority = 1;
            lesserpriority = 4;
        }
        else
        if (SharedArray[i]->nFilePriority == 1)
        {
            upperpriority = 2;
            lesserpriority = 0;
        }
        else
        if (SharedArray[i]->nFilePriority == 2)
        {
            upperpriority = 3;
            lesserpriority = 1;
        }
        else
        if (SharedArray[i]->nFilePriority == 3)
        {
            upperpriority = 5;
            lesserpriority = 2;
        }
        else
        if (SharedArray[i]->nFilePriority == 5)
        {
            upperpriority = 5;
            lesserpriority = 3;
        }
        if (SharedArray[i]->bFileAutoPriority)
        {
            upperpriority = 5;
            lesserpriority = 3;
        }
        sprintf(HTTPTempC, "%i", upperpriority);
        HTTPProcessData.Replace("[PriorityUpLink]", "hash=" + SharedArray[i]->sFileHash + "&setpriority=" + wxString(HTTPTempC));
        sprintf(HTTPTempC, "%i", lesserpriority);
        HTTPProcessData.Replace("[PriorityDownLink]", "hash=" + SharedArray[i]->sFileHash + "&setpriority=" + wxString(HTTPTempC));
        sSharedList += HTTPProcessData;
    }
    // clear the array
    for (int qq = 0 ; qq < SharedArray.GetCount() ; qq++)
    {
        delete SharedArray[qq];
    }
    Out.Replace("[SharedFilesList]", sSharedList);
    Out.Replace("[Session]", sSession);
    return Out;
}

wxString CWebServer::_GetGraphs(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString Out = pThis->m_Templates.sGraphs;
    XBMDraw drawUp, drawDown;
    drawUp.CreateImage("image_up", WEB_GRAPH_WIDTH, WEB_GRAPH_HEIGHT);
    drawDown.CreateImage("image_down", WEB_GRAPH_WIDTH, WEB_GRAPH_HEIGHT);
    wxString sGraphDownload = "", sGraphUpload = "";
    int nPrevValUp = 0, nPrevValDown = 0;
    for (int i = 0 ; i < WEB_GRAPH_WIDTH ; i++)
    {
        if (i % 4 == 0)
        {
            for (int j = 1 ; j < 6 ; j++)
            {
                drawDown.Plot(i, (WEB_GRAPH_HEIGHT / 6) *j);
                drawUp.Plot(i, (WEB_GRAPH_HEIGHT / 6) *j);
            }
        }
        int nVal;
        if (i < pThis->m_Params.PointsForWeb.GetCount())
        {
            int nI = i;
            if (pThis->m_Params.PointsForWeb.GetCount() < WEB_GRAPH_WIDTH)
            nI = WEB_GRAPH_WIDTH - pThis->m_Params.PointsForWeb.GetCount() + i;
            // download
            nVal = (int)(pThis->m_Params.PointsForWeb[i]->download *WEB_GRAPH_HEIGHT) /
            (theApp.glob_prefs->GetMaxGraphDownloadRate() + 4);
            if (nVal > WEB_GRAPH_HEIGHT)
            nVal = WEB_GRAPH_HEIGHT;
            drawDown.Plot(nI, nVal);
            if (i != 0)
            drawDown.Line(nI - 1, nPrevValDown, nI, nVal);
            nPrevValDown = nVal;
            // upload
            nVal = (int)(pThis->m_Params.PointsForWeb[i]->upload *WEB_GRAPH_HEIGHT) /
            (theApp.glob_prefs->GetMaxGraphUploadRate() + 4);
            if (nVal > WEB_GRAPH_HEIGHT)
            nVal = WEB_GRAPH_HEIGHT;
            drawUp.Plot(nI, nVal);
            if (i != 0)
            drawUp.Line(nI - 1, nPrevValUp, nI, nVal);
            nPrevValUp = nVal;
        }
    }
    wxString sUpC, sDownC;
    drawUp.GetImage(sUpC);
    drawDown.GetImage(sDownC);
    wxString sUp, sDown;
    sUp = sUpC.GetData();
    sDown = sDownC.GetData();
    for (int ix = 0 ; ix < sUp.Length() - 1 ; ix++)
    {
        if (sUp.Mid(ix, 2) .Cmp("0x") == 0)
        {
            if (sUp.GetChar(ix + 3) == ',' ||sUp.GetChar(ix + 3) == ' ')
            {
    /*sUp.Insert(ix+2,'0');*/
                ix += 4;
            }
        }
    }
    for (int ix = 0 ; ix < sDown.Length() - 1 ; ix++)
    {
        if (sDown.Mid(ix, 2) .Cmp("0x") == 0)
        {
            if (sDown.GetChar(ix + 3) == ',' ||sDown.GetChar(ix + 3) == ' ')
            {
    /*sDown.Insert(ix+2,'0');*/
                ix += 4;
            }
        }
    }
    Out.Replace("[GraphDownload]", sDown + drawDown.GetImageTag());
    Out.Replace("[GraphUpload]", sUp + drawUp.GetImageTag());
    Out.Replace("[TxtDownload]", _GetPlainResString(IDS_DOWNLOAD));
    Out.Replace("[TxtUpload]", _GetPlainResString(IDS_PW_CON_UPLBL));
    wxString sScale;
    sScale.Printf("%s %s", _GetPlainResString(IDS_TIME) .GetData(),
    CastSecondsToHM(theApp.glob_prefs->GetTrafficOMeterInterval() *WEB_GRAPH_WIDTH) .GetData());
    wxString s1, s2;
    s1.Printf("%d " + _GetPlainResString(IDS_KBYTESEC) + ", ", theApp.glob_prefs->GetMaxGraphDownloadRate() + 4);
    s2.Printf("%d " + _GetPlainResString(IDS_KBYTESEC) + ", ", theApp.glob_prefs->GetMaxGraphUploadRate() + 4);
    s1 += sScale;
    s2 += sScale;
    Out.Replace("[MaxDownload]", s1);
    Out.Replace("[MaxUpload]", s2);
    return Out;
}

wxString CWebServer::_GetAddServerBox(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession = _ParseURL(Data.sURL, "ses");
    if (!IsSessionAdmin(Data, sSession)) return "";
    wxString Out = pThis->m_Templates.sAddServerBox;
    if (_ParseURL(Data.sURL, "addserver") == "true")
    {
        CServer *nsrv = new CServer(atoi((char *) _ParseURL(Data.sURL, "serverport") .GetData()), (char *) _ParseURL(Data.sURL, "serveraddr") .GetData());
        theApp.serverlist->AddServer(nsrv);
        //arning logtext is private
        //_SpecialChars(theApp.xmuledlg->logtext);	//Pick-up last line of the log:
        wxString resultlog = "";
        //resultlog = resultlog.TrimRight('\n');
        //resultlog = resultlog.Mid(resultlog.ReverseFind('\n'));
        Out.Replace("[Message]", resultlog);
    }
    else
    if (_ParseURL(Data.sURL, "updateservermetfromurl") == "true")
    {
        // uh-oh. this can't succeed....
        //arning FATAL. Trying to call main threads method
        theApp.xmuledlg->serverwnd->UpdateServerMetFromURL(_ParseURL(Data.sURL, "servermeturl"));
        //arning logtext is private
        // _SpecialChars(theApp.xmuledlg->logtext);:
        wxString resultlog = "";
        //resultlog = resultlog.TrimRight('\n');
        //resultlog = resultlog.Mid(resultlog.ReverseFind('\n'));
        Out.Replace("[Message]", resultlog);
    }
    else
    Out.Replace("[Message]", "");
    Out.Replace("[AddServer]", _GetPlainResString(IDS_SV_NEWSERVER));
    Out.Replace("[IP]", _GetPlainResString(IDS_SV_ADDRESS));
    Out.Replace("[Port]", _GetPlainResString(IDS_SV_PORT));
    Out.Replace("[Name]", _GetPlainResString(IDS_SW_NAME));
    Out.Replace("[Add]", _GetPlainResString(IDS_SV_ADD));
    Out.Replace("[UpdateServerMetFromURL]", _GetPlainResString(IDS_SV_MET));
    Out.Replace("[URL]", _GetPlainResString(IDS_SV_URL));
    Out.Replace("[Apply]", _GetPlainResString(IDS_PW_APPLY));
    return Out;
}

wxString CWebServer::_GetWebSearch(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession = _ParseURL(Data.sURL, "ses");
    wxString Out = pThis->m_Templates.sWebSearch;
    if (_ParseURL(Data.sURL, "tosearch") != "")
    {
        wxString query;
        wxString tosearch = _ParseURL(Data.sURL, "tosearch");
        query = "http://www.filedonkey.com/fdsearch/index.php?media=";
        query += _ParseURL(Data.sURL, "media");
        tosearch = URLEncode(tosearch);
        tosearch.Replace("%20", "+");
        query += "&pattern=";
        query += _ParseURL(Data.sURL, "tosearch");
        query += "&action=search&name=FD-Search&op=modload&file=index&requestby=xmule";
        Out += "\n<script language=\"javascript\">";
        Out += "\n searchwindow=window.open('" + query + "','searchwindow');";
        Out += "\n</script>";
    }
    Out.Replace("[Session]", sSession);
    Out.Replace("[WebSearch]", _GetPlainResString(IDS_SW_WEBBASED));
    Out.Replace("[Name]", _GetPlainResString(IDS_SW_NAME));
    Out.Replace("[Type]", _GetPlainResString(IDS_TYPE));
    Out.Replace("[Any]", _GetPlainResString(IDS_SEARCH_ANY));
    Out.Replace("[Audio]", _GetPlainResString(IDS_SEARCH_AUDIO));
    Out.Replace("[Video]", _GetPlainResString(IDS_SEARCH_VIDEO));
    Out.Replace("[Other]", "Other");
    Out.Replace("[Search]", _GetPlainResString(IDS_SW_START));
    return Out;
}

wxString CWebServer::_GetLog(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession = _ParseURL(Data.sURL, "ses");
    wxString Out = pThis->m_Templates.sLog;
    if (_ParseURL(Data.sURL, "clear") == "yes")
    {
        theApp.xmuledlg->ResetLog();
    }
    Out.Replace("[Clear]", _GetPlainResString(IDS_PW_RESET));
    //arning logtext is private
    //Out.Replace("[Log]", _SpecialChars(theApp.xmuledlg->logtext));
    Out.Replace("[Session]", sSession);
    return Out;
}

wxString CWebServer::_GetServerInfo(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession = _ParseURL(Data.sURL, "ses");
    wxString Out = pThis->m_Templates.sServerInfo;
    if (_ParseURL(Data.sURL, "clear") == "yes")
    {
        //arning cant do this
        //theApp.xmuledlg->serverwnd.servermsgbox.SetWindowText("");
    }
    Out.Replace("[Clear]", _GetPlainResString(IDS_PW_RESET));
    //arning cant do this
    //Out.Replace("[ServerInfo]", _SpecialChars(theApp.xmuledlg->serverwnd.servermsgbox.GetHyperText()->GetText()));
    Out.Replace("[Session]", sSession);
    return Out;
}

wxString CWebServer::_GetDebugLog(ThreadData Data)
{
    //arning We dont even have decent debug log
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession = _ParseURL(Data.sURL, "ses");
    wxString Out = pThis->m_Templates.sDebugLog;
    if (_ParseURL(Data.sURL, "clear") == "yes")
    {
        //theApp.xmuledlg->ResetDebugLog();
    }
    Out.Replace("[Clear]", _GetPlainResString(IDS_PW_RESET));
    //Out.Replace("[DebugLog]", _SpecialChars(theApp.xmuledlg->debuglog));
    Out.Replace("[Session]", sSession);
    return Out;
}

wxString CWebServer::_GetStats(ThreadData Data)
{
    printf("***_GetStats arrived\n");
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession = _ParseURL(Data.sURL, "ses");
    // refresh statistics.. ARGH. NO NO NO NO
    // (it will be done in statisticsdlg and in main thread)
    //theApp.xmuledlg->ShowStatistics();
    wxString Out = pThis->m_Templates.sStats;
    Out.Replace("[Stats]", theApp.xmuledlg->statisticswnd->ExportHTML());
    return Out;
}

wxString CWebServer::_GetPreferences(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession = _ParseURL(Data.sURL, "ses");
    wxString Out = pThis->m_Templates.sPreferences;
    Out.Replace("[Session]", sSession);
    if ((_ParseURL(Data.sURL, "saveprefs") == "true") &&IsSessionAdmin(Data, sSession))
    {
        if (_ParseURL(Data.sURL, "gzip") == "true" || _ParseURL(Data.sURL, "gzip") == "on")
        {
            theApp.glob_prefs->SetWebUseGzip(true);
        }
        if (_ParseURL(Data.sURL, "gzip") == "false" || _ParseURL(Data.sURL, "gzip") == "")
        {
            theApp.glob_prefs->SetWebUseGzip(false);
        }
        if (_ParseURL(Data.sURL, "showuploadqueue") == "true" || _ParseURL(Data.sURL, "showuploadqueue") == "on")
        {
            pThis->m_Params.bShowUploadQueue = true;
        }
        if (_ParseURL(Data.sURL, "showuploadqueue") == "false" || _ParseURL(Data.sURL, "showuploadqueue") == "")
        {
            pThis->m_Params.bShowUploadQueue = false;
        }
        if (_ParseURL(Data.sURL, "refresh") != "")
        {
            theApp.glob_prefs->SetWebPageRefresh(atoi(_ParseURL(Data.sURL, "refresh")));
        }
        if (_ParseURL(Data.sURL, "maxdown") != "")
        {
            if (atoi(_ParseURL(Data.sURL, "maxdown")) > 0)
            theApp.glob_prefs->SetMaxDownload(atoi(_ParseURL(Data.sURL, "maxdown")));
            else
            theApp.glob_prefs->SetMaxDownload(65535);
        }
        if (_ParseURL(Data.sURL, "maxup") != "")
        {
            if (atoi(_ParseURL(Data.sURL, "maxup")) > 0)
            theApp.glob_prefs->SetMaxUpload(atoi(_ParseURL(Data.sURL, "maxup")));
            else
            theApp.glob_prefs->SetMaxUpload(65535);
        }
        if (_ParseURL(Data.sURL, "maxcapdown") != "")
        {
            theApp.glob_prefs->SetMaxGraphDownloadRate(atoi(_ParseURL(Data.sURL, "maxcapdown")));
        }
        if (_ParseURL(Data.sURL, "maxcapup") != "")
        {
            theApp.glob_prefs->SetMaxGraphUploadRate(atoi(_ParseURL(Data.sURL, "maxcapup")));
        }
        if (_ParseURL(Data.sURL, "maxsources") != "")
        {
            theApp.glob_prefs->SetMaxSourcesPerFile(atoi(_ParseURL(Data.sURL, "maxsources")));
        }
        if (_ParseURL(Data.sURL, "maxconnections") != "")
        {
            theApp.glob_prefs->SetMaxConnections(atoi(_ParseURL(Data.sURL, "maxconnections")));
        }
        if (_ParseURL(Data.sURL, "maxconnectionsperfive") != "")
        {
            theApp.glob_prefs->SetMaxConsPerFive(atoi(_ParseURL(Data.sURL, "maxconnectionsperfive")));
        }
        theApp.glob_prefs->SetTransferFullChunks((_ParseURL(Data.sURL, "fullchunks") == "on"));
        theApp.glob_prefs->SetPreviewPrio((_ParseURL(Data.sURL, "firstandlast") == "on"));
    }
    // Fill form
    if (theApp.glob_prefs->GetWebUseGzip())
    {
        Out.Replace("[UseGzipVal]", "checked");
    }
    else
    {
        Out.Replace("[UseGzipVal]", "");
    }
    if (pThis->m_Params.bShowUploadQueue)
    {
        Out.Replace("[ShowUploadQueueVal]", "checked");
    }
    else
    {
        Out.Replace("[ShowUploadQueueVal]", "");
    }
    if (theApp.glob_prefs->GetPreviewPrio())
    {
        Out.Replace("[FirstAndLastVal]", "checked");
    }
    else
    {
        Out.Replace("[FirstAndLastVal]", "");
    }
    if (theApp.glob_prefs->TransferFullChunks())
    {
        Out.Replace("[FullChunksVal]", "checked");
    }
    else
    {
        Out.Replace("[FullChunksVal]", "");
    }
    wxString sRefresh;
    sRefresh.Printf("%d", theApp.glob_prefs->GetWebPageRefresh());
    Out.Replace("[RefreshVal]", sRefresh);
    sRefresh.Printf("%d", theApp.glob_prefs->GetMaxSourcePerFile());
    Out.Replace("[MaxSourcesVal]", sRefresh);
    sRefresh.Printf("%d", theApp.glob_prefs->GetMaxConnections());
    Out.Replace("[MaxConnectionsVal]", sRefresh);
    sRefresh.Printf("%d", theApp.glob_prefs->GetMaxConperFive());
    Out.Replace("[MaxConnectionsPer5Val]", sRefresh);
    Out.Replace("[KBS]", _GetPlainResString(IDS_KBYTESEC) + ":");
    Out.Replace("[FileSettings]", wxString(_GetPlainResString(IDS_WEB_FILESETTINGS) + ":"));
    Out.Replace("[LimitForm]", _GetPlainResString(IDS_WEB_CONLIMITS) + ":");
    Out.Replace("[MaxSources]", _GetPlainResString(IDS_PW_MAXSOURCES) + ":");
    Out.Replace("[MaxConnections]", _GetPlainResString(IDS_PW_MAXC) + ":");
    Out.Replace("[MaxConnectionsPer5]", _GetPlainResString(IDS_MAXCON5SECLABEL) + ":");
    Out.Replace("[UseGzipForm]", _GetPlainResString(IDS_WEB_GZIP_COMPRESSION));
    Out.Replace("[UseGzipComment]", _GetPlainResString(IDS_WEB_GZIP_COMMENT));
    Out.Replace("[ShowUploadQueueForm]", _GetPlainResString(IDS_WEB_SHOW_UPLOAD_QUEUE));
    Out.Replace("[ShowUploadQueueComment]", _GetPlainResString(IDS_WEB_UPLOAD_QUEUE_COMMENT));
    Out.Replace("[ShowQueue]", _GetPlainResString(IDS_WEB_SHOW_UPLOAD_QUEUE));
    Out.Replace("[HideQueue]", _GetPlainResString(IDS_WEB_HIDE_UPLOAD_QUEUE));
    Out.Replace("[RefreshTimeForm]", _GetPlainResString(IDS_WEB_REFRESH_TIME));
    Out.Replace("[RefreshTimeComment]", _GetPlainResString(IDS_WEB_REFRESH_COMMENT));
    Out.Replace("[SpeedForm]", _GetPlainResString(IDS_SPEED_LIMITS));
    Out.Replace("[MaxDown]", _GetPlainResString(IDS_DOWNLOAD));
    Out.Replace("[MaxUp]", _GetPlainResString(IDS_PW_CON_UPLBL));
    Out.Replace("[SpeedCapForm]", _GetPlainResString(IDS_CAPACITY_LIMITS));
    Out.Replace("[MaxCapDown]", _GetPlainResString(IDS_DOWNLOAD));
    Out.Replace("[MaxCapUp]", _GetPlainResString(IDS_PW_CON_UPLBL));
    Out.Replace("[TryFullChunks]", _GetPlainResString(IDS_FULLCHUNKTRANS));
    Out.Replace("[FirstAndLast]", _GetPlainResString(IDS_DOWNLOADMOVIECHUNKS));
    Out.Replace("[WebControl]", _GetPlainResString(IDS_WEB_CONTROL));
    Out.Replace("[xMuleAppName]", "xMule");
    Out.Replace("[Apply]", _GetPlainResString(IDS_PW_APPLY));
    wxString sT;
    int n = (int) theApp.glob_prefs->GetMaxDownload();
    if (n < 0 || n == 65535) n = 0;
    sT.Printf("%d", n);
    Out.Replace("[MaxDownVal]", sT);
    n = (int) theApp.glob_prefs->GetMaxUpload();
    if (n < 0 || n == 65535) n = 0;
    sT.Printf("%d", n);
    Out.Replace("[MaxUpVal]", sT);
    sT.Printf("%d", theApp.glob_prefs->GetMaxGraphDownloadRate());
    Out.Replace("[MaxCapDownVal]", sT);
    sT.Printf("%d", theApp.glob_prefs->GetMaxGraphUploadRate());
    Out.Replace("[MaxCapUpVal]", sT);
    return Out;
}

wxString CWebServer::_GetLoginScreen(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession = _ParseURL(Data.sURL, "ses");
    wxString Out = "";
    Out += pThis->m_Templates.sLogin;
    Out.Replace("[CharSet]", _GetWebCharSet());
    Out.Replace("[xMulePlus]", "xMule");
    Out.Replace("[xMuleAppName]", "xMule");
    Out.Replace("[version]", CURRENT_VERSION_LONG);
    Out.Replace("[Login]", _GetPlainResString(IDS_WEB_LOGIN));
    Out.Replace("[EnterPassword]", _GetPlainResString(IDS_WEB_ENTER_PASSWORD));
    Out.Replace("[LoginNow]", _GetPlainResString(IDS_WEB_LOGIN_NOW));
    Out.Replace("[WebControl]", _GetPlainResString(IDS_WEB_CONTROL));
    return Out;
}

wxString CWebServer::_GetConnectedServer(ThreadData Data)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession = _ParseURL(Data.sURL, "ses");
    wxString HTTPTemp = "";
    char HTTPTempC[100] = "";
    wxString OutS = pThis->m_Templates.sConnectedServer;
    OutS.Replace("[ConnectedServer]", _GetPlainResString(IDS_PW_SERVER));
    OutS.Replace("[Servername]", _GetPlainResString(IDS_SL_SERVERNAME));
    OutS.Replace("[Status]", _GetPlainResString(IDS_STATUS));
    OutS.Replace("[Usercount]", _GetPlainResString(IDS_LUSERS));
    OutS.Replace("[Action]", _GetPlainResString(IDS_CONNECTING));
    OutS.Replace("[URL_Disconnect]", IsSessionAdmin(Data, sSession) ?wxString("/?ses=" + sSession + "&w=server&c=disconnect"): GetPermissionDenied());
    OutS.Replace("[URL_Connect]", IsSessionAdmin(Data, sSession) ?wxString("/?ses=" + sSession + "&w=server&c=connect"): GetPermissionDenied());
    OutS.Replace("[Disconnect]", _GetPlainResString(IDS_IRC_DISCONNECT));
    OutS.Replace("[Connect]", _GetPlainResString(IDS_CONNECTTOANYSERVER));
    OutS.Replace("[URL_ServerOptions]", IsSessionAdmin(Data, sSession) ?wxString("/?ses=" + sSession + "&w=server&c=options"): GetPermissionDenied());
    OutS.Replace("[ServerOptions]", wxString(_GetPlainResString(IDS_SERVER) + _GetPlainResString(IDS_EM_PREFS)));
    OutS.Replace("[WebSearch]", _GetPlainResString(IDS_SW_WEBBASED));
    if (theApp.serverconnect->IsConnected())
    {
        if (!theApp.serverconnect->IsLowID())
        OutS.Replace("[1]", _GetPlainResString(IDS_CONNECTED));
        else
        OutS.Replace("[1]", _GetPlainResString(IDS_CONNECTED) + " (" + _GetPlainResString(IDS_IDLOW) + ")");
        CServer *cur_server = theApp.serverconnect->GetCurrentServer();
        OutS.Replace("[2]", wxString(cur_server->GetListName()));
        sprintf(HTTPTempC, "%10i", cur_server->GetUsers());
        HTTPTemp = HTTPTempC;
        OutS.Replace("[3]", HTTPTemp);
    }
    else if(theApp.serverconnect->IsConnecting())
    {
        OutS.Replace("[1]", _GetPlainResString(IDS_CONNECTING));
        OutS.Replace("[2]", "");
        OutS.Replace("[3]", "");
    }
    else
    {
        OutS.Replace("[1]", _GetPlainResString(IDS_DISCONNECTED));
        OutS.Replace("[2]", "");
        OutS.Replace("[3]", "");
    }
    return OutS;
}

// We have to add gz-header and some other stuff
// to standard zlib functions
// in order to use gzip in web pages
int CWebServer::_GzipCompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)
{
    const static int gz_magic[2] =
    {
        0x1f, 0x8b
        // gzip magic header:
        };
    int err;
    uLong crc;
    z_stream stream =
    {
        0
        };
    stream.zalloc = (alloc_func) 0;
    stream.zfree = (free_func) 0;
    stream.opaque = (voidpf) 0;
    crc = crc32(0L, Z_NULL, 0);
    // init Zlib stream
    // NOTE windowBits is passed < 0 to suppress zlib header
    err = deflateInit2( &stream, level, Z_DEFLATED, - MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
    if (err != Z_OK)
    return err;
    sprintf((char *) dest, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
    Z_DEFLATED, 0 /*flags*/
    , 0, 0, 0, 0 /*time*/
    , 0 /*xflags*/
    , 255);
    // wire buffers
    stream.next_in = (Bytef *) source;
    stream.avail_in = (uInt) sourceLen;
    stream.next_out = ((Bytef *) dest) + 10;
    stream.avail_out = *destLen - 18;
    // doit
    err = deflate( &stream, Z_FINISH);
    if (err != Z_STREAM_END)
    {
        deflateEnd( &stream);
        return err;
    }
    err = deflateEnd( &stream);
    crc = crc32(crc, (const Bytef *) source, sourceLen);
    //CRC
    * (((Bytef *) dest) + 10 + stream.total_out) = (Bytef)(crc &0xFF);
    * (((Bytef *) dest) + 10 + stream.total_out + 1) = (Bytef)((crc >> 8) &0xFF);
    * (((Bytef *) dest) + 10 + stream.total_out + 2) = (Bytef)((crc >> 16) &0xFF);
    * (((Bytef *) dest) + 10 + stream.total_out + 3) = (Bytef)((crc >> 24) &0xFF);
    // Length
    * (((Bytef *) dest) + 10 + stream.total_out + 4) = (Bytef)(sourceLen &0xFF);
    * (((Bytef *) dest) + 10 + stream.total_out + 5) = (Bytef)((sourceLen >> 8) &0xFF);
    * (((Bytef *) dest) + 10 + stream.total_out + 6) = (Bytef)((sourceLen >> 16) &0xFF);
    * (((Bytef *) dest) + 10 + stream.total_out + 7) = (Bytef)((sourceLen >> 24) &0xFF);
    // return  destLength
    *destLen = 10 + stream.total_out + 8;
    return err;
}

bool CWebServer::_IsLoggedIn(ThreadData Data, long lSession)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    _RemoveTimeOuts(Data, lSession);
    // find our session
    // i should have used CMap there, but i like CArray more ;-)
    for (int i = 0 ; i < pThis->m_Params.Sessions.GetSize() ; i++)
    {
        if (pThis->m_Params.Sessions[i]->lSession == lSession &&lSession != 0)
        {
            // if found, also reset expiration time
            pThis->m_Params.Sessions[i]->startTime = time(NULL);
            return true;
        }
    }
    return false;
}

void CWebServer::_RemoveTimeOuts(ThreadData Data, long lSession)
{
    // remove expired sessions
    CWebServer *pThis = (CWebServer *) Data.pThis;
    pThis->UpdateSessionCount();
}

bool CWebServer::_RemoveSession(ThreadData Data, long lSession)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    // find our session
    for (int i = 0 ; i < pThis->m_Params.Sessions.GetSize() ; i++)
    {
        if (pThis->m_Params.Sessions[i]->lSession == lSession &&lSession != 0)
        {
            // delete it!!!!!!!
            pThis->m_Params.Sessions.RemoveAt(i);
            // DONT!!
            //theApp.xmuledlg->AddLogLine(true,GetResString(IDS_WEB_SESSIONEND),lSession);
            return true;
        }
    }
    return false;
}

Session CWebServer::GetSessionByID(ThreadData Data, long sessionID)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis != NULL)
    {
        for (int i = 0 ; i < pThis->m_Params.Sessions.GetSize() ; i++)
        {
            if (pThis->m_Params.Sessions[i]->lSession == sessionID &&sessionID != 0)
            return * (pThis->m_Params.Sessions.GetAt(i));
        }
    }
    Session ses;
    ses.admin = false;
    ses.startTime = 0;
    return ses;
}

bool CWebServer::IsSessionAdmin(ThreadData Data, wxString SsessionID)
{
    long sessionID = atoll(SsessionID);
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis != NULL)
    {
        for (int i = 0 ; i < pThis->m_Params.Sessions.GetSize() ; i++)
        {
            if (pThis->m_Params.Sessions[i]->lSession == sessionID &&sessionID != 0)
            return pThis->m_Params.Sessions[i]->admin;
        }
    }
    return false;
}

wxString CWebServer::GetPermissionDenied()
{
    return "javascript:alert(\'" + _GetPlainResString(IDS_ACCESSDENIED) + "\')";
}

bool CWebServer::_GetFileHash(wxString sHash, unsigned char *FileHash)
{
    char hex_byte[3];
    int byte;
    hex_byte[2] = '\0';
    for (int i = 0 ; i < 16 ; i++)
    {
        hex_byte[0] = sHash.GetChar(i *2);
        hex_byte[1] = sHash.GetChar((i *2 + 1));
        sscanf(hex_byte, "%02x", &byte);
        FileHash[i] = (unsigned char) byte;
    }
    return true;
}

wxString CWebServer::_GetPlainResString(UINT nID, bool noquot)
{
    wxString sRet = GetResString(nID);
    sRet.Replace("&", "");
    if (noquot)
    {
        sRet.Replace("'", "\\'");
        sRet.Replace("\n", "\\n");
    }
    return sRet;
}

// EC + kuchin
wxString CWebServer::_GetWebCharSet()
{
#if 0
    switch (theApp.glob_prefs->GetLanguageID())
    {
    case MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT): return "windows-1250";
    case MAKELANGID(LANG_RUSSIAN, SUBLANG_DEFAULT): return "windows-1251";
    case MAKELANGID(LANG_GREEK, SUBLANG_DEFAULT): return "ISO-8859-7";
    case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT): return "ISO-8859-8";
    case MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT): return "EUC-KR";
    case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED): return "GB2312";
    case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL): return "Big5";
    case MAKELANGID(LANG_LITHUANIAN, SUBLANG_DEFAULT): return "windows-1257";
    }
#endif
    // Western (Latin) includes Catalan, Danish, Dutch, English, Faeroese, Finnish, French,
    // German, Galician, Irish, Icelandic, Italian, Norwegian, Portuguese, Spanish and Swedish
    return "ISO-8859-1";
}

// Ornis: creating the progressbar. colored if ressources are given/available
wxString CWebServer::_GetDownloadGraph(ThreadData Data, wxString filehash)
{
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    CPartFile *cur_file;
    unsigned char fileid[16];
    DecodeBase16(filehash.GetData(), filehash.Length(), fileid);
    cur_file = theApp.downloadqueue->GetFileByID(fileid);
    wxString resPath = pThis->m_Templates.sResDir;
    if (resPath == "" &&wxFileName::FileExists(wxString(theApp.glob_prefs->GetAppDir()) + "webserver/black.gif"))
    {
        resPath.Printf("file://%swebserver/", theApp.glob_prefs->GetAppDir());
        resPath.Replace("\\", "/");
    }
    wxString Out = "";
    // simple style if ressources cant be found
    if (resPath == "")
    {
        XBMDraw bar;
        int proc = (int) cur_file->GetPercentCompleted();
        if (proc < 0) proc = 0;
        if (proc > 100) proc = 100;
        int size = (int)((float) proc/ (float) 100) * (pThis->m_Templates.iProgressbarWidth);
        if (proc > 0) bar.CreateImage("img_progressbar", size, 10, 255);
        else bar.CreateImage("img_progressbar", 8, 10, 0);
        wxString sBar;
        wxString sBarC;
        bar.GetImage(sBarC);
        sBar = sBarC.GetData();
        for (int ix = 0 ; ix < sBar.Length() - 1 ; ix++)
        {
            if (sBar.Mid(ix, 2) .Cmp("0x") == 0)
            {
                //arning no insert in wxstring
                if (sBar.GetChar(ix + 3) == ',' ||sBar.GetChar(ix + 3) == ' ')
                {
    /*sBar.Insert(ix+2,'0');*/
                    ix += 4;
                }
            }
        }
        Out.Printf("%s\n<img src=\"javascript:img_progressbar\">", sBar.GetData());
        // cool style
    }
    else
    {
        wxString progresscolor[7];
        progresscolor[0] = "green.gif";
        progresscolor[1] = "black.gif";
        progresscolor[2] = "yellow.gif";
        progresscolor[3] = "blue.gif";
        progresscolor[4] = "red.gif";
        progresscolor[5] = "greenpercent.gif";
        progresscolor[6] = "transparent.gif";
        //arning PartFile needs work.
        wxString s_ChunkBar = cur_file->GetProgressString(pThis->m_Templates.iProgressbarWidth);
        // and now make a graph out of the array - need to be in a progressive way
        uint8_t lastcolor = 1;
        uint16_t lastindex = 0;
        wxString temp;
        for (uint16_t i = 0 ; i < pThis->m_Templates.iProgressbarWidth ; i++)
        {
            if (lastcolor != atoi(s_ChunkBar.Mid(i, 1)))
            {
                if (i > lastindex)
                {
                    //temp.Printf("<img src=\"%s%s\" height=10 width=%i>",resPath.GetData(),progresscolor[lastcolor].GetData(),i-lastindex);
                    temp.Printf("<img src=\"%s\" height=10 width=%i>", progresscolor[lastcolor].GetData(), i - lastindex);
                    Out += temp;
                }
                lastcolor = atoi(s_ChunkBar.Mid(i, 1));
                lastindex = i;
            }
        }
        //temp.Printf("<img src=\"%s%s\" height=10 width=%i>",resPath.GetData(),progresscolor[lastcolor].GetData(),pThis->m_Templates.iProgressbarWidth-lastindex);
        temp.Printf("<img src=\"%s\" height=10 width=%i>", progresscolor[lastcolor].GetData(), pThis->m_Templates.iProgressbarWidth - lastindex);
        Out += temp;
        int complx = (int)((pThis->m_Templates.iProgressbarWidth/100) *cur_file->GetPercentCompleted());
        //if(complx>0) temp.Printf("<img src=\"%s%s\" height=3 width=%i><br>",resPath.GetData(),progresscolor[5].GetData(),complx);
        //else temp.Printf("<img src=\"%s%s\" height=3 width=5><br>",resPath.GetData(),progresscolor[6].GetData());
        if (complx > 0) temp.Printf("<img src=\"%s\" height=3 width=%i><br>", progresscolor[5].GetData(), complx);
        else temp.Printf("<img src=\"%s\" height=3 width=5><br>", progresscolor[6].GetData());
        Out = temp + Out;
    }
    return Out;
}

wxString CWebServer::_GetSearch(ThreadData Data)
{
#if 0
    CWebServer *pThis = (CWebServer *) Data.pThis;
    if (pThis == NULL)
    return "";
    wxString sSession = _ParseURL(Data.sURL, "ses");
    wxString Out = pThis->m_Templates.sSearch;
    if (_ParseURL(Data.sURL, "downloads") != "" &&IsSessionAdmin(Data, sSession))
    {
        wxString downloads = _ParseURLArray(Data.sURL, "downloads");
        wxString resToken;
        int curPos = 0;
        resToken = downloads.Tokenize("|", curPos);
        while (resToken != "")
        {
            unsigned char fileid[16];
            DecodeBase16(resToken.GetBuffer(), resToken.GetLength(), fileid);
            //theApp.search list->AddFileToDownloadByHash(fileid);
            resToken = downloads.Tokenize("|", curPos);
        }
    }
    if (_ParseURL(Data.sURL, "tosearch") != "" &&IsSessionAdmin(Data, sSession))
    {
        // perform search
        theApp.xmuledlg->searchwnd.DeleteAllSearchs();
        theApp.xmuledlg->searchwnd.DoNewSearch(
        _ParseURL(Data.sURL, "tosearch"),
        _ParseURL(Data.sURL, "type"),
        atol(_ParseURL(Data.sURL, "min")) *1048576,
        atol(_ParseURL(Data.sURL, "max")) *1048576,
        atoi(_ParseURL(Data.sURL, "avail")),
        _ParseURL(Data.sURL, "ext"),
        (_ParseURL(Data.sURL, "global") == "on")
        );
        Out.Replace("[Message]", _GetPlainResString(IDS_SW_SEARCHINGINFO));
    }
    else if(_ParseURL(Data.sURL, "tosearch") != "" && !IsSessionAdmin(Data, sSession))
    {
        Out.Replace("[Message]", _GetPlainResString(IDS_ACCESSDENIED));
    }
    else Out.Replace("[Message]", "");
    wxString result = pThis->m_Templates.sSearchHeader + theApp.search list->GetWebList(pThis->m_Templates.sSearchResultLine);
    Out.Replace("[SEARCHINFOMSG]", "");
    Out.Replace("[RESULTLIST]", result);
    Out.Replace("[Result]", GetResString(IDS_SW_RESULT));
    Out.Replace("[Session]", sSession);
    Out.Replace("[WebSearch]", _GetPlainResString(IDS_SW_WEBBASED));
    Out.Replace("[Name]", _GetPlainResString(IDS_SW_NAME));
    Out.Replace("[Type]", _GetPlainResString(IDS_TYPE));
    Out.Replace("[Any]", _GetPlainResString(IDS_SEARCH_ANY));
    Out.Replace("[Audio]", _GetPlainResString(IDS_SEARCH_AUDIO));
    Out.Replace("[Image]", _GetPlainResString(IDS_SEARCH_PICS));
    Out.Replace("[Video]", _GetPlainResString(IDS_SEARCH_VIDEO));
    Out.Replace("[Other]", "Other");
    Out.Replace("[Search]", _GetPlainResString(IDS_SW_SEARCHBOX));
    Out.Replace("[RefetchResults]", _GetPlainResString(IDS_SW_REFETCHRES));
    Out.Replace("[Download]", _GetPlainResString(IDS_DOWNLOAD));
    Out.Replace("[Filesize]", _GetPlainResString(IDS_DL_SIZE));
    Out.Replace("[Sources]", _GetPlainResString(IDS_DL_SOURCES));
    Out.Replace("[Filehash]", _GetPlainResString(IDS_FILEHASH));
    Out.Replace("[Filename]", _GetPlainResString(IDS_DL_FILENAME));
    Out.Replace("[WebSearch]", _GetPlainResString(IDS_SW_WEBBASED));
    Out.Replace("[SizeMin]", _GetPlainResString(IDS_SEARCHMINSIZE));
    Out.Replace("[SizeMax]", _GetPlainResString(IDS_SEARCHMAXSIZE));
    Out.Replace("[Availabl]", _GetPlainResString(IDS_SEARCHAVAIL));
    Out.Replace("[Extention]", _GetPlainResString(IDS_SEARCHEXTENTION));
    Out.Replace("[Global]", _GetPlainResString(IDS_GLOBALSEARCH2));
    Out.Replace("[MB]", _GetPlainResString(IDS_MBYTES));
    return Out;
#endif
    return "";
}

int CWebServer::UpdateSessionCount()
{
    int oldvalue = m_Params.Sessions.GetSize();
    for (int i = 0 ; i < m_Params.Sessions.GetSize() ;)
    {
        //CTimeSpan ts = CTime::GetCurrentTime() - m_Params.Sessions[i].startTime;
        time_t ts = time(NULL) - m_Params.Sessions[i]->startTime;
        if (ts > SESSION_TIMEOUT_SECS)
        {
            m_Params.Sessions.RemoveAt(i);
        }
        else
        i++;
    }
    if (oldvalue != m_Params.Sessions.GetSize()) theApp.xmuledlg->serverwnd->UpdateMyInfo();
    return m_Params.Sessions.GetCount();
}

