Login   Register  
PHP Classes
elePHPant
Icontem

File: tools/updater.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Kristo Vaher  >  Wave Framework  >  tools/updater.php  >  Download  
File: tools/updater.php
Role: Auxiliary script
Content type: text/plain
Description: Updater Tool
Class: Wave Framework
MVC framework for building Web sites and APIs
Author: By
Last change: Re-implemented system version number and updated versioning documentation. You can also limit API version numbers with API profiles now.
Date: 1 year ago
Size: 14,873 bytes
 

Contents

Class file image Download
<?php

/**
 * Wave Framework <http://www.waveframework.com>
 * 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>