Import source

This commit is contained in:
Steffen Lange 2019-07-15 22:27:48 +02:00
parent 50b489784d
commit 32b8c4cb56
34 changed files with 890 additions and 0 deletions

69
Database.php Normal file
View file

@ -0,0 +1,69 @@
<?php
class Database {
private $time = 0;
private $file = '';
private $data = array();
function __construct(string $file) {
$this->time = time();
$this->file = $file;
}
function sort() : bool {
return usort($this->data, array($this, 'cmp'));
}
function load() : bool {
if ($json = file_get_contents($this->file)) {
if ($arr = json_decode($json, true)) {
foreach ($arr as $obj) {
array_push($this->data, new PatchObject($obj));
}
return true;
}
}
return false;
}
function save() : bool {
$arr = array();
foreach ($this->data as $obj) {
array_push($arr, $obj->toArray());
}
if ($json = json_encode($arr, JSON_PRETTY_PRINT)) {
if (file_put_contents($this->file, $json)) {
return true;
}
}
return false;
}
function time() : int {
return $this->time;
}
function count() : int {
return count($this->data);
}
function get(int $n) : PatchObject {
return $this->data[$n];
}
function find(string $id) : PatchObject {
foreach ($this->data as $obj) {
if (strcmp($obj->GetId(), $id) == 0) {
return $obj;
}
}
return new PatchObject();
}
function addOrUpdate(PatchObject $patch) {
$patch->SetTimestamp($this->time);
foreach ($this->data as &$obj) {
if (strcmp($obj->GetId(), $patch->GetId()) == 0) {
$obj = $patch;
return;
}
}
array_push($this->data, $patch);
}
private function cmp(PatchObject $a, PatchObject $b) : int {
return strcasecmp($a->getProduct(), $b->getProduct());
}
}
?>

78
PatchBase.php Normal file
View file

@ -0,0 +1,78 @@
<?php
abstract class PatchBase {
protected $patch;
protected $data = '';
function __construct(string $vendor, string $product, string $url) {
$this->patch = new PatchObject(array('id' => $this->id(), 'vendor' => $vendor, 'product' => $product, 'url' => $url));
}
function __toString() : string {
return (string)$this->patch;
}
function id() : string {
return get_class($this);
}
function getPatch() : PatchObject {
return $this->patch;
}
abstract function check() : bool;
protected function fetch(string $url, bool $json = false) : bool {
$opt = array('http' => array('user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:1.0) Gecko/20100101 Patchbot/1.0'));
$ctx = stream_context_create($opt);
if ($str = file_get_contents($url, false, $ctx)) {
$this->data = $str;
if ($json) {
if (!($this->data = json_decode($str, true)))
return false;
}
return true;
}
return false;
}
protected function parse(string $re) : bool {
if ($str = $this->regex_str($re)) {
$this->patch->SetVersion($str);
return true;
}
return false;
}
protected function parse_json(string $key) : bool {
$flat = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveArrayIterator($this->data)));
if (!empty($flat[$key])) {
$this->patch->SetVersion($flat[$key]);
return true;
}
return false;
}
protected function array_extract(string $search) {
foreach ($this->data as $val) {
if (array_search($search, array_values($val)))
$this->data = $val;
}
}
protected function str_crop(string $head = '', string $tail = '') {
if (!empty($head)) {
if ($str = strstr($this->data, $head))
$this->data = $str;
}
if (!empty($tail)) {
if ($str = strstr($this->data, $tail, true))
$this->data = $str;
}
}
private function regex(string $pattern) {
if (!preg_match($pattern, $this->data, $m))
return false;
// suppress full pattern match
unset($m[0]);
return $m;
}
private function regex_str(string $pattern) {
$m = $this->regex($pattern);
if ($m)
return $m[1];
return false;
}
}
?>

39
PatchCollector.php Normal file
View file

@ -0,0 +1,39 @@
<?php
require('PatchObject.php');
require('PatchBase.php');
require('Database.php');
$list = array();
foreach (new \DirectoryIterator(__DIR__ . '/modules') as $file) {
if ($file->isFile() && $file->getExtension() == 'php') {
if ((include __DIR__ . '/modules/' . $file->getFilename()) == TRUE) {
$name = $file->getBasename('.php');
array_push($list, new $name());
}
}
}
$db = new Database(__DIR__ . '/db.json');
echo 'Time: ' . date('c', $db->time()) . PHP_EOL;
if ($db->load()) {
foreach ($list as $patch) {
$oldVer = $db->find($patch->id())->getVersion();
if ($patch->check()) {
$newVer = $patch->getPatch()->getVersion();
echo $patch->id() . ': Version \'' . $newVer . '\' ';
if (!empty($newVer) && $newVer != $oldVer) {
echo 'is newer than \'' . $oldVer . '\'!';
$db->addOrUpdate($patch->getPatch());
}
else
echo 'is up to date.';
echo PHP_EOL;
}
else
fwrite(STDERR, $patch->id() . ': CHECK FAILED!' . PHP_EOL);
}
$db->save();
}
?>

