'; echo GetMessages(); echo $this->contentBuffer; echo ''; } function __construct($process='page'){ $this->GetData(); //called from admin_tools.php if( $process == 'embededcheck' ){ $this->DoRemoteCheck(); header('content-type: image/gif'); echo base64_decode('R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='); // send 1x1 transparent gif die(); } ob_start(); $this->Run(); $this->contentBuffer = ob_get_clean(); } function Run(){ if( !$this->CheckPHP() ){ echo $this->output_phpcheck; return; } $cmd = \gp\tool::GetCommand(); $show = true; switch($cmd){ case 'checkremote': $this->DoRemoteCheck(true); break; case 'update'; if( gp_remote_update && $this->UpdateCMS() ){ $show = false; } break; } if( $show ){ $this->ShowStatus(); echo '

Status

'; $this->CheckStatus(); echo $this->output_phpcheck; } } /** * $update_data['packages'][id] = array() * * array['id'] = id of addon (unique across all types), "core" if type is "core" * array['type'] = [core,plugin,theme] * array['md5'] = expected md5 sum of zip file * array['file'] = file on local system * array['version'] = version of the package * */ function GetData(){ $this->data_timestamp = \gp\admin\Tools::VersionData($update_data); $this->update_data = $update_data; if( isset($this->update_data['packages']['core']) ){ $this->core_package =& $this->update_data['packages']['core']; } } function CheckPHP(){ global $dataDir, $langmessage; ob_start(); $passed = true; echo ''; echo ''; // RemoteGet echo ''; //root installation echo ''; echo '
'; echo $langmessage['Test']; echo ''; echo $langmessage['Value']; echo ''; echo $langmessage['Expected']; echo '
'; echo 'RemoteGet'; echo ''; if( \gp\tool\RemoteGet::Test() !== false ){ echo ''.$langmessage['True'].''; }else{ $passed = false; echo ''.$langmessage['False'].''; } echo ''; echo $langmessage['True']; echo '
'; echo 'Root Installation'; echo ''; if( !defined('multi_site_unique') ){ echo ''.$langmessage['True'].''; }else{ echo ''.$langmessage['False'].''; if( gpdebug ){ msg('This feature is not normally available in a multi-site installation. It is currently accessible because gpdebug is set to true. Continuing is not recommended.'); }else{ $passed = false; } } echo ''; echo $langmessage['True']; echo '
'; if( !$passed ){ echo '
'; echo $langmessage['Server_isnt_supported']; echo '
'; } $this->output_phpcheck = ob_get_clean(); return $passed; } function CheckStatus(){ global $langmessage; $diff = time() - $this->data_timestamp; if( $this->data_timestamp > 0 ){ echo '

'; echo sprintf($langmessage['Software_updates_checked'],\gp\tool::date($langmessage['strftime_datetime'],$this->data_timestamp)); echo '

'; } //one hour old if( $diff > 3600 ){ echo '

'; echo ''.$langmessage['Check Now'].''; echo '

