Guest User

Untitled

a guest
Jun 1st, 2016
37
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.61 KB | None | 0 0
  1. # HLstatsX Community Edition - Real-time player and clan rankings and statistics
  2. # Copyleft (L) 2008-20XX Nicholas Hastings (nshastings@gmail.com)
  3. # http://www.hlxcommunity.com
  4. #
  5. # HLstatsX Community Edition is a continuation of
  6. # ELstatsNEO - Real-time player and clan rankings and statistics
  7. # Copyleft (L) 2008-20XX Malte Bayer (steam@neo-soft.org)
  8. # http://ovrsized.neo-soft.org/
  9. #
  10. # ELstatsNEO is an very improved & enhanced - so called Ultra-Humongus Edition of HLstatsX
  11. # HLstatsX - Real-time player and clan rankings and statistics for Half-Life 2
  12. # http://www.hlstatsx.com/
  13. # Copyright (C) 2005-2007 Tobias Oetzel (Tobi@hlstatsx.com)
  14. #
  15. # HLstatsX is an enhanced version of HLstats made by Simon Garner
  16. # HLstats - Real-time player and clan rankings and statistics for Half-Life
  17. # http://sourceforge.net/projects/hlstats/
  18. # Copyright (C) 2001 Simon Garner
  19. #
  20. # This program is free software; you can redistribute it and/or
  21. # modify it under the terms of the GNU General Public License
  22. # as published by the Free Software Foundation; either version 2
  23. # of the License, or (at your option) any later version.
  24. #
  25. # This program is distributed in the hope that it will be useful,
  26. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  28. # GNU General Public License for more details.
  29. #
  30. # You should have received a copy of the GNU General Public License
  31. # along with this program; if not, write to the Free Software
  32. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  33. #
  34. # For support and installation notes visit http://www.hlxcommunity.com
  35.  
  36.  
  37. # HLstatsX CE release version number
  38.  
  39. $g_version = "<Unable to Detect>";
  40. my %db_stmt_cache = ();
  41.  
  42. %g_eventTables = (
  43. "TeamBonuses",
  44. ["playerId", "actionId", "bonus"],
  45. "ChangeRole",
  46. ["playerId", "role"],
  47. "ChangeName",
  48. ["playerId", "oldName", "newName"],
  49. "ChangeTeam",
  50. ["playerId", "team"],
  51. "Connects",
  52. ["playerId", "ipAddress", "hostname", "hostgroup"],
  53. "Disconnects",
  54. ["playerId"],
  55. "Entries",
  56. ["playerId"],
  57. "Frags",
  58. ["killerId", "victimId", "weapon", "headshot", "killerRole", "victimRole", "pos_x","pos_y","pos_z", "pos_victim_x","pos_victim_y","pos_victim_z"],
  59. "PlayerActions",
  60. ["playerId", "actionId", "bonus", "pos_x","pos_y","pos_z"],
  61. "PlayerPlayerActions",
  62. ["playerId", "victimId", "actionId", "bonus", "pos_x","pos_y","pos_z", "pos_victim_x","pos_victim_y","pos_victim_z"],
  63. "Suicides",
  64. ["playerId", "weapon", "pos_x","pos_y","pos_z"],
  65. "Teamkills",
  66. ["killerId", "victimId", "weapon", "pos_x","pos_y","pos_z", "pos_victim_x","pos_victim_y","pos_victim_z"],
  67. "Rcon",
  68. ["type", "remoteIp", "password", "command"],
  69. "Admin",
  70. ["type", "message", "playerName"],
  71. "Statsme",
  72. ["playerId", "weapon", "shots", "hits", "headshots", "damage", "kills", "deaths"],
  73. "Statsme2",
  74. ["playerId", "weapon", "head", "chest", "stomach", "leftarm", "rightarm", "leftleg", "rightleg"],
  75. "StatsmeLatency",
  76. ["playerId", "ping"],
  77. "StatsmeTime",
  78. ["playerId", "time"],
  79. "Latency",
  80. ["playerId", "ping"],
  81. "Chat",
  82. ["playerId", "message_mode", "message"]
  83. );
  84. %g_eventTables2 = (
  85. "TeamBonuses",
  86. ["playerId", "actionId", "bonus"],
  87. "ChangeRole",
  88. ["playerId", "role"],
  89. "ChangeName",
  90. ["playerId", "oldName", "newName"],
  91. "ChangeTeam",
  92. ["playerId", "team"],
  93. "Connects",
  94. ["playerId", "ipAddress", "hostname", "hostgroup"],
  95. "Disconnects",
  96. ["playerId"],
  97. "Entries",
  98. ["playerId"],
  99. "Frags",
  100. ["killerId", "victimId", "weapon", "headshot", "killerRole", "victimRole", "pos_x","pos_y","pos_z", "pos_victim_x","pos_victim_y","pos_victim_z"],
  101. "PlayerActions",
  102. ["playerId", "actionId", "bonus", "pos_x","pos_y","pos_z"],
  103. "PlayerPlayerActions",
  104. ["playerId", "victimId", "actionId", "bonus", "pos_x","pos_y","pos_z", "pos_victim_x","pos_victim_y","pos_victim_z"],
  105. "Suicides",
  106. ["playerId", "weapon", "pos_x","pos_y","pos_z"],
  107. "Teamkills",
  108. ["killerId", "victimId", "weapon", "pos_x","pos_y","pos_z", "pos_victim_x","pos_victim_y","pos_victim_z"],
  109. "Rcon",
  110. ["type", "remoteIp", "password", "command"],
  111. "Admin",
  112. ["type", "message", "playerName"],
  113. "Statsme",
  114. ["playerId", "weapon", "shots", "hits", "headshots", "damage", "kills", "deaths"],
  115. "Statsme2",
  116. ["playerId", "weapon", "head", "chest", "stomach", "leftarm", "rightarm", "leftleg", "rightleg"],
  117. "StatsmeLatency",
  118. ["playerId", "ping"],
  119. "StatsmeTime",
  120. ["playerId", "time"],
  121. "Latency",
  122. ["playerId", "ping"],
  123. "Chat",
  124. ["playerId", "message_mode", "message"]
  125. );
  126.  
  127.  
  128. ##
  129. ## Common Functions
  130. ##
  131.  
  132. sub number_format {
  133. local $_ = shift;
  134. 1 while s/^(-?\d+)(\d{3})/$1,$2/;
  135. return $_;
  136. }
  137.  
  138. sub date_format {
  139. my $timestamp = shift;
  140. return sprintf('%dd %02d:%02d:%02dh',
  141. $timestamp / 86400,
  142. $timestamp / 3600 % 24,
  143. $timestamp / 60 % 60,
  144. $timestamp % 60
  145. );
  146. }
  147.  
  148.  
  149.  
  150. #
  151. # void error (string errormsg)
  152. #
  153. # Dies, and optionally mails error messages to $g_mailto.
  154. #
  155.  
  156. sub error
  157. {
  158. my $errormsg = $_[0];
  159.  
  160. if ($g_mailto && $g_mailpath)
  161. {
  162. system("echo \"$errormsg\" | $g_mailpath -s \"HLstatsX:CE crashed `date`\" $g_mailto");
  163. }
  164.  
  165. die("$errormsg\n");
  166. }
  167.  
  168.  
  169. #
  170. # string quoteSQL (string varQuote)
  171. #
  172. # Escapes all quote characters in a variable, making it suitable for use in an
  173. # SQL query. Returns the escaped version.
  174. #
  175.  
  176. sub quoteSQL
  177. {
  178. my $varQuote = $_[0];
  179.  
  180. $varQuote =~ s/\\/\\\\/g; # replace \ with \\
  181. $varQuote =~ s/'/\\'/g; # replace ' with \'
  182.  
  183. return $varQuote;
  184. }
  185.  
  186. #
  187. # void doConnect
  188. #
  189. # Connects to the HLstatsX database
  190. #
  191.  
  192. sub doConnect
  193. {
  194. $db_conn = DBI->connect(
  195. "DBI:mysql:$db_name:$db_host",
  196. $db_user, $db_pass, { mysql_enable_utf8 => 1 }
  197. );
  198. while(!$db_conn) {
  199. &printEvent("MYSQL", "\nCan't connect to MySQL database '$db_name' on '$db_host'\n" .
  200. "Server error: $DBI::errstr\n");
  201. sleep(5);
  202. $db_conn = DBI->connect(
  203. "DBI:mysql:$db_name:$db_host",
  204. $db_user, $db_pass, { mysql_enable_utf8 => 1 }
  205. );
  206. }
  207. $db_conn->do("SET NAMES 'utf8'");
  208. &printEvent("MYSQL", "Connecting to MySQL database '$db_name' on '$db_host' as user '$db_user' ... connected ok", 1);
  209. %db_stmt_cache = ();
  210. }
  211.  
  212. #
  213. # result doQuery (string query)
  214. #
  215. # Executes the SQL query 'query' and returns the result identifier.
  216. #
  217.  
  218. sub doQuery
  219. {
  220. my ($query, $callref) = @_;
  221. if(!$db_conn->ping()) {
  222. &printEvent("HLSTATSX", "Lost database connection. Trying to reconnect...", 1);
  223. &doConnect();
  224. }
  225.  
  226. my $result = $db_conn->prepare($query) or die("Unable to prepare query:\n$query\n$DBI::errstr\n$callref");
  227. $result->execute or die("Unable to execute query:\n$query\n$DBI::errstr\n$callref");
  228.  
  229. return $result;
  230. }
  231.  
  232. sub execNonQuery
  233. {
  234. my ($query) = @_;
  235. if(!$db_conn->ping()) {
  236. &printEvent("HLSTATSX", "Lost database connection. Trying to reconnect...", 1);
  237. &doConnect();
  238. }
  239. #&printEvent("DEBUG","execNonQuery:\n".$query);
  240. $db_conn->do($query);
  241. }
  242.  
  243. sub execCached {
  244. my ($query_id,$query, @bind_args) = @_;
  245.  
  246. if(!$db_conn->ping()) {
  247. &printEvent("HLSTATSX", "Lost database connection. Trying to reconnect...", 1);
  248. &doConnect();
  249. }
  250.  
  251. if(!$db_stmt_cache{$query_id}) {
  252. $db_stmt_cache{$query_id} = $db_conn->prepare($query) or die("Unable to prepare query ($query_id):\n$query\n$DBI::errstr");
  253. #&printEvent("HLSTATSX", "Prepared a statement ($query_id) for the first time.", 1);
  254. }
  255. $db_stmt_cache{$query_id}->execute(@bind_args) or die ("Unable to execute query ($query_id):\n$query\n$DBI::errstr");
  256. return $db_stmt_cache{$query_id};
  257. }
  258.  
  259. #
  260. # string resolveIp (string ip, boolean quiet)
  261. #
  262. # Do a DNS reverse-lookup on an IP address and return the hostname, or empty
  263. # string on error.
  264. #
  265.  
  266. sub resolveIp
  267. {
  268. my ($ip, $quiet) = @_;
  269. my ($host) = "";
  270.  
  271. unless ($g_dns_resolveip)
  272. {
  273. return "";
  274. }
  275.  
  276.  
  277. eval
  278. {
  279. $SIG{ALRM} = sub { die "DNS Timeout\n" };
  280. alarm $g_dns_timeout; # timeout after $g_dns_timeout sec
  281. $host = gethostbyaddr(inet_aton($ip), AF_INET);
  282. alarm 0;
  283. };
  284.  
  285. if ($@)
  286. {
  287. my $error = $@;
  288. chomp($error);
  289. printEvent("DNS", "Resolving hostname (timeout $g_dns_timeout sec) for IP \"$ip\" - $error ", 1);
  290. $host = ""; # some error occurred
  291. }
  292. elsif (!defined($host))
  293. {
  294. printEvent("DNS", "Resolving hostname (timeout $g_dns_timeout sec) for IP \"$ip\" - No Host ", 1);
  295. $host = ""; # ip did not resolve to any host
  296. } else {
  297. $host = lc($host); # lowercase
  298. printEvent("DNS", "Resolving hostname (timeout $g_dns_timeout sec) for IP \"$ip\" - $host ", 1);
  299. }
  300. chomp($host);
  301. return $host;
  302. }
  303.  
  304.  
  305. #
  306. # object queryHostGroups ()
  307. #
  308. # Returns result identifier.
  309. #
  310.  
  311. sub queryHostGroups
  312. {
  313. return &doQuery("
  314. SELECT
  315. pattern,
  316. name,
  317. LENGTH(pattern) AS patternlength
  318. FROM
  319. hlstats_HostGroups
  320. ORDER BY
  321. patternlength DESC,
  322. pattern ASC
  323. ");
  324. }
  325.  
  326.  
  327. #
  328. # string getHostGroup (string hostname[, object result])
  329. #
  330. # Return host group name if any match, or last 2 or 3 parts of hostname.
  331. #
  332.  
  333. sub getHostGroup
  334. {
  335. my ($hostname, $result) = @_;
  336. my $hostgroup = "";
  337.  
  338. # User can define special named hostgroups in hlstats_HostGroups, i.e.
  339. # '.adsl.someisp.net' => 'SomeISP ADSL'
  340.  
  341. $result = &queryHostGroups() unless ($result);
  342. $result->execute();
  343.  
  344. while (my($pattern, $name) = $result->fetchrow_array())
  345. {
  346. $pattern = quotemeta($pattern);
  347. $pattern =~ s/\\\*/[^.]*/g; # allow basic shell-style globbing in pattern
  348. if ($hostname =~ /$pattern$/)
  349. {
  350. $hostgroup = $name;
  351. last;
  352. }
  353. }
  354. $result->finish;
  355.  
  356. if (!$hostgroup)
  357. {
  358. #
  359. # Group by last 2 or 3 parts of hostname, i.e. 'max1.xyz.someisp.net' as
  360. # 'someisp.net', and 'max1.xyz.someisp.net.nz' as 'someisp.net.nz'.
  361. # Unfortunately some countries do not have categorical SLDs, so this
  362. # becomes more complicated. The dom_nosld array below contains a list of
  363. # known country codes that do not use categorical second level domains.
  364. # If a country uses SLDs and is not listed below, then it will be
  365. # incorrectly grouped, i.e. 'max1.xyz.someisp.yz' will become
  366. # 'xyz.someisp.yz', instead of just 'someisp.yz'.
  367. #
  368. # Please mail sgarner@hlstats.org with any additions.
  369. #
  370.  
  371. my @dom_nosld = (
  372. "ca", # Canada
  373. "ch", # Switzerland
  374. "be", # Belgium
  375. "de", # Germany
  376. "ee", # Estonia
  377. "es", # Spain
  378. "fi", # Finland
  379. "fr", # France
  380. "ie", # Ireland
  381. "nl", # Netherlands
  382. "no", # Norway
  383. "ru", # Russia
  384. "se", # Sweden
  385. );
  386.  
  387. my $dom_nosld = join("|", @dom_nosld);
  388.  
  389. if ($hostname =~ /([\w-]+\.(?:$dom_nosld|\w\w\w))$/)
  390. {
  391. $hostgroup = $1;
  392. }
  393. elsif ($hostname =~ /([\w-]+\.[\w-]+\.\w\w)$/)
  394. {
  395. $hostgroup = $1;
  396. }
  397. else
  398. {
  399. $hostgroup = $hostname;
  400. }
  401. }
  402.  
  403. return $hostgroup;
  404. }
  405.  
  406.  
  407. #
  408. # void doConf (object conf, hash directives)
  409. #
  410. # Walk through configuration directives, setting values of global variables.
  411. #
  412.  
  413. sub doConf
  414. {
  415. my ($conf, %directives) = @_;
  416.  
  417. while (($directive, $variable) = each(%directives))
  418. {
  419. if ($directive eq "Servers") {
  420. %$variable = $conf->get($directive);
  421. } else {
  422. $$variable = $conf->get($directive);
  423. }
  424. }
  425.  
  426. }
  427.  
  428. #
  429. # void setOptionsConf (hash optionsconf)
  430. #
  431. # Walk through configuration directives, setting values of global variables.
  432. #
  433.  
  434. sub setOptionsConf
  435. {
  436. my (%optionsconf) = @_;
  437.  
  438. while (($thekey, $theval) = each(%optionsconf))
  439. {
  440. if($theval)
  441. {
  442. $$thekey = $theval;
  443. }
  444. }
  445.  
  446. }
  447.  
  448.  
  449. #
  450. # string abbreviate (string thestring[, int maxlength)
  451. #
  452. # Returns thestring abbreviated to maxlength-3 characters plus "...", unless
  453. # thestring is shorter than maxlength.
  454. #
  455.  
  456. sub abbreviate
  457. {
  458. my ($thestring, $maxlength) = @_;
  459.  
  460. $maxlength = 12 unless ($maxlength);
  461.  
  462. if (length($thestring) > $maxlength)
  463. {
  464. $thestring = substr($thestring, 0, $maxlength - 3);
  465. return "$thestring...";
  466. }
  467. else
  468. {
  469. return $thestring;
  470. }
  471. }
  472.  
  473.  
  474. #
  475. # void printEvent (int code, string description)
  476. #
  477. # Logs event information to stdout.
  478. #
  479.  
  480. sub printEvent
  481. {
  482. my ($code, $description, $update_timestamp, $force_output) = @_;
  483. if ( (($g_debug > 0) && ($g_stdin == 0))|| (($g_stdin == 1) && ($force_output == 1)) ) {
  484. my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time());
  485. my $timestamp = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
  486. if ($update_timestamp == 0) {
  487. $timestamp = $ev_timestamp;
  488. }
  489. if (is_number($code)) {
  490. printf("%s: %21s - E%03d: %s\n", $timestamp, $s_addr, $code, $description);
  491. } else {
  492. printf("%s: %21s - %s: %s\n", $timestamp, $s_addr, $code, $description);
  493. }
  494. }
  495. }
  496.  
  497. 1;
Add Comment
Please, Sign In to add comment