39
PatchCollector_test.php Normal file
View file

@ -0,0 +1,39 @@
<?php
require('PatchObject.php');
require('PatchBase.php');
require('Database.php');
$list = array();
foreach (new \DirectoryIterator(__DIR__ . '/modules_test') as $file) {
if ($file->isFile() && $file->getExtension() == 'php') {
if ((include __DIR__ . '/modules_test/' . $file->getFilename()) == TRUE) {
$name = $file->getBasename('.php');
array_push($list, new $name());
}
}
}
$db = new Database(__DIR__ . '/db.json');
echo 'Time: ' . date('c', $db->time()) . PHP_EOL;
if ($db->load()) {
foreach ($list as $patch) {
$oldVer = $db->find($patch->id())->getVersion();
if ($patch->check()) {
$newVer = $patch->getPatch()->getVersion();
echo $patch->id() . ': Version \'' . $newVer . '\' ';
if (!empty($newVer) && $newVer != $oldVer) {
echo 'is newer than \'' . $oldVer . '\'!';
$db->addOrUpdate($patch->getPatch());
}
else
echo 'is up to date.';
echo PHP_EOL;
}
else
fwrite(STDERR, $patch->id() . ': CHECK FAILED!' . PHP_EOL);
}
$db->save();
}
?>

48
PatchObject.php Normal file
View file

@ -0,0 +1,48 @@
<?php
class PatchObject {
private $id = '';
private $vendor = '';
private $product = '';
private $version = '';
private $url = '';
private $timestamp = 0;
function __construct(array $arr = array()) {
foreach ($arr as $key => $val) {
if (property_exists(__CLASS__, $key))
$this->{$key} = $val;
}
}
function __toString() : string {
return $this->vendor . ' ' . $this->product . ' ' . $this->version;
}
function toArray() : array {
return array('id' => $this->id, 'vendor' => $this->vendor, 'product' => $this->product, 'version' => $this->version, 'url' => $this->url, 'timestamp' => $this->timestamp);
}
function getId() : string {
return $this->id;
}
function getVendor() : string {
return $this->vendor;
}
function getProduct() : string {
return $this->product;
}
function getVersion() : string {
return $this->version;
}
function setVersion(string $version) {
$this->version = $version;
}
function getURL() : string {
return $this->url;
}
function getTimestamp() : int {
return $this->timestamp;
}
function setTimestamp(int $timestamp) {
$this->timestamp = $timestamp;
}
}
?>

56
PatchViewer.php Normal file
View file

@ -0,0 +1,56 @@
<?php
require('PatchObject.php');
require('Database.php');
$db = new Database(__DIR__ . '/db.json');
if (!$db->load()) {
exit(1);
}
$db->sort();
?>
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>Patchbot</title>
</head>
<body>
<div class="container p-5">
<h2 class="mb-4">Patch Notification Robot</h2>
<p class="text-center"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=WYQZCVJPVSS5L&amp;source=url"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" alt="Donate" /></a></p>
<p>Providing you the latest update notifications:</p>
<table class="table table-bordered table-hover table-sm">
<thead class="thead-dark">
<tr>
<th>Vendor</th>
<th>Product</th>
<th>Version</th>
<th>Release Date*</th>
</tr>
</thead>
<tbody>
<?php
for ($i = 0; $i < $db->count(); $i++) {
$patch = $db->get($i);
echo '<tr>';
echo '<td>' . $patch->getVendor() . '</td>';
echo '<td><a href="' . $patch->getURL() . '">' . $patch->getProduct() . '</a></td>';
echo '<td>' . $patch->getVersion() . '</td>';
echo '<td>' . date('Y-m-d', $patch->getTimestamp()) . '</td>';
echo '</tr>' . "\r\n";
}
?>
</tbody>
</table>
<div class="text-right">
<p><a href="https://www.dateihal.de/cms/imprint">Imprint</a> &amp; <a href="https://www.dateihal.de/cms/privacy">Privacy</a></p>
</div>
</div>
</body>
</html>

