コード例 #1
0
ファイル: Whois.php プロジェクト: nicholasryan/CorePlus
 /**
  * Lookup query
  *
  * @param string $query  IP or hostname to lookup
  * @param bool   $is_utf Require UTF-8
  *
  * @return WhoisResult
  */
 public static function Lookup($query = '', $is_utf = true)
 {
     // See if this query has been cached by Core <3
     $cachekey = \Core\str_to_url('whois-' . $query);
     $cached = \Core\Cache::Get($cachekey);
     if ($cached) {
         $result = $cached;
     } else {
         $whois = new phpwhois\Whois();
         $result = $whois->lookup($query, $is_utf);
         // Cache the results for 6 hours
         \Core\Cache::Set($cachekey, $result, 3600 * 6);
     }
     if (!is_array($result)) {
         return new WhoisNotFoundResult($query);
     }
     if (!sizeof($result)) {
         return new WhoisNotFoundResult($query);
     }
     return new WhoisResult($result, $query);
 }
コード例 #2
0
ファイル: FileRemote.php プロジェクト: nicholasryan/CorePlus
	/**
	 * Get the temporary local version of the file.
	 * This is useful for doing operations such as hash and identicalto.
	 *
	 * @return FileLocal
	 */
	protected function _getTmpLocal() {
		if ($this->_tmplocal === null) {
			$f = md5($this->getFilename());

			// Gotta love obviously-named flags.
			$needtodownload = true;

			$this->_tmplocal = Filestore\Factory::File('tmp/remotefile-cache/' . $f);

			// File exists already!  Check and see if it needs to be redownloaded.
			if ($this->cacheable && $this->_tmplocal->exists()) {
				// Lookup this file in the system cache.
				$systemcachedata = Cache::Get('remotefile-cache-header-' . $f);
				if ($systemcachedata && isset($systemcachedata['headers'])) {
					// I can only look them up if the cache is available.

					// First check will be the expires header.
					if(isset($systemcachedata['headers']['Expires']) && strtotime($systemcachedata['headers']['Expires']) > time()){
						$needtodownload = false;
						// And set the headers!
						// This is required
						$this->_headers = $systemcachedata['headers'];
						$this->_response = $systemcachedata['response'];
					}
					// Next, try ETag.
					elseif ($this->_getHeader('ETag') && isset($systemcachedata['headers']['ETag'])) {
						$needtodownload = ($this->_getHeader('ETag') != $systemcachedata['headers']['ETag']);
					}
					// No?  How 'bout 
					elseif ($this->_getHeader('Last-Modified') && isset($systemcachedata['headers']['Last-Modified'])) {
						$needtodownload = ($this->_getHeader('Last-Modified') != $systemcachedata['headers']['Last-Modified']);
					}
					// Still no?  The default is to download it anyway.
				}
			}

			if ($needtodownload || !$this->cacheable) {
				// Make sure that the headers are updated, this is a requirement to use the 302 tag.
				$this->_getHeaders();
				if(($this->_response == '302' || $this->_response == '301') && $this->_redirectFile !== null){
					$this->_tmplocal = $this->_redirectFile->_getTmpLocal();
				}
				else{
					// BTW, use cURL.
					$curl = curl_init();
					curl_setopt_array(
						$curl, array(
							CURLOPT_HEADER         => false,
							CURLOPT_NOBODY         => false,
							CURLOPT_RETURNTRANSFER => true,
							CURLOPT_URL            => $this->getURL(),
							CURLOPT_HTTPHEADER     => \Core::GetStandardHTTPHeaders(true),
						)
					);

					$result = curl_exec($curl);
					if($result === false){
						switch(curl_errno($curl)){
							case CURLE_COULDNT_CONNECT:
							case CURLE_COULDNT_RESOLVE_HOST:
							case CURLE_COULDNT_RESOLVE_PROXY:
								$this->_response = 404;
								return $this->_tmplocal;
								break;
							default:
								$this->_response = 500;
								return $this->_tmplocal;
								break;
						}
					}

					curl_close($curl);

					// Copy the data down to the local file.
					$this->_tmplocal->putContents($result);
				}

				// And remember this header data for nexttime.
				Cache::Set(
					'remotefile-cache-header-' . $f,
					[
						'headers'  => $this->_getHeaders(),
						'response' => $this->_response,
					]
				);
			}
		}

		return $this->_tmplocal;
	}
