*
* This file is part of NOCC. NOCC is free software under the terms of the
* GNU General Public License. You should have received a copy of the license
* along with NOCC. If not, see .
*
* @package NOCC
* @license http://www.gnu.org/licenses/ GNU General Public License
* @version SVN: $Id: update.php 2610 2016-08-30 08:48:56Z oheil $
*/
require_once './common.php';
$currentdir=getcwd();
try {
$pop = new nocc_imap();
$pop->close();
}
catch (Exception $ex) {
require_once './utils/proxy.php';
Header('Location: ' . $conf->base_url . 'index.php?'.NOCC_Session::getUrlGetSession());
return;
}
require './html/header.php';
require './html/menu_inbox.php';
$state_ok=true;
$start_time=time();
echo '
';
echo '
This section is available only in english.
';
if( $state_ok && ( !isset($_SESSION['auto_update']) || !$_SESSION['auto_update'] ) ) {
echo '
Missing proper rights, contact your system administrator.
';
$state_ok=false;
}
if( $state_ok && ini_get("allow_url_fopen")!=1 ) {
echo '
php.ini "allow_url_fopen" is not set, contact your system administrator.
';
unset($_SESSION['auto_update_new']);
$state_ok=false;
}
if( $state_ok && ( !isset($_SESSION['auto_update_new']) || $_SESSION['auto_update_new']===2 ) ) {
echo '
New NOCC version is undetermined, please try again.
';
unset($_SESSION['auto_update_new']);
$state_ok=false;
}
if( $state_ok && ( !isset($_SESSION['auto_update_new']) || $_SESSION['auto_update_new']===1 ) ) {
echo '
No new NOCC version.
';
$state_ok=false;
}
$nocc_update_running=false;
if( $state_ok && is_file("NOCC_UPDATE_RUNNING") ) {
$nocc_update_running=true;
echo '
Another update process is running!
';
echo '
Please wait some minutes to make sure that a running process can finish.
';
echo '
Then, if possible, delete the file NOCC_UPDATE_RUNNING in your NOCC root directory if it still exists or contact your system administrator.
';
echo '
Go back into NOCC and check if an update is still needed.
';
$state_ok=false;
}
$new_version="undefined";
if( $state_ok ) {
$new_version=$_SESSION['auto_update_new'];
$new_version=str_ireplace("-dev","",$new_version);
$new_v=explode('.',$new_version);
$old_v=explode('.',str_ireplace("-dev","",$conf->nocc_version));
$old_dev_version=false;
if( preg_match("/-dev/",$conf->nocc_version) ) {
$old_dev_version=true;
}
if(
($old_dev_version && $old_v[0]==$new_v[0] && $old_v[1]==$new_v[1] && $old_v[2]<=$new_v[2]) ||
($old_v[0]==$new_v[0] && $old_v[1]==$new_v[1] && $old_v[2]<$new_v[2]) ||
($old_v[0]==$new_v[0] && $old_v[1]<$new_v[1]) ||
($old_v[0]<$new_v[0]) ||
0
) {
echo '
Udate from '.$conf->nocc_version.' to '.$new_version.' possible.
';
}
else {
echo '
No update possible. Current version: '.$conf->nocc_version.', new version: '.$new_version.'
';
unset($_SESSION['auto_update_new']);
$state_ok=false;
}
}
if( $state_ok ) {
echo '
Your version is: '.$conf->nocc_version.', Updating to version: '.$new_version.'
';
echo '
Checking environment
';
$nocc_root=dirname(__FILE__);
chdir($nocc_root);
if( is_writable(".") ) {
echo '
NOCC root directory is writable.
';
}
else {
echo '
NOCC root directory is not writable.
';
$state_ok=false;
}
$target_extract_dir="nocc-".$new_version;
if( ! file_exists($target_extract_dir) ) {
echo '
Directory '.$target_extract_dir.' does not exist. Good.
';
}
else {
echo '
Directory '.$target_extract_dir.' should not exist.
';
$state_ok=false;
}
if( strncasecmp(PHP_OS,"win",3)==0 ) {
if( defined("ZIPARCHIVE::CREATE") ) {
echo '
ZipArchive extension exists.
';
}
else {
echo '
ZipArchive extension missing.
';
$state_ok=false;
}
}
if( defined("Phar::TAR") && Phar::TAR==2 && defined("Phar::ZIP") && Phar::ZIP==3 ) {
echo '
Phar extension exists.
';
}
else {
echo '
Phar extension missing.
';
$state_ok=false;
}
try {
$file_list=array(
'action.php',
'ckeditor.php',
'ckeditor5.php',
//'ckeditor_php4.php',
//'ckeditor_php5.php',
'addcgipath.sh',
'common.php',
'contacts_manager.php',
'contacts.php',
'delete.php',
'download.php',
'down_mail.php',
'favicon.ico',
'get_img.php',
'help.php',
'index.php',
'logout.php',
'robots.txt',
'rss.php',
'send.php',
'update.php'
);
$file_list=array_merge($file_list,recursive_directory("htmlpurifier","/^.*(?getMessage());
require './html/error.php';
$state_ok=false;
}
foreach($file_list as $file) {
if( file_exists($file) && ! is_writable($file) ) {
if( is_file($file) ) {
echo '
File '.$file.' is not writable!
';
}
else if( is_dir($file) ) {
echo '
Folder '.$file.' is not writable!
';
}
else {
echo '
File '.$file.' can not be checked for being writable!
';
}
$state_ok=false;
}
}
$number_of_files=count($file_list);
if( $state_ok ) {
echo '
All '.$number_of_files.' files are writable.
';
}
$max_execution_time=ini_get("max_execution_time");
$end_time=time();
$diff_time=$end_time-$start_time;
if( $diff_time >= 1 ) {
echo '
Environment check took '.$diff_time.' seconds.
';
}
else {
$diff_time=1;
echo '
Environment check took less than 1 second.
';
}
$min_execution_time=30*$diff_time+60;
if( $max_execution_time>$min_execution_time ) {
echo '
Your php max_execution_time of '.$max_execution_time.' seconds seems to be sufficient.
';
}
else {
echo '
Your php max_execution_time of '.$max_execution_time.' could be to small. Please consider setting the php max_execution_time to at least '.($min_execution_time+20).' seconds.';
echo '
';
$state_ok=false;
}
}
if( ! isset($_GET['doUpdate']) || $_GET['doUpdate']!=1 ) {
if( $state_ok ) {
//creating zip files with Phar has performance issues under windows
if( strncasecmp(PHP_OS,"win",3)==0 ) {
$archive_name="nocc-".$conf->nocc_version."_backup_".date("YmdHis").".zip";
}
else {
$archive_name="nocc-".$conf->nocc_version."_backup_".date("YmdHis").".tar.gz";
}
//unpacking zip file with Phar does not work on windows
if( strncasecmp(PHP_OS,"win",3)==0 ) {
$download_link='http://downloads.sourceforge.net/project/nocc/NOCC/'.$new_version.'/nocc-'.$new_version.'.zip';
}
else {
$download_link='http://downloads.sourceforge.net/project/nocc/NOCC/'.$new_version.'/nocc-'.$new_version.'.tar.gz';
}
echo '
';
echo '
Change Log:
';
$news=file_get_contents('http://nocc.sourceforge.net/docs/NEWS?v='.$conf->nocc_version);
echo '
';
echo '
What will happen:
';
echo '
Backup:';
echo '';
echo '- Your old NOCC files will be saved as archive in your NOCC root directory.
';
echo '- The archive file name will have the current date and time, e.g.: '.$archive_name.'
';
echo '- The file config/conf.php and .htaccess files will NOT be part of this archive.
';
echo '- You can download the archive or move it on the server to some place you wish.
';
echo '- If you need to go back just unpack the archive in your NOCC root directory overwriting the existing files.
';
echo '
';
echo 'Update:';
echo '';
echo '- The latest NOCC version will be downloaded automatically from the projects web site: '.$download_link.'
';
echo '- The MD5 or SHA256 checksum will be checked.
';
echo '- The downloaded distribution archive will be unpacked overwriting your existing files.
';
echo '
';
}
else {
echo 'Automatic update not possible.
';
}
}
else {
error_log('NOCC: user <'.$_SESSION['nocc_user'].'@'.$_SESSION['nocc_domain'].'> initiated system update');
if( $state_ok ) {
if( $nocc_update_running ) {
$state_ok=false;
}
else {
$step=0;
file_put_contents("NOCC_UPDATE_RUNNING",$step);
}
}
if( $state_ok ) {
echo 'Creating backup
';
try {
//creating zip files with Phar has performance issues under windows
if( strncasecmp(PHP_OS,"win",3)==0 ) {
$archive_name="nocc-".$conf->nocc_version."_backup_".date("YmdHis").".zip";
echo '
Creating backup file: '.$archive_name.'
';
//$archive=new PharData($archive_name,FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO,"",Phar::ZIP);
$archive=new ZipArchive();
$archive->open($archive_name,ZIPARCHIVE::CREATE);
foreach($file_list as $file) {
if( is_dir($file) ) {
//$number_of_files--;
$archive->addEmptyDir($file);
}
else {
$archive->addFile($file);
}
}
//unset($archive);
$archive->close();
$archive=new PharData($archive_name);
$number_of_files_check=$archive->count();
unset($archive);
if( $number_of_files==$number_of_files_check ) {
echo '
Created archive of '.$number_of_files_check.' files successfully: '.$archive_name.'
';
}
else {
echo '
Number of files in '.$archive_name.' is '.$number_of_files_check.', should be '.$number_of_files.'.
';
unlink($archive_name);
$state_ok=false;
}
}
else {
$archive_name="nocc-".$conf->nocc_version."_backup_".date("YmdHis").".tar";
echo '
Creating backup file: '.$archive_name.'
';
$archive=new PharData($archive_name,FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO,"",Phar::TAR);
foreach($file_list as $file) {
//can not add directory name to archive under windows
if( strncasecmp(PHP_OS,"win",3)==0 && is_dir($file) ) {
$number_of_files--;
}
else {
$archive->addFile($file);
}
}
echo '
Compressing archive: '.$archive_name.'.gz
';
//the following fails in php 8.2 with Allowed memory size exhausted
//$archive->compress(Phar::GZ);
//doing it manually:
$gzfile=gzcompressfile($archive_name);
unset($archive);
echo '
Removing file: '.$archive_name.'
';
Phar::unlinkArchive($archive_name);
$archive_name=gzdecompressfile($gzfile);
$archive=new PharData($archive_name);
$number_of_files_check=$archive->count();
unset($archive);
unlink($archive_name);
if( $number_of_files==$number_of_files_check ) {
echo '
Created archive of '.$number_of_files_check.' files successfully: '.$archive_name.'.gz
';
}
else {
echo '
Number of files in '.$archive_name.'.gz is '.$number_of_files_check.', should be '.$number_of_files.'.
';
unlink($archive_name.'.gz');
$state_ok=false;
}
}
}
catch (Exception $ex) {
$ev = new NoccException($ex->getMessage());
require './html/error.php';
$state_ok=false;
}
}
if( $state_ok ) {
echo '
Download new version
';
//creating zip files with Phar has performance issues under windows
//unpacking zip file with Phar does not work on windows
if( strncasecmp(PHP_OS,"win",3)==0 ) {
$archive_name='nocc-'.$new_version.'.zip';
$download_link='http://downloads.sourceforge.net/project/nocc/NOCC/'.$new_version.'/nocc-'.$new_version.'.zip';
}
else {
$archive_name='nocc-'.$new_version.'.tar.gz';
$download_link='http://downloads.sourceforge.net/project/nocc/NOCC/'.$new_version.'/nocc-'.$new_version.'.tar.gz';
}
if( ! is_file($archive_name) ) {
$fpc=file_put_contents($archive_name,fopen($download_link,'r'));
if( $fpc!=false ) {
echo '
Downloaded new version archive successful.
';
}
else {
echo '
Downloaded new version archive failed. You can savely try again.
';
$state_ok=false;
}
}
else {
echo '
New version archive already exists, proceeding to checksum.
';
}
}
if( $state_ok ) {
echo '
Checking checksum
';
$ckecksums=file_get_contents('https://nocc.sourceforge.net/checksums.txt');
$checksum="";
$checksumType="";
$matches=array();
if( preg_match("/".$archive_name."\tsha256\t(\S+)\R/",$ckecksums,$matches) ) {
$checksum=$matches[1];
$checksumType="sha256";
}
else if( preg_match("/".$archive_name."\tmd5\t(\S+)\R/",$ckecksums,$matches) ) {
$checksum=$matches[1];
$checksumType="md5";
}
else if( preg_match("/".$archive_name."\t(\S+)\R/",$ckecksums,$matches) ) {
$checksum=$matches[1];
$checksumType="md5";
}
else {
echo '
Could not find checksum. See also http://nocc.sourceforge.net/download/
';
$state_ok=false;
}
if( $checksumType == "md5" ) {
$md5sum_check=md5_file($archive_name);
if( $checksum == $md5sum_check) {
echo '
MD5 checksums match: '.$checksum.'. See also http://nocc.sourceforge.net/download/
';
}
else {
echo '
Failed md5 checksum match: '.$md5sum_check.' should be '.$checksum.'.
';
echo '
See also http://nocc.sourceforge.net/download/
';
$state_ok=false;
}
}
if( $checksumType == "sha256" ) {
$sha256sum_check=hash_file("sha256",$archive_name);
if( $checksum == $sha256sum_check ) {
echo '
sha256 checksums match: '.$checksum.'. See also http://nocc.sourceforge.net/download/
';
}
else {
echo '
Failed sha256 checksum match: '.$sha256sum_check.' should be '.$checksum.'.
';
echo '
See also http://nocc.sourceforge.net/download/
';
$state_ok=false;
}
}
}
if( $state_ok ) {
echo '
Unpacking new version
';
if( strncasecmp(PHP_OS,"win",3)==0 ) {
$archive=new ZipArchive();
$archive->open($archive_name);
$archive->extractTo('.');
$archive->close();
}
else {
//the following fails in php 8.2 with Allowed memory size exhausted
//$archive=new PharData($archive_name);
//doing it manually:
$tar_archive_name=gzdecompressfile($archive_name);
$archive=new PharData($tar_archive_name);
$archive->extractTo('.');
unset($archive);
unlink($tar_archive_name);
}
chdir($target_extract_dir);
$file_list=recursive_directory(".","/^.*(?Failed creating file: '.$file.'.nocc-'.$new_version.'. Try manually.';
}
echo '
Important:
';
echo ' Integrate content of new file '.$file.".nocc-".$new_version.' into '.$file.'
';
}
else {
echo '
New file '.$target_extract_dir.DIRECTORY_SEPARATOR.$file.' and '.$file.' match, nothing to do.
';
}
unlink($target_extract_dir.DIRECTORY_SEPARATOR.$file);
}
else {
if( ! is_dir(dirname($file)) ) {
mkdir(dirname($file),0777,true);
}
if( ! copy($target_extract_dir.DIRECTORY_SEPARATOR.$file,$file) ) {
echo '
Failed to copy file: '.$file.'. Try manually.
';
}
unlink($target_extract_dir.DIRECTORY_SEPARATOR.$file);
}
}
else {
if( is_file($target_extract_dir.DIRECTORY_SEPARATOR.$file) ) {
if( ! is_dir(dirname($file)) ) {
mkdir(dirname($file),0777,true);
}
if( ! copy($target_extract_dir.DIRECTORY_SEPARATOR.$file,$file) ) {
echo '
Failed to copy file: '.$file.'. Try manually.
';
}
unlink($target_extract_dir.DIRECTORY_SEPARATOR.$file);
}
else if( is_dir($target_extract_dir.DIRECTORY_SEPARATOR.$file) ) {
rmdir($target_extract_dir.DIRECTORY_SEPARATOR.$file);
}
}
}
rmdir($target_extract_dir);
}
if( $state_ok ) {
echo '
Removing deprecated files
';
$file_list=array(
'ckeditor_php4.php',
'ckeditor_php5.php',
);
foreach($file_list as $file) {
if( file_exists($file) ) {
if( ! unlink($file) ) {
echo '
Failed to remove deprecated file: '.$file.'. Try manually.
';
}
else {
echo '
File '.$file.' removed.
';
}
}
}
}
$end_time=time();
$diff_time=$end_time-$start_time;
if( ! $state_ok ) {
echo '
Update failed.
';
}
else {
echo '
Update took '.$diff_time.' seconds to finish successfully.';
unset($_SESSION['auto_update_new']);
}
if( ! $nocc_update_running && is_file("NOCC_UPDATE_RUNNING") ) {
unlink("NOCC_UPDATE_RUNNING");
}
}
echo '
';
chdir($currentdir);
require './html/menu_inbox.php';
require './html/footer.php';
// https://stackoverflow.com/questions/6073397/how-do-you-create-a-gz-file-using-php/56140427#56140427
function gzcompressfile(string $inFilename, int $level = 9): string
{
// Is the file gzipped already?
$extension = pathinfo($inFilename, PATHINFO_EXTENSION);
if ($extension == "gz") {
return $inFilename;
}
// Open input file
$inFile = fopen($inFilename, "rb");
if ($inFile === false) {
throw new \Exception("Unable to open input file: $inFilename");
}
// Open output file
$gzFilename = $inFilename.".gz";
$mode = "wb".$level;
$gzFile = gzopen($gzFilename, $mode);
if ($gzFile === false) {
fclose($inFile);
throw new \Exception("Unable to open output file: $gzFilename");
}
// Stream copy
$length = 512 * 1024; // 512 kB
while (!feof($inFile)) {
gzwrite($gzFile, fread($inFile, $length));
}
// Close files
fclose($inFile);
gzclose($gzFile);
// Return the new filename
return $gzFilename;
}
// https://stackoverflow.com/questions/3293121/how-can-i-unzip-a-gz-file-with-php
function gzdecompressfile(string $file_name): string
{
// Raising this value may increase performance
$buffer_size = 4096; // read 4kb at a time
$out_file_name = str_replace('.gz', '', $file_name);
// Open our files (in binary mode)
$file = gzopen($file_name, 'rb');
$out_file = fopen($out_file_name, 'wb');
// Keep repeating until the end of the input file
while(!gzeof($file)) {
// Read buffer-size bytes
// Both fwrite and gzread and binary-safe
fwrite($out_file, gzread($file, $buffer_size));
}
// Files are done, close files
fclose($out_file);
gzclose($file);
return $out_file_name;
}