Guest User

Untitled

a guest
Feb 11th, 2017
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 39.06 KB | None | 0 0
  1. <?php
  2.  /*----------------------------------------------------------------------------------------------------------\
  3.  |                                                                                                            |
  4.  |                      [ LIVE GAME SERVER LIST ] [  RICHARD PERRY FROM GREYCUBE.COM ]                       |
  5.  |                                                                                                            |
  6.  |    Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org)    |
  7.  |                                                                                                            |
  8.  \-----------------------------------------------------------------------------------------------------------*/
  9.  
  10. //------------------------------------------------------------------------------------------------------------+
  11. //------------------------------------------------------------------------------------------------------------+
  12.  
  13.   if (!function_exists('lgsl_url_path')) { // START OF DOUBLE LOAD PROTECTION
  14.  
  15. //------------------------------------------------------------------------------------------------------------+
  16. //------------------------------------------------------------------------------------------------------------+
  17.  
  18.   function lgsl_bg($rotation_overide = "no")
  19.   {
  20.     global $lgsl_config;
  21.     global $lgsl_bg_rotate;
  22.  
  23.     if ($rotation_overide !== "no")
  24.     {
  25.       $lgsl_bg_rotate = $rotation_overide ? TRUE : FALSE;
  26.     }                                                                          
  27.     else
  28.     {
  29.       $lgsl_bg_rotate = $lgsl_bg_rotate ? FALSE : TRUE;
  30.     }
  31.  
  32.     $background = $lgsl_bg_rotate ? $lgsl_config['background'][1] : $lgsl_config['background'][2];
  33.  
  34.     return $background;
  35.   }
  36.  
  37. //------------------------------------------------------------------------------------------------------------+
  38.  
  39.   function lgsl_link($s = "")
  40.   {
  41.     global $lgsl_config, $lgsl_url_path;
  42.  
  43.     $index = $lgsl_config['direct_index'] ? "index.php" : "";
  44.  
  45.     switch($lgsl_config['cms'])
  46.     {
  47.       case "e107":
  48.         $link = $s ? e_PLUGIN."lgsl/{$index}?s={$s}" : e_PLUGIN."lgsl/{$index}";
  49.       break;
  50.  
  51.       case "joomla":
  52.         $link = $s ? JRoute::_("index.php?option=com_lgsl&s={$s}") : JRoute::_("index.php?option=com_lgsl");
  53.       break;
  54.  
  55.       case "drupal":
  56.         $link = $s ? url("LGSL/{$s}") : url("LGSL");
  57.       break;
  58.  
  59.       case "phpnuke":
  60.         $link = $s ? "modules.php?name=LGSL&s={$s}" : "modules.php?name=LGSL";
  61.       break;
  62.  
  63.       default: // "sa"
  64.         $link = $s ? $lgsl_url_path."../{$index}?s={$s}" : $lgsl_url_path."../{$index}";
  65.       break;
  66.     }
  67.  
  68.     return $link;
  69.   }
  70.  
  71. //------------------------------------------------------------------------------------------------------------+
  72.  
  73. function lgsl_database()
  74.   {
  75.     global $enlace, $lgsl_config, $lgsl_file_path;
  76.  
  77.     if (!isset($lgsl_config['db']['prefix']))
  78.     {
  79.       $lgsl_config['db']['prefix'] = "";
  80.     }
  81.  
  82.     if (!$lgsl_config['db']['pass'])
  83.     {
  84.       switch($lgsl_config['cms'])
  85.       {
  86.         case "e107":
  87.           @include "{$lgsl_file_path}../../../e107_config.php";
  88.           $lgsl_config['db']['server'] = $mySQLserver;
  89.           $lgsl_config['db']['user']   = $mySQLuser;
  90.           $lgsl_config['db']['pass']   = $mySQLpassword;
  91.           $lgsl_config['db']['db']     = $mySQLdefaultdb;
  92.           $lgsl_config['db']['prefix'] = $mySQLprefix;
  93.         break;
  94.  
  95.         case "joomla":
  96.           @include_once "{$lgsl_file_path}../../../configuration.php";
  97.           $joomla_config = new JConfig();
  98.           $lgsl_config['db']['server'] = $joomla_config->host;
  99.           $lgsl_config['db']['user']   = $joomla_config->user;
  100.           $lgsl_config['db']['pass']   = $joomla_config->password;
  101.           $lgsl_config['db']['db']     = $joomla_config->db;
  102.           $lgsl_config['db']['prefix'] = $joomla_config->dbprefix;
  103.         break;
  104.  
  105.         case "drupal":
  106.           global $db_url, $db_prefix;
  107.           if (empty($db_url)) { @include "{$lgsl_file_path}../../../sites/default/settings.php"; }
  108.           $drupal_config = is_array($db_url) ? parse_url($db_url['default']) : parse_url($db_url);
  109.           $lgsl_config['db']['server'] = $drupal_config['host'];
  110.           $lgsl_config['db']['user']   = $drupal_config['user'];
  111.           $lgsl_config['db']['pass']   = isset($drupal_config['pass']) ? $drupal_config['pass'] : "";
  112.           $lgsl_config['db']['db']     = substr($drupal_config['path'], 1);
  113.           $lgsl_config['db']['prefix'] = isset($db_prefix['default']) ? $db_prefix['default'] : "";
  114.         break;
  115.  
  116.         case "phpnuke":
  117.           @include "{$lgsl_file_path}../../../config.php";
  118.           @include "{$lgsl_file_path}../../../conf.inc.php";
  119.           @include "{$lgsl_file_path}../../../includes/config.php";
  120.           $lgsl_config['db']['server'] = $dbhost;
  121.           $lgsl_config['db']['user']   = $dbuname;
  122.           $lgsl_config['db']['pass']   = $dbpass;
  123.           $lgsl_config['db']['db']     = $dbname;
  124.           $lgsl_config['db']['prefix'] = $prefix."_";
  125.         break;
  126.       }
  127.     }
  128.  
  129.     $lgsl_database = mysqli_connect($lgsl_config['db']['server'], $lgsl_config['db']['user'], $lgsl_config['db']['pass'], $lgsl_config['db']['db']);
  130.  
  131.     if(mysqli_connect_errno()) {
  132.       die('Falla en la conexion: '.mysqli_connect_error());
  133.     }
  134.  
  135.     return $lgsl_database;
  136.   }
  137.  
  138. //------------------------------------------------------------------------------------------------------------+
  139.  
  140.   function lgsl_query_cached($type, $ip, $c_port, $q_port, $s_port, $request, $id = NULL)
  141.   {
  142.     global $lgsl_config;
  143.  
  144.     $enlace = lgsl_database();
  145.  
  146.     // LOOKUP SERVER
  147.  
  148.     if ($id != NULL)
  149.     {
  150.       $id           = intval($id);
  151.       $mysql_query  = "SELECT * FROM `{$lgsl_config['db']['prefix']}{$lgsl_config['db']['table']}` WHERE `id`='{$id}' LIMIT 1";
  152.       $mysql_result = mysqli_query($enlace, $mysql_query) or die(mysqli_error($enlace));
  153.       $mysql_row    = mysqli_fetch_array($mysql_result, MYSQLI_ASSOC);
  154.       if (!$mysql_row) { return FALSE; }
  155.       list($type, $ip, $c_port, $q_port, $s_port) = array($mysql_row['type'], $mysql_row['ip'], $mysql_row['c_port'], $mysql_row['q_port'], $mysql_row['s_port']);
  156.     }
  157.     else
  158.     {
  159.       list($type, $ip, $c_port, $q_port, $s_port) = array(mysqli_real_escape_string($enlace, $type), mysqli_real_escape_string($enlace, $ip), intval($c_port), intval($q_port), intval($s_port));
  160.  
  161.       if (!$type || !$ip || !$c_port || !$q_port) { exit("LGSL PROBLEM: INVALID SERVER '{$type} : {$ip} : {$c_port} : {$q_port} : {$s_port}'"); }
  162.       $mysql_query  = "SELECT * FROM `{$lgsl_config['db']['prefix']}{$lgsl_config['db']['table']}` WHERE `type`='{$type}' AND `ip`='{$ip}' AND `q_port`='{$q_port}' LIMIT 1";
  163.       $mysql_result = mysqli_query($enlace, $mysql_query) or die(mysqli_error($enlace));
  164.       $mysql_row    = mysqli_fetch_array($mysql_result, MYSQLI_ASSOC);
  165.       if (!$mysql_row)
  166.       {
  167.         if (strpos($request, "a") === FALSE) { exit("LGSL PROBLEM: SERVER NOT IN DATABASE '{$type} : {$ip} : {$c_port} : {$q_port} : {$s_port}'"); }
  168.         $mysql_query  = "INSERT INTO `{$lgsl_config['db']['prefix']}{$lgsl_config['db']['table']}` (`type`,`ip`,`c_port`,`q_port`,`s_port`,`cache`,`cache_time`) VALUES ('{$type}','{$ip}','{$c_port}','{$q_port}','{$s_port}','','')";
  169.         $mysql_result = mysqli_query($enlace, $mysql_query) or die(mysqli_error($enlace));
  170.         $mysql_row    = array("id"=>mysqli_insert_id($enlace), "zone"=>"0", "comment"=>"");
  171.       }
  172.  
  173.       mysqli_free_result($mysql_query);
  174.     }
  175.  
  176.     // UNPACK CACHE AND CACHE TIMES
  177.  
  178.     $cache      = empty($mysql_row['cache'])      ? array()      : unserialize(base64_decode($mysql_row['cache']));
  179.     $cache_time = empty($mysql_row['cache_time']) ? array(0,0,0) : explode("_", $mysql_row['cache_time']);
  180.  
  181.     // SET THE SERVER AS OFFLINE AND PENDING WHEN THERE IS NO CACHE
  182.  
  183.     if (empty($cache['b']) || !is_array($cache))
  184.     {
  185.       $cache      = array();
  186.       $cache['b'] = array();
  187.       $cache['b']['status']  = 0;
  188.       $cache['b']['pending'] = 1;
  189.     }
  190.  
  191.     // CONVERT HOSTNAME TO IP WHEN NEEDED
  192.  
  193.     if ($lgsl_config['host_to_ip'])
  194.     {
  195.       $ip = gethostbyname($ip);
  196.     }
  197.  
  198.     // UPDATE CACHE WITH FIXED VALUES
  199.  
  200.     $cache['b']['type']    = $type;
  201.     $cache['b']['ip']      = $ip;
  202.     $cache['b']['c_port']  = $c_port;
  203.     $cache['b']['q_port']  = $q_port;
  204.     $cache['b']['s_port']  = $s_port;
  205.     $cache['o']['request'] = $request;
  206.     $cache['o']['id']      = $mysql_row['id'];
  207.     $cache['o']['zone']    = $mysql_row['zone'];
  208.     $cache['o']['comment'] = $mysql_row['comment'];
  209.  
  210.     // UPDATE CACHE WITH LOCATION
  211.  
  212.     if (empty($cache['o']['location']))
  213.     {
  214.       $cache['o']['location'] = $lgsl_config['locations'] ? lgsl_query_location($ip) : "";
  215.     }
  216.  
  217.     // UPDATE CACHE WITH DEFAULT OFFLINE VALUES
  218.  
  219.     if (!isset($cache['s']))
  220.     {
  221.       $cache['s']               = array();
  222.       $cache['s']['game']       = $type;
  223.       $cache['s']['name']       = $lgsl_config['text']['nnm'];
  224.       $cache['s']['map']        = $lgsl_config['text']['nmp'];
  225.       $cache['s']['players']    = 0;
  226.       $cache['s']['playersmax'] = 0;
  227.       $cache['s']['password']   = 0;
  228.     }
  229.  
  230.     if (!isset($cache['e'])) { $cache['e'] = array(); }
  231.     if (!isset($cache['p'])) { $cache['p'] = array(); }
  232.  
  233.     // CHECK AND GET THE NEEDED DATA
  234.  
  235.     $needed = "";
  236.  
  237.     if (strpos($request, "c") === FALSE) // CACHE ONLY REQUEST
  238.     {
  239.       if (strpos($request, "s") !== FALSE && time() > ($cache_time[0]+$lgsl_config['cache_time'])) { $needed .= "s"; }
  240.       if (strpos($request, "e") !== FALSE && time() > ($cache_time[1]+$lgsl_config['cache_time'])) { $needed .= "e"; }
  241.       if (strpos($request, "p") !== FALSE && time() > ($cache_time[2]+$lgsl_config['cache_time'])) { $needed .= "p"; }
  242.     }
  243.  
  244.     if ($needed)
  245.     {
  246.       // UPDATE CACHE TIMES BEFORE QUERY - PREVENTS OTHER INSTANCES FROM QUERY FLOODING THE SAME SERVER
  247.  
  248.       $packed_times = time() + $lgsl_config['cache_time'] + 10;
  249.       $packed_times = "{$packed_times}_{$packed_times}_{$packed_times}";
  250.       $mysql_query  = "UPDATE {$lgsl_config['db']['prefix']}{$lgsl_config['db']['table']} SET cache_time='{$packed_times}' WHERE id='{$mysql_row['id']}' LIMIT 1";
  251.       $mysql_result = mysqli_query($enlace, $mysql_query) or die(mysqli_error($enlace));
  252.       mysqli_free_result($mysql_query);
  253.       // GET WHAT IS NEEDED
  254.  
  255.       $live = lgsl_query_live($type, $ip, $c_port, $q_port, $s_port, $needed);
  256.  
  257.       if (!$live['b']['status'] && $lgsl_config['retry_offline'] && !$lgsl_config['feed']['method'])
  258.       {
  259.         $live = lgsl_query_live($type, $ip, $c_port, $q_port, $s_port, $needed);
  260.       }
  261.  
  262.       // CHECK AND CONVERT TO UTF-8 WHERE NEEDED
  263.  
  264.       $live = lgsl_charset_convert($live, lgsl_charset_detect($live));
  265.  
  266.       // IF SERVER IS OFFLINE PRESERVE SOME OF THE CACHE AND CLEAR THE REST
  267.  
  268.       if (!$live['b']['status'])
  269.       {
  270.         $live['s']['game']       = $cache['s']['game'];
  271.         $live['s']['name']       = $cache['s']['name'];
  272.         $live['s']['map']        = $cache['s']['map'];
  273.         $live['s']['password']   = $cache['s']['password'];
  274.         $live['s']['players']    = 0;
  275.         $live['s']['playersmax'] = $cache['s']['playersmax'];
  276.         $live['e']               = array();
  277.         $live['p']               = array();
  278.       }
  279.  
  280.       // MERGE LIVE INTO CACHE
  281.  
  282.       if (isset($live['b'])) { $cache['b'] = $live['b']; $cache['b']['pending'] = 0; }
  283.       if (isset($live['s'])) { $cache['s'] = $live['s']; $cache_time[0] = time(); }
  284.       if (isset($live['e'])) { $cache['e'] = $live['e']; $cache_time[1] = time(); }
  285.       if (isset($live['p'])) { $cache['p'] = $live['p']; $cache_time[2] = time(); }
  286.  
  287.       // UPDATE CACHE
  288.  
  289.       $packed_cache = mysqli_real_escape_string($enlace, base64_encode(serialize($cache)));
  290.       $packed_times = mysqli_real_escape_string($enlace, implode("_", $cache_time));
  291.       $mysql_query  = "UPDATE `{$lgsl_config['db']['prefix']}{$lgsl_config['db']['table']}` SET `status`='{$cache['b']['status']}',`cache`='{$packed_cache}',`cache_time`='{$packed_times}' WHERE `id`='{$mysql_row['id']}' LIMIT 1";
  292.       $mysql_result = mysqli_query($enlace, $mysql_query) or die(mysqli_error($enlace));
  293.       mysqli_free_result($mysql_query);
  294.     }
  295.  
  296.     // RETURN ONLY THE REQUESTED
  297.  
  298.     if (strpos($request, "s") === FALSE) { unset($cache['s']); }
  299.     if (strpos($request, "e") === FALSE) { unset($cache['e']); }
  300.     if (strpos($request, "p") === FALSE) { unset($cache['p']); }
  301.  
  302.     return $cache;
  303.   }
  304.  
  305. //------------------------------------------------------------------------------------------------------------+
  306. //EXAMPLE USAGE: lgsl_query_group( array("request"=>"sep", "hide_offline"=>0, "random"=>0, "type"=>"source", "game"=>"cstrike") )
  307.  
  308.   function lgsl_query_group($options = array())
  309.   {
  310.     if (!is_array($options)) { exit("LGSL PROBLEM: lgsl_query_group OPTIONS MUST BE ARRAY"); }
  311.  
  312.     global $lgsl_config;
  313.  
  314.      $enlace = lgsl_database();
  315.  
  316.     $request      = isset($options['request'])      ? $options['request']              : "s";
  317.     $zone         = isset($options['zone'])         ? intval($options['zone'])         : 0;
  318.     $hide_offline = isset($options['hide_offline']) ? intval($options['hide_offline']) : intval($lgsl_config['hide_offline'][$zone]);
  319.     $random       = isset($options['random'])       ? intval($options['random'])       : intval($lgsl_config['random'][$zone]);
  320.     $type         = empty($options['type'])         ? ""                               : preg_replace("/[^a-z0-9_]/", "_", strtolower($options['type']));
  321.     $game         = empty($options['game'])         ? ""                               : preg_replace("/[^a-z0-9_]/", "_", strtolower($options['game']));
  322.     $mysql_order  = empty($random)                  ? "`cache_time` ASC"               : "rand()";
  323.     $server_limit = empty($random)                  ? 0                                : $random;
  324.  
  325.                        $mysql_where   = array("`disabled`=0");
  326.     if ($zone != 0)  { $mysql_where[] = "FIND_IN_SET('{$zone}',`zone`)"; }
  327.     if ($type != "") { $mysql_where[] = "`type`='{$type}'"; }
  328.  
  329.     $mysql_query  = "SELECT `id` FROM `{$lgsl_config['db']['prefix']}{$lgsl_config['db']['table']}` WHERE ".implode(" AND ", $mysql_where)." ORDER BY {$mysql_order}";
  330.     $mysql_result = mysqli_query($enlace, $mysql_query) or die(mysqli_error($enlace));
  331.     $server_list  = array();
  332.     while ($mysql_row = mysqli_fetch_array($mysql_result, MYSQLI_ASSOC))
  333.     {
  334.       if (strpos($request, "c") === FALSE && lgsl_timer("check")) { $request .= "c"; }
  335.  
  336.       $server = lgsl_query_cached("", "", "", "", "", $request, $mysql_row['id']);
  337.  
  338.       if ($hide_offline && empty($server['b']['status'])) { continue; }
  339.       if ($game && $game != preg_replace("/[^a-z0-9_]/", "_", strtolower($server['s']['game']))) { continue; }
  340.  
  341.       $server_list[] = $server;
  342.  
  343.       if ($server_limit && count($server_list) >= $server_limit) { break; }
  344.     }
  345.     mysqli_free_result($mysql_result);
  346.     return $server_list;
  347.   }
  348.  
  349. //------------------------------------------------------------------------------------------------------------+
  350.  
  351.   function lgsl_group_totals($server_list = FALSE)
  352.   {
  353.     if (!is_array($server_list)) { $server_list = lgsl_query_group( array( "request"=>"sc" ) ); }
  354.  
  355.     $total = array("players"=>0, "playersmax"=>0, "servers"=>0, "servers_online"=>0, "servers_offline"=>0);
  356.  
  357.     foreach ($server_list as $server)
  358.     {
  359.       $total['players']    += $server['s']['players'];
  360.       $total['playersmax'] += $server['s']['playersmax'];
  361.  
  362.                                     $total['servers']         ++;
  363.       if ($server['b']['status']) { $total['servers_online']  ++; }
  364.       else                        { $total['servers_offline'] ++; }
  365.     }
  366.  
  367.     return $total;
  368.   }
  369.  
  370. //------------------------------------------------------------------------------------------------------------+
  371.  
  372.   function lgsl_query_cached_all($request) // LEGACY - DO NOT USE
  373.   {
  374.     return lgsl_query_group( array( "request"=>$request ) );
  375.   }
  376.  
  377. //------------------------------------------------------------------------------------------------------------+
  378.  
  379.   function lgsl_query_cached_zone($request, $zone) // LEGACY - DO NOT USE
  380.   {
  381.     return lgsl_query_group( array( "request"=>$request, "zone"=>$zone ) );
  382.   }
  383.  
  384. //------------------------------------------------------------------------------------------------------------+
  385.  
  386.   function lgsl_cached_totals() // LEGACY - DO NOT USE
  387.   {
  388.     return lgsl_group_totals();
  389.   }
  390.  
  391. //------------------------------------------------------------------------------------------------------------+
  392.  
  393.   function lgsl_lookup_id($id) // LEGACY - DO NOT USE
  394.   {
  395.     global $lgsl_config;
  396.  
  397.      $enlace = lgsl_database();
  398.  
  399.     $id           = mysqli_real_escape_string($enlace, intval($id));
  400.     $mysql_query  = "SELECT `type`,`ip`,`c_port`,`q_port`,`s_port` FROM `{$lgsl_config['db']['prefix']}{$lgsl_config['db']['table']}` WHERE `id`='{$id}' LIMIT 1";
  401.     $mysql_result = mysqli_query($enlace, $mysql_query) or die(mysqli_error($enlace));
  402.     $mysql_row    = mysqli_fetch_array($mysql_result, MYSQLI_ASSOC);
  403.     mysqli_free_result($mysql_query);
  404.     return $mysql_row;
  405.   }
  406.  
  407. //------------------------------------------------------------------------------------------------------------+
  408.  
  409.   function lgsl_timer($action)
  410.   {
  411.     global $lgsl_config;
  412.     global $lgsl_timer;
  413.  
  414.     if (!$lgsl_timer)
  415.     {
  416.       $microtime  = microtime();
  417.       $microtime  = explode(' ', $microtime);
  418.       $microtime  = $microtime[1] + $microtime[0];
  419.       $lgsl_timer = $microtime - 0.01;
  420.     }
  421.  
  422.     $time_limit = intval($lgsl_config['live_time']);
  423.     $time_php   = ini_get("max_execution_time");
  424.  
  425.     if ($time_limit > $time_php)
  426.     {
  427.       @set_time_limit($time_limit + 5);
  428.  
  429.       $time_php = ini_get("max_execution_time");
  430.  
  431.       if ($time_limit > $time_php)
  432.       {
  433.         $time_limit = $time_php - 5;
  434.       }
  435.     }
  436.  
  437.     if ($action == "limit")
  438.     {
  439.       return $time_limit;
  440.     }
  441.  
  442.     $microtime  = microtime();
  443.     $microtime  = explode(' ', $microtime);
  444.     $microtime  = $microtime[1] + $microtime[0];
  445.     $time_taken = $microtime - $lgsl_timer;
  446.  
  447.     if ($action == "check")
  448.     {
  449.       return ($time_taken > $time_limit) ? TRUE : FALSE;
  450.     }
  451.     else
  452.     {
  453.       return round($time_taken, 2);
  454.     }
  455.   }
  456.  
  457. //------------------------------------------------------------------------------------------------------------+
  458.  
  459.   function lgsl_server_misc($server)
  460.   {
  461.     global $lgsl_config, $lgsl_url_path;
  462.  
  463.     $misc['icon_details']       = $lgsl_url_path."other/icon_details.gif";
  464.     $misc['icon_game']          = lgsl_icon_game($server['b']['type'], $server['s']['game']);
  465.     $misc['icon_status']        = lgsl_icon_status($server['b']['status'], $server['s']['password'], $server['b']['pending']);
  466.     $misc['icon_location']      = lgsl_icon_location($server['o']['location']);
  467.     $misc['image_map']          = lgsl_image_map($server['b']['status'], $server['b']['type'], $server['s']['game'], $server['s']['map'], TRUE, $server['o']['id']);
  468.     $misc['image_map_password'] = lgsl_image_map_password($server['b']['status'], $server['s']['password']);
  469.     $misc['text_status']        = lgsl_text_status($server['b']['status'], $server['s']['password'], $server['b']['pending']);
  470.     $misc['text_type_game']     = lgsl_text_type_game($server['b']['type'], $server['s']['game']);
  471.     $misc['text_location']      = lgsl_text_location($server['o']['location']);
  472.     $misc['name_filtered']      = lgsl_string_html($server['s']['name'], FALSE, 20); // LEGACY
  473.     $misc['software_link']      = lgsl_software_link($server['b']['type'], $server['b']['ip'], $server['b']['c_port'], $server['b']['q_port'], $server['b']['s_port']);
  474.     $misc['location_link']      = lgsl_location_link($server['o']['location']);
  475.  
  476.     return $misc;
  477.   }
  478.  
  479. //------------------------------------------------------------------------------------------------------------+
  480.  
  481.   function lgsl_icon_game($type, $game)
  482.   {
  483.     global $lgsl_file_path, $lgsl_url_path;
  484.  
  485.     $type = preg_replace("/[^a-z0-9_]/", "_", strtolower($type));
  486.     $game = preg_replace("/[^a-z0-9_]/", "_", strtolower($game));
  487.  
  488.     $path_list = array(
  489.     "icons/{$type}/{$game}.gif",
  490.     "icons/{$type}/{$game}.png",
  491.     "icons/{$type}/{$type}.gif",
  492.     "icons/{$type}/{$type}.png");
  493.  
  494.     foreach ($path_list as $path)
  495.     {
  496.       if (file_exists($lgsl_file_path.$path)) { return $lgsl_url_path.$path; }
  497.     }
  498.  
  499.     return "{$lgsl_url_path}other/icon_unknown.gif";
  500.   }
  501.  
  502. //------------------------------------------------------------------------------------------------------------+
  503.  
  504.   function lgsl_icon_status($status, $password, $pending = 0)
  505.   {
  506.     global $lgsl_url_path;
  507.  
  508.     if ($pending)  { return "{$lgsl_url_path}other/icon_unknown.gif"; }
  509.     if (!$status)  { return "{$lgsl_url_path}other/icon_no_response.gif"; }
  510.     if ($password) { return "{$lgsl_url_path}other/icon_online_password.gif"; }
  511.  
  512.     return "{$lgsl_url_path}other/icon_online.gif";
  513.   }
  514.  
  515. //------------------------------------------------------------------------------------------------------------+
  516.  
  517.   function lgsl_icon_location($location)
  518.   {
  519.     global $lgsl_file_path, $lgsl_url_path;
  520.  
  521.     if (!$location) { return "{$lgsl_url_path}locations/OFF.png"; }
  522.  
  523.     if ($location)
  524.     {
  525.       $location = "locations/".preg_replace("/[^a-zA-Z0-9_]/", "_", $location).".png";
  526.  
  527.       if (file_exists($lgsl_file_path.$location)) { return $lgsl_url_path.$location; }
  528.     }
  529.  
  530.     return "{$lgsl_url_path}locations/XX.png";
  531.   }
  532.  
  533. //------------------------------------------------------------------------------------------------------------+
  534.  
  535.   function lgsl_image_map($status, $type, $game, $map, $check_exists = TRUE, $id = 0)
  536.   {
  537.     global $lgsl_file_path, $lgsl_url_path;
  538.  
  539.     $type = preg_replace("/[^a-z0-9_]/", "_", strtolower($type));
  540.     $game = preg_replace("/[^a-z0-9_]/", "_", strtolower($game));
  541.     $map  = preg_replace("/[^a-z0-9_]/", "_", strtolower($map));
  542.  
  543.     if ($check_exists !== TRUE) { return "{$lgsl_url_path}maps/{$type}/{$game}/{$map}.jpg"; }
  544.  
  545.     if ($status)
  546.     {
  547.       $path_list = array(
  548.       "maps/{$type}/{$game}/{$map}.jpg",
  549.       "maps/{$type}/{$game}/{$map}.gif",
  550.       "maps/{$type}/{$game}/{$map}.png",
  551.       "maps/{$type}/{$map}.jpg",
  552.       "maps/{$type}/{$map}.gif",
  553.       "maps/{$type}/{$map}.png",
  554.       "maps/{$type}/map_no_image.jpg",
  555.       "maps/{$type}/map_no_image.gif",
  556.       "maps/{$type}/map_no_image.png",
  557.       "other/map_no_image_{$id}.jpg",
  558.       "other/map_no_image_{$id}.gif",
  559.       "other/map_no_image_{$id}.png",
  560.       "other/map_no_image.jpg");
  561.     }
  562.     else
  563.     {
  564.       $path_list = array(
  565.       "maps/{$type}/map_no_response.jpg",
  566.       "maps/{$type}/map_no_response.gif",
  567.       "maps/{$type}/map_no_response.png",
  568.       "other/map_no_response_{$id}.jpg",
  569.       "other/map_no_response_{$id}.gif",
  570.       "other/map_no_response_{$id}.png",
  571.       "other/map_no_response.jpg");
  572.     }
  573.  
  574.     foreach ($path_list as $path)
  575.     {
  576.       if (file_exists($lgsl_file_path.$path)) { return "{$lgsl_url_path}{$path}"; }
  577.     }
  578.  
  579.     return "#LGSL_DEFAULT_IMAGES_MISSING#";
  580.   }
  581.  
  582. //------------------------------------------------------------------------------------------------------------+
  583.  
  584.   function lgsl_image_map_password($status, $password)
  585.   {
  586.     global $lgsl_url_path;
  587.  
  588.     if (!$password || !$status) { return "{$lgsl_url_path}other/map_overlay.gif"; }
  589.  
  590.     return "{$lgsl_url_path}other/map_overlay_password.gif";
  591.   }
  592.  
  593. //------------------------------------------------------------------------------------------------------------+
  594.  
  595.   function lgsl_text_status($status, $password, $pending = 0)
  596.   {
  597.     global $lgsl_config;
  598.  
  599.     if ($pending)  { return $lgsl_config['text']['pen']; }
  600.     if (!$status)  { return $lgsl_config['text']['nrs']; }
  601.     if ($password) { return $lgsl_config['text']['onp']; }
  602.  
  603.     return $lgsl_config['text']['onl'];
  604.   }
  605.  
  606. //------------------------------------------------------------------------------------------------------------+
  607.  
  608.   function lgsl_text_type_game($type, $game)
  609.   {
  610.     global $lgsl_config;
  611.  
  612.     return "[ {$lgsl_config['text']['typ']} {$type} ] [ {$lgsl_config['text']['gme']} {$game} ]";
  613.   }
  614.  
  615. //------------------------------------------------------------------------------------------------------------+
  616.  
  617.   function lgsl_text_location($location)
  618.   {
  619.     global $lgsl_config;
  620.  
  621.     return $location ? "{$lgsl_config['text']['loc']} {$location}" : "";
  622.   }
  623.  
  624. //------------------------------------------------------------------------------------------------------------+
  625.  
  626.   function lgsl_sort_servers($server_list)
  627.   {
  628.     global $lgsl_config;
  629.  
  630.     if (!is_array($server_list)) { return $server_list; }
  631.  
  632.     if     ($lgsl_config['sort']['servers'] == "id")      { usort($server_list, "lgsl_sort_servers_by_id");      }
  633.     elseif ($lgsl_config['sort']['servers'] == "zone")    { usort($server_list, "lgsl_sort_servers_by_zone");    }
  634.     elseif ($lgsl_config['sort']['servers'] == "type")    { usort($server_list, "lgsl_sort_servers_by_type");    }
  635.     elseif ($lgsl_config['sort']['servers'] == "status")  { usort($server_list, "lgsl_sort_servers_by_status");  }
  636.     elseif ($lgsl_config['sort']['servers'] == "players") { usort($server_list, "lgsl_sort_servers_by_players"); }
  637.  
  638.     return $server_list;
  639.   }
  640.  
  641. //------------------------------------------------------------------------------------------------------------+
  642.  
  643.   function lgsl_sort_fields($server, $fields_show, $fields_hide, $fields_other)
  644.   {
  645.     $fields_list = array();
  646.  
  647.     if (!is_array($server['p'])) { return $fields_list; }
  648.  
  649.     foreach ($server['p'] as $player)
  650.     {
  651.       foreach ($player as $field => $value)
  652.       {
  653.         if ($value === "") { continue; }
  654.         if (in_array($field, $fields_list)) { continue; }
  655.         if (in_array($field, $fields_hide)) { continue; }
  656.         $fields_list[] = $field;
  657.       }
  658.     }
  659.  
  660.     $fields_show = array_intersect($fields_show, $fields_list);
  661.  
  662.     if ($fields_other == FALSE) { return $fields_show; }
  663.  
  664.     $fields_list = array_diff($fields_list, $fields_show);
  665.  
  666.     return array_merge($fields_show, $fields_list);
  667.   }
  668.  
  669. //------------------------------------------------------------------------------------------------------------+
  670.  
  671.   function lgsl_sort_servers_by_id($server_a, $server_b)
  672.   {
  673.     if ($server_a['o']['id'] == $server_b['o']['id']) { return 0; }
  674.  
  675.     return ($server_a['o']['id'] > $server_b['o']['id']) ? 1 : -1;
  676.   }
  677.  
  678. //------------------------------------------------------------------------------------------------------------+
  679.  
  680.   function lgsl_sort_servers_by_zone($server_a, $server_b)
  681.   {
  682.     if ($server_a['o']['zone'] == $server_b['o']['zone']) { return 0; }
  683.  
  684.     return ($server_a['o']['zone'] > $server_b['o']['zone']) ? 1 : -1;
  685.   }
  686.  
  687. //------------------------------------------------------------------------------------------------------------+
  688.  
  689.   function lgsl_sort_servers_by_type($server_a, $server_b)
  690.   {
  691.     $result = strcasecmp($server_a['b']['type'], $server_b['b']['type']);
  692.  
  693.     if ($result == 0)
  694.     {
  695.       $result = strcasecmp($server_a['s']['game'], $server_b['s']['game']);
  696.     }
  697.  
  698.     return $result;
  699.   }
  700.  
  701. //------------------------------------------------------------------------------------------------------------+
  702.  
  703.   function lgsl_sort_servers_by_status($server_a, $server_b)
  704.   {
  705.     if ($server_a['b']['status'] == $server_b['b']['status']) { return 0; }
  706.  
  707.     return ($server_a['b']['status'] < $server_b['b']['status']) ? 1 : -1;
  708.   }
  709.  
  710. //------------------------------------------------------------------------------------------------------------+
  711.  
  712.   function lgsl_sort_servers_by_players($server_a, $server_b)
  713.   {
  714.     if ($server_a['s']['players'] == $server_b['s']['players']) { return 0; }
  715.  
  716.     return ($server_a['s']['players'] < $server_b['s']['players']) ? 1 : -1;
  717.   }
  718.  
  719. //------------------------------------------------------------------------------------------------------------+
  720.  
  721.   function lgsl_sort_extras($server)
  722.   {
  723.     if (!is_array($server['e'])) { return $server; }
  724.  
  725.     ksort($server['e']);
  726.  
  727.     return $server;
  728.   }
  729.  
  730. //------------------------------------------------------------------------------------------------------------+
  731.  
  732.   function lgsl_sort_players($server)
  733.   {
  734.     global $lgsl_config;
  735.  
  736.     if (!is_array($server['p'])) { return $server; }
  737.  
  738.     if     ($lgsl_config['sort']['players'] == "name")  { usort($server['p'], "lgsl_sort_players_by_name");  }
  739.     elseif ($lgsl_config['sort']['players'] == "score") { usort($server['p'], "lgsl_sort_players_by_score"); }
  740.  
  741.     return $server;
  742.   }
  743.  
  744. //------------------------------------------------------------------------------------------------------------+
  745.  
  746.   function lgsl_sort_players_by_score($player_a, $player_b)
  747.   {
  748.     if ($player_a['score'] == $player_b['score']) { return 0; }
  749.  
  750.     return ($player_a['score'] < $player_b['score']) ? 1 : -1;
  751.   }
  752.  
  753. //------------------------------------------------------------------------------------------------------------+
  754.  
  755.   function lgsl_sort_players_by_name($player_a, $player_b)
  756.   {
  757.     // REMOVE NON ALPHA NUMERIC ASCII WHILE LEAVING UPPER UTF-8 CHARACTERS
  758.     $name_a = preg_replace("/[\x{00}-\x{2F}\x{3A}-\x{40}\x{5B}-\x{60}\x{7B}-\x{7F}]/", "", $player_a['name']);
  759.     $name_b = preg_replace("/[\x{00}-\x{2F}\x{3A}-\x{40}\x{5B}-\x{60}\x{7B}-\x{7F}]/", "", $player_b['name']);
  760.  
  761.     if (function_exists("mb_convert_case"))
  762.     {
  763.       $name_a = @mb_convert_case($name_a, MB_CASE_LOWER, "UTF-8");
  764.       $name_b = @mb_convert_case($name_b, MB_CASE_LOWER, "UTF-8");
  765.       return strcmp($name_a, $name_b);
  766.     }
  767.     else
  768.     {
  769.       return strcasecmp($name_a, $name_b);
  770.     }
  771.   }
  772.  
  773. //------------------------------------------------------------------------------------------------------------+
  774.  
  775.   function lgsl_charset_detect($server)
  776.   {
  777.     if (!function_exists("mb_detect_encoding")) { return "AUTO"; }
  778.  
  779.     $test = "";
  780.  
  781.     if (isset($server['s']['name'])) { $test .= " {$server['s']['name']} "; }
  782.  
  783.     if (isset($server['p']) && $server['p'])
  784.     {
  785.       foreach ($server['p'] as $player)
  786.       {
  787.         if (isset($player['name'])) { $test .= " {$player['name']} "; }
  788.       }
  789.     }
  790.  
  791.     $charset = @mb_detect_encoding($server['s']['name'], "UTF-8, Windows-1252, ISO-8859-1, ISO-8859-15");
  792.  
  793.     return $charset ? $charset : "AUTO";
  794.   }
  795.  
  796. //------------------------------------------------------------------------------------------------------------+
  797.  
  798.   function lgsl_charset_convert($server, $charset)
  799.   {
  800.     if (!function_exists("mb_convert_encoding")) { return $server; }
  801.  
  802.     if (is_array($server))
  803.     {
  804.       foreach ($server as $key => $value)
  805.       {
  806.         $server[$key] = lgsl_charset_convert($value, $charset);
  807.       }
  808.     }
  809.     else
  810.     {
  811.       $server = @mb_convert_encoding($server, "UTF-8", $charset);
  812.     }
  813.  
  814.     return $server;
  815.   }
  816.  
  817. //------------------------------------------------------------------------------------------------------------+
  818.  
  819.   function lgsl_server_html($server, $word_wrap = 20)
  820.   {
  821.     foreach ($server as $key => $value)
  822.     {
  823.       $server[$key] = is_array($value) ? lgsl_server_html($value, $word_wrap) : lgsl_string_html($value, FALSE, $word_wrap);
  824.     }
  825.  
  826.     return $server;
  827.   }
  828.  
  829. //------------------------------------------------------------------------------------------------------------+
  830.  
  831.   function lgsl_string_html($string, $xml_feed = FALSE, $word_wrap = 0)
  832.   {
  833.     if ($word_wrap) { $string = lgsl_word_wrap($string, $word_wrap); }
  834.  
  835.     if ($xml_feed != FALSE)
  836.     {
  837.       $string = htmlspecialchars($string, ENT_QUOTES);
  838.     }
  839.     elseif (function_exists("mb_convert_encoding"))
  840.     {
  841.       $string = htmlspecialchars($string, ENT_QUOTES);
  842.       $string = @mb_convert_encoding($string, "HTML-ENTITIES", "UTF-8");
  843.     }
  844.     else
  845.     {
  846.       $string = htmlentities($string, ENT_QUOTES, "UTF-8");
  847.     }
  848.  
  849.     if ($word_wrap) { $string = lgsl_word_wrap($string); }
  850.  
  851.     return $string;
  852.   }
  853.  
  854. //------------------------------------------------------------------------------------------------------------+
  855.  
  856.   function lgsl_word_wrap($string, $length_limit = 0)
  857.   {
  858.     if (!$length_limit)
  859.     {
  860. //    http://www.quirksmode.org/oddsandends/wbr.html
  861. //    return str_replace("\x05\x06", " ",       $string); // VISIBLE
  862. //    return str_replace("\x05\x06", "&shy;",   $string); // FF2 VISIBLE AND DIV NEEDED
  863.       return str_replace("\x05\x06", "?", $string); // IE6 VISIBLE
  864.     }
  865.  
  866.     $word_list = explode(" ", $string);
  867.  
  868.     foreach ($word_list as $key => $word)
  869.     {
  870.       $word_length = function_exists("mb_strlen") ? mb_strlen($word, "UTF-8") : strlen($word);
  871.  
  872.       if ($word_length < $length_limit) { continue; }
  873.  
  874.       $word_new = "";
  875.  
  876.       for ($i=0; $i<$word_length; $i+=$length_limit)
  877.       {
  878.         $word_new .= function_exists("mb_substr") ? mb_substr($word, $i, $length_limit, "UTF-8") : substr($word, $i, $length_limit);
  879.         $word_new .= "\x05\x06";
  880.       }
  881.  
  882.       $word_list[$key] = $word_new;
  883.     }
  884.  
  885.     return implode(" ", $word_list);
  886.   }
  887.  
  888. //------------------------------------------------------------------------------------------------------------+
  889.  
  890.   function lgsl_location_link($location)
  891.   {
  892.     if (!$location) { return "#"; }
  893.  
  894.     if (strlen($location) == 2) { return "http://www.wipmania.com/map/{$location}"; }
  895.  
  896.     return "http://www.google.com/search?q=".urlencode($location);
  897.   }
  898.  
  899. //------------------------------------------------------------------------------------------------------------+
  900.  
  901.   function lgsl_query_location($ip)
  902.   {
  903.     global $lgsl_config;
  904.  
  905.     if ($lgsl_config['locations'] !== 1) { return $lgsl_config['locations']; }
  906.  
  907.     $ip = gethostbyname($ip);
  908.  
  909.     if (long2ip(ip2long($ip)) == "255.255.255.255") { return "XX"; }
  910.  
  911.     $url = "http://api.wipmania.com/".urlencode($ip)."?".urlencode($_SERVER['HTTP_HOST']);
  912.  
  913.     if (function_exists('curl_init') && function_exists('curl_setopt') && function_exists('curl_exec'))
  914.     {
  915.       $lgsl_curl = curl_init();
  916.  
  917.       curl_setopt($lgsl_curl, CURLOPT_HEADER, 0);
  918.       curl_setopt($lgsl_curl, CURLOPT_TIMEOUT, 2);
  919.       curl_setopt($lgsl_curl, CURLOPT_RETURNTRANSFER, 1);
  920.       curl_setopt($lgsl_curl, CURLOPT_CONNECTTIMEOUT, 2);
  921.       curl_setopt($lgsl_curl, CURLOPT_URL, $url);
  922.  
  923.       $location = curl_exec($lgsl_curl);
  924.  
  925.       if (curl_error($lgsl_curl)) { $location = "XX"; }
  926.  
  927.       curl_close($lgsl_curl);
  928.     }
  929.     else
  930.     {
  931.       $location = @file_get_contents($url);
  932.     }
  933.  
  934.     if (strlen($location) != 2) { $location = "XX"; }
  935.  
  936.     return $location;
  937.   }
  938.  
  939. //------------------------------------------------------------------------------------------------------------+
  940.  
  941.   function lgsl_realpath($path)
  942.   {
  943.     // WRAPPER SO IT CAN BE DISABLED
  944.  
  945.     global $lgsl_config;
  946.  
  947.     return $lgsl_config['no_realpath'] ? $path : realpath($path);
  948.   }
  949.  
  950. //------------------------------------------------------------------------------------------------------------+
  951.  
  952.   function lgsl_file_path()
  953.   {
  954.     // GET THE LGSL_CLASS.PHP PATH
  955.  
  956.     $lgsl_path = __FILE__;
  957.  
  958.     // SHORTEN TO JUST THE FOLDERS AND ADD TRAILING SLASH
  959.  
  960.     $lgsl_path = dirname($lgsl_path)."/";
  961.  
  962.     // CONVERT WINDOWS BACKSLASHES TO FORWARDSLASHES
  963.  
  964.     $lgsl_path = str_replace("\\", "/", $lgsl_path);
  965.  
  966.     return $lgsl_path;
  967.   }
  968.  
  969. //------------------------------------------------------------------------------------------------------------+
  970.  
  971.   function lgsl_url_path()
  972.   {
  973.     // CHECK IF PATH HAS BEEN SET IN CONFIG
  974.  
  975.     global $lgsl_config;
  976.  
  977.     if ($lgsl_config['url_path'])
  978.     {
  979.       return $lgsl_config['url_path'];
  980.     }
  981.  
  982.     // USE FULL DOMAIN PATH TO AVOID ALIAS PROBLEMS
  983.  
  984.     $host_path  = (!isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) != "on") ? "http://" : "https://";
  985.     $host_path .= $_SERVER['HTTP_HOST'];
  986.  
  987.     // GET FULL PATHS ( EXTRA CODE FOR WINDOWS AND IIS - NO DOCUMENT_ROOT - BACKSLASHES - DOUBLESLASHES - ETC )
  988.  
  989.     if ($_SERVER['DOCUMENT_ROOT'])
  990.     {
  991.       $base_path = lgsl_realpath($_SERVER['DOCUMENT_ROOT']);
  992.       $base_path = str_replace("\\", "/", $base_path);
  993.       $base_path = str_replace("//", "/", $base_path);
  994.     }
  995.     else
  996.     {
  997.       $file_path = $_SERVER['SCRIPT_NAME'];
  998.       $file_path = str_replace("\\", "/", $file_path);
  999.       $file_path = str_replace("//", "/", $file_path);
  1000.  
  1001.       $base_path = $_SERVER['PATH_TRANSLATED'];
  1002.       $base_path = str_replace("\\", "/", $base_path);
  1003.       $base_path = str_replace("//", "/", $base_path);
  1004.       $base_path = substr($base_path, 0, -strlen($file_path));
  1005.     }
  1006.  
  1007.     $lgsl_path = dirname(lgsl_realpath(__FILE__));
  1008.     $lgsl_path = str_replace("\\", "/", $lgsl_path);
  1009.  
  1010.     // REMOVE ANY TRAILING SLASHES
  1011.  
  1012.     if (substr($base_path, -1) == "/") { $base_path = substr($base_path, 0, -1); }
  1013.     if (substr($lgsl_path, -1) == "/") { $lgsl_path = substr($lgsl_path, 0, -1); }
  1014.  
  1015.     // USE THE DIFFERENCE BETWEEN PATHS
  1016.  
  1017.     if (substr($lgsl_path, 0, strlen($base_path)) == $base_path)
  1018.     {
  1019.       $url_path = substr($lgsl_path, strlen($base_path));
  1020.  
  1021.       return $host_path.$url_path."/";
  1022.     }
  1023.  
  1024.     return "/#LGSL_PATH_PROBLEM#{$base_path}#{$lgsl_path}#/";
  1025.   }
  1026.  
  1027. //------------------------------------------------------------------------------------------------------------+
  1028. //------------------------------------------------------------------------------------------------------------+
  1029.  
  1030.   } // END OF DOUBLE LOAD PROTECTION
  1031.  
  1032. //------------------------------------------------------------------------------------------------------------+
  1033. //------------------------------------------------------------------------------------------------------------+
  1034.  
  1035.   global $lgsl_file_path, $lgsl_url_path;
  1036.  
  1037.   $lgsl_file_path = lgsl_file_path();
  1038.  
  1039.   if (isset($_GET['lgsl_debug']))
  1040.   {
  1041.     echo "<hr /><pre>".print_r($_SERVER, TRUE)."</pre>
  1042.          <hr />#d0# ".__FILE__."
  1043.          <hr />#d1# ".@realpath(__FILE__)."
  1044.          <hr />#d2# ".dirname(__FILE__)."
  1045.          <hr />#d3# {$lgsl_file_path}
  1046.          <hr />#d4# {$_SERVER['DOCUMENT_ROOT']}
  1047.          <hr />#d5# ".@realpath($_SERVER['DOCUMENT_ROOT']);
  1048.   }
  1049.  
  1050.   require $lgsl_file_path."lgsl_config.php";
  1051.   require $lgsl_file_path."lgsl_protocol.php";
  1052.  
  1053.   $lgsl_url_path = lgsl_url_path();
  1054.  
  1055.   if (isset($_GET['lgsl_debug']))
  1056.   {
  1057.     echo "<hr />#d6# {$lgsl_url_path}
  1058.          <hr />#c0# {$lgsl_config['url_path']}
  1059.          <hr />#c1# {$lgsl_config['no_realpath']}
  1060.          <hr />#c2# {$lgsl_config['feed']['method']}
  1061.          <hr />#c3# {$lgsl_config['feed']['url']}
  1062.          <hr />#c4# {$lgsl_config['cache_time']}
  1063.          <hr />#c5# {$lgsl_config['live_time']}
  1064.          <hr />#c6# {$lgsl_config['timeout']}
  1065.          <hr />#c7# {$lgsl_config['cms']}
  1066.          <hr />";
  1067.   }
  1068.  
  1069.   if (!isset($lgsl_config['locations']))
  1070.   {
  1071.     exit("LGSL PROBLEM: lgsl_config.php FAILED TO LOAD OR MISSING ENTRIES");
  1072.   }
  1073.  
  1074. //------------------------------------------------------------------------------------------------------------+
  1075. ?>
Add Comment
Please, Sign In to add comment