To run as PHP CLI server:
php -S localhost:8888 /full/path/to/elgg/index.php
The full path is necessary to work around this: https://bugs.php.net/bug.php?id=55726
/** * Bootstraps test suite * * @global stdClass $CONFIG Global config * @global stdClass $_ELGG Global vars * @return void */ public static function bootstrap() { date_default_timezone_set('America/Los_Angeles'); error_reporting(E_ALL | E_STRICT); $config = new Config((object) self::getTestingConfigArray()); $sp = new ServiceProvider($config); $sp->setFactory('plugins', function (ServiceProvider $c) { $pool = new InMemory(); return new TestingPlugins($pool, $c->pluginSettingsCache); }); $sp->setValue('mailer', new InMemoryTransport()); $sp->siteSecret->setTestingSecret('z1234567890123456789012345678901'); // persistentLogin service needs this set to instantiate without calling DB $sp->config->getCookieConfig(); $app = new Application($sp); Application::setTestingApplication(true); Application::$_instance = $app; // loadCore bails on repeated calls, so we need to manually inject this to make // sure it happens before each test. $app->loadCore(); _elgg_services($sp); // Invalidate memcache _elgg_get_memcache('new_entity_cache')->clear(); self::$_mocks = null; // reset mocking service }
/** * Handle a request for a file * * @param Request $request HTTP request * @return Response */ public function getResponse($request) { $response = new Response(); $response->prepare($request); $path = implode('/', $request->getUrlSegments()); if (!preg_match('~download-file/g(\\d+)$~', $path, $m)) { return $response->setStatusCode(400)->setContent('Malformatted request URL'); } $this->application->start(); $guid = (int) $m[1]; $file = get_entity($guid); if (!$file instanceof ElggFile) { return $response->setStatusCode(404)->setContent("File with guid {$guid} does not exist"); } $filenameonfilestore = $file->getFilenameOnFilestore(); if (!is_readable($filenameonfilestore)) { return $response->setStatusCode(404)->setContent('File not found'); } $last_updated = filemtime($filenameonfilestore); $etag = '"' . $last_updated . '"'; $response->setPublic()->setEtag($etag); if ($response->isNotModified($request)) { return $response; } $response = new BinaryFileResponse($filenameonfilestore, 200, array(), false, 'attachment'); $response->prepare($request); $expires = strtotime('+1 year'); $expires_dt = (new DateTime())->setTimestamp($expires); $response->setExpires($expires_dt); $response->setEtag($etag); return $response; }
/** * Handle a request for a file * * @param Request $request HTTP request * @return Response */ public function getResponse($request) { $response = new Response(); $response->prepare($request); $path = implode('/', $request->getUrlSegments()); if (!preg_match('~serve-file/e(\\d+)/l(\\d+)/d([ia])/c([01])/([a-zA-Z0-9\\-_]+)/(.*)$~', $path, $m)) { return $response->setStatusCode(400)->setContent('Malformatted request URL'); } list(, $expires, $last_updated, $disposition, $use_cookie, $mac, $path_from_dataroot) = $m; if ($expires && $expires < time()) { return $response->setStatusCode(403)->setContent('URL has expired'); } $etag = '"' . $last_updated . '"'; $response->setPublic()->setEtag($etag); if ($response->isNotModified($request)) { return $response; } // @todo: change to minimal boot without plugins $this->application->bootCore(); $hmac_data = array('expires' => (int) $expires, 'last_updated' => (int) $last_updated, 'disposition' => $disposition, 'path' => $path_from_dataroot, 'use_cookie' => (int) $use_cookie); if ((bool) $use_cookie) { $hmac_data['cookie'] = _elgg_services()->session->getId(); } ksort($hmac_data); $hmac = elgg_build_hmac($hmac_data); if (!$hmac->matchesToken($mac)) { return $response->setStatusCode(403)->setContent('HMAC mistmatch'); } $dataroot = _elgg_services()->config->getDataPath(); $filenameonfilestore = "{$dataroot}{$path_from_dataroot}"; if (!is_readable($filenameonfilestore)) { return $response->setStatusCode(404)->setContent('File not found'); } $actual_last_updated = filemtime($filenameonfilestore); if ($actual_last_updated != $last_updated) { return $response->setStatusCode(403)->setContent('URL has expired'); } $public = $use_cookie ? false : true; $content_disposition = $disposition == 'i' ? 'inline' : 'attachment'; $response = new BinaryFileResponse($filenameonfilestore, 200, array(), $public, $content_disposition); $response->prepare($request); if (empty($expires)) { $expires = strtotime('+1 year'); } $expires_dt = (new DateTime())->setTimestamp($expires); $response->setExpires($expires_dt); $response->setEtag($etag); return $response; }
/** * Do a minimal engine load * * @return void */ protected function setupSimplecache() { // we can't use Elgg\Config::get yet. It fails before the core is booted $config = $this->config; $config->loadSettingsFile(); if ($config->getVolatile('dataroot') && $config->getVolatile('simplecache_enabled') !== null) { // we can work with these... return; } $db = $this->application->getDb(); try { $rows = $db->getData("\n\t\t\t\tSELECT `name`, `value`\n\t\t\t\tFROM {$db->getTablePrefix()}datalists\n\t\t\t\tWHERE `name` IN ('dataroot', 'simplecache_enabled')\n\t\t\t"); if (!$rows) { $this->send403('Cache error: unable to get the data root'); } } catch (\DatabaseException $e) { if (0 === strpos($e->getMessage(), "Elgg couldn't connect")) { $this->send403('Cache error: unable to connect to database server'); } else { $this->send403('Cache error: unable to connect to Elgg database'); } exit; // unnecessary, but helps PhpStorm understand } foreach ($rows as $row) { $config->set($row->name, $row->value); } if (!$config->getVolatile('dataroot')) { $this->send403('Cache error: unable to get the data root'); } }
/** * {@inheritdoc} */ protected function handle() { $uri = '/' . ltrim($this->argument('uri'), '/'); $method = $this->argument('method') ?: 'GET'; $add_csrf_tokens = $this->option('tokens'); $site_url = elgg_get_site_url(); $uri = substr(elgg_normalize_url($uri), strlen($site_url)); $path_key = Application::GET_PATH_KEY; $parameters = []; $query = trim((string) $this->option('query'), '?'); parse_str($query, $parameters); if ($add_csrf_tokens) { $ts = time(); $parameters['__elgg_ts'] = $ts; $parameters['__elgg_token'] = _elgg_services()->actions->generateActionToken($ts); } $request = Request::create("?{$path_key}=" . urlencode($uri), $method, $parameters); $cookie_name = _elgg_services()->config->getCookieConfig()['session']['name']; $session_id = _elgg_services()->session->getId(); $request->cookies->set($cookie_name, $session_id); $request->headers->set('Referer', elgg_normalize_url()); if ($this->option('export')) { elgg_set_viewtype('json'); $request->headers->set('X-Elgg-Ajax-API', '2'); } _elgg_services()->setValue('request', $request); Application::index(); }
/** * {@inheritdoc} */ public function getDataPath() { if (!isset($this->config->dataroot)) { \Elgg\Application::getDataPath(); } return $this->config->dataroot; }
/** * Add CLI tools to the console application * @return void */ protected function bootstrap() { if ($this->isInstalled()) { Application::start(); $commands = elgg_trigger_plugin_hook('commands', 'cli', null, $this->getCommands()); foreach ($commands as $command) { if (class_exists($command) && is_subclass_of($command, Command::class)) { $this->console->add(new $command()); } } } else { $this->console->add(new InstallCommand()); } }
/** * {@inheritdoc} */ protected function handle() { $action = trim($this->argument('action_name'), '/'); $path_key = Application::GET_PATH_KEY; $uri = "action/{$action}"; $parameters = []; $query = trim((string) $this->option('query'), '?'); parse_str($query, $parameters); $ts = time(); $parameters['__elgg_ts'] = $ts; $parameters['__elgg_token'] = _elgg_services()->actions->generateActionToken($ts); $request = Request::create("?{$path_key}=" . urlencode($uri), 'POST', $parameters); $cookie_name = _elgg_services()->config->getCookieConfig()['session']['name']; $session_id = _elgg_services()->session->getId(); $request->cookies->set($cookie_name, $session_id); $request->headers->set('Referer', elgg_normalize_url('cli')); $request->headers->set('X-Elgg-Ajax-API', 2); elgg_set_viewtype('json'); _elgg_services()->setValue('request', $request); Application::index(); }
/** * Make it possible for composer-managed Elgg site to recognize plugins * version-controlled in Elgg core. * * @param string $plugin The name of the plugin to symlink * * @return bool Whether the symlink succeeded. */ private static function symlinkPluginFromRootToElgg($plugin) { $from = Directory\Local::root()->getPath("mod/{$plugin}"); $to = Elgg\Application::elggDir()->getPath("mod/{$plugin}"); return !file_exists($from) && symlink($to, $from); }
/** * Initialize the site including site entity, plugins, and configuration * * @param array $submissionVars Submitted vars * * @return bool */ protected function saveSiteSettings($submissionVars) { // ensure that file path, data path, and www root end in / $submissionVars['dataroot'] = sanitise_filepath($submissionVars['dataroot']); $submissionVars['wwwroot'] = sanitise_filepath($submissionVars['wwwroot']); $site = new ElggSite(); $site->name = strip_tags($submissionVars['sitename']); $site->url = $submissionVars['wwwroot']; $site->access_id = ACCESS_PUBLIC; $site->email = $submissionVars['siteemail']; $guid = $site->save(); if (!$guid) { register_error(_elgg_services()->translator->translate('install:error:createsite')); return FALSE; } // bootstrap site info $this->CONFIG->site_guid = $guid; $this->CONFIG->site = $site; _elgg_services()->configTable->set('installed', time()); _elgg_services()->configTable->set('dataroot', $submissionVars['dataroot']); _elgg_services()->configTable->set('default_site', $site->getGUID()); _elgg_services()->configTable->set('version', elgg_get_version()); _elgg_services()->configTable->set('simplecache_enabled', 1); _elgg_services()->configTable->set('system_cache_enabled', 1); _elgg_services()->configTable->set('simplecache_lastupdate', time()); // new installations have run all the upgrades $upgrades = elgg_get_upgrade_files(\Elgg\Application::elggDir()->getPath("/engine/lib/upgrades/")); _elgg_services()->configTable->set('processed_upgrades', $upgrades); _elgg_services()->configTable->set('view', 'default', $site->getGUID()); _elgg_services()->configTable->set('language', 'en', $site->getGUID()); _elgg_services()->configTable->set('default_access', $submissionVars['siteaccess'], $site->getGUID()); _elgg_services()->configTable->set('allow_registration', TRUE, $site->getGUID()); _elgg_services()->configTable->set('walled_garden', FALSE, $site->getGUID()); _elgg_services()->configTable->set('allow_user_default_access', '', $site->getGUID()); _elgg_services()->configTable->set('default_limit', 10, $site->getGUID()); _elgg_services()->configTable->set('security_protect_upgrade', true, $site->getGUID()); _elgg_services()->configTable->set('security_notify_admins', true, $site->getGUID()); _elgg_services()->configTable->set('security_notify_user_password', true, $site->getGUID()); _elgg_services()->configTable->set('security_email_require_password', true, $site->getGUID()); $this->setSubtypeClasses(); $this->enablePlugins(); return TRUE; }
<?php $autoload_root = dirname(__DIR__); if (!is_file("{$autoload_root}/vendor/autoload.php")) { $autoload_root = dirname(dirname(dirname($autoload_root))); } require_once "{$autoload_root}/vendor/autoload.php"; \Elgg\Application::start(); elgg_deprecated_notice('You should load the core using \\Elgg\\Application::start() instead of including start.php', "2.0.0");
<?php /** * Core Elgg JavaScript file */ // this warning is due to the change in JS boot order in Elgg 1.9 echo <<<JS if (typeof elgg != 'object') { \tthrow new Error('elgg configuration object is not defined! You must include the js/initialize_elgg view in html head before JS library files!'); } JS; // We use named AMD modules and inline them here in order to save HTTP requests, // as these modules will be required on each page echo elgg_view('elgg/popup.js'); $elggDir = \Elgg\Application::elggDir(); $files = array($elggDir->getPath("js/lib/elgglib.js"), $elggDir->getPath("js/classes/ElggEntity.js"), $elggDir->getPath("js/classes/ElggUser.js"), $elggDir->getPath("js/classes/ElggPriorityList.js"), $elggDir->getPath("js/lib/prototypes.js"), $elggDir->getPath("js/lib/hooks.js"), $elggDir->getPath("js/lib/security.js"), $elggDir->getPath("js/lib/languages.js"), $elggDir->getPath("js/lib/ajax.js"), $elggDir->getPath("js/lib/session.js"), $elggDir->getPath("js/lib/pageowner.js"), $elggDir->getPath("js/lib/configuration.js"), $elggDir->getPath("js/lib/comments.js"), $elggDir->getPath("js/lib/ui.js")); foreach ($files as $file) { readfile($file); // putting a new line between the files to address https://github.com/elgg/elgg/issues/3081 echo "\n"; } foreach (_elgg_get_js_site_data() as $expression => $value) { $value = json_encode($value); echo "{$expression} = {$value};\n"; } ?> //<script> // page data overrides site data $.extend(elgg.data, elgg._data); delete elgg._data;
/** * Get the current Elgg version information * * @param bool $human_readable Whether to return a human readable version (default: false) * * @return string|false Depending on success * @since 1.9 */ function elgg_get_version($human_readable = false) { static $version, $release; if (!isset($version) || !isset($release)) { $path = \Elgg\Application::elggDir()->getPath('version.php'); if (!is_file($path)) { return false; } include $path; } return $human_readable ? $release : $version; }
<?php $autoload_path = __DIR__ . '/vendor/autoload.php'; $autoload_available = (include_once $autoload_path); if (!$autoload_available) { die("Couldn't include '{$autoload_path}'. Did you run `composer install`?"); } \Elgg\Application::upgrade();
<?php $autoload_path = __DIR__ . '/vendor/autoload.php'; $autoload_available = (include_once $autoload_path); if (!$autoload_available) { die("Couldn't include '{$autoload_path}'. Did you run `composer install`?"); } \Elgg\Application::install();
<?php $autoload_path = __DIR__ . '/vendor/autoload.php'; $autoload_available = (include_once $autoload_path); if (!$autoload_available) { die("Couldn't include '{$autoload_path}'. Did you run `composer install`?"); } \Elgg\Application::index();
/** * Boots the engine * * @return void */ public function boot() { // Register the error handlers set_error_handler('_elgg_php_error_handler'); set_exception_handler('_elgg_php_exception_handler'); $db = _elgg_services()->db; // we inject the logger here to allow use of DB without loading core $db->setLogger(_elgg_services()->logger); $db->setupConnections(); $db->assertInstalled(); $CONFIG = _elgg_services()->config->getStorageObject(); $local_path = Local::root()->getPath(); // setup stuff available without any DB info $CONFIG->path = $local_path; $CONFIG->plugins_path = "{$local_path}mod/"; $CONFIG->pluginspath = "{$local_path}mod/"; $CONFIG->entity_types = ['group', 'object', 'site', 'user']; $CONFIG->language = 'en'; // set cookie values for session and remember me _elgg_services()->config->getCookieConfig(); // we need this stuff before cache $rows = $db->getData("\n\t\t\tSELECT *\n\t\t\tFROM {$db->prefix}config\n\t\t\tWHERE `name` IN ('__site_secret__', 'default_site', 'dataroot')\n\t\t"); $configs = []; foreach ($rows as $row) { $configs[$row->name] = unserialize($row->value); } // booting during installation if (empty($configs['dataroot'])) { $configs['dataroot'] = ''; // don't use cache $CONFIG->boot_cache_ttl = 0; } if (!$GLOBALS['_ELGG']->dataroot_in_settings) { $CONFIG->dataroot = rtrim($configs['dataroot'], '/\\') . DIRECTORY_SEPARATOR; } $CONFIG->site_guid = (int) $configs['default_site']; if (!isset($CONFIG->boot_cache_ttl)) { $CONFIG->boot_cache_ttl = self::DEFAULT_BOOT_CACHE_TTL; } if ($this->timer) { $this->timer->begin([__CLASS__ . '::getBootData']); } // early config is done, now get the core boot data $data = $this->getBootData($CONFIG, $db); if ($this->timer) { $this->timer->begin([__CLASS__ . '::getBootData']); } $configs_cache = $data->getConfigValues(); $CONFIG->site = $data->getSite(); $CONFIG->wwwroot = $CONFIG->site->url; $CONFIG->sitename = $CONFIG->site->name; $CONFIG->sitedescription = $CONFIG->site->description; $CONFIG->url = $CONFIG->wwwroot; _elgg_services()->subtypeTable->setCachedValues($data->getSubtypeData()); foreach ($data->getConfigValues() as $key => $value) { $CONFIG->{$key} = $value; } _elgg_services()->plugins->setBootPlugins($data->getActivePlugins()); _elgg_services()->pluginSettingsCache->setCachedValues($data->getPluginSettings()); if (!$GLOBALS['_ELGG']->simplecache_enabled_in_settings) { $simplecache_enabled = $configs_cache['simplecache_enabled']; $CONFIG->simplecache_enabled = $simplecache_enabled === false ? 1 : $simplecache_enabled; } $system_cache_enabled = $configs_cache['system_cache_enabled']; $CONFIG->system_cache_enabled = $system_cache_enabled === false ? 1 : $system_cache_enabled; // needs to be set before [init, system] for links in html head $CONFIG->lastcache = (int) $configs_cache['simplecache_lastupdate']; $GLOBALS['_ELGG']->i18n_loaded_from_cache = false; if (!empty($CONFIG->debug)) { _elgg_services()->logger->setLevel($CONFIG->debug); _elgg_services()->logger->setDisplay(true); } _elgg_services()->views->view_path = \Elgg\Application::elggDir()->getPath("/views/"); // finish boot sequence _elgg_session_boot(); if ($CONFIG->system_cache_enabled) { _elgg_services()->systemCache->loadAll(); } _elgg_services()->translator->loadTranslations(); // we always need site->email and user->icontime, so load them together $user_guid = _elgg_services()->session->getLoggedInUserGuid(); if ($user_guid) { _elgg_services()->metadataCache->populateFromEntities([$user_guid]); } // gives hint to get() how to approach missing values $CONFIG->site_config_loaded = true; // invalidate on some actions just in case other invalidation triggers miss something _elgg_services()->hooks->registerHandler('action', 'all', function ($action) { if (0 === strpos($action, 'admin/' || $action === 'plugins/settings/save')) { $this->invalidateCache(); } }, 1); }
/** * Get the current Elgg version information * * @param bool $human_readable Whether to return a human readable version (default: false) * * @return string|false Depending on success * @since 1.9 */ function elgg_get_version($human_readable = false) { static $version, $release; if (!isset($version) || !isset($release)) { if (!(include \Elgg\Application::elggDir()->getPath('version.php'))) { return false; } } return $human_readable ? $release : $version; }
/** * @access private */ function _elgg_config_test($hook, $type, $tests) { $tests[] = \Elgg\Application::elggDir()->getPath("engine/tests/ElggCoreConfigTest.php"); return $tests; }
/** * Create Elgg's .htaccess file or confirm that it exists * * @param string $url URL of rewrite test * * @return bool */ public function createHtaccess($url) { $root = Directory\Local::root(); $file = $root->getFile(".htaccess"); if ($file->exists()) { // check that this is the Elgg .htaccess $data = $file->getContents(); if ($data === FALSE) { // don't have permission to read the file $this->htaccessIssue = 'read_permission'; return FALSE; } if (strpos($data, 'Elgg') === FALSE) { $this->htaccessIssue = 'non_elgg_htaccess'; return FALSE; } else { // check if this is an old Elgg htaccess if (strpos($data, 'RewriteRule ^rewrite.php$ install.php') == FALSE) { $this->htaccessIssue = 'old_elgg_htaccess'; return FALSE; } return TRUE; } } if (!is_writable($root->getPath())) { $this->htaccessIssue = 'write_permission'; return FALSE; } // create the .htaccess file $result = copy(\Elgg\Application::elggDir()->getPath("install/config/htaccess.dist"), $file->getPath()); if (!$result) { $this->htaccessIssue = 'cannot_copy'; return FALSE; } // does default RewriteBase work already? if (!$this->runRewriteTest($url)) { //try to rewrite to guessed subdirectory if ($subdir = $this->guessSubdirectory($url)) { $contents = $file->getContents(); $contents = preg_replace("/#RewriteBase \\/(\r?\n)/", "RewriteBase {$subdir}\$1", $contents); if ($contents) { $file->putContents($contents); } } } return TRUE; }
$site_guid = (int) $_GET['site_guid']; // If is the same ETag, content didn't changed. $etag = md5($name . $site_guid . $guid); if (isset($_SERVER["HTTP_IF_NONE_MATCH"])) { list($etag_header) = explode("-", trim($_SERVER["HTTP_IF_NONE_MATCH"], "\"")); if ($etag_header === $etag) { header("HTTP/1.1 304 Not Modified"); exit; } } $autoload_root = dirname(dirname(dirname(__DIR__))); if (!is_file("{$autoload_root}/vendor/autoload.php")) { $autoload_root = dirname(dirname(dirname($autoload_root))); } require_once "{$autoload_root}/vendor/autoload.php"; $data_root = \Elgg\Application::getDataPath(); if (isset($data_root)) { $bucket_size = 500; $lower_bound = (int) max(floor($guid / $bucket_size) * $bucket_size, 1); $user_path = "ckeditor_upload/" . $site_guid . "/" . $lower_bound . "/" . $guid . "/"; $filename = $data_root . $user_path . $name; $filecontents = @file_get_contents($filename); if ($filecontents) { $filesize = strlen($filecontents); header("Content-type: image/jpeg"); header('Expires: ' . gmdate('D, d M Y H:i:s \\G\\M\\T', strtotime("+6 months")), true); header("Pragma: public"); header("Cache-Control: public"); header("Content-Length: {$filesize}"); header("ETag: \"{$etag}\""); echo $filecontents;
list($guid, $type, $filename) = explode('/', trim($_GET['__uri'], '/')); $guid = (int) $guid; if (!$guid) { $response = new Response('', Response::HTTP_NOT_FOUND); $response->send(); } $last_cache = empty($_GET['lastcache']) ? 0 : (int) $_GET['lastcache']; // icontime // If is the same ETag, content didn't changed. $etag = $last_cache . $guid; if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) == "\"{$etag}\"") { $response = new Response('', Response::HTTP_NOT_MODIFIED); $response->send(); } // @todo: validate hmac $hmac = $_GET['hmac']; $data_root = Application::getDataPath(); $locator = new EntityDirLocator($guid); $full_path = "{$data_root}{$locator->getPath()}media/{$type}/{$filename}"; if (!file_exists($full_path)) { header("HTTP/1.1 404 Not Found"); exit; } $contents = file_get_contents($full_path); $response = new Response($contents); $d = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_INLINE, basename($full_path)); $response->headers->set('Content-Disposition', $d); $response->headers->set('Content-Type', 'image/jpeg'); $response->headers->set('Expires', gmdate('D, d M Y H:i:s \\G\\M\\T', strtotime("+6 months"))); $response->headers->set('ETag', $etag); $response->send();