diff --git a/checker.php b/checker.php
index 64cf572..483cc72 100644
--- a/checker.php
+++ b/checker.php
@@ -14,7 +14,7 @@ $pdo = (new DB($options))->pdo;
$results = [];
-/* Fetch hosts for check from database */
+echo "[DB] Fetching hosts to check from database" . PHP_EOL;
if ((($options['fullhour'] >= 0) && ($options['fullhour'] <= 23)) && date('H') == $options['fullhour']) { // check all hosts at full check hour
$STH = $pdo->query("SELECT `host`, `base32` FROM `hosts`");
} else {
@@ -22,7 +22,7 @@ if ((($options['fullhour'] >= 0) && ($options['fullhour'] <= 23)) && date('H') =
}
$hosts = $STH->fetchAll(PDO::FETCH_KEY_PAIR);
-/* Start temporary BOB tunnel for checking */
+echo "[BOB] Starting session for checking" . PHP_EOL;
$bob = new BOB($options);
$bob->setnick();
$bob->options();
@@ -31,7 +31,7 @@ $bob->intun();
$bob->start();
/* Sleep 10 seconds awaitng tunnels get built */
-echo "BOB session started, awaiting 10 seconds for tunnels" . PHP_EOL;
+echo "[BOB] Session started, awaiting 10 seconds for tunnels" . PHP_EOL;
sleep(10);
/* Start async checker tasks */
diff --git a/config.php.dist b/config.php.dist
index 57e3977..81d74cd 100644
--- a/config.php.dist
+++ b/config.php.dist
@@ -14,9 +14,10 @@ $options = [
/* I2P settings */
'bob_host' => '127.0.0.1',
'bob_port' => '2827',
- 'bob_options' => 'inbound.quantity=3 outbound.quantity=3 inbound.length=1 outbound.length=1 i2cp.leaseSetType=3',
+ 'bob_options' => 'inbound.quantity=3 outbound.quantity=3 inbound.length=1 outbound.length=1 i2cp.leaseSetType=3 i2cp.dontPublishLeaseSet=true',
'bob_nick' => 'hostchecker',
- 'check_tries' => 1,
+ 'check_tries' => 2, // lookup tries
+ 'retry_delay' => 3, // delay in seconds between tries
'http_proxy' => 'tcp://127.0.0.1:4444', // this is HTTP proxy, which must be specified as tcp protocol because we using stream context
/* Service settings */
diff --git a/fetch.php b/fetch.php
index 1d856f5..a3a5059 100644
--- a/fetch.php
+++ b/fetch.php
@@ -58,7 +58,11 @@ foreach ($lists as $list) {
$domain = "";
$record = $util->parseHostRecord($buffer);
- if (!$util->isValidDomain($record['host'], $error)) {
+ if (!isset($record['host'])) {
+ echo "Error while validating record " . $buffer . ": No host is found." . PHP_EOL;
+ continue;
+
+ } else if (!$util->isValidDomain($record['host'], $error)) {
echo "Error while validating " . $record['host'] . ": " . $error . PHP_EOL;
continue;
diff --git a/lib/bob.php b/lib/bob.php
index 7b2811d..f10dbc0 100644
--- a/lib/bob.php
+++ b/lib/bob.php
@@ -25,6 +25,9 @@ class BOB {
}
else
{
+ socket_set_option($this->sock, SOL_SOCKET, SO_RCVTIMEO, ['sec' => 10, 'usec' => 10 * 1000]);
+ socket_set_option($this->sock, SOL_SOCKET, SO_SNDTIMEO, ['sec' => 10, 'usec' => 10 * 1000]);
+
$result = socket_connect($this->sock, $this->options["bob_host"], $this->options["bob_port"]);
if ($result === false)
{
@@ -33,11 +36,13 @@ class BOB {
/* Reading BOB greeting */
$response = socket_read($this->sock, 1024);
-
if(!preg_match('/OK/', $response))
{
- throw new \ErrorException("BOB returned incorrect response on connect");
+ throw new \ErrorException("BOB returned incorrect response on connect or timed out");
}
+
+ /* Post-init timeouts setting */
+ socket_set_option($this->sock, SOL_SOCKET, SO_RCVTIMEO, ['sec' => 180, 'usec' => 180 * 1000]);
}
}
diff --git a/lib/checker.php b/lib/checker.php
index fb6ffea..d7285ac 100644
--- a/lib/checker.php
+++ b/lib/checker.php
@@ -30,7 +30,7 @@ class Checker implements Task
$bob->getnick();
$result = false;
- for ($i = 0, $tries = $this->options['check_tries']; $i < $tries; ++$i) {
+ for ($i = 0, $tries = $this->options['check_tries'], $sleep = $this->options['retry_delay']; $i < $tries; ++$i) {
$result = $bob->lookuplocal($this->base32 . ".b32.i2p");
if(!$result) {
$result = $bob->lookup($this->base32 . ".b32.i2p");
@@ -39,6 +39,10 @@ class Checker implements Task
if ($result) {
break;
}
+
+ // sleep before next try if we must do more that 1 tries to lookup destination
+ if($tries > 1 && $i < $tries) // do not sleep if that is last try
+ sleep($sleep);
}
$bob = null;
diff --git a/lib/utils.php b/lib/utils.php
index 0d53477..6b2f0de 100644
--- a/lib/utils.php
+++ b/lib/utils.php
@@ -212,7 +212,7 @@ class Utils {
{
$record = [];
- /* Return empty array if no data provided */
+ /* Return empty array if no data provided */
if(!strlen($data))
return $record;
@@ -223,6 +223,11 @@ class Utils {
/* Parse host record */
$host = preg_split("/\=/", $tmp[0], 2);
+
+ /* Return empty array if host or b64 is not set */
+ if(!isset($host[0]) || !isset($host[1]))
+ return $record;
+
$record["host"] = $host[0];
$record["b64"] = $host[1];
@@ -234,7 +239,7 @@ class Utils {
$cmdlist = preg_split("/#/", $tmp[1]);
foreach($cmdlist as $i)
{
- list($name,$value) = explode('=', $i, 2);
+ list($name, $value) = explode('=', $i, 2);
$cmds[$name] = $value;
}
diff --git a/public/index.php b/public/index.php
index 81ee6f3..650757d 100644
--- a/public/index.php
+++ b/public/index.php
@@ -23,6 +23,10 @@ $r->addRoute('^/all/?([0-9]+)?/?', function($url, $page = 1) {
require __DIR__ . '/../views/all.php';
});
+$r->addRoute('^/api/?(all|status)?/?([^\?/]*)?/?(?:\?|$)', function($url, $command, $query = "") {
+ require __DIR__ . '/../views/api.php';
+});
+
$r->addRoute('^/jump/?([^\?/]*)/?(?:\?|$)', function($url, $query = "") {
require __DIR__ . '/../views/jump.php';
});
diff --git a/templates/add.twig b/templates/add.twig
index cce7e26..8d73326 100644
--- a/templates/add.twig
+++ b/templates/add.twig
@@ -19,6 +19,8 @@
Subdomain successfuly added
{% elseif result.command == 'changedest' %}
Domain destination successfuly changed
+ {% elseif result.reregister %}
+ Domain successfuly re-registered
{% else %}
Domain successfuly added
{% endif %}
diff --git a/templates/alive.twig b/templates/alive.twig
index 9cce899..b434a7b 100644
--- a/templates/alive.twig
+++ b/templates/alive.twig
@@ -15,7 +15,7 @@
AH |
B32 |
Full Base32 |
- Last seen |
+ Last seen (UTC) |
diff --git a/templates/all.twig b/templates/all.twig
index 2790b35..defd076 100644
--- a/templates/all.twig
+++ b/templates/all.twig
@@ -16,7 +16,7 @@
AH |
B32 |
Full Base32 |
- Last seen |
+ Last seen (UTC) |
diff --git a/templates/hidden.twig b/templates/hidden.twig
index fee3b31..c88fd34 100644
--- a/templates/hidden.twig
+++ b/templates/hidden.twig
@@ -15,7 +15,7 @@
AH |
B32 |
Full Base32 |
- Last seen |
+ Last seen (UTC) |
diff --git a/templates/latest.twig b/templates/latest.twig
index b6c07e0..4a15abc 100644
--- a/templates/latest.twig
+++ b/templates/latest.twig
@@ -16,7 +16,7 @@
AH |
B32 |
Full Base32 |
- Added |
+ Added (UTC) |
diff --git a/templates/search.twig b/templates/search.twig
index 032034e..dd0eeb5 100644
--- a/templates/search.twig
+++ b/templates/search.twig
@@ -24,7 +24,7 @@
AH |
B32 |
Full Base32 |
- Last seen |
+ Last seen (UTC) |
diff --git a/views/add.php b/views/add.php
index 3c915ef..c2802a6 100644
--- a/views/add.php
+++ b/views/add.php
@@ -32,11 +32,16 @@ if (isset($_POST["record"]) && !empty($_POST["record"])) {
$parsed = $util->parseHostRecord($record);
- if (!$util->isValidDomain($parsed['host'], $error)) {
+ if (!isset($parsed['host'])) {
+ $result["error"] = "Error while validating: Incorrect Auth string";
+
+ } else if (!$util->isValidDomain($parsed['host'], $error)) {
$result["error"] = "Error while validating: " . $error;
+
} else {
if ($util->isPunycodeDomain($parsed['host'])) {
$domain = idn_to_utf8($parsed['host'], 0, INTL_IDNA_VARIANT_UTS46);
+
} else {
$domain = $parsed['host'];
}
@@ -48,10 +53,10 @@ if (isset($_POST["record"]) && !empty($_POST["record"])) {
$result["error"] = "Error while validating: " . $error[0];
} else {
- /* Check if such domain name already registered */
- $STH = $pdo->query("SELECT COUNT(*) FROM `hosts` WHERE `host` = '" . $domain . "' LIMIT 1");
-
if (isset($parsed["commands"]["action"])) {
+ /* Check if such domain name already registered */
+ $STH = $pdo->query("SELECT COUNT(*) FROM `hosts` WHERE `host` = '" . $domain . "' LIMIT 1");
+
switch ($parsed["commands"]["action"]) {
case 'addsubdomain':
if ($STH->fetchColumn() == 1) {
@@ -125,7 +130,7 @@ if (isset($_POST["record"]) && !empty($_POST["record"])) {
/* Getting domain level (2LD, 3LD and etc.) and validating that domain at higher level is registered (2LD if registering 3LD). */
} else if (sizeof(explode(".", $domain)) > 2) {
- $result["error"] = "Error while validating: you can't register subdomain (sub.example.i2p) as domain alias using addname action.";
+ $result["error"] = "Error while validating: you can't register subdomain (sub.example.i2p) as domain alias using addname action.";
} else if (!isset($parsed["commands"]["oldname"])) {
$result["error"] = "Error while validating: required fields not found. Re-check your registration string.";
@@ -161,9 +166,16 @@ if (isset($_POST["record"]) && !empty($_POST["record"])) {
}
} else {
- if($STH->fetchColumn() == 1) {
+ /* Check if such domain name already registered */
+ $STH = $pdo->query("SELECT `host`, `base32`, `base64`, `initial`, `disabled` FROM `hosts` WHERE `host` = '" . $domain . "' LIMIT 1");
+ $row = $STH->fetch(PDO::FETCH_ASSOC);
+
+ if(count($row) && !$row['disabled']) {
$result["error"] = "Error while validating: That domain is already registered.";
+ } else if(count($row) && $row['disabled'] && $row['initial']) {
+ $result["error"] = "Error while validating: That domain is reserved and can't be re-registered automatically. Please contact service support team.";
+
} else {
if (isset($parsed["commands"]["oldname"]) || isset($parsed["commands"]["olddest"]) || isset($parsed["commands"]["oldsig"])) {
$result["error"] = "Error while validating: unexpected fields found.";
@@ -172,6 +184,24 @@ if (isset($_POST["record"]) && !empty($_POST["record"])) {
$result["error"] = "Error while validating: you can't register subdomain without specific action field.";
} else {
+ $result["reregister"] = false;
+ if(count($row) && $row['disabled']) { /* processing disabled domain */
+ $log = "[" . date("d-M-Y H:i:s e") . "] Re-registering attempt for " . $row['host'] . "! Next records will be deleted:" . PHP_EOL;
+
+ /* print all records, which will be deleted*/
+ $STH = $pdo->query("SELECT `host`, `base32`, `base64` FROM `hosts` WHERE `host` = '" . $domain . "' OR `host` LIKE '%." . $domain . "'");
+ $hosts = $STH->fetchAll(PDO::FETCH_ASSOC);
+ foreach ($hosts as $host) {
+ $log .= "Host: " . $host['host'] . PHP_EOL . "Base32: " . $host['base32'] . PHP_EOL . "Base64: " . $host['base64'] . PHP_EOL;
+ }
+
+ file_put_contents(__DIR__ . '/../logs/reg.log', $log, FILE_APPEND);
+
+ /* remove domain and subdomains if any found */
+ $pdo->exec("DELETE FROM `hosts` WHERE `host` = '" . $domain . "' OR `host` LIKE '%." . $domain . "'");
+ $result["reregister"] = true;
+ }
+
$base32 = $util->b32from64($parsed["b64"]);
/* Adding to database 2LD domain */
diff --git a/views/api.php b/views/api.php
new file mode 100644
index 0000000..da637c6
--- /dev/null
+++ b/views/api.php
@@ -0,0 +1,30 @@
+pdo;
+
+header('Content-Type: application/json');
+
+if (isset($_GET["all"]))
+ $all = true;
+
+if(!$command || !in_array($command, ['all', 'status']))
+ exit(json_encode(["status" => "error", "message" => "Incorrect request"]));
+
+if($command == "all") {
+ $STH = $pdo->query ("SELECT `base32`, UNIX_TIMESTAMP(`last_seen`) as `last_seen` FROM `hosts` " .
+ "WHERE `approved` = 1 AND `disabled` = 0" .
+ ($all ? " " : " AND `blacklisted` = 0 "));
+ $STH->setFetchMode(PDO::FETCH_ASSOC);
+ $rows = $STH->fetchAll();
+
+ $data = [];
+ foreach($rows as $row) {
+ $data[$row["base32"] . ".b32.i2p"] = $row["last_seen"];
+ }
+
+ exit(json_encode($data, JSON_PRETTY_PRINT));
+}