202
db.json Normal file
View file

@ -0,0 +1,202 @@
[
{
"id": "GoogleChrome",
"vendor": "Google",
"product": "Chrome",
"version": "75.0.3770.100",
"url": "https:\/\/www.google.de\/chrome\/",
"timestamp": 1561739765
},
{
"id": "AdobeReader",
"vendor": "Adobe",
"product": "Acrobat Reader DC",
"version": "2019.012.20034",
"url": "https:\/\/get.adobe.com\/de\/reader\/",
"timestamp": 1558278109
},
{
"id": "AdoptOpenJDK11",
"vendor": "AdoptOpenJDK",
"product": "OpenJDK JRE 11",
"version": "11.0.3+7",
"url": "https:\/\/adoptopenjdk.net\/",
"timestamp": 1558278109
},
{
"id": "AdoptOpenJDK12",
"vendor": "AdoptOpenJDK",
"product": "OpenJDK JRE 12",
"version": "12.0.1+12",
"url": "https:\/\/adoptopenjdk.net\/",
"timestamp": 1558278109
},
{
"id": "AdoptOpenJDK8",
"vendor": "AdoptOpenJDK",
"product": "OpenJDK JRE 8",
"version": "8u212-b04",
"url": "https:\/\/adoptopenjdk.net\/",
"timestamp": 1559992285
},
{
"id": "Arduino",
"vendor": "Arduino",
"product": "Arduino IDE",
"version": "1.8.9",
"url": "https:\/\/www.arduino.cc\/",
"timestamp": 1561541195
},
{
"id": "DirectoryLister",
"vendor": "Chris Kankiewicz",
"product": "Directory Lister",
"version": "2.7.1",
"url": "https:\/\/www.directorylister.com\/",
"timestamp": 1561318803
},
{
"id": "GIMP",
"vendor": "GIMP Team",
"product": "GNU Image Manipulation Program",
"version": "2.10.12",
"url": "https:\/\/www.gimp.org\/",
"timestamp": 1563107345
},
{
"id": "GpgWin",
"vendor": "Gpg4win Initiative",
"product": "GNU Privacy Guard for Windows",
"version": "3.1.10",
"url": "https:\/\/www.gpg4win.de\/",
"timestamp": 1563107271
},
{
"id": "MSOffice2019",
"vendor": "Microsoft",
"product": "Office 2019",
"version": "1906 (Build 11727.20244)",
"url": "https:\/\/docs.microsoft.com\/en-us\/OfficeUpdates\/update-history-office-2019#retail-versions-of-office-2016-c2r-and-office-2019",
"timestamp": 1562745139
},
{
"id": "MSOffice2019VL",
"vendor": "Microsoft",
"product": "Office 2019 VL",
"version": "1808 (Build 10348.20020)",
"url": "https:\/\/docs.microsoft.com\/en-us\/OfficeUpdates\/update-history-office-2019#volume-licensed-versions-of-office-2019",
"timestamp": 1562745139
},
{
"id": "MikroTikRouterOS",
"vendor": "MikroTik",
"product": "RouterOS",
"version": "6.45.1",
"url": "https:\/\/mikrotik.com\/download",
"timestamp": 1562431335
},
{
"id": "MozillaFirefox",
"vendor": "Mozilla",
"product": "Firefox",
"version": "68.0",
"url": "https:\/\/www.mozilla.org\/de\/firefox\/all\/",
"timestamp": 1562745139
},
{
"id": "MozillaFirefoxESR",
"vendor": "Mozilla",
"product": "Firefox ESR",
"version": "60.8.0",
"url": "https:\/\/www.mozilla.org\/de\/firefox\/organizations\/all\/",
"timestamp": 1562745139
},
{
"id": "MozillaThunderbird",
"vendor": "Mozilla",
"product": "Thunderbird",
"version": "60.8.0",
"url": "https:\/\/www.thunderbird.net\/de\/thunderbird\/all\/",
"timestamp": 1563107107
},
{
"id": "PuTTY",
"vendor": "Simon Tatham",
"product": "PuTTY",
"version": "0.71",
"url": "https:\/\/www.chiark.greenend.org.uk\/~sgtatham\/putty\/",
"timestamp": 1561380235
},
{
"id": "SevenZip",
"vendor": "Igor Pavlov",
"product": "7-Zip",
"version": "19.00",
"url": "https:\/\/www.7-zip.org\/",
"timestamp": 1561234479
},
{
"id": "TotalCommander",
"vendor": "Ghisler",
"product": "Total Commander",
"version": "9.22a",
"url": "https:\/\/www.ghisler.com\/",
"timestamp": 1561405210
},
{
"id": "VLC",
"vendor": "VideoLAN",
"product": "VLC media player",
"version": "3.0.7.1",
"url": "https:\/\/www.videolan.org\/vlc\/",
"timestamp": 1560345804
},
{
"id": "Wireshark",
"vendor": "Gerald Combs",
"product": "Wireshark",
"version": "3.0.2",
"url": "https:\/\/www.wireshark.org\/",
"timestamp": 1561489221
},
{
"id": "AdobeFlashPlayer",
"vendor": "Adobe",
"product": "Flash Player",
"version": "32.0.0.223",
"url": "https:\/\/get.adobe.com\/de\/flashplayer\/",
"timestamp": 1562745139
},
{
"id": "PHP",
"vendor": "PHP Group",
"product": "PHP",
"version": "7.3.7",
"url": "https:\/\/www.php.net\/",
"timestamp": 1562431335
},
{
"id": "Caddy",
"vendor": "Matthew Holt",
"product": "Caddy",
"version": "v1.0.1",
"url": "https:\/\/caddyserver.com\/",
"timestamp": 1563107271
},
{
"id": "Gitea",
"vendor": "Gitea Authors",
"product": "Gitea",
"version": "v1.9.0-rc2",
"url": "https:\/\/gitea.io\/",
"timestamp": 1563208203
},
{
"id": "cTop",
"vendor": "Bradley Cicenas",
"product": "ctop",
"version": "v0.7.2",
"url": "https:\/\/ctop.sh\/",
"timestamp": 1563107271
}
]

