public function unpackWith(Unpacker $up) { if (empty($this->fields)) { $this->fields = $up->unpack($this->data); unset($this->data); } return $this->fields; }
/** * Makes sure that the file is a valid template set. The file can be packed * in any of the formats supported by the Unpacker class (.tar.gz, .tar.bz2 * and .zip as of the time of writing these lines) * Returns true if the template is valid or a negative value carrying an * error code. * * @param file The file that contains the template set * @return Returns true (positive value) if template set is ok or a negative * value otherwise. */ function checkTemplateSet($file, $filePath) { // get the temporary folder $config =& Config::getConfig(); $tmpFolder = $config->getValue('temp_folder'); if ($tmpFolder[strlen($tmpFolder) - 1] != '/') { $tmpFolder .= '/'; } // get the name of the file, which we will use in many places $fileNameParts = explode('.', $file); $fileNameNoExt = $fileNameParts[0]; // create our working folder $workFolder = $tmpFolder . File::getTempName() . '/'; if (!File::createDir($workFolder, 0777)) { return TEMPLATE_SANDBOX_ERROR_CREATING_WORKING_FOLDER; } // now we can unpack the file to the temporary folder $unpacker = new Unpacker(); if (!$unpacker->unpack($filePath . $file, $workFolder)) { $this->cleanUp($workFolder . $fileNameNoExt); if (File::exists($workFolder)) { File::delete($workFolder); } return TEMPLATE_SANDBOX_ERROR_UNPACKING; } // if the file was correctly unpacked, now we will need the TemplateValidator // class to do some work for us $fileNameParts = explode('.', $file); $fileNameNoExt = $fileNameParts[0]; // we can use the checkTenmplateFolder which will do all the rest of // the work for us... $res = $this->checkTemplateFolder($fileNameNoExt, $workFolder); if ($res < 0) { //$this->cleanUp( $workFolder.$fileNameNoExt ); $this->cleanUp($workFolder); if (File::isReadable($workFolder) && File::isDir($workFolder)) { File::delete($workFolder); } return $res; } $this->cleanUp($workFolder . $fileNameNoExt); File::delete($workFolder); return true; }
function run($args, $options) { if ($options['dns']) return $this->print_dns(); // Set some forced args and options $temp = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; $stage_path = $temp . 'osticket' . substr(md5('osticket-stage'.getmypid().getcwd()), -8); $args['install-path'] = $stage_path . '/upload'; // Deployment will auto-create the staging area // Ensure that the staging path is cleaned up on exit register_shutdown_function(function() use ($stage_path) { $delTree = function($dir) use (&$delTree) { $files = array_diff(scandir($dir), array('.','..')); foreach ($files as $file) { (is_dir("$dir/$file")) ? $delTree("$dir/$file") : unlink("$dir/$file"); } return rmdir($dir); }; return $delTree($stage_path); }); $options['setup'] = true; $options['git'] = true; $options['verbose'] = true; $options['clean'] = false; $options['dry-run'] = false; $options['include'] = false; $this->_args = $args; $this->_options = $options; // TODO: Run the testing applet first $root = $this->find_root_folder(); if (!$this->getOption('skip-test') && $this->run_tests($root) > 0) $this->fail("Regression tests failed. Cowardly refusing to package"); // Run the deployment // NOTE: The deployment will change the working directory parent::run($args, $options); // Deploy the `setup/scripts` folder to `/scripts` $root = $this->source; Unpacker::unpackage("$root/setup/scripts/{,.}*", "$stage_path/scripts", -1); // Package up the staging area $version = exec('git describe'); switch (strtolower($this->getOption('format'))) { case 'zip': default: $this->packageZip("$root/osTicket-$version.zip", $stage_path); } }
/** * Unpack a db backup file, if necessary * Note: This requires a minimal PEAR setup (incl. Tar and Zip classes) and a * way to set the PEAR include path. But if that doesn't work on your * setup, then chances are you won't get Geeklog up and running anyway ... * * @param string $backupPath path to the "backups" directory * @param string $backupFile backup file name * @param string $display reference to HTML string (for error msg) * @return mixed file name of unpacked file or false: error */ function INST_unpackFile($backupPath, $backupFile, &$display) { global $_CONF, $LANG_MIGRATE; if (!preg_match('/\\.(zip|tar\\.gz|tgz)$/i', $backupFile)) { // not packed return $backupFile; } require_once $_CONF['path'] . 'systems/classes/Autoload.php'; Geeklog\Autoload::initialize(); $archive = new Unpacker($backupPath . $backupFile); // we're going to extract the first .sql file we find in the archive $dirName = ''; $foundSqlFile = false; $files = $archive->getList(); foreach ($files as $file) { if (!isset($file['folder']) || !$file['folder']) { if (preg_match('/\\.sql$/', $file['filename'])) { $dirName = preg_replace('/\\/.*$/', '', $file['filename']); $foundSqlFile = true; break; } } } if (!$foundSqlFile) { // no .sql file found in archive $display .= INST_getAlertMsg(sprintf($LANG_MIGRATE[40], $backupFile)); return false; } if (isset($file) && $dirName === $file['filename']) { $dirName = ''; // no directory } if (empty($dirName)) { $unpacked_file = $file['filename']; } else { $unpacked_file = substr($file['filename'], strlen($dirName) + 1); } $success = $archive->unpack($backupPath, array($file['filename'])); if (!$success || !file_exists($backupPath . $unpacked_file)) { // error unpacking file $display .= INST_getAlertMsg(sprintf($LANG_MIGRATE[41], $unpacked_file)); return false; } unset($archive); return $unpacked_file; }
function unpackage($folder, $destination, $recurse=0, $exclude=false) { $use_git = $this->getOption('git', false); if (!$use_git) return parent::unpackage($folder, $destination, $recurse, $exclude); // Attempt to read from git using `git ls-files` for deployment if (substr($destination, -1) !== '/') $destination .= '/'; $source = $this->source; if (substr($source, -1) != '/') $source .= '/'; $local = str_replace(array($source, '{,.}*'), array('',''), $folder); $pipes = array(); $patterns = array(); foreach ((array) $exclude as $x) { $patterns[] = str_replace($source, '', $x); } $X = implode(' --exclude-per-directory=', $patterns); chdir($source.$local); if (!($files = proc_open( "git ls-files -zs --exclude-standard --exclude-per-directory=$X -- .", array(1 => array('pipe', 'w')), $pipes ))) { return parent::unpackage($folder, $destination, $recurse, $exclude); } $dryrun = $this->getOption('dry-run', false); $verbose = $this->getOption('verbose') || $dryrun; while ($line = stream_get_line($pipes[1], 255, "\x00")) { list($mode, $hash, , $path) = preg_split('/\s+/', $line); $src = $source.$local.$path; if ($this->exclude($exclude, $src)) continue; if (!$this->isChanged($src, $hash)) continue; $dst = $destination.$path; if ($verbose) $this->stdout->write($dst."\n"); if ($dryrun) continue; if (!is_dir(dirname($dst))) mkdir(dirname($dst), 0755, true); $this->copyFile($src, $dst, $hash, octdec($mode)); } }
/** * installs an uploaded template */ function _performUploadTemplate() { // handle the uploaded file $files = HttpVars::getFiles(); $uploads = new FileUploads($files); if (count($files) == 0 || $files["templateFile"]["name"] == "") { $this->_view = new AdminTemplatedView($this->_blogInfo, "newglobaltemplate"); $this->_view->setValue("templateFolder", TemplateSetStorage::getBaseTemplateFolder()); $this->_view->setErrorMessage($this->_locale->tr("error_must_upload_file")); $this->setCommonData(); return false; } $config =& Config::getConfig(); $tmpFolder = $config->getValue('temp_folder'); // move it to the temporary folder $result = $uploads->process($tmpFolder); // and from there, unpack it $upload = new FileUpload($files['templateFile']); $templateSandbox = new TemplateSandbox(); $valid = $templateSandbox->checkTemplateSet($upload->getFileName(), $tmpFolder . '/'); if ($valid < 0) { $this->_view = new AdminSiteTemplatesListView($this->_blogInfo); $this->_view->setErrorMessage($this->_checkTemplateSandboxResult($valid)); $this->setCommonData(); return false; } // the template was ok, so then we can proceed and move it to the main // template folder, add it to our array of templates // // :KLUDGE: // // maybe we should simply move the files rather than unpacking the whole // thing again, but this indeed makes things easier! ;) $unpacker = new Unpacker(); $templateFolder = $config->getValue('template_folder'); $fileToUnpack = $tmpFolder . '/' . $upload->getFileName(); if (!$unpacker->unpack($fileToUnpack, $templateFolder)) { $this->_view = new AdminSiteTemplatesListView($this->_blogInfo); $tf = new Textfilter(); $this->_view->setErrorMessage($this->_locale->pr('error_installing_template', $tf->filterAllHtml($upload->getFileName()))); $this->setCommonData(); return false; } // if the template set was installed ok in the template folder, we can record // it as a valid set $ts = new TemplateSetStorage(); $fileParts = explode(".", $upload->getFileName()); $templateName = $fileParts[0]; $ts->addTemplate($templateName); $this->_view = new AdminSiteTemplatesListView($this->_blogInfo); $this->_view->setSuccessMessage($this->_locale->pr('template_installed_ok', $templateName)); $this->setCommonData(); return true; }
function copyFile($src, $dest) { static $short = false; static $version = false; if (substr($src, -4) != '.php') { return parent::copyFile($src, $dest); } if (!$short) { $hash = exec('git rev-parse HEAD'); $short = substr($hash, 0, 7); } if (!$version) { $version = exec('git describe'); } if (!$short || !$version) { return parent::copyFile($src, $dest); } $source = file_get_contents($src); $source = preg_replace(':<script(.*) src="([^"]+)\\.js"></script>:', '<script$1 src="$2.js?' . $short . '"></script>', $source); $source = preg_replace(':<link(.*) href="([^"]+)\\.css"([^/>]*)/?>:', '<link$1 href="$2.css?' . $short . '"$3/>', $source); // Set THIS_VERSION $source = preg_replace("/^(\\s*)define\\s*\\(\\s*'THIS_VERSION'.*\$/m", "\$1define('THIS_VERSION', '" . $version . "'); // Set by installer", $source); // Set GIT_VERSION $source = preg_replace("/^(\\s*)define\\s*\\(\\s*'GIT_VERSION'.*\$/m", "\$1define('GIT_VERSION', '" . $short . "'); // Set by installer", $source); // Disable error display $source = preg_replace("/^(\\s*)ini_set\\s*\\(\\s*'(display_errors|display_startup_errors)'.*\$/m", "\$1ini_set('\$2', '0'); // Set by installer", $source); if (!file_put_contents($dest, $source)) { die("Unable to apply rewrite rules to " . $dest); } return true; }
public function unpackuint($datum, $intmax = PHP_INT_MAX) { return parent::unpackuint($datum, $intmax); }
/** * Handle uploaded plugin * * @return string HTML: redirect or main plugin screen + error message */ function plugin_upload() { global $_CONF, $_TABLES; $retval = ''; $path_admin = $_CONF['path_html'] . substr($_CONF['site_admin_url'], strlen($_CONF['site_url']) + 1) . '/'; $upload_success = false; // If an error occured while uploading the file. $error_msg = plugin_getUploadError($_FILES['plugin']); if (!empty($error_msg)) { $retval .= plugin_main($error_msg); } else { $plugin_file = $_CONF['path_data'] . $_FILES['plugin']['name']; // Name the plugin file $archive = new Unpacker($_FILES['plugin']['tmp_name'], $_FILES['plugin']['type']); $tmp = $archive->getList(); // Grab the contents of the tarball to see what the plugin name is $dirName = preg_replace('/\\/.*$/', '', $tmp[0]['filename']); if (empty($dirName)) { // If $dirname is blank it's probably because the user uploaded a non Tarball file. COM_redirect($_CONF['site_admin_url'] . '/plugins.php?msg=100'); } else { $pi_did_exist = false; // plugin directory already existed $pi_had_entry = false; // plugin had an entry in the database $pi_was_enabled = false; // plugin was enabled if (file_exists($_CONF['path'] . 'plugins/' . $dirName)) { $pi_did_exist = true; // plugin directory already exists $pstatus = DB_query("SELECT pi_name, pi_enabled FROM {$_TABLES['plugins']} WHERE pi_name = '{$dirName}'"); $A = DB_fetchArray($pstatus); if (isset($A['pi_name'])) { $pi_had_entry = true; $pi_was_enabled = $A['pi_enabled'] == 1; } $callback = 'plugin_enablestatechange_' . $dirName; if ($pi_was_enabled) { // disable temporarily while we move the files around if (is_callable($callback)) { changePluginStatus($dirName); } else { DB_change($_TABLES['plugins'], 'pi_enabled', 0, 'pi_name', $dirName); } } $plugin_dir = $_CONF['path'] . 'plugins/' . $dirName; if (file_exists($plugin_dir . '.previous')) { Geeklog\FileSystem::remove($plugin_dir . '.previous'); } if (file_exists($plugin_dir)) { rename($plugin_dir, $plugin_dir . '.previous'); } $public_dir = $_CONF['path_html'] . $dirName; if (file_exists($public_dir . '.previous')) { Geeklog\FileSystem::remove($public_dir . '.previous'); } if (file_exists($public_dir)) { rename($public_dir, $public_dir . '.previous'); } $admin_dir = $path_admin . 'plugins/' . $dirName; if (file_exists($admin_dir . '.previous')) { Geeklog\FileSystem::remove($admin_dir . '.previous'); } if (file_exists($admin_dir)) { rename($admin_dir, $admin_dir . '.previous'); } } /** * Install the plugin * This doesn't work if the public_html & public_html/admin/plugins directories aren't 777 */ // Extract the tarball to data so we can get the $pi_name name from admin/install.php $archive->unpack($_CONF['path'] . 'data/', array($dirName . '/admin/install.php')); $plugin_inst = $_CONF['path'] . 'data/' . $dirName . '/admin/install.php'; $fileData = @file_get_contents($plugin_inst); /* // Remove the plugin from data/ Geeklog\FileSystem::remove($_CONF['path'] . 'data/' . $dirname); */ // Some plugins seem to expect files under the data directory to // be unchanged while they are disabled. Let's leave the files untouched. /** * One time I wanted to install a muffler on my car and * needed to match up the outside diameter of the car's * exhaust pipe to the inside diameter of the muffler. * Unfortunately, when I went to the auto parts store they * didn't have a coupling adapter that would perfectly * match the two pipes, only a bunch of smaller adapters. * I ended up using about 4 small adapters to step down * one size at a time to the size of the muffler's input. * It's kind of like this regular expression: */ $fileData = str_replace(array("\n", ' '), '', $fileData); $pi_name = preg_replace('/^.*\\$pi\\_name=\'/', '', $fileData); $pi_name = preg_replace('/\'.*$/', '', $pi_name); // Some plugins don't have $pi_name set in their install.php file, // This means our regex won't work and we should just use $dirname if (empty($pi_name) || preg_match('/\\<\\?php/', $pi_name) || preg_match('/--/', $pi_name)) { $pi_name = $dirName; } // Extract the uploaded archive to the plugins directory $upload_success = $archive->unpack($_CONF['path'] . 'plugins/'); $plg_path = $_CONF['path'] . 'plugins/' . $pi_name . '/'; if ($upload_success) { if (file_exists($plg_path . 'public_html')) { rename($plg_path . 'public_html', $_CONF['path_html'] . $pi_name); } if (file_exists($plg_path . 'admin')) { rename($plg_path . 'admin', $path_admin . 'plugins/' . $pi_name); } } unset($archive); // Collect some garbage // cleanup when uploading a new version if ($pi_did_exist) { $plugin_dir = $_CONF['path'] . 'plugins/' . $dirName; if (file_exists($plugin_dir . '.previous')) { Geeklog\FileSystem::remove($plugin_dir . '.previous'); } $public_dir = $_CONF['path_html'] . $dirName; if (file_exists($public_dir . '.previous')) { Geeklog\FileSystem::remove($public_dir . '.previous'); } $admin_dir = $path_admin . 'plugins/' . $dirName; if (file_exists($admin_dir . '.previous')) { Geeklog\FileSystem::remove($admin_dir . '.previous'); } if ($pi_was_enabled) { // Enable the plugin again if (is_callable($callback)) { changePluginStatus($dirName); } else { DB_change($_TABLES['plugins'], 'pi_enabled', 1, 'pi_name', $dirName); } } } $msg_with_plugin_name = false; if ($pi_did_exist) { if ($pi_was_enabled) { // check if we have to perform an update $pi_version = DB_getItem($_TABLES['plugins'], 'pi_version', "pi_name = '{$dirName}'"); $code_version = PLG_chkVersion($dirName); if (!empty($code_version) && $code_version != $pi_version) { /** * At this point, we would have to call PLG_upgrade(). * However, we've loaded the plugin's old functions.inc * (in lib-common.php). We can't load the new one here * now since that would result in duplicate function * definitions. Solution: Trigger a reload (with the new * functions.inc) and continue there. */ $url = $_CONF['site_admin_url'] . '/plugins.php' . '?mode=continue_upgrade' . '&codeversion=' . urlencode($code_version) . '&piversion=' . urlencode($pi_version) . '&plugin=' . urlencode($dirName); COM_redirect($url); } else { $msg = 98; // successfully uploaded } } else { $msg = 98; // successfully uploaded } } elseif (file_exists($plg_path . 'autoinstall.php')) { // if the plugin has an autoinstall.php, install it now if (plugin_autoinstall($pi_name)) { PLG_pluginStateChange($pi_name, 'installed'); $msg = 44; // successfully installed } else { $msg = 72; // an error occured while installing the plugin } } else { $msg = 98; // successfully uploaded } $url = $_CONF['site_admin_url'] . '/plugins.php?msg=' . $msg; if ($msg_with_plugin_name) { $url .= '&plugin=' . $dirName; } COM_redirect($url); } } return $retval; }
* the user to select which plugins to install */ case 1: // If 'file_uploads' is enabled in php.ini and the plugin directories are writable by the web server. $upload_enabled = ini_get('file_uploads') && is_writable($_CONF['path'] . 'plugins/') && is_writable($_CONF['path_html']) && is_writable($installer->getAdminPath() . 'plugins/'); $display .= '<p>' . $LANG_PLUGINS[3] . ($upload_enabled ? ' ' . $LANG_PLUGINS[4] : '') . '</p>' . PHP_EOL; // Check if a plugin file was uploaded $upload_success = false; if (isset($_FILES['plugin'])) { if ($error_msg = $installer->getUploadError($_FILES['plugin'])) { // If an error occured while uploading the file. $display .= '<div class="notice"><span class="error">' . $LANG_INSTALL[38] . '</span> ' . $error_msg . '</div>' . PHP_EOL; } else { $plugin_file = $_CONF['path_data'] . $_FILES['plugin']['name']; // Name the plugin file $archive = new Unpacker($_CONF['path_data'] . $_FILES['plugin']['name'], $_FILES['plugin']['type']); $contents = $archive->getList(); $dirName = preg_replace('/\\/.*$/', '', $contents[0]['filename']); if (empty($dirName)) { // If $dirname is blank it's probably because the user uploaded a non Tarball file. $display .= '<div class="notice"><span class="error">' . $LANG_INSTALL[38] . '</span> ' . $LANG_PLUGINS[5] . '</div>' . PHP_EOL; } elseif (file_exists($_CONF['path'] . 'plugins/' . $dirName)) { // If plugin directory already exists $display .= '<div class="notice"><span class="error">' . $LANG_INSTALL[38] . '</span> ' . $LANG_PLUGINS[6] . '</div>' . PHP_EOL; } else { /** * Install the plugin * This doesn't work if the public_html & public_html/admin/plugins directories aren't 777 */ // Extract the archive to data so we can get the $pi_name name from admin/install.php $archive->unpack($_CONF['path'] . 'data/', array($dirName . '/admin/install.php'));
function _performUploadTemplate() { // get the temporary folder $config =& Config::getConfig(); $tmpFolder = $config->getValue("temp_folder"); // move it to the temporary folder $files = HttpVars::getFiles(); if (count($files) == 0 || $files["templateFile"]["name"] == "") { $this->_view = new AdminTemplatedView($this->_blogInfo, "newblogtemplate"); $this->_view->setValue("templateFolder", TemplateSetStorage::getBlogBaseTemplateFolder($this->_blogInfo->getId())); $this->_view->setErrorMessage($this->_locale->tr("error_must_upload_file")); $this->setCommonData(); return false; } $uploads = new FileUploads($files); $result = $uploads->process($tmpFolder); if ($result < 0) { $this->_view = new AdminBlogTemplateSetsListView($this->_blogInfo); $this->_view->setErrorMessage($this->_locale->tr("error_uploads_disabled")); $this->setCommonData(); return false; } $upload = new FileUpload($files["templateFile"]); // and make it go through the template sandbox to check if // we're dealing with a 'healthy' file $templateSandbox = new TemplateSandbox(); $valid = $templateSandbox->checkTemplateSet($upload->getFileName(), $tmpFolder . "/"); if ($valid < 0) { $this->_view = new AdminBlogTemplateSetsListView($this->_blogInfo); $this->_view->setErrorMessage(AdminAddTemplateAction::_checkTemplateSandboxResult($valid)); $this->setCommonData(); return false; } // // :KLUDGE: // // maybe we should simply move the files rather than unpacking the whole // thing again, but this indeed makes things easier! ;) // // since it is a local template, the path has to be $template_folder/blog_x/$templateName $ts = new TemplateSetStorage(); $blogTemplateFolder = $ts->createBlogTemplateFolder($this->_blogInfo->getId()); // it should be there now... we can continue $destFolder = $blogTemplateFolder . "/"; $unpacker = new Unpacker(); if (!$unpacker->unpack($tmpFolder . "/" . $upload->getFileName(), $destFolder)) { $this->_view = new AdminBlogTemplateSetsListView($this->_blogInfo); $this->_view->setErrorMessage($this->_locale->tr("error_installing_template")); $this->setCommonData(); // remove the file before returning! File::delete($tmpFolder . "/" . $upload->getFileName()); return false; } // if the template set was installed ok in the template folder, we can record // it as a valid set $fileParts = explode(".", $upload->getFileName()); $templateName = $fileParts[0]; $ts->addTemplate($templateName, $this->_blogInfo->getId()); // remove the file File::delete($tmpFolder . "/" . $upload->getFileName()); $this->_view = new AdminBlogTemplateSetsListView($this->_blogInfo); $this->_view->setSuccessMessage($this->_locale->pr("template_installed_ok", $templateName)); $this->setCommonData(); return true; }