Advertisement
Guest User

Untitled

a guest
Feb 8th, 2014
134
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 23.83 KB | None
  1. webservermanager.cpp:
  2.  
  3. #include "stdinc.h"
  4. #include "DCPlusPlus.h"
  5.  
  6. #include "WebServerManager.h"
  7.  
  8. #include "QueueManager.h"
  9. #include "FinishedManager.h"
  10. #include "ClientManager.h"
  11. #include "LogManager.h"
  12. #include "StringTokenizer.h"
  13.  
  14. WebServerManager* Singleton<WebServerManager>::instance = NULL;
  15.  
  16. WebServerManager::WebServerManager() : started(false), sended_search(false), hub(-1) {
  17.     SettingsManager::getInstance()->addListener(this);
  18.  
  19.     html_header1 =
  20.         "<html>\n"
  21.         "<head>\n"
  22.         "<title>ZouDC</title>\n"
  23.         "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n"
  24.         ;
  25.     html_header2 =
  26.         "<link rel=\"stylesheet\" type=\"text/css\" href=\"http://www.123gen.com/monstyle.css\">\n"
  27.         "<style type=\"text/css\">\n"
  28.         "body {\n"
  29.         "text-align: center;\n"
  30.         "cursor: url(http://www.123gen.com/curseur.ani)\n"
  31.         "}\n"
  32.         "td {\n"
  33.         "text-align: center;\n"
  34.         "font: x-small Georgia, \"Times New Roman\", Times, serif\n"
  35.         "}\n"
  36.         "</style>\n"
  37.         "</head>\n"
  38.         "\n"
  39.         "<body>\n"
  40.         "<h1><a href=\"index.html\" style=\"color: #FF962D\">Contr&ocirc;le de ZouDC par le web</a></h1>\n"
  41.         "<font face=\"Georgia, Times New Roman, Times, serif\" size=\"2\"><b>\n"
  42.         ;
  43.     html_footer =
  44.         "</blockquote>\n"
  45.         "</b></font>\n"
  46.         "</body>\n"
  47.         "</html>"
  48.         ;
  49.  
  50.     if(BOOLSETTING(WEBSERVER)) {
  51.         try {
  52.             Start();
  53.         } catch(const Exception&) { }
  54.     }
  55. }
  56.  
  57. WebServerManager::~WebServerManager() {
  58.     SettingsManager::getInstance()->removeListener(this);
  59.  
  60.     Stop();
  61. }
  62.  
  63. void WebServerManager::Restart() {
  64.     Stop();
  65.     Start();
  66. }
  67.  
  68. string WebServerManager::getLoginPage(bool mauvais_identifiants) {
  69.     string pagehtml =
  70.         html_header1 +
  71.         html_header2 +
  72.         "<blockquote>\n"
  73.         ;
  74.     if(mauvais_identifiants)
  75.         pagehtml += "<font color=\"#FF0000\">Mauvais identifiants</font>\n";
  76.     pagehtml +=
  77.         "<form method=\"post\" action=\"index.html\">\n"
  78.         "Login :\n"
  79.         "<input type=\"text\" name=\"login\" size=\"20\"><br>\n"
  80.         "Passe :\n"
  81.         "<input type=\"password\" name=\"passe\" size=\"20\"><br>\n"
  82.         "<input type=\"submit\" value=\"Connexion\">\n"
  83.         "</form>\n" +
  84.         html_footer
  85.         ;
  86.     return
  87.         "HTTP/1.1 200 OK\r\n"
  88.         "Content-Type: text/html\r\n"
  89.         "Content-Length: " + Util::toString((int)pagehtml.size()) + "\r\n"
  90.         "Connection: close\r\n"
  91.         "\r\n" +
  92.         pagehtml
  93.         ;
  94. }
  95.  
  96. string WebServerManager::getPage(const string& file) {
  97.     string header = "HTTP/1.1 200 OK\r\n", pagehtml = html_header1;
  98.     if(sended_search && (Util::stricmp(file.c_str(), "/rech.htm") == 0))
  99.         pagehtml += "<meta http-equiv=\"refresh\" content=\"10;URL=rech.htm?stop=true\">";
  100.     bool pas_dans_hub = ((Util::stricmp(file.c_str(), "/hub_.htm") != 0) && (Util::stricmp(file.c_str(), "/chat.htm") != 0));
  101.     if(pas_dans_hub) {
  102.         pagehtml +=
  103.             html_header2 +
  104.             "<a href=\"\"><img src=\"http://www.123gen.com/zoudc/barre.gif\" width=\"216\" height=\"24\" border=\"0\" usemap=\"#Barre\"></a>\n"
  105.             "<map name=\"Barre\">\n"
  106.             "<area shape=\"rect\" coords=\"0,0,24,24\" href=\"hubs.htm\" title=\"Hubs\">\n"
  107.             "<area shape=\"rect\" coords=\"24,0,48,24\" href=\"liste_dl.htm\" title=\"Liste de téléchargement\">\n"
  108.             "<area shape=\"rect\" coords=\"48,0,72,24\" href=\"dl_finis.htm\" title=\"Téléchargements termin&eacute;s\">\n"
  109.             "<area shape=\"rect\" coords=\"72,0,96,24\" href=\"ul_finis.htm\" title=\"Envois termin&eacute;s\">\n"
  110.             "<area shape=\"rect\" coords=\"96,0,120,24\" href=\"rech.htm\" title=\"Recherche\">\n"
  111.             "<area shape=\"rect\" coords=\"120,0,144,24\" href=\"log.htm\" title=\"Log\">\n"
  112.             "<area shape=\"rect\" coords=\"144,0,168,24\" href=\"options.htm\" title=\"Options\">\n"
  113.             "<area shape=\"rect\" coords=\"168,0,192,24\" href=\"arret.htm\" title=\"Arr&ecirc;t automatique\">\n"
  114.             "<area shape=\"rect\" coords=\"192,0,216,24\" href=\"notepad.htm\" title=\"Bloc-notes\">\n"
  115.             "</map>\n"
  116.             "<hr>\n"
  117.             "<blockquote>\n"
  118.             ;
  119.     }
  120.     int action_arret = -1;
  121.     if((Util::stricmp(file.c_str(), "/") == 0) || (Util::stricmp(file.c_str(), "/index.html") == 0)) {
  122.         pagehtml += "Temps de fonctionnement : " + Util::formatSeconds(Util::getUptime()) + "<br>\n";
  123.         StringList a_afficher = ClientManager::getInstance()->getStats();
  124.         for(StringIter id_for = a_afficher.begin(); id_for != a_afficher.end(); ++id_for)
  125.             pagehtml += *id_for + "<br>\n";
  126.     } else if(Util::stricmp(file.c_str(), "/hubs.htm") == 0) {
  127.         hubs.clear();
  128.         ClientManager* clientMgr = ClientManager::getInstance();
  129.         clientMgr->lock();
  130.         Client::List& clients = clientMgr->getClients();
  131.         for(Client::Iter i = clients.begin(); i != clients.end(); ++i) {
  132.             hubs.push_back((*i)->getAddressPort());
  133.             pagehtml += "<p><a href=\"hub.htm?hub=" + Util::toString(hubs.size() - 1) + "\">" + (*i)->getName() + "</a></p>\n";
  134.         }
  135.         clientMgr->unlock();
  136.     } else if(Util::stricmp(file.c_str(), "/hub.htm") == 0) {
  137.         chat = "";
  138.         pagehtml +=
  139.             "</blockquote>\n"
  140.             "<iframe name=\"cadre_hub_\" width=\"0\" height=\"0\" style=\"display: none; visibility: hidden\"></iframe>\n"
  141.             "<table width=\"90%\" height=\"50%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n"
  142.             "<tr>\n"
  143.             "<td>\n"
  144.             "<iframe name=\"cadre_chat\" src=\"chat.htm\" width=\"100%\" height=\"100%\" leftmargin=\"1\" topmargin=\"0\" marginwidth=\"1\" marginheight=\"0\"></iframe>\n"
  145.             "</td>\n"
  146.             "<td width=\"200\">\n"
  147.             "<iframe name=\"cadre_users\" width=\"100%\" height=\"100%\" leftmargin=\"1\" topmargin=\"0\" marginwidth=\"1\" marginheight=\"0\"></iframe>\n"
  148.             "</td>\n"
  149.             "</tr>\n"
  150.             "</table>\n"
  151.             "<blockquote>\n"
  152.             "<form name=\"form_envoi\" method=\"post\" action=\"hub_.htm\" target=\"cadre_hub_\" onSubmit=\"submit(); message.value=''; return false\">\n"
  153.             "<input type=\"text\" name=\"message\" size=\"86\">\n"
  154.             "<input type=\"submit\" value=\"Envoyer\">\n"
  155.             "</form>\n"
  156.             ;
  157.     } else if(Util::stricmp(file.c_str(), "/hub_.htm") == 0) {
  158.         pagehtml +=
  159.             "</head>\n"
  160.             "\n"
  161.             "<body>\n"
  162.             "<script language=\"JavaScript\">\n"
  163.             "with (parent){\n"
  164.             ;
  165.         if((hub >= 0) && (hub < (int)hubs.size())) {
  166.             fire(WebServerListener::CHAT_WEB, hubs[hub]);
  167.             pagehtml +=
  168.                 "with (cadre_chat.document){\n"
  169.                 "body.innerHTML=\"" + chat + "\";\n"
  170.                 "if (getElementById(\"fin\")){ getElementById(\"fin\").scrollIntoView(); }\n"
  171.                 "}\n"
  172.                 "cadre_users.document.body.innerHTML=\"" + users + "\";\n"
  173.                 "}\n"
  174.                 "setTimeout(\"location='hub_.htm'\", 1000);\n"
  175.                 ;
  176.         } else {
  177.             pagehtml +=
  178.                 "cadre_chat.document.body.innerHTML=\"\";\n"
  179.                 "cadre_users.document.body.innerHTML=\"\";\n"
  180.                 "}\n"
  181.                 ;
  182.         }
  183.         pagehtml +=
  184.             "</script>\n"
  185.             "</body>\n"
  186.             "</html>"
  187.             ;
  188.     } else if(Util::stricmp(file.c_str(), "/chat.htm") == 0) {
  189.         pagehtml +=
  190.             Util::styles +
  191.             "</head>\n"
  192.             "\n"
  193.             "<body onLoad=\"parent.cadre_hub_.location='hub_.htm'\">\n"
  194.             "</body>\n"
  195.             "</html>"
  196.             ;
  197.     } else if(Util::stricmp(file.c_str(), "/liste_dl.htm") == 0)
  198.         pagehtml += getDLQueue();
  199.     else if(Util::stricmp(file.c_str(), "/dl_finis.htm") == 0)
  200.         pagehtml += getFinished(false);
  201.     else if(Util::stricmp(file.c_str(), "/ul_finis.htm") == 0)
  202.         pagehtml += getFinished(true);
  203.     else if(Util::stricmp(file.c_str(), "/rech.htm") == 0)
  204.         pagehtml += getSearch();
  205.     else if(Util::stricmp(file.c_str(), "/log.htm") == 0) {
  206.         pagehtml +=
  207.             "<p align=\"left\">\n" +
  208.             fichier_HTML(Util::validateFileName(SETTING(LOG_DIRECTORY) + "Contrôle de ZouDC par le web.log")) +
  209.             "</p>\n"
  210.             ;
  211.     } else if(Util::stricmp(file.c_str(), "/options.htm") == 0) {
  212.         pagehtml +=
  213.             "<form method=\"get\" action=\"options.htm\">\n"
  214.             "<input type=\"checkbox\" name=\"deconnexion_lents\""
  215.             ;
  216.         if(BOOLSETTING(DISCONNECTING_ENABLE))
  217.             pagehtml += " checked";
  218.         pagehtml +=
  219.             ">Activer la d&eacute;connexion des utilisateurs lents<br>\n"
  220.             "<input type=\"checkbox\" name=\"limiter\""
  221.             ;
  222.         if(BOOLSETTING(THROTTLE_ENABLE))
  223.             pagehtml += " checked";
  224.         pagehtml +=
  225.             ">Limiter la bande passante<br>\n"
  226.             "<input type=\"submit\" name=\"options\" value=\"Ok !\">\n"
  227.             "</form>\n"
  228.             ;
  229.     } else if(Util::stricmp(file.c_str(), "/arret.htm") == 0)
  230.         pagehtml +=
  231.         "<p><a href=\"eteindre.htm\">&Eacute;teindre l'ordinateur</a></p>\n"
  232.         "<p><a href=\"session.htm\">Fermer la session</a></p>\n"
  233.         "<p><a href=\"redem.htm\">Red&eacute;marrer l'ordinateur</a></p>\n"
  234.         "<p><a href=\"quitter.htm\">Quitter ZouDC</a></p>\n"
  235.         ;
  236.     else if(Util::stricmp(file.c_str(), "/eteindre.htm") == 0)
  237.         action_arret = 0;
  238.     else if(Util::stricmp(file.c_str(), "/session.htm") == 0)
  239.         action_arret = 1;
  240.     else if(Util::stricmp(file.c_str(), "/redem.htm") == 0)
  241.         action_arret = 2;
  242.     else if(Util::stricmp(file.c_str(), "/quitter.htm") == 0)
  243.         action_arret = 3;
  244.     else if(Util::stricmp(file.c_str(), "/notepad.htm") == 0) {
  245.         pagehtml +=
  246.             "<p align=\"left\">\n" +
  247.             fichier_HTML(Util::getAppPath() + "Notepad.txt") +
  248.             "</p>\n"
  249.             ;
  250.     } else {
  251.         header = "HTTP/1.1 404 Not Found\r\n";
  252.         pagehtml += "Page introuvable\n";
  253.     }
  254.     if(action_arret != -1) {
  255.         fire(WebServerListener::ARRET, action_arret);
  256.         pagehtml +=
  257.             "Demande d'arr&ecirc;t envoy&eacute;e<br>\n"
  258.             "Temps avant l'arr&ecirc;t : " + Util::toTime(SETTING(SHUTDOWN_TIMEOUT)) + "\n"
  259.             ;
  260.     }
  261.     if(pas_dans_hub) {
  262.         pagehtml +=
  263.             "</blockquote>\n"
  264.             "<hr>\n"
  265.             "<blockquote>\n"
  266.             "<a href=\"javascript:location.reload()\">Rafra&icirc;chir</a> - <a href=\"index.html\">Retour à la page d'accueil</a> - <a href=\"?deconnexion=1\">D&eacute;connexion</a>\n" +
  267.             html_footer
  268.             ;
  269.     }
  270.     header +=
  271.         "Content-Type: text/html\r\n"
  272.         "Content-Length: " + Util::toString((int)pagehtml.size()) + "\r\n"
  273.         "Connection: close\r\n"
  274.         "\r\n"
  275.         ;
  276.     return header + pagehtml;
  277. }
  278.  
  279. void WebServerManager::search(string search_str, int search_type) {
  280.     if(!sended_search) {
  281.         int i = 0;
  282.         while((i = search_str.find("+", i)) != string::npos) {
  283.             search_str.replace(i, 1, " ");
  284.             i++;
  285.         }
  286.         if((SearchManager::TypeModes)search_type == SearchManager::TYPE_HASH)
  287.             search_str = "TTH:" + search_str;
  288.         SearchManager::getInstance()->addListener(this);
  289.         SearchManager::getInstance()->search(search_str, (SearchManager::TypeModes)search_type);
  290.         results = Util::emptyString;
  291.         row = 0;
  292.         sended_search = true;
  293.     }
  294. }
  295.  
  296. void WebServerManager::reset() {
  297.     row = 0;
  298.     SearchManager::getInstance()->removeListener(this);
  299. }
  300.  
  301. void WebServerManager::Start() {
  302.     if(started)
  303.         return;
  304.  
  305.     Lock l(cs);
  306.     started = true;
  307.  
  308.     socket.addListener(this);
  309.     socket.waitForConnections((uint16_t)SETTING(WEBSERVER_PORT));
  310.     fire(WebServerListener::SETUP);
  311. }
  312.  
  313. void WebServerManager::Stop() {
  314.     if(!started)
  315.         return;
  316.  
  317.     started = false;
  318.     Lock l(cs);
  319.  
  320.     socket.removeListener(this);
  321.     socket.disconnect();
  322. }
  323.  
  324. string WebServerManager::getDLQueue() {
  325.     string ret =
  326.         "</blockquote>\n"
  327.         "<table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n"
  328.         "<tr>\n"
  329.         "<td><b>Nom du fichier</b></td>\n"
  330.         "<td><b>Taille</b></td>\n"
  331.         "<td><b>T&eacute;l&eacute;charg&eacute;</b></td>\n"
  332.         "</tr>\n"
  333.         ;
  334.     const QueueItem::StringMap& li = QueueManager::getInstance()->lockQueue();
  335.     for(QueueItem::StringMap::const_iterator j = li.begin(); j != li.end(); ++j) {
  336.         QueueItem* aQI = j->second;
  337.         double percent = (aQI->getSize() > 0) ? aQI->getDownloadedBytes() * 100.0 / aQI->getSize() : 0;
  338.         ret +=
  339.             "<tr>\n"
  340.             "<td>" + aQI->getTargetFileName() + "</td>\n"
  341.             "<td>" + Util::formatBytes(aQI->getSize()) + "</td>\n"
  342.             "<td>" + Util::formatBytes(aQI->getDownloadedBytes()) + " (" + Util::toString(percent) + "%)</td>\n"
  343.             "</tr>\n"
  344.             ;
  345.     }
  346.     QueueManager::getInstance()->unlockQueue();
  347.     ret +=
  348.         "</table>\n"
  349.         "<blockquote>\n"
  350.         ;
  351.     return ret;
  352. }
  353.  
  354. string WebServerManager::getFinished(bool uploads) {
  355.     string ret =
  356.         "</blockquote>\n"
  357.         "<table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n"
  358.         "<tr>\n"
  359.         "<td><b>Temps</b></td>\n"
  360.         "<td><b>Fichier</b></td>\n"
  361.         "<td><b>Taille</b></td>\n"
  362.         "</tr>\n"
  363.         ;
  364.     const FinishedItem::List& fl = FinishedManager::getInstance()->lockList(uploads);
  365.     for(FinishedItem::List::const_iterator i = fl.begin(); i != fl.end(); ++i) {
  366.         ret +=
  367.             "<tr>\n"
  368.             "<td>" + Util::formatTime(SETTING(TIMESTAMPS_LOGS), (*i)->getTime()) + "</td>\n"
  369.             "<td>" + Util::getFileName((*i)->getTarget()) + "</td>\n"
  370.             "<td>" + Util::formatBytes((*i)->getSize()) + "</td>\n"
  371.             "</tr>\n"
  372.             ;
  373.     }
  374.     FinishedManager::getInstance()->unlockList();
  375.     ret +=
  376.         "</table>\n"
  377.         "<blockquote>\n"
  378.         ;
  379.     return ret;
  380. }
  381.  
  382. string WebServerManager::getSearch() {
  383.     string ret = "<form method=\"post\" action=\"rech.htm\" enctype=\"multipart/form-data\">\n";
  384.     if(sended_search) {
  385.         ret +=
  386.             "Recherche en cours...<br>\n"
  387.             "<input type=\"submit\" name=\"stop\" value=\"Arr&ecirc;ter la recherche\">\n"
  388.             "</form>\n"
  389.             ;
  390.         sended_search = false;
  391.     } else {
  392.         ret +=
  393.             "Rechercher :\n"
  394.             "<input type=\"text\" name=\"recherche\" size=\"20\"><br>\n"
  395.             "<select name=\"type\">\n"
  396.             "<option value=\"0\" selected>Tous</option>\n"
  397.             "<option value=\"1\">Audio</option>\n"
  398.             "<option value=\"2\">Fichier compressé</option>\n"
  399.             "<option value=\"3\">Document</option>\n"
  400.             "<option value=\"4\">Programme</option>\n"
  401.             "<option value=\"5\">Image</option>\n"
  402.             "<option value=\"6\">Vidéo</option>\n"
  403.             "<option value=\"7\">Dossier</option>\n"
  404.             "<option value=\"8\">TTH</option>\n"
  405.             "</select><br>\n"
  406.             "<input type=\"submit\" value=\"Recherche\">\n"
  407.             "</form>\n"
  408.             ;
  409.         if(!results.empty()) {
  410.             ret +=
  411.                 "</blockquote>\n"
  412.                 "<table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n"
  413.                 "<tr>\n"
  414.                 "<td><b>Utilisateur</b></td>\n"
  415.                 "<td><b>Fichier</b></td>\n"
  416.                 "<td><b>Taille</b></td>\n"
  417.                 "<td><b>TTH</b></td>\n"
  418.                 "</tr>\n" +
  419.                 results +
  420.                 "</table>\n"
  421.                 ;
  422.         }
  423.         results = Util::emptyString;
  424.     }
  425.     return ret;
  426. }
  427.  
  428. string WebServerManager::fichier_HTML(const string& chemin) {
  429.     string a_retourner;
  430.     try {
  431.         a_retourner = File(chemin, File::READ, File::OPEN).read();
  432.     } catch (const FileException&) { }
  433.     if(!a_retourner.empty())
  434.         Util::remplacer("\r\n", "<br>\n", a_retourner);
  435.     return a_retourner;
  436. }
  437.  
  438. // ServerSocketListener
  439. void WebServerManager::onAction(ServerSocketListener::Types type) throw() {
  440.     if(type == ServerSocketListener::INCOMING_CONNECTION) {
  441.         WebServerSocket* wss = new WebServerSocket();
  442.         wss->accept(&socket);
  443.         wss->start();
  444.     }
  445. }
  446.  
  447. // SettingsManagerListener
  448. void WebServerManager::onAction(SettingsManagerListener::Types type, SimpleXML* /*xml*/) throw() {
  449.     if((type == SettingsManagerListener::LOAD) || (type == SettingsManagerListener::SAVE))
  450.         BOOLSETTING(WEBSERVER) ? Restart() : Stop();
  451. }
  452.  
  453. // SearchManagerListener
  454. void WebServerManager::onAction(SearchManagerListener::Types type, SearchResult* sr) throw() {
  455.     if(type == SearchManagerListener::SEARCH_RESULT) {
  456.         {
  457.             Lock l(cs);
  458.             if(sr->getType() == SearchResult::TYPE_FILE) {
  459.                 string TTH = (sr->getTTH() == NULL) ? Util::emptyString : sr->getTTH()->toBase32();
  460.                 results +=
  461.                     "<tr style=\"cursor: hand\" onMouseOver=\"this.style.background='#DEFFBD'\" onMouseOut=\"this.style.background=''\" onClick=\"form" + Util::toString(row) + ".submit()\">\n"
  462.                     "<td>\n"
  463.                     "<form method=\"post\" name=\"form" + Util::toString(row) + "\" action=\"rech.htm\">\n"
  464.                     "<input type=\"hidden\" name=\"taille\" value=\"" + Util::toString(sr->getSize()) + "\">\n"
  465.                     "<input type=\"hidden\" name=\"fichier\" value=\"" + sr->getFileName() + "\">\n"
  466.                     "<input type=\"hidden\" name=\"tth\" value=\"" + TTH + "\">\n"
  467.                     "<input type=\"hidden\" name=\"type\" value=\"" + Util::toString(sr->getType()) + "\">\n"
  468.                     "</form>\n" +
  469.                     sr->getUser()->getNick() + "\n"
  470.                     "</td>\n"
  471.                     "<td>" + sr->getFileName() + "</td>\n"
  472.                     "<td>" + Util::formatBytes(sr->getSize()) + "</td>\n"
  473.                     "<td>" + (TTH.empty() ? "Pas de TTH" : "<span title=\"" + TTH + "\">" + TTH.substr(0, 2) + "..." + TTH.substr(TTH.size() - 2) + "</span>") + "</td>\n"
  474.                     "</tr>\n"
  475.                     ;
  476.                 row++;
  477.             }
  478.         }
  479.     }
  480. }
  481.  
  482. void WebServerSocket::accept(ServerSocket* s) {
  483.     int fromlen = sizeof(from);
  484.     sock = ::accept(s->getSocket(), (struct sockaddr*)&from, &fromlen);
  485.     u_long b = 1;
  486.     ::ioctlsocket(sock, FIONBIO, &b);
  487. }
  488.  
  489. string WebServerSocket::erreur(const string& contenu) {
  490.     return
  491.         "HTTP/1.1 " + contenu + "\r\n"
  492.         "Connection: close\r\n"
  493.         "\r\n"
  494.         ;
  495. }
  496.  
  497. StringMap WebServerSocket::getArgs(const string& arguments) {
  498.     StringMap args;
  499.     string::size_type i, j = 0, idx;
  500.     while((i = arguments.find("=", j)) != string::npos) {
  501.         string key = arguments.substr(j, i - j), value = arguments.substr(i + 1);
  502.         j = i + 1;
  503.         if((i = arguments.find("&", j)) != string::npos) {
  504.             value = arguments.substr(j, i - j);
  505.             j = i + 1;
  506.         }
  507.         for(idx = 0; idx < value.size(); ++idx) {
  508.             if((value.size() > (idx + 2)) && (value[idx] == '%') && isxdigit(value[idx + 1]) && isxdigit(value[idx + 2])) {
  509.                 value[idx] = Util::fromHexEscape(value.substr(idx + 1, 2));
  510.                 value.erase(idx + 1, 2);
  511.             } else if(value[idx] == '+')
  512.                 value[idx] = ' ';
  513.         }
  514.         args[key] = value;
  515.     }
  516.     return args;
  517. }
  518.  
  519. int WebServerSocket::run() {
  520.     string requete;
  521.     int compteur = 0;
  522.     while(true) {
  523.         if(++compteur > 10000)
  524.             break;
  525.         u_long restants;
  526.         if(::ioctlsocket(sock, FIONREAD, &restants) == SOCKET_ERROR)
  527.             continue;
  528.         if(restants > 0) {
  529.             char* buffeur = new char[restants + 1];
  530.             int recus = ::recv(sock, buffeur, restants, 0);
  531.             if((recus != SOCKET_ERROR) && (recus > 0))
  532.                 requete.append(buffeur, recus);
  533.             delete[] buffeur;
  534.             continue;
  535.         }
  536.         if(requete.empty())
  537.             continue;
  538.         string::size_type fin = requete.find("\r\n");
  539.         if(fin == string::npos)
  540.             continue;
  541.         string a_envoyer;
  542.         StringList champs = StringTokenizer(requete.substr(0, fin), ' ').getTokens();
  543.         if(champs.size() == 3) {
  544.             if((champs[2] == "HTTP/1.0") || (champs[2] == "HTTP/1.1")) {
  545.                 bool par_POST = (champs[0] == "POST");
  546.                 if(par_POST) {
  547.                     string::size_type debut = requete.find("Content-Length: ");
  548.                     if(debut == string::npos) {
  549.                         if(requete.find("\r\n\r\n") != string::npos)
  550.                             a_envoyer = erreur("411 Length Required");
  551.                         else
  552.                             continue;
  553.                     } else {
  554.                         debut += 16;
  555.                         fin = requete.find("\r\n", debut);
  556.                         if(fin == string::npos)
  557.                             continue;
  558.                         if(fin == debut)
  559.                             a_envoyer = erreur("400 Bad Request");
  560.                         else {
  561.                             int64_t content_length = Util::toInt64(requete.substr(debut, fin - debut));
  562.                             if(content_length < 0)
  563.                                 a_envoyer = erreur("400 Bad Request");
  564.                             else {
  565.                                 debut = requete.find("\r\n\r\n");
  566.                                 if((debut == string::npos) || ((requete.size() - debut - 4) != content_length))
  567.                                     continue;
  568.                             }
  569.                         }
  570.                     }
  571.                 }
  572.                 if((par_POST && a_envoyer.empty()) || (champs[0] == "GET")) {
  573.                     if(champs[1].empty())
  574.                         a_envoyer = erreur("400 Bad Request");
  575.                     else {
  576.                         string IP = Util::toString(from.sin_addr.S_un.S_un_b.s_b1) + '.' + Util::toString(from.sin_addr.S_un.S_un_b.s_b2) + '.' + Util::toString(from.sin_addr.S_un.S_un_b.s_b3) + '.' + Util::toString(from.sin_addr.S_un.S_un_b.s_b4);
  577.  
  578.                         if(BOOLSETTING(LOG_WEBSERVER) && (Util::stricmp(champs[1].c_str(), "/hub_.htm") != 0) && (Util::stricmp(champs[1].c_str(), "/chat.htm") != 0))
  579.                             LOGDT("Contrôle de ZouDC par le web", IP + " : " + champs[1]);
  580.  
  581.                         bool mauvais_identifiants = false;
  582.  
  583.                         string::size_type start = par_POST ? requete.rfind("\r\n") : champs[1].find("?");
  584.                         if(start != string::npos) {
  585.                             StringMap m = getArgs(par_POST ? requete.substr(start + 2) : champs[1].substr(start + 1));
  586.  
  587.                             if(par_POST && (!m["login"].empty())) {
  588.                                 if((m["login"] == SETTING(WEBSERVER_LOGIN)) && (m["passe"] == SETTING(WEBSERVER_PASSE)))
  589.                                     WebServerManager::getInstance()->setLogin_IP(IP);
  590.                                 else
  591.                                     mauvais_identifiants = true;
  592.                             }
  593.  
  594.                             if(WebServerManager::getInstance()->getLogin_IP() == IP) {
  595.                                 if(!m["deconnexion"].empty())
  596.                                     WebServerManager::getInstance()->setLogin_IP("");
  597.  
  598.                                 if(!m["recherche"].empty())
  599.                                     WebServerManager::getInstance()->search(m["recherche"], Util::toInt(m["type"]));
  600.                                 if(!m["stop"].empty())
  601.                                     WebServerManager::getInstance()->reset();
  602.                                 if(!m["fichier"].empty())
  603.                                     QueueManager::getInstance()->add(m["fichier"], Util::toInt64(m["taille"]), m["tth"]);
  604.  
  605.                                 if(!m["hub"].empty())
  606.                                     WebServerManager::getInstance()->setHub(Util::toInt(m["hub"]));
  607.                                 if(!m["message"].empty()) {
  608.                                     string hub_courant = WebServerManager::getInstance()->hub_courant();
  609.                                     if(!hub_courant.empty())
  610.                                         WebServerManager::getInstance()->fire(WebServerListener::MESSAGE_HUB, hub_courant, m["message"]);
  611.                                 }
  612.  
  613.                                 if(!m["options"].empty()) {
  614.                                     SettingsManager::getInstance()->set(SettingsManager::DISCONNECTING_ENABLE, !m["deconnexion_lents"].empty());
  615.                                     SettingsManager::getInstance()->set(SettingsManager::THROTTLE_ENABLE, !m["limiter"].empty());
  616.                                     WebServerManager::getInstance()->fire(WebServerListener::LIMITATION, !m["limiter"].empty());
  617.                                 }
  618.                             }
  619.                         }
  620.  
  621.                         a_envoyer = (WebServerManager::getInstance()->getLogin_IP() == IP) ? WebServerManager::getInstance()->getPage(par_POST ? champs[1] : champs[1].substr(0, start)) : WebServerManager::getInstance()->getLoginPage(mauvais_identifiants);
  622.                     }
  623.                 } else
  624.                     a_envoyer = erreur("501 Not Implemented");
  625.             } else
  626.                 a_envoyer = erreur("505 Version not supported");
  627.         } else
  628.             a_envoyer = erreur("400 Bad Request");
  629.         if(!a_envoyer.empty())
  630.             ::send(sock, a_envoyer.c_str(), a_envoyer.size(), 0);
  631.         break;
  632.     }
  633.     ::closesocket(sock);
  634.     delete this;
  635.     return 0;
  636. }
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645. webservermanager.h:
  646.  
  647.  
  648.  
  649. #ifndef ZOUDC_CLIENT_WEBSERVERMANAGER_H
  650. #define ZOUDC_CLIENT_WEBSERVERMANAGER_H
  651.  
  652. #pragma once
  653.  
  654. #include "ServerSocket.h"
  655. #include "SettingsManager.h"
  656. #include "SearchManager.h"
  657.  
  658. class WebServerListener {
  659. public:
  660.     enum Types {
  661.         SETUP,
  662.         CHAT_WEB,
  663.         MESSAGE_HUB,
  664.         LIMITATION,
  665.         ARRET
  666.     };
  667.  
  668.     virtual void onAction(Types) throw() { }
  669.     virtual void onAction(Types, const string&) throw() { }
  670.     virtual void onAction(Types, const string&, const string&) throw() { }
  671.     virtual void onAction(Types, bool) throw() { }
  672.     virtual void onAction(Types, int) throw() { }
  673. };
  674.  
  675. class WebServerManager : public Singleton<WebServerManager>, public ServerSocketListener, public Speaker<WebServerListener>, private SettingsManagerListener, private SearchManagerListener
  676. {
  677. private:
  678.     friend Singleton<WebServerManager>;
  679.  
  680.     WebServerManager();
  681.     ~WebServerManager();
  682.  
  683. public:
  684.     void Restart();
  685.  
  686.     string getLoginPage(bool mauvais_identifiants);
  687.     string getPage(const string& file);
  688.  
  689.     void search(string search_str, int search_type);
  690.     void reset();
  691.  
  692.     ServerSocket& getServerSocket() { return socket; }
  693.  
  694.     void setHub(int hub_) { hub = hub_; }
  695.     string hub_courant() { return ((hub >= 0) && (hub < (int)hubs.size())) ? hubs[hub] : ""; }
  696.     void setChat(const string& chat_) { chat = chat_; }
  697.     void setUsers(const string& users_) { users = users_; }
  698.  
  699.     GETSET(string, login_IP, Login_IP);
  700.  
  701. private:
  702.     ServerSocket socket;
  703.  
  704.     string html_header1, html_header2, html_footer;
  705.  
  706.     StringList hubs;
  707.     int hub;
  708.     string chat, users;
  709.  
  710.     bool started, sended_search;
  711.     string results;
  712.  
  713.     int row; // Counter to permit FireFox correct item clicks
  714.  
  715.     CriticalSection cs;
  716.  
  717.     void Start();
  718.     void Stop();
  719.  
  720.     string getDLQueue();
  721.     string getFinished(bool uploads);
  722.     string getSearch();
  723.     string fichier_HTML(const string& chemin);
  724.  
  725.     // ServerSocketListener
  726.     virtual void onAction(ServerSocketListener::Types type) throw();
  727.  
  728.     // SettingsManagerListener
  729.     virtual void onAction(SettingsManagerListener::Types type, SimpleXML* /*xml*/) throw();
  730.  
  731.     // SearchManagerListener
  732.     virtual void onAction(SearchManagerListener::Types type, SearchResult* sr) throw();
  733. };
  734.  
  735. class WebServerSocket : public Thread {
  736. public:
  737.     void accept(ServerSocket* s);
  738.  
  739.     inline string erreur(const string& contenu);
  740.     StringMap getArgs(const string& arguments);
  741.  
  742.     virtual int run();
  743.  
  744. private:
  745.     sockaddr_in from;
  746.     SOCKET sock;
  747. };
  748.  
  749. #endif
Advertisement
RAW Paste Data Copied
Advertisement