mirror of https://github.com/PurpleI2P/regi2p.git
commit
80bb08fbd2
43 changed files with 3710 additions and 0 deletions
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
Copyright 2021 © The PurpleI2P Project |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
@ -0,0 +1,110 @@
@@ -0,0 +1,110 @@
|
||||
Registry - reg.i2p |
||||
=== |
||||
|
||||
This is reg.i2p domain registry code |
||||
|
||||
|
||||
Requirements |
||||
--- |
||||
|
||||
* i2pd with enabled BOB protocol |
||||
* `verifyhost` binary built inside i2pd-tools project folder |
||||
* PHP and php-fpm 7.2+ |
||||
* Composer |
||||
* Corntab (for jobs) |
||||
|
||||
|
||||
Installation |
||||
--- |
||||
|
||||
1. Clone repository in your webserver working directory. Note: that must not be `/var/www/html` or something like this, your webserver must point to `public` directory of forked project. |
||||
2. Fetch requirements by runnning `composer update`. |
||||
3. Point your webserver to serving webpages from `public` directory. |
||||
4. Create cron jobs for quering and updating hosts lists. |
||||
|
||||
|
||||
nginx configuration |
||||
--- |
||||
|
||||
```nginx |
||||
server { |
||||
listen 127.0.0.1:8000; |
||||
|
||||
access_log /dev/null; |
||||
error_log /dev/null; |
||||
|
||||
root /home/www/reg.i2p/public; |
||||
index index.php index.html; |
||||
port_in_redirect off; |
||||
|
||||
location ~* ^/hosts\.txt$ { |
||||
if ($http_if_none_match) { |
||||
rewrite ^/hosts\.txt$ /export/hosts.txt break; |
||||
} |
||||
|
||||
rewrite ^/hosts\.txt$ /export/hosts-basic.txt break; |
||||
} |
||||
|
||||
location / { |
||||
try_files $uri $uri/ /index.php$request_uri; |
||||
} |
||||
|
||||
location ~ ^/index\.php(/|$) { |
||||
include fastcgi_params; |
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; |
||||
fastcgi_param SERVER_PORT 80; |
||||
fastcgi_pass unix:/home/www/reg.i2p/tmp/php-fpm.sock; |
||||
} |
||||
} |
||||
``` |
||||
|
||||
php-fpm configuration |
||||
--- |
||||
|
||||
```conf |
||||
[reg.i2p] |
||||
|
||||
prefix = /home/www/$pool |
||||
user = www-data |
||||
group = www-data |
||||
listen = tmp/php-fpm.sock |
||||
|
||||
listen.owner = www-data |
||||
listen.group = www-data |
||||
listen.mode = 0660 |
||||
|
||||
pm = dynamic |
||||
pm.max_children = 5 |
||||
pm.start_servers = 1 |
||||
pm.min_spare_servers = 1 |
||||
pm.max_spare_servers = 2 |
||||
pm.max_requests = 500 |
||||
|
||||
chdir = public |
||||
|
||||
php_admin_flag[log_errors] = On |
||||
php_admin_flag[display_errors] = Off |
||||
php_admin_value[error_reporting] = E_ALL |
||||
php_admin_value[error_log] = /home/www/$pool/logs/php-error.log |
||||
|
||||
php_admin_value[upload_tmp_dir] = /home/www/$pool/tmp |
||||
php_admin_value[date.timezone] = Etc/UTC |
||||
|
||||
php_admin_value[session.save_path] = /home/www/$pool/sessions |
||||
php_admin_value[session.save_handler] = files |
||||
php_admin_value[session.gc_probability] = 2 |
||||
php_admin_value[session.gc_maxlifetime] = 1440 |
||||
|
||||
php_admin_value[memory_limit] = 32M |
||||
php_admin_value[upload_max_filesize] = "2M" |
||||
php_admin_value[max_execution_time] = 60 |
||||
``` |
||||
|
||||
Cron jobs |
||||
--- |
||||
|
||||
```crontab |
||||
5 * * * * php7.2 /home/www/reg.i2p/checker.php > /home/www/reg.i2p/logs/checker.log 2>&1 |
||||
45 */6 * * * php7.2 /home/www/reg.i2p/export.php > /home/www/reg.i2p/logs/export.log 2>&1 |
||||
50 23 * * * php7.2 /home/www/reg.i2p/fetch.php > /home/www/reg.i2p/logs/fetch.log 2>&1 |
||||
``` |
@ -0,0 +1,107 @@
@@ -0,0 +1,107 @@
|
||||
#include <iostream> |
||||
#include <fstream> |
||||
#include <sstream> |
||||
#include "Identity.h" |
||||
#include "Base.h" |
||||
|
||||
int main (int argc, char * argv[]) |
||||
{ |
||||
if (argc < 2) |
||||
{ |
||||
std::cout << "Usage: verifyhost '<host record>'" << std::endl; |
||||
return -1; |
||||
} |
||||
|
||||
i2p::crypto::InitCrypto (false, true, true, false); |
||||
|
||||
i2p::data::IdentityEx Identity, OldIdentity; |
||||
|
||||
std::string str (argv[1]); |
||||
std::size_t pos; |
||||
|
||||
// get record without command block after "#!"
|
||||
pos = str.find ("#!"); |
||||
std::string hostStr = str.substr (0, pos); |
||||
|
||||
// get host base64
|
||||
pos = hostStr.find ("="); |
||||
std::string hostBase64 = hostStr.substr (pos + 1); |
||||
|
||||
// load identity
|
||||
if (Identity.FromBase64 (hostBase64)) |
||||
{ |
||||
// get record without sig key and signature
|
||||
pos = str.find ("#sig="); |
||||
if (pos == std::string::npos) |
||||
{ |
||||
pos = str.find ("!sig="); |
||||
if (pos == std::string::npos) |
||||
{ |
||||
std::cout << "Destination signature not found." << std::endl; |
||||
return 1; |
||||
} |
||||
} |
||||
|
||||
int offset = (str[pos - 1] == '#' /* only sig in record */) ? 1 : 0; |
||||
|
||||
std::string hostNoSig = str.substr (0, pos - offset); |
||||
std::string sig = str.substr (pos + 5); // after "#sig=" till end
|
||||
|
||||
auto signatureLen = Identity.GetSignatureLen (); |
||||
uint8_t * signature = new uint8_t[signatureLen]; |
||||
|
||||
// validate signature
|
||||
i2p::data::Base64ToByteStream(sig.c_str (), sig.length(), signature, signatureLen); |
||||
if (!Identity.Verify ((uint8_t *)hostNoSig.c_str (), hostNoSig.length (), signature)) |
||||
{ |
||||
std::cout << "Invalid destination signature." << std::endl; |
||||
return 1; |
||||
} |
||||
|
||||
if (str.find ("olddest=") != std::string::npos) // if olddest present
|
||||
{ |
||||
// get olddest
|
||||
pos = str.find ("#olddest="); |
||||
std::string oldDestCut = str.substr (pos + 9); |
||||
pos = oldDestCut.find ("#"); |
||||
std::string oldDestBase64 = oldDestCut.substr (0, pos); |
||||
|
||||
// load identity
|
||||
if(!OldIdentity.FromBase64 (oldDestBase64)) |
||||
{ |
||||
std::cout << "Invalid old destination base64." << std::endl; |
||||
return 1; |
||||
} |
||||
|
||||
signatureLen = OldIdentity.GetSignatureLen (); |
||||
signature = new uint8_t[signatureLen]; |
||||
|
||||
// get record till oldsig key and oldsig
|
||||
pos = str.find ("#oldsig="); |
||||
std::string hostNoOldSig = str.substr (0, pos); |
||||
|
||||
std::string oldSigCut = str.substr (pos + 8); |
||||
pos = oldSigCut.find ("#"); |
||||
std::string oldSig = oldSigCut.substr (0, pos); |
||||
|
||||
// validate signature
|
||||
i2p::data::Base64ToByteStream(oldSig.c_str (), oldSig.length(), signature, signatureLen); |
||||
bool oldSignValid = OldIdentity.Verify ((uint8_t *)hostNoOldSig.c_str (), hostNoOldSig.length (), signature); |
||||
|
||||
if(!oldSignValid) |
||||
{ |
||||
std::cout << "Invalid old destination signature." << std::endl; |
||||
return 1; |
||||
} |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
std::cout << "Invalid destination base64." << std::endl; |
||||
return 1; |
||||
} |
||||
|
||||
i2p::crypto::TerminateCrypto (); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
|
||||
<?php |
||||
require __DIR__ . '/vendor/autoload.php'; |
||||
require __DIR__ . '/config.php'; |
||||
|
||||
use App\BOB; |
||||
use App\DB; |
||||
use Amp\Loop; |
||||
use Amp\Parallel\Worker\DefaultPool; |
||||
|
||||
/* Disable execution limit */ |
||||
set_time_limit(0); |
||||
|
||||
$pdo = (new DB($options))->pdo; |
||||
|
||||
$results = []; |
||||
|
||||
$STH = $pdo->query("SELECT `host`, `base32` FROM `hosts`"); |
||||
$hosts = $STH->fetchAll(PDO::FETCH_KEY_PAIR); |
||||
|
||||
/* Start temporary BOB tunnel for checking */ |
||||
$bob = new BOB($options); |
||||
$bob->setnick(); |
||||
$bob->options(); |
||||
$bob->newkeys(); |
||||
$bob->intun(); |
||||
$bob->start(); |
||||
|
||||
/* Sleep 10 seconds awaitng tunnels get built */ |
||||
echo "BOB session started, awaiting 10 seconds for tunnels" . PHP_EOL; |
||||
sleep(10); |
||||
|
||||
/* Start async checker tasks */ |
||||
Loop::run(function () use (&$results, $hosts, $options) { |
||||
$pool = new DefaultPool(64); |
||||
|
||||
$coroutines = []; |
||||
|
||||
foreach ($hosts as $host => $base32) { |
||||
$coroutines[$host] = Amp\call(function () use ($pool, $base32, $options) { |
||||
$result = yield $pool->enqueue(new App\Checker($base32, $options)); |
||||
return $result; |
||||
}); |
||||
} |
||||
|
||||
$results = yield Amp\Promise\all($coroutines); |
||||
|
||||
return yield $pool->shutdown(); |
||||
}); |
||||
|
||||
/* Stop BOB tunnel and terminate */ |
||||
$bob->stop(); |
||||
$bob->clear(); |
||||
$bob = null; |
||||
|
||||
/* Update last seen time in DB */ |
||||
$i = 0; |
||||
$pdo->beginTransaction(); |
||||
|
||||
foreach ($results as $host => $result) |
||||
{ |
||||
if($result) |
||||
{ |
||||
$pdo->exec("UPDATE `hosts` SET `last_seen` = current_timestamp() WHERE `host` = '" . $host . "'"); |
||||
$i++; |
||||
} |
||||
} |
||||
|
||||
$pdo->commit(); |
||||
|
||||
echo "Result: Total hosts: " . count($results) . ", Alive: " . $i . PHP_EOL; |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
{ |
||||
"name": "purplei2p/regi2p", |
||||
"description": "I2P domain registrar", |
||||
"type": "project", |
||||
"require": { |
||||
"php": "^7.2.5", |
||||
"twig/twig": "^3.0", |
||||
"amphp/parallel": "^1.4" |
||||
}, |
||||
"license": "MIT", |
||||
"authors": [ |
||||
{ |
||||
"name": "R4SAS", |
||||
"email": "r4sas@i2pmail.org" |
||||
} |
||||
], |
||||
"autoload": { |
||||
"files": [ |
||||
"lib/bob.php", |
||||
"lib/checker.php", |
||||
"lib/db.php", |
||||
"lib/router.php", |
||||
"lib/utils.php" |
||||
] |
||||
}, |
||||
"scripts": { |
||||
"checker": [ |
||||
"Composer\\Config::disableProcessTimeout", |
||||
"php checker.php" |
||||
], |
||||
"clearCache": "rm -rf cache/*", |
||||
"export": "php export.php", |
||||
"fetch": [ |
||||
"Composer\\Config::disableProcessTimeout", |
||||
"php fetch.php" |
||||
] |
||||
} |
||||
} |
@ -0,0 +1,718 @@
@@ -0,0 +1,718 @@
|
||||
{ |
||||
"_readme": [ |
||||
"This file locks the dependencies of your project to a known state", |
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", |
||||
"This file is @generated automatically" |
||||
], |
||||
"content-hash": "4053556a32d0a974795f8ab1ee625ae1", |
||||
"packages": [ |
||||
{ |
||||
"name": "amphp/amp", |
||||
"version": "v2.5.2", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/amphp/amp.git", |
||||
"reference": "efca2b32a7580087adb8aabbff6be1dc1bb924a9" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/amphp/amp/zipball/efca2b32a7580087adb8aabbff6be1dc1bb924a9", |
||||
"reference": "efca2b32a7580087adb8aabbff6be1dc1bb924a9", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": ">=7" |
||||
}, |
||||
"require-dev": { |
||||
"amphp/php-cs-fixer-config": "dev-master", |
||||
"amphp/phpunit-util": "^1", |
||||
"ext-json": "*", |
||||
"jetbrains/phpstorm-stubs": "^2019.3", |
||||
"phpunit/phpunit": "^6.0.9 | ^7", |
||||
"psalm/phar": "^3.11@dev", |
||||
"react/promise": "^2" |
||||
}, |
||||
"type": "library", |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-master": "2.x-dev" |
||||
} |
||||
}, |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Amp\\": "lib" |
||||
}, |
||||
"files": [ |
||||
"lib/functions.php", |
||||
"lib/Internal/functions.php" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Daniel Lowrey", |
||||
"email": "rdlowrey@php.net" |
||||
}, |
||||
{ |
||||
"name": "Aaron Piotrowski", |
||||
"email": "aaron@trowski.com" |
||||
}, |
||||
{ |
||||
"name": "Bob Weinand", |
||||
"email": "bobwei9@hotmail.com" |
||||
}, |
||||
{ |
||||
"name": "Niklas Keller", |
||||
"email": "me@kelunik.com" |
||||
} |
||||
], |
||||
"description": "A non-blocking concurrency framework for PHP applications.", |
||||
"homepage": "http://amphp.org/amp", |
||||
"keywords": [ |
||||
"async", |
||||
"asynchronous", |
||||
"awaitable", |
||||
"concurrency", |
||||
"event", |
||||
"event-loop", |
||||
"future", |
||||
"non-blocking", |
||||
"promise" |
||||
], |
||||
"support": { |
||||
"irc": "irc://irc.freenode.org/amphp", |
||||
"issues": "https://github.com/amphp/amp/issues", |
||||
"source": "https://github.com/amphp/amp/tree/v2.5.2" |
||||
}, |
||||
"funding": [ |
||||
{ |
||||
"url": "https://github.com/amphp", |
||||
"type": "github" |
||||
} |
||||
], |
||||
"time": "2021-01-10T17:06:37+00:00" |
||||
}, |
||||
{ |
||||
"name": "amphp/byte-stream", |
||||
"version": "v1.8.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/amphp/byte-stream.git", |
||||
"reference": "f0c20cf598a958ba2aa8c6e5a71c697d652c7088" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/amphp/byte-stream/zipball/f0c20cf598a958ba2aa8c6e5a71c697d652c7088", |
||||
"reference": "f0c20cf598a958ba2aa8c6e5a71c697d652c7088", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"amphp/amp": "^2", |
||||
"php": ">=7.1" |
||||
}, |
||||
"require-dev": { |
||||
"amphp/php-cs-fixer-config": "dev-master", |
||||
"amphp/phpunit-util": "^1.4", |
||||
"friendsofphp/php-cs-fixer": "^2.3", |
||||
"jetbrains/phpstorm-stubs": "^2019.3", |
||||
"phpunit/phpunit": "^6 || ^7 || ^8", |
||||
"psalm/phar": "^3.11.4" |
||||
}, |
||||
"type": "library", |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-master": "1.x-dev" |
||||
} |
||||
}, |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Amp\\ByteStream\\": "lib" |
||||
}, |
||||
"files": [ |
||||
"lib/functions.php" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Aaron Piotrowski", |
||||
"email": "aaron@trowski.com" |
||||
}, |
||||
{ |
||||
"name": "Niklas Keller", |
||||
"email": "me@kelunik.com" |
||||
} |
||||
], |
||||
"description": "A stream abstraction to make working with non-blocking I/O simple.", |
||||
"homepage": "http://amphp.org/byte-stream", |
||||
"keywords": [ |
||||
"amp", |
||||
"amphp", |
||||
"async", |
||||
"io", |
||||
"non-blocking", |
||||
"stream" |
||||
], |
||||
"support": { |
||||
"irc": "irc://irc.freenode.org/amphp", |
||||
"issues": "https://github.com/amphp/byte-stream/issues", |
||||
"source": "https://github.com/amphp/byte-stream/tree/master" |
||||
}, |
||||
"time": "2020-06-29T18:35:05+00:00" |
||||
}, |
||||
{ |
||||
"name": "amphp/parallel", |
||||
"version": "v1.4.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/amphp/parallel.git", |
||||
"reference": "2c1039bf7ca137eae4d954b14c09a7535d7d4e1c" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/amphp/parallel/zipball/2c1039bf7ca137eae4d954b14c09a7535d7d4e1c", |
||||
"reference": "2c1039bf7ca137eae4d954b14c09a7535d7d4e1c", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"amphp/amp": "^2", |
||||
"amphp/byte-stream": "^1.6.1", |
||||
"amphp/parser": "^1", |
||||
"amphp/process": "^1", |
||||
"amphp/serialization": "^1", |
||||
"amphp/sync": "^1.0.1", |
||||
"php": ">=7.1" |
||||
}, |
||||
"require-dev": { |
||||
"amphp/php-cs-fixer-config": "dev-master", |
||||
"amphp/phpunit-util": "^1.1", |
||||
"phpunit/phpunit": "^8 || ^7" |
||||
}, |
||||
"type": "library", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Amp\\Parallel\\": "lib" |
||||
}, |
||||
"files": [ |
||||
"lib/Context/functions.php", |
||||
"lib/Sync/functions.php", |
||||
"lib/Worker/functions.php" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Aaron Piotrowski", |
||||
"email": "aaron@trowski.com" |
||||
}, |
||||
{ |
||||
"name": "Stephen Coakley", |
||||
"email": "me@stephencoakley.com" |
||||
} |
||||
], |
||||
"description": "Parallel processing component for Amp.", |
||||
"homepage": "https://github.com/amphp/parallel", |
||||
"keywords": [ |
||||
"async", |
||||
"asynchronous", |
||||
"concurrent", |
||||
"multi-processing", |
||||
"multi-threading" |
||||
], |
||||
"support": { |
||||
"issues": "https://github.com/amphp/parallel/issues", |
||||
"source": "https://github.com/amphp/parallel/tree/master" |
||||
}, |
||||
"time": "2020-04-27T15:12:37+00:00" |
||||
}, |
||||
{ |
||||
"name": "amphp/parser", |
||||
"version": "v1.0.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/amphp/parser.git", |
||||
"reference": "f83e68f03d5b8e8e0365b8792985a7f341c57ae1" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/amphp/parser/zipball/f83e68f03d5b8e8e0365b8792985a7f341c57ae1", |
||||
"reference": "f83e68f03d5b8e8e0365b8792985a7f341c57ae1", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": ">=7" |
||||
}, |
||||
"require-dev": { |
||||
"friendsofphp/php-cs-fixer": "^2.3", |
||||
"phpunit/phpunit": "^6" |
||||
}, |
||||
"type": "library", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Amp\\Parser\\": "lib" |
||||
} |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Niklas Keller", |
||||
"email": "me@kelunik.com" |
||||
}, |
||||
{ |
||||
"name": "Aaron Piotrowski", |
||||
"email": "aaron@trowski.com" |
||||
} |
||||
], |
||||
"description": "A generator parser to make streaming parsers simple.", |
||||
"homepage": "https://github.com/amphp/parser", |
||||
"keywords": [ |
||||
"async", |
||||
"non-blocking", |
||||
"parser", |
||||
"stream" |
||||
], |
||||
"support": { |
||||
"issues": "https://github.com/amphp/parser/issues", |
||||
"source": "https://github.com/amphp/parser/tree/is-valid" |
||||
}, |
||||
"time": "2017-06-06T05:29:10+00:00" |
||||
}, |
||||
{ |
||||
"name": "amphp/process", |
||||
"version": "v1.1.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/amphp/process.git", |
||||
"reference": "355b1e561b01c16ab3d78fada1ad47ccc96df70e" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/amphp/process/zipball/355b1e561b01c16ab3d78fada1ad47ccc96df70e", |
||||
"reference": "355b1e561b01c16ab3d78fada1ad47ccc96df70e", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"amphp/amp": "^2", |
||||
"amphp/byte-stream": "^1.4", |
||||
"php": ">=7" |
||||
}, |
||||
"require-dev": { |
||||
"amphp/php-cs-fixer-config": "dev-master", |
||||
"amphp/phpunit-util": "^1", |
||||
"phpunit/phpunit": "^6" |
||||
}, |
||||
"type": "library", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Amp\\Process\\": "lib" |
||||
}, |
||||
"files": [ |
||||
"lib/functions.php" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Bob Weinand", |
||||
"email": "bobwei9@hotmail.com" |
||||
}, |
||||
{ |
||||
"name": "Niklas Keller", |
||||
"email": "me@kelunik.com" |
||||
}, |
||||
{ |
||||
"name": "Aaron Piotrowski", |
||||
"email": "aaron@trowski.com" |
||||
} |
||||
], |
||||
"description": "Asynchronous process manager.", |
||||
"homepage": "https://github.com/amphp/process", |
||||
"support": { |
||||
"issues": "https://github.com/amphp/process/issues", |
||||
"source": "https://github.com/amphp/process/tree/master" |
||||
}, |
||||
"time": "2019-02-26T16:33:03+00:00" |
||||
}, |
||||
{ |
||||
"name": "amphp/serialization", |
||||
"version": "v1.0.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/amphp/serialization.git", |
||||
"reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/amphp/serialization/zipball/693e77b2fb0b266c3c7d622317f881de44ae94a1", |
||||
"reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": ">=7.1" |
||||
}, |
||||
"require-dev": { |
||||
"amphp/php-cs-fixer-config": "dev-master", |
||||
"phpunit/phpunit": "^9 || ^8 || ^7" |
||||
}, |
||||
"type": "library", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Amp\\Serialization\\": "src" |
||||
}, |
||||
"files": [ |
||||
"src/functions.php" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Aaron Piotrowski", |
||||
"email": "aaron@trowski.com" |
||||
}, |
||||
{ |
||||
"name": "Niklas Keller", |
||||
"email": "me@kelunik.com" |
||||
} |
||||
], |
||||
"description": "Serialization tools for IPC and data storage in PHP.", |
||||
"homepage": "https://github.com/amphp/serialization", |
||||
"keywords": [ |
||||
"async", |
||||
"asynchronous", |
||||
"serialization", |
||||
"serialize" |
||||
], |
||||
"support": { |
||||
"issues": "https://github.com/amphp/serialization/issues", |
||||
"source": "https://github.com/amphp/serialization/tree/master" |
||||
}, |
||||
"time": "2020-03-25T21:39:07+00:00" |
||||
}, |
||||
{ |
||||
"name": "amphp/sync", |
||||
"version": "v1.4.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/amphp/sync.git", |
||||
"reference": "613047ac54c025aa800a9cde5b05c3add7327ed4" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/amphp/sync/zipball/613047ac54c025aa800a9cde5b05c3add7327ed4", |
||||
"reference": "613047ac54c025aa800a9cde5b05c3add7327ed4", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"amphp/amp": "^2.2", |
||||
"php": ">=7.1" |
||||
}, |
||||
"require-dev": { |
||||
"amphp/php-cs-fixer-config": "dev-master", |
||||
"amphp/phpunit-util": "^1.1", |
||||
"phpunit/phpunit": "^9 || ^8 || ^7" |
||||
}, |
||||
"type": "library", |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Amp\\Sync\\": "src" |
||||
}, |
||||
"files": [ |
||||
"src/functions.php", |
||||
"src/ConcurrentIterator/functions.php" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Aaron Piotrowski", |
||||
"email": "aaron@trowski.com" |
||||
}, |
||||
{ |
||||
"name": "Stephen Coakley", |
||||
"email": "me@stephencoakley.com" |
||||
} |
||||
], |
||||
"description": "Mutex, Semaphore, and other synchronization tools for Amp.", |
||||
"homepage": "https://github.com/amphp/sync", |
||||
"keywords": [ |
||||
"async", |
||||
"asynchronous", |
||||
"mutex", |
||||
"semaphore", |
||||
"synchronization" |
||||
], |
||||
"support": { |
||||
"issues": "https://github.com/amphp/sync/issues", |
||||
"source": "https://github.com/amphp/sync/tree/v1.4.0" |
||||
}, |
||||
"time": "2020-05-07T18:57:50+00:00" |
||||
}, |
||||
{ |
||||
"name": "symfony/polyfill-ctype", |
||||
"version": "v1.22.1", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/symfony/polyfill-ctype.git", |
||||
"reference": "c6c942b1ac76c82448322025e084cadc56048b4e" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", |
||||
"reference": "c6c942b1ac76c82448322025e084cadc56048b4e", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": ">=7.1" |
||||
}, |
||||
"suggest": { |
||||
"ext-ctype": "For best performance" |
||||
}, |
||||
"type": "library", |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-main": "1.22-dev" |
||||
}, |
||||
"thanks": { |
||||
"name": "symfony/polyfill", |
||||
"url": "https://github.com/symfony/polyfill" |
||||
} |
||||
}, |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Symfony\\Polyfill\\Ctype\\": "" |
||||
}, |
||||
"files": [ |
||||
"bootstrap.php" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Gert de Pagter", |
||||
"email": "BackEndTea@gmail.com" |
||||
}, |
||||
{ |
||||
"name": "Symfony Community", |
||||
"homepage": "https://symfony.com/contributors" |
||||
} |
||||
], |
||||
"description": "Symfony polyfill for ctype functions", |
||||
"homepage": "https://symfony.com", |
||||
"keywords": [ |
||||
"compatibility", |
||||
"ctype", |
||||
"polyfill", |
||||
"portable" |
||||
], |
||||
"support": { |
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" |
||||
}, |
||||
"funding": [ |
||||
{ |
||||
"url": "https://symfony.com/sponsor", |
||||
"type": "custom" |
||||
}, |
||||
{ |
||||
"url": "https://github.com/fabpot", |
||||
"type": "github" |
||||
}, |
||||
{ |
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony", |
||||
"type": "tidelift" |
||||
} |
||||
], |
||||
"time": "2021-01-07T16:49:33+00:00" |
||||
}, |
||||
{ |
||||
"name": "symfony/polyfill-mbstring", |
||||
"version": "v1.22.1", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/symfony/polyfill-mbstring.git", |
||||
"reference": "5232de97ee3b75b0360528dae24e73db49566ab1" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1", |
||||
"reference": "5232de97ee3b75b0360528dae24e73db49566ab1", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": ">=7.1" |
||||
}, |
||||
"suggest": { |
||||
"ext-mbstring": "For best performance" |
||||
}, |
||||
"type": "library", |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-main": "1.22-dev" |
||||
}, |
||||
"thanks": { |
||||
"name": "symfony/polyfill", |
||||
"url": "https://github.com/symfony/polyfill" |
||||
} |
||||
}, |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Symfony\\Polyfill\\Mbstring\\": "" |
||||
}, |
||||
"files": [ |
||||
"bootstrap.php" |
||||
] |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"MIT" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Nicolas Grekas", |
||||
"email": "p@tchwork.com" |
||||
}, |
||||
{ |
||||
"name": "Symfony Community", |
||||
"homepage": "https://symfony.com/contributors" |
||||
} |
||||
], |
||||
"description": "Symfony polyfill for the Mbstring extension", |
||||
"homepage": "https://symfony.com", |
||||
"keywords": [ |
||||
"compatibility", |
||||
"mbstring", |
||||
"polyfill", |
||||
"portable", |
||||
"shim" |
||||
], |
||||
"support": { |
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1" |
||||
}, |
||||
"funding": [ |
||||
{ |
||||
"url": "https://symfony.com/sponsor", |
||||
"type": "custom" |
||||
}, |
||||
{ |
||||
"url": "https://github.com/fabpot", |
||||
"type": "github" |
||||
}, |
||||
{ |
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony", |
||||
"type": "tidelift" |
||||
} |
||||
], |
||||
"time": "2021-01-22T09:19:47+00:00" |
||||
}, |
||||
{ |
||||
"name": "twig/twig", |
||||
"version": "v3.3.0", |
||||
"source": { |
||||
"type": "git", |
||||
"url": "https://github.com/twigphp/Twig.git", |
||||
"reference": "1f3b7e2c06cc05d42936a8ad508ff1db7975cdc5" |
||||
}, |
||||
"dist": { |
||||
"type": "zip", |
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/1f3b7e2c06cc05d42936a8ad508ff1db7975cdc5", |
||||
"reference": "1f3b7e2c06cc05d42936a8ad508ff1db7975cdc5", |
||||
"shasum": "" |
||||
}, |
||||
"require": { |
||||
"php": ">=7.2.5", |
||||
"symfony/polyfill-ctype": "^1.8", |
||||
"symfony/polyfill-mbstring": "^1.3" |
||||
}, |
||||
"require-dev": { |
||||
"psr/container": "^1.0", |
||||
"symfony/phpunit-bridge": "^4.4.9|^5.0.9" |
||||
}, |
||||
"type": "library", |
||||
"extra": { |
||||
"branch-alias": { |
||||
"dev-master": "3.3-dev" |
||||
} |
||||
}, |
||||
"autoload": { |
||||
"psr-4": { |
||||
"Twig\\": "src/" |
||||
} |
||||
}, |
||||
"notification-url": "https://packagist.org/downloads/", |
||||
"license": [ |
||||
"BSD-3-Clause" |
||||
], |
||||
"authors": [ |
||||
{ |
||||
"name": "Fabien Potencier", |
||||
"email": "fabien@symfony.com", |
||||
"homepage": "http://fabien.potencier.org", |
||||
"role": "Lead Developer" |
||||
}, |
||||
{ |
||||
"name": "Twig Team", |
||||
"role": "Contributors" |
||||
}, |
||||
{ |
||||
"name": "Armin Ronacher", |
||||
"email": "armin.ronacher@active-4.com", |
||||
"role": "Project Founder" |
||||
} |
||||
], |
||||
"description": "Twig, the flexible, fast, and secure template language for PHP", |
||||
"homepage": "https://twig.symfony.com", |
||||
"keywords": [ |
||||
"templating" |
||||
], |
||||
"support": { |
||||
"issues": "https://github.com/twigphp/Twig/issues", |
||||
"source": "https://github.com/twigphp/Twig/tree/v3.3.0" |
||||
}, |
||||
"funding": [ |
||||
{ |
||||
"url": "https://github.com/fabpot", |
||||
"type": "github" |
||||
}, |
||||
{ |
||||
"url": "https://tidelift.com/funding/github/packagist/twig/twig", |
||||
"type": "tidelift" |
||||
} |
||||
], |
||||
"time": "2021-02-08T09:54:36+00:00" |
||||
} |
||||
], |
||||
"packages-dev": [], |
||||
"aliases": [], |
||||
"minimum-stability": "stable", |
||||
"stability-flags": [], |
||||
"prefer-stable": false, |
||||
"prefer-lowest": false, |
||||
"platform": { |
||||
"php": "^7.2.5" |
||||
}, |
||||
"platform-dev": [], |
||||
"plugin-api-version": "2.0.0" |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
<?php |
||||
/** |
||||
* Configuration file |
||||
*/ |
||||
|
||||
/* Service options */ |
||||
$options = [ |
||||
/* Database settings */ |
||||
'db_host' => '127.0.0.1', |
||||
'db_user' => 'regi2p', |
||||
'db_pass' => 'pass', |
||||
'db_name' => 'user', |
||||
|
||||
/* I2P settings */ |
||||
'bob_host' => '127.0.0.1', |
||||
'bob_port' => '2827', |
||||
'bob_options' => 'inbound.quantity=5 outbound.quantity=5 inbound.length=1 outbound.length=1 i2cp.leaseSetType=3', |
||||
'bob_nick' => 'hostchecker', |
||||
'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 */ |
||||
'approval' => true, // require approval (check host for availability before publishing) |
||||
'fetcher' => true, // enable external subscriptions fetcher |
||||
'tableitems' => 30, // records limit on alive, all, search pages |
||||
|
||||
/* Records processing options */ |
||||
'approvedelay' => 24, // check host for availability before publishing for this time (hours) |
||||
'approveseen' => 3, // host must be seen lesser than this amount of hours for approving (hours) |
||||
|
||||
'newdays' => 7, // assume host as new for that amout of days |
||||
'delnewdays' => 3, // if new host not seen more than X days, disable it and disapprove |
||||
'delolddays' => 30, // same as above, but for old hosts |
||||
]; |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; |
||||
START TRANSACTION; |
||||
SET time_zone = "+00:00"; |
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; |
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; |
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; |
||||
/*!40101 SET NAMES utf8mb4 */; |
||||
|
||||
|
||||
CREATE TABLE `hosts` ( |
||||
`host` varchar(67) NOT NULL, |
||||
`base64` varchar(616) NOT NULL, |
||||
`base32` varchar(52) NOT NULL, |
||||
`description` varchar(128) NOT NULL DEFAULT '', |
||||
`add_date` timestamp NOT NULL DEFAULT current_timestamp(), |
||||
`last_seen` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', |
||||
`approved` tinyint(1) NOT NULL DEFAULT 0, |
||||
`initial` tinyint(1) NOT NULL DEFAULT 0 |
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
||||
|
||||
CREATE TABLE `subscriptions` ( |
||||
`name` varchar(67) NOT NULL, |
||||
`url` varchar(256) NOT NULL, |
||||
`etag` varchar(64) NOT NULL DEFAULT '', |
||||
`active` tinyint(1) NOT NULL DEFAULT 0 |
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
||||
|
||||
|
||||
ALTER TABLE `hosts` |
||||
ADD PRIMARY KEY (`host`); |
||||
|
||||
ALTER TABLE `subscriptions` |
||||
ADD PRIMARY KEY (`name`); |
||||
COMMIT; |
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; |
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; |
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; |
@ -0,0 +1,118 @@
@@ -0,0 +1,118 @@
|
||||
<?php |
||||
require __DIR__ . '/vendor/autoload.php'; |
||||
require __DIR__ . '/config.php'; |
||||
|
||||
set_time_limit (0); |
||||
date_default_timezone_set ('UTC'); |
||||
|
||||
$pdo = (new App\DB($options))->pdo; |
||||
$util = new App\Utils; |
||||
|
||||
$STH = $pdo->query ("SELECT `host`, `base64`, `base32`, `add_date`, `last_seen`, `approved`, `initial` FROM hosts"); |
||||
$hosts = $STH->fetchAll(PDO::FETCH_ASSOC); |
||||
|
||||
// for automatic approving |
||||
$approffs = date ("Y-m-d H:i:s", strtotime ("-" . $options["approvedelay"] . " hour")); // approval offset |
||||
$apprseen = date ("Y-m-d H:i:s", strtotime ("-" . $options["approveseen"] . " hour")); // approval maxseen offset |
||||
|
||||
$newregoffs = date ("Y-m-d H:i:s", strtotime ("-" . $options["newdays"] . " day")); |
||||
$newseenlim = date ("Y-m-d H:i:s", strtotime ("-" . $options["delnewdays"] . " day")); |
||||
$oldseenlim = date ("Y-m-d H:i:s", strtotime ("-" . $options["delolddays"] . " day")); |
||||
|
||||
$export_full = $export_live = $export_init = []; |
||||
$export_addr_full = $export_addr_live = $export_addr_init = []; |
||||
|
||||
foreach ($hosts as $host) |
||||
{ |
||||
/* Convert UFT-8 domains to Punycode */ |
||||
$domain = $util->isASCII ($host["host"]) ? $host["host"] : idn_to_ascii ($host["host"]); |
||||
|
||||
array_push($export_full, $domain . "=" . $host["base64"]); |
||||
array_push($export_addr_full, $domain . "," . $host["base32"]); |
||||
|
||||
if ( |
||||
($options["approval"] == false || $host["approved"] == 1) && ( |
||||
($host["add_date"] > $newregoffs && $host["last_seen"] > $newseenlim) || |
||||
($host["add_date"] < $newregoffs && $host["last_seen"] > $oldseenlim) |
||||
) |
||||
) |
||||
{ |
||||
array_push($export_live, $domain . "=" . $host["base64"]); |
||||
array_push($export_addr_live, $domain . "," . $host["base32"]); |
||||
|
||||
if ($host["initial"] == 1) |
||||
{ |
||||
array_push($export_init, $domain . "=" . $host["base64"]); |
||||
array_push($export_addr_init, $domain . "," . $host["base32"]); |
||||
} |
||||
} |
||||
else if ( |
||||
$host["approved"] == 0 && ( |
||||
($host["add_date"] < $approffs && $host["last_seen"] > $apprseen) // if host were registered more then X days ago and seen lesser than X hours ago |
||||
) |
||||
) |
||||
{ |
||||
$pdo->exec ("UPDATE `hosts` SET `approved` = 1 WHERE `host` = '" . $host["host"] . "'"); |
||||
array_push($export_live, $domain . "=" . $host["base64"]); |
||||
array_push($export_addr_live, $domain . "," . $host["base32"]); |
||||
} |
||||
} |
||||
|
||||
$STH = null; |
||||
$pdo = null; |
||||
|
||||
/* Sort records */ |
||||
sort ($export_full); |
||||
sort ($export_addr_full); |
||||
// |
||||
sort ($export_live); |
||||
sort ($export_addr_live); |
||||
// |
||||
sort ($export_init); |
||||
sort ($export_addr_init); |
||||
|
||||
|
||||
/* Export all records */ |
||||
$f = fopen (__DIR__ . "/public/export/hosts-all.txt", "w"); |
||||
foreach ($export_full as $l) { |
||||
$toWrite = print_r ($l, true); |
||||
fwrite ($f, $toWrite . "\n"); |
||||
} |
||||
fclose ($f); |
||||
|
||||
$f = fopen (__DIR__ . "/public/export/addresses-all.csv", "w"); |
||||
foreach ($export_addr_full as $l) { |
||||
$toWrite = print_r ($l, true); |
||||
fwrite ($f, $toWrite . "\n"); |
||||
} |
||||
fclose ($f); |
||||
|
||||
/* Export alive records */ |
||||
$f = fopen (__DIR__ . "/public/export/hosts.txt", "w"); |
||||
foreach ($export_live as $l) { |
||||
$toWrite = print_r ($l, true); |
||||
fwrite ($f, $toWrite . "\n"); |
||||
} |
||||
fclose ($f); |
||||
|
||||
$f = fopen (__DIR__ . "/public/export/addresses.csv", "w"); |
||||
foreach ($export_addr_live as $l) { |
||||
$toWrite = print_r ($l, true); |
||||
fwrite ($f, $toWrite . "\n"); |
||||
} |
||||
fclose ($f); |
||||
|
||||
/* Export initial records */ |
||||
$f = fopen (__DIR__ . "/public/export/hosts-basic.txt", "w"); |
||||
foreach ($export_init as $l) { |
||||
$toWrite = print_r ($l, true); |
||||
fwrite ($f, $toWrite . "\n"); |
||||
} |
||||
fclose ($f); |
||||
|
||||
$f = fopen (__DIR__ . "/public/export/addresses-basic.csv", "w"); |
||||
foreach ($export_addr_init as $l) { |
||||
$toWrite = print_r ($l, true); |
||||
fwrite ($f, $toWrite . "\n"); |
||||
} |
||||
fclose ($f); |
@ -0,0 +1,110 @@
@@ -0,0 +1,110 @@
|
||||
<?php |
||||
require __DIR__ . '/vendor/autoload.php'; |
||||
require __DIR__ . '/config.php'; |
||||
|
||||
$pdo = (new App\DB($options))->pdo; |
||||
$util = new App\Utils; |
||||
|
||||
$error = ""; |
||||
|
||||
$aContext = array( |
||||
'http' => array( |
||||
'method' => 'GET', |
||||
'proxy' => $options['http_proxy'], |
||||
'user_agent' => 'MYOB/6.66 (AN/ON)', |
||||
'request_fulluri' => true, |
||||
'timeout' => 120.0, |
||||
), |
||||
); |
||||
|
||||
|
||||
$STH = $pdo->query ("SELECT `name`, `url`, `etag` FROM `subscriptions` WHERE `active` = 1"); |
||||
$lists = $STH->fetchAll(PDO::FETCH_ASSOC); |
||||
|
||||
foreach ($lists as $list) { |
||||
echo "Processing " . $list['name'] . " subscription..." . PHP_EOL; |
||||
|
||||
if (!empty($list['etag'])) |
||||
$aContext['http']['header'] = 'If-None-Match: ' . $list['etag'] . '\r\n'; |
||||
|
||||
$cxContext = stream_context_create($aContext); |
||||
$f = fopen($list['url'], "r", false, $cxContext); |
||||
|
||||
if ($f) { |
||||
$f_meta = stream_get_meta_data($f); |
||||
|
||||
if (strpos($f_meta['wrapper_data'][0], "200") === false) { |
||||
continue; |
||||
} |
||||
|
||||
$etagHeader = array_filter($f_meta['wrapper_data'], function($el) { |
||||
return (strpos($el, "ETag") !== false); |
||||
}); |
||||
|
||||
if ($etagHeader) { |
||||
$etag = substr($etagHeader[array_keys($etagHeader)[0]], 6); |
||||
var_dump($etag); |
||||
$pdo->exec("UPDATE `subscriptions` SET `etag` = '" . $etag . "' WHERE `name` = '" . $list['name'] . "'"); |
||||
} |
||||
|
||||
while (($buffer = fgets($f, 4096)) !== false) { |
||||
$domain = ""; |
||||
$record = $util->parseHostRecord($buffer); |
||||
|
||||
if (!$util->isValidAddress($record['host'], $error)) { |
||||
echo "Error while validating " . $record['host'] . ": " . $error . PHP_EOL; |
||||
continue; |
||||
|
||||
} else { |
||||
if ($util->isPunycodeDomain($record['host'])) { |
||||
$domain = idn_to_utf8($record['host']); |
||||
|
||||
} else { |
||||
$domain = $record['host']; |
||||
} |
||||
} |
||||
|
||||
if (!$util->isValidBase64($record['b64'])) { |
||||
continue; |
||||
} |
||||
|
||||
if ((isset($record['commands']) && isset($record['commands']['action']) && $record['commands']['action'] == "adddest" && isset($record['commands']['olddest'])) && |
||||
$pdo->query("SELECT COUNT(*) FROM `hosts` WHERE `host` = '" . $domain . "' AND `base64` = '" . $record['commands']['olddest'] . "' LIMIT 1")->fetchColumn()) { |
||||
|
||||
$base32 = $util->b32from64($record['b64']); |
||||
$pdo->exec("UPDATE `hosts` SET `base64` = '" . $record["b64"] . "', `base32` = '" . $base32 . "' WHERE `host` = '" . $domain . "'"); |
||||
echo "Processed " . $domain . " (adddest)" . PHP_EOL; |
||||
continue; |
||||
} |
||||
|
||||
if ((isset($record['commands']) && isset($record['commands']['action']) && $record['commands']['action'] == "addsubdomain" && isset($record['commands']['oldname']) && isset($record['commands']['olddest'])) && |
||||
($pdo->query("SELECT COUNT(*) FROM `hosts` WHERE `host` = '" . $record['commands']['oldname'] . "' AND `base64` = '" . $record['commands']['olddest'] . "' LIMIT 1")->fetchColumn() && |
||||
!$pdo->query("SELECT COUNT(*) FROM `hosts` WHERE `host` = '" . $domain . "'")->fetchColumn())) { |
||||
|
||||
$base32 = $util->b32from64($record['b64']); |
||||
$pdo->exec("INSERT INTO `hosts` (`host`, `base64`, `base32`, `approved`) VALUES ('" . $domain . "', '" . $record["b64"] . "', '" . $base32 . "', 1)"); |
||||
echo "Processed " . $domain . " (addsubdomain)" . PHP_EOL; |
||||
continue; |
||||
} |
||||
|
||||
if(isset($record['commands']) && !$pdo->query("SELECT COUNT(*) FROM `hosts` WHERE `host` = '" . $domain . "' LIMIT 1")->fetchColumn()) { |
||||
|
||||
$base32 = $util->b32from64($record['b64']); |
||||
$pdo->exec("INSERT INTO `hosts` (`host`, `base64`, `base32`, `approved`) VALUES ('" . $domain . "', '" . $record["b64"] . "', '" . $base32 . "', 1)"); |
||||
echo "Processed " . $domain . PHP_EOL; |
||||
continue; |
||||
} |
||||
} |
||||
|
||||
if (!feof($f)) { |
||||
echo "Error: fgets() ended earlier than needed." . PHP_EOL; |
||||
} |
||||
|
||||
fclose($f); |
||||
} else { |
||||
echo "Empty response while fetching update from " . $list['name']. "." . PHP_EOL; |
||||
} |
||||
} |
||||
|
||||
$pdo = null; |
||||
|
@ -0,0 +1,65 @@
@@ -0,0 +1,65 @@
|
||||
<?php |
||||
require __DIR__ . '/vendor/autoload.php'; |
||||
require __DIR__ . '/config.php'; |
||||
|
||||
$pdo = (new App\DB($options))->pdo; |
||||
$util = new App\Utils; |
||||
|
||||
$error = ""; |
||||
$f = @fopen("hosts.txt", "r"); |
||||
|
||||
if ($f) { |
||||
$pdo->beginTransaction(); |
||||
|
||||
$STH = $pdo->prepare("INSERT IGNORE INTO hosts (host, base64, base32) VALUES (:host, :base64, :base32)"); |
||||
$STH->bindParam('host', $domain); |
||||
$STH->bindParam('base64', $base64); |
||||
$STH->bindParam('base32', $base32); |
||||
|
||||
while (($buffer = fgets($f, 4096)) !== false) |
||||
{ |
||||
$domain = ""; |
||||
$record = $util->parseHostRecord($buffer); |
||||
|
||||
if (!$util->isValidAddress($record['host'], $error)) |
||||
{ |
||||
echo "Error while validating " . $record['host'] . ": " . $error . PHP_EOL; |
||||
continue; |
||||
} |
||||
else |
||||
{ |
||||
if($util->isPunycodeDomain($record['host'])) |
||||
{ |
||||
$domain = idn_to_utf8($record['host']); |
||||
} |
||||
else |
||||
{ |
||||
$domain = $record['host']; |
||||
} |
||||
} |
||||
|
||||
if (!$util->isValidBase64($record['b64'])) |
||||
{ |
||||
echo "Error while validating " . $record['host'] . ": incorrect base64: " . $record['b64'] . PHP_EOL; |
||||
continue; |
||||
} |
||||
|
||||
$base64 = $record['b64']; |
||||
$base32 = $util->b32from64($record['b64']); |
||||
|
||||
$STH->execute(); |
||||
} |
||||
if (!feof($f)) |
||||
{ |
||||
echo "Error: fgets() ended earlier than needed" . PHP_EOL; |
||||
} |
||||
|
||||
if (!$pdo->commit()) |
||||
{ |
||||
echo "Error while saving records to database"; |
||||
} |
||||
|
||||
fclose($f); |
||||
} |
||||
|
||||
$pdo = null; |
@ -0,0 +1,168 @@
@@ -0,0 +1,168 @@
|
||||
<?php |
||||
|
||||
namespace App; |
||||
|
||||
class BOB { |
||||
private $sock; |
||||
|
||||
protected $options = [ |
||||
"bob_host" => "127.0.0.1", |
||||
"bob_port" => "2827", |
||||
"bob_options" => "inbound.quantity=5 outbound.quantity=5 inbound.length=1 outbound.length=1 i2cp.leaseSetType=3", |
||||
"bob_nick" => "hostchecker", |
||||
]; |
||||
|
||||
public function __construct(array $options = []) |
||||
{ |
||||
ob_implicit_flush(); |
||||
|
||||
$this->options = array_merge($this->options, (array) $options); |
||||
|
||||
$this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); |
||||
if ($this->sock === false) |
||||
{ |
||||
throw new \ErrorException("socket_create() failed: reason: " . socket_strerror(socket_last_error())); |
||||
} |
||||
else |
||||
{ |
||||
$result = socket_connect($this->sock, $this->options["bob_host"], $this->options["bob_port"]); |
||||
if ($result === false) |
||||
{ |
||||
throw new \ErrorException("socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket))); |
||||
} |
||||
|
||||
/* Reading BOB greeting */ |
||||
$response = socket_read($this->sock, 1024); |
||||
|
||||
if(!preg_match('/OK/', $response)) |
||||
{ |
||||
throw new \ErrorException("BOB returned incorrect response on connect"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public function __destruct() |
||||
{ |
||||
$command = "quit\n"; |
||||
|
||||
socket_write($this->sock, $command, strlen($command)); |
||||
socket_read($this->sock, 1024, PHP_NORMAL_READ); |
||||
|
||||
socket_close($this->sock); |
||||
} |
||||
|
||||
public function setnick() |
||||
{ |
||||
$command = "setnick " . $this->options["bob_nick"] . "\n"; |
||||
socket_write($this->sock, $command, strlen($command)); |
||||
|
||||
$response = socket_read($this->sock, 1024, PHP_NORMAL_READ); |
||||
if(!preg_match('/^OK/', $response)) |
||||
echo "BOB response: " . $response; |
||||
} |
||||
|
||||
public function options() |
||||
{ |
||||
$options = explode(" ", $this->options["bob_options"]); |
||||
|
||||
foreach($options as $option) |
||||
{ |
||||
$command = "option " . $option . "\n"; |
||||
socket_write($this->sock, $command, strlen($command)); |
||||
|
||||
$response = socket_read($this->sock, 1024, PHP_NORMAL_READ); |
||||
if(!preg_match('/^OK/', $response)) |
||||
echo "BOB response: " . $response; |
||||
} |
||||
} |
||||
|
||||
public function newkeys() |
||||
{ |
||||
$command = "newkeys\n"; |
||||
socket_write($this->sock, $command, strlen($command)); |
||||
|
||||
$response = socket_read($this->sock, 1024, PHP_NORMAL_READ); |
||||
if(!preg_match('/^OK/', $response)) |
||||
echo "BOB response: " . $response; |
||||
} |
||||
|
||||
public function start() |
||||
{ |
||||
$command = "start\n"; |
||||
socket_write($this->sock, $command, strlen($command)); |
||||
|
||||
$response = socket_read($this->sock, 1024, PHP_NORMAL_READ); |
||||
if(!preg_match('/^OK/', $response)) |
||||
echo "BOB response: " . $response; |
||||
} |
||||
|
||||
public function intun() |
||||
{ |
||||
$command = "inhost 127.0.0.1\n"; |
||||
socket_write($this->sock, $command, strlen($command)); |
||||
|
||||
$response = socket_read($this->sock, 1024, PHP_NORMAL_READ); |
||||
if(!preg_match('/^OK/', $response)) |
||||
echo "BOB response: " . $response; |
||||
|
||||
$command = "inport " . rand(1024, 65535) . "\n"; |
||||
socket_write($this->sock, $command, strlen($command)); |
||||
|
||||
$response = socket_read($this->sock, 1024, PHP_NORMAL_READ); |
||||
if(!preg_match('/^OK/', $response)) |
||||
echo "BOB response: " . $response; |
||||
} |
||||
|
||||
public function getnick() |
||||
{ |
||||
$command = "getnick " . $this->options["bob_nick"] . "\n"; |
||||
socket_write($this->sock, $command, strlen($command)); |
||||
|
||||
$response = socket_read($this->sock, 1024, PHP_NORMAL_READ); |
||||
if(!preg_match('/^OK/', $response)) |
||||
echo "BOB response: " . $response; |
||||
} |
||||
|
||||
public function lookup(string $address): bool |
||||
{ |
||||
$command = "lookup " . $address . "\n"; |
||||
socket_write($this->sock, $command, strlen($command)); |
||||
|
||||
$response = socket_read($this->sock, 1024, PHP_NORMAL_READ); |
||||
|
||||
if(preg_match('/^OK/', $response)) |
||||
return true; |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public function stop() |
||||
{ |
||||
$command = "stop\n"; |
||||
socket_write($this->sock, $command, strlen($command)); |
||||
|
||||
$response = socket_read($this->sock, 1024, PHP_NORMAL_READ); |
||||
if(!preg_match('/^OK/', $response)) |
||||
echo "BOB response: " . $response; |
||||
} |
||||
|
||||
public function clear() |
||||
{ |
||||
$command = "clear\n"; |
||||
socket_write($this->sock, $command, strlen($command)); |
||||
|
||||
$response = socket_read($this->sock, 1024, PHP_NORMAL_READ); |
||||
if(!preg_match('/^OK/', $response)) |
||||
echo "BOB response: " . $response; |
||||
} |
||||
|
||||
public function zap() |
||||
{ |
||||
$command = "zap\n"; |
||||
socket_write($this->sock, $command, strlen($command)); |
||||
|
||||
$response = socket_read($this->sock, 1024, PHP_NORMAL_READ); |
||||
if(!preg_match('/^OK/', $response)) |
||||
echo "BOB response: " . $response; |
||||
} |
||||
} |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
<?php |
||||
|
||||
namespace App; |
||||
|
||||
use App\BOB; |
||||
use Amp\Parallel\Worker\Environment; |
||||
use Amp\Parallel\Worker\Task; |
||||
use Amp\Parallel\Worker\TaskFailureError; |
||||
use Amp\Parallel\Worker\TaskFailureException; |
||||
use Amp\Parallel\Worker\TaskFailureThrowable; |
||||
|
||||
class Checker implements Task |
||||
{ |
||||
private $options = []; |
||||
private $base32; |
||||
|
||||
public function __construct($base32, $options = []) |
||||
{ |
||||
$this->options = array_merge($this->options, (array) $options); |
||||
$this->base32 = $base32; |
||||
} |
||||
|
||||
/** |
||||
* @param Environment $environment |
||||
* @return \Amp\Promise|\Generator|mixed |
||||
*/ |
||||
public function run(Environment $environment) |
||||
{ |
||||
$bob = new BOB($this->options); |
||||
|
||||
$bob->getnick(); |
||||
$result = $bob->lookup($this->base32 . ".b32.i2p"); |
||||
|
||||
$bob = null; |
||||
echo "Processed " . $this->base32 . ": " . ($result ? "online" : "offline") . PHP_EOL; |
||||
return $result; |
||||
} |
||||
} |
||||
|
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
<?php |
||||
|
||||
namespace App; |
||||
|
||||
use PDO; |
||||
|
||||
class DB |
||||
{ |
||||
public $pdo; |
||||
|
||||
protected $options = [ |
||||
"db_host" => "127.0.0.1", |
||||
"db_user" => "regi2p", |
||||
"db_pass" => "password", |
||||
"db_name" => "regi2p", |
||||
]; |
||||
|
||||
public function __construct(array $options = []) |
||||
{ |
||||
$this->options = array_merge($this->options, (array) $options); |
||||
|
||||
try { |
||||
$this->pdo = new PDO("mysql:host=".$this->options["db_host"].";dbname=".$this->options["db_name"], $this->options["db_user"], $this->options["db_pass"]); |
||||
$this->pdo->setAttribute(PDO::ATTR_TIMEOUT, 20); |
||||
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); |
||||
$this->pdo->exec("set names utf8mb4"); |
||||
} |
||||
|
||||
catch(PDOException $e) { |
||||
exit("Database connection error: " . $e . PHP_EOL); |
||||
} |
||||
} |
||||
|
||||
public function __destruct() |
||||
{ |
||||
$pdo = null; |
||||
} |
||||
} |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
<?php |
||||
|
||||
namespace App; |
||||
|
||||
class Router |
||||
{ |
||||
private $routes; |
||||
private $errRoute; |
||||
|
||||
public function addRoute($pattern, $function) { |
||||
$this->routes['{'.$pattern.'}'] = $function; |
||||
} |
||||
|
||||
public function addErrorRoute($function) { |
||||
$this->errRoute = $function; |
||||
} |
||||
|
||||
public function run() { |
||||
foreach ($this->routes as $pattern => $function) { |
||||
if (preg_match($pattern, $_SERVER['REQUEST_URI'], $params)) { |
||||
array_shift($params); |
||||
array_unshift($params, $_SERVER['REQUEST_URI']); |
||||
return call_user_func_array($function, array_values($params)); |
||||
} |
||||
} |
||||
return call_user_func($this->errRoute); |
||||
} |
||||
} |