コード例 #3
0
ファイル: I18NLoader.php プロジェクト: nicholasryan/CorePlus
	/**
	 * Get an array of locales currently available on the base system.
	 *
	 * @return array
	 */
	public static function GetLocalesAvailable(){
		$cacheKey = 'core-i18n-locales';
		$cacheTime = DEVELOPMENT_MODE ? 3600 : 604800;
		$cached = Cache::Get($cacheKey, $cacheTime);
		if($cached){
			return $cached;
		}

		exec('locale -a', $output);
		$locales = [];
		foreach($output as $line){
			if($line == 'C' || $line == 'POSIX' || $line == 'C.UTF-8'){
				// Yeah, skip these!
				continue;
			}
			if(($dotpos = strpos($line, '.')) !== false){
				// Trim anything after the ".", this is the charset which we, (in theory), don't need.
				// ex: .UTF-8 or .UTF-16.
				$line = substr($line, 0, $dotpos);
			}
			
			if(isset(self::$Languages[$line])){
				$locales[$line] = self::$Languages[$line];
			}
		}

		// Cache this so I don't have to execute the command and lookup the values all over again!
		Cache::Set($cacheKey, $locales, $cacheTime);
		return $locales;
	}
コード例 #4
0
ファイル: UserAgent.php プロジェクト: nicholasryan/CorePlus
	/**
	 * Construct a UserAgent object with full caching enabled.
	 *
	 * @param $useragent
	 *
	 * @return UserAgent
	 */
	public static function Construct($useragent = null){
		if($useragent === null){
			$useragent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
		}

		$cachekey = 'useragent-constructor-' . md5($useragent);
		$cache = Cache::Get($cachekey);
		if(!$cache){
			$cache = new UserAgent($useragent);
			Cache::Set($cachekey, $cache, SECONDS_ONE_WEEK);
		}

		return $cache;
	}
