LCOV - code coverage report
Current view: top level - src - serverlist.cpp (source / functions) Hit Total Coverage
Test: report Lines: 69 143 48.3 %
Date: 2015-07-11 18:23:49 Functions: 8 11 72.7 %

          Line data    Source code
       1             : /*
       2             : Minetest
       3             : Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
       4             : 
       5             : This program is free software; you can redistribute it and/or modify
       6             : it under the terms of the GNU Lesser General Public License as published by
       7             : the Free Software Foundation; either version 2.1 of the License, or
       8             : (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 Lesser General Public License for more details.
      14             : 
      15             : You should have received a copy of the GNU Lesser General Public License along
      16             : with this program; if not, write to the Free Software Foundation, Inc.,
      17             : 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             : */
      19             : 
      20             : #include <fstream>
      21             : #include <iostream>
      22             : #include <sstream>
      23             : #include <algorithm>
      24             : 
      25             : #include "version.h"
      26             : #include "settings.h"
      27             : #include "serverlist.h"
      28             : #include "filesys.h"
      29             : #include "porting.h"
      30             : #include "log.h"
      31             : #include "network/networkprotocol.h"
      32             : #include "json/json.h"
      33             : #include "convert_json.h"
      34             : #include "httpfetch.h"
      35             : #include "util/string.h"
      36             : 
      37             : namespace ServerList
      38             : {
      39             : 
      40           6 : std::string getFilePath()
      41             : {
      42          12 :         std::string serverlist_file = g_settings->get("serverlist_file");
      43             : 
      44          12 :         std::string dir_path = "client" DIR_DELIM "serverlist" DIR_DELIM;
      45           6 :         fs::CreateDir(porting::path_user + DIR_DELIM  "client");
      46           6 :         fs::CreateDir(porting::path_user + DIR_DELIM + dir_path);
      47          12 :         return porting::path_user + DIR_DELIM + dir_path + serverlist_file;
      48             : }
      49             : 
      50             : 
      51           4 : std::vector<ServerListSpec> getLocal()
      52             : {
      53           8 :         std::string path = ServerList::getFilePath();
      54           8 :         std::string liststring;
      55           4 :         if (fs::PathExists(path)) {
      56           8 :                 std::ifstream istream(path.c_str());
      57           4 :                 if (istream.is_open()) {
      58           8 :                         std::ostringstream ostream;
      59           4 :                         ostream << istream.rdbuf();
      60           4 :                         liststring = ostream.str();
      61           4 :                         istream.close();
      62             :                 }
      63             :         }
      64             : 
      65           8 :         return deSerialize(liststring);
      66             : }
      67             : 
      68             : 
      69           0 : std::vector<ServerListSpec> getOnline()
      70             : {
      71           0 :         std::ostringstream geturl;
      72           0 :         geturl << g_settings->get("serverlist_url") <<
      73           0 :                 "/list?proto_version_min=" << CLIENT_PROTOCOL_VERSION_MIN <<
      74           0 :                 "&proto_version_max=" << CLIENT_PROTOCOL_VERSION_MAX;
      75           0 :         Json::Value root = fetchJsonValue(geturl.str(), NULL);
      76             : 
      77           0 :         std::vector<ServerListSpec> server_list;
      78             : 
      79           0 :         if (!root.isObject()) {
      80           0 :                 return server_list;
      81             :         }
      82             : 
      83           0 :         root = root["list"];
      84           0 :         if (!root.isArray()) {
      85           0 :                 return server_list;
      86             :         }
      87             : 
      88           0 :         for (unsigned int i = 0; i < root.size(); i++) {
      89           0 :                 if (root[i].isObject()) {
      90           0 :                         server_list.push_back(root[i]);
      91             :                 }
      92             :         }
      93             : 
      94           0 :         return server_list;
      95             : }
      96             : 
      97             : 
      98             : // Delete a server from the local favorites list
      99           1 : bool deleteEntry(const ServerListSpec &server)
     100             : {
     101           2 :         std::vector<ServerListSpec> serverlist = ServerList::getLocal();
     102           9 :         for (std::vector<ServerListSpec>::iterator it = serverlist.begin();
     103           6 :                         it != serverlist.end();) {
     104           3 :                 if ((*it)["address"] == server["address"] &&
     105           1 :                                 (*it)["port"] == server["port"]) {
     106           1 :                         it = serverlist.erase(it);
     107             :                 } else {
     108           1 :                         ++it;
     109             :                 }
     110             :         }
     111             : 
     112           2 :         std::string path = ServerList::getFilePath();
     113           2 :         std::ostringstream ss(std::ios_base::binary);
     114           1 :         ss << ServerList::serialize(serverlist);
     115           1 :         if (!fs::safeWriteToFile(path, ss.str()))
     116           0 :                 return false;
     117           1 :         return true;
     118             : }
     119             : 
     120             : // Insert a server to the local favorites list
     121           1 : bool insert(const ServerListSpec &server)
     122             : {
     123             :         // Remove duplicates
     124           1 :         ServerList::deleteEntry(server);
     125             : 
     126           2 :         std::vector<ServerListSpec> serverlist = ServerList::getLocal();
     127             : 
     128             :         // Insert new server at the top of the list
     129           1 :         serverlist.insert(serverlist.begin(), server);
     130             : 
     131           2 :         std::string path = ServerList::getFilePath();
     132           2 :         std::ostringstream ss(std::ios_base::binary);
     133           1 :         ss << ServerList::serialize(serverlist);
     134           1 :         if (!fs::safeWriteToFile(path, ss.str()))
     135           0 :                 return false;
     136             : 
     137           1 :         return true;
     138             : }
     139             : 
     140           4 : std::vector<ServerListSpec> deSerialize(const std::string &liststring)
     141             : {
     142           4 :         std::vector<ServerListSpec> serverlist;
     143           8 :         std::istringstream stream(liststring);
     144           8 :         std::string line, tmp;
     145          32 :         while (std::getline(stream, line)) {
     146          14 :                 std::transform(line.begin(), line.end(), line.begin(), ::toupper);
     147          14 :                 if (line == "[SERVER]") {
     148          14 :                         ServerListSpec server;
     149           7 :                         std::getline(stream, tmp);
     150           7 :                         server["name"] = tmp;
     151           7 :                         std::getline(stream, tmp);
     152           7 :                         server["address"] = tmp;
     153           7 :                         std::getline(stream, tmp);
     154           7 :                         server["port"] = tmp;
     155           7 :                         std::getline(stream, tmp);
     156           7 :                         server["description"] = tmp;
     157           7 :                         serverlist.push_back(server);
     158             :                 }
     159             :         }
     160           8 :         return serverlist;
     161             : }
     162             : 
     163           2 : const std::string serialize(const std::vector<ServerListSpec> &serverlist)
     164             : {
     165           2 :         std::string liststring;
     166          15 :         for (std::vector<ServerListSpec>::const_iterator it = serverlist.begin();
     167          10 :                         it != serverlist.end();
     168             :                         it++) {
     169           3 :                 liststring += "[server]\n";
     170           3 :                 liststring += (*it)["name"].asString() + '\n';
     171           3 :                 liststring += (*it)["address"].asString() + '\n';
     172           3 :                 liststring += (*it)["port"].asString() + '\n';
     173           3 :                 liststring += (*it)["description"].asString() + '\n';
     174           3 :                 liststring += '\n';
     175             :         }
     176           2 :         return liststring;
     177             : }
     178             : 
     179           0 : const std::string serializeJson(const std::vector<ServerListSpec> &serverlist)
     180             : {
     181           0 :         Json::Value root;
     182           0 :         Json::Value list(Json::arrayValue);
     183           0 :         for (std::vector<ServerListSpec>::const_iterator it = serverlist.begin();
     184           0 :                         it != serverlist.end();
     185             :                         it++) {
     186           0 :                 list.append(*it);
     187             :         }
     188           0 :         root["list"] = list;
     189           0 :         Json::FastWriter writer;
     190           0 :         return writer.write(root);
     191             : }
     192             : 
     193             : 
     194             : #if USE_CURL
     195           0 : void sendAnnounce(const std::string &action,
     196             :                 const u16 port,
     197             :                 const std::vector<std::string> &clients_names,
     198             :                 const double uptime,
     199             :                 const u32 game_time,
     200             :                 const float lag,
     201             :                 const std::string &gameid,
     202             :                 const std::string &mg_name,
     203             :                 const std::vector<ModSpec> &mods)
     204             : {
     205           0 :         Json::Value server;
     206           0 :         server["action"] = action;
     207           0 :         server["port"] = port;
     208           0 :         if (g_settings->exists("server_address")) {
     209           0 :                 server["address"] = g_settings->get("server_address");
     210             :         }
     211           0 :         if (action != "delete") {
     212           0 :                 bool strict_checking = g_settings->getBool("strict_protocol_version_checking");
     213           0 :                 server["name"]         = g_settings->get("server_name");
     214           0 :                 server["description"]  = g_settings->get("server_description");
     215           0 :                 server["version"]      = g_version_string;
     216           0 :                 server["proto_min"]    = strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MIN;
     217           0 :                 server["proto_max"]    = strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MAX;
     218           0 :                 server["url"]          = g_settings->get("server_url");
     219           0 :                 server["creative"]     = g_settings->getBool("creative_mode");
     220           0 :                 server["damage"]       = g_settings->getBool("enable_damage");
     221           0 :                 server["password"]     = g_settings->getBool("disallow_empty_password");
     222           0 :                 server["pvp"]          = g_settings->getBool("enable_pvp");
     223           0 :                 server["uptime"]       = (int) uptime;
     224           0 :                 server["game_time"]    = game_time;
     225           0 :                 server["clients"]      = (int) clients_names.size();
     226           0 :                 server["clients_max"]  = g_settings->getU16("max_users");
     227           0 :                 server["clients_list"] = Json::Value(Json::arrayValue);
     228           0 :                 for (std::vector<std::string>::const_iterator it = clients_names.begin();
     229           0 :                                 it != clients_names.end();
     230             :                                 ++it) {
     231           0 :                         server["clients_list"].append(*it);
     232             :                 }
     233           0 :                 if (gameid != "") server["gameid"] = gameid;
     234             :         }
     235             : 
     236           0 :         if (action == "start") {
     237           0 :                 server["dedicated"]         = g_settings->getBool("server_dedicated");
     238           0 :                 server["rollback"]          = g_settings->getBool("enable_rollback_recording");
     239           0 :                 server["mapgen"]            = mg_name;
     240           0 :                 server["privs"]             = g_settings->get("default_privs");
     241           0 :                 server["can_see_far_names"] = g_settings->getS16("player_transfer_distance") <= 0;
     242           0 :                 server["mods"]              = Json::Value(Json::arrayValue);
     243           0 :                 for (std::vector<ModSpec>::const_iterator it = mods.begin();
     244           0 :                                 it != mods.end();
     245             :                                 ++it) {
     246           0 :                         server["mods"].append(it->name);
     247             :                 }
     248           0 :                 actionstream << "Announcing to " << g_settings->get("serverlist_url") << std::endl;
     249             :         } else {
     250           0 :                 if (lag)
     251           0 :                         server["lag"] = lag;
     252             :         }
     253             : 
     254           0 :         Json::FastWriter writer;
     255           0 :         HTTPFetchRequest fetch_request;
     256           0 :         fetch_request.url = g_settings->get("serverlist_url") + std::string("/announce");
     257           0 :         fetch_request.post_fields["json"] = writer.write(server);
     258           0 :         fetch_request.multipart = true;
     259           0 :         httpfetch_async(fetch_request);
     260           0 : }
     261             : #endif
     262             : 
     263           3 : } //namespace ServerList

Generated by: LCOV version 1.11