1
empty.json Normal file
View file

@ -0,0 +1 @@
[{}]

View file

@ -0,0 +1,16 @@
<?php
class AdobeFlashPlayer extends PatchBase {
function __construct() {
parent::__construct('Adobe', 'Flash Player', 'https://get.adobe.com/de/flashplayer/');
}
function check() : bool {
if ($this->fetch('https://get.adobe.com/flashplayer/webservices/json/?platform_type=Windows&platform_dist=XP&platform_arch=x86-32&platform_misc=&exclude_version=10&browser_arch=&browser_type=&browser_vers=&browser_dist=&eventname=flashplayerotherversions', true)) {
$this->array_extract('flashplayerax');
return $this->parse_json('Version');
}
return false;
}
}
?>

14
modules/AdobeReader.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class AdobeReader extends PatchBase {
function __construct() {
parent::__construct('Adobe', 'Acrobat Reader DC', 'https://get.adobe.com/de/reader/');
}
function check() : bool {
if ($this->fetch('https://get.adobe.com/de/reader/'))
return $this->parse('_<strong>Version ([\d\.]+)</strong>_');
return false;
}
}
?>

View file

@ -0,0 +1,14 @@
<?php
class AdoptOpenJDK11 extends PatchBase {
function __construct() {
parent::__construct('AdoptOpenJDK', 'OpenJDK JRE 11', 'https://adoptopenjdk.net/');
}
function check() : bool {
if ($this->fetch('https://api.adoptopenjdk.net/v2/info/releases/openjdk11?release=latest&openjdk_impl=hotspot&type=jre&os=windows&arch=x64', true))
return $this->parse_json('openjdk_version');
return false;
}
}
?>

View file

@ -0,0 +1,14 @@
<?php
class AdoptOpenJDK12 extends PatchBase {
function __construct() {
parent::__construct('AdoptOpenJDK', 'OpenJDK JRE 12', 'https://adoptopenjdk.net/');
}
function check() : bool {
if ($this->fetch('https://api.adoptopenjdk.net/v2/info/releases/openjdk12?release=latest&openjdk_impl=hotspot&type=jre&os=windows&arch=x64', true))
return $this->parse_json('openjdk_version');
return false;
}
}
?>

14
modules/AdoptOpenJDK8.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class AdoptOpenJDK8 extends PatchBase {
function __construct() {
parent::__construct('AdoptOpenJDK', 'OpenJDK JRE 8', 'https://adoptopenjdk.net/');
}
function check() : bool {
if ($this->fetch('https://api.adoptopenjdk.net/v2/info/releases/openjdk8?release=latest&openjdk_impl=hotspot&type=jre&os=windows&arch=x64', true))
return $this->parse_json('openjdk_version');
return false;
}
}
?>

