Started implementing of new update mechanism

This commit is contained in:
kolaente 2017-10-05 23:01:05 +02:00
parent 9e1397a4dd
commit e8e1ff2451
8 changed files with 193 additions and 101 deletions

View File

@ -79,7 +79,7 @@ if (hasPerm('manage_system'))
stream_message('{user} put the site into construction mode.', 2);
} else
{
echo msg('fail', $lang->get('action_try_again_later') . ' <a href="general_config.php">' . $lang->get('back') . '</a>');
echo msg('fail', $lang->get('action_construction_error') . ' <a href="general_config.php">' . $lang->get('back') . '</a>');
}
} else
{
@ -105,7 +105,7 @@ if (hasPerm('manage_system'))
stream_message('{user} put the site into production mode.', 2);
} else
{
echo msg('fail', $lang->get('action_try_again_later') . ' <a href="general_config.php">' . $lang->get('back') . '</a>');
echo msg('fail', $lang->get('action_construction_removed_error') . ' <a href="general_config.php">' . $lang->get('back') . '</a>');
}
} else
{

View File

@ -68,7 +68,7 @@ if (isset($_POST['submit']))
$CONFIG['Templating']['tpl_webUri'] = 'website_uri';
$CONFIG['Versioning']['version'] = '0.96';
$CONFIG['Versioning']['version_num'] = 9;
$CONFIG['Versioning']['update_uri'][] = 'https://cdn.kola-entertainments.de/cms/';
$CONFIG['Versioning']['update_servers'][] = 'https://cdn.kola-entertainments.de/cms/';
$CONFIG['Mail']['smtp'] = false;
//Mail Settings

View File

@ -210,8 +210,10 @@ $lang['action_construction_message_success'] = 'Die Meldung wurde erfolgreich ge
$lang['action_try_again_later'] = 'Fehler. Bitte versuchen Sie es später noch einmal.';
$lang['action_construction_message_edit'] = 'Baustellen-Meldung bearbeiten';
$lang['action_construction_success'] = 'Die Webseite wurde erfolgreich in den Baustellenzustand versetzt.';
$lang['action_construction_error'] = 'Beim Versetzen in den Baustellenmodus trat ein Fehler auf.';
$lang['action_construction_confirm'] = 'Wollen Sie die Webseite wirklich in den Baustellenzustand verstzten?';
$lang['action_construction_removed_success'] = 'Der Baustellenzustand wurde erfolgreich aufgehoben.';
$lang['action_construction_removed_error'] = 'Beim Aufheben des Baustellenzustandes ist ein Fehler aufgetreten.';
$lang['action_construction_remove'] = 'Wollen Sie den Baustellenzustand wirklich aufheben?';
$lang['action_change_page_title_success'] = 'Die Änderungen des Seitentitels wurden erfolgreich gespeichert.';
@ -225,7 +227,7 @@ $lang['update_app_succss'] = '"%1$s" wurde erfolgreich upgedatet.';
$lang['update_fail'] = 'Fehler beim Updaten.';
$lang['update_config_fail'] = 'Beim Bearbeiten der Configdatei ist ein Fehler aufgetreten.';
$lang['update_fail_unzip'] = 'Fehler beim Entpacken des Updates.';
$lang['update_md5_fake'] = 'Die Heruntergeladene Datei ist vermutlich falsch.';
$lang['update_wrong_hash'] = 'Die Heruntergeladene Datei ist vermutlich falsch.';
$lang['update_fail_copy'] = 'Fehler beim Herunterladen des Updates. <b>Hinweis:</b> Der Nutzer, unter welchem der Webserver läuft, muss im Verzeichnis /admin Schreibrechte haben!';
$lang['update_version'] = 'Version';
$lang['update_version_current'] = 'Installierte Version';
@ -233,6 +235,9 @@ $lang['update_new_version'] = 'Neue Version verfügbar!';
$lang['update_version_current_new'] = 'Die installierte Version ist aktuell.';
$lang['update_app_update_available'] = 'App-Update - Neue Version für "%1$s" verfügbar: %2$s';
$lang['update_log'] = '{user} hat das System geupdated.';
$lang['update_folder_not_writeable'] = 'Der Updateordner ist nicht schreibbar. Bitte stelle sicher, dass der Webserver Schreibrechte im Updateordner hat.';
$lang['update_create_backup_error'] = 'Beim Erstellen eines Backups ist ein Fehler aufgetreten.';
$lang['update_cleanup_error'] = 'Beim Aufräumen ist ein Fehler aufgetreten.';
//Stream Messages
$lang['stream_saved_settings'] = '{user} hat seinen Benutzername/Email-Adresse geändert.';

View File

@ -203,8 +203,10 @@ $lang['action_construction_message_success'] = 'The construction-message was edi
$lang['action_try_again_later'] = 'Error. Please try again later.';
$lang['action_construction_message_edit'] = 'Edit Construction Message';
$lang['action_construction_success'] = 'The website was set to construction mode successfully.';
$lang['action_construction_error'] = 'An error occured while setting the site to construction mode.';
$lang['action_construction_confirm'] = 'Are you sure you want to enable construction mode?';
$lang['action_construction_removed_success'] = 'Construction Mode was successfully disabled.';
$lang['action_construction_removed_error'] = 'An error occured while disabling construction mode.';
$lang['action_construction_remove'] = 'Are you sure you want to disable construction mode?';
$lang['action_change_page_title_success'] = 'Page Title was successfully edited.';
@ -219,7 +221,7 @@ $lang['update_app_succss'] = '"%1$s" was updated successfully.';
$lang['update_fail'] = 'An error occured while updating.';
$lang['update_config_fail'] = 'An error occured while updating the config file.';
$lang['update_fail_unzip'] = 'An error occured while unpacking the update.';
$lang['update_md5_fake'] = 'The downloaded file has a wrong checksum.';
$lang['update_wrong_hash'] = 'The downloaded file has a wrong checksum.';
$lang['update_fail_copy'] = 'An error occured while downloading the update. <b>Hint:</b> The webserver needs writing permissions in the folder /admin!';
$lang['update_version'] = 'Version';
$lang['update_version_current'] = 'Installed Version';
@ -227,6 +229,9 @@ $lang['update_new_version'] = 'New Version Available!';
$lang['update_version_current_new'] = 'Installed Version is up-to-date';
$lang['update_app_update_available'] = 'App-Update - New Version for "%1$s" available: %2$s';
$lang['update_log'] = '{user} updated the System.';
$lang['update_folder_not_writeable'] = 'The updatefolder is not writeable. Please make sure your webserver can write into the folder.';
$lang['update_create_backup_error'] = 'An error occured while creating a backup.';
$lang['update_cleanup_error'] = 'Beim Aufräumen ist ein Fehler aufgetreten.';
//Stream Messages
$lang['stream_saved_settings'] = '{user} changed it\'s username and/or email-adress.';

View File

@ -1,5 +1,19 @@
<?php
require_once '../inc/autoload_adm.php';
require_once '../inc/libs/updater.php';
$update = new Mowie\Updater\updater();
$update->setServer($MCONF['update_servers']);
$update->setCurrentVersion($MCONF['version']);
$update->setUpdateDir('../');
$update->thingsToNotUpdate = [
'apps/',
'config/',
'content/',
'vendor/',
'templates_c',
'docker-dev'
];
//Update-Checker
if (isset($_GET['checkUpdate']))
@ -8,79 +22,26 @@ if (isset($_GET['checkUpdate']))
if (hasPerm('update'))
{
//Check for newer Version
$nextVersion = $MCONF['version_num'] + 1;
$foundNewVersion = false;
$hasChangelog = false;
foreach ($MCONF['update_uri'] as $update_server)
try
{
$updateUrl = $update_server . 'System/v' . $nextVersion;
if (remote_file_exists($updateUrl . '/version.json'))
{
$version_remote = json_decode(file_get_contents($updateUrl . '/version.json'));
if ($version_remote->versionNum > $MCONF['version_num'])
{
$foundNewVersion = true;
//Check for Changelog
if (remote_file_exists($updateUrl . '/changelog.md'))
{
$hasChangelog = $update_server;
}
}
}
$new = $update->checkUpdateAvailable();
} catch (\Exception $e)
{
echo 'Error. ' . $e->getMessage();
}
if ($foundNewVersion)
// If we have a new version, show it
if (isset($new))
{
echo $lang->get('update_new_version') . ' <b>' . $version_remote->version . '</b> <a href="update.php?update" class="button">' . $lang->get('update_title') . '</a>';
if ($hasChangelog !== false)
echo $lang->get('update_new_version') . ' <b>' . $new['version'] . '</b> <a href="update.php?update" class="button">' . $lang->get('update_title') . '</a>';
if (isset($new['changelog']))
{
echo '<a href="update.php?showChangelog&server=' . urlencode($hasChangelog) . '&v=' . $nextVersion . '" class="button"><i class="fa fa-list-alt" aria-hidden="true"></i>&nbsp;&nbsp;Changelog</a>';
echo '<a href="update.php?showChangelog&url=' . urlencode($new['server'] . $new['changelog']) . '" class="button"><i class="fa fa-list-alt" aria-hidden="true"></i>&nbsp;&nbsp;Changelog</a>';
}
} else
{
echo $lang->get('update_version_current_new');
}
//Check for App-Updates
foreach ($apps->getApps() as $appdir => $app)
{
if(isset($app['app_build']))
{
$nextVersion = $app['app_build'] + 1;
$foundNewVersion = false;
$hasChangelog = false;
foreach ($MCONF['update_uri'] as $update_server)
{
$updateUrl = $update_server . 'apps/' . str_replace(' ', '-', $app['app_name']) . '/v' . $nextVersion;
if (remote_file_exists($updateUrl . '/version.json'))
{
$version_remote = json_decode(file_get_contents($updateUrl . '/version.json'));
if ($version_remote->versionNum > $app['app_build'])
{
$foundNewVersion = true;
//Check for Changelog
if (remote_file_exists($updateUrl . '/changelog.md'))
{
$hasChangelog = $update_server;
}
}
}
}
if ($foundNewVersion)
{
echo '<br/>'.sprintf($lang->get('update_app_update_available'), $app['app_name'], $version_remote->version). ' <a href="update.php?update&appUpdate='.urlencode($appdir).'" class="button">' . $lang->get('update_title') . '</a>';
if ($hasChangelog !== false)
{
echo '<a href="update.php?showChangelog&app='.str_replace(' ', '-', $app['app_name']).'&server=' . urlencode($hasChangelog) . '&v=' . $nextVersion . '" class="button"><i class="fa fa-list-alt" aria-hidden="true"></i>&nbsp;&nbsp;Changelog</a>';
}
}
}
}
}
exit;
}
@ -92,29 +53,15 @@ if (isset($_GET['showChangelog']))
echo '<div class="main">';
if (hasPerm('update'))
{
if(isset($_GET['server']))
if(isset($_GET['url']))
{
//If we want to see the changelog for an app, we need to look in a different directory
$remoteSubDir = 'System';
if(isset($_GET['app']))
{
$remoteSubDir = 'apps/'.$_GET['app'];
}
if (isset($_GET['v']))
{
if (remote_file_exists(urldecode($_GET['server']) . $remoteSubDir . '/v' . $_GET['v'] . '/changelog.md'))
{
$Parsedown = new Parsedown();
echo $Parsedown->text(file_get_contents(urldecode($_GET['server']) . $remoteSubDir . '/v' . $_GET['v'] . '/changelog.md'));
}
} else
{
echo 'Missing Version.';
}
$parsedown = new Parsedown();
$change = $update->getChangelog(urldecode($_GET['url']));
echo $parsedown->parse($change);
}
else
{
echo 'Missing Server';
echo 'Missing Url';
}
} else
{
@ -131,8 +78,108 @@ if (isset($_GET['update']))
printHeader($lang->get('update_title'));
if (hasPerm('update'))
{
//Check for newer Version
try
{
$new = $update->checkUpdateAvailable();
} catch (\Exception $e)
{
echo 'Error. ' . $e->getMessage();
}
// Update if we have one
if(isset($new))
{
//Check writing permissions
if($update->updateFolderIsWritable())
{
// Download the update
if ($update->downloadUpdate($new))
{
// Check downloaded update file
if($update->verifyUpdate($new))
{
// Put the site in "under construction mode"
if (copy('../content/.system/construction2.txt', '../content/.system/construction.txt'))
{
stream_message('{user} put the site into construction mode.', 2);
// Create a backup
if($update->backupUpdateFolder())
{
// The actual update
try
{
$update->rollTheUpdate();
}
catch (\Exception $e)
{
echo msg('fail', $lang->get('update_fail_unzip'). ' ('.$e->getMessage().')');
}
// Execute migrations
$update->migrate();
// Clean afterwards
if($update->cleanup())
{
// Update new Version in Config file
$conf = \Symfony\Component\Yaml\Yaml::parse(file_get_contents('../config.yml'));
$conf['Versioning']['version'] = $update->getCurrentVersion();
$configfile = \Symfony\Component\Yaml\Yaml::dump($CONFIG);
if (file_put_contents('../config/config.yml', $configfile))
{
// Disable Construction mode
if (unlink('../content/.system/construction.txt'))
{
echo msg('success', $lang->get('update_succss') . ' <a href="general_config.php">' . $lang->get('back') . '</a>');
stream_message('{user} updated the System.', 2);
stream_message('{user} put the site into production mode.', 2);
}
else
{
echo msg('success', $lang->get('action_construction_removed_error'));
}
}
}
else
{
echo msg('fail', $lang->get('update_cleanup_error'));
}
}
else
{
echo msg('fail', $lang->get('update_create_backup_error'));
}
} else
{
echo msg('fail', $lang->get('action_construction_error'));
}
}
else
{
echo msg('fail', $lang->get('update_wrong_hash'));
}
}
else
{
echo msg('fail', $lang->get('update_fail_copy'));
}
}
else
{
echo msg('fail', $lang->get('update_folder_not_writeable'));
}
}
else
{
echo msg('info', $lang->get('update_version_current_new'));
}
/*
$updated = false;
foreach ($MCONF['update_uri'] as $update_server)
foreach ($MCONF['update_servers'] as $update_server)
{
$nextVersion = $MCONF['version_num'] + 1;
$installedVersion = $MCONF['version_num'];
@ -252,6 +299,7 @@ if (isset($_GET['update']))
{
echo msg('info', $lang->get('update_version_current_new'));
}
*/
}
require_once '../inc/footer.php';
}