'; } } function DoRemoteCheck($ForceCheck = false){ global $langmessage; $diff = time() - $this->data_timestamp; //604800 one week if( !$ForceCheck && ($diff < 604800) ){ return; } if( !$this->DoRemoteCheck2() ){ msg($langmessage['check_remote_failed']); }else{ msg($langmessage['check_remote_success']); $this->data_timestamp = time(); } \gp\admin\Tools::VersionData($this->update_data); } /** * Update available package information * */ function DoRemoteCheck2(){ global $config, $dataDir; $path = \gp\tool::IdUrl(); //add any locally available themes with addon ids $dir = $dataDir.'/themes'; $themes = scandir($dir); $theme_ids = array(); foreach($themes as $name){ if( $name == '.' || $name == '..' ){ continue; } $full_dir = $dir.'/'.$name; if( !is_dir($full_dir) ){ continue; } $templateFile = $full_dir.'/template.php'; $ini_file = $full_dir.'/Addon.ini'; if( !file_exists($templateFile) ){ continue; } $ini_info = array(); if( file_exists($ini_file) ){ $ini_info = \gp\tool\Ini::ParseFile($ini_file); } if( isset($ini_info['Addon_Unique_ID']) ){ $theme_ids[] = $ini_info['Addon_Unique_ID']; } } $theme_ids = array_unique($theme_ids ); if( count($theme_ids) ){ $path .= '&th='.implode('-',$theme_ids ); } //get data $result = \gp\tool\RemoteGet::Get_Successful($path); if( !$result ){ $this->msg(\gp\tool\RemoteGet::Debug('Sorry, data not fetched')); return false; } //zipped data possible since 4.1 /* if( function_exists('gzinflate') ){ $temp = gzinflate($result); if( $temp ){ $result = $temp; } } */ $result = trim($result); $array = json_decode($result, true); //json since 4.1 if( !is_array($array) ){ $debug = array(); $debug['Type'] = gettype($array); $debug['json_last_error'] = json_last_error(); $debug['Two'] = substr($result,0,20); $this->msg(\gp\tool\RemoteGet::Debug('Sorry, data not fetched',$debug)); return false; } if( !$array ){ $debug = array(); $debug['Count'] = count($array); $debug['Two'] = substr($result,0,20); $this->msg(\gp\tool\RemoteGet::Debug('Sorry, data not fetched',$debug)); return false; } $this->update_data['packages'] = array(); foreach($array as $info){ $id =& $info['id']; if( !is_numeric($id) ){ continue; } if( !isset($info['type']) ){ continue; } if( $info['type'] == 'core' ){ $id = 'core'; } $this->update_data['packages'][$id] = $info; } if( isset($this->update_data['packages']['core']) ){ $this->core_package = $this->update_data['packages']['core']; } return true; } function ShowStatus(){ global $langmessage; if( !$this->core_package ){ return; } echo '
'; if( version_compare(gpversion,$this->core_package['version'],'<') ){ echo ''; echo $langmessage['New_version_available']; echo '   '; echo ''; if( gp_remote_update ){ echo ' » '.$langmessage['Update_Now'].' « '; }else{ echo 'Remote Updating is not available'; } echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo '
'.$langmessage['Your_version'].''.gpversion.'
'.$langmessage['New_version'].''.$this->core_package['version'].'
'; }else{ echo $langmessage['UP_TO_DATE']; echo '
'.$langmessage['Your_version']; echo ' '.gpversion; echo '
'; echo '
'; echo \gp\tool::link('',$langmessage['return_to_your_site']); echo '
'; $this->RemoveUpdateMessage(); } echo '
'; } function UpdateCMS(){ global $langmessage; if( !$this->core_package ){ echo $langmessage['OOPS'].' (Core Package Not Set)'; return false; } if( isset($_POST['step']) ){ $this->curr_step = (int)$_POST['step']; } //already up to date? if( ($this->curr_step < 4) && version_compare(gpversion,$this->core_package['version'],'>=') ){ msg($langmessage['UP_TO_DATE']); return false; } //filesystem $filesystem_method = $this->DetectFileSystem(); if( !$filesystem_method ){ msg('Update Aborted: Could not establish a file writing method compatible with your server.'); return false; } $this->Steps(); echo '
'; if( $filesystem_method ){ echo ''; } $step_content = $this->RunStep(); $this->OutputMessages(); echo $step_content; if( $this->FileSystem ){ $this->FileSystem->destruct(); } \gp\admin\Tools::VersionData($this->update_data); //save any changes made by the steps if( !$this->done ){ if( $this->passed ){ echo ''; echo ''; }elseif( $this->curr_step < 3 ){ echo ''; echo ''; }else{ echo ''; echo ''; echo ''; } } echo '
'; return true; } /** * Display the update steps and current * */ protected function Steps(){ global $langmessage; $this->steps[1] = $langmessage['step:prepare']; $this->steps[2] = $langmessage['step:download']; $this->steps[3] = $langmessage['step:unpack']; $this->steps[4] = $langmessage['step:clean']; echo '
'.$langmessage['update_steps'].'
'; echo '
    '; $curr_step_label = ''; foreach($this->steps as $temp_step => $message ){ if( $this->curr_step == $temp_step ){ echo '
  1. '.$message.'
  2. '; $curr_step_label = $message; }elseif( $temp_step < $this->curr_step ){ echo '
  3. '.$message.'
  4. '; }else{ echo '
  5. '.$message.'
  6. '; } } echo '
