/** * Get the metadata stored in the PHP archive. * * @param InstallFile $fileInfo * @return array */ protected function getMetadata(InstallFile $fileInfo) : array { $alias = Base64UrlSafe::encode(\random_bytes(33)) . '.phar'; $phar = new \Phar($fileInfo->getPath(), \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME); $phar->setAlias($alias); $metadata = $phar->getMetadata(); unset($phar); return $metadata; }
/** * Return XRL's version. * * \retval string * XRL's version, or "dev" if the version * information could not be retrieved. */ public static function getVersion() { // From a phar release. if (!strncmp('phar://', __FILE__, 7)) { $phar = new \Phar(__FILE__); $md = $phar->getMetadata(); return $md['version']; } // From a composer install. $getver = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'erebot' . DIRECTORY_SEPARATOR . 'buildenv' . DIRECTORY_SEPARATOR . 'get_version.php'; if (file_exists($getver)) { return trim(shell_exec($getver)); } // Default guess. return 'dev'; }
/** * Displays the phar file metadata and optionally a file list * * @param boolean $includeFileList * @return void */ function showInfo($includeFileList = false) { $p = new Phar('phar://' . __FILE__); fwrite(STDOUT, "Morph Library\n-------------\n"); foreach ($p->getMetadata() as $field => $value) { $field = str_pad($field, 16, ' ', STR_PAD_RIGHT); fwrite(STDOUT, "{$field}: {$value}\n"); } if ($includeFileList === true) { fwrite(STDOUT, "\nFile List\n---------\n"); $i = new RecursiveIteratorIterator($p); $baseName = 'phar://' . __FILE__ . '/'; foreach ($i as $file) { $name = $file->getPath() . '/' . $file->getFilename(); $name = str_replace($baseName, '', $name); fwrite(STDOUT, "{$name}\n"); } } fwrite(STDOUT, "\n"); }
/** * Entry-point for Erebot. * * \return * This method never returns. * Instead, the program exits with an appropriate * return code when Erebot is stopped. */ public static function run() { // Apply patches. \Erebot\Patches::patch(); // Load the configuration for the Dependency Injection Container. $dic = new \Symfony\Component\DependencyInjection\ContainerBuilder(); $dic->setParameter('Erebot.src_dir', __DIR__); $loader = new \Symfony\Component\DependencyInjection\Loader\XmlFileLoader($dic, new \Symfony\Component\Config\FileLocator(getcwd())); $dicConfig = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'defaults.xml'; $dicCwdConfig = getcwd() . DIRECTORY_SEPARATOR . 'defaults.xml'; if (!strncasecmp(__FILE__, 'phar://', 7)) { if (!file_exists($dicCwdConfig)) { copy($dicConfig, $dicCwdConfig); } $dicConfig = $dicCwdConfig; } elseif (file_exists($dicCwdConfig)) { $dicConfig = $dicCwdConfig; } $loader->load($dicConfig); // Determine availability of PHP extensions // needed by some of the command-line options. $hasPosix = in_array('posix', get_loaded_extensions()); $hasPcntl = in_array('pcntl', get_loaded_extensions()); $logger = $dic->get('logging'); $localeGetter = $dic->getParameter('i18n.default_getter'); $coreTranslatorCls = $dic->getParameter('core.classes.i18n'); $translator = new $coreTranslatorCls("Erebot\\Core"); $categories = array('LC_MESSAGES', 'LC_MONETARY', 'LC_TIME', 'LC_NUMERIC'); foreach ($categories as $category) { $locales = call_user_func($localeGetter); $locales = empty($locales) ? array() : array($locales); $localeSources = array('LANGUAGE' => true, 'LC_ALL' => false, $category => false, 'LANG' => false); foreach ($localeSources as $source => $multiple) { if (!isset($_SERVER[$source])) { continue; } if ($multiple) { $locales = explode(':', $_SERVER[$source]); } else { $locales = array($_SERVER[$source]); } break; } $translator->setLocale($translator->nameToCategory($category), $locales); } // Also, include some information about the version // of currently loaded PHAR modules, if any. $version = 'dev-master'; if (!strncmp(__FILE__, 'phar://', 7)) { $phar = new \Phar(\Phar::running(true)); $md = $phar->getMetadata(); $version = $md['version']; } if (defined('Erebot_PHARS')) { $phars = unserialize(Erebot_PHARS); ksort($phars); foreach ($phars as $module => $metadata) { if (strncasecmp($module, 'Erebot_Module_', 14)) { continue; } $version .= "\n with {$module} version {$metadata['version']}"; } } \Console_CommandLine::registerAction('StoreProxy', '\\Erebot\\Console\\StoreProxyAction'); $parser = new \Console_CommandLine(array('name' => 'Erebot', 'description' => $translator->gettext('A modular IRC bot written in PHP'), 'version' => $version, 'add_help_option' => true, 'add_version_option' => true, 'force_posix' => false)); $parser->accept(new \Erebot\Console\MessageProvider()); $parser->renderer->options_on_different_lines = true; $defaultConfigFile = getcwd() . DIRECTORY_SEPARATOR . 'Erebot.xml'; $parser->addOption('config', array('short_name' => '-c', 'long_name' => '--config', 'description' => $translator->gettext('Path to the configuration file to use instead ' . 'of "Erebot.xml", relative to the current ' . 'directory.'), 'help_name' => 'FILE', 'action' => 'StoreString', 'default' => $defaultConfigFile)); $parser->addOption('daemon', array('short_name' => '-d', 'long_name' => '--daemon', 'description' => $translator->gettext('Run the bot in the background (daemon).' . ' [requires the POSIX and pcntl extensions]'), 'action' => 'StoreTrue')); $noDaemon = new \Erebot\Console\ParallelOption('no_daemon', array('short_name' => '-n', 'long_name' => '--no-daemon', 'description' => $translator->gettext('Do not run the bot in the background. ' . 'This is the default, unless the -d option ' . 'is used or the bot is configured otherwise.'), 'action' => 'StoreProxy', 'action_params' => array('option' => 'daemon'))); $parser->addOption($noDaemon); $parser->addOption('pidfile', array('short_name' => '-p', 'long_name' => '--pidfile', 'description' => $translator->gettext("Store the bot's PID in this file."), 'help_name' => 'FILE', 'action' => 'StoreString', 'default' => null)); $parser->addOption('group', array('short_name' => '-g', 'long_name' => '--group', 'description' => $translator->gettext('Set group identity to this GID/group during ' . 'startup. The default is to NOT change group ' . 'identity, unless configured otherwise.' . ' [requires the POSIX extension]'), 'help_name' => 'GROUP/GID', 'action' => 'StoreString', 'default' => null)); $parser->addOption('user', array('short_name' => '-u', 'long_name' => '--user', 'description' => $translator->gettext('Set user identity to this UID/username during ' . 'startup. The default is to NOT change user ' . 'identity, unless configured otherwise.' . ' [requires the POSIX extension]'), 'help_name' => 'USER/UID', 'action' => 'StoreString', 'default' => null)); try { $parsed = $parser->parse(); } catch (\Exception $exc) { $parser->displayError($exc->getMessage()); exit(1); } // Parse the configuration file. $config = new \Erebot\Config\Main($parsed->options['config'], \Erebot\Config\Main::LOAD_FROM_FILE, $translator); $coreCls = $dic->getParameter('core.classes.core'); $bot = new $coreCls($config, $translator); $dic->set('bot', $bot); // Use values from the XML configuration file // if there is no override from the command line. $overrides = array('daemon' => 'mustDaemonize', 'group' => 'getGroupIdentity', 'user' => 'getUserIdentity', 'pidfile' => 'getPidfile'); foreach ($overrides as $option => $func) { if ($parsed->options[$option] === null) { $parsed->options[$option] = $config->{$func}(); } } /* Handle daemonization. * See also: * - http://www.itp.uzh.ch/~dpotter/howto/daemonize * - http://andytson.com/blog/2010/05/daemonising-a-php-cli-script */ if ($parsed->options['daemon']) { if (!$hasPosix) { $logger->error($translator->gettext('The posix extension is required in order ' . 'to start the bot in the background')); exit(1); } if (!$hasPcntl) { $logger->error($translator->gettext('The pcntl extension is required in order ' . 'to start the bot in the background')); exit(1); } foreach (array('SIGCHLD', 'SIGUSR1', 'SIGALRM') as $signal) { if (defined($signal)) { pcntl_signal(constant($signal), array(__CLASS__, 'startupSighandler')); } } $logger->info($translator->gettext('Starting the bot in the background...')); $pid = pcntl_fork(); if ($pid < 0) { $logger->error($translator->gettext('Could not start in the background (unable to fork)')); exit(1); } if ($pid > 0) { pcntl_wait($dummy, WUNTRACED); pcntl_alarm(2); pcntl_signal_dispatch(); exit(1); } $parent = posix_getppid(); // Ignore some of the signals. foreach (array('SIGTSTP', 'SIGTOU', 'SIGTIN', 'SIGHUP') as $signal) { if (defined($signal)) { pcntl_signal(constant($signal), SIG_IGN); } } // Restore the signal handlers we messed with. foreach (array('SIGCHLD', 'SIGUSR1', 'SIGALRM') as $signal) { if (defined($signal)) { pcntl_signal(constant($signal), SIG_DFL); } } umask(0); if (umask() != 0) { $logger->warning($translator->gettext('Could not change umask')); } if (posix_setsid() == -1) { $logger->error($translator->gettext('Could not start in the background (unable to setsid)')); exit(1); } // Prevent the child from ever acquiring a controlling terminal. // Not required under Linux, but required by at least System V. $pid = pcntl_fork(); if ($pid < 0) { $logger->error($translator->gettext('Could not start in the background (unable to fork)')); exit(1); } if ($pid > 0) { exit(0); } // Avoid locking up the current directory. if (!chdir(DIRECTORY_SEPARATOR)) { $logger->error($translator->gettext('Could not chdir to "%(path)s"'), array('path' => DIRECTORY_SEPARATOR)); } // Explicitly close the magic stream-constants (just in case). foreach (array('STDIN', 'STDOUT', 'STDERR') as $stream) { if (defined($stream)) { fclose(constant($stream)); } } // Re-open them with the system's blackhole. /** * \todo * should be made portable, but the requirement on the POSIX * extension prevents this, so this is okay for now. */ $stdin = fopen('/dev/null', 'r'); $stdout = fopen('/dev/null', 'w'); $stderr = fopen('/dev/null', 'w'); if (defined('SIGUSR1')) { posix_kill($parent, SIGUSR1); } $logger->info($translator->gettext('Successfully started in the background')); } try { /// @TODO: Check the interface or something like that. $identd = $dic->get('identd'); } catch (\InvalidArgumentException $e) { $identd = null; } try { /// @TODO: Check the interface or something like that. $prompt = $dic->get('prompt'); } catch (\InvalidArgumentException $e) { $prompt = null; } // Change group identity if necessary. if ($parsed->options['group'] !== null && $parsed->options['group'] != '') { if (!$hasPosix) { $logger->warning($translator->gettext('The posix extension is needed in order ' . 'to change group identity.')); } elseif (posix_getuid() !== 0) { $logger->warning($translator->gettext('Only root can change group identity! ' . 'Your current UID is %(uid)d'), array('uid' => posix_getuid())); } else { if (ctype_digit($parsed->options['group'])) { $info = posix_getgrgid((int) $parsed->options['group']); } else { $info = posix_getgrnam($parsed->options['group']); } if ($info === false) { $logger->error($translator->gettext('No such group "%(group)s"'), array('group' => $parsed->options['group'])); exit(1); } if (!posix_setgid($info['gid'])) { $logger->error($translator->gettext('Could not set group identity ' . 'to "%(name)s" (%(id)d)'), array('id' => $info['gid'], 'name' => $info['name'])); exit(1); } $logger->debug($translator->gettext('Successfully changed group identity ' . 'to "%(name)s" (%(id)d)'), array('name' => $info['name'], 'id' => $info['gid'])); } } // Change user identity if necessary. if ($parsed->options['user'] !== null || $parsed->options['user'] != '') { if (!$hasPosix) { $logger->warning($translator->gettext('The posix extension is needed in order ' . 'to change user identity.')); } elseif (posix_getuid() !== 0) { $logger->warning($translator->gettext('Only root can change user identity! ' . 'Your current UID is %(uid)d'), array('uid' => posix_getuid())); } else { if (ctype_digit($parsed->options['user'])) { $info = posix_getpwuid((int) $parsed->options['user']); } else { $info = posix_getpwnam($parsed->options['user']); } if ($info === false) { $logger->error($translator->gettext('No such user "%(user)s"'), array('user' => $parsed->options['user'])); exit(1); } if (!posix_setuid($info['uid'])) { $logger->error($translator->gettext('Could not set user identity ' . 'to "%(name)s" (%(id)d)'), array('name' => $info['name'], 'id' => $info['uid'])); exit(1); } $logger->debug($translator->gettext('Successfully changed user identity ' . 'to "%(name)s" (%(id)d)'), array('name' => $info['name'], 'id' => $info['uid'])); } } // Write new pidfile. if ($parsed->options['pidfile'] !== null && $parsed->options['pidfile'] != '') { $pid = @file_get_contents($parsed->options['pidfile']); // If the file already existed, the bot may already be started // or it may contain data not related to Erebot at all. if ($pid !== false) { $pid = (int) rtrim($pid); if (!$pid) { $logger->error($translator->gettext('The pidfile (%(pidfile)s) contained garbage. ' . 'Exiting'), array('pidfile' => $parsed->options['pidfile'])); exit(1); } else { posix_kill($pid, 0); $res = posix_errno(); switch ($res) { case 0: // No error. $logger->error($translator->gettext('Erebot is already running ' . 'with PID %(pid)d'), array('pid' => $pid)); exit(1); case 3: // ESRCH. $logger->warning($translator->gettext('Found stalled PID %(pid)d in pidfile ' . '"%(pidfile)s". Removing it'), array('pidfile' => $parsed->options['pidfile'], 'pid' => $pid)); @unlink($parsed->options['pidfile']); break; case 1: // EPERM. $logger->error($translator->gettext('Found another program\'s PID %(pid)d in ' . 'pidfile "%(pidfile)s". Exiting'), array('pidfile' => $parsed->options['pidfile'], 'pid' => $pid)); exit(1); default: $logger->error($translator->gettext('Unknown error while checking for ' . 'the existence of another running ' . 'instance of Erebot (%(error)s)'), array('error' => posix_get_last_error())); exit(1); } } } $pidfile = fopen($parsed->options['pidfile'], 'wt'); flock($pidfile, LOCK_EX | LOCK_NB, $wouldBlock); if ($wouldBlock) { $logger->error($translator->gettext('Could not lock pidfile (%(pidfile)s). ' . 'Is the bot already running?'), array('pidfile' => $parsed->options['pidfile'])); exit(1); } $pid = sprintf("%u\n", getmypid()); $res = fwrite($pidfile, $pid); if ($res !== strlen($pid)) { $logger->error($translator->gettext('Unable to write PID to pidfile (%(pidfile)s)'), array('pidfile' => $parsed->options['pidfile'])); exit(1); } $logger->debug($translator->gettext('PID (%(pid)d) written into %(pidfile)s'), array('pidfile' => $parsed->options['pidfile'], 'pid' => getmypid())); // Register a callback to remove the pidfile upon exit. register_shutdown_function(array(__CLASS__, 'cleanupPidfile'), $pidfile, $parsed->options['pidfile']); } // Display a desperate warning when run as user root. if ($hasPosix && posix_getuid() === 0) { $logger->warning($translator->gettext('You SHOULD NOT run Erebot as root!')); } if ($identd !== null) { $identd->connect(); } if ($prompt !== null) { $prompt->connect(); } // This doesn't return until we purposely // make the bot drop all active connections. $bot->start($dic->get('factory.connection')); exit(0); }
/** * Let's install the automatic update. * * If we get to this point: * * 1. We know the signature is signed by * Paragon Initiative Enterprises, LLC. * 2. The hash was checked into Keyggdrasil, which * was independently vouched for by our peers. * * @param UpdateInfo $info * @param UpdateFile $file * @throws CouldNotUpdate */ protected function install(UpdateInfo $info, UpdateFile $file) { if (!$file->hashMatches($info->getChecksum())) { throw new CouldNotUpdate(\__('Checksum mismatched')); } // Let's open the update package: $path = $file->getPath(); $updater = new \Phar($path, \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME); $updater->setAlias($this->pharAlias); $metadata = $updater->getMetadata(); // We need to do this while we're replacing files. $this->bringSiteDown(); if (isset($metadata['files'])) { foreach ($metadata['files'] as $fileName) { $this->replaceFile($fileName); } } if (isset($metadata['autoRun'])) { foreach ($metadata['autoRun'] as $autoRun) { $this->autoRunScript($autoRun); } } // If we included composer.lock, we need to install the dependencies. if (\in_array('composer.lock', $metadata['files'])) { $composers = ['/usr/bin/composer', '/usr/bin/composer.phar', \dirname(ROOT) . '/composer', \dirname(ROOT) . '/composer.phar']; $composerUpdated = false; foreach ($composers as $composer) { if (\file_exists($composer)) { $dir = \getcwd(); \chdir(\dirname(ROOT)); \shell_exec("{$composer} install"); \chdir($dir); $composerUpdated = true; break; } } if (!$composerUpdated) { self::$continuumLogger->store(LogLevel::INFO, 'Could not update dependencies. Please run Composer manually.', $this->getLogContext($info, $file)); } } // Free up the updater alias $garbageAlias = Base64UrlSafe::encode(\random_bytes(63)) . '.phar'; $updater->setAlias($garbageAlias); unset($updater); // Now bring it back up. $this->bringSiteBackUp(); self::$continuumLogger->store(LogLevel::INFO, 'CMS Airship core update installed', $this->getLogContext($info, $file)); }
/** * We just need to replace the Phar * * If we get to this point: * * 1. We know the signature is signed by the supplier. * 2. The hash was checked into Keyggdrasil, which * was independently vouched for by our peers. * * @param UpdateInfo $info * @param UpdateFile $file * @throws CouldNotUpdate */ protected function install(UpdateInfo $info, UpdateFile $file) { if (!$file->hashMatches($info->getChecksum())) { throw new CouldNotUpdate(\__('Checksum mismatched')); } // Create a backup of the old Gadget: \rename($this->filePath, $this->filePath . '.backup'); \rename($file->getPath(), $this->filePath); $this->log('Begin install process', LogLevel::DEBUG, ['path' => $file->getPath(), 'hash' => $file->getHash(), 'version' => $file->getVersion(), 'size' => $file->getSize()]); // Get metadata from the old version of this Gadget: $oldAlias = Base64UrlSafe::encode(\random_bytes(48)) . '.phar'; $oldGadget = new \Phar($this->filePath, \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME); $oldGadget->setAlias($oldAlias); $oldMetadata = $oldGadget->getMetadata(); unset($oldGadget); unset($oldAlias); // Let's open the update package: $newGadget = new \Phar($this->filePath, \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME, $this->pharAlias); $newGadget->setAlias($this->pharAlias); $metaData = $newGadget->getMetadata(); // We need to do this while we're replacing files. $this->bringSiteDown(); Sandbox::safeRequire('phar://' . $this->pharAlias . '/update_trigger.php', $oldMetadata); // Free up the updater alias $garbageAlias = Base64UrlSafe::encode(\random_bytes(48)) . '.phar'; $newGadget->setAlias($garbageAlias); unset($newGadget); // Now bring it back up. $this->bringSiteBackUp(); // Make sure we update the version info. in the DB cache: $this->updateDBRecord('Gadget', $info); if ($metaData) { $this->updateJSON($info, $metaData); } self::$continuumLogger->store(LogLevel::INFO, 'Gadget update installed', $this->getLogContext($info, $file)); }
<?php $p = new Phar(__FILE__); var_dump($p->getMetadata()); $p->setMetadata("hi"); var_dump($p->getMetadata()); echo "ok\n"; __halt_compiler(); ?> 6test.txt���H���E�<?php __HALT_COMPILER();~�bp�DZNu�@.�]GBMB
/** * Apply the update * * @access public * @return boolean */ public static function applyPackage($pharWithPath = null, $pharType = 'addon') { $phar_can_open = true; $meta = array(); $pro_hart = array(); try { if ($pharWithPath == null) { $pharFile = 'update.phar'; $phar = new Phar(DIR_FS_WORK . 'updates/' . $pharFile); $meta = $phar->getMetadata(); self::$_to_version = $meta['version_to']; // reset the log if (file_exists(DIR_FS_WORK . 'logs/update-' . self::$_to_version . '.txt') && is_writable(DIR_FS_WORK . 'logs/update-' . self::$_to_version . '.txt')) { unlink(DIR_FS_WORK . 'logs/update-' . self::$_to_version . '.txt'); } $pharCode = 'update'; if (defined('ADDONS_SYSTEM_LOADED_7_PRO_STATUS') && is_dir(DIR_FS_CATALOG . 'addons/Loaded_7_Pro')) { self::rmdir_r(DIR_FS_CATALOG . 'addons/Loaded_7_Pro'); } if (defined('ADDONS_SYSTEM_LOADED_7_B2B_STATUS') && is_dir(DIR_FS_CATALOG . 'addons/Loaded_7_B2B')) { self::rmdir_r(DIR_FS_CATALOG . 'addons/Loaded_7_B2B'); } self::log('##### UPDATE TO ' . self::$_to_version . ' STARTED', $pharCode); } else { $pharFile = end(explode('/', $pharWithPath)); $phar = new Phar(DIR_FS_WORK . 'addons/' . $pharFile); $meta = $phar->getMetadata(); $pharCode = str_replace('.phar', '', $pharFile); if ($meta['type'] != '') { $pharType = $meta['type']; } // reset the log if (file_exists(DIR_FS_WORK . 'logs/addon-' . $pharCode . '.txt') && is_writable(DIR_FS_WORK . 'logs/addon-' . $pharCode . '.txt')) { unlink(DIR_FS_WORK . 'logs/addon-' . $pharCode . '.txt'); } self::log('##### ADDON INSTALL ' . $pharCode . ' STARTED', $pharCode); } // first delete files before extracting new files if (is_array($meta['delete']) && count($meta['delete']) > 0) { foreach ($meta['delete'] as $file) { $directory = realpath(DIR_FS_CATALOG) . '/'; if (file_exists($directory . $file)) { if (is_dir($directory . $file)) { if (rename($directory . $file, $directory . dirname($file) . '/.CU_' . basename($file))) { $pro_hart[] = array('type' => 'directory', 'where' => $directory, 'path' => dirname($file) . '/.CU_' . basename($file), 'log' => true); } } else { if (rename($directory . $file, $directory . dirname($file) . '/.CU_' . basename($file))) { $pro_hart[] = array('type' => 'file', 'where' => $directory, 'path' => dirname($file) . '/.CU_' . basename($file), 'log' => true); } } } } } // loop through each file individually as extractTo() does not work with // directories (see http://bugs.php.net/bug.php?id=54289) foreach (new RecursiveIteratorIterator($phar) as $iteration) { if (($pos = strpos($iteration->getPathName(), '.phar')) !== false) { $file = substr($iteration->getPathName(), $pos + 6); if (version_compare($meta['compatibility'], '7.002.0.0') != -1 || $pharType == 'template' || $pharType == 'language' || $pharWithPath == null) { $directory = realpath(DIR_FS_CATALOG) . '/'; } else { $directory = realpath(DIR_FS_CATALOG) . '/addons/' . $pharCode . '/'; } if (file_exists($directory . $file)) { if (rename($directory . $file, $directory . dirname($file) . '/.CU_' . basename($file))) { $pro_hart[] = array('type' => 'file', 'where' => $directory, 'path' => dirname($file) . '/.CU_' . basename($file), 'log' => false); } } if ($phar->extractTo($directory, $file, true)) { self::log('Extracted: ' . $file, $pharCode); } else { self::log('*** Could Not Extract: ' . $file, $pharCode); } } } self::log('##### CLEANUP', $pharCode); foreach (array_reverse($pro_hart, true) as $mess) { if ($mess['type'] == 'directory') { if (self::rmdir_r($mess['where'] . $mess['path'])) { if ($mess['log'] === true) { self::log('Deleted: ' . str_replace('/.CU_', '/', $mess['path']), $pharCode); } } else { if ($mess['log'] === true) { self::log('*** Could Not Delete: ' . str_replace('/.CU_', '/', $mess['path']), $pharCode); } } } else { if (unlink($mess['where'] . $mess['path'])) { if ($mess['log'] === true) { self::log('Deleted: ' . str_replace('/.CU_', '/', $mess['path']), $pharCode); } } else { if ($mess['log'] === true) { self::log('*** Could Not Delete: ' . str_replace('/.CU_', '/', $mess['path']), $pharCode); } } } } } catch (Exception $e) { $phar_can_open = false; self::log('##### ERROR: ' . $e->getMessage(), $pharCode); self::log('##### REVERTING STARTED', $pharCode); foreach (array_reverse($pro_hart, true) as $mess) { if ($mess['type'] == 'directory') { if (file_exists($mess['where'] . str_replace('/.CU_', '/', $mess['path']))) { self::rmdir_r($mess['where'] . str_replace('/.CU_', '/', $mess['path'])); } } else { if (file_exists($mess['where'] . str_replace('/.CU_', '/', $mess['path']))) { unlink($mess['where'] . str_replace('/.CU_', '/', $mess['path'])); } } if (file_exists($mess['where'] . $mess['path'])) { rename($mess['where'] . $mess['path'], $mess['where'] . str_replace('/.CU_', '/', $mess['path'])); } self::log('Reverted: ' . str_replace('/.CU_', '/', $mess['path']), $pharCode); } self::log('##### REVERTING COMPLETE', $pharCode); self::log('##### UPDATE TO ' . self::$_to_version . ' FAILED', $pharCode); trigger_error($e->getMessage()); trigger_error('Please review the update log at: ' . DIR_FS_WORK . 'logs/update-' . self::$_to_version . '.txt'); } if ($pharWithPath == null) { // execute run after process self::doRunAfter(); // verify 644 permissions on PHP files on Linux systems if (utility::execEnabled() === true && utility::isLinux() === true) { try { exec('\\find ' . DIR_FS_CATALOG . ' \\( -type f -exec chmod 644 {} \\; \\);'); self::log('##### UPDATED Permissions on PHP files/directories', $pharCode); } catch (Exception $e) { self::log('*** Could NOT Set Permissions on PHP files/directories', $pharCode); } self::log('##### UPDATE TO ' . self::$_to_version . ' COMPLETE', $pharCode); } else { try { self::chmod_r(DIR_FS_CATALOG); self::log('##### UPDATED Permissions on PHP files/directories', $pharCode); } catch (Exception $e) { self::log('*** Could NOT Set Permissions on PHP files/directories', $pharCode); } // remove the update phar if (file_exists(DIR_FS_WORK . 'updates/update.phar')) { unlink(DIR_FS_WORK . 'updates/update.phar'); } self::log('##### UPDATE TO ' . self::$_to_version . ' COMPLETE', $pharCode); } } else { // remove the addon phar & pubkey if (file_exists(DIR_FS_WORK . 'addons/' . $pharCode . '.phar')) { unlink(DIR_FS_WORK . 'addons/' . $pharCode . '.phar'); } if (file_exists(DIR_FS_WORK . 'addons/' . $pharCode . '.phar.pubkey')) { unlink(DIR_FS_WORK . 'addons/' . $pharCode . '.phar.pubkey'); } self::log('##### ADDON INSTALL ' . $code . ' COMPLETE', $pharCode); } return $phar_can_open; }
public static function install($key) { global $lC_Database, $lC_Language, $lC_Vqmod, $lC_Addons; $isTemplate = strstr($key, 'lC_Template_') ? true : false; if ($isTemplate) { $key = str_replace('lC_Template_', '', $key); if (!file_exists(DIR_FS_ADMIN . 'includes/templates/' . $key . '.php')) { // get the addon phar from the store self::getAddonPhar($key, 'template'); // apply the addon phar if (file_exists(DIR_FS_WORK . 'addons/' . $key . '.phar')) { lC_Updates_Admin::applyPackage(DIR_FS_WORK . 'addons/' . $key . '.phar', 'template'); } } self::_resetAddons(); return true; } else { // is addon or language if (!file_exists(DIR_FS_CATALOG . 'addons/' . $key . '/controller.php')) { // get the addon phar from the store self::getAddonPhar($key); $phar = new Phar(DIR_FS_WORK . 'addons/' . $key . '.phar', 0); $meta = $phar->getMetadata(); // apply the addon phar if (file_exists(DIR_FS_WORK . 'addons/' . $key . '.phar')) { lC_Updates_Admin::applyPackage(DIR_FS_WORK . 'addons/' . $key . '.phar'); } if ($meta['type'] == 'language') { return true; } } // sanity check to see if the object is already installed $okToInstall = true; $Qchk = $lC_Database->query("select id from :table_templates_boxes where modules_group LIKE '%" . $key . "%'"); $Qchk->bindTable(':table_templates_boxes', TABLE_TEMPLATES_BOXES); $Qchk->execute(); if ($Qchk->numberOfRows() > 0) { $okToInstall = false; } $Qchk->freeResult(); if (file_exists(DIR_FS_CATALOG . 'addons/' . $key . '/controller.php') && $okToInstall === true) { include_once DIR_FS_CATALOG . 'addons/' . $key . '/controller.php'; $addon = $key; $addon = new $addon(); $modules_group = $addon->getAddonType() . '|' . $key; $addon->install(); $code = $addon->getAddonType(); $title = $addon->getAddonTitle(); // check for payment or shipping modules and adjust addon $code to module $code if (is_dir(DIR_FS_CATALOG . 'addons/' . $addon->getAddonCode() . '/modules/payment/')) { $lC_DirectoryListing = new lC_DirectoryListing(DIR_FS_CATALOG . 'addons/' . $addon->getAddonCode() . '/modules/payment/'); $lC_DirectoryListing->setCheckExtension('php'); foreach ($lC_DirectoryListing->getFiles() as $ao) { if (isset($ao['name'])) { $code = substr($ao['name'], 0, strpos($ao['name'], '.')); $title = str_replace('_', ' ', $key); $modules_group = 'payment|' . $key; break; } } } else { if (is_dir(DIR_FS_CATALOG . 'addons/' . $addon->getAddonCode() . '/modules/shipping/')) { $lC_DirectoryListing = new lC_DirectoryListing(DIR_FS_CATALOG . 'addons/' . $addon->getAddonCode() . '/modules/shipping/'); $lC_DirectoryListing->setCheckExtension('php'); foreach ($lC_DirectoryListing->getFiles() as $ao) { if (isset($ao['name'])) { $code = substr($ao['name'], 0, strpos($ao['name'], '.')); $title = str_replace('_', ' ', $key); $modules_group = 'shipping|' . $key; break; } } } } if (empty($code) === false) { $Qdel = $lC_Database->query('delete from :table_templates_boxes where modules_group = :modules_group'); $Qdel->bindTable(':table_templates_boxes', TABLE_TEMPLATES_BOXES); $Qdel->bindValue(':modules_group', $modules_group); $Qdel->execute(); $Qinstall = $lC_Database->query('insert into :table_templates_boxes (title, code, author_name, author_www, modules_group) values (:title, :code, :author_name, :author_www, :modules_group)'); $Qinstall->bindTable(':table_templates_boxes', TABLE_TEMPLATES_BOXES); $Qinstall->bindValue(':title', $title); $Qinstall->bindValue(':code', $code); $Qinstall->bindValue(':author_name', $addon->getAddonAuthor()); $Qinstall->bindValue(':author_www', $addon->getAddonAuthorWWW()); $Qinstall->bindValue(':modules_group', $modules_group); $Qinstall->execute(); self::_resetAddons(); return true; } } } return false; }
foreach ($package['autoload']['psr-0'] as $autoload) { Erebot_Autoload::initialize("phar://" . $pharPath . "/vendor/{$package['name']}/{$autoload}"); } } } } catch (Exception $e) { } // Create installed repo, this contains all local packages // and platform packages (php, extensions & system libs). $platformRepository = new \Composer\Repository\PlatformRepository(); $installedRepository = new \Composer\Repository\CompositeRepository(array($platformRepository, $repository)); $pool = new \Composer\DependencyResolver\Pool(); $pool->addRepository($platformRepository); $pool->addRepository($repository); $request = new \Composer\DependencyResolver\Request($pool); $phar = new Phar(__FILE__); $md = $phar->getMetadata(); $request->install("erebot/erebot"); $policy = new \Composer\DependencyResolver\DefaultPolicy(); $solver = new \Composer\DependencyResolver\Solver($policy, $pool, $repository); try { $solver->solve($request); } catch (\Composer\DependencyResolver\SolverProblemsException $e) { echo $e->getMessage() . PHP_EOL; exit(1); } // Necessary for PEAR 1 packages that require() stuff. set_include_path(implode(PATH_SEPARATOR, Erebot_Autoload::getPaths())); Erebot_CLI::run(); __halt_compiler();
<?php echo "PocketMine-MP plugin timezoneFix v1.0-alpha\nThis file has been generated using DevTools vbleeding-x at Tue, 05 Jan 2016 15:48:43 +0900\n----------------\n"; if (extension_loaded("phar")) { $phar = new \Phar(__FILE__); foreach ($phar->getMetadata() as $key => $value) { echo ucfirst($key) . ": " . (is_array($value) ? implode(", ", $value) : $value) . "\n"; } } __halt_compiler(); ?>
echo "Usage: -e <phar_file> [extract_directory]\n"; } } elseif (strtolower($argv[1]) == "-i") { //PharTools Info command if (isset($argv[2])) { //Get fixed filename if (strtolower(substr($argv[2], -5)) == ".phar" || strpos($argv[2], '.') !== false) { $file = $argv[2]; } else { $file = $argv[2] . ".phar"; } if (file_exists($file)) { try { $phar = new Phar($file, 0); if ($phar->hasMetadata()) { $metadata = metadataToString($phar->getMetadata()); } else { $metadata = "No metadata found\n"; } echo "Size: " . round(filesize($file) * 0.0009765625 * 0.0009765625, 2) . " MB (" . round(filesize($file) * 0.0009765625, 3) . " KB)\n"; echo "Signature: " . $phar->getSignature()["hash"] . "\n"; echo "Signature type: " . $phar->getSignature()["hash_type"] . "\n"; echo "Writable: " . strbool($phar->isWritable()) . "\n"; echo "Readable: " . strbool($phar->isReadable()) . "\n"; echo "Metadata: " . $metadata; echo "Show stub (y, n)? "; $input = fopen("php://stdin", "r"); $line = fgets($input); if (trim($line) == 'y') { echo $phar->getStub(); }
/** * Cabin install process. * * 1. Extract files to proper directory. * 2. Run the update triggers (install hooks and incremental upgrades) * 3. Create/update relevant configuration files. * 4. Create symbolic links. * 5. Clear the cache files. * * @param InstallFile $fileInfo * @return bool */ public function install(InstallFile $fileInfo) : bool { $ns = $this->makeNamespace($this->supplier->getName(), $this->package); $alias = 'cabin.' . $this->supplier->getName() . '.' . $this->package . '.phar'; $updater = new \Phar($fileInfo->getPath(), \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME); $updater->setAlias($alias); $metadata = $updater->getMetadata(); // Overwrite files $updater->extractTo(ROOT . '/Cabin/' . $ns); // Run the update trigger. $updateTrigger = ROOT . '/Cabin/' . $ns . '/update_trigger.php'; if (\file_exists($updateTrigger)) { /** * @security Make sure arbitrary RCE isn't possible here. */ \shell_exec('php -dphar.readonly=0 ' . \escapeshellarg($updateTrigger) . ' >/dev/null 2>&1 &'); } // Free up the updater alias $garbageAlias = Base64UrlSafe::encode(\random_bytes(33)) . '.phar'; $updater->setAlias($garbageAlias); unset($updater); self::$continuumLogger->store(LogLevel::INFO, 'Cabin install successful', $this->getLogContext($fileInfo)); return $this->configure($ns, $metadata); }
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php'; $fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.2.phar.php'; if (file_exists($fname)) { unlink($fname); } if (file_exists($fname2)) { unlink($fname2); } $phar = new Phar($fname); // no entries, never flushed $phar->setAlias('first'); $phar->setMetadata('hi'); unset($phar); $phar = new Phar($fname2); $phar['b'] = 'whatever'; // flushed try { $phar->setAlias('first'); } catch (Exception $e) { echo $e->getMessage() . "\n"; } $phar = new Phar($fname); var_dump($phar->getMetadata()); var_dump($phar->getAlias()); var_dump(file_exists($fname)); ?> ===DONE=== <?php error_reporting(0); unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php'); unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.2.phar.php');
<?php try { $p = new Phar(dirname(__FILE__) . '/bug69324.phar', 0); $meta = $p->getMetadata(); var_dump($meta); } catch (Exception $e) { echo $e->getMessage(); }
/** * Get metadata from the Phar * * @param string $file * @return array */ public function getPharManifest(string $file) : array { $phar = new \Phar($file); $phar->setAlias(Base64UrlSafe::encode(\random_bytes(33))); $meta = $phar->getMetadata(); if (empty($meta)) { return []; } return $meta; }
function unphar_toZip($tmpName, &$result, $name = "") { $result = ["tmpDir" => null, "zipPath" => null, "zipRelativePath" => null, "basename" => null, "error" => false]; rename($tmpName, "{$tmpName}.phar"); $tmpName .= ".phar"; try { $phar = new Phar($tmpName); $result["tmpDir"] = $tmpDir = getTmpDir(); $pharPath = "phar://{$phar->getPath()}/"; foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($pharPath)) as $f) { $subpath = substr($f, strlen($pharPath)); @mkdir(dirname($realSubpath = $tmpDir . $subpath), 0777, true); copy($f, $realSubpath); } $zip = new ZipArchive(); $dir = "/data/phars/"; while (is_file($file = htdocs . ($rel = $dir . randomClass(16, "zip_" . $name . "_") . ".zip"))) { } $result["zipPath"] = $file; $result["zipRelativePath"] = $rel; $result["basename"] = substr($rel, 12); $err = $zip->open($file, ZipArchive::CREATE); if ($err !== true) { $msg = "Error creating zip file: "; switch ($err) { case ZipArchive::ER_EXISTS: $msg .= "ER_EXISTS ({$err}) File already exists ({$file})"; break; case ZipArchive::ER_INCONS: $msg .= "ER_INCONS ({$err}) Zip archive inconsistent."; break; case ZipArchive::ER_INVAL: $msg .= "ER_INVAL ({$err}) Invalid argument."; break; case ZipArchive::ER_MEMORY: $msg .= "ER_MEMORY ({$err}) Malloc failure."; break; case ZipArchive::ER_NOENT: $msg .= "ER_NOENT ({$err}) No such file."; break; case ZipArchive::ER_NOZIP: $msg .= "ER_NOZIP ({$err}) Not a zip archive."; break; case ZipArchive::ER_OPEN: $msg .= "ER_OPEN ({$err}) Can't open file."; break; case ZipArchive::ER_READ: $msg .= "ER_READ ({$err}) Read error."; break; case ZipArchive::ER_SEEK: $msg .= "ER_SEEK ({$err}) Seek error."; } throw new RuntimeException($msg . " Dump: " . var_export($result, true)); } $tmpDir = realpath($tmpDir); foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($tmpDir)) as $file) { if (!is_file($file)) { continue; } $file = realpath($file); $rel = substr($file, strlen($tmpDir) + 1); $zip->addFile($file, str_replace("\\", "/", $rel)); } $zip->setArchiveComment(json_encode($phar->getMetadata(), JSON_PRETTY_PRINT)); $zip->close(); } catch (Exception $e) { echo "<pre>"; echo get_class($e) . ": {$e->getMessage()}"; echo "\r\n\tat {$e->getFile()}:{$e->getLine()}</pre>"; $result["error"] = true; } }
/** * Displays this module's version. */ public function run_version() { $phar = new Phar(__FILE__); $md = $phar->getMetadata(); echo $md['version'] . PHP_EOL; }
<?php define('OC_CACHE_HOST', '127.0.0.1'); define('OC_CACHE_PORT', '11211'); define('OC_TMP', 'TMP'); define('OC_LAST_ADD_VM', 'lastAddVM'); define('OC_LAST_ADD_PM', 'lastAddPM'); define('OC_LAST_REM_VM', 'lastRemVM'); define('OC_LAST_REM_PM', 'lastRemPM'); define('OC_ND_HIGH_CONVERGENCE', true); define('OC_STORE', 'classes'); $phar = Phar::running(); $p = new Phar($phar); $files = $p->getMetadata()['files']; foreach ($files as $file) { require_once $phar . "/" . $file; } $cache = new Memcached(); $cache->addServer(OC_CACHE_HOST, OC_CACHE_PORT); Cache::$cache = $cache; require_once "tests/dummyClasses.php"; Counter::$start = time() - 1;