diff --git a/backend/getIP.php b/backend/getIP.php index 0eb2f3a..a2ed9a0 100644 --- a/backend/getIP.php +++ b/backend/getIP.php @@ -80,7 +80,10 @@ function getLocalOrPrivateIpInfo($ip) */ function getIpInfoTokenString() { - if (!file_exists(API_KEY_FILE)) { + if ( + !file_exists(API_KEY_FILE) + || !is_readable(API_KEY_FILE) + ) { return ''; } @@ -139,7 +142,10 @@ function getIsp($rawIspInfo) function getServerLocation() { $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; } if (is_string($serverLoc) && !empty($serverLoc)) { diff --git a/doc.md b/doc.md index 856edfb..74592b5 100644 --- a/doc.md +++ b/doc.md @@ -44,7 +44,7 @@ Server side, you'll need: * 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) * 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 - SQLite 3 and its PHP PDO module * 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 * PHP 5.4 or newer * 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 - SQLite 3 and its PHP PDO module * If you want to enable results sharing: diff --git a/results/idObfuscation.php b/results/idObfuscation.php index 3b4482a..f7dd8a5 100644 --- a/results/idObfuscation.php +++ b/results/idObfuscation.php @@ -1,43 +1,72 @@ >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; + +define('ID_OBFUSCATION_SALT_FILE', __DIR__.'/idObfuscation_salt.php'); + +/** + * @return string|int + */ +function getObfuscationSalt() +{ + if (!file_exists(ID_OBFUSCATION_SALT_FILE)) { + $bytes = openssl_random_pseudo_bytes(4); + + $saltData = " \ No newline at end of file +/** + * 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; +} diff --git a/results/index.php b/results/index.php index a9dac38..52c7316 100644 --- a/results/index.php +++ b/results/index.php @@ -1,164 +1,213 @@ 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(); + return number_format($d, 0, '.', ''); +} -$dl=format($dl); -$ul=format($ul); -$ping=format($ping); -$jit=format($jit); +/** + * @param array $speedtest + * + * @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"]; -$dash=strpos($ispinfo,"-"); -if(!($dash===FALSE)){ - $ispinfo=substr($ispinfo,$dash+2); - $par=strrpos($ispinfo,"("); - if(!($par===FALSE)) $ispinfo=substr($ispinfo,0,$par); -}else $ispinfo=""; + $ispinfo = json_decode($speedtest['ispinfo'], true)['processedString']; + $dash = strpos($ispinfo, '-'); + if ($dash !== false) { + $ispinfo = substr($ispinfo, $dash + 2); + $par = strrpos($ispinfo, '('); + if ($par !== false) { + $ispinfo = substr($ispinfo, 0, $par); + } + } else { + $ispinfo = ''; + } -$dlBbox=imageftbbox($FONT_LABEL_SIZE_BIG,0,$FONT_LABEL,$DL_TEXT); -$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; + $speedtest['ispinfo'] = $ispinfo; -imagefilledrectangle($im, 0, 0, $WIDTH, $HEIGHT, $BACKGROUND_COLOR); -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); + return $speedtest; +} -?> +/** + * @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); diff --git a/results/stats.php b/results/stats.php index 1e6ff1c..be35a6e 100644 --- a/results/stats.php +++ b/results/stats.php @@ -1,6 +1,10 @@ - -LibreSpeed - Stats - - - -

LibreSpeed - Stats

- - Please set $stats_password in telemetry_settings.php to enable access. - -
-
-

Search test results

- - - - -
- 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(); - $q->store_result(); - $q->bind_result($id,$timestamp,$ip,$ispinfo,$ua,$lang,$dl,$ul,$ping,$jitter,$log,$extra); - } else if($db_type=="sqlite"||$db_type=="postgresql"){ - $q=$conn->prepare("select id,timestamp,ip,ispinfo,ua,lang,dl,ul,ping,jitter,log,extra from speedtest_users where id=?"); - $q->execute(array($id)); - } else die(); - }else{ - if($db_type=="mysql"){ - $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"); - $q->execute(); - $q->store_result(); - $q->bind_result($id,$timestamp,$ip,$ispinfo,$ua,$lang,$dl,$ul,$ping,$jitter,$log,$extra); - } else if($db_type=="sqlite"||$db_type=="postgresql"){ - $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"); - $q->execute(); - }else die(); - } - while(true){ - $id=null; $timestamp=null; $ip=null; $ispinfo=null; $ua=null; $lang=null; $dl=null; $ul=null; $ping=null; $jitter=null; $log=null; $extra=null; - if($db_type=="mysql"){ - if(!$q->fetch()) break; - } else if($db_type=="sqlite"||$db_type=="postgresql"){ - if(!($row=$q->fetch())) break; - $id=$row["id"]; - $timestamp=$row["timestamp"]; - $ip=$row["ip"]; - $ispinfo=$row["ispinfo"]; - $ua=$row["ua"]; - $lang=$row["lang"]; - $dl=$row["dl"]; - $ul=$row["ul"]; - $ping=$row["ping"]; - $jitter=$row["jitter"]; - $log=$row["log"]; - $extra=$row["extra"]; - }else die(); - ?> - - - - - - - - - - - -
Test ID
Date and time
IP and ISP Info
User agent and locale
Download speed
Upload speed
Ping
Jitter
Log
Extra info
- - -
-

Login

- - -
- - + + LibreSpeed - Stats + + + +

LibreSpeed - Stats

+ + Please set $stats_password in telemetry_settings.php to enable access. + +
+
+

Search test results

+ + + + +
+ There was an error trying to fetch the speedtest result for ID "'.$_GET['id'].'".'; + } elseif (null === $speedtest) { + echo '
Could not find a speedtest result for ID "'.$_GET['id'].'".
'; + } else { + $speedtests = [$speedtest]; + } + } else { + $speedtests = getLatestSpeedtestUsers(); + if (false === $speedtests) { + echo '
There was an error trying to fetch latest speedtest results.
'; + } elseif (empty($speedtests)) { + echo '
Could not find any speedtest results in database.
'; + } + } + foreach ($speedtests as $speedtest) { + ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test ID
Date and time
IP and ISP Info +
+ +
User agent and locale
+ +
Download speed
Upload speed
Ping
Jitter
Log
Extra info
+ +
+

Login

+ + +
+ + diff --git a/results/telemetry.php b/results/telemetry.php index 5699777..5824c43 100644 --- a/results/telemetry.php +++ b/results/telemetry.php @@ -1,81 +1,42 @@ prepare("INSERT INTO speedtest_users (ip,ispinfo,extra,ua,lang,dl,ul,ping,jitter,log) VALUES (?,?,?,?,?,?,?,?,?,?)") or die("2"); - $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; +$id = insertSpeedtestUser($ip, $ispinfo, $extra, $ua, $lang, $dl, $ul, $ping, $jitter, $log); +if (false === $id) { + exit(1); } -else die("-1"); -?> + +echo 'id '.$id; diff --git a/results/telemetry_db.php b/results/telemetry_db.php new file mode 100644 index 0000000..6a1aee3 --- /dev/null +++ b/results/telemetry_db.php @@ -0,0 +1,220 @@ + 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; +} diff --git a/results/telemetry_settings.php b/results/telemetry_settings.php index ad80cf3..78bc343 100644 --- a/results/telemetry_settings.php +++ b/results/telemetry_settings.php @@ -1,26 +1,26 @@ \ No newline at end of file +$PostgreSql_username = 'USERNAME'; +$PostgreSql_password = 'PASSWORD'; +$PostgreSql_hostname = 'DB_HOSTNAME'; +$PostgreSql_databasename = 'DB_NAME';