コード例 #5
0
ファイル: Core.class.php プロジェクト: nicholasryan/CorePlus
	/**
	 * Load all the components in the system, replacement for the Core.
	 * @throws CoreException
	 */
	private function _loadComponents() {
		// cannot reload components.
		if ($this->_components) return null;

		$this->_components = array();
		$this->_libraries  = array();
		$tempcomponents    = false;
		Core\Utilities\Logger\write_debug('Starting loading of component metadata');

		// If the site is in DEVELOPMENT mode, component caching would probably be a bad idea; ie: the developer probably wants
		// those component files loaded everytime.
		if(DEVELOPMENT_MODE){
			$enablecache = false;
		}
		else{
			$enablecache = true;
		}

		// Is there a cache of elements available?  This is a primary system cache that greatly increases performance,
		// since it will no longer have to run through each component.xml file to register each one.
		if($enablecache){
			Core\Utilities\Logger\write_debug('Checking core-components cache');
			// Try to load up the cached components and check them first.
			$tempcomponents = \Core\Cache::Get('core-components', (3600 * 24));

			if($tempcomponents !== false){
				// Cached components only need to be loaded.
				foreach ($tempcomponents as $c) {
					try {
						$c->load();
					}
					catch (Exception $e) {
						// Don't completely bail out here, just invalidate the cache and continue on.
						\Core\Cache::Delete('core-components');
						$tempcomponents = false;
					}
				}
			}
		}


		if(!$enablecache || $tempcomponents == false){
			\Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Scanning for component.xml files manually');
			Core\Utilities\Logger\write_debug('Scanning for component.xml files manually');

			// Core is first, (obviously)
			$tempcomponents['core'] = ComponentFactory::Load(ROOT_PDIR . 'core/component.xml');
			Core\Utilities\Logger\write_debug('Core component loaded');

			// First, build my cache of components, regardless if the component is installed or not.
			$dh = opendir(ROOT_PDIR . 'components');
			if (!$dh) throw new CoreException('Unable to open directory [' . ROOT_PDIR . 'components/] for reading.');

			// This will read through every directory in 'components', which is
			// where all components in the system are installed to.
			while (($file = readdir($dh)) !== false) {
				// skip hidden directories.
				if ($file{0} == '.') continue;

				// skip non-directories
				if (!is_dir(ROOT_PDIR . 'components/' . $file)) continue;

				// Skip directories that do not have a readable component.xml file.
				if (!is_readable(ROOT_PDIR . 'components/' . $file . '/component.xml')) continue;

				//Core\Utilities\Logger\write_debug(' * Loading component ' . $file);
				$c = ComponentFactory::Load(ROOT_PDIR . 'components/' . $file . '/component.xml');
				Core\Utilities\Logger\write_debug('Opened component ' . $file);

				// All further operations are case insensitive.
				// The original call to Component needs to be case sensitive because it sets the filename to pull.
				$file = strtolower($file);

				// If the component was flagged as invalid.. just skip to the next one.
				if (!$c->isValid()) {
					if (DEVELOPMENT_MODE) {
						\Core\set_message('Component ' . $c->getName() . ' appears to be invalid.');
					}
					continue;
				}


				$tempcomponents[$file] = $c;
				unset($c);
			}
			closedir($dh);
			\Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Component XML files scanned');

			// Now I probably could actually load the components!

			foreach ($tempcomponents as $c) {
				/** @var Component_2_1 $c */
				try {
					// Load some of the data in the class so that it's available in the cached version.
					// This is because the component 2.1 has built-in caching for many of the XML requests.
					// by calling them once, that lookup data is cached in that component, which in turn gets
					// copied to the cache version here!
					$c->load();
					$c->getClassList();
					$c->getViewSearchDir();
					$c->getSmartyPluginDirectory();
					$c->getWidgetList();
				}
				catch (Exception $e) {
					var_dump($e);
					die();
				}
			}

			// Cache this list!
			if($enablecache){
				Core\Utilities\Logger\write_debug(' * Caching core-components for next pass');
				\Core\Cache::Set('core-components', $tempcomponents, (3600 * 24));
			}
		}

		$list = $tempcomponents;

		\Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Component metadata loaded, starting registration');
		Core\Utilities\Logger\write_debug(' * Component metadata loaded, starting registration');

		// The core component at a minimum needs to be loaded and registered.
		//		$this->_registerComponent($list['core']);
		//		$this->_components['core']->loadFiles();
		//		unset($list['core']);

		// Now that I have a list of components available, copy them into a list of 
		//	components that are installed.

		do {
			$size = sizeof($list);
			foreach ($list as $n => $c) {
				/** @var $c Component_2_1 */

				// Disabled components don't get recognized.
				if($c->isInstalled() && !$c->isEnabled()){
					// But they do get sent to the disabled list!
					$this->_componentsDisabled[$n] = $c;

					unset($list[$n]);
					continue;
				}

				// Clear out the temporary class list
				$this->_tmpclasses = [];

				// If it's loaded, register it and remove it from the list!
				if ($c->isInstalled() && $c->isLoadable() && $c->loadFiles()) {

					try{
						// Allow for on-the-fly package upgrading regardless of DEV mode or not.
						if ($c->needsUpdated()) {

							// Load this component's classes in case an upgrade operation requires one.
							// This allows a component to be loaded partially without completely being loaded.
							$this->_tmpclasses = $c->getClassList();

							// Lock the site first!
							// This is because some upgrade procedures take a long time to upgrade.
							file_put_contents(TMP_DIR . 'lock.message', 'Core Plus is being upgraded, please try again in a minute. ');
							$c->upgrade();
							unlink(TMP_DIR . 'lock.message');
						}
					}
					catch(Exception $e){
						SystemLogModel::LogErrorEvent('/core/component/failedupgrade', 'Ignoring component [' . $n . '] due to an error during upgrading!', $e->getMessage());

						unlink(TMP_DIR . 'lock.message');
						//$c->disable();
						$this->_componentsDisabled[$n] = $c;
						unset($list[$n]);
						continue;
					}

					try{
						$this->_components[$n] = $c;
						$this->_registerComponent($c);
						$c->loadSupplementalModels();
					}
					catch(Exception $e){
						SystemLogModel::LogErrorEvent('/core/component/failedregister', 'Ignoring component [' . $n . '] due to an error during registration!', $e->getMessage());

						//$c->disable();
						$this->_componentsDisabled[$n] = $c;
						unset($list[$n]);
						continue;
					}

					unset($list[$n]);
					continue;
				}


				// Allow for on-the-fly package upgrading regardless of DEV mode or not.
				// Guess this is needed for the loadFiles part...
				if ($c->isInstalled() && $c->needsUpdated() && $c->isLoadable()) {
					// Lock the site first!
					// This is because some upgrade procedures take a long time to upgrade.
					file_put_contents(TMP_DIR . 'lock.message', 'Core Plus is being upgraded, please try again in a minute. ');

					$c->upgrade();
					$c->loadFiles();
					$this->_components[$n] = $c;
					$this->_registerComponent($c);
					unlink(TMP_DIR . 'lock.message');

					unset($list[$n]);
					continue;
				}

				// Allow packages to be auto-installed if in DEV mode.
				// If DEV mode is not enabled, just install the new component, do not enable it.
				if (!$c->isInstalled() && $c->isLoadable()) {
					// Load this component's classes in case an install operation requires one.
					// This allows a component to be loaded partially without completely being loaded.
					$this->_tmpclasses = $c->getClassList();

					// w00t
					$c->install();
					// BLAH, until I fix the disabled-packages-not-viewable bug...
					$c->enable();
					$c->loadFiles();
					$this->_components[$n] = $c;
					$this->_registerComponent($c);

					/*
					if(!DEVELOPMENT_MODE){
						$c->disable();
					}
					else{
						$c->enable();
						$c->loadFiles();
						$this->_components[$n] = $c;
						$this->_registerComponent($c);
					}
					*/
					unset($list[$n]);
					continue;
				}
			}
		}
		while ($size > 0 && ($size != sizeof($list)));

		// If dev mode is enabled, display a list of components installed but not loadable.

		foreach ($list as $n => $c) {

			//$this->_components[$n] = $c;
			$this->_componentsDisabled[$n] = $c;

			// Ignore anything with the execmode different, those should be minor notices for debugging if anything.
			if ($c->error & Component_2_1::ERROR_WRONGEXECMODE) continue;

			if (DEVELOPMENT_MODE) {
				SystemLogModel::LogErrorEvent('/core/component/missingrequirement', 'Could not load installed component ' . $n . ' due to requirement failed.', $c->getErrors());
			}
		}

		// Don't forget to load the themes too!
		if(class_exists('ThemeHandler')){
			foreach(ThemeHandler::GetAllThemes() as $theme){
				/** @var $theme Theme */
				$theme->load();
			}
		}

		// Lastly, make sure that the template path cache is updated!
		if(class_exists('\\Core\\Templates\\Template')){
			\Core\Templates\Template::RequeryPaths();	
		}
	}
