Merge branch 'master' of https://github.com/librespeed/speedtest into master

This commit is contained in:
dosse91 2020-10-24 09:32:53 +02:00
commit 3a35cd9cf2
8 changed files with 709 additions and 445 deletions

View file

@ -80,7 +80,10 @@ function getLocalOrPrivateIpInfo($ip)
*/ */
function getIpInfoTokenString() function getIpInfoTokenString()
{ {
if (!file_exists(API_KEY_FILE)) { if (
!file_exists(API_KEY_FILE)
|| !is_readable(API_KEY_FILE)
) {
return ''; return '';
} }
@ -139,7 +142,10 @@ function getIsp($rawIspInfo)
function getServerLocation() function getServerLocation()
{ {
$serverLoc = null; $serverLoc = null;
if (file_exists(SERVER_LOCATION_CACHE_FILE)) { if (
file_exists(SERVER_LOCATION_CACHE_FILE)
&& is_readable(SERVER_LOCATION_CACHE_FILE)
) {
require SERVER_LOCATION_CACHE_FILE; require SERVER_LOCATION_CACHE_FILE;
} }
if (is_string($serverLoc) && !empty($serverLoc)) { if (is_string($serverLoc) && !empty($serverLoc)) {

4
doc.md
View file

@ -44,7 +44,7 @@ Server side, you'll need:
* PHP 5.4 or newer, a 64-bit version is strongly recommended * PHP 5.4 or newer, a 64-bit version is strongly recommended
* OpenSSL and its PHP module (this is usually installed automatically by most distros) * OpenSSL and its PHP module (this is usually installed automatically by most distros)
* If you want to store test results (telemetry), one of the following: * If you want to store test results (telemetry), one of the following:
- MySQL/MariaDB and the mysqli PHP module - MySQL/MariaDB and its PHP PDO module
- PostgreSQL and its PHP PDO module - PostgreSQL and its PHP PDO module
- SQLite 3 and its PHP PDO module - SQLite 3 and its PHP PDO module
* If you want to enable results sharing: * If you want to enable results sharing:
@ -137,7 +137,7 @@ Requirements:
* Apache 2 (nginx and IIS also supported). A fast connection is not mandatory, but is still recommended * Apache 2 (nginx and IIS also supported). A fast connection is not mandatory, but is still recommended
* PHP 5.4 or newer * PHP 5.4 or newer
* If you want to store test results (telemetry), one of the following: * If you want to store test results (telemetry), one of the following:
- MySQL/MariaDB and the mysqli PHP module - MySQL/MariaDB and its PHP PDO module
- PostgreSQL and its PHP PDO module - PostgreSQL and its PHP PDO module
- SQLite 3 and its PHP PDO module - SQLite 3 and its PHP PDO module
* If you want to enable results sharing: * If you want to enable results sharing:

View file

@ -1,43 +1,72 @@
<?php <?php
function getObfuscationSalt(){
$saltFile=dirname(__FILE__)."/idObfuscation_salt.php"; define('ID_OBFUSCATION_SALT_FILE', __DIR__.'/idObfuscation_salt.php');
if(file_exists($saltFile)){
require $saltFile; /**
}else{ * @return string|int
$bytes=openssl_random_pseudo_bytes(4); */
$sf=fopen($saltFile,"w"); function getObfuscationSalt()
fwrite($sf,chr(60)."?php\n"); {
fwrite($sf,'$OBFUSCATION_SALT=0x'.bin2hex($bytes).";\n"); if (!file_exists(ID_OBFUSCATION_SALT_FILE)) {
fwrite($sf,"?".chr(62)); $bytes = openssl_random_pseudo_bytes(4);
fclose($sf);
require $saltFile; $saltData = "<?php\n\n\$OBFUSCATION_SALT = 0x".bin2hex($bytes).";\n";
} file_put_contents(ID_OBFUSCATION_SALT_FILE, $saltData);
return isset($OBFUSCATION_SALT)?$OBFUSCATION_SALT:0; }
}
/* if (
This is a simple reversible hash function I made for encoding and decoding test IDs. file_exists(ID_OBFUSCATION_SALT_FILE)
It is not cryptographically secure, don't use it to hash passwords or something! && is_readable(ID_OBFUSCATION_SALT_FILE)
*/ ) {
function obfdeobf($id,$dec){ require ID_OBFUSCATION_SALT_FILE;
$salt=getObfuscationSalt()&0xFFFFFFFF; }
$id=$id&0xFFFFFFFF;
if($dec){ return isset($OBFUSCATION_SALT) ? $OBFUSCATION_SALT : 0;
$id=$id^$salt;
$id=(($id&0xAAAAAAAA)>>1)|($id&0x55555555)<<1;
$id=(($id&0x0000FFFF)<<16)|(($id&0xFFFF0000)>>16);
return $id;
}else{
$id=(($id&0x0000FFFF)<<16)|(($id&0xFFFF0000)>>16);
$id=(($id&0xAAAAAAAA)>>1)|($id&0x55555555)<<1;
return $id^$salt;
}
}
function obfuscateId($id){
return str_pad(base_convert(obfdeobf($id+1,false),10,36),7,0,STR_PAD_LEFT);
}
function deobfuscateId($id){
return obfdeobf(base_convert($id,36,10),true)-1;
} }
//IMPORTANT: DO NOT ADD ANYTHING BELOW THE PHP CLOSING TAG, NOT EVEN EMPTY LINES! /**
?> * This is a simple reversible hash function I made for encoding and decoding test IDs.
* It is not cryptographically secure, don't use it to hash passwords or something!
*
* @param int|string $id
* @param bool $dec
*
* @return int|string
*/
function obfdeobf($id, $dec)
{
$salt = getObfuscationSalt() & 0xFFFFFFFF;
$id &= 0xFFFFFFFF;
if ($dec) {
$id ^= $salt;
$id = (($id & 0xAAAAAAAA) >> 1) | ($id & 0x55555555) << 1;
$id = (($id & 0x0000FFFF) << 16) | (($id & 0xFFFF0000) >> 16);
return $id;
}
$id = (($id & 0x0000FFFF) << 16) | (($id & 0xFFFF0000) >> 16);
$id = (($id & 0xAAAAAAAA) >> 1) | ($id & 0x55555555) << 1;
return $id ^ $salt;
}
/**
* @param int $id
*
* @return string
*/
function obfuscateId($id)
{
return str_pad(base_convert(obfdeobf($id + 1, false), 10, 36), 7, 0, STR_PAD_LEFT);
}
/**
* @param string $id
*
* @return int
*/
function deobfuscateId($id)
{
return obfdeobf(base_convert($id, 36, 10), true) - 1;
}

View file

@ -1,164 +1,213 @@
<?php <?php
$WATERMARK_TEXT="LibreSpeed";
require_once 'telemetry_db.php';
error_reporting(0); error_reporting(0);
putenv('GDFONTPATH=' . realpath('.')); putenv('GDFONTPATH='.realpath('.'));
function tryFont($name){
$rp=realpath('.'); /**
if(imageftbbox(12,0,$name,"M")[5]==0){ * @param string $name
$name=$rp."/".$name.".ttf"; *
if(imageftbbox(12,0,$name,"M")[5]==0){ * @return string|null
return null; */
} function tryFont($name)
} {
return $name; if (is_array(imageftbbox(12, 0, $name, 'M'))) {
} return $name;
function format($d){ }
if($d<10) return number_format($d,2,".","");
if($d<100) return number_format($d,1,".",""); $fullPathToFont = realpath('.').'/'.$name.'.ttf';
return number_format($d,0,".",""); if (is_array(imageftbbox(12, 0, $fullPathToFont, 'M'))) {
return $fullPathToFont;
}
return null;
} }
$SCALE=1.25; /**
$WIDTH=400*$SCALE; * @param int|float $d
$HEIGHT=229*$SCALE; *
$im=imagecreatetruecolor($WIDTH,$HEIGHT); * @return string
$BACKGROUND_COLOR=imagecolorallocate($im,255,255,255); */
$FONT_LABEL=tryFont("OpenSans-Semibold"); function format($d)
$FONT_LABEL_SIZE=14*$SCALE; {
$FONT_LABEL_SIZE_BIG=16*$SCALE; if ($d < 10) {
$FONT_METER=tryFont("OpenSans-Light"); return number_format($d, 2, '.', '');
$FONT_METER_SIZE=20*$SCALE; }
$FONT_METER_SIZE_BIG=22*$SCALE; if ($d < 100) {
$FONT_MEASURE=tryFont("OpenSans-Semibold"); return number_format($d, 1, '.', '');
$FONT_MEASURE_SIZE=12*$SCALE; }
$FONT_MEASURE_SIZE_BIG=12*$SCALE;
$FONT_ISP=tryFont("OpenSans-Semibold");
$FONT_ISP_SIZE=9*$SCALE;
$FONT_WATERMARK=tryFont("OpenSans-Light");
$FONT_WATERMARK_SIZE=8*$SCALE;
$TEXT_COLOR_LABEL=imagecolorallocate($im,40,40,40);
$TEXT_COLOR_DL_METER=imagecolorallocate($im,96,96,170);
$TEXT_COLOR_UL_METER=imagecolorallocate($im,96,96,96);
$TEXT_COLOR_PING_METER=imagecolorallocate($im,170,96,96);
$TEXT_COLOR_JIT_METER=imagecolorallocate($im,170,96,96);
$TEXT_COLOR_MEASURE=imagecolorallocate($im,40,40,40);
$TEXT_COLOR_ISP=imagecolorallocate($im,40,40,40);
$TEXT_COLOR_WATERMARK=imagecolorallocate($im,160,160,160);
$POSITION_Y_DL_LABEL=105*$SCALE;
$POSITION_Y_UL_LABEL=105*$SCALE;
$POSITION_Y_PING_LABEL=24*$SCALE;
$POSITION_Y_JIT_LABEL=24*$SCALE;
$POSITION_Y_DL_METER=143*$SCALE;
$POSITION_Y_UL_METER=143*$SCALE;
$POSITION_Y_PING_METER=60*$SCALE;
$POSITION_Y_JIT_METER=60*$SCALE;
$POSITION_Y_DL_MEASURE=169*$SCALE;
$POSITION_Y_UL_MEASURE=169*$SCALE;
$POSITION_Y_PING_MEASURE=60*$SCALE;
$POSITION_Y_JIT_MEASURE=60*$SCALE;
$POSITION_Y_ISP=205*$SCALE;
$POSITION_X_DL=120*$SCALE;
$POSITION_X_UL=280*$SCALE;
$POSITION_X_PING=125*$SCALE;
$POSITION_X_JIT=275*$SCALE;
$POSITION_X_ISP=4*$SCALE;
$SMALL_SEP=8*$SCALE;
$SEPARATOR_Y=211*$SCALE;
$SEPARATOR_COLOR=imagecolorallocate($im,192,192,192);
$POSITION_Y_WATERMARK=223*$SCALE;
$DL_TEXT="Download";
$UL_TEXT="Upload";
$PING_TEXT="Ping";
$JIT_TEXT="Jitter";
$MBPS_TEXT="Mbps";
$MS_TEXT="ms";
$id=$_GET["id"]; return number_format($d, 0, '.', '');
include_once('telemetry_settings.php'); }
require 'idObfuscation.php';
if($enable_id_obfuscation) $id=deobfuscateId($id);
$conn=null; $q=null;
$ispinfo=null; $dl=null; $ul=null; $ping=null; $jit=null;
if($db_type=="mysql"){
$conn = new mysqli($MySql_hostname, $MySql_username, $MySql_password, $MySql_databasename, $MySql_port);
$q = $conn->prepare("select ispinfo,dl,ul,ping,jitter from speedtest_users where id=?");
$q->bind_param("i",$id);
$q->execute();
$q->bind_result($ispinfo,$dl,$ul,$ping,$jit);
$q->fetch();
}else if($db_type=="sqlite"){
$conn = new PDO("sqlite:$Sqlite_db_file") or die();
$q=$conn->prepare("select ispinfo,dl,ul,ping,jitter from speedtest_users where id=?") or die();
$q->execute(array($id)) or die();
$row=$q->fetch() or die();
$ispinfo=$row["ispinfo"];
$dl=$row["dl"];
$ul=$row["ul"];
$ping=$row["ping"];
$jit=$row["jitter"];
$conn=null;
}else if($db_type=="postgresql"){
$conn_host = "host=$PostgreSql_hostname";
$conn_db = "dbname=$PostgreSql_databasename";
$conn_user = "user=$PostgreSql_username";
$conn_password = "password=$PostgreSql_password";
$conn = new PDO("pgsql:$conn_host;$conn_db;$conn_user;$conn_password") or die();
$q=$conn->prepare("select ispinfo,dl,ul,ping,jitter from speedtest_users where id=?") or die();
$q->execute(array($id)) or die();
$row=$q->fetch() or die();
$ispinfo=$row["ispinfo"];
$dl=$row["dl"];
$ul=$row["ul"];
$ping=$row["ping"];
$jit=$row["jitter"];
$conn=null;
}else die();
$dl=format($dl); /**
$ul=format($ul); * @param array $speedtest
$ping=format($ping); *
$jit=format($jit); * @return array
*/
function formatSpeedtestDataForImage($speedtest)
{
// format values for the image
$speedtest['dl'] = format($speedtest['dl']);
$speedtest['ul'] = format($speedtest['ul']);
$speedtest['ping'] = format($speedtest['ping']);
$speedtest['jit'] = format($speedtest['jitter']);
$ispinfo=json_decode($ispinfo,true)["processedString"]; $ispinfo = json_decode($speedtest['ispinfo'], true)['processedString'];
$dash=strpos($ispinfo,"-"); $dash = strpos($ispinfo, '-');
if(!($dash===FALSE)){ if ($dash !== false) {
$ispinfo=substr($ispinfo,$dash+2); $ispinfo = substr($ispinfo, $dash + 2);
$par=strrpos($ispinfo,"("); $par = strrpos($ispinfo, '(');
if(!($par===FALSE)) $ispinfo=substr($ispinfo,0,$par); if ($par !== false) {
}else $ispinfo=""; $ispinfo = substr($ispinfo, 0, $par);
}
} else {
$ispinfo = '';
}
$dlBbox=imageftbbox($FONT_LABEL_SIZE_BIG,0,$FONT_LABEL,$DL_TEXT); $speedtest['ispinfo'] = $ispinfo;
$ulBbox=imageftbbox($FONT_LABEL_SIZE_BIG,0,$FONT_LABEL,$UL_TEXT);
$pingBbox=imageftbbox($FONT_LABEL_SIZE,0,$FONT_LABEL,$PING_TEXT);
$jitBbox=imageftbbox($FONT_LABEL_SIZE,0,$FONT_LABEL,$JIT_TEXT);
$dlMeterBbox=imageftbbox($FONT_METER_SIZE_BIG,0,$FONT_METER,$dl);
$ulMeterBbox=imageftbbox($FONT_METER_SIZE_BIG,0,$FONT_METER,$ul);
$pingMeterBbox=imageftbbox($FONT_METER_SIZE,0,$FONT_METER,$ping);
$jitMeterBbox=imageftbbox($FONT_METER_SIZE,0,$FONT_METER,$jit);
$mbpsBbox=imageftbbox($FONT_MEASURE_SIZE_BIG,0,$FONT_MEASURE,$MBPS_TEXT);
$msBbox=imageftbbox($FONT_MEASURE_SIZE,0,$FONT_MEASURE,$MS_TEXT);
$watermarkBbox=imageftbbox($FONT_WATERMARK_SIZE,0,$FONT_WATERMARK,$WATERMARK_TEXT);
$POSITION_X_WATERMARK=$WIDTH-$watermarkBbox[4]-4*$SCALE;
imagefilledrectangle($im, 0, 0, $WIDTH, $HEIGHT, $BACKGROUND_COLOR); return $speedtest;
imagefttext($im,$FONT_LABEL_SIZE_BIG,0,$POSITION_X_DL-$dlBbox[4]/2,$POSITION_Y_DL_LABEL,$TEXT_COLOR_LABEL,$FONT_LABEL,$DL_TEXT); }
imagefttext($im,$FONT_LABEL_SIZE_BIG,0,$POSITION_X_UL-$ulBbox[4]/2,$POSITION_Y_UL_LABEL,$TEXT_COLOR_LABEL,$FONT_LABEL,$UL_TEXT);
imagefttext($im,$FONT_LABEL_SIZE,0,$POSITION_X_PING-$pingBbox[4]/2,$POSITION_Y_PING_LABEL,$TEXT_COLOR_LABEL,$FONT_LABEL,$PING_TEXT);
imagefttext($im,$FONT_LABEL_SIZE,0,$POSITION_X_JIT-$jitBbox[4]/2,$POSITION_Y_JIT_LABEL,$TEXT_COLOR_LABEL,$FONT_LABEL,$JIT_TEXT);
imagefttext($im,$FONT_METER_SIZE_BIG,0,$POSITION_X_DL-$dlMeterBbox[4]/2,$POSITION_Y_DL_METER,$TEXT_COLOR_DL_METER,$FONT_METER,$dl);
imagefttext($im,$FONT_METER_SIZE_BIG,0,$POSITION_X_UL-$ulMeterBbox[4]/2,$POSITION_Y_UL_METER,$TEXT_COLOR_UL_METER,$FONT_METER,$ul);
imagefttext($im,$FONT_METER_SIZE,0,$POSITION_X_PING-$pingMeterBbox[4]/2-$msBbox[4]/2-$SMALL_SEP/2,$POSITION_Y_PING_METER,$TEXT_COLOR_PING_METER,$FONT_METER,$ping);
imagefttext($im,$FONT_METER_SIZE,0,$POSITION_X_JIT-$jitMeterBbox[4]/2-$msBbox[4]/2-$SMALL_SEP/2,$POSITION_Y_JIT_METER,$TEXT_COLOR_JIT_METER,$FONT_METER,$jit);
imagefttext($im,$FONT_MEASURE_SIZE_BIG,0,$POSITION_X_DL-$mbpsBbox[4]/2,$POSITION_Y_DL_MEASURE,$TEXT_COLOR_MEASURE,$FONT_MEASURE,$MBPS_TEXT);
imagefttext($im,$FONT_MEASURE_SIZE_BIG,0,$POSITION_X_UL-$mbpsBbox[4]/2,$POSITION_Y_UL_MEASURE,$TEXT_COLOR_MEASURE,$FONT_MEASURE,$MBPS_TEXT);
imagefttext($im,$FONT_MEASURE_SIZE,0,$POSITION_X_PING+$pingMeterBbox[4]/2+$SMALL_SEP/2-$msBbox[4]/2,$POSITION_Y_PING_MEASURE,$TEXT_COLOR_MEASURE,$FONT_MEASURE,$MS_TEXT);
imagefttext($im,$FONT_MEASURE_SIZE,0,$POSITION_X_JIT+$jitMeterBbox[4]/2+$SMALL_SEP/2-$msBbox[4]/2,$POSITION_Y_JIT_MEASURE,$TEXT_COLOR_MEASURE,$FONT_MEASURE,$MS_TEXT);
imagefttext($im,$FONT_ISP_SIZE,0,$POSITION_X_ISP,$POSITION_Y_ISP,$TEXT_COLOR_ISP,$FONT_ISP,$ispinfo);
imagefttext($im,$FONT_WATERMARK_SIZE,0,$POSITION_X_WATERMARK,$POSITION_Y_WATERMARK,$TEXT_COLOR_WATERMARK,$FONT_WATERMARK,$WATERMARK_TEXT);
imagefilledrectangle($im, 0, $SEPARATOR_Y, $WIDTH, $SEPARATOR_Y, $SEPARATOR_COLOR);
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
?> /**
* @param array $speedtest
*
* @return void
*/
function drawImage($speedtest)
{
// format values for the image
$data = formatSpeedtestDataForImage($speedtest);
$dl = $data['dl'];
$ul = $data['ul'];
$ping = $data['ping'];
$jit = $data['jitter'];
$ispinfo = $data['ispinfo'];
// initialize the image
$SCALE = 1.25;
$SMALL_SEP = 8 * $SCALE;
$WIDTH = 400 * $SCALE;
$HEIGHT = 229 * $SCALE;
$im = imagecreatetruecolor($WIDTH, $HEIGHT);
$BACKGROUND_COLOR = imagecolorallocate($im, 255, 255, 255);
// configure fonts
$FONT_LABEL = tryFont('OpenSans-Semibold');
$FONT_LABEL_SIZE = 14 * $SCALE;
$FONT_LABEL_SIZE_BIG = 16 * $SCALE;
$FONT_METER = tryFont('OpenSans-Light');
$FONT_METER_SIZE = 20 * $SCALE;
$FONT_METER_SIZE_BIG = 22 * $SCALE;
$FONT_MEASURE = tryFont('OpenSans-Semibold');
$FONT_MEASURE_SIZE = 12 * $SCALE;
$FONT_MEASURE_SIZE_BIG = 12 * $SCALE;
$FONT_ISP = tryFont('OpenSans-Semibold');
$FONT_ISP_SIZE = 9 * $SCALE;
$FONT_WATERMARK = tryFont('OpenSans-Light');
$FONT_WATERMARK_SIZE = 8 * $SCALE;
// configure text colors
$TEXT_COLOR_LABEL = imagecolorallocate($im, 40, 40, 40);
$TEXT_COLOR_PING_METER = imagecolorallocate($im, 170, 96, 96);
$TEXT_COLOR_JIT_METER = imagecolorallocate($im, 170, 96, 96);
$TEXT_COLOR_DL_METER = imagecolorallocate($im, 96, 96, 170);
$TEXT_COLOR_UL_METER = imagecolorallocate($im, 96, 96, 96);
$TEXT_COLOR_MEASURE = imagecolorallocate($im, 40, 40, 40);
$TEXT_COLOR_ISP = imagecolorallocate($im, 40, 40, 40);
$SEPARATOR_COLOR = imagecolorallocate($im, 192, 192, 192);
$TEXT_COLOR_WATERMARK = imagecolorallocate($im, 160, 160, 160);
// configure positioning or the different parts on the image
$POSITION_X_PING = 125 * $SCALE;
$POSITION_Y_PING_LABEL = 24 * $SCALE;
$POSITION_Y_PING_METER = 60 * $SCALE;
$POSITION_Y_PING_MEASURE = 60 * $SCALE;
$POSITION_X_JIT = 275 * $SCALE;
$POSITION_Y_JIT_LABEL = 24 * $SCALE;
$POSITION_Y_JIT_METER = 60 * $SCALE;
$POSITION_Y_JIT_MEASURE = 60 * $SCALE;
$POSITION_X_DL = 120 * $SCALE;
$POSITION_Y_DL_LABEL = 105 * $SCALE;
$POSITION_Y_DL_METER = 143 * $SCALE;
$POSITION_Y_DL_MEASURE = 169 * $SCALE;
$POSITION_X_UL = 280 * $SCALE;
$POSITION_Y_UL_LABEL = 105 * $SCALE;
$POSITION_Y_UL_METER = 143 * $SCALE;
$POSITION_Y_UL_MEASURE = 169 * $SCALE;
$POSITION_X_ISP = 4 * $SCALE;
$POSITION_Y_ISP = 205 * $SCALE;
$SEPARATOR_Y = 211 * $SCALE;
$POSITION_Y_WATERMARK = 223 * $SCALE;
// configure labels
$MBPS_TEXT = 'Mbps';
$MS_TEXT = 'ms';
$PING_TEXT = 'Ping';
$JIT_TEXT = 'Jitter';
$DL_TEXT = 'Download';
$UL_TEXT = 'Upload';
$WATERMARK_TEXT = 'LibreSpeed';
// create text boxes for each part of the image
$mbpsBbox = imageftbbox($FONT_MEASURE_SIZE_BIG, 0, $FONT_MEASURE, $MBPS_TEXT);
$msBbox = imageftbbox($FONT_MEASURE_SIZE, 0, $FONT_MEASURE, $MS_TEXT);
$pingBbox = imageftbbox($FONT_LABEL_SIZE, 0, $FONT_LABEL, $PING_TEXT);
$pingMeterBbox = imageftbbox($FONT_METER_SIZE, 0, $FONT_METER, $ping);
$jitBbox = imageftbbox($FONT_LABEL_SIZE, 0, $FONT_LABEL, $JIT_TEXT);
$jitMeterBbox = imageftbbox($FONT_METER_SIZE, 0, $FONT_METER, $jit);
$dlBbox = imageftbbox($FONT_LABEL_SIZE_BIG, 0, $FONT_LABEL, $DL_TEXT);
$dlMeterBbox = imageftbbox($FONT_METER_SIZE_BIG, 0, $FONT_METER, $dl);
$ulBbox = imageftbbox($FONT_LABEL_SIZE_BIG, 0, $FONT_LABEL, $UL_TEXT);
$ulMeterBbox = imageftbbox($FONT_METER_SIZE_BIG, 0, $FONT_METER, $ul);
$watermarkBbox = imageftbbox($FONT_WATERMARK_SIZE, 0, $FONT_WATERMARK, $WATERMARK_TEXT);
$POSITION_X_WATERMARK = $WIDTH - $watermarkBbox[4] - 4 * $SCALE;
// put the parts together to draw the image
imagefilledrectangle($im, 0, 0, $WIDTH, $HEIGHT, $BACKGROUND_COLOR);
// ping
imagefttext($im, $FONT_LABEL_SIZE, 0, $POSITION_X_PING - $pingBbox[4] / 2, $POSITION_Y_PING_LABEL, $TEXT_COLOR_LABEL, $FONT_LABEL, $PING_TEXT);
imagefttext($im, $FONT_METER_SIZE, 0, $POSITION_X_PING - $pingMeterBbox[4] / 2 - $msBbox[4] / 2 - $SMALL_SEP / 2, $POSITION_Y_PING_METER, $TEXT_COLOR_PING_METER, $FONT_METER, $ping);
imagefttext($im, $FONT_MEASURE_SIZE, 0, $POSITION_X_PING + $pingMeterBbox[4] / 2 + $SMALL_SEP / 2 - $msBbox[4] / 2, $POSITION_Y_PING_MEASURE, $TEXT_COLOR_MEASURE, $FONT_MEASURE, $MS_TEXT);
// jitter
imagefttext($im, $FONT_LABEL_SIZE, 0, $POSITION_X_JIT - $jitBbox[4] / 2, $POSITION_Y_JIT_LABEL, $TEXT_COLOR_LABEL, $FONT_LABEL, $JIT_TEXT);
imagefttext($im, $FONT_METER_SIZE, 0, $POSITION_X_JIT - $jitMeterBbox[4] / 2 - $msBbox[4] / 2 - $SMALL_SEP / 2, $POSITION_Y_JIT_METER, $TEXT_COLOR_JIT_METER, $FONT_METER, $jit);
imagefttext($im, $FONT_MEASURE_SIZE, 0, $POSITION_X_JIT + $jitMeterBbox[4] / 2 + $SMALL_SEP / 2 - $msBbox[4] / 2, $POSITION_Y_JIT_MEASURE, $TEXT_COLOR_MEASURE, $FONT_MEASURE, $MS_TEXT);
// dl
imagefttext($im, $FONT_LABEL_SIZE_BIG, 0, $POSITION_X_DL - $dlBbox[4] / 2, $POSITION_Y_DL_LABEL, $TEXT_COLOR_LABEL, $FONT_LABEL, $DL_TEXT);
imagefttext($im, $FONT_METER_SIZE_BIG, 0, $POSITION_X_DL - $dlMeterBbox[4] / 2, $POSITION_Y_DL_METER, $TEXT_COLOR_DL_METER, $FONT_METER, $dl);
imagefttext($im, $FONT_MEASURE_SIZE_BIG, 0, $POSITION_X_DL - $mbpsBbox[4] / 2, $POSITION_Y_DL_MEASURE, $TEXT_COLOR_MEASURE, $FONT_MEASURE, $MBPS_TEXT);
// ul
imagefttext($im, $FONT_LABEL_SIZE_BIG, 0, $POSITION_X_UL - $ulBbox[4] / 2, $POSITION_Y_UL_LABEL, $TEXT_COLOR_LABEL, $FONT_LABEL, $UL_TEXT);
imagefttext($im, $FONT_METER_SIZE_BIG, 0, $POSITION_X_UL - $ulMeterBbox[4] / 2, $POSITION_Y_UL_METER, $TEXT_COLOR_UL_METER, $FONT_METER, $ul);
imagefttext($im, $FONT_MEASURE_SIZE_BIG, 0, $POSITION_X_UL - $mbpsBbox[4] / 2, $POSITION_Y_UL_MEASURE, $TEXT_COLOR_MEASURE, $FONT_MEASURE, $MBPS_TEXT);
// isp
imagefttext($im, $FONT_ISP_SIZE, 0, $POSITION_X_ISP, $POSITION_Y_ISP, $TEXT_COLOR_ISP, $FONT_ISP, $ispinfo);
// separator
imagefilledrectangle($im, 0, $SEPARATOR_Y, $WIDTH, $SEPARATOR_Y, $SEPARATOR_COLOR);
// watermark
imagefttext($im, $FONT_WATERMARK_SIZE, 0, $POSITION_X_WATERMARK, $POSITION_Y_WATERMARK, $TEXT_COLOR_WATERMARK, $FONT_WATERMARK, $WATERMARK_TEXT);
// send the image to the browser
header('Content-Type: image/png');
imagepng($im);
}
$speedtest = getSpeedtestUserById($_GET['id']);
if (!is_array($speedtest)) {
exit(1);
}
drawImage($speedtest);

View file

@ -1,6 +1,10 @@
<?php <?php
session_start(); session_start();
error_reporting(0); error_reporting(0);
require 'telemetry_settings.php';
require_once 'telemetry_db.php';
header('Content-Type: text/html; charset=utf-8'); header('Content-Type: text/html; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0, s-maxage=0'); header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0, s-maxage=0');
header('Cache-Control: post-check=0, pre-check=0', false); header('Cache-Control: post-check=0, pre-check=0', false);
@ -8,163 +12,158 @@ header('Pragma: no-cache');
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>LibreSpeed - Stats</title> <title>LibreSpeed - Stats</title>
<style type="text/css"> <style type="text/css">
html,body{ html,body{
margin:0; margin:0;
padding:0; padding:0;
border:none; border:none;
width:100%; min-height:100%; width:100%; min-height:100%;
} }
html{ html{
background-color: hsl(198,72%,35%); background-color: hsl(198,72%,35%);
font-family: "Segoe UI","Roboto",sans-serif; font-family: "Segoe UI","Roboto",sans-serif;
} }
body{ body{
background-color:#FFFFFF; background-color:#FFFFFF;
box-sizing:border-box; box-sizing:border-box;
width:100%; width:100%;
max-width:70em; max-width:70em;
margin:4em auto; margin:4em auto;
box-shadow:0 1em 6em #00000080; box-shadow:0 1em 6em #00000080;
padding:1em 1em 4em 1em; padding:1em 1em 4em 1em;
border-radius:0.4em; border-radius:0.4em;
} }
h1,h2,h3,h4,h5,h6{ h1,h2,h3,h4,h5,h6{
font-weight:300; font-weight:300;
margin-bottom: 0.1em; margin-bottom: 0.1em;
} }
h1{ h1{
text-align:center; text-align:center;
} }
table{ table{
margin:2em 0; margin:2em 0;
width:100%; width:100%;
} }
table, tr, th, td { table, tr, th, td {
border: 1px solid #AAAAAA; border: 1px solid #AAAAAA;
} }
th { th {
width: 6em; width: 6em;
} }
td { td {
word-break: break-all; word-break: break-all;
} }
</style> div {
</head> margin: 1em 0;
<body> }
<h1>LibreSpeed - Stats</h1> </style>
<?php </head>
include_once("telemetry_settings.php"); <body>
require "idObfuscation.php"; <h1>LibreSpeed - Stats</h1>
if($stats_password=="PASSWORD"){ <?php
?> if (!isset($stats_password) || $stats_password === 'PASSWORD') {
Please set $stats_password in telemetry_settings.php to enable access. ?>
<?php Please set $stats_password in telemetry_settings.php to enable access.
}else if($_SESSION["logged"]===true){ <?php
if($_GET["op"]=="logout"){ } elseif ($_SESSION['logged'] === true) {
$_SESSION["logged"]=false; if ($_GET['op'] === 'logout') {
?><script type="text/javascript">window.location=location.protocol+"//"+location.host+location.pathname;</script><?php $_SESSION['logged'] = false;
}else{ ?><script type="text/javascript">window.location=location.protocol+"//"+location.host+location.pathname;</script><?php
$conn=null; } else {
if($db_type=="mysql"){ ?>
$conn = new mysqli($MySql_hostname, $MySql_username, $MySql_password, $MySql_databasename, $MySql_port); <form action="stats.php" method="GET"><input type="hidden" name="op" value="logout" /><input type="submit" value="Logout" /></form>
}else if($db_type=="sqlite"){ <form action="stats.php" method="GET">
$conn = new PDO("sqlite:$Sqlite_db_file"); <h3>Search test results</h3>
} else if($db_type=="postgresql"){ <input type="hidden" name="op" value="id" />
$conn_host = "host=$PostgreSql_hostname"; <input type="text" name="id" id="id" placeholder="Test ID" value=""/>
$conn_db = "dbname=$PostgreSql_databasename"; <input type="submit" value="Find" />
$conn_user = "user=$PostgreSql_username"; <input type="submit" onclick="document.getElementById('id').value=''" value="Show last 100 tests" />
$conn_password = "password=$PostgreSql_password"; </form>
$conn = new PDO("pgsql:$conn_host;$conn_db;$conn_user;$conn_password"); <?php
}else die(); if ($_GET['op'] === 'id' && !empty($_GET['id'])) {
?> $speedtest = getSpeedtestUserById($_GET['id']);
<form action="stats.php" method="GET"><input type="hidden" name="op" value="logout" /><input type="submit" value="Logout" /></form> $speedtests = [];
<form action="stats.php" method="GET"> if (false === $speedtest) {
<h3>Search test results</h6> echo '<div>There was an error trying to fetch the speedtest result for ID "'.$_GET['id'].'".</div>';
<input type="hidden" name="op" value="id" /> } elseif (null === $speedtest) {
<input type="text" name="id" id="id" placeholder="Test ID" value=""/> echo '<div>Could not find a speedtest result for ID "'.$_GET['id'].'".</div>';
<input type="submit" value="Find" /> } else {
<input type="submit" onclick="document.getElementById('id').value=''" value="Show last 100 tests" /> $speedtests = [$speedtest];
</form> }
<?php } else {
$q=null; $speedtests = getLatestSpeedtestUsers();
if($_GET["op"]=="id"&&!empty($_GET["id"])){ if (false === $speedtests) {
$id=$_GET["id"]; echo '<div>There was an error trying to fetch latest speedtest results.</div>';
if($enable_id_obfuscation) $id=deobfuscateId($id); } elseif (empty($speedtests)) {
if($db_type=="mysql"){ echo '<div>Could not find any speedtest results in database.</div>';
$q=$conn->prepare("select id,timestamp,ip,ispinfo,ua,lang,dl,ul,ping,jitter,log,extra from speedtest_users where id=?"); }
$q->bind_param("i",$id); }
$q->execute(); foreach ($speedtests as $speedtest) {
$q->store_result(); ?>
$q->bind_result($id,$timestamp,$ip,$ispinfo,$ua,$lang,$dl,$ul,$ping,$jitter,$log,$extra); <table>
} else if($db_type=="sqlite"||$db_type=="postgresql"){ <tr>
$q=$conn->prepare("select id,timestamp,ip,ispinfo,ua,lang,dl,ul,ping,jitter,log,extra from speedtest_users where id=?"); <th>Test ID</th>
$q->execute(array($id)); <td><?= htmlspecialchars($speedtest['id_formatted'], ENT_HTML5, 'UTF-8') ?></td>
} else die(); </tr>
}else{ <tr>
if($db_type=="mysql"){ <th>Date and time</th>
$q=$conn->prepare("select id,timestamp,ip,ispinfo,ua,lang,dl,ul,ping,jitter,log,extra from speedtest_users order by timestamp desc limit 0,100"); <td><?= htmlspecialchars($speedtest['timestamp'], ENT_HTML5, 'UTF-8') ?></td>
$q->execute(); </tr>
$q->store_result(); <tr>
$q->bind_result($id,$timestamp,$ip,$ispinfo,$ua,$lang,$dl,$ul,$ping,$jitter,$log,$extra); <th>IP and ISP Info</th>
} else if($db_type=="sqlite"||$db_type=="postgresql"){ <td>
$q=$conn->prepare("select id,timestamp,ip,ispinfo,ua,lang,dl,ul,ping,jitter,log,extra from speedtest_users order by timestamp desc limit 100"); <?= htmlspecialchars($speedtest['ip'], ENT_HTML5, 'UTF-8') ?><br/>
$q->execute(); <?= htmlspecialchars($speedtest['ispinfo'], ENT_HTML5, 'UTF-8') ?>
}else die(); </td>
} </tr>
while(true){ <tr>
$id=null; $timestamp=null; $ip=null; $ispinfo=null; $ua=null; $lang=null; $dl=null; $ul=null; $ping=null; $jitter=null; $log=null; $extra=null; <th>User agent and locale</th>
if($db_type=="mysql"){ <td><?= htmlspecialchars($speedtest['ua'], ENT_HTML5, 'UTF-8') ?><br/>
if(!$q->fetch()) break; <?= htmlspecialchars($speedtest['lang'], ENT_HTML5, 'UTF-8') ?>
} else if($db_type=="sqlite"||$db_type=="postgresql"){ </td>
if(!($row=$q->fetch())) break; </tr>
$id=$row["id"]; <tr>
$timestamp=$row["timestamp"]; <th>Download speed</th>
$ip=$row["ip"]; <td><?= htmlspecialchars($speedtest['dl'], ENT_HTML5, 'UTF-8') ?></td>
$ispinfo=$row["ispinfo"]; </tr>
$ua=$row["ua"]; <tr>
$lang=$row["lang"]; <th>Upload speed</th>
$dl=$row["dl"]; <td><?= htmlspecialchars($speedtest['ul'], ENT_HTML5, 'UTF-8') ?></td>
$ul=$row["ul"]; </tr>
$ping=$row["ping"]; <tr>
$jitter=$row["jitter"]; <th>Ping</th>
$log=$row["log"]; <td><?= htmlspecialchars($speedtest['ping'], ENT_HTML5, 'UTF-8') ?></td>
$extra=$row["extra"]; </tr>
}else die(); <tr>
?> <th>Jitter</th>
<table> <td><?= htmlspecialchars($speedtest['jitter'], ENT_HTML5, 'UTF-8') ?></td>
<tr><th>Test ID</th><td><?=htmlspecialchars(($enable_id_obfuscation?(obfuscateId($id)." (deobfuscated: ".$id.")"):$id), ENT_HTML5, 'UTF-8') ?></td></tr> </tr>
<tr><th>Date and time</th><td><?=htmlspecialchars($timestamp, ENT_HTML5, 'UTF-8') ?></td></tr> <tr>
<tr><th>IP and ISP Info</th><td><?=$ip ?><br/><?=htmlspecialchars($ispinfo, ENT_HTML5, 'UTF-8') ?></td></tr> <th>Log</th>
<tr><th>User agent and locale</th><td><?=$ua ?><br/><?=htmlspecialchars($lang, ENT_HTML5, 'UTF-8') ?></td></tr> <td><?= htmlspecialchars($speedtest['log'], ENT_HTML5, 'UTF-8') ?></td>
<tr><th>Download speed</th><td><?=htmlspecialchars($dl, ENT_HTML5, 'UTF-8') ?></td></tr> </tr>
<tr><th>Upload speed</th><td><?=htmlspecialchars($ul, ENT_HTML5, 'UTF-8') ?></td></tr> <tr>
<tr><th>Ping</th><td><?=htmlspecialchars($ping, ENT_HTML5, 'UTF-8') ?></td></tr> <th>Extra info</th>
<tr><th>Jitter</th><td><?=htmlspecialchars($jitter, ENT_HTML5, 'UTF-8') ?></td></tr> <td><?= htmlspecialchars($speedtest['extra'], ENT_HTML5, 'UTF-8') ?></td>
<tr><th>Log</th><td><?=htmlspecialchars($log, ENT_HTML5, 'UTF-8') ?></td></tr> </tr>
<tr><th>Extra info</th><td><?=htmlspecialchars($extra, ENT_HTML5, 'UTF-8') ?></td></tr> </table>
</table> <?php
<?php }
} }
?> } elseif ($_GET['op'] === 'login' && $_POST['password'] === $stats_password) {
<?php $_SESSION['logged'] = true;
} ?><script type="text/javascript">window.location=location.protocol+"//"+location.host+location.pathname;</script><?php
}else{ } else {
if($_GET["op"]=="login"&&$_POST["password"]===$stats_password){ ?>
$_SESSION["logged"]=true; <form action="stats.php?op=login" method="POST">
?><script type="text/javascript">window.location=location.protocol+"//"+location.host+location.pathname;</script><?php <h3>Login</h3>
}else{ <input type="password" name="password" placeholder="Password" value=""/>
?> <input type="submit" value="Login" />
<form action="stats.php?op=login" method="POST"> </form>
<h3>Login</h3> <?php
<input type="password" name="password" placeholder="Password" value=""/> }
<input type="submit" value="Login" /> ?>
</form> </body>
<?php
}
}
?>
</body>
</html> </html>

View file

@ -1,81 +1,42 @@
<?php <?php
include_once('telemetry_settings.php');
require 'idObfuscation.php';
$ip=($_SERVER['REMOTE_ADDR']); require 'telemetry_settings.php';
$ispinfo=($_POST["ispinfo"]); require_once 'telemetry_db.php';
$extra=($_POST["extra"]);
$ua=($_SERVER['HTTP_USER_AGENT']);
$lang=""; if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) $lang=($_SERVER['HTTP_ACCEPT_LANGUAGE']);
$dl=($_POST["dl"]);
$ul=($_POST["ul"]);
$ping=($_POST["ping"]);
$jitter=($_POST["jitter"]);
$log=($_POST["log"]);
if($redact_ip_addresses){ $ip = $_SERVER['REMOTE_ADDR'];
$ip="0.0.0.0"; $ispinfo = $_POST['ispinfo'];
$ipv4_regex='/(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/'; $extra = $_POST['extra'];
$ipv6_regex='/(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/'; $ua = $_SERVER['HTTP_USER_AGENT'];
$hostname_regex='/"hostname":"([^\\\\"]|\\\\")*"/'; $lang = '';
$ispinfo=preg_replace($ipv4_regex,"0.0.0.0",$ispinfo); if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$ispinfo=preg_replace($ipv6_regex,"0.0.0.0",$ispinfo); $lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
$ispinfo=preg_replace($hostname_regex,"\"hostname\":\"REDACTED\"",$ispinfo); }
$log=preg_replace($ipv4_regex,"0.0.0.0",$log); $dl = $_POST['dl'];
$log=preg_replace($ipv6_regex,"0.0.0.0",$log); $ul = $_POST['ul'];
$log=preg_replace($hostname_regex,"\"hostname\":\"REDACTED\"",$log); $ping = $_POST['ping'];
$jitter = $_POST['jitter'];
$log = $_POST['log'];
if (isset($redact_ip_addresses) && true === $redact_ip_addresses) {
$ip = '0.0.0.0';
$ipv4_regex = '/(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/';
$ipv6_regex = '/(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/';
$hostname_regex = '/"hostname":"([^\\\\"]|\\\\")*"/';
$ispinfo = preg_replace($ipv4_regex, '0.0.0.0', $ispinfo);
$ispinfo = preg_replace($ipv6_regex, '0.0.0.0', $ispinfo);
$ispinfo = preg_replace($hostname_regex, '"hostname":"REDACTED"', $ispinfo);
$log = preg_replace($ipv4_regex, '0.0.0.0', $log);
$log = preg_replace($ipv6_regex, '0.0.0.0', $log);
$log = preg_replace($hostname_regex, '"hostname":"REDACTED"', $log);
} }
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0, s-maxage=0'); header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0, s-maxage=0');
header('Cache-Control: post-check=0, pre-check=0', false); header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache'); header('Pragma: no-cache');
if($db_type=="mysql"){ $id = insertSpeedtestUser($ip, $ispinfo, $extra, $ua, $lang, $dl, $ul, $ping, $jitter, $log);
$conn = new mysqli($MySql_hostname, $MySql_username, $MySql_password, $MySql_databasename, $MySql_port) or die("1"); if (false === $id) {
$stmt = $conn->prepare("INSERT INTO speedtest_users (ip,ispinfo,extra,ua,lang,dl,ul,ping,jitter,log) VALUES (?,?,?,?,?,?,?,?,?,?)") or die("2"); exit(1);
$stmt->bind_param("ssssssssss",$ip,$ispinfo,$extra,$ua,$lang,$dl,$ul,$ping,$jitter,$log) or die("3");
$stmt->execute() or die("4");
$stmt->close() or die("5");
$id=$conn->insert_id;
echo "id ".($enable_id_obfuscation?obfuscateId($id):$id);
$conn->close() or die("6");
}elseif($db_type=="sqlite"){
$conn = new PDO("sqlite:$Sqlite_db_file") or die("1");
$conn->exec("
CREATE TABLE IF NOT EXISTS `speedtest_users` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`ispinfo` text,
`extra` text,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ip` text NOT NULL,
`ua` text NOT NULL,
`lang` text NOT NULL,
`dl` text,
`ul` text,
`ping` text,
`jitter` text,
`log` longtext
);
");
$stmt = $conn->prepare("INSERT INTO speedtest_users (ip,ispinfo,extra,ua,lang,dl,ul,ping,jitter,log) VALUES (?,?,?,?,?,?,?,?,?,?)") or die("2");
$stmt->execute(array($ip,$ispinfo,$extra,$ua,$lang,$dl,$ul,$ping,$jitter,$log)) or die("3");
$id=$conn->lastInsertId();
echo "id ".($enable_id_obfuscation?obfuscateId($id):$id);
$conn = null;
}elseif($db_type=="postgresql"){
// Prepare connection parameters for db connection
$conn_host = "host=$PostgreSql_hostname";
$conn_db = "dbname=$PostgreSql_databasename";
$conn_user = "user=$PostgreSql_username";
$conn_password = "password=$PostgreSql_password";
// Create db connection
$conn = new PDO("pgsql:$conn_host;$conn_db;$conn_user;$conn_password") or die("1");
$stmt = $conn->prepare("INSERT INTO speedtest_users (ip,ispinfo,extra,ua,lang,dl,ul,ping,jitter,log) VALUES (?,?,?,?,?,?,?,?,?,?)") or die("2");
$stmt->execute(array($ip,$ispinfo,$extra,$ua,$lang,$dl,$ul,$ping,$jitter,$log)) or die("3");
$id=$conn->lastInsertId();
echo "id ".($enable_id_obfuscation?obfuscateId($id):$id);
$conn = null;
} }
else die("-1");
?> echo 'id '.$id;

220
results/telemetry_db.php Normal file
View file

@ -0,0 +1,220 @@
<?php
require_once 'idObfuscation.php';
define('TELEMETRY_SETTINGS_FILE', 'telemetry_settings.php');
/**
* @return PDO|false
*/
function getPdo()
{
if (
!file_exists(TELEMETRY_SETTINGS_FILE)
|| !is_readable(TELEMETRY_SETTINGS_FILE)
) {
return false;
}
require TELEMETRY_SETTINGS_FILE;
if (!isset($db_type)) {
return false;
}
$pdoOptions = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
];
try {
if ('mysql' === $db_type) {
if (!isset(
$MySql_hostname,
$MySql_port,
$MySql_databasename,
$MySql_username,
$MySql_password
)) {
return false;
}
$dsn = 'mysql:'
.'host='.$MySql_hostname
.';port='.$MySql_port
.';dbname='.$MySql_databasename;
return new PDO($dsn, $MySql_username, $MySql_password, $pdoOptions);
}
if ('sqlite' === $db_type) {
if (!isset($Sqlite_db_file)) {
return false;
}
$pdo = new PDO('sqlite:'.$Sqlite_db_file, null, null, $pdoOptions);
$pdo->exec('
CREATE TABLE IF NOT EXISTS `speedtest_users` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`ispinfo` text,
`extra` text,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ip` text NOT NULL,
`ua` text NOT NULL,
`lang` text NOT NULL,
`dl` text,
`ul` text,
`ping` text,
`jitter` text,
`log` longtext
);
');
return $pdo;
}
if ('postgresql' === $db_type) {
if (!isset(
$PostgreSql_hostname,
$PostgreSql_databasename,
$PostgreSql_username,
$PostgreSql_password
)) {
return false;
}
$dsn = 'pgsql:'
.'host='.$PostgreSql_hostname
.';dbname='.$PostgreSql_databasename;
return new PDO($dsn, $PostgreSql_username, $PostgreSql_password, $pdoOptions);
}
} catch (Exception $e) {
return false;
}
return false;
}
/**
* @return bool
*/
function isObfuscationEnabled()
{
require TELEMETRY_SETTINGS_FILE;
return
isset($enable_id_obfuscation)
&& true === $enable_id_obfuscation;
}
/**
* @return string|false returns the id of the inserted column or false on error
*/
function insertSpeedtestUser($ip, $ispinfo, $extra, $ua, $lang, $dl, $ul, $ping, $jitter, $log)
{
$pdo = getPdo();
if (!($pdo instanceof PDO)) {
return false;
}
try {
$stmt = $pdo->prepare(
'INSERT INTO speedtest_users
(ip,ispinfo,extra,ua,lang,dl,ul,ping,jitter,log)
VALUES (?,?,?,?,?,?,?,?,?,?)'
);
$stmt->execute([
$ip, $ispinfo, $extra, $ua, $lang, $dl, $ul, $ping, $jitter, $log
]);
$id = $pdo->lastInsertId();
} catch (Exception $e) {
return false;
}
if (isObfuscationEnabled()) {
return obfuscateId($id);
}
return $id;
}
/**
* @param int|string $id
*
* @return array|null|false returns the speedtest data as array, null
* if no data is found for the given id or
* false if there was an error
*
* @throws RuntimeException
*/
function getSpeedtestUserById($id)
{
$pdo = getPdo();
if (!($pdo instanceof PDO)) {
return false;
}
if (isObfuscationEnabled()) {
$id = deobfuscateId($id);
}
try {
$stmt = $pdo->prepare(
'SELECT
id, timestamp, ip, ispinfo, ua, lang, dl, ul, ping, jitter, log, extra
FROM speedtest_users
WHERE id = :id'
);
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (Exception $e) {
return false;
}
if (!is_array($row)) {
return null;
}
$row['id_formatted'] = $row['id'];
if (isObfuscationEnabled()) {
$row['id_formatted'] = obfuscateId($row['id']).' (deobfuscated: '.$row['id'].')';
}
return $row;
}
/**
* @return array|false
*/
function getLatestSpeedtestUsers()
{
$pdo = getPdo();
if (!($pdo instanceof PDO)) {
return false;
}
try {
$stmt = $pdo->query(
'SELECT
id, timestamp, ip, ispinfo, ua, lang, dl, ul, ping, jitter, log, extra
FROM speedtest_users
ORDER BY timestamp DESC
LIMIT 100'
);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $i => $row) {
$rows[$i]['id_formatted'] = $row['id'];
if (isObfuscationEnabled()) {
$rows[$i]['id_formatted'] = obfuscateId($row['id']).' (deobfuscated: '.$row['id'].')';
}
}
} catch (Exception $e) {
return false;
}
return $rows;
}

