add('name', PLUGIN_EVENT_AUTOUPDATE_NAME); $propbag->add('description', PLUGIN_EVENT_AUTOUPDATE_DESC); $propbag->add('stackable', false); $propbag->add('author', 'onli'); $propbag->add('version', '0.4'); $propbag->add('requirements', array( 'serendipity' => '0.8', 'php' => '5.1' )); $propbag->add('event_hooks', array('plugin_dashboard_updater' => true, 'backend_sidebar_entries_event_display_update' => true)); $propbag->add('groups', array('BACKEND_FEATURES')); $this->dependencies = array('serendipity_event_dashboard' => 'keep'); } function generate_content(&$title) { $title = $this->title; } /*function introspect_config_item($name, &$propbag) { }*/ function event_hook($event, &$bag, &$eventData, $addData = null) { global $serendipity; $hooks = &$bag->get('event_hooks'); if (isset($hooks[$event])) { switch($event) { case 'plugin_dashboard_updater': $eventData = '
'; return true; break; case 'backend_sidebar_entries_event_display_update': if (! (serendipity_checkPermission('siteConfiguration') || serendipity_checkPermission('blogConfiguration'))) { return; } $nv = $_REQUEST['serendipity']['newVersion']; ini_set('max_execution_time', 180); #ini_set('memory_limit', '-1'); // extending memory_limit may be prevented by suhosin extension. /* As long scripts are not running within safe_mode they are free to change the memory_limit to whatever value they want. Suhosin changes this fact and disallows setting the memory_limit to a value greater than the one the script started with, when this option is left at 0. A value greater than 0 means that Suhosin will disallows scripts setting the memory_limit to a value above this configured hard limit. This is for example usefull if you want to run the script normaly with a limit of 16M but image processing scripts may raise it to 20M. Edit /etc/php5/conf.d/suhosin.ini and add e.g. suhosin.memory_limit = 512M ... */ echo ''."\n"; $logmsg = ''; $start = microtime(true); $update = $this->fetchUpdate($nv); usleep(1); $time = microtime(true) - $start; $logmsg .= sprintf("In %0.4d seconds run fcn fetchUpdate()\n", $time); // print in readable format 1.2345 if (! empty($update)) { $start = microtime(true); if ($this->verifyUpdate($update, $nv)) { usleep(1); $time = microtime(true) - $start; $logmsg .= sprintf("In %0.4d seconds run fcn verifyUpdate()\n", $time); $start = microtime(true); if ($this->checkWritePermissions($update)) { usleep(1); $time = microtime(true) - $start; $logmsg .= sprintf("In %0.4d seconds run fcn checkWritePermissions()\n", $time); $start = microtime(true); $unpacked = $this->unpackUpdate($nv); usleep(1); $time = microtime(true) - $start; $logmsg .= sprintf("In %0.4d seconds run fcn unpackUpdate()\n", $time); if ($unpacked) { $start = microtime(true); if ($this->checkIntegrity($nv)) { usleep(1); $time = microtime(true) - $start; $logmsg .= sprintf("In %0.4d seconds run fcn checkIntegrity()\n", $time); $start = microtime(true); $copied = $this->copyUpdate($nv); usleep(1); $time = microtime(true) - $start; $logmsg .= sprintf("In %0.4d seconds run fcn copyUpdate()\n", $time); if ($copied) { $start = microtime(true); if (true === $this->cleanTemplatesC($nv) ) { echo ''."\n"; } usleep(1); $time = microtime(true) - $start; $logmsg .= sprintf("In %0.4d seconds run fcn cleanTemplatesC()\n", $time); $this->doUpdate($logmsg); } else { echo 'Copying the files for the update failed
'; } } else { $this->showChecksumErrors($nv); echo ''; } } else { echo 'Unpacking the update failed
'; } } else { $this->showNotWriteable($update); echo ''; } } } return true; break; default: return false; } } else { return false; } } /** * fetch the zip file from server * @param string version * @return string updatepath */ function fetchUpdate($version) { global $serendipity; $url = (string)"http://prdownloads.sourceforge.net/php-blog/serendipity-$version.zip?download"; $update = (string)$serendipity ['serendipityPath'] . 'templates_c/' . "serendipity-$version.zip"; // do we already have it? $done = !file_exists($update) ? @copy($url, $update ) : true; if (! $done) { //try it again with curl if copy was forbidden if (function_exists('curl_init')) { $out = @fopen($file, 'wb'); $ch = @curl_init(); @curl_setopt($ch, CURLOPT_FILE, $out); @curl_setopt($ch, CURLOPT_HEADER, 0); @curl_setopt($ch, CURLOPT_URL, $update); $success = @curl_exec($ch); if ( !$success ) { echo 'Downloading update failed
'; return; } } } echo ''."\n"; return $update; } /** * compare the md5 of downloaded archive with the md5 posted on the downloadpage * @param string updatePath * @param string version * @return boolean */ function verifyUpdate($update, $version) { $url = (string)"http://prdownloads.sourceforge.net/php-blog/serendipity-$version.zip?download"; $updatePage = (string)$this->getPage("http://www.s9y.org/12.html"); $downloadLink = substr($updatePage, strpos($updatePage, $url), 200); $found = array(); // grep the checksum preg_match("/\(MD5: (.*)\)/", $downloadLink, $found); $checksum = $found[1]; $check = md5_file($update); if ($check == $checksum) { return true; } else { echo 'Error. Could not verify the update.
'; return false; } } /** * get file content of updatePage * @param string url * @return page content */ function getPage($url) { $page = file_get_contents($url); if ( empty($page) ) { //try it again with curl if fopen was forbidden if (function_exists('curl_init')) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, "20"); $page = curl_exec($ch); curl_close($ch); } } return $page; } /** * unpack the update to templates_c * @param string version * @return boolean */ function unpackUpdate($version) { global $serendipity; $update = (string)$serendipity['serendipityPath'] . 'templates_c/' . "serendipity-$version.zip"; $updateDir = (string)$serendipity['serendipityPath'] . 'templates_c/' . "serendipity-$version/"; // do we already have it? if (is_dir($updateDir) && is_file($updateDir . '/serendipity/README.markdown')) { return true; } $zip = new ZipArchive; if ($zip->open($update) === true) { // 1.get all filenames apart from the root 'serendipity' $i=1; $files = array(); $name = $zip->getNameIndex($i); while (!empty($name)) { $files[] = $name; $name = $zip->getNameIndex($i); $i+=1; } // 2.extraxt all files to temp $zip->extractTo($updateDir); echo ''."\n"; $zip->close(); } else { return false; } return true; } /** * copy the update from templates_c over the existing files * @param string version * @return boolean */ function copyUpdate($version) { global $serendipity; $update = (string)$serendipity['serendipityPath'] . 'templates_c/' . "serendipity-$version.zip"; $updateDir = (string)$serendipity['serendipityPath'] . 'templates_c/' . "serendipity-$version/"; $zip = new ZipArchive; if ($zip->open($update) === true) { // 1.get all filenames apart from the root 'serendipity' $i=1; $files = array(); $name = $zip->getNameIndex($i); while ( !empty($name) ) { $files[] = $name; $name = $zip->getNameIndex($i); $i+=1; } $zip->close(); // 2. copy them over foreach ($files as $file) { $target = $serendipity['serendipityPath'] . substr($file, 12); if (is_dir($updateDir .$file)) { if (!file_exists($target)) { $success = mkdir($target); } else { $success = true; } } else { $success = @copy($updateDir . $file, $target); } if ( !$success ) { echo "Error copying file to $target"; return false; } } } else { return false; } return true; } /** * check write permissions * @param string updatePath * @return boolean */ function checkWritePermissions($update) { global $serendipity; $zip = new ZipArchive; if ($zip->open($update) === true) { $i=0; $files = array(); $name = $zip->getNameIndex($i); while (!empty($name)) { $files[] = $name; $name = $zip->getNameIndex($i); $i+=1; } foreach ($files as $file) { $target = $serendipity['serendipityPath'] . substr($file, 12); if ( (! is_writable($target)) && file_exists($target) ) { return false; } } } return true; } /** * show not writable * @param string updatePath * @return error */ function showNotWriteable($update) { global $serendipity; $zip = new ZipArchive; if ($zip->open($update) === true) { $i=0; $files = array(); $name = $zip->getNameIndex($i); while (!empty($name)) { $files[] = $name; $name = $zip->getNameIndex($i); $i+=1; } $notWritable = array(); foreach ($files as $file) { $target = $serendipity['serendipityPath'] . substr($file, 12); if ((! is_writable($target)) && file_exists($target) ) { $notWriteable[] = $target; } } } echo 'Unpacking the update failed, because following files were not writeable:
'; echo "Updating failed, because the integrity-test for the following files failed:
'; echo "