コード例 #6
0
	/**
	 * Render the View to the browser.
	 */
	public function render(){
		\Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Starting PageRequest->render()');

		$view = $this->getView();
		$page = $this->getPageModel();

		// Dispatch the hooks here if it's a 404 or 403.
		if ($view->error == View::ERROR_ACCESSDENIED || $view->error == View::ERROR_NOTFOUND) {
			// Let other things chew through it... (optionally)
			HookHandler::DispatchHook('/core/page/error-' . $view->error, $view);
		}

		try {
			// This will pre-fetch the contents of the entire page and store it into memory.
			// If it is cacheable, then it will be cached and used for the next execution.

			// If the user has the view user activity permission, add the link to that page!
			if(\Core\user()->checkAccess('p:user_activity_list') && $page && $page->exists()){
				$view->addControl(
					'User Activity Details',
					'/useractivity/details?filter[baseurl]=' . $page->get('baseurl'),
					'eye'
				);
			}

			$view->fetch();
		}
		catch (Exception $e) {
			// If something happens in the rendering of the template... consider it a server error.
			$view->error   = View::ERROR_SERVERERROR;
			$view->baseurl = '/error/error/500';
			$view->setParameters(array());
			$view->templatename   = '/pages/error/error500.tpl';
			$view->mastertemplate = ConfigHandler::Get('/theme/default_template');
			$view->assignVariable('exception', $e);
			\Core\ErrorManagement\exception_handler($e);

			$view->fetch();
		}


		if($this->isCacheable()){
			$uakey = \Core\UserAgent::Construct()->getPseudoIdentifier();
			$urlkey = $this->host . $this->uri;
			$expires = $page->get('expires'); // Number of seconds.
			$key = 'page-cache-' . md5($urlkey . '-' . $uakey);

			$d = new \Core\Date\DateTime();
			$d->modify('+' . $expires . ' seconds');

			$view->headers['Cache-Control'] = 'max-age=' . $expires;
			$view->headers['Expires'] = $d->format('r', \Core\Date\Timezone::TIMEZONE_GMT);
			$view->headers['Vary'] = 'Accept-Encoding,User-Agent,Cookie';
			$view->headers['X-Core-Cached-Date'] = \Core\Date\DateTime::NowGMT('r');
			$view->headers['X-Core-Cached-Server'] = 1; // @todo Implement multi-server support.
			$view->headers['X-Core-Cached-Render-Time'] = \Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->getTimeFormatted();

			// Record the actual View into cache.
			\Core\Cache::Set($key, $view, $expires);

			// And record the key onto an index cache record so there's a record of what to delete on updates.
			$indexkey = $page->getIndexCacheKey();
			$index = \Core\Cache::Get($indexkey, SECONDS_ONE_DAY);
			if(!$index){
				$index = [];
			}
			$index[] = $key;
			\Core\Cache::Set($indexkey, $index, SECONDS_ONE_DAY);
		}
		elseif(($reason = $this->isNotCacheableReason()) !== null){
			$view->headers['X-Core-NotCached-Reason'] = $reason;
		}
		$view->headers['X-Core-Render-Time'] = \Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->getTimeFormatted();

		$view->render();

		// Make sure I update any existing page now that the controller has ran.
		if ($page && $page->exists() && $view->error == View::ERROR_NOERROR) {

			// Only increase the pageview count if the visitor is not a bot.
			// UA detection isn't very accurate, but this isn't for precision accuracy, merely a rough estimate.
			if(!\Core\UserAgent::Construct()->isBot()){
				$page->set('pageviews', $page->get('pageviews') + 1);
			}

			$page->set('last_template', $view->templatename);
			$page->set('body', $view->fetchBody());

			$page->save();
		}

		// Just before the page stops execution...
		HookHandler::DispatchHook('/core/page/postrender');
	}
