home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 217 / DPCS0306DVD.ISO / Toolkit / Internet / FileZilla / Server / FileZilla_Server-0.9.11.exe / source / Options.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2005-08-21  |  36.5 KB  |  1,580 lines

  1. // FileZilla Server - a Windows ftp server
  2.  
  3. // Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>
  4.  
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9.  
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14.  
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. // Options.cpp: Implementierungsdatei
  20. //
  21.  
  22. #include "stdafx.h"
  23. #include "options.h"
  24. #include "platform.h"
  25. #include "version.h"
  26. #include "misc\MarkupSTL.h"
  27. #include "iputils.h"
  28.  
  29. #ifdef _DEBUG
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #endif
  33.  
  34. std::list<COptions *> COptions::m_InstanceList;
  35. CCriticalSectionWrapper COptions::m_Sync;
  36. COptions::t_OptionsCache COptions::m_sOptionsCache[OPTIONS_NUM];
  37. BOOL COptions::m_bInitialized=FALSE;
  38.  
  39. SPEEDLIMITSLIST COptions::m_sDownloadSpeedLimits;
  40. SPEEDLIMITSLIST COptions::m_sUploadSpeedLimits;
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // COptionsHelperWindow
  44.  
  45. class COptionsHelperWindow
  46. {
  47. public:
  48.     COptionsHelperWindow(COptions *pOptions)
  49.     {
  50.         ASSERT(pOptions);
  51.         m_pOptions=pOptions;
  52.  
  53.         //Create window
  54.         WNDCLASSEX wndclass;
  55.         wndclass.cbSize=sizeof wndclass;
  56.         wndclass.style=0;
  57.         wndclass.lpfnWndProc=WindowProc;
  58.         wndclass.cbClsExtra=0;
  59.         wndclass.cbWndExtra=0;
  60.         wndclass.hInstance=GetModuleHandle(0);
  61.         wndclass.hIcon=0;
  62.         wndclass.hCursor=0;
  63.         wndclass.hbrBackground=0;
  64.         wndclass.lpszMenuName=0;
  65.         wndclass.lpszClassName=_T("COptions Helper Window");
  66.         wndclass.hIconSm=0;
  67.  
  68.         RegisterClassEx(&wndclass);
  69.  
  70.         m_hWnd=CreateWindow(_T("COptions Helper Window"), _T("COptions Helper Window"), 0, 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0));
  71.         ASSERT(m_hWnd);
  72.         SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG)this);
  73.     };
  74.  
  75.     virtual ~COptionsHelperWindow()
  76.     {
  77.         //Destroy window
  78.         if (m_hWnd)
  79.         {
  80.             DestroyWindow(m_hWnd);
  81.             m_hWnd=0;
  82.         }
  83.     }
  84.  
  85.     HWND GetHwnd()
  86.     {
  87.         return m_hWnd;
  88.     }
  89.  
  90. protected:
  91.     static LRESULT CALLBACK WindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
  92.     {
  93.         if (message==WM_USER)
  94.         {
  95.             COptionsHelperWindow *pWnd=(COptionsHelperWindow *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  96.             if (!pWnd)
  97.                 return 0;
  98.             ASSERT(pWnd);
  99.             ASSERT(pWnd->m_pOptions);
  100.             for (int i=0;i<OPTIONS_NUM;i++)
  101.                 pWnd->m_pOptions->m_OptionsCache[i].bCached = FALSE;
  102.             EnterCritSection(COptions::m_Sync);
  103.             pWnd->m_pOptions->m_DownloadSpeedLimits = COptions::m_sDownloadSpeedLimits;
  104.             pWnd->m_pOptions->m_UploadSpeedLimits = COptions::m_sUploadSpeedLimits;
  105.             LeaveCritSection(COptions::m_Sync);
  106.         }
  107.         return ::DefWindowProc(hWnd, message, wParam, lParam);
  108.     }
  109.     COptions *m_pOptions;
  110.  
  111. private:
  112.     HWND m_hWnd;
  113. };
  114.  
  115. /////////////////////////////////////////////////////////////////////////////
  116. // Dialogfeld COptions
  117.  
  118. COptions::COptions()
  119. {
  120.     for (int i=0;i<OPTIONS_NUM;i++)
  121.         m_OptionsCache[i].bCached=FALSE;
  122.     m_pOptionsHelperWindow=new COptionsHelperWindow(this);
  123.     EnterCritSection(m_Sync);
  124. #ifdef _DEBUG
  125.     for (std::list<COptions *>::iterator iter=m_InstanceList.begin(); iter!=m_InstanceList.end(); iter++)
  126.         ASSERT(*iter!=this);
  127. #endif _DEBUG
  128.     m_InstanceList.push_back(this);
  129.     m_DownloadSpeedLimits = m_sDownloadSpeedLimits;
  130.     m_UploadSpeedLimits = m_sUploadSpeedLimits;
  131.     LeaveCritSection(m_Sync);
  132. }
  133.  
  134. COptions::~COptions()
  135. {
  136.     EnterCritSection(m_Sync);
  137.     std::list<COptions *>::iterator iter;
  138.     for (iter=m_InstanceList.begin(); iter!=m_InstanceList.end(); iter++)
  139.         if (*iter==this)
  140.             break;
  141.  
  142.     ASSERT(iter!=m_InstanceList.end());
  143.     m_InstanceList.erase(iter);
  144.     LeaveCritSection(m_Sync);
  145.  
  146.     if (m_pOptionsHelperWindow)
  147.         delete m_pOptionsHelperWindow;
  148.     m_pOptionsHelperWindow=0;
  149. }
  150.  
  151. void COptions::SetOption(int nOptionID, _int64 value)
  152. {
  153.     switch (nOptionID)
  154.     {
  155.     case OPTION_MAXUSERS:
  156.         if (value<0)
  157.             value=0;
  158.         break;
  159.     case OPTION_THREADNUM:
  160.         if (value<1)
  161.             value=2;
  162.         else if (value>50)
  163.             value=2;
  164.         break;
  165.     case OPTION_TIMEOUT:
  166.     case OPTION_NOTRANSFERTIMEOUT:
  167.         if (value<0)
  168.             value=120;
  169.         else if (value>9999)
  170.             value=120;
  171.         break;
  172.     case OPTION_LOGINTIMEOUT:
  173.         if (value<0)
  174.             value=60;
  175.         else if (value>9999)
  176.             value=60;
  177.         break;
  178.     case OPTION_ADMINPORT:
  179.         if (value>65535)
  180.             value=14147;
  181.         else if (value<1)
  182.             value=14147;
  183.         break;
  184.     case OPTION_LOGTYPE:
  185.         if (value!=0 && value!=1)
  186.             value = 0;
  187.         break;
  188.     case OPTION_LOGLIMITSIZE:
  189.         if ((value > 999999 || value < 10) && value!=0)
  190.             value = 100;
  191.         break;
  192.     case OPTION_LOGDELETETIME:
  193.         if (value > 999 || value < 0)
  194.             value = 14;
  195.         break;
  196.     case OPTION_DOWNLOADSPEEDLIMITTYPE:
  197.     case OPTION_UPLOADSPEEDLIMITTYPE:
  198.         if (value < 0 || value > 2)
  199.             value = 0;
  200.         break;
  201.     case OPTION_DOWNLOADSPEEDLIMIT:
  202.     case OPTION_UPLOADSPEEDLIMIT:
  203.         if (value > 65535 || value < 1)
  204.             value = 10;
  205.         break;
  206.     case OPTION_BUFFERSIZE:
  207.         if (value < 256 || value > (1024*1024))
  208.             value = 32768;
  209.         break;
  210.     case OPTION_BUFFERSIZE2:
  211.         if (value < 256 || value > (1024*1024))
  212.             value = 65536;
  213.         break;
  214.     case OPTION_CUSTOMPASVIPTYPE:
  215.         if (value < 0 || value > 2)
  216.             value = 0;
  217.         break;
  218.     case OPTION_MODEZ_USE:
  219.         if (value < 0 || value > 1)
  220.             value = 0;
  221.         break;
  222.     case OPTION_MODEZ_LEVELMIN:
  223.         if (value < 0 || value > 8)
  224.             value = 1;
  225.         break;
  226.     case OPTION_MODEZ_LEVELMAX:
  227.         if (value < 8 || value > 9)
  228.             value = 9;
  229.         break;
  230.     case OPTION_MODEZ_ALLOWLOCAL:
  231.         if (value < 0 || value > 1)
  232.             value = 0;
  233.         break;
  234.     }
  235.  
  236.     Init();
  237.  
  238.     EnterCritSection(m_Sync);
  239.     m_sOptionsCache[nOptionID-1].nType = 1;
  240.     m_sOptionsCache[nOptionID-1].value = value;
  241.     m_sOptionsCache[nOptionID-1].bCached = TRUE;
  242.     m_OptionsCache[nOptionID-1] = m_sOptionsCache[nOptionID-1];
  243.  
  244.     LeaveCritSection(m_Sync);
  245.  
  246.     TCHAR buffer[MAX_PATH + 1000]; //Make it large enough
  247.     GetModuleFileName( 0, buffer, MAX_PATH );
  248.     LPTSTR pos=_tcsrchr(buffer, '\\');
  249.     if (pos)
  250.         *++pos=0;
  251.     _tcscat(buffer, _T("FileZilla Server.xml"));
  252.     CMarkupSTL xml;
  253.     if (!xml.Load(buffer))
  254.         return;
  255.  
  256.     if (!xml.FindElem( _T("FileZillaServer") ))
  257.         return;
  258.  
  259.     if (!xml.FindChildElem( _T("Settings") ))
  260.         xml.AddChildElem( _T("Settings") );
  261.  
  262.     CStdString valuestr;
  263.     valuestr.Format( _T("%I64d"), value);
  264.     xml.IntoElem();
  265.     BOOL res = xml.FindChildElem();
  266.     while (res)
  267.     {
  268.         CStdString name=xml.GetChildAttrib( _T("name"));
  269.         if (!_tcscmp(name, m_Options[nOptionID-1].name))
  270.         {
  271.             xml.SetChildAttrib(_T("name"), m_Options[nOptionID-1].name);
  272.             xml.SetChildAttrib(_T("type"), _T("numeric"));
  273.             xml.SetChildData(valuestr);
  274.             break;
  275.         }
  276.         res=xml.FindChildElem();
  277.     }
  278.     if (!res)
  279.     {
  280.         xml.InsertChildElem(_T("Item"), valuestr);
  281.         xml.SetChildAttrib(_T("name"), m_Options[nOptionID-1].name);
  282.         xml.SetChildAttrib(_T("type"), _T("numeric"));
  283.     }
  284.     xml.Save(buffer);
  285. }
  286.  
  287. void COptions::SetOption(int nOptionID, LPCTSTR value)
  288. {
  289.     CStdString str = value;
  290.     Init();
  291.  
  292.     switch (nOptionID)
  293.     {
  294.     case OPTION_SERVERPORT:
  295.     case OPTION_SSLPORTS:
  296.         {
  297.             std::set<int> portSet;
  298.             
  299.             str.TrimLeft(" ,");
  300.  
  301.             int pos = str.FindOneOf(_T(" ,"));
  302.             while (pos != -1)
  303.             {
  304.                 int port = atoi(str.Left(pos));
  305.                 if (port >= 1 && port <= 65535)
  306.                     portSet.insert(port);
  307.                 str = str.Mid(pos + 1);
  308.                 str.TrimLeft(" ,");
  309.                 pos = str.FindOneOf(_T(" ,"));
  310.             }
  311.             if (str != "")
  312.             {
  313.                 int port = atoi(str);
  314.                 if (port >= 1 && port <= 65535)
  315.                     portSet.insert(port);
  316.             }
  317.  
  318.             str = "";
  319.             for (std::set<int>::const_iterator iter = portSet.begin(); iter != portSet.end(); iter++)
  320.             {
  321.                 CStdString tmp;
  322.                 tmp.Format("%d ", *iter);
  323.                 str += tmp;
  324.             }
  325.             str.TrimRight(' ');
  326.         }
  327.         break;
  328.     case OPTION_WELCOMEMESSAGE:
  329.         {
  330.             std::vector<CStdString> msgLines;
  331.             int oldpos=0;
  332.             str.Replace("\r\n", "\n");
  333.             int pos=str.Find("\n");
  334.             CStdString line;
  335.             while (pos!=-1)
  336.             {
  337.                 if (pos)
  338.                 {
  339.                     line = str.Mid(oldpos, pos-oldpos);
  340.                     line = line.Left(CONST_WELCOMEMESSAGE_LINESIZE);
  341.                     line.TrimRight(" ");
  342.                     if (msgLines.size() || line!="")
  343.                         msgLines.push_back(line);
  344.                 }
  345.                 oldpos=pos+1;
  346.                 pos=str.Find("\n", oldpos);
  347.             }
  348.             line=str.Mid(oldpos);
  349.             if (line!="")
  350.             {
  351.                 line=line.Left(CONST_WELCOMEMESSAGE_LINESIZE);
  352.                 msgLines.push_back(line);
  353.             }
  354.             str="";
  355.             for (unsigned int i=0;i<msgLines.size();i++)
  356.                 str+=msgLines[i]+"\r\n";
  357.             str.TrimRight("\r\n");
  358.             if (str=="")
  359.             {
  360.                 str="%v";
  361.                 str+="\r\nwritten by Tim Kosse (Tim.Kosse@gmx.de)";
  362.                 str+="\r\nPlease visit http://sourceforge.net/projects/filezilla/";
  363.             }
  364.         }
  365.         break;
  366.     case OPTION_ADMINIPBINDINGS:
  367.         {
  368.             CStdString sub;
  369.             std::list<CStdString> ipBindList;
  370.             for (unsigned int i = 0; i<_tcslen(value); i++)
  371.             {
  372.                 char cur = value[i];
  373.                 if ((cur<'0' || cur>'9') && cur!='.')
  374.                 {
  375.                     if (sub=="" && cur=='*')
  376.                     {
  377.                         ipBindList.clear();
  378.                         ipBindList.push_back("*");
  379.                         break;
  380.                     }
  381.  
  382.                     if (sub != "")
  383.                     {
  384.                         //Parse IP
  385.                         SOCKADDR_IN sockAddr;
  386.                         memset(&sockAddr,0,sizeof(sockAddr));
  387.  
  388.                         sockAddr.sin_family = AF_INET;
  389.                         sockAddr.sin_addr.s_addr = inet_addr(sub);
  390.  
  391.                         if (sockAddr.sin_addr.s_addr != INADDR_NONE)
  392.                         {
  393.                             sub = inet_ntoa(sockAddr.sin_addr);
  394.                             std::list<CStdString>::iterator iter;
  395.                             for (iter = ipBindList.begin(); iter!=ipBindList.end(); iter++)
  396.                                 if (*iter==sub)
  397.                                     break;
  398.                             if (iter == ipBindList.end())
  399.                                 ipBindList.push_back(sub);
  400.                         }
  401.                         sub = "";
  402.                     }
  403.                 }
  404.                 else
  405.                     sub += cur;
  406.             }
  407.             if (sub != "")
  408.             {
  409.                 //Parse IP
  410.                 SOCKADDR_IN sockAddr;
  411.                 memset(&sockAddr,0,sizeof(sockAddr));
  412.  
  413.                 sockAddr.sin_family = AF_INET;
  414.                 sockAddr.sin_addr.s_addr = inet_addr(sub);
  415.  
  416.                 if (sockAddr.sin_addr.s_addr != INADDR_NONE)
  417.                 {
  418.                     sub = inet_ntoa(sockAddr.sin_addr);
  419.                     std::list<CStdString>::iterator iter;
  420.                     for (iter = ipBindList.begin(); iter!=ipBindList.end(); iter++)
  421.                         if (*iter==sub)
  422.                             break;
  423.                     if (iter == ipBindList.end())
  424.                         ipBindList.push_back(sub);
  425.                 }
  426.                 sub = "";
  427.             }
  428.             str = "";
  429.             for (std::list<CStdString>::iterator iter = ipBindList.begin(); iter!=ipBindList.end(); iter++)
  430.                 if (*iter != "127.0.0.1")
  431.                     str += *iter + " ";
  432.  
  433.             str.TrimRight(" ");
  434.         }
  435.         break;
  436.     case OPTION_ADMINIPADDRESSES:
  437.         {
  438.             CStdString sub;
  439.             int dotCount = 0;
  440.             std::list<CStdString> ipList;
  441.             for (unsigned int i = 0; i < _tcslen(value); i++)
  442.             {
  443.                 char cur = value[i];
  444.                 if ((cur < '0' || cur > '9') && cur != '.' && cur != '*' && cur != '?')
  445.                 {
  446.                     if (sub!="" && dotCount==3)
  447.                     {
  448.                         while (sub.Replace("**", "*"));
  449.                         BOOL bError = FALSE;
  450.                         CStdString ip;
  451.                         for (int j=0; j<3; j++)
  452.                         {
  453.                             int pos = sub.Find(".");
  454.                             if (pos<1 || pos>3)
  455.                             {
  456.                                 bError = TRUE;
  457.                                 break;
  458.                             }
  459.                             ip += sub.Left(pos) + ".";
  460.                             sub = sub.Mid(pos + 1);
  461.                         }
  462.                         if (!bError && sub.GetLength() != 0)
  463.                         {
  464.                             ip += sub;
  465.                             ipList.push_back(ip);
  466.                         }
  467.                     }
  468.                     sub = "";
  469.                     dotCount = 0;
  470.                 }
  471.                 else
  472.                 {
  473.                     sub+=cur;
  474.                     if (cur == '.')
  475.                         dotCount++;
  476.                 }
  477.             }
  478.             if (sub!="" && dotCount==3)
  479.             {
  480.                 while (sub.Replace("**", "*"));
  481.                 BOOL bError = FALSE;
  482.                 CStdString ip;
  483.                 for (int j=0; j<3; j++)
  484.                 {
  485.                     int pos = sub.Find(".");
  486.                     if (pos<1 || pos>3)
  487.                     {
  488.                         bError = TRUE;
  489.                         break;
  490.                     }
  491.                     ip += sub.Left(pos) + ".";
  492.                     sub = sub.Mid(pos + 1);
  493.                 }
  494.                 if (!bError && sub.GetLength() != 0)
  495.                 {
  496.                     ip += sub;
  497.                     ipList.push_back(ip);
  498.                 }
  499.             }
  500.  
  501.             str = "";
  502.             for (std::list<CStdString>::iterator iter = ipList.begin(); iter!=ipList.end(); iter++)
  503.                 if (*iter != "127.0.0.1")
  504.                     str += *iter + " ";
  505.             str.TrimRight(" ");
  506.         }
  507.         break;
  508.     case OPTION_ADMINPASS:
  509.         if (str.GetLength() < 6)
  510.             return;
  511.         break;
  512.     case OPTION_MODEZ_DISALLOWED_IPS:
  513.     case OPTION_IPFILTER_ALLOWED:
  514.     case OPTION_IPFILTER_DISALLOWED:
  515.         {
  516.             str.Replace('\r', ' ');
  517.             str.Replace('\n', ' ');
  518.             str.Replace('\r', ' ');
  519.             while (str.Replace("  ", " "));
  520.             str += " ";
  521.  
  522.             CStdString ips;
  523.  
  524.             int pos = str.Find(' ');
  525.             while (pos != -1)
  526.             {
  527.                 CStdString sub = str.Left(pos);
  528.                 str = str.Mid(pos + 1);
  529.                 str.TrimLeft(' ');
  530.  
  531.                 if (sub == "*")
  532.                     ips += " " + sub;
  533.                 else
  534.                 {
  535.                     if (IsValidAddressFilter(sub))
  536.                         ips += " " + sub;
  537.                     pos = str.Find(' ');
  538.                 }
  539.             }
  540.             ips.TrimLeft(' ');
  541.  
  542.             str = ips;
  543.         }
  544.         break;
  545.     case OPTION_IPBINDINGS:
  546.         {
  547.             CStdString sub;
  548.             std::list<CStdString> ipBindList;
  549.             for (unsigned int i = 0; i<_tcslen(value); i++)
  550.             {
  551.                 char cur = value[i];
  552.                 if ((cur<'0' || cur>'9') && cur!='.')
  553.                 {
  554.                     if (sub=="" && cur=='*')
  555.                     {
  556.                         ipBindList.clear();
  557.                         ipBindList.push_back("*");
  558.                         break;
  559.                     }
  560.  
  561.                     if (sub != "")
  562.                     {
  563.                         //Parse IP
  564.                         SOCKADDR_IN sockAddr;
  565.                         memset(&sockAddr,0,sizeof(sockAddr));
  566.  
  567.                         sockAddr.sin_family = AF_INET;
  568.                         sockAddr.sin_addr.s_addr = inet_addr(sub);
  569.  
  570.                         if (sockAddr.sin_addr.s_addr != INADDR_NONE)
  571.                         {
  572.                             sub = inet_ntoa(sockAddr.sin_addr);
  573.                             std::list<CStdString>::iterator iter;
  574.                             for (iter = ipBindList.begin(); iter != ipBindList.end(); iter++)
  575.                                 if (*iter == sub)
  576.                                     break;
  577.                             if (iter == ipBindList.end())
  578.                                 ipBindList.push_back(sub);
  579.                         }
  580.                         sub = "";
  581.                     }
  582.                 }
  583.                 else
  584.                     sub += cur;
  585.             }
  586.             if (sub != "")
  587.             {
  588.                 //Parse IP
  589.                 SOCKADDR_IN sockAddr;
  590.                 memset(&sockAddr,0,sizeof(sockAddr));
  591.  
  592.                 sockAddr.sin_family = AF_INET;
  593.                 sockAddr.sin_addr.s_addr = inet_addr(sub);
  594.  
  595.                 if (sockAddr.sin_addr.s_addr != INADDR_NONE)
  596.                 {
  597.                     sub = inet_ntoa(sockAddr.sin_addr);
  598.                     std::list<CStdString>::iterator iter;
  599.                     for (iter = ipBindList.begin(); iter != ipBindList.end(); iter++)
  600.                         if (*iter == sub)
  601.                             break;
  602.                     if (iter == ipBindList.end())
  603.                         ipBindList.push_back(sub);
  604.                 }
  605.                 sub = "";
  606.             }
  607.  
  608.             if (ipBindList.empty())
  609.                 ipBindList.push_back("*");
  610.  
  611.             str = "";
  612.             for (std::list<CStdString>::iterator iter = ipBindList.begin(); iter != ipBindList.end(); iter++)
  613.                 str += *iter + " ";
  614.  
  615.             str.TrimRight(" ");
  616.         }
  617.         break;
  618.     }
  619.     EnterCritSection(m_Sync);
  620.     m_sOptionsCache[nOptionID-1].bCached = TRUE;
  621.     m_sOptionsCache[nOptionID-1].nType = 0;
  622.     m_sOptionsCache[nOptionID-1].str = str;
  623.     m_OptionsCache[nOptionID-1]=m_sOptionsCache[nOptionID-1];
  624.     LeaveCritSection(m_Sync);
  625.  
  626.     TCHAR buffer[MAX_PATH + 1000]; //Make it large enough
  627.     GetModuleFileName( 0, buffer, MAX_PATH );
  628.     LPTSTR pos=_tcsrchr(buffer, '\\');
  629.     if (pos)
  630.         *++pos=0;
  631.     _tcscat(buffer, _T("FileZilla Server.xml"));
  632.     CMarkupSTL xml;
  633.     if (!xml.Load(buffer))
  634.         return;
  635.  
  636.     if (!xml.FindElem( _T("FileZillaServer") ))
  637.         return;
  638.  
  639.     if (!xml.FindChildElem( _T("Settings") ))
  640.         xml.AddChildElem( _T("Settings") );
  641.  
  642.     xml.IntoElem();
  643.     BOOL res=xml.FindChildElem();
  644.     while (res)
  645.     {
  646.         CStdString name=xml.GetChildAttrib( _T("name"));
  647.         if (!_tcscmp(name, m_Options[nOptionID-1].name))
  648.         {
  649.             xml.SetChildAttrib(_T("name"), m_Options[nOptionID-1].name);
  650.             xml.SetChildAttrib(_T("type"), _T("string"));
  651.             xml.SetChildData(str);
  652.             break;
  653.         }
  654.         res=xml.FindChildElem();
  655.     }
  656.     if (!res)
  657.     {
  658.         xml.InsertChildElem( _T("Item"), str );
  659.         xml.SetChildAttrib(_T("name"), m_Options[nOptionID-1].name);
  660.         xml.SetChildAttrib(_T("type"), _T("string"));
  661.     }
  662.     xml.Save(buffer);
  663. }
  664.  
  665. CStdString COptions::GetOption(int nOptionID)
  666. {
  667.     ASSERT(nOptionID>0 && nOptionID<=OPTIONS_NUM);
  668.     ASSERT(!m_Options[nOptionID-1].nType);
  669.     Init();
  670.  
  671.     if (m_OptionsCache[nOptionID-1].bCached)
  672.         return m_OptionsCache[nOptionID-1].str;
  673.  
  674.     EnterCritSection(m_Sync);
  675.  
  676.     if (!m_sOptionsCache[nOptionID-1].bCached)
  677.     {
  678.         //Default values
  679.         switch (nOptionID)
  680.         {
  681.         case OPTION_SERVERPORT:
  682.             m_sOptionsCache[nOptionID-1].str = "21";
  683.             break;
  684.         case OPTION_WELCOMEMESSAGE:
  685.             m_sOptionsCache[nOptionID-1].str = "%v";
  686.             m_sOptionsCache[nOptionID-1].str += "\r\nwritten by Tim Kosse (Tim.Kosse@gmx.de)";
  687.             m_sOptionsCache[nOptionID-1].str += "\r\nPlease visit http://sourceforge.net/projects/filezilla/";
  688.             break;
  689.         case OPTION_CUSTOMPASVIPSERVER:
  690.             m_sOptionsCache[nOptionID-1].str = "http://filezilla.sourceforge.net/misc/ip.php";
  691.             break;
  692.         case OPTION_IPBINDINGS:
  693.             m_sOptionsCache[nOptionID-1].str = "*";
  694.             break;
  695.         case OPTION_SSLPORTS:
  696.             m_sOptionsCache[nOptionID-1].str = "990";
  697.             break;
  698.         default:
  699.             m_sOptionsCache[nOptionID-1].str = "";
  700.             break;
  701.         }
  702.         m_sOptionsCache[nOptionID-1].bCached = TRUE;
  703.         m_sOptionsCache[nOptionID-1].nType = 0;
  704.     }
  705.     m_OptionsCache[nOptionID-1] = m_sOptionsCache[nOptionID - 1];
  706.     LeaveCritSection(m_Sync);
  707.     return m_OptionsCache[nOptionID-1].str;
  708. }
  709.  
  710. _int64 COptions::GetOptionVal(int nOptionID)
  711. {
  712.     ASSERT(nOptionID>0 && nOptionID<=OPTIONS_NUM);
  713.     ASSERT(m_Options[nOptionID-1].nType == 1);
  714.     Init();
  715.  
  716.     if (m_OptionsCache[nOptionID-1].bCached)
  717.         return m_OptionsCache[nOptionID-1].value;
  718.  
  719.     EnterCritSection(m_Sync);
  720.  
  721.     if (!m_sOptionsCache[nOptionID-1].bCached)
  722.     {
  723.         //Default values
  724.         switch (nOptionID)
  725.         {
  726.             case OPTION_MAXUSERS:
  727.                 m_sOptionsCache[nOptionID-1].value = 0;
  728.                 break;
  729.             case OPTION_THREADNUM:
  730.                 m_sOptionsCache[nOptionID-1].value = 2;
  731.                 break;
  732.             case OPTION_TIMEOUT:
  733.             case OPTION_NOTRANSFERTIMEOUT:
  734.                 m_sOptionsCache[nOptionID-1].value = 120;
  735.                 break;
  736.             case OPTION_LOGINTIMEOUT:
  737.                 m_sOptionsCache[nOptionID-1].value = 60;
  738.                 break;
  739.             case OPTION_ADMINPORT:
  740.                 m_sOptionsCache[nOptionID-1].value = 14147;
  741.                 break;
  742.             case OPTION_DOWNLOADSPEEDLIMIT:
  743.             case OPTION_UPLOADSPEEDLIMIT:
  744.                 m_sOptionsCache[nOptionID-1].value = 10;
  745.                 break;
  746.             case OPTION_BUFFERSIZE:
  747.                 m_sOptionsCache[nOptionID-1].value = 32768;
  748.                 break;
  749.             case OPTION_CUSTOMPASVIPTYPE:
  750.                 m_sOptionsCache[nOptionID-1].value = 0;
  751.                 break;
  752.             case OPTION_MODEZ_USE:
  753.                 m_sOptionsCache[nOptionID-1].value = 0;
  754.                 break;
  755.             case OPTION_MODEZ_LEVELMIN:
  756.                 m_sOptionsCache[nOptionID-1].value = 1;
  757.                 break;
  758.             case OPTION_MODEZ_LEVELMAX:
  759.                 m_sOptionsCache[nOptionID-1].value = 9;
  760.                 break;
  761.             case OPTION_MODEZ_ALLOWLOCAL:
  762.                 m_sOptionsCache[nOptionID-1].value = 0;
  763.                 break;
  764.             case OPTION_ALLOWEXPLICITSSL:
  765.                 m_sOptionsCache[nOptionID-1].value = 1;
  766.                 break;
  767.             case OPTION_BUFFERSIZE2:
  768.                 m_sOptionsCache[nOptionID-1].value = 65536;
  769.                 break;
  770.             default:
  771.                 m_sOptionsCache[nOptionID-1].value = 0;
  772.         }
  773.         m_sOptionsCache[nOptionID-1].bCached=TRUE;
  774.         m_sOptionsCache[nOptionID-1].nType=1;
  775.     }
  776.     m_OptionsCache[nOptionID-1]=m_sOptionsCache[nOptionID-1];
  777.     LeaveCritSection(m_Sync);
  778.     return m_OptionsCache[nOptionID-1].value;
  779. }
  780.  
  781. void COptions::UpdateInstances()
  782. {
  783.     EnterCritSection(m_Sync);
  784.     for (std::list<COptions *>::iterator iter=m_InstanceList.begin(); iter!=m_InstanceList.end(); iter++)
  785.     {
  786.         ASSERT((*iter)->m_pOptionsHelperWindow);
  787.         ::PostMessage((*iter)->m_pOptionsHelperWindow->GetHwnd(), WM_USER, 0, 0);
  788.     }
  789.     LeaveCritSection(m_Sync);
  790. }
  791.  
  792. void COptions::Init()
  793. {
  794.     if (m_bInitialized)
  795.         return;
  796.     EnterCritSection(m_Sync);
  797.     m_bInitialized = TRUE;
  798.     CFileStatus64 status;
  799.     CMarkupSTL xml;
  800.     TCHAR buffer[MAX_PATH + 1000]; //Make it large enough
  801.     GetModuleFileName( 0, buffer, MAX_PATH );
  802.     LPTSTR pos=_tcsrchr(buffer, '\\');
  803.     if (pos)
  804.         *++pos=0;
  805.     _tcscat(buffer, _T("FileZilla Server.xml"));
  806.  
  807.     for (int i=0; i<OPTIONS_NUM; i++)
  808.         m_sOptionsCache[i].bCached=FALSE;
  809.  
  810.     if (!GetStatus64(buffer, status) )
  811.     {
  812.         xml.AddElem( _T("FileZillaServer") );
  813.         if (!xml.Save(buffer))
  814.         {
  815.             LeaveCritSection(m_Sync);
  816.             return;
  817.         }
  818.     }
  819.     else if (status.m_attribute&FILE_ATTRIBUTE_DIRECTORY)
  820.     {
  821.         LeaveCritSection(m_Sync);
  822.         return;
  823.     }
  824.  
  825.     if (xml.Load(buffer))
  826.     {
  827.         if (xml.FindElem( _T("FileZillaServer") ))
  828.         {
  829.             if (!xml.FindChildElem( _T("Settings") ))
  830.                 xml.AddChildElem( _T("Settings") );
  831.  
  832.             CStdString str;
  833.             xml.IntoElem();
  834.             str=xml.GetTagName();
  835.             while (xml.FindChildElem())
  836.             {
  837.                 CStdString value=xml.GetChildData();
  838.                 CStdString name=xml.GetChildAttrib( _T("name") );
  839.                 CStdString type=xml.GetChildAttrib( _T("type") );
  840.                 for (int i=0;i<OPTIONS_NUM;i++)
  841.                 {
  842.                     if (!_tcscmp(name, m_Options[i].name))
  843.                     {
  844.                         if (m_sOptionsCache[i].bCached)
  845.                             break;
  846.                         else
  847.                         {
  848.                             if (type=="numeric")
  849.                             {
  850.                                 if (m_Options[i].nType!=1)
  851.                                     break;
  852.                                 _int64 value64=_ttoi64(value);
  853.                                 if (IsNumeric(value))
  854.                                     SetOption(i+1, value64);
  855.                             }
  856.                             else
  857.                             {
  858.                                 if (m_Options[i].nType!=0)
  859.                                     break;
  860.                                 SetOption(i+1, value);
  861.                             }
  862.                         }
  863.                         break;
  864.                     }
  865.                 }
  866.             }
  867.             ReadSpeedLimits(&xml);
  868.  
  869.             LeaveCritSection(m_Sync);
  870.             UpdateInstances();
  871.             return;
  872.         }
  873.     }
  874.     LeaveCritSection(m_Sync);
  875. }
  876.  
  877. bool COptions::IsNumeric(LPCTSTR str)
  878. {
  879.     if (!str)
  880.         return false;
  881.     LPCTSTR p=str;
  882.     while(*p)
  883.     {
  884.         if (*p<'0' || *p>'9')
  885.         {
  886.             return false;
  887.         }
  888.         p++;
  889.     }
  890.     return true;
  891. }
  892.  
  893. CMarkupSTL *COptions::GetXML()
  894. {
  895.     EnterCritSection(m_Sync);
  896.     TCHAR buffer[MAX_PATH + 1000]; //Make it large enough
  897.     GetModuleFileName( 0, buffer, MAX_PATH );
  898.     LPTSTR pos=_tcsrchr(buffer, '\\');
  899.     if (pos)
  900.         *++pos=0;
  901.     _tcscat(buffer, _T("FileZilla Server.xml"));
  902.     CMarkupSTL *pXML=new CMarkupSTL;
  903.     if (!pXML->Load(buffer))
  904.     {
  905.         LeaveCritSection(m_Sync);
  906.         delete pXML;
  907.         return NULL;
  908.     }
  909.  
  910.     if (!pXML->FindElem( _T("FileZillaServer") ))
  911.     {
  912.         LeaveCritSection(m_Sync);
  913.         delete pXML;
  914.         return NULL;
  915.     }
  916.     return pXML;
  917. }
  918.  
  919. BOOL COptions::FreeXML(CMarkupSTL *pXML)
  920. {
  921.     ASSERT(pXML);
  922.     if (!pXML)
  923.         return FALSE;
  924.     TCHAR buffer[MAX_PATH + 1000]; //Make it large enough
  925.     GetModuleFileName( 0, buffer, MAX_PATH );
  926.     LPTSTR pos=_tcsrchr(buffer, '\\');
  927.     if (pos)
  928.         *++pos=0;
  929.     _tcscat(buffer, _T("FileZilla Server.xml"));
  930.     if (!pXML->Save(buffer))
  931.         return FALSE;
  932.     delete pXML;
  933.     LeaveCritSection(m_Sync);
  934.     return TRUE;
  935. }
  936.  
  937. BOOL COptions::GetAsCommand(char **pBuffer, DWORD *nBufferLength)
  938. {
  939.     int i;
  940.     DWORD len = 2;
  941.  
  942.     EnterCritSection(m_Sync);
  943.     for (i=0; i<OPTIONS_NUM; i++)
  944.     {
  945.         len+=1;
  946.         if (!m_Options[i].nType)
  947.             if ((i+1)!=OPTION_ADMINPASS)
  948.                 len+=GetOption(i+1).GetLength()+2;
  949.             else if (GetOption(i+1).GetLength() >= 6)
  950.                 len+=GetOption(i+1).GetLength()+2;
  951.             else
  952.                 len+=3;
  953.         else
  954.             len+=8;
  955.     }
  956.  
  957.     len +=4;
  958.     SPEEDLIMITSLIST::const_iterator iter;
  959.     for (iter = m_sDownloadSpeedLimits.begin(); iter != m_sDownloadSpeedLimits.end(); iter++)
  960.         len += iter->GetRequiredBufferLen();
  961.     for (iter = m_sUploadSpeedLimits.begin(); iter != m_sUploadSpeedLimits.end(); iter++)
  962.         len += iter->GetRequiredBufferLen();
  963.  
  964.     *pBuffer=new char[len];
  965.     char *p=*pBuffer;
  966.     *p++ = OPTIONS_NUM/256;
  967.     *p++ = OPTIONS_NUM%256;
  968.     for (i=0; i<OPTIONS_NUM; i++)
  969.     {
  970.         *p++ = m_Options[i].nType;
  971.         switch(m_Options[i].nType) {
  972.         case 0:
  973.             {
  974.                 CStdString str = GetOption(i+1);
  975.                 if ((i+1)==OPTION_ADMINPASS) //Do NOT send admin password,
  976.                                              //instead send empty string if admin pass is set
  977.                                              //and send a single char if admin pass is invalid (len < 6)
  978.                 if (str.GetLength() >= 6)
  979.                     str="";
  980.                 else
  981.                     str="*";
  982.                 *p++ = str.GetLength() / 256;
  983.                 *p++ = str.GetLength() % 256;
  984.                 memcpy(p, str, str.GetLength());
  985.                 p+=str.GetLength();
  986.             }
  987.             break;
  988.         case 1:
  989.             {
  990.                 _int64 value = GetOptionVal(i+1);
  991.                 memcpy(p, &value, 8);
  992.                 p+=8;
  993.             }
  994.             break;
  995.         default:
  996.             ASSERT(FALSE);
  997.         }
  998.     }
  999.  
  1000.     *p++ = m_sDownloadSpeedLimits.size() << 8;
  1001.     *p++ = m_sDownloadSpeedLimits.size() %256;
  1002.     for (iter = m_sDownloadSpeedLimits.begin(); iter != m_sDownloadSpeedLimits.end(); iter++)
  1003.         p = iter->FillBuffer(p);
  1004.  
  1005.     *p++ = m_sUploadSpeedLimits.size() << 8;
  1006.     *p++ = m_sUploadSpeedLimits.size() %256;
  1007.     for (iter = m_sUploadSpeedLimits.begin(); iter != m_sUploadSpeedLimits.end(); iter++)
  1008.         p = iter->FillBuffer(p);
  1009.  
  1010.     LeaveCritSection(m_Sync);
  1011.  
  1012.     *nBufferLength = len;
  1013.  
  1014.     return TRUE;
  1015. }
  1016.  
  1017. BOOL COptions::ParseOptionsCommand(unsigned char *pData, DWORD dwDataLength, BOOL bFromLocal /*=FALSE*/)
  1018. {
  1019.     unsigned char *p=pData;
  1020.     int num = *p * 256 + p[1];
  1021.     p+=2;
  1022.     if (num!=OPTIONS_NUM)
  1023.         return FALSE;
  1024.  
  1025.     int i;
  1026.     for (i = 0; i < num; i++)
  1027.     {
  1028.         if ((DWORD)(p-pData)>=dwDataLength)
  1029.             return FALSE;
  1030.         int nType = *p++;
  1031.         if (!nType)
  1032.         {
  1033.             if ((DWORD)(p-pData+2) >= dwDataLength)
  1034.                 return 2;
  1035.             int len= *p * 256 + p[1];
  1036.             p+=2;
  1037.             if ((DWORD)(p-pData+len)>dwDataLength)
  1038.                 return FALSE;
  1039.             char *pBuffer = new char[len+1];
  1040.             memcpy(pBuffer, p, len);
  1041.             pBuffer[len]=0;
  1042.             if (!m_Options[i].bOnlyLocal || bFromLocal) //Do not change admin interface settings from remote connections
  1043.                 SetOption(i+1, pBuffer);
  1044.             delete [] pBuffer;
  1045.             p+=len;
  1046.         }
  1047.         else if (nType == 1)
  1048.         {
  1049.             if ((DWORD)(p-pData+8)>dwDataLength)
  1050.                 return FALSE;
  1051.             if (!m_Options[i].bOnlyLocal || bFromLocal) //Do not change admin interface settings from remote connections
  1052.                 SetOption(i+1, GET64(p));
  1053.             p+=8;
  1054.         }
  1055.         else
  1056.             return FALSE;
  1057.     }
  1058.  
  1059.     SPEEDLIMITSLIST dl;
  1060.     SPEEDLIMITSLIST ul;
  1061.  
  1062.     if ((DWORD)(p-pData+2)>dwDataLength)
  1063.         return FALSE;
  1064.     num = *p++ << 8;
  1065.     num |= *p++;
  1066.     EnterCritSection(m_Sync);
  1067.     for (i=0; i<num; i++)
  1068.     {
  1069.         CSpeedLimit limit;
  1070.         p = limit.ParseBuffer(p, dwDataLength - (p - pData));
  1071.         if (!p)
  1072.         {
  1073.             LeaveCritSection(m_Sync);
  1074.             return FALSE;
  1075.         }
  1076.         dl.push_back(limit);
  1077.     }
  1078.  
  1079.     if ((DWORD)(p-pData+2)>dwDataLength)
  1080.     {
  1081.         LeaveCritSection(m_Sync);
  1082.         return FALSE;
  1083.     }
  1084.     num = *p++ << 8;
  1085.     num |= *p++;
  1086.     for (i=0; i<num; i++)
  1087.     {
  1088.         CSpeedLimit limit;
  1089.         p = limit.ParseBuffer(p, dwDataLength - (p - pData));
  1090.         if (!p)
  1091.         {
  1092.             LeaveCritSection(m_Sync);
  1093.             return FALSE;
  1094.         }
  1095.         ul.push_back(limit);
  1096.     }
  1097.  
  1098.     m_sDownloadSpeedLimits = dl;
  1099.     m_sUploadSpeedLimits = ul;
  1100.     VERIFY(SaveSpeedLimits());
  1101.  
  1102.     LeaveCritSection(m_Sync);
  1103.  
  1104.     UpdateInstances();
  1105.     return TRUE;
  1106. }
  1107.  
  1108. BOOL COptions::SaveSpeedLimits()
  1109. {
  1110.     TCHAR buffer[MAX_PATH + 1000]; //Make it large enough
  1111.     GetModuleFileName( 0, buffer, MAX_PATH );
  1112.     LPTSTR pos=_tcsrchr(buffer, '\\');
  1113.     if (pos)
  1114.         *++pos=0;
  1115.     _tcscat(buffer, _T("FileZilla Server.xml"));
  1116.     CMarkupSTL xml;
  1117.     if (!xml.Load(buffer))
  1118.         return FALSE;
  1119.  
  1120.     if (!xml.FindElem( _T("FileZillaServer") ))
  1121.         return FALSE;
  1122.  
  1123.     EnterCritSection(m_Sync);
  1124.  
  1125.     if (!xml.FindChildElem( _T("Settings") ))
  1126.         xml.AddChildElem( _T("Settings") );
  1127.  
  1128.     xml.IntoElem();
  1129.  
  1130.     while (xml.FindChildElem(_T("SpeedLimits")))
  1131.         xml.RemoveChildElem();
  1132.     xml.AddChildElem(_T("SpeedLimits"));
  1133.  
  1134.     CStdString str;
  1135.  
  1136.     xml.IntoElem();
  1137.  
  1138.     SPEEDLIMITSLIST::iterator iter;
  1139.  
  1140.     xml.AddChildElem("Download");
  1141.     xml.IntoElem();
  1142.     for (iter = m_sDownloadSpeedLimits.begin(); iter != m_sDownloadSpeedLimits.end(); iter++)
  1143.     {
  1144.         const CSpeedLimit& limit = *iter;
  1145.         xml.AddChildElem(_T("Rule"));
  1146.  
  1147.         xml.SetChildAttrib(_T("Speed"), limit.m_Speed);
  1148.  
  1149.         xml.IntoElem();
  1150.  
  1151.         str.Format("%d", limit.m_Day);
  1152.         xml.AddChildElem(_T("Days"), str);
  1153.  
  1154.         if (limit.m_DateCheck)
  1155.         {
  1156.             xml.AddChildElem(_T("Date"));
  1157.             xml.SetChildAttrib(_T("Year"), limit.m_Date.y);
  1158.             xml.SetChildAttrib(_T("Month"), limit.m_Date.m);
  1159.             xml.SetChildAttrib(_T("Day"), limit.m_Date.d);
  1160.         }
  1161.  
  1162.         if (limit.m_FromCheck)
  1163.         {
  1164.             xml.AddChildElem(_T("From"));
  1165.             xml.SetChildAttrib(_T("Hour"), limit.m_FromTime.h);
  1166.             xml.SetChildAttrib(_T("Minute"), limit.m_FromTime.m);
  1167.             xml.SetChildAttrib(_T("Second"), limit.m_FromTime.s);
  1168.         }
  1169.  
  1170.         if (limit.m_ToCheck)
  1171.         {
  1172.             xml.AddChildElem(_T("To"));
  1173.             xml.SetChildAttrib(_T("Hour"), limit.m_ToTime.h);
  1174.             xml.SetChildAttrib(_T("Minute"), limit.m_ToTime.m);
  1175.             xml.SetChildAttrib(_T("Second"), limit.m_ToTime.s);
  1176.         }
  1177.  
  1178.         xml.OutOfElem();
  1179.     }
  1180.     xml.OutOfElem();
  1181.  
  1182.     xml.AddChildElem("Upload");
  1183.     xml.IntoElem();
  1184.     for (iter = m_sUploadSpeedLimits.begin(); iter != m_sUploadSpeedLimits.end(); iter++)
  1185.     {
  1186.         const CSpeedLimit& limit = *iter;
  1187.         xml.AddChildElem(_T("Rule"));
  1188.  
  1189.         xml.SetChildAttrib(_T("Speed"), limit.m_Speed);
  1190.  
  1191.         xml.IntoElem();
  1192.  
  1193.         str.Format("%d", limit.m_Day);
  1194.         xml.AddChildElem(_T("Days"), str);
  1195.  
  1196.         if (limit.m_DateCheck)
  1197.         {
  1198.             xml.AddChildElem(_T("Date"));
  1199.             xml.SetChildAttrib(_T("Year"), limit.m_Date.y);
  1200.             xml.SetChildAttrib(_T("Month"), limit.m_Date.m);
  1201.             xml.SetChildAttrib(_T("Day"), limit.m_Date.d);
  1202.         }
  1203.  
  1204.         if (limit.m_FromCheck)
  1205.         {
  1206.             xml.AddChildElem(_T("From"));
  1207.             xml.SetChildAttrib(_T("Hour"), limit.m_FromTime.h);
  1208.             xml.SetChildAttrib(_T("Minute"), limit.m_FromTime.m);
  1209.             xml.SetChildAttrib(_T("Second"), limit.m_FromTime.s);
  1210.         }
  1211.  
  1212.         if (limit.m_ToCheck)
  1213.         {
  1214.             xml.AddChildElem(_T("To"));
  1215.             xml.SetChildAttrib(_T("Hour"), limit.m_ToTime.h);
  1216.             xml.SetChildAttrib(_T("Minute"), limit.m_ToTime.m);
  1217.             xml.SetChildAttrib(_T("Second"), limit.m_ToTime.s);
  1218.         }
  1219.  
  1220.         xml.OutOfElem();
  1221.     }
  1222.     xml.OutOfElem();
  1223.  
  1224.     xml.OutOfElem();
  1225.  
  1226.     xml.OutOfElem();
  1227.  
  1228.     xml.Save(buffer);
  1229.  
  1230.     LeaveCritSection(m_Sync);
  1231.     return TRUE;
  1232. }
  1233.  
  1234. BOOL COptions::ReadSpeedLimits(CMarkupSTL *pXML)
  1235. {
  1236.     EnterCritSection(m_Sync);
  1237.     pXML->ResetChildPos();
  1238.  
  1239.     while (pXML->FindChildElem(_T("SpeedLimits")))
  1240.     {
  1241.         CStdString str;
  1242.         int n;
  1243.  
  1244.         pXML->IntoElem();
  1245.  
  1246.         while (pXML->FindChildElem(_T("Download")))
  1247.         {
  1248.             pXML->IntoElem();
  1249.  
  1250.             while (pXML->FindChildElem(_T("Rule")))
  1251.             {
  1252.                 CSpeedLimit limit;
  1253.                 str = pXML->GetChildAttrib("Speed");
  1254.                 n = _ttoi(str);
  1255.                 if (n < 0 || n > 65535)
  1256.                     n = 10;
  1257.                 limit.m_Speed = n;
  1258.  
  1259.                 pXML->IntoElem();
  1260.  
  1261.                 if (pXML->FindChildElem("Days"))
  1262.                 {
  1263.                     str = pXML->GetChildData();
  1264.                     if (str != "")
  1265.                         n = _ttoi(str);
  1266.                     else
  1267.                         n = 0x7F;
  1268.                     limit.m_Day = n & 0x7F;
  1269.                 }
  1270.                 pXML->ResetChildPos();
  1271.  
  1272.                 limit.m_DateCheck = FALSE;
  1273.                 if (pXML->FindChildElem("Date"))
  1274.                 {
  1275.                     limit.m_DateCheck = TRUE;
  1276.                     str = pXML->GetChildAttrib("Year");
  1277.                     n = _ttoi(str);
  1278.                     if (n < 1900 || n > 3000)
  1279.                         n = 2003;
  1280.                     limit.m_Date.y = n;
  1281.                     str = pXML->GetChildAttrib("Month");
  1282.                     n = _ttoi(str);
  1283.                     if (n < 1 || n > 12)
  1284.                         n = 1;
  1285.                     limit.m_Date.m = n;
  1286.                     str = pXML->GetChildAttrib("Day");
  1287.                     n = _ttoi(str);
  1288.                     if (n < 1 || n > 31)
  1289.                         n = 1;
  1290.                     limit.m_Date.d = n;
  1291.                 }
  1292.                 pXML->ResetChildPos();
  1293.  
  1294.                 limit.m_FromCheck = FALSE;
  1295.                 if (pXML->FindChildElem("From"))
  1296.                 {
  1297.                     limit.m_FromCheck = TRUE;
  1298.                     str = pXML->GetChildAttrib("Hour");
  1299.                     n = _ttoi(str);
  1300.                     if (n < 0 || n > 23)
  1301.                         n = 0;
  1302.                     limit.m_FromTime.h = n;
  1303.                     str = pXML->GetChildAttrib("Minute");
  1304.                     n = _ttoi(str);
  1305.                     if (n < 0 || n > 59)
  1306.                         n = 0;
  1307.                     limit.m_FromTime.m = n;
  1308.                     str = pXML->GetChildAttrib("Second");
  1309.                     n = _ttoi(str);
  1310.                     if (n < 0 || n > 59)
  1311.                         n = 0;
  1312.                     limit.m_FromTime.s = n;
  1313.                 }
  1314.                 pXML->ResetChildPos();
  1315.  
  1316.                 limit.m_ToCheck = FALSE;
  1317.                 if (pXML->FindChildElem("To"))
  1318.                 {
  1319.                     limit.m_ToCheck = TRUE;
  1320.                     str = pXML->GetChildAttrib("Hour");
  1321.                     n = _ttoi(str);
  1322.                     if (n < 0 || n > 23)
  1323.                         n = 0;
  1324.                     limit.m_ToTime.h = n;
  1325.                     str = pXML->GetChildAttrib("Minute");
  1326.                     n = _ttoi(str);
  1327.                     if (n < 0 || n > 59)
  1328.                         n = 0;
  1329.                     limit.m_ToTime.m = n;
  1330.                     str = pXML->GetChildAttrib("Second");
  1331.                     n = _ttoi(str);
  1332.                     if (n < 0 || n > 59)
  1333.                         n = 0;
  1334.                     limit.m_ToTime.s = n;
  1335.                 }
  1336.                 pXML->ResetChildPos();
  1337.  
  1338.                 pXML->OutOfElem();
  1339.  
  1340.                 m_sDownloadSpeedLimits.push_back(limit);
  1341.             }
  1342.             pXML->OutOfElem();
  1343.         }
  1344.         pXML->ResetChildPos();
  1345.  
  1346.         while (pXML->FindChildElem(_T("Upload")))
  1347.         {
  1348.             pXML->IntoElem();
  1349.  
  1350.             while (pXML->FindChildElem(_T("Rule")))
  1351.             {
  1352.                 CSpeedLimit limit;
  1353.                 str = pXML->GetChildAttrib("Speed");
  1354.                 n = _ttoi(str);
  1355.                 if (n < 0 || n > 65535)
  1356.                     n = 10;
  1357.                 limit.m_Speed = n;
  1358.  
  1359.                 pXML->IntoElem();
  1360.  
  1361.                 if (pXML->FindChildElem("Days"))
  1362.                 {
  1363.                     str = pXML->GetChildData();
  1364.                     if (str != "")
  1365.                         n = _ttoi(str);
  1366.                     else
  1367.                         n = 0x7F;
  1368.                     limit.m_Day = n & 0x7F;
  1369.                 }
  1370.                 pXML->ResetChildPos();
  1371.  
  1372.                 limit.m_DateCheck = FALSE;
  1373.                 if (pXML->FindChildElem("Date"))
  1374.                 {
  1375.                     limit.m_DateCheck = TRUE;
  1376.                     str = pXML->GetChildAttrib("Year");
  1377.                     n = _ttoi(str);
  1378.                     if (n < 1900 || n > 3000)
  1379.                         n = 2003;
  1380.                     limit.m_Date.y = n;
  1381.                     str = pXML->GetChildAttrib("Month");
  1382.                     n = _ttoi(str);
  1383.                     if (n < 1 || n > 12)
  1384.                         n = 1;
  1385.                     limit.m_Date.m = n;
  1386.                     str = pXML->GetChildAttrib("Day");
  1387.                     n = _ttoi(str);
  1388.                     if (n < 1 || n > 31)
  1389.                         n = 1;
  1390.                     limit.m_Date.d = n;
  1391.                 }
  1392.                 pXML->ResetChildPos();
  1393.  
  1394.                 limit.m_FromCheck = FALSE;
  1395.                 if (pXML->FindChildElem("From"))
  1396.                 {
  1397.                     limit.m_FromCheck = TRUE;
  1398.                     str = pXML->GetChildAttrib("Hour");
  1399.                     n = _ttoi(str);
  1400.                     if (n < 0 || n > 23)
  1401.                         n = 0;
  1402.                     limit.m_FromTime.h = n;
  1403.                     str = pXML->GetChildAttrib("Minute");
  1404.                     n = _ttoi(str);
  1405.                     if (n < 0 || n > 59)
  1406.                         n = 0;
  1407.                     limit.m_FromTime.m = n;
  1408.                     str = pXML->GetChildAttrib("Second");
  1409.                     n = _ttoi(str);
  1410.                     if (n < 0 || n > 59)
  1411.                         n = 0;
  1412.                     limit.m_FromTime.s = n;
  1413.                 }
  1414.                 pXML->ResetChildPos();
  1415.  
  1416.                 limit.m_ToCheck = FALSE;
  1417.                 if (pXML->FindChildElem("To"))
  1418.                 {
  1419.                     limit.m_ToCheck = TRUE;
  1420.                     str = pXML->GetChildAttrib("Hour");
  1421.                     n = _ttoi(str);
  1422.                     if (n < 0 || n > 23)
  1423.                         n = 0;
  1424.                     limit.m_ToTime.h = n;
  1425.                     str = pXML->GetChildAttrib("Minute");
  1426.                     n = _ttoi(str);
  1427.                     if (n < 0 || n > 59)
  1428.                         n = 0;
  1429.                     limit.m_ToTime.m = n;
  1430.                     str = pXML->GetChildAttrib("Second");
  1431.                     n = _ttoi(str);
  1432.                     if (n < 0 || n > 59)
  1433.                         n = 0;
  1434.                     limit.m_ToTime.s = n;
  1435.                 }
  1436.                 pXML->ResetChildPos();
  1437.  
  1438.                 pXML->OutOfElem();
  1439.  
  1440.                 m_sUploadSpeedLimits.push_back(limit);
  1441.             }
  1442.             pXML->OutOfElem();
  1443.         }
  1444.  
  1445.         pXML->OutOfElem();
  1446.     }
  1447.     LeaveCritSection(m_Sync);
  1448.  
  1449.     return TRUE;
  1450. }
  1451.  
  1452. int COptions::GetCurrentSpeedLimit(int nMode)
  1453. {
  1454.     Init();
  1455.     if (nMode)
  1456.     {
  1457.         int nType = (int)GetOptionVal(OPTION_UPLOADSPEEDLIMITTYPE);
  1458.         switch (nType)
  1459.         {
  1460.             case 0:
  1461.                 return -1;
  1462.             case 1:
  1463.                 return (int)GetOptionVal(OPTION_UPLOADSPEEDLIMIT);
  1464.             default:
  1465.                 {
  1466.                     SYSTEMTIME s;
  1467.                     GetLocalTime(&s);
  1468.                     for (SPEEDLIMITSLIST::const_iterator iter = m_UploadSpeedLimits.begin(); iter != m_UploadSpeedLimits.end(); iter++)
  1469.                         if (iter->IsItActive(s))
  1470.                             return iter->m_Speed;
  1471.                     return -1;
  1472.                 }
  1473.         }
  1474.     }
  1475.     else
  1476.     {
  1477.         int nType = (int)GetOptionVal(OPTION_DOWNLOADSPEEDLIMITTYPE);
  1478.         switch (nType)
  1479.         {
  1480.             case 0:
  1481.                 return -1;
  1482.             case 1:
  1483.                 return (int)GetOptionVal(OPTION_DOWNLOADSPEEDLIMIT);
  1484.             default:
  1485.                 {
  1486.                     SYSTEMTIME s;
  1487.                     GetLocalTime(&s);
  1488.                     for (SPEEDLIMITSLIST::const_iterator iter = m_DownloadSpeedLimits.begin(); iter != m_DownloadSpeedLimits.end(); iter++)
  1489.                         if (iter->IsItActive(s))
  1490.                             return iter->m_Speed;
  1491.                     return -1;
  1492.                 }
  1493.         }
  1494.     }
  1495. }
  1496.  
  1497. void COptions::ReloadConfig()
  1498. {
  1499.     EnterCritSection(m_Sync);
  1500.  
  1501.     m_bInitialized = TRUE;
  1502.     CFileStatus64 status;
  1503.     CMarkupSTL xml;
  1504.     TCHAR buffer[MAX_PATH + 1000]; //Make it large enough
  1505.     GetModuleFileName( 0, buffer, MAX_PATH );
  1506.     LPTSTR pos=_tcsrchr(buffer, '\\');
  1507.     if (pos)
  1508.         *++pos=0;
  1509.     _tcscat(buffer, _T("FileZilla Server.xml"));
  1510.  
  1511.     for (int i=0; i<OPTIONS_NUM; i++)
  1512.         m_sOptionsCache[i].bCached = FALSE;
  1513.  
  1514.     if (!GetStatus64(buffer, status) )
  1515.     {
  1516.         xml.AddElem( _T("FileZillaServer") );
  1517.         if (!xml.Save(buffer))
  1518.         {
  1519.             LeaveCritSection(m_Sync);
  1520.             return;
  1521.         }
  1522.     }
  1523.     else if (status.m_attribute&FILE_ATTRIBUTE_DIRECTORY)
  1524.     {
  1525.         LeaveCritSection(m_Sync);
  1526.         return;
  1527.     }
  1528.  
  1529.     if (xml.Load(buffer))
  1530.     {
  1531.         if (xml.FindElem( _T("FileZillaServer") ))
  1532.         {
  1533.             if (!xml.FindChildElem( _T("Settings") ))
  1534.                 xml.AddChildElem( _T("Settings") );
  1535.  
  1536.             CStdString str;
  1537.             xml.IntoElem();
  1538.             str=xml.GetTagName();
  1539.             while (xml.FindChildElem())
  1540.             {
  1541.                 CStdString value=xml.GetChildData();
  1542.                 CStdString name=xml.GetChildAttrib( _T("name") );
  1543.                 CStdString type=xml.GetChildAttrib( _T("type") );
  1544.                 for (int i=0;i<OPTIONS_NUM;i++)
  1545.                 {
  1546.                     if (!_tcscmp(name, m_Options[i].name))
  1547.                     {
  1548.                         if (m_sOptionsCache[i].bCached)
  1549.                             break;
  1550.                         else
  1551.                         {
  1552.                             if (type == "numeric")
  1553.                             {
  1554.                                 if (m_Options[i].nType!=1)
  1555.                                     break;
  1556.                                 _int64 value64=_ttoi64(value);
  1557.                                 if (IsNumeric(value))
  1558.                                     SetOption(i+1, value64);
  1559.                             }
  1560.                             else
  1561.                             {
  1562.                                 if (m_Options[i].nType!=0)
  1563.                                     break;
  1564.                                 SetOption(i+1, value);
  1565.                             }
  1566.                         }
  1567.                         break;
  1568.                     }
  1569.                 }
  1570.             }
  1571.             ReadSpeedLimits(&xml);
  1572.  
  1573.             LeaveCritSection(m_Sync);
  1574.             UpdateInstances();
  1575.             return;
  1576.         }
  1577.     }
  1578.     LeaveCritSection(m_Sync);
  1579. }
  1580.