View file

@ -1,26 +1,26 @@
<?php <?php
$db_type="mysql"; //Type of db: "mysql", "sqlite" or "postgresql" // Type of db: "mysql", "sqlite" or "postgresql"
$stats_password="PASSWORD"; //password to login to stats.php. Change this!!! $db_type = 'mysql';
$enable_id_obfuscation=false; //if set to true, test IDs will be obfuscated to prevent users from guessing URLs of other tests // Password to login to stats.php. Change this!!!
$redact_ip_addresses=false; //if set to true, IP addresses will be redacted from IP and ISP info fields, as well as the log $stats_password = 'PASSWORD';
// If set to true, test IDs will be obfuscated to prevent users from guessing URLs of other tests
$enable_id_obfuscation = false;
// If set to true, IP addresses will be redacted from IP and ISP info fields, as well as the log
$redact_ip_addresses = false;
// Sqlite3 settings // Sqlite3 settings
$Sqlite_db_file = "../../speedtest_telemetry.sql"; $Sqlite_db_file = '../../speedtest_telemetry.sql';
// Mysql settings // Mysql settings
$MySql_username="USERNAME"; $MySql_username = 'USERNAME';
$MySql_password="PASSWORD"; $MySql_password = 'PASSWORD';
$MySql_hostname="DB_HOSTNAME"; $MySql_hostname = 'DB_HOSTNAME';
$MySql_databasename="DB_NAME"; $MySql_databasename = 'DB_NAME';
$MySql_port="3306"; $MySql_port = '3306';
// Postgresql settings // Postgresql settings
$PostgreSql_username="USERNAME"; $PostgreSql_username = 'USERNAME';
$PostgreSql_password="PASSWORD"; $PostgreSql_password = 'PASSWORD';
$PostgreSql_hostname="DB_HOSTNAME"; $PostgreSql_hostname = 'DB_HOSTNAME';
$PostgreSql_databasename="DB_NAME"; $PostgreSql_databasename = 'DB_NAME';
//IMPORTANT: DO NOT ADD ANYTHING BELOW THIS PHP CLOSING TAG, NOT EVEN EMPTY LINES!
?>