'; echo '

'.$curr_step_label.'

'; } /** * Run the current step * */ protected function RunStep(){ ob_start(); switch($this->curr_step){ case 4: $this->done = $this->CleanUp(); break; case 3: $this->passed = $this->UnpackAndReplace(); $this->OldFolders(); break; case 2: $this->passed = $this->DownloadSource(); break; case 1: $this->passed = $this->GetServerInfo(); break; } return ob_get_clean(); } /** * Determine how we'll be writing the new code to the server (ftp or direct) * */ function DetectFileSystem(){ global $dataDir; //already determined if( isset($_POST['filesystem_method']) ){ $this->FileSystem = \gp\tool\FileSystem::set_method($_POST['filesystem_method']); if( $this->FileSystem ){ return $_POST['filesystem_method']; } } $this->curr_step = 1; //make sure we don't attempt anything beyond step 1 $context[$dataDir] = 'file'; // Need to be able to write to the dataDir $context[$dataDir . '/include'] = 'file'; // Need to be able to rename or delete the include directory $context[$dataDir . '/themes'] = 'dir'; // These may have user content in them and should not be completely replaced $context[$dataDir . '/addons'] = 'dir'; $this->FileSystem = \gp\tool\FileSystem::init($context); if( !$this->FileSystem ){ return false; } return $this->FileSystem->method; } /** * Remove folders and files that are no longer needed * */ function CleanUp(){ global $langmessage; //delete old folders if( isset($_POST['old_folder']) && is_array($_POST['old_folder']) ){ $this->CleanUpFolders($_POST['old_folder']); } //failed install message if( isset($_POST['failed_install']) ){ $this->msg($langmessage['settings_restored']); echo '

'; echo \gp\tool::link('',$langmessage['return_to_your_site']); echo '     '; echo ''.$langmessage['try_again'].''; echo '

'; return true; } //delete zip file if( !empty($this->core_package['file']) && file_exists($this->core_package['file']) ){ unlink($this->core_package['file']); } $this->msg($langmessage['settings_restored']); $this->msg($langmessage['software_updated']); echo '

'; echo \gp\tool::link('','» '.$langmessage['return_to_your_site']); echo '

'; return true; } /** * Delete folders * */ function CleanUpFolders($folders){ global $langmessage; if( !$this->FileSystem->connect() ){ $this->msg($langmessage['OOPS'].' (not connected)'); return false; } $not_deleted = array(); $this->FileSystem->CleanUpFolders($folders, $not_deleted); if( count($not_deleted) > 0 ){ $this->msg($langmessage['delete_incomplete'].': '.implode(', ',$not_deleted)); return false; } return true; } /** * Remove configuration setting that indicates the CMS is being updated * */ function RemoveUpdateMessage(){ global $config, $langmessage; if( !isset($config['updating_message']) ){ return true; } unset($config['updating_message']); if( !\gp\admin\Tools::SaveConfig(true) ){ return false; } return true; } /** * Replace the /include, /themes and /addons folders * Start by creating the new folders with the new content * Then replace the existing directories with the new directories * */ function UnpackAndReplace(){ global $langmessage, $config, $dataDir; if( !$this->FileSystem->connect() ){ $this->msg($langmessage['OOPS'].': (not connected)'); return false; } try{ if( !$this->UnpackAndSort($this->core_package['file']) ){ return false; } }catch( \Exception $e){ $this->msg($langmessage['error_unpacking'].' (no root)'); return false; } $this->msg('Files Sorted'); $config['updating_message'] = $langmessage['sorry_currently_updating']; if( !\gp\admin\Tools::SaveConfig() ){ $this->msg($langmessage['error_updating_settings']); return false; } $replaced = $this->FileSystem->ReplaceDirs( $this->replace_dirs, $this->extra_dirs ); if( $replaced !== true ){ $this->msg($langmessage['error_unpacking'].' '.$replaced); $this->RemoveUpdateMessage(); return false; } $this->msg($langmessage['copied_new_files']); $this->RemoveUpdateMessage(); return true; } /** * Show which files will be deleted in the cleanup * */ function OldFolders(){ global $langmessage, $dataDir; $dirs = array_merge( array_values($this->replace_dirs), array_values($this->extra_dirs)); $dirs = array_unique( $dirs ); if( count($dirs) == 0 ){ return; } $filesystem_base = $this->FileSystem->get_base_dir(); ob_start(); echo $langmessage['old_folders_created']; echo ''; $this->msg(ob_get_clean()); } /** * Unpack the archive and save the files in temporary folders * @return bool */ function UnpackAndSort($file){ global $langmessage; $archive = new \gp\tool\Archive($file); $archive_root = $archive->GetRoot(); if( is_null($archive_root) ){ $this->msg($langmessage['error_unpacking'].' (no root)'); return false; } $archive_root_len = strlen($archive_root); $archive_files = $archive->ListFiles(); $this->msg($langmessage['package_unpacked']); foreach($archive_files as $file){ if( strpos($file['name'],$archive_root) === false ){ continue; } $rel_filename = substr($file['name'],$archive_root_len); $name_parts = explode('/',trim($rel_filename,'/')); $dir = array_shift($name_parts); $replace_dir = false; switch($dir){ case 'include': $replace_dir = 'include'; $rel_filename = implode('/',$name_parts); break; case 'themes': case 'addons': if( count($name_parts) == 0 ){ continue 2; } $replace_dir = $dir.'/'.array_shift($name_parts); $rel_filename = implode('/',$name_parts); break; } if( $replace_dir === false ){ continue; } $content = $archive->getFromName($file['name']); if( empty($content) ){ continue; } $replace_dir = trim($replace_dir,'/'); if( !isset( $this->replace_dirs[$replace_dir] ) ){ $this->replace_dirs[$replace_dir] = \gp\tool\FileSystem::TempFile( $replace_dir ); } $file_rel = $this->replace_dirs[$replace_dir].'/'.$rel_filename; if( !$this->PutFile( $file_rel, $content ) ){ return false; } } return true; } /** * Use FileSystem to save the file contents so permissions are consistent * */ private function PutFile( $dest_rel, $content ){ global $langmessage; $full = $this->FileSystem->get_base_dir().'/'.trim($dest_rel,'/'); if( !$this->FileSystem->put_contents($full,$content) ){ trigger_error('Could not create file: '.$full); $this->msg($langmessage['error_unpacking'].' (2)'); return true; } return true; } /** * Download the source code * */ function DownloadSource(){ global $langmessage, $dataDir; $this->msg('Downloading version '.$this->core_package['version'].' from '.CMS_READABLE_DOMAIN.'.'); /* for testing * $download = 'http://gpeasy.loc/x_gpEasy.zip'; */ $download = addon_browse_path.'/Special_gpEasy?cmd=download'; $contents = \gp\tool\RemoteGet::Get_Successful($download); if( !$contents || empty($contents) ){ $this->msg($langmessage['download_failed'].'(1)'); return false; } $this->msg($langmessage['package_downloaded']); $md5 = md5($contents); if( $md5 != $this->core_package['md5'] ){ $this->msg($langmessage['download_failed_md5'].'
Downloaded Checksum ('.$md5.') != Expected Checksum ('.$this->core_package['md5'].')'); return false; } $this->msg($langmessage['download_verified']); //save contents $temp_file = $dataDir.\gp\tool\FileSystem::TempFile('/data/_temp/update','.zip'); if( !\gp\tool\Files::Save($temp_file,$contents) ){ $this->msg($langmessage['download_failed'].' (2)'); return false; } $this->core_package['file'] = $temp_file; return true; } /** * Make sure we actuallly have the ability to write to the server using * */ function GetServerInfo(){ global $langmessage; if( $this->FileSystem->connect() ){ $this->DoRemoteCheck2(); //make sure we have the latest information $this->msg($langmessage['ready_for_upgrade']); return true; } if( isset($_POST['connect_values_submitted']) ){ msg($this->FileSystem->connect_msg); } //not connected, show form echo ''; $this->FileSystem->connectForm(); echo '
'; return false; } /** * Add an update message * */ function msg($msg){ $this->update_msgs[] = $msg; } function OutputMessages(){ if( !$this->update_msgs ){ return; } echo ''; } }