Merge branch 'master' into docker

This commit is contained in:
adolfintel 2019-01-31 12:32:50 +01:00
commit 94574b5f29
10 changed files with 87 additions and 38 deletions

3
.gitignore vendored
View file

@ -1,2 +1 @@
ugly.bat
wishlist.txt
telemetry/idObfuscation_salt.php

13
doc.md
View file

@ -1,7 +1,7 @@
# HTML5 Speedtest
> by Federico Dossena
> Version 4.7
> Version 4.7.1
> [https://github.com/adolfintel/speedtest/](https://github.com/adolfintel/speedtest/)
@ -148,7 +148,7 @@ The response from the worker is a JSON string containing these entries:
* __dlProgress__: the progress of the download test as a number between 0 and 1
* __ulProgress__: the progress of the upload test as a number between 0 and 1
* __pingProgress__: the progress of the ping+jitter test as a number between 0 and 1
* __testId__: when telemetry is active, this is the ID of the test as an integer. This string is 'noID' until the test is finished (testState 4). This ID is used for results sharing
* __testId__: when telemetry is active, this is the ID of the test in the database. This string is null until the test is finished (testState 4), or if telemetry encounters an error. This ID is used for results sharing
### Starting the test
To start the test with the default settings, which is usually the best choice, send the start command to the worker:
@ -381,6 +381,15 @@ This feature requires Telemetry to be enabled, and FreeType2 must be installed i
__Important:__ This feature relies on PHP functions `imagefttext` and `imageftbbox` that are well known for being problematic. The most common problem is that they can't find the font files and therefore nothing is drawn. This problem is metioned [here](http://php.net/manual/en/function.imagefttext.php) and was experienced by a lot of users.
#### Obfuscated Test IDs
By default, the telemetry generates a progressive ID for each test. Even if no sensitive information is leaked, you might not want users to be able to guess other test IDs. To avoid this, you can turn on ID obfuscation, which turns IDs into a reversible hash, much like YouTube video IDs.
To enable this feature, edit `telemetry_settings.php` and set `enable_id_obfuscation` to true.
From now on, all test IDs will be obfuscated using a unique salt. The IDs in the database are still progressive, but users will only know their obfuscated versions and won't be able to easily guess other IDs.
__Important:__ Make sure PHP is allowed to write to the `telemetry` folder. The salt will be stored in a file called `idObfuscation_salt.php`. This file is like a private key, don't lose it or you won't be able to deobfuscate IDs anymore!
### Seeing the results
A basic front-end for visualizing and searching tests by ID is available in `telemetry/stats.php`.

View file

@ -190,8 +190,8 @@ function startStop(){
if(status==4){
//if testId is present, show sharing panel, otherwise do nothing
try{
var testId=Number(data.testId);
if(!isNaN(testId)){
var testId=data.testId;
if(testId!=null){
var shareURL=window.location.href.substring(0,window.location.href.lastIndexOf("/"))+"/results/?id="+testId;
I("resultsImg").src=shareURL;
I("resultsURL").value=shareURL;

View file

@ -52,6 +52,8 @@ $WATERMARK_TEXT="HTML5 Speedtest";
$id=$_GET["id"];
include_once('../telemetry/telemetry_settings.php');
require '../telemetry/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"){

View file

@ -1,5 +1,5 @@
/*
HTML5 Speedtest v4.7
HTML5 Speedtest v4.7.1
by Federico Dossena
https://github.com/adolfintel/speedtest/
GNU LGPLv3 License
@ -15,7 +15,7 @@ var clientIp = ""; // client's IP address as reported by getIP.php
var dlProgress = 0; //progress of download test 0-1
var ulProgress = 0; //progress of upload test 0-1
var pingProgress = 0; //progress of ping+jitter test 0-1
var testId = "noID"; //test ID (sent back by telemetry if used, the string 'noID' otherwise)
var testId = null; //test ID (sent back by telemetry if used, null otherwise)
var log = ""; //telemetry log
function tlog(s) {
@ -173,7 +173,7 @@ this.addEventListener("message", function(e) {
if (settings.telemetry_level > 0)
sendTelemetry(function(id) {
testStatus = 4;
if (id != -1) testId = id;
if (id != null) testId = id;
});
else testStatus = 4;
return;
@ -460,21 +460,11 @@ function ulTest(done) {
}
if (ie11workaround) {
// IE11 workarond: xhr.upload does not work properly, therefore we send a bunch of small 256k requests and use the onload event as progress. This is not precise, especially on fast connections
xhr[i].onload = function() {
xhr[i].onload = xhr[i].onerror = function() {
tverb("ul stream progress event (ie11wa)");
totLoaded += reqsmall.size;
testStream(i, 0);
};
xhr[i].onerror = function() {
// error, abort
tverb("ul stream failed (ie11wa)");
if (settings.xhr_ignoreErrors === 0) failed = true; //abort
try {
xhr[i].abort();
} catch (e) {}
delete xhr[i];
if (settings.xhr_ignoreErrors === 1) testStream(i, 0); //restart stream
};
xhr[i].open("POST", settings.url_ul + url_sep(settings.url_ul) + "r=" + Math.random(), true); // random string to prevent caching
xhr[i].setRequestHeader("Content-Encoding", "identity"); // disable compression (some browsers may refuse it, but data is incompressible anyway)
xhr[i].send(reqsmall);
@ -662,15 +652,14 @@ function sendTelemetry(done) {
var parts = xhr.responseText.split(" ");
if (parts[0] == "id") {
try {
var id = Number(parts[1]);
if (!isNaN(id)) done(id);
else done(-1);
var id = parts[1];
done(id);
} catch (e) {
done(-1);
done(null);
}
} else done(-1);
} else done(null);
} catch (e) {
done(-1);
done(null);
}
};
xhr.onerror = function() {

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,39 @@
<?php
function getObfuscationSalt(){
$saltFile=dirname(__FILE__)."/idObfuscation_salt.php";
if(file_exists($saltFile)){
require $saltFile;
}else{
$bytes=openssl_random_pseudo_bytes(4);
$sf=fopen($saltFile,"w");
fwrite($sf,chr(60)."?php\n");
fwrite($sf,'$OBFUSCATION_SALT=0x'.bin2hex($bytes).";\n");
fwrite($sf,"?".chr(62));
fclose($sf);
require $saltFile;
}
return isset($OBFUSCATION_SALT)?$OBFUSCATION_SALT:0;
}
/*
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!
*/
function obfdeobf($id){
$salt=getObfuscationSalt()&0xFFFFFFFF;
$id=$id&0xFFFFFFFF;
for($i=0;$i<16;$i++){
$id=$id^$salt;
$id=(($id>>1)&0xFFFFFFFF)|(($id&0x00000001)<<31);
$salt=(($salt<<1)&0xFFFFFFFF)|(($salt&0xA0000000)>>31);
}
return $id;
}
function obfuscateId($id){
return base_convert(obfdeobf($id),10,36);
}
function deobfuscateId($id){
return obfdeobf(base_convert($id,36,10));
}
//IMPORTANT: DO NOT ADD ANYTHING BELOW THE PHP CLOSING TAG, NOT EVEN EMPTY LINES!
?>

View file

@ -2,6 +2,9 @@
session_start();
error_reporting(0);
header('Content-Type: text/html; charset=utf-8');
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
?>
<!DOCTYPE html>
<html>
@ -54,6 +57,7 @@ header('Content-Type: text/html; charset=utf-8');
<h1>HTML5 Speedtest - Stats</h1>
<?php
include_once("telemetry_settings.php");
require "idObfuscation.php";
if($stats_password=="PASSWORD"){
?>
Please set $stats_password in telemetry_settings.php to enable access.
@ -61,7 +65,7 @@ if($stats_password=="PASSWORD"){
}else if($_SESSION["logged"]===true){
if($_GET["op"]=="logout"){
$_SESSION["logged"]=false;
?><script type="text/javascript">window.location.search=""</script><?php
?><script type="text/javascript">window.location=location.protocol+"//"+location.host+location.pathname;</script><?php
}else{
$conn=null;
if($db_type=="mysql"){
@ -76,20 +80,22 @@ if($stats_password=="PASSWORD"){
$conn = new PDO("pgsql:$conn_host;$conn_db;$conn_user;$conn_password");
}else die();
?>
<form action="stats.php?op=logout" method="POST"><input type="submit" value="Logout" /></form>
<form action="stats.php?op=id" method="POST">
<form action="stats.php" method="GET"><input type="hidden" name="op" value="logout" /><input type="submit" value="Logout" /></form>
<form action="stats.php" method="GET">
<h3>Search test results</h6>
<input type="hidden" name="op" value="id" />
<input type="text" name="id" id="id" placeholder="Test ID" value=""/>
<input type="submit" value="Find" />
<input type="submit" onclick="document.getElementById('id').value=''" value="Show last 100 tests" />
</form>
<?php
$q=null;
if($_GET["op"]=="id"&&!empty($_POST["id"])){
$id=$_POST["id"];
if($_GET["op"]=="id"&&!empty($_GET["id"])){
$id=$_GET["id"];
if($enable_id_obfuscation) $id=deobfuscateId($id);
if($db_type=="mysql"){
$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",$_POST["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);
@ -129,7 +135,7 @@ if($stats_password=="PASSWORD"){
}else die();
?>
<table>
<tr><th>Test ID</th><td><?=htmlspecialchars($id, ENT_HTML5, 'UTF-8') ?></td></tr>
<tr><th>Test ID</th><td><?=htmlspecialchars(($enable_id_obfuscation?obfuscateId($id):$id), ENT_HTML5, 'UTF-8') ?></td></tr>
<tr><th>Date and time</th><td><?=htmlspecialchars($timestamp, ENT_HTML5, 'UTF-8') ?></td></tr>
<tr><th>IP and ISP Info</th><td><?=$ip ?><br/><?=htmlspecialchars($ispinfo, ENT_HTML5, 'UTF-8') ?></td></tr>
<tr><th>User agent and locale</th><td><?=$ua ?><br/><?=htmlspecialchars($lang, ENT_HTML5, 'UTF-8') ?></td></tr>
@ -148,7 +154,7 @@ if($stats_password=="PASSWORD"){
}else{
if($_GET["op"]=="login"&&$_POST["password"]===$stats_password){
$_SESSION["logged"]=true;
?><script type="text/javascript">window.location.search=""</script><?php
?><script type="text/javascript">window.location=location.protocol+"//"+location.host+location.pathname;</script><?php
}else{
?>
<form action="stats.php?op=login" method="POST">

View file

@ -1,5 +1,6 @@
<?php
include_once('telemetry_settings.php');
require 'idObfuscation.php';
$ip=($_SERVER['REMOTE_ADDR']);
$ispinfo=($_POST["ispinfo"]);
@ -18,7 +19,8 @@ if($db_type=="mysql"){
$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");
echo "id ".$conn->insert_id;
$id=$conn->insert_id;
echo "id ".($enable_id_obfuscation?obfuscateId($id):$id);
$conn->close() or die("6");
}elseif($db_type=="sqlite"){
@ -41,7 +43,8 @@ if($db_type=="mysql"){
");
$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");
echo "id ".$conn->lastInsertId();
$id=$conn->lastInsertId();
echo "id ".($enable_id_obfuscation?obfuscateId($id):$id);
$conn = null;
}elseif($db_type=="postgresql"){
// Prepare connection parameters for db connection
@ -53,7 +56,8 @@ if($db_type=="mysql"){
$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");
echo "id ".$conn->lastInsertId();
$id=$conn->lastInsertId();
echo "id ".($enable_id_obfuscation?obfuscateId($id):$id);
$conn = null;
}
else die("-1");

View file

@ -2,6 +2,7 @@
$db_type="mysql"; //Type of db: "mysql", "sqlite" or "postgresql"
$stats_password="PASSWORD"; //password to login to stats.php. Change this!!!
$enable_id_obfuscation=false; //if set to true, test IDs will be obfuscated to prevent users from guessing URLs of other tests
// Sqlite3 settings
$Sqlite_db_file = "../../telemetry.sql";