14
modules/Arduino.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class Arduino extends PatchBase {
function __construct() {
parent::__construct('Arduino AG', 'Arduino IDE', 'https://www.arduino.cc/');
}
function check() : bool {
if ($this->fetch('https://www.arduino.cc/en/Main/Software'))
return $this->parse('_<div class="blue-title">[\s]*ARDUINO ([\d\.]+)[\s]*</div>_');
return false;
}
}
?>

14
modules/Caddy.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class Caddy extends PatchBase {
function __construct() {
parent::__construct('Matthew Holt', 'Caddy', 'https://caddyserver.com/');
}
function check() : bool {
if ($this->fetch('https://api.github.com/repos/caddyserver/caddy/releases/latest', true))
return $this->parse_json('tag_name');
return false;
}
}
?>

View file

@ -0,0 +1,14 @@
<?php
class DirectoryLister extends PatchBase {
function __construct() {
parent::__construct('Chris Kankiewicz', 'Directory Lister', 'https://www.directorylister.com/');
}
function check() : bool {
if ($this->fetch('https://api.github.com/repos/DirectoryLister/DirectoryLister/releases/latest', true))
return $this->parse_json('tag_name');
return false;
}
}
?>

14
modules/GIMP.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class GIMP extends PatchBase {
function __construct() {
parent::__construct('GIMP Team', 'GNU Image Manipulation Program', 'https://www.gimp.org/');
}
function check() : bool {
if ($this->fetch('https://www.gimp.org/downloads/'))
return $this->parse('_//download\.gimp\.org/mirror/pub/gimp/v[\d\.]+/windows/gimp-([\d\.]+)-setup[\-\d]*\.exe_');
return false;
}
}
?>

14
modules/Gitea.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class Gitea extends PatchBase {
function __construct() {
parent::__construct('Gitea Authors', 'Gitea', 'https://gitea.io/');
}
function check() : bool {
if ($this->fetch('https://api.github.com/repos/go-gitea/gitea/releases/latest', true))
return $this->parse_json('tag_name');
return false;
}
}
?>

14
modules/GoogleChrome.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class GoogleChrome extends PatchBase {
function __construct() {
parent::__construct('Google', 'Chrome', 'https://www.google.de/chrome/');
}
function check() : bool {
if ($this->fetch('https://omahaproxy.appspot.com/all'))
return $this->parse('/win64,stable,([\d\.]+),/');
return false;
}
}
?>

14
modules/GpgWin.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class GpgWin extends PatchBase {
function __construct() {
parent::__construct('Gpg4win Initiative', 'GNU Privacy Guard for Windows', 'https://www.gpg4win.de/');
}
function check() : bool {
if ($this->fetch('https://www.gpg4win.de/get-gpg4win-de.html'))
return $this->parse('/<h2>Download Gpg4win ([\d\.]+) \(/');
return false;
}
}
?>

16
modules/MSOffice2019.php Normal file
View file

@ -0,0 +1,16 @@
<?php
class MSOffice2019 extends PatchBase {
function __construct() {
parent::__construct('Microsoft', 'Office 2019', 'https://docs.microsoft.com/en-us/OfficeUpdates/update-history-office-2019#retail-versions-of-office-2016-c2r-and-office-2019');
}
function check() : bool {
if ($this->fetch('https://docs.microsoft.com/en-us/OfficeUpdates/update-history-office-2019')) {
$this->str_crop('retail-versions-of-office-2016-c2r-and-office-2019', '</table>');
return $this->parse('/Version ([\d]+ \(Build [\d\.]+\))/');
}
return false;
}
}
?>

View file

@ -0,0 +1,16 @@
<?php
class MSOffice2019VL extends PatchBase {
function __construct() {
parent::__construct('Microsoft', 'Office 2019 VL', 'https://docs.microsoft.com/en-us/OfficeUpdates/update-history-office-2019#volume-licensed-versions-of-office-2019');
}
function check() : bool {
if ($this->fetch('https://docs.microsoft.com/en-us/OfficeUpdates/update-history-office-2019')) {
$this->str_crop('volume-licensed-versions-of-office-2019', '</table>');
return $this->parse('/Version ([\d]+ \(Build [\d\.]+\))/');
}
return false;
}
}
?>

View file

