From 4e1d990b918df84b94714021ba79e87b87ef0800 Mon Sep 17 00:00:00 2001 From: Matthias Vogel Date: Tue, 15 Jul 2014 17:38:39 +0200 Subject: [PATCH] added AutoUpdate --- cache/installedVersion.json | 3 + system/admin/views/updated-to.html.php | 5 + system/htmly.php | 21 +++++ system/includes/functions.php | 8 ++ system/includes/updater.php | 161 +++++++++++++++++++++++++++++++++ 5 files changed, 198 insertions(+) create mode 100644 cache/installedVersion.json create mode 100644 system/admin/views/updated-to.html.php create mode 100644 system/includes/updater.php diff --git a/cache/installedVersion.json b/cache/installedVersion.json new file mode 100644 index 0000000..2d86412 --- /dev/null +++ b/cache/installedVersion.json @@ -0,0 +1,3 @@ +{ + "tag_name": "v2.1" +} \ No newline at end of file diff --git a/system/admin/views/updated-to.html.php b/system/admin/views/updated-to.html.php new file mode 100644 index 0000000..c11dc91 --- /dev/null +++ b/system/admin/views/updated-to.html.php @@ -0,0 +1,5 @@ +printOne(); + +?> \ No newline at end of file diff --git a/system/htmly.php b/system/htmly.php index 9720f68..0c29618 100644 --- a/system/htmly.php +++ b/system/htmly.php @@ -6,6 +6,7 @@ date_default_timezone_set('Asia/Jakarta'); // Explicitly including the dispatch framework, // and our functions.php file require 'system/includes/dispatch.php'; +require 'system/includes/updater.php'; require 'system/includes/functions.php'; require 'system/admin/admin.php'; require 'system/includes/session.php'; @@ -1109,6 +1110,26 @@ get('/feed/opml',function(){ }); +get('/admin/update/now/:csrf',function($CSRF){ + + $proper = is_csrf_proper($CSRF); + $updater = new Updater; + if( login() && $proper && $updater->updateAble()) + { + $updater->update(); + config('views.root', 'system/admin/views'); + render('updated-to', array( + 'head_contents' => head_contents('Updated - ' . blog_title(), blog_description(), site_url()), + 'updater' => $updater, + )); + } + else + { + $login = site_url() . 'login'; + header("location: $login"); + } +}); + // If we get here, it means that // nothing has been matched above diff --git a/system/includes/functions.php b/system/includes/functions.php index 1644e78..0af8f2b 100644 --- a/system/includes/functions.php +++ b/system/includes/functions.php @@ -1673,6 +1673,10 @@ function toolbar() { $role = user('role', $user); $base = site_url(); + $CSRF = get_csrf(); + + $updater = new Updater; + echo << EOF; @@ -1686,6 +1690,10 @@ EOF; echo '
  • Import
  • '; echo '
  • Backup
  • '; echo '
  • Clear cache
  • '; + if( $updater->updateAble()) + { + echo '
  • UpdateMe[' . $updater->getName() . ']
  • '; + } echo '
  • Logout
  • '; echo ''; diff --git a/system/includes/updater.php b/system/includes/updater.php new file mode 100644 index 0000000..d0db34f --- /dev/null +++ b/system/includes/updater.php @@ -0,0 +1,161 @@ +fileName = $fileName; + $this->holdTime = $holdTime; + } + + public function is() + { + if(! file_exists($this->fileName)) + return false; + if(filemtime($this->fileName) < ( time() - $this->holdTime ) ) + { + unlink($this->fileName); + return false; + } + return true; + } + public function get() + { + return file_get_contents($this->fileName); + } + public function set($content) + { + file_put_contents($this->fileName,$content); + } +} + +class Updater +{ + protected $cachedInfo = "cache/downloadInfo.json"; + protected $versionFile = "cache/installedVersion.json"; + protected $zipFile = "cache/tmpZipFile.zip"; + + protected $infos = []; + + public function __construct() + { + if(! file_exists("cache/")) + { + mkdir("cache/"); + } + $this->cachedInfo = new CacheOneFile($this->cachedInfo); + $this->infos = $this->getInfos(); + } + + protected function getInfos() + { + $path = "https://api.github.com/repos/danpros/htmly/releases"; + if($this->cachedInfo->is()) + { + $fileContent = $this->cachedInfo->get(); + } + else + { + $fileContent = @file_get_contents($path,false, stream_context_create(['http'=>['header'=>"User-Agent: Awesome-Update-My-Self\r\n"]])); + if($fileContent == false) + { + return []; + } + $json = json_decode($fileContent,true); + $fileContent = json_encode($json, JSON_PRETTY_PRINT); + $this->cachedInfo->set($fileContent); + return $json; + } + return json_decode($fileContent,true); + } + + public function updateAble() + { + if(empty($this->infos)) + return false; + + if(file_exists($this->versionFile)) + { + $fileContent = file_get_contents($this->versionFile); + $current = json_decode($fileContent,true); + + if(isset($current['id']) && $current['id'] == $this->infos[0]['id']) + return false; + if(isset($current['tag_name']) && $current['tag_name'] == $this->infos[0]['tag_name']) + return false; + } + return true; + } + + public function update() + { + if($this->updateAble()) + { + if($this->download("https://github.com/danpros/htmly/archive/" . $this->infos[0]['tag_name'] . ".zip")) + { + if($this->unZip()) + { + unlink($this->zipFile); + file_put_contents($this->versionFile, json_encode([ + "id" => $this->infos[0]['id'], + "tag_name" => $this->infos[0]['tag_name'] + ], JSON_PRETTY_PRINT)); + return true; + } + } + } + return false; + } + protected function download($url) + { + $file = @fopen($url, 'r'); + if($file == false) + return false; + file_put_contents($this->zipFile, $file); + return true; + } + protected function unZip() + { + $path = $this->zipFile; + $zip = new ZipArchive; + if ($zip->open($path) === true) { + $cutLength = strlen($zip->getNameIndex(0)); + for($i = 1; $i < $zip->numFiles; $i++) {//iterate throw the Zip + $fileName = $zip->getNameIndex($i); + if($zip->statIndex($i)["crc"] == 0) + { + $dirName = substr($fileName,$cutLength); + if(! file_exists($dirName)) + { + //mkdir($dirName); + } + } + else{ + //copy("zip://".$path."#".$filename, substr($filename,$cutLength)); + } + } + $zip->close(); + return true; + } + else{ + return false; + } + } + + public function printOne() + { + $releases = $this->infos; + $string = "

    Updated to

    "; + $string .= "

    [" . $releases[0]['tag_name'] . "] " . $releases[0]['name'] . "

    \n"; + $string .= "

    " . $releases[0]['body'] . "

    \n"; + return $string; + } + + public function getName() + { + return $this->infos[0]['tag_name']; + } +} \ No newline at end of file