コード例 #7
0
ファイル: IPLookup.php プロジェクト: nicholasryan/CorePlus
 public function __construct($ip_addr)
 {
     try {
         if ($ip_addr == '127.0.0.1') {
             // Load local connections up with Columbus, OH.
             // Why?  ;)
             $cache = ['city' => 'Columbus', 'province' => 'OH', 'country' => 'US', 'timezone' => 'America/New_York', 'postal' => '43215'];
         } else {
             $cacheKey = 'iplookup-' . $ip_addr;
             $cache = Cache::Get($cacheKey);
             if (!$cache) {
                 $reader = new \GeoIp2\Database\Reader(ROOT_PDIR . 'components/geographic-codes/libs/maxmind-geolite-db/GeoLite2-City.mmdb');
                 /** @var \GeoIp2\Model\CityIspOrg $geo */
                 $geo = $reader->cityIspOrg($ip_addr);
                 //$geo = $reader->cityIspOrg('67.149.214.236');
                 $reader->close();
                 $sd = isset($geo->subdivisions[0]) ? $geo->subdivisions[0] : null;
                 $cache = ['city' => $geo->city->name, 'province' => $sd ? $sd->isoCode : '', 'country' => $geo->country->isoCode, 'timezone' => $geo->location->timeZone, 'postal' => $geo->postal->code];
                 Cache::Set($cacheKey, $cache, SECONDS_ONE_WEEK);
             }
         }
     } catch (\Exception $e) {
         // Well, we tried!  Load something at least.
         $cacheKey = 'iplookup-' . $ip_addr;
         $cache = ['city' => 'McMurdo Base', 'province' => '', 'country' => 'AQ', 'timezone' => 'CAST', 'postal' => ''];
         Cache::Set($cacheKey, $cache, SECONDS_ONE_HOUR);
     }
     $this->city = $cache['city'];
     $this->province = $cache['province'];
     $this->country = $cache['country'];
     $this->timezone = $cache['timezone'];
     $this->postal = $cache['postal'];
 }