0
composer.json Normal file → Executable file
View File

View File

@ -50,7 +50,7 @@ $MCONF['tpl_webUri'] = $config['Templating']['tpl_webUri'];
//Versioning
$MCONF['version'] = $config['Versioning']['version'];
$MCONF['version_num'] = $config['Versioning']['version_num'];
$MCONF['update_uri'] = $config['Versioning']['update_uri'];
$MCONF['update_servers'] = $config['Versioning']['update_servers'];
//Mailer
$MCONF['smtp'] = $config['Mail']['smtp'];

58
inc/libs/updater.php Normal file → Executable file
View File

@ -12,8 +12,22 @@ class updater
private $updateServer;
private $updateDir;
/**
* Every file/folder, including subdirectories which should not be updated or deleted after the update.
* @var string
*/
public $thingsToNotUpdate;
public function __construct()
{
// Bypass memory error
ini_set('memory_limit', '-1');
// Bypass Max execution time
set_time_limit(0);
}
/**
* Sets the server to use. Can be an array, in this case it will loop through all servers and check if there is an update
* @param $server
@ -40,7 +54,7 @@ class updater
public function setCurrentVersion($version)
{
// Check if version string is properly formatted
if (preg_match('[0-9]+\.[0-9]+\.[0-9]+', $version))
if (preg_match('/[0-9]+\.[0-9]+\.[0-9]+/', $version))
{
$this->currentVersion = $version;
} else
@ -77,6 +91,7 @@ class updater
$updateInfos = $this->getNewestVersionFromServer($server);
if (isset($updateInfos))
{
$this->newVersion = $updateInfos['version'];
if (version_compare($updateInfos['version'], $this->currentVersion, '>'))
{
$updateInfos['server'] = $server;
@ -113,13 +128,21 @@ class updater
$updateInfosUrl = $server . 'update.json';
if ($this->remote_file_exists($updateInfosUrl))
{
$updateInfo = json_decode(file_get_contents($updateInfosUrl));
$this->newVersion = $updateInfo['version'];
$updateInfo = json_decode(urldecode(file_get_contents($updateInfosUrl)), true);
return $updateInfo;
}
return null;
}
public function getChangelog($changelogUrl)
{
if($this->remote_file_exists($changelogUrl))
{
return file_get_contents($changelogUrl);
}
return '';
}
//////////////////////////////////
/// Check writing permissions ///
@ -131,18 +154,19 @@ class updater
* @return bool
* @throws \Exception
*/
public function updateFolderIsWritable()
public function updateFolderIsWritable($updateFolder = '')
{
if (is_dir($this->updateDir))
if($updateFolder == '') $updateFolder = $this->updateDir;
if (is_dir($updateFolder))
{
if (is_writable($this->updateDir))
if (is_writable($updateFolder))
{
$objects = scandir($this->updateDir);
$objects = scandir($updateFolder);
foreach ($objects as $object)
{
if ($object != "." && $object != "..")
if (is_dir($object) && $object != "." && $object != ".." && substr($object, 0, 1) != '.')
{
if (!$this->updateFolderIsWritable($this->updateDir . "/" . $object))
if (!$this->updateFolderIsWritable($updateFolder . "/" . $object))
{
return false;
} else
@ -156,7 +180,9 @@ class updater
{
return false;
}
} else
}
if($updateFolder == $this->updateDir && !is_dir($this->updateDir))
{
throw new \Exception('Update folder is not a folder!');
}
@ -200,7 +226,8 @@ class updater
/**
* Creates a backup of the current state to use later in case something goes wrong
* Creates a backup of the current state to use later in case we screw something up later
* @return bool
*/
public function backupUpdateFolder()
{
@ -208,6 +235,13 @@ class updater
$archive = $zippy->create('.update-backup.zip', array(
'folder' => $this->updateDir
), true);
// Check if the creation was successfull
if (file_exists('.update-backup.zip'))
{
return true;
}
return false;
}
@ -236,7 +270,7 @@ class updater
}
/**
* Executes the migration script found in the root update directory
* Executes the migration script if found in the root update directory
*/
public function migrate()
{