diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php index 90e77c000..1be034941 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php @@ -448,6 +448,33 @@ class ActionsAdmin extends Actions ('plugin' !== $sType ? array('Reload' => true) : true) : false); } + // /?admin/Backup + public function DoAdminBackup() : void + { + try { + $this->IsAdminLoggined(); + $file = \SnappyMail\Upgrade::backup(); + \header('Content-Type: application/gzip'); + \header('Content-Disposition: attachment; filename="' . \basename($file) . '"'); + \header('Content-Transfer-Encoding: binary'); + \header('Content-Length: ' . \filesize($file)); + $fp = \fopen($file, 'rb'); + \fpassthru($fp); + \unlink($file); + } catch (\Throwable $e) { + if (102 == $e->getCode()) { + \MailSo\Base\Http::StatusHeader(403); + } + echo $e->getMessage(); + } + exit; + } + + public function DoAdminUpgradeCore() : array + { + return $this->DefaultResponse(__FUNCTION__, \SnappyMail\Upgrade::core()); + } + public function DoAdminPluginDisable() : array { $this->IsAdminLoggined(); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php index b36c089fc..2d214bd28 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php @@ -74,6 +74,16 @@ class ServiceActions return $this; } +/* + public function ServiceBackup() : void + { + if (\method_exists($this->oActions, 'DoAdminBackup')) { + $this->oActions->DoAdminBackup(); + } + exit; + } +*/ + public function ServiceJson() : string { \ob_start(); diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/repository.php b/snappymail/v/0.0.0/app/libraries/snappymail/repository.php index 1eee2695b..e503b4330 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/repository.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/repository.php @@ -7,11 +7,11 @@ abstract class Repository // snappyMailRepo const BASE_URL = 'https://snappymail.eu/repository/v2/'; - private static function get(string $path, string $proxy, string $proxy_auth) : string + private static function get(string $path) : string { $oHTTP = HTTP\Request::factory(/*'socket' or 'curl'*/); - $oHTTP->proxy = $proxy; - $oHTTP->proxy_auth = $proxy_auth; + $oHTTP->proxy = \RainLoop\Api::Config()->Get('labs', 'curl_proxy', ''); + $oHTTP->proxy_auth = \RainLoop\Api::Config()->Get('labs', 'curl_proxy_auth', ''); $oHTTP->max_response_kb = 0; $oHTTP->timeout = 15; // timeout in seconds. $oResponse = $oHTTP->doRequest('GET', static::BASE_URL . $path); @@ -26,16 +26,17 @@ abstract class Repository // $aRep = \json_decode($sRep); - private static function download(string $path, string $proxy, string $proxy_auth) : string + private static function download(string $path) : string { $sTmp = APP_PRIVATE_DATA . \md5(\microtime(true).$path) . \preg_replace('/^.*?(\\.[a-z\\.]+)$/Di', '$1', $path); $pDest = \fopen($sTmp, 'w+b'); if (!$pDest) { throw new \Exception('Cannot create temp file: '.$sTmp); } + $oHTTP = HTTP\Request::factory(/*'socket' or 'curl'*/); - $oHTTP->proxy = $proxy; - $oHTTP->proxy_auth = $proxy_auth; + $oHTTP->proxy = \RainLoop\Api::Config()->Get('labs', 'curl_proxy', ''); + $oHTTP->proxy_auth = \RainLoop\Api::Config()->Get('labs', 'curl_proxy_auth', ''); $oHTTP->max_response_kb = 0; $oHTTP->timeout = 15; // timeout in seconds. $oHTTP->streamBodyTo($pDest); @@ -81,10 +82,7 @@ abstract class Repository if ('' === $sRep || 0 === $iRepTime || \time() - 3600 > $iRepTime) { - $sRep = static::get($sRepoFile, - \RainLoop\Api::Config()->Get('labs', 'curl_proxy', ''), - \RainLoop\Api::Config()->Get('labs', 'curl_proxy_auth', '') - ); + $sRep = static::get($sRepoFile); if ($sRep) { $aRep = \json_decode($sRep); @@ -150,6 +148,21 @@ abstract class Repository return $aResult; } + public static function getLatestCoreInfo() + { + \RainLoop\Api::Actions()->IsAdminLoggined(); + $sRep = static::get('core.json'); + return $sRep ? \json_decode($sRep) : null; + } + + public static function downloadCore(string $path) : ?string + { + $info = static::getLatestCoreInfo(); + return \version_compare(APP_VERSION, $info->version, '<') + ? static::download($info->file) // '../latest.tar.gz' + : null; + } + public static function getPackagesList() : array { \RainLoop\Api::Actions()->IsAdminLoggined(); @@ -230,27 +243,23 @@ abstract class Repository } if (isset($aList[$sId]) && $sFile === $aList[$sId]['file']) { $sRealFile = $sFile; - $sTmp = static::download($sFile, - \RainLoop\Api::Config()->Get('labs', 'curl_proxy', ''), - \RainLoop\Api::Config()->Get('labs', 'curl_proxy_auth', '') - ); + $sTmp = static::download($sFile); } } if ($sTmp) { $oArchive = new \PharData($sTmp, 0, $sRealFile); - if (static::deletePackageDir($sId)) { - if ('.phar' === \substr($sRealFile, -5)) { - $bResult = \copy($sTmp, APP_PLUGINS_PATH . \basename($sRealFile)); - } else { - $bResult = $oArchive->extractTo(\rtrim(APP_PLUGINS_PATH, '\\/')); - } - if (!$bResult) { - throw new \Exception('Cannot extract package files: '.$oArchive->getStatusString()); - } - } else { + if (!static::deletePackageDir($sId)) { throw new \Exception('Cannot remove previous plugin folder: '.$sId); } + if ('.phar' === \substr($sRealFile, -5)) { + $bResult = \copy($sTmp, APP_PLUGINS_PATH . \basename($sRealFile)); + } else { + $bResult = $oArchive->extractTo(\rtrim(APP_PLUGINS_PATH, '\\/')); + } + if (!$bResult) { + throw new \Exception('Cannot extract package files: '.$oArchive->getStatusString()); + } } } catch (\Throwable $e) { \RainLoop\Api::Logger()->Write("Install package {$sRealFile} failed: {$e->getMessage()}", \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/upgrade.php b/snappymail/v/0.0.0/app/libraries/snappymail/upgrade.php index a1d03ef42..a54c99cc3 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/upgrade.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/upgrade.php @@ -162,4 +162,49 @@ abstract class Upgrade return \unserialize($sData) ?: array(); } } + + public static function backup() : string + { +// $tar_destination = APP_DATA_FOLDER_PATH . APP_VERSION . '.tar'; + $tar_destination = APP_DATA_FOLDER_PATH . 'backup-' . \date('YmdHis') . '.tar'; + $tar = new \PharData($tar_destination); + $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(APP_DATA_FOLDER_PATH . '_data_'), \RecursiveIteratorIterator::SELF_FIRST); + $l = \strlen(APP_DATA_FOLDER_PATH); + foreach ($files as $file) { + $file = \str_replace('\\', '/', $file); + if (\is_file($file) && !\strpos($file, '/cache/')) { + $tar->addFile($file, \substr($file, $l)); + } + } + $tar->compress(\Phar::GZ); + \unlink($tar_destination); + return $tar_destination . '.gz'; + } + + public static function core() : bool + { + $this->IsAdminLoggined(); + + $bResult = false; + if (\version_compare(APP_VERSION, '2.0', '>') + && \is_writable(\dirname(APP_VERSION_ROOT_PATH)) + && \is_writable(APP_INDEX_ROOT_PATH . 'index.php') + ) { + $sTmp = null; + try { + $sTmp = Repository::downloadCore($info->file); + if ($sTmp) { + static::backup(); + $oArchive = new \PharData($sTmp, 0); + $bResult = $oArchive->extractTo(\rtrim(APP_VERSION_ROOT_PATH, '\\/')); + if (!$bResult) { + throw new \Exception('Cannot extract core files: '.$oArchive->getStatusString()); + } + } + } finally { + $sTmp && \unlink($sTmp); + } + } + return $bResult; + } }