Initial release

This commit is contained in:
Daniel Winzen
2016-12-11 08:36:05 +01:00
commit 34dd1cbe24
10 changed files with 711 additions and 0 deletions

26
README Normal file
View File

@ -0,0 +1,26 @@
GENERAL INFORMATION:
This is a set of script to run a hit counter, specifically designed for TOR hidden services. An up-to-date copy can be downloaded at https://github.com/DanWin/hit-counter
INSTALLATION INSTRUCTIONS:
You'll need to have php with pdo_mysql, pcre and date extension, a web-server and a MySQL server installed.
When you have everything installed, you'll have to create a database and a user for the scripts.
Then edit the configuration in counter_config.php to reflect the appropriate database settings and to modify the settings the way you like them.
Then copy the scripts to your web-server directory and open the setup.php script like this: http://(server)/setup.php
Note: If you updated the script, please visit http://(server)/setup.php again, to make sure, that any database changes are applied and no errors occure.
TRANSLATING:
Copy counter_lang_en.php and rename it to counter_lang_YOUR_LANGCODE.php
Then edit the file and translate the messages into your language and change $I to $T at the top.
If you ever use a ' character, you have to escape it by using \' instead or the script will fail.
When you are done, you have to edit counter_config.php, to include your translation. Simply add a line with
'lang_code' => 'Language name',
to the $L array below the settings, similar to what I did for the German translation.
Please share your translation with me, so I can add it to the official version.
To update your translation, you can copy each new string to your translation file or edit the automated lang_update.php script to reflect you language and run it.
LIVE DEMO:
If you want to see the scripts in action, you can visit my TOR hidden service http://tt3j2x4k5ycaa5zt.onion/counter_reg.php or via my clearnet proxy https://danwin1210.me/counter_reg.php if you don't have TOR installed.

30
README.md Normal file
View File

@ -0,0 +1,30 @@
General information:
--------------------
This is a set of script to run a hit counter, specifically designed for TOR hidden services. An up-to-date copy can be downloaded at https://github.com/DanWin/hit-counter
Installation instructions:
--------------------------
You'll need to have php with pdo_mysql, pcre and date extension, a web-server and a MySQL server installed.
When you have everything installed, you'll have to create a database and a user for the scripts.
Then edit the configuration in counter_config.php to reflect the appropriate database settings and to modify the settings the way you like them.
Then copy the scripts to your web-server directory and open the setup.php script like this: http://(server)/setup.php
Note: If you updated the script, please visit http://(server)/setup.php again, to make sure, that any database changes are applied and no errors occure.
Translating:
------------
Copy counter_lang_en.php and rename it to counter_lang_YOUR_LANGCODE.php
Then edit the file and translate the messages into your language and change $I to $T at the top.
If you ever use a ' character, you have to escape it by using \' instead or the script will fail.
When you are done, you have to edit counter_config.php, to include your translation. Simply add a line with
```'lang_code' => 'Language name',```
to the $L array below the settings, similar to what I did for the German translation.
Please share your translation with me, so I can add it to the official version.
To update your translation, you can copy each new string to your translation file or edit the automated lang_update.php script to reflect you language and run it.
Live Demo:
----------
If you want to see the scripts in action, you can visit my TOR hidden service http://tt3j2x4k5ycaa5zt.onion/counter_reg.php or via my clearnet proxy https://danwin1210.me/counter_reg.php if you don't have TOR installed.

98
counter.php Normal file
View File

