<?php
/**
* Wave Framework <http://github.com/kristovaher/Wave-Framework>
* Updater
*
* This script is used to update Wave Framework application. It downloads an archive from specific
* URL and unpacks it in the temporary folder where it will be used by FTP to update all files in
* root folder of the system.
*
* @package Tools
* @author Kristo Vaher <kristo@waher.net>
* @copyright Copyright (c) 2012, Kristo Vaher
* @license GNU Lesser General Public License Version 3
* @tutorial /doc/pages/guide_tools.htm
* @since 1.8.9
* @version 3.7.1
*/
// This initializes tools and authentication
require('.'.DIRECTORY_SEPARATOR.'tools_autoload.php');
// Log is printed out in plain text format
header('Content-Type: text/html;charset=utf-8');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<title>Updater</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width"/>
<link type="text/css" href="style.css" rel="stylesheet" media="all"/>
<link rel="icon" href="../favicon.ico" type="image/x-icon"/>
<link rel="icon" href="../favicon.ico" type="image/vnd.microsoft.icon"/>
<meta content="noindex,nocache,nofollow,noarchive,noimageindex,nosnippet" name="robots"/>
<meta http-equiv="cache-control" content="no-cache"/>
<meta http-equiv="pragma" content="no-cache"/>
<meta http-equiv="expires" content="0"/>
</head>
<body>
<?php
// Pops up an alert about default password
passwordNotification($config['http-authentication-password']);
// Header
echo '<h1>System update</h1>';
echo '<h4 class="highlight">';
foreach($softwareVersions as $software=>$version){
// Adding version numbers
echo '<b>'.$software.'</b> ('.$version.') ';
}
echo '</h4>';
// Nothing has been submitted yet
if(empty($_POST) && empty($_GET)){
echo '<h2>Apply Update</h2>';
// This script only works if Zip and FTP functions are supported
if(extension_loaded('Zip') && extension_loaded('ftp')){
?>
<form method="post" action="" enctype="multipart/form-data">
<p class="bold">Update archive URL:</p>
<input type="text" name="archive_url" value=""/>
<p class="bold">Update archive file upload:</p>
<input type="file" name="archive_file"/>
<p class="bold">FTP directory (this is the directory your system is installed in)</p>
<input type="text" name="ftp_directory" value="/"/>
<p class="bold">FTP username</p>
<input type="text" name="ftp_username" value=""/>
<p class="bold">FTP password</p>
<input type="password" name="ftp_password" value=""/>
<p><input type="submit" value="APPLY UPDATE"/></p>
</form>
<?php
} else {
// required extensions don't seem to be used
echo '<p class="bold">Updater requires Zip and FTP PHP extensions</p>';
}
} elseif(trim($_REQUEST['ftp_username'])!='' && trim($_REQUEST['ftp_password'])!='' && trim($_REQUEST['ftp_directory'])!=''){
// Error encounter flag
$error='';
// This script only works if Zip and FTP functions are supported
if(extension_loaded('Zip') && extension_loaded('ftp')){
// If file has been uploaded then this is used instead of archive URL
if(isset($_FILES['archive_file']) && !empty($_FILES['archive_file']) && $_FILES['archive_file']['error']==0){
// Update archive is moved to temporary directory
if(!move_uploaded_file($_FILES['archive_file']['tmp_name'],'..'.DIRECTORY_SEPARATOR.'filesystem'.DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'update.zip')){
// Error is archive file creation failed
$error='Cannot store update archive to temporary files';
}
} elseif(isset($_REQUEST['archive_url']) && trim($_REQUEST['archive_url'])!=''){
// Since archive URL was set, then system downloads the file
$file=file_get_contents($_REQUEST['archive_url']);
if($file){
// Downloaded file contents are placed in update.zip file in temporary directory
if(!file_put_contents('..'.DIRECTORY_SEPARATOR.'filesystem'.DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'update.zip',$file)){
// Error is archive file creation failed
$error='<p class="bold red">Cannot store update archive to temporary files';
}
} else {
// Error is thrown if downloading failed
$error='Cannot download update archive from '.$_REQUEST['archive_url'];
}
} else {
// Since archive file was not set with URL or uploaded file, system throws an error
$error='Update archive was not uploaded or found';
}
// Only continues if no error has been encountered
if($error==''){
// Zip is used to unpack the update archive
$zip=new ZipArchive;
// Opening the previously created archive
if($zip->open('..'.DIRECTORY_SEPARATOR.'filesystem'.DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'update.zip')){
// This is the directory where update archive contents will be unpacked
$updateArchiveDirectory='..'.DIRECTORY_SEPARATOR.'filesystem'.DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'update-'.date('Y-m-d-H-i-s').DIRECTORY_SEPARATOR;
// If cache folder does not exist, it is created
if(!is_dir($updateArchiveDirectory)){
if(!mkdir($updateArchiveDirectory,0755)){
$error='Cannot create update folder';
}
}
// Only continues if no error has been encountered
if($error==''){
// Archive is unpacked
if($zip->extractTo($updateArchiveDirectory)){
// Testing if the update archive version is new or not
if(file_exists($updateArchiveDirectory.'.version')){
// Default version numbers
$updateVersions=array();
// Loading data from version file to array
$versionsRaw=explode("\n",str_replace("\r",'',file_get_contents($updateArchiveDirectory.'.version')));
foreach($versionsRaw as $ver){
// Versions are separated by colon in the version file
$thisVersion=explode(':',$ver);
$updateVersions[$thisVersion[0]]=$thisVersion[1];
}
// This tests if new version numbers are good for this update
$versionValid=true;
// Comparing Wave Framework version numbers
if(!isset($updateVersions['www']) || version_compare($updateVersions['www'],$softwareVersions['www'])==-1){
$versionValid=false;
}
// Comparing system version numbers
if(!isset($updateVersions['system']) || version_compare($updateVersions['system'],$softwareVersions['system'])==-1){
$versionValid=false;
}
// Note that API version numbers are never compared due to technically being API specifications
// This means that system version numbers apply to API as well.
// Making sure that update archive version numbers are at least equal to current installations version numbers
if($versionValid){
// Connecting to localhost FTP
$ftpConnection=ftp_connect('localhost');
// If connection is a success
if($ftpConnection){
// If log-in with provided authentication is a success
if(ftp_login($ftpConnection,$_REQUEST['ftp_username'],$_REQUEST['ftp_password'])){
// This attempts to change current FTP connection to installation directory
if(ftp_chdir($ftpConnection,$_REQUEST['ftp_directory'])){
// Assigning current FTP directory
$ftpDirectory=$_REQUEST['ftp_directory'];
// Making sure that FTP directory ends in slash
$lastCharacter=strrev($ftpDirectory);
if($lastCharacter[0]!=DIRECTORY_SEPARATOR){
$ftpDirectory.=DIRECTORY_SEPARATOR;
}
// This is the directory where files are
$ftpUpdateDirectory=$ftpDirectory.'filesystem/tmp/update/';
// Installation directory contents
$directoryContents=ftp_nlist($ftpConnection,'.');
// This checks if .version file exists in this directory and is the same size as the current installation and has been modified at the same time
if(in_array('.version',$directoryContents) && ftp_size($ftpConnection,'.version')==filesize('..'.DIRECTORY_SEPARATOR.'.version') && ftp_mdtm($ftpConnection,'.version')==filemtime('..'.DIRECTORY_SEPARATOR.'.version')){
// Target archive of the backup
$backupFilename='system-backup-'.date('Y-m-d-H-i-s').'.zip.tmp';
// This creates a backup of all core files, if this fails then updater will not continue
if(systemBackup('../','..'.DIRECTORY_SEPARATOR.'filesystem'.DIRECTORY_SEPARATOR.'backups'.DIRECTORY_SEPARATOR.$backupFilename)){
// This stores log messages
$log=array();
// Since backup was successful
$log[]='SYSTEM BACKUP SAVED TO /filesystem/backups/'.$backupFilename;
// Scanning the unpacked archive directory
$files=scandir($updateArchiveDirectory);
// Notice that files were updated
$log[]='INSTALLING UPDATE FILES';
// This will loop over all the files if files were found in this directory
if(!empty($files)){
$log=array_merge($log,ftpFileMover($ftpConnection,$ftpUpdateDirectory,$ftpDirectory));
}
// Notice that files were updated
$log[]='INSTALLATION COMPLETE';
// If uploader also uploaded an updater script then this is executed and then removed
if(file_exists('../www-updater.php')){
// Log message for updater script
$log[]='EXECUTING UPDATER SCRIPT';
// Building software version string
$softwareVersionString=array();
foreach($softwareVersions as $software=>$version){
$softwareVersionString[]=$software.'-version='.$version;
}
// This is the URL that needs to be executed for update to complete
$updateScriptAddress=((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS']==1 || $_SERVER['HTTPS']=='on'))?'https':'http').'://'.$_SERVER['SERVER_NAME'].'/www-updater.php?'.implode('&',$softwareVersionString);
// Request is made with file get contents, so allow_url_fopen must be enabled
if(function_exists('ini_get') && ini_get('allow_url_fopen')==1){
// Script is executed over HTTP
$updaterScript=file_get_contents($updateScriptAddress);
// If updater script was a success
if($updaterScript){
// Adding log messages from updater script
$log=array_merge($log,explode("\n",$updaterScript));
// Successful log message for updater script
$log[]='UPDATER SCRIPT COMPLETE';
// Removing updater script
ftp_delete($ftpConnection,$ftpDirectory.'www-updater.php');
} else {
// Failed log message for updater script
$log[]='UPDATER SCRIPT FAILED, PLEASE RUN '.$updateScriptAddress.' MANUALLY AND THEN DELETE THE FILE';
}
} else {
// Failed log message for updater script
$log[]='CANNOT MAKE URL REQUESTS, PLEASE RUN '.$updateScriptAddress.' MANUALLY AND THEN DELETE THE FILE';
}
}
// Printing out plain-text log
echo '<p>';
echo implode('</p><p>',$log);
echo '</p>';
// Notice that files were updated
echo '<p class="bold">UPDATE COMPLETE</p>';
} else {
// Backup creation failed
echo '<p class="bold red">Cannot create backup, update halted</p>';
}
} else {
// This is shown when the installation directory given is different based on .version file information
echo '<p class="bold red">Incorrect installation directory</p>';
}
} else {
// This is thrown when FTP cannot move its directory
echo '<p class="bold red">Cannot move to installation directory</p>';
}
} else {
// This is thrown when FTP authentication fails
echo '<p class="bold red">Cannot log-in to FTP</p>';
}
// Closing FTP connection
ftp_close($ftpConnection);
} else {
// This is thrown when localhost FTP connection does not work
echo '<p class="bold red">Cannot connect to localhost with FTP</p>';
}
} else {
// Error message
echo '<p class="bold red">Update archive version numbers are too old for current installation</p>';
}
} else {
// Error message
echo '<p class="bold red">Update archive version number information is missing</p>';
}
// Cleaning the update directory and removing the directory
dirCleaner($updateArchiveDirectory,time());
rmdir($updateArchiveDirectory);
} else {
// This is thrown when it was not possible to unpack the archive
echo '<p class="bold red">Cannot unpack archive</p>';
}
// Zip class is closed as the file is not used anymore
$zip->close();
// Archive file is removed
unlink('..'.DIRECTORY_SEPARATOR.'filesystem'.DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'update.zip');
} else {
echo '<p class="bold red">'.$error.'</p>';
}
} else {
// Since opening archive fails, the file is removed and error is thrown
unlink('..'.DIRECTORY_SEPARATOR.'filesystem'.DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'update.zip');
echo '<p class="bold red">Cannot open archive</p>';
}
} else {
echo '<p class="bold red">'.$error.'</p>';
}
} else {
// required extensions don't seem to be used
echo '<p class="bold red">Updater requires Zip and FTP PHP extensions</p>';
}
} else {
// Error is thrown if downloading failed
echo '<p class="bold red">FTP authentication is required</p>';
}
// Footer
echo '<p class="footer small bold">Generated at '.date('d.m.Y h:i').' GMT '.date('P').' for '.$_SERVER['HTTP_HOST'].'</p>';
?>
</body>
</html>
|