@ -0,0 +1,16 @@
<?php
class MikroTikRouterOS extends PatchBase {
function __construct() {
parent::__construct('MikroTik', 'RouterOS', 'https://mikrotik.com/download');
}
function check() : bool {
if ($this->fetch('https://mikrotik.com/download')) {
$this->str_crop('id="routeros"', '</thead>');
return $this->parse('/<th>([\d\.]+) \(Stable\)/');
}
return false;
}
}
?>

View file

@ -0,0 +1,14 @@
<?php
class MozillaFirefox extends PatchBase {
function __construct() {
parent::__construct('Mozilla', 'Firefox', 'https://www.mozilla.org/de/firefox/all/');
}
function check() : bool {
if ($this->fetch('https://www.mozilla.org/de/firefox/all/'))
return $this->parse('/data-latest-firefox="([\d\.]+)"/');
return false;
}
}
?>

View file

@ -0,0 +1,14 @@
<?php
class MozillaFirefoxESR extends PatchBase {
function __construct() {
parent::__construct('Mozilla', 'Firefox ESR', 'https://www.mozilla.org/de/firefox/organizations/all/');
}
function check() : bool {
if ($this->fetch('https://www.mozilla.org/de/firefox/organizations/all/'))
return $this->parse('/data-esr-versions="([\d\.]+)[ "]/');
return false;
}
}
?>

View file

@ -0,0 +1,14 @@
<?php
class MozillaThunderbird extends PatchBase {
function __construct() {
parent::__construct('Mozilla', 'Thunderbird', 'https://www.thunderbird.net/de/thunderbird/all/');
}
function check() : bool {
if ($this->fetch('https://www.thunderbird.net/de/thunderbird/all/'))
return $this->parse('_"https://download\.mozilla\.org/\?product=thunderbird-([\d\.]+)(-SSL)?&(amp;)?os=win&(amp;)?lang=en-US"_');
return false;
}
}
?>

14
modules/PHP.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class PHP extends PatchBase {
function __construct() {
parent::__construct('PHP Group', 'PHP', 'https://www.php.net/');
}
function check() : bool {
if ($this->fetch('https://www.php.net/downloads.php'))
return $this->parse('_Current Stable</span>[\s]*PHP ([\d\.]+)_');
return false;
}
}
?>

14
modules/PuTTY.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class PuTTY extends PatchBase {
function __construct() {
parent::__construct('Simon Tatham', 'PuTTY', 'https://www.chiark.greenend.org.uk/~sgtatham/putty/');
}
function check() : bool {
if ($this->fetch('https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html'))
return $this->parse('/latest release \(([\d\.]+)\)/');
return false;
}
}
?>

14
modules/SevenZip.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class SevenZip extends PatchBase {
function __construct() {
parent::__construct('Igor Pavlov', '7-Zip', 'https://www.7-zip.org/');
}
function check() : bool {
if ($this->fetch('https://www.7-zip.org/download.html'))
return $this->parse('/Download 7-Zip ([\d\.]+) \(/');
return false;
}
}
?>

View file

@ -0,0 +1,14 @@
<?php
class TotalCommander extends PatchBase {
function __construct() {
parent::__construct('Ghisler', 'Total Commander', 'https://www.ghisler.com/');
}
function check() : bool {
if ($this->fetch('https://www.ghisler.com/download.htm'))
return $this->parse('/version ([\d\w\.]+) of/');
return false;
}
}
?>

14
modules/VLC.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class VLC extends PatchBase {
function __construct() {
parent::__construct('VideoLAN', 'VLC media player', 'https://www.videolan.org/vlc/');
}
function check() : bool {
if ($this->fetch('https://www.videolan.org/vlc/download-windows.html'))
return $this->parse('_//get\.videolan\.org/vlc/([\d\.]+)/win32/vlc-[\d\.]+-win32\.exe_');
return false;
}
}
?>

14
modules/Wireshark.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class Wireshark extends PatchBase {
function __construct() {
parent::__construct('Gerald Combs', 'Wireshark', 'https://www.wireshark.org/');
}
function check() : bool {
if ($this->fetch('https://www.wireshark.org/download.html'))
return $this->parse('/>Stable Release \(([\d\.]+)\)/');
return false;
}
}
?>

14
modules/cTop.php Normal file
View file

@ -0,0 +1,14 @@
<?php
class cTop extends PatchBase {
function __construct() {
parent::__construct('Bradley Cicenas', 'ctop', 'https://ctop.sh/');
}
function check() : bool {
if ($this->fetch('https://api.github.com/repos/bcicen/ctop/releases/latest', true))
return $this->parse_json('tag_name');
return false;
}
}
?>

0
modules_test/.gitkeep Normal file
View file