@ -0,0 +1,98 @@
<?php
/*
* Hit Counter - Counter image
*
* Copyright (C) 2016 Daniel Winzen <d@winzen4.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//prepare
include_once('counter_config.php');
$time=time();
$update_time=$time-($time%3600);
try{
$db=new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPASS, [PDO::ATTR_ERRMODE=>PDO::ERRMODE_WARNING, PDO::ATTR_PERSISTENT=>PERSISTENT]);
}catch(PDOException $e){
exit($I['nodb']);
}
if(!isset($_REQUEST['id'])){
exit;
}
$stmt=$db->prepare('SELECT * FROM ' . PREFIX . 'registered WHERE api_key=?;');
$stmt->execute([$_REQUEST['id']]);
if(!$id=$stmt->fetch(PDO::FETCH_NUM)){
exit;
}
//headers
header('Pragma: no-cache');
header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0');
header('Expires: 0');
header('Content-Type: image/gif');
//add visitor to db
$stmt=$db->prepare('INSERT INTO ' . PREFIX . 'visitors (id, time, count) VALUES (?, ?, 1) ON DUPLICATE KEY UPDATE count=count+1;');
$stmt->execute([$id[0], $update_time]);
if(!isSet($_COOKIE["counted$_REQUEST[id]"])){
$stmt=$db->prepare('UPDATE ' . PREFIX . 'visitors SET unique_count=unique_count+1 WHERE id=? AND time=?;');
$stmt->execute([$id[0], $update_time]);
setcookie("counted$_REQUEST[id]", 1, $time+3600);
}
//get number of visitors
if(!isSet($_REQUEST['unique']) || $_REQUEST['unique']==0){
$stmt=$db->prepare('SELECT SUM(count) FROM ' . PREFIX . 'visitors WHERE id=? AND time>=? AND time<?;');
}else{
$stmt=$db->prepare('SELECT SUM(unique_count) FROM ' . PREFIX . 'visitors WHERE id=? AND time>=? AND time<?;');
}
if(!isSet($_REQUEST['mode']) || $_REQUEST['mode']==0){
//overalll
$stmt->execute([$id[0], 0, $time]);
}elseif($_REQUEST['mode']==1){
//last hour
$stmt->execute([$id[0], $update_time-3600, $update_time]);
}elseif($_REQUEST['mode']==2){
//last 24 hours
$stmt->execute([$id[0], $update_time-86400, $update_time]);
}elseif($_REQUEST['mode']==3){
// last week
$stmt->execute([$id[0], $update_time-604800, $update_time]);
}else{
//last month
$stmt->execute([$id[0], $update_time-2592000, $update_time]);
}
$num=$stmt->fetch(PDO::FETCH_NUM);
//prepare and output image
$im=imagecreatetruecolor(strlen($num[0])*9+10, 24);
if(isset($_REQUEST['bg']) && preg_match('/^[0-9A-F]{6}$/i', $_REQUEST['bg'])){
$bg=imagecolorallocate($im, hexdec(substr($_REQUEST['bg'], 0, 2)), hexdec(substr($_REQUEST['bg'], 2, 2)), hexdec(substr($_REQUEST['bg'], 4, 2)));
}else{
$bg=imagecolorallocate($im, 0, 0, 0);
}
if(isset($_REQUEST['fg']) && preg_match('/^[0-9A-F]{6}$/i', $_REQUEST['fg'])){
$fg=imagecolorallocate($im, hexdec(substr($_REQUEST['fg'], 0, 2)), hexdec(substr($_REQUEST['fg'], 2, 2)), hexdec(substr($_REQUEST['fg'], 4, 2)));
}else{
$fg=imagecolorallocate($im, 255, 255, 255);
}
if(isset($_REQUEST['tr']) && $_REQUEST['tr']==1){
$bg=imagecolorallocate($im, 0, 0, 0);
imagecolortransparent($im, $bg);
}else{
imagefill($im, 0, 0, $bg);
}
imagestring($im, 5, 5, 5, $num[0], $fg);
imagegif($im);
imagedestroy($im);
?>

71
counter_config.php Normal file
View File

@ -0,0 +1,71 @@
<?php
/*
* Hit Counter - Configuration
*
* Copyright (C) 2016 Daniel Winzen <d@winzen4.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Configuration
const DBHOST='localhost'; // Database host
const DBUSER='www-data'; // Database user
const DBPASS='YOUR_PASS'; // Database password
const DBNAME='counter'; // Database
const PREFIX=''; // Table Prefix - useful if other programs use the same names for tables - use only alpha-numeric values (A-Z, a-z, 0-9, or _)
const PERSISTENT=true; // Use persistent database conection true/false
const LANG='en'; // Default language
const BASEURL='http://tt3j2x4k5ycaa5zt.onion/'; // URL where the scripts are (e.g. http://example.com/path/)
const VERSION='1.0'; // Script version
const DBVERSION=1; // Database layout version
// Language selection
$L=[
'de' => 'Deutsch',
'en' => 'English',
];
if(isSet($_REQUEST['lang']) && isSet($L[$_REQUEST['lang']])){
$language=$_REQUEST['lang'];
if(!isSet($_COOKIE['language']) || $_COOKIE['language']!==$language){
setcookie('language', $language);
}
}elseif(isSet($_COOKIE['language']) && isSet($L[$_COOKIE['language']])){
$language=$_COOKIE['language'];
}else{
$language=LANG;
}
include_once('counter_lang_en.php'); //always include English
if($language!=='en'){
$T=[];
include_once("counter_lang_$language.php"); //replace with translation if available
foreach($T as $name=>$translation){
$I[$name]=$translation;
}
}
function print_langs(){
global $I, $L;
echo "<small>$I[language]: ";
$query=preg_replace('/(&?lang=[a-z_\-]*)/i', '', $_SERVER['QUERY_STRING']);
foreach($L as $code=>$name){
if($query===''){
$uri="?lang=$code";
}else{
$uri='?'.htmlspecialchars($query)."&amp;lang=$code";
}
echo " <a href=\"$uri\">$name</a>";
}
echo '</small>';
}
?>

60
counter_lang_de.php Normal file
View File

@ -0,0 +1,60 @@
<?php
/*
* Hit Counter - German translation
*
* Copyright (C) 2016 Daniel Winzen <d@winzen4.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
$T=[
'titlereg' => 'Hit Counter',
'descriptionreg' => 'Hier kannst du dienen eigenen Hit Counter registrieren.',
'preload' => 'Soviele Aufrufe vorladen: %s (Nützlich, wenn von einem anderen Dienst umgezogen wird <small>oder zum fälschen</small>)',
'register' => 'Registrieren',
'regsuccess' => 'Du hast erfolgreich einen neuen Hit Counter registriert. Dein API-Key ist: %s',
'embedinstruct' => 'Um deinen Zähler einzubinden, kannst du den folgenden Code zu deiner Seite hinzufügen:',
'modifyinstruct' => 'Um den Zähler an deine wünsche anzupassen, kannst du die folgenden Parameter ändern:',
'modid' => 'id - Dein eindeutiger API-Key',
'modbg' => 'bg - Hexadezimaler Farbcode für die Hintergrundfarbe (Standard: 000000)',
'modfg' => 'fg - Hexadezimaler Farbcode für die Vordergrundfarbe (Standard: FFFFFF)',
'modtr' => 'tr - Transparent: 1 oder 0 (Standard: 0)',
'modunique' => 'unique - Eindeutige (1) oder alle (0) Besuche anzeigen (Standard: 0):',
'modmode' => 'mode - Anzeigemodus (Standard: 0):',
'modmode0' => '0 für alle insgesamt',
'modmode1' => '1 für letzte Stunde',
'modmode2' => '2 für letzter Tag',
'modmode3' => '3 für letzte Woche',
'modmode4' => '4 und alles andere für letzter Monat',
'titlestat' => 'Besucher-Statistiken',
'descriptionstat' => 'Statistiken werden durch ein Zähl-Bild generiert. Es zählt nicht jeden Aufruf auf dem Server, nur die zu den Hauptseiten. Eindeutige Besucher werden durch ein Cookie gezählt, um zu sehen, wer bereits gezählt wurde. Dies ist ungenau, da nicht jeder Cookies aktiviert hat und wenn der Zähler für eine andere Seite ist, viele Cookies von Drittanbietern deaktiviert haben.',
'fallback' => 'Ungültige id, zeige Statistiken dieser Seite statdessen.',
'when' => 'Wann',
'count' => 'Anzahl',
'unique' => 'Eindeutig',
'lasthour' => 'Letzte Stunde',
'lastday' => 'Letzten 24 Stunden',
'lastweek' => 'Letzten 7 Tage',
'lastmonth' => 'Letzten 30 Tage',
'overall' => 'Alle insgesamt',
'graphs' => 'Graphen: <small>(<span style="color:#FF0000;">Besucherzahl</span>, <span style="color:#0000FF;">Eindeutig</span>)</small>',
'language' => 'Sprache',
'pdo_mysqlextrequired' => 'Die pdo_mysql Erweiterung von PHP wird benötigt. Bitte installieren Sie diese zuerst.',
'pcreextrequired' => 'Die pcre Erweiterung von PHP wird benötigt. Bitte installieren Sie diese zuerst.',
'dateextrequired' => 'Die date Erweiterung von PHP wird benötigt. Bitte installieren Sie diese zuerst.',
'succdbcreate' => 'Die Datenbank wurde erfolgreich erstellt!',
'statusok' => 'Status: OK',
'nodb' => 'Keine Datenbankverbindung!',
];
?>

60
counter_lang_en.php Normal file
View File

@ -0,0 +1,60 @@
<?php
/*
* Hit Counter - English translation
*
* Copyright (C) 2016 Daniel Winzen <d@winzen4.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
$I=[
'titlereg' => 'Hit Counter',
'descriptionreg' => 'Here you can register your own hit counter.',
'preload' => 'Preload with this many hits: %s (Useful when moving from another service <small>or faking</small>)',
'register' => 'Register',
'regsuccess' => 'You have successfully registered a new hit counter. Your api_key is: %s',
'embedinstruct' => 'To embed your counter, you can add the following code to your website:',
'modifyinstruct' => 'To modify the counter to your needs, you can change the following parameters:',
'modid' => 'id - Your unique api key',
'modbg' => 'bg - Hexadecimal colour code for the background colour (Default: 000000)',
'modfg' => 'fg - Hexadecimal colour code for the forground colour (Default: FFFFFF)',
'modtr' => 'tr - Transparent: 1 or 0 (Default: 0)',
'modunique' => 'unique - Show unique (1) or all (0) visits (Default: 0):',
'modmode' => 'mode - Display mode (Default: 0):',
'modmode0' => '0 for overall stats',
'modmode1' => '1 for last hour',
'modmode2' => '2 for last 24 hours',
'modmode3' => '3 for last week',
'modmode4' => '4 and anything else for last month',
'titlestat' => 'Visitor statistics',
'descriptionstat' => 'Statistics are generated via a counter image. It does not include every single request to the server, only those on the main pages. Unique visitors get counted by setting a cookie to see who we already counted. Treat unique hits as tainted, because not everyone has cookies enabled and if it\'s the hit counter of another site, many have 3rd party cookies blocked.',
'fallback' => 'Invalid id, showing statistics of this page instead.',
'when' => 'When',
'count' => 'Count',
'unique' => 'Unique',
'lasthour' => 'Last hour',
'lastday' => 'Last 24 hours',
'lastweek' => 'Last 7 days',
'lastmonth' => 'Last 30 days',
'overall' => 'Overall',
'graphs' => 'Graphs: <small>(<span style="color:#FF0000;">visit count</span>, <span style="color:#0000FF;">unique</span>)</small>',
'language' => 'Language',
'pdo_mysqlextrequired' => 'The pdo_mysql extension of PHP is required. Please install it first.',
'pcreextrequired' => 'The pcre extension of PHP is required. Please install it first.',
'dateextrequired' => 'The date extension of PHP is required. Please install it first.',
'succdbcreate' => 'The database has successfully been created!',
'statusok' => 'Status: OK',
'nodb' => 'No database connection!',
];
?>

82
counter_reg.php Normal file
View File

@ -0,0 +1,82 @@
<?php
/*
* Hit Counter - Registration
*
* Copyright (C) 2016 Daniel Winzen <d@winzen4.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once('counter_config.php');
header('Content-Type: text/html; charset=UTF-8');
echo '<!DOCTYPE html><html><head>';
echo "<title>$I[titlereg]</title>";
echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
echo '<meta name=viewport content="width=device-width, initial-scale=1">';
echo '</head><body>';
echo "<h2>$I[titlereg]</h2>";
print_langs();
echo "<p>$I[descriptionreg]</p>";
echo "<form action=\"$_SERVER[SCRIPT_NAME]\" method=\"POST\">";
echo '<p>'.sprintf($I['preload'], '<input type="number" placeholder="0" name="preload">').'</p>';
echo "<input type=\"submit\" name=\"register\" value=\"$I[register]\">";
echo '</form>';
if($_SERVER['REQUEST_METHOD']==='POST'){
try{
$db=new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPASS, [PDO::ATTR_ERRMODE=>PDO::ERRMODE_WARNING, PDO::ATTR_PERSISTENT=>PERSISTENT]);
}catch(PDOException $e){
exit($I['nodb']);
}
$stmt=$db->prepare('SELECT * FROM ' . PREFIX . 'registered WHERE api_key=?;');
do{
if(function_exists('random_bytes')){
$key=bin2hex(random_bytes(16));
}else{
$key=md5(uniqid('', true).mt_rand());
}
$stmt->execute([$key]);
}while($stmt->fetch(PDO::FETCH_NUM));
$stmt=$db->prepare('INSERT INTO ' . PREFIX . 'registered (api_key) VALUES (?);');
$stmt->execute([$key]);
if(isset($_REQUEST['preload'])){
settype($_REQUEST['preload'], 'int');
if($_REQUEST['preload']>0){
$stmt=$db->prepare('INSERT INTO ' . PREFIX . 'visitors (id, time, count) VALUES ((SELECT id FROM ' . PREFIX . 'registered WHERE api_key=?), 0, ?)');
$stmt->execute([$key, $_REQUEST['preload']]);
}
}
echo '<p style="color:green;">'.sprintf($I['regsuccess'], $key).'</p>';
}else{
$key='YOUR_API_KEY';
}
echo "<p>$I[embedinstruct]<br>";
echo '&lt;a href=&quot;' . BASEURL . "visits.php?id=$key&quot;&gt;&lt;img style=&quot;height:24px;width:auto;&quot; src=&quot;" . BASEURL . "counter.php?id=$key&amp;bg=000000&amp;fg=FFFFFF&amp;tr=0&amp;unique=0&amp;mode=0&quot;&gt;&lt;/a&gt;</p>";
echo "<p>$I[modifyinstruct]</p>";
echo '<ul>';
echo "<li>$I[modid]</li>";
echo "<li>$I[modbg]</li>";
echo "<li>$I[modfg]</li>";
echo "<li>$I[modtr]</li>";
echo "<li>$I[modunique]<ul>";
echo "<li>$I[modmode]<ul>";
echo "<li>$I[modmode0]</li>";
echo "<li>$I[modmode1]</li>";
echo "<li>$I[modmode2]</li>";
echo "<li>$I[modmode3]</li>";
echo "<li>$I[modmode4]</li>";
echo '</ul></li>';
echo '</ul>';
echo '<br><p style="text-align:center;font-size:small;"><a target="_blank" href="https://github.com/DanWin/hit-counter">Hit Counter - ' . VERSION . '</a></p>';
echo '</body></html>';
?>

45
lang_update.php Normal file
View File

@ -0,0 +1,45 @@
<?php
$native = 'Deutsch'; // Native lanugae name
$english = 'German'; // Enlish language name
$code = 'de'; // Language code
ob_start();
echo "<?php
/*
* Hit Counter - $english translation
*
* Copyright (C) 2016 Daniel Winzen <d@winzen4.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//Native language name: $native
\$T=[
";
if(file_exists("counter_lang_$code.php")){
include("counter_lang_$code.php");
}
include('counter_lang_en.php');
foreach($T as $id=>$value){
if(isSet($I[$id])){
$I[$id]=$value;
}
}
foreach($I as $id=>$value){
echo "\t'$id' => '".str_replace("'", "\'", $value)."',\n";
}
echo "];\n?>\n";
$file=ob_get_clean();
file_put_contents("counter_lang_$code.php", $file);
?>

57
setup.php Normal file
View File

@ -0,0 +1,57 @@
<?php
/*
* Onion Link List - Setup
*
* Copyright (C) 2016 Daniel Winzen <d@winzen4.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include('counter_config.php');
if(!extension_loaded('pdo_mysql')){
die($I['pdo_mysqlextrequired']);
}
if(!extension_loaded('pcre')){
die($I['pcreextrequired']);
}
if(!extension_loaded('date')){
die($I['dateextrequired']);
}
try{
$db=new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPASS, [PDO::ATTR_ERRMODE=>PDO::ERRMODE_WARNING, PDO::ATTR_PERSISTENT=>PERSISTENT]);
}catch(PDOException $e){
try{
//Attempt to create database
$db=new PDO('mysql:host=' . DBHOST, DBUSER, DBPASS, [PDO::ATTR_ERRMODE=>PDO::ERRMODE_WARNING, PDO::ATTR_PERSISTENT=>PERSISTENT]);
if(false!==$db->exec('CREATE DATABASE ' . DBNAME)){
$db=new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPASS, [PDO::ATTR_ERRMODE=>PDO::ERRMODE_WARNING, PDO::ATTR_PERSISTENT=>PERSISTENT]);
}else{
die($I['nodb']);
}
}catch(PDOException $e){
die($I['nodb']);
}
}
if(!@$db->query('SELECT * FROM ' . PREFIX . 'settings LIMIT 1;')){
//create tables
$db->exec('CREATE TABLE ' . PREFIX . 'registered (id int(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, api_key char(32) NOT NULL UNIQUE) DEFAULT CHARSET=latin1;');
$db->exec('CREATE TABLE ' . PREFIX . 'visitors (id int(10) UNSIGNED NOT NULL, time int(10) UNSIGNED NOT NULL, count int(10) UNSIGNED NOT NULL, unique_count int(10) UNSIGNED NOT NULL);');
$db->exec('ALTER TABLE ' . PREFIX . 'visitors ADD PRIMARY KEY (id,time), ADD KEY id (id), ADD KEY time (time);');
$db->exec('CREATE TABLE ' . PREFIX . 'settings (setting varchar(50) NOT NULL PRIMARY KEY, value varchar(15000) NOT NULL);');
$db->exec('INSERT INTO ' . PREFIX . "settings (setting, value) VALUES ('version', '1');");
echo "$I[succdbcreate]\n";
}else{
echo "$I[statusok]\n";
}
?>

182
visits.php Normal file
View File

@ -0,0 +1,182 @@
<?php
/*
* Hit Counter - Visitor statistics
*
* Copyright (C) 2016 Daniel Winzen <d@winzen4.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
include_once('counter_config.php');
try{
$db=new PDO('mysql:host=' . DBHOST . ';dbname=' . DBNAME, DBUSER, DBPASS, [PDO::ATTR_ERRMODE=>PDO::ERRMODE_WARNING, PDO::ATTR_PERSISTENT=>PERSISTENT]);
}catch(PDOException $e){
exit($I['nodb']);
}
$fallback=false;
if(isset($_REQUEST['id'])){
$stmt=$db->prepare('SELECT * FROM ' . PREFIX . 'registered WHERE api_key=?;');
$stmt->execute([$_REQUEST['id']]);
if($id=$stmt->fetch(PDO::FETCH_NUM)){
$id=$id[0];
}else{
$fallback=true;
$id=0;
}
}else{
$fallback=true;
$id=0;
}
$stmt=$db->prepare('SELECT SUM(count) FROM ' . PREFIX . 'visitors WHERE id=? AND time>=? AND time<?;');
$stmt2=$db->prepare('SELECT SUM(unique_count) FROM ' . PREFIX . 'visitors WHERE id=? AND time>=? AND time<?;');
header('Content-Type: text/html; charset=UTF-8');
echo '<!DOCTYPE html><html><head>';
echo "<title>$I[titlestat]</title>";
echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
echo '<meta name=viewport content="width=device-width, initial-scale=1">';
echo '</head><body>';
echo "<h2>$I[titlestat]</h2>";
$time=time();
$update_time=$time-$time%3600;
print_langs();
echo "<p>$I[descriptionstat]</p>";
if($fallback){
echo "<p style=\"color:red;\">$I[fallback]</p>";
}
echo '<table>';
echo "<tr><th>$I[when]</th><th>$I[count]</th><th>$I[unique]</th></tr>";
echo "<tr><td>$I[lasthour]</td>";
$num=fetch_numbers($id, $update_time-3600, $update_time);
echo "<td>$num[0]</td><td>$num[1]</td></tr>";
echo "<tr><td>$I[lastday]</td>";
$num=fetch_numbers($id, $update_time-86400, $update_time);
echo "<td>$num[0]</td><td>$num[1]</td></tr>";
echo "<tr><td>$I[lastweek]</td>";
$num=fetch_numbers($id, $update_time-604800, $update_time);
echo "<td>$num[0]</td><td>$num[1]</td></tr>";
echo "<tr><td>$I[lastmonth]</td>";
$num=fetch_numbers($id, $update_time-2592000, $update_time);
echo "<td>$num[0]</td><td>$num[1]</td></tr>";
echo "<tr><td>$I[overall]</td>";
$num=fetch_numbers($id, 0, $time);
echo "<td>$num[0]</td><td>$num[1]</td></tr>";
echo '</table>';
echo "<br><p>$I[graphs]</small></p>";
echo "<p>$I[lastday]</p>";
$visits=[];
$unvisits=[];
$highest=1;
for($i=24; $i>0; --$i){
$stmt->execute([$id, $time-3600*($i+1), $time-3600*$i]);
$tmp=$stmt->fetch(PDO::FETCH_NUM);
$stmt2->execute([$id, $time-3600*($i+1), $time-3600*$i]);
$tmp2=$stmt2->fetch(PDO::FETCH_NUM);
$visits[]=$tmp[0];
$unvisits[]=$tmp2[0];
if($highest<$tmp[0]){
$highest=$tmp[0];
}
}
$im=imagecreate(230, 100);
$bg=imagecolorallocate($im, 0, 0, 0);
imagefill($im, 0, 0, $bg);
$color=imagecolorallocate($im, 255, 0, 0);
$uncolor=imagecolorallocate($im, 0, 0, 255);
for($i=0; $i<23; ++$i){
imageline($im, $i*10, 100-($visits[$i]/$highest)*100, ($i+1)*10, 100-($visits[$i+1]/$highest)*100, $color);
imageline($im, $i*10, 100-($unvisits[$i]/$highest)*100, ($i+1)*10, 100-($unvisits[$i+1]/$highest)*100, $uncolor);
}
echo '<img width="230" height="100" src="data:image/gif;base64,';
ob_start();
imagegif($im);
imagedestroy($im);
echo base64_encode(ob_get_clean()).'">';
echo "<br><p>$I[lastweek]</p>";
$visits=[];
$unvisits=[];
$highest=1;
for($i=28; $i>0; --$i){
$stmt->execute([$id, $time-21600*($i+1), $time-21600*$i]);
$tmp=$stmt->fetch(PDO::FETCH_NUM);
$stmt2->execute([$id, $time-21600*($i+1), $time-21600*$i]);
$tmp2=$stmt2->fetch(PDO::FETCH_NUM);
$visits[]=$tmp[0];
$unvisits[]=$tmp2[0];
if($highest<$tmp[0]){
$highest=$tmp[0];
}
}
$im=imagecreate(270, 100);
$bg=imagecolorallocate($im, 0, 0, 0);
imagefill($im, 0, 0, $bg);
$color=imagecolorallocate($im, 255, 0, 0);
$uncolor=imagecolorallocate($im, 0, 0, 255);
for($i=0; $i<27; ++$i){
imageline($im, $i*10, 100-($visits[$i]/$highest)*100, ($i+1)*10, 100-($visits[$i+1]/$highest)*100, $color);
imageline($im, $i*10, 100-($unvisits[$i]/$highest)*100, ($i+1)*10, 100-($unvisits[$i+1]/$highest)*100, $uncolor);
}
echo '<img width="270" height="100" src="data:image/gif;base64,';
ob_start();
imagegif($im);
imagedestroy($im);
echo base64_encode(ob_get_clean()).'">';
echo "<br><p>$I[lastmonth]</p>";
$visits=[];
$unvisits=[];
$highest=1;
for($i=30; $i>0; --$i){
$stmt->execute([$id, $time-86400*($i+1), $time-86400*$i]);
$tmp=$stmt->fetch(PDO::FETCH_NUM);
$stmt2->execute([$id, $time-86400*($i+1), $time-86400*$i]);
$tmp2=$stmt2->fetch(PDO::FETCH_NUM);
$visits[]=$tmp[0];
$unvisits[]=$tmp2[0];
if($highest<$tmp[0]){
$highest=$tmp[0];
}
}
$im=imagecreate(290, 100);
$bg=imagecolorallocate($im, 0, 0, 0);
imagefill($im, 0, 0, $bg);
$color=imagecolorallocate($im, 255, 0, 0);
$uncolor=imagecolorallocate($im, 0, 0, 255);
for($i=0; $i<29; ++$i){
imageline($im, $i*10, 100-($visits[$i]/$highest)*100, ($i+1)*10, 100-($visits[$i+1]/$highest)*100, $color);
imageline($im, $i*10, 100-($unvisits[$i]/$highest)*100, ($i+1)*10, 100-($unvisits[$i+1]/$highest)*100, $uncolor);
}
echo '<img width="290" height="100" src="data:image/gif;base64,';
ob_start();
imagegif($im);
imagedestroy($im);
echo base64_encode(ob_get_clean()).'">';
echo '<br><p style="text-align:center;font-size:small;"><a target="_blank" href="https://github.com/DanWin/hit-counter">Hit Counter - ' . VERSION . '</a></p>';
echo '</body></html>';
function fetch_numbers($id, $start, $end){
global $stmt, $stmt2, $num, $num2;
$stmt->execute([$id, $start, $end]);
$num=$stmt->fetch(PDO::FETCH_NUM);
$stmt2->execute([$id, $start, $end]);
$num2=$stmt2->fetch(PDO::FETCH_NUM);
if(!$num[0]){
$num[0]=0;
}
if(!$num2[0]){
$num2[0]=0;
}
return [number_format($num[0]), number_format($num2[0])];
}
?>