mirror of
https://github.com/maxpozdeev/mytinytodo.git
synced 2026-03-11 08:55:27 +00:00
little more debug info in updater extension
This commit is contained in:
parent
4c01eca4ad
commit
28c59c3c5b
6 changed files with 171 additions and 105 deletions
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
(C) Copyright 2022-2023 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
|
|
@ -16,14 +16,22 @@ class Controller extends \ApiController
|
|||
function postCheck()
|
||||
{
|
||||
$prefs = UpdaterExtension::preferences();
|
||||
$a = UpdaterExtension::lastVersionInfo();
|
||||
$updater = new Updater;
|
||||
$a = $updater->lastVersionInfo();
|
||||
if ($a) {
|
||||
$prefs['lastCheck'] = time();
|
||||
$prefs['version'] = $a['version'] ?? '';
|
||||
$prefs['download'] = $a['download'] ?? '';
|
||||
Config::saveDomain(UpdaterExtension::domain, $prefs);
|
||||
$this->response->data = [ 'total' => 1 ];
|
||||
}
|
||||
else {
|
||||
$this->response->data = [
|
||||
'total' => 0,
|
||||
'msg' => __("error"),
|
||||
'details' => $updater->lastErrorString ?? ''
|
||||
];
|
||||
}
|
||||
$this->response->data = [ 'total' => 1 ];
|
||||
}
|
||||
|
||||
function postUpdate()
|
||||
|
|
@ -34,15 +42,22 @@ class Controller extends \ApiController
|
|||
$this->response->data = [ 'total' => 0, 'msg' => __("updater.download_error") ];
|
||||
return;
|
||||
}
|
||||
$updater = new Updater;
|
||||
$file = MTTPATH. 'update.tar.gz';
|
||||
$error = null;
|
||||
if (!UpdaterExtension::download($url, $file, $error)) {
|
||||
$this->response->data = [ 'total' => 0, 'msg' => __("updater.download_error"), 'details' => $error ];
|
||||
if (!$updater->download($url, $file)) {
|
||||
$this->response->data = [
|
||||
'total' => 0,
|
||||
'msg' => __("updater.download_error"),
|
||||
'details' => $updater->lastErrorString ?? ''
|
||||
];
|
||||
return;
|
||||
}
|
||||
$error = null;
|
||||
if (!UpdaterExtension::extractAndReplace($file, $error)) {
|
||||
$this->response->data = [ 'total' => 0, 'msg' => __("updater.update_error"), 'details' => $error ];
|
||||
if (!$updater->extractAndReplace($file)) {
|
||||
$this->response->data = [
|
||||
'total' => 0,
|
||||
'msg' => __("updater.update_error"),
|
||||
'details' => $updater->lastErrorString ?? ''
|
||||
];
|
||||
return;
|
||||
}
|
||||
@unlink($file);
|
||||
|
|
|
|||
118
src/ext/updater/class.updater.php
Normal file
118
src/ext/updater/class.updater.php
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2023 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
namespace UpdaterExtension;
|
||||
|
||||
class Updater
|
||||
{
|
||||
public $lastErrorString = null;
|
||||
|
||||
public function lastVersionInfo(): ?array
|
||||
{
|
||||
$options = array(
|
||||
'http' => array(
|
||||
'header' => "Content-type: application/json\r\nUser-Agent: mytinytodo\r\n"
|
||||
)
|
||||
);
|
||||
$context = stream_context_create($options);
|
||||
set_error_handler(function ($errno, $message, $file, $line) {
|
||||
throw new \ErrorException($message, $errno, $errno, $file, $line);
|
||||
});
|
||||
$json = null;
|
||||
$this->lastErrorString = null;
|
||||
try {
|
||||
$json = @file_get_contents("https://api.github.com/repos/maxpozdeev/mytinytodo/releases/latest", false, $context);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$this->lastErrorString = boolval(ini_get('html_errors')) ? htmlspecialchars_decode($e->getMessage()) : $e->getMessage();
|
||||
}
|
||||
restore_error_handler();
|
||||
if ($json === false || $json == '') {
|
||||
error_log("Failed to get last version info: ".$this->lastErrorString);
|
||||
return null;
|
||||
}
|
||||
$a = json_decode($json, true) ?? [];
|
||||
$ret = [];
|
||||
if ( isset($a['name']) && isset($a['assets']) &&
|
||||
is_array($a['assets']) && count($a['assets']) > 0 &&
|
||||
($asset = $a['assets'][0]) && isset($asset['browser_download_url']) )
|
||||
{
|
||||
$ret['version'] = substr($a['name'], 1); //remove first 'v'
|
||||
$ret['download'] = $asset['browser_download_url'];
|
||||
}
|
||||
else {
|
||||
error_log("HTTP response contains unexpected content");
|
||||
$this->lastErrorString = "HTTP response contains unexpected content";
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function download(string $url, string $outfile): bool
|
||||
{
|
||||
$this->lastErrorString = null;
|
||||
$dir = dirname($outfile);
|
||||
if (!is_dir($dir) || !is_writable($dir)) {
|
||||
$this->lastErrorString = "myTinyTodo directory is not writable";
|
||||
return false;
|
||||
}
|
||||
$f = @fopen($url, 'r');
|
||||
if ($f === false) {
|
||||
$ea = error_get_last();
|
||||
$this->lastErrorString = $ea['message'] ?? "Failed to open stream";
|
||||
return false;
|
||||
}
|
||||
$bytes = @file_put_contents($outfile, $f, LOCK_EX);
|
||||
$ea = error_get_last();
|
||||
fclose($f);
|
||||
if ($bytes === false) {
|
||||
$this->lastErrorString = $ea['message'] ?? "Can not save file";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function extractAndReplace(string $filename): bool
|
||||
{
|
||||
$this->lastErrorString = null;
|
||||
$dir = MTTPATH;
|
||||
if (!is_dir($dir) || !is_writable($dir)) {
|
||||
$this->lastErrorString = "myTinyTodo directory is not writable";
|
||||
return false;
|
||||
}
|
||||
|
||||
$output = null;
|
||||
$retval = null;
|
||||
$command = "tar xzf ". escapeshellarg($filename). " --strip-components 1 -C ". escapeshellarg($dir). " 2>&1";
|
||||
@exec($command, $output, $retval);
|
||||
if ($retval != 0) {
|
||||
$this->lastErrorString = "Failed to execute tar command ($retval): ". ($output ? implode("\n", $output) : "no output");
|
||||
error_log($this->lastErrorString);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extensions
|
||||
$dir = MTT_EXT;
|
||||
$filename = $dir . 'extensions.tar.gz';
|
||||
if (file_exists($filename)) {
|
||||
if (!is_writable($dir)) {
|
||||
$this->lastErrorString = "Extensions directory is not writable";
|
||||
return false;
|
||||
}
|
||||
$command = "tar xzf ". escapeshellarg($filename). " -C ". escapeshellarg($dir). " 2>&1";
|
||||
@exec($command, $output, $retval);
|
||||
if ($retval != 0) {
|
||||
$this->lastErrorString = "Extensions: failed to execute tar command ($retval): ". ($output ? implode("\n", $output) : "no output");
|
||||
error_log($this->lastErrorString);
|
||||
return false;
|
||||
}
|
||||
unlink($filename);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"bundleId": "updater",
|
||||
"name": "Updates",
|
||||
"version": "0.9",
|
||||
"version": "0.9.1",
|
||||
"description": "myTinyTodo self-updater"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
{
|
||||
"ext.updater.name": "Updates",
|
||||
"updater.urlconfigwarning": "Enable PHP 'allow_url_fopen' directive to be able to download updates.",
|
||||
"updater.tarwarning": "Update is not possible, 'tar' utility is not found.",
|
||||
"updater.h_check_updates": "Check updates",
|
||||
"updater.check": "Check",
|
||||
"updater.no_updates": "No updates available",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
{
|
||||
"ext.updater.name": "Обновления",
|
||||
"updater.urlconfigwarning": "Для получения обновлений требуется включить директиву 'allow_url_fopen' в настройках PHP .",
|
||||
"updater.tarwarning": "Исполняемый файл 'tar' не найден, обновление невозможно.",
|
||||
"updater.h_check_updates": "Проверка обновлений",
|
||||
"updater.check": "Проверить",
|
||||
"updater.no_updates": "Нет обновлений",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
(C) Copyright 2022-2023 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
|
|
@ -11,6 +11,7 @@ if (!defined('MTTPATH')) {
|
|||
}
|
||||
|
||||
require_once('class.controller.php');
|
||||
require_once('class.updater.php');
|
||||
|
||||
function mtt_ext_updater_instance(): MTTExtension
|
||||
{
|
||||
|
|
@ -18,6 +19,7 @@ function mtt_ext_updater_instance(): MTTExtension
|
|||
}
|
||||
|
||||
use UpdaterExtension\Controller;
|
||||
use UpdaterExtension\Updater;
|
||||
|
||||
class UpdaterExtension extends MTTExtension implements MTTExtensionSettingsInterface, MTTHttpApiExtender
|
||||
{
|
||||
|
|
@ -53,31 +55,50 @@ class UpdaterExtension extends MTTExtension implements MTTExtensionSettingsInter
|
|||
$version = $prefs['version'] ?? '';
|
||||
$updateStr = '';
|
||||
$curVersion = htmlspecialchars(mytinytodo\Version::VERSION);
|
||||
$err = null;
|
||||
if (time() - $lastCheck > 86400*7) {
|
||||
$a = self::lastVersionInfo();
|
||||
$updater = new Updater;
|
||||
$a = $updater->lastVersionInfo();
|
||||
if ($a) {
|
||||
$lastCheck = $prefs['lastCheck'] = time();
|
||||
$version = $prefs['version'] = $a['version'] ?? '';
|
||||
$prefs['download'] = $a['download'] ?? '';
|
||||
Config::saveDomain(self::domain, $prefs);
|
||||
}
|
||||
else {
|
||||
$err = $updater->lastErrorString;
|
||||
}
|
||||
}
|
||||
$warning = '';
|
||||
if ($version != '') {
|
||||
if ( version_compare($version, mytinytodo\Version::VERSION) > 0 ) {
|
||||
$updateStr = "<br> {$e('updater.updatet_version_avaialable')}: ". htmlspecialchars($version);
|
||||
# allow update to v1.7.x only
|
||||
if ("1.7." == substr($version, 0, 4)) {
|
||||
$updateStr .= "<br><br>\n <a href=\"#\" data-ext-settings-action=\"post:update\" data-ext=\"$ext\">{$e('updater.update')}</a> ";
|
||||
}
|
||||
$retval = 0;
|
||||
$output = null;
|
||||
unset($output);
|
||||
@exec('tar --version', $output, $retval);
|
||||
if ($retval != 0) {
|
||||
$warning = "<div class=\"tr\"><div style=\"width:100%;text-align:center;\">⚠️ {$e('updater.tarwarning')}</div></div>";
|
||||
}
|
||||
}
|
||||
else {
|
||||
$updateStr = "<br>{$e('updater.no_updates')}";
|
||||
}
|
||||
}
|
||||
$lastCheckStr = $lastCheck ? timestampToDatetime($lastCheck, true) : "";
|
||||
$lastCheckStr = $err ? $e('updater.download_error') : ($lastCheck ? timestampToDatetime($lastCheck, true) : "");
|
||||
|
||||
if (!boolval(ini_get('allow_url_fopen'))) {
|
||||
$warning .= "<div class=\"tr\"><div style=\"width:100%;text-align:center;\">⚠️ {$e('updater.urlconfigwarning')}</div></div>";
|
||||
}
|
||||
|
||||
|
||||
return
|
||||
<<<EOD
|
||||
$warning
|
||||
<div class="tr">
|
||||
<div class="th"> {$e('updater.h_check_updates')} </div>
|
||||
<div class="td">
|
||||
|
|
@ -95,101 +116,9 @@ EOD;
|
|||
}
|
||||
|
||||
|
||||
|
||||
static function preferences(): array
|
||||
{
|
||||
$prefs = Config::requestDomain(self::domain);
|
||||
return $prefs;
|
||||
}
|
||||
|
||||
static function lastVersionInfo(): ?array
|
||||
{
|
||||
$options = array(
|
||||
'http' => array(
|
||||
'header' => "Content-type: application/json\r\nUser-Agent: mytinytodo\r\n"
|
||||
)
|
||||
);
|
||||
$context = stream_context_create($options);
|
||||
$json = @file_get_contents("https://api.github.com/repos/maxpozdeev/mytinytodo/releases/latest", false, $context);
|
||||
if ($json === false || $json == '') {
|
||||
return null;
|
||||
}
|
||||
$a = json_decode($json, true) ?? [];
|
||||
$ret = [];
|
||||
if ( isset($a['name']) && isset($a['assets']) &&
|
||||
is_array($a['assets']) && count($a['assets']) > 0 &&
|
||||
($asset = $a['assets'][0]) && isset($asset['browser_download_url']) )
|
||||
{
|
||||
$ret['version'] = substr($a['name'], 1); //remove first 'v'
|
||||
$ret['download'] = $asset['browser_download_url'];
|
||||
}
|
||||
else {
|
||||
error_log("Unexpected content");
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function download(string $url, string $outfile, string &$error = null): bool
|
||||
{
|
||||
$dir = dirname($outfile);
|
||||
if (!is_dir($dir) || !is_writable($dir)) {
|
||||
$error = "myTinyTodo directory is not writable";
|
||||
return false;
|
||||
}
|
||||
$f = @fopen($url, 'r');
|
||||
if ($f === false) {
|
||||
$ea = error_get_last();
|
||||
$error = ($ea && isset($ea['message'])) ? $ea['message'] : "Failed to open stream";
|
||||
return false;
|
||||
}
|
||||
$bytes = @file_put_contents($outfile, $f, LOCK_EX);
|
||||
$ea = error_get_last();
|
||||
fclose($f);
|
||||
if ($bytes === false) {
|
||||
$error = ($ea && isset($ea['message'])) ? $ea['message'] : "Can not save file";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static function extractAndReplace(string $filename, string &$error = null): bool
|
||||
{
|
||||
$dir = MTTPATH;
|
||||
if (!is_dir($dir) || !is_writable($dir)) {
|
||||
$error = "myTinyTodo directory is not writable";
|
||||
return false;
|
||||
}
|
||||
|
||||
$output = null;
|
||||
$retval = null;
|
||||
$command = "tar xzf ". escapeshellarg($filename). " --strip-components 1 -C ". escapeshellarg($dir). " 2>&1";
|
||||
@exec($command, $output, $retval);
|
||||
if ($retval != 0) {
|
||||
$error = "Failed to execute tar command ($retval): ". ($output ? implode("\n", $output) : "no output");
|
||||
error_log($error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extensions
|
||||
$dir = MTT_EXT;
|
||||
$filename = $dir . 'extensions.tar.gz';
|
||||
if (file_exists($filename)) {
|
||||
if (!is_writable($dir)) {
|
||||
$error = "Extensions directory is not writable";
|
||||
return false;
|
||||
}
|
||||
$command = "tar xzf ". escapeshellarg($filename). " -C ". escapeshellarg($dir). " 2>&1";
|
||||
@exec($command, $output, $retval);
|
||||
if ($retval != 0) {
|
||||
$error = "Extensions: failed to execute tar command ($retval): ". ($output ? implode("\n", $output) : "no output");
|
||||
error_log($error);
|
||||
return false;
|
||||
}
|
||||
unlink($filename);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue