2326 lines
		
	
	
	
		
			58 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			2326 lines
		
	
	
	
		
			58 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
 | 
						|
namespace gp{
 | 
						|
 | 
						|
	defined('is_running') or die('Not an entry point...');
 | 
						|
 | 
						|
	class tool{
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return the type of response was requested by the client
 | 
						|
		 * @since 3.5b2
 | 
						|
		 * @return string
 | 
						|
		 */
 | 
						|
		public static function RequestType(){
 | 
						|
 | 
						|
			$types = ['body', 'flush', 'json', 'content', 'admin'];
 | 
						|
 | 
						|
			if( isset($_REQUEST['gpreq']) && in_array($_REQUEST['gpreq'], $types) ){
 | 
						|
				return $_REQUEST['gpreq'];
 | 
						|
			}
 | 
						|
 | 
						|
			return 'template';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Send a 304 Not Modified Response to the client if HTTP_IF_NONE_MATCH matched $etag and headers have not already been sent
 | 
						|
		 * Othewise, send the etag
 | 
						|
		 * @param string $etag The calculated etag for the current page
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function Send304($etag){
 | 
						|
			global $config;
 | 
						|
 | 
						|
			if( !$config['etag_headers'] ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			if( headers_sent() ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			//always send the etag
 | 
						|
			header('ETag: "' . $etag . '"');
 | 
						|
 | 
						|
			if( empty($_SERVER['HTTP_IF_NONE_MATCH']) ||
 | 
						|
				trim($_SERVER['HTTP_IF_NONE_MATCH'], '"') != $etag
 | 
						|
			){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			//don't use ob_get_level() in while loop to prevent endless loops;
 | 
						|
			$level = ob_get_level();
 | 
						|
			while( $level > 0 ){
 | 
						|
				@ob_end_clean();
 | 
						|
				$level--;
 | 
						|
			}
 | 
						|
 | 
						|
			// 304 should not have a response body or Content-Length header
 | 
						|
			//header('Not Modified', true, 304);
 | 
						|
			self::status_header(304, 'Not Modified');
 | 
						|
			header('Connection: close');
 | 
						|
			exit();
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Set HTTP status header.
 | 
						|
		 * Modified From Wordpress
 | 
						|
		 *
 | 
						|
		 * @since 2.3.3
 | 
						|
		 * @uses apply_filters() Calls 'status_header' on status header string, HTTP
 | 
						|
		 *		HTTP code, HTTP code description, and protocol string as separate
 | 
						|
		 *		parameters.
 | 
						|
		 *
 | 
						|
		 * @param int $header HTTP status code
 | 
						|
		 * @param string $text HTTP status
 | 
						|
		 * @return unknown
 | 
						|
		 */
 | 
						|
		public static function status_header($header, $text){
 | 
						|
 | 
						|
			$protocol = '';
 | 
						|
			if( isset($_SERVER['SERVER_PROTOCOL']) ){
 | 
						|
				$protocol = $_SERVER['SERVER_PROTOCOL'];
 | 
						|
			}
 | 
						|
			if( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol ){
 | 
						|
				$protocol = 'HTTP/1.0';
 | 
						|
			}
 | 
						|
 | 
						|
			$status_header = "$protocol $header $text";
 | 
						|
			return @header($status_header, true, $header);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function GenEtag(){
 | 
						|
			global $dirPrefix, $dataDir;
 | 
						|
			$etag = '';
 | 
						|
			$args = func_get_args();
 | 
						|
			$args[] = $dataDir . $dirPrefix;
 | 
						|
			foreach($args as $arg){
 | 
						|
				if( !ctype_digit($arg) ){
 | 
						|
					$arg = crc32( $arg );
 | 
						|
					$arg = sprintf("%u\n", $arg);
 | 
						|
				}
 | 
						|
				$etag .= base_convert($arg, 10, 36);
 | 
						|
			}
 | 
						|
			return $etag;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Generate an etag from the filemtime and filesize of each file
 | 
						|
		 * @param array $files
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function FilesEtag($files){
 | 
						|
			$modified				= 0;
 | 
						|
			$content_length			= 0;
 | 
						|
			foreach($files as $file){
 | 
						|
				$content_length		+= @filesize($file);
 | 
						|
				$modified			= max($modified, @filemtime($file));
 | 
						|
			}
 | 
						|
 | 
						|
			return self::GenEtag($modified, $content_length);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function CheckTheme(){
 | 
						|
			global $page;
 | 
						|
			if( $page->theme_name === false ){
 | 
						|
				$page->SetTheme();
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return an array of information about the layout
 | 
						|
		 * @param string $layout the layout key
 | 
						|
		 * @param bool $check_existence Whether or not to check for the existence of the template.php file
 | 
						|
		 * @return mixed false | array
 | 
						|
		 */
 | 
						|
		public static function LayoutInfo($layout, $check_existence=true){
 | 
						|
			global $gpLayouts, $dataDir;
 | 
						|
 | 
						|
			if( !isset($gpLayouts[$layout]) ){
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			$layout_info = $gpLayouts[$layout];
 | 
						|
			$layout_info += ['is_addon' => false];
 | 
						|
			$layout_info['theme_name'] = self::DirName($layout_info['theme']);
 | 
						|
			$layout_info['theme_color'] = basename($layout_info['theme']);
 | 
						|
 | 
						|
			$relative = '/themes/';
 | 
						|
			if( $layout_info['is_addon'] ){
 | 
						|
				$relative = '/data/_themes/';
 | 
						|
			}
 | 
						|
			$layout_info['path'] = $relative . $layout_info['theme'];
 | 
						|
 | 
						|
			$layout_info['dir'] = $dataDir . $relative . $layout_info['theme_name'];
 | 
						|
			if( $check_existence && !file_exists($layout_info['dir'] . '/template.php') ){
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			return $layout_info;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Returns the layout id used by the current page
 | 
						|
		 * @return string $layout_id
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetCurrentLayoutId(){
 | 
						|
			global $page, $config;
 | 
						|
 | 
						|
			if( !is_object($page) || $page->pagetype === 'admin_display' ){
 | 
						|
				return '';
 | 
						|
			}
 | 
						|
 | 
						|
			if( isset($page->TitleInfo['gpLayout']) ){
 | 
						|
				// page uses a custom layout
 | 
						|
				return $page->TitleInfo['gpLayout'];
 | 
						|
			}
 | 
						|
 | 
						|
			$inheritance = \gp\admin\Menu\Tools::Inheritance_Info();
 | 
						|
 | 
						|
			if( isset($inheritance[$page->gp_index]['parent_layout']) ){
 | 
						|
				// page inherits the layout from main menu parent
 | 
						|
				return $inheritance[$page->gp_index]['parent_layout'];
 | 
						|
			}
 | 
						|
 | 
						|
			// page uses the default layout
 | 
						|
			return $config['gpLayout'];
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Returns detailed information of the layout used by the current page
 | 
						|
		 * @return array $layout_info
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetCurrentLayoutInfo(){
 | 
						|
			global $gpLayouts;
 | 
						|
		
 | 
						|
			$layout_id = self::GetCurrentLayoutId();
 | 
						|
			if( empty($layout_id) ){
 | 
						|
				return [];
 | 
						|
			}
 | 
						|
			$layout_info = $gpLayouts[$layout_id];
 | 
						|
			$layout_info['layout_id'] = $layout_id;
 | 
						|
 | 
						|
			return $layout_info;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/*
 | 
						|
		 *
 | 
						|
		 *
 | 
						|
		 * Entry Functions
 | 
						|
		 *
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
 | 
						|
		public static function EntryPoint($level=0, $expecting='index.php', $sessions=true){
 | 
						|
 | 
						|
			self::CheckRequest();
 | 
						|
 | 
						|
			clearstatcache();
 | 
						|
 | 
						|
			$ob_gzhandler = false;
 | 
						|
			if( !self::IniGet('zlib.output_compression') && 'ob_gzhandler' != ini_get('output_handler') ){
 | 
						|
				@ob_start('ob_gzhandler'); //ini_get() does not always work for this test
 | 
						|
				$ob_gzhandler = true;
 | 
						|
			}
 | 
						|
 | 
						|
			self::SetGlobalPaths($level, $expecting);
 | 
						|
			spl_autoload_register(['\\gp\\tool', 'Autoload']);
 | 
						|
 | 
						|
			includeFile('tool/functions.php');
 | 
						|
			if( $sessions ){
 | 
						|
				ob_start(['\\gp\\tool\\Output', 'BufferOut']);
 | 
						|
			}elseif( !$ob_gzhandler ){
 | 
						|
				ob_start();
 | 
						|
			}
 | 
						|
 | 
						|
			self::RequestLevel();
 | 
						|
			self::GetConfig();
 | 
						|
			self::SetLinkPrefix();
 | 
						|
			self::SetCookieArgs();
 | 
						|
			if( $sessions ){
 | 
						|
				self::sessions();
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Setup SPL Autoloading
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function Autoload($class){
 | 
						|
			global $config, $dataDir;
 | 
						|
 | 
						|
			$class		= trim($class, '\\');
 | 
						|
			$parts		= explode('\\', $class);
 | 
						|
			$part_0		= array_shift($parts);
 | 
						|
 | 
						|
			if( !$parts ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			//gp namespace
 | 
						|
			if( $part_0 === 'gp' ){
 | 
						|
				$path	= $dataDir . '/include/' . implode('/', $parts) . '.php';
 | 
						|
				if( file_exists($path) ){
 | 
						|
					include_once( $path );
 | 
						|
				}else{
 | 
						|
					trigger_error('Autoload for gp namespace failed. Class: ' . $class . ' path: ' . $path);
 | 
						|
				}
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			//look for addon namespace
 | 
						|
			if( $part_0 === 'Addon' ){
 | 
						|
 | 
						|
				$namespace = array_shift($parts);
 | 
						|
				if( !$parts ){
 | 
						|
					return;
 | 
						|
				}
 | 
						|
 | 
						|
				foreach($config['addons'] as $addon_key => $addon){
 | 
						|
					if( isset($addon['Namespace']) && $addon['Namespace'] == $namespace ){
 | 
						|
 | 
						|
						\gp\tool\Plugins::SetDataFolder($addon_key);
 | 
						|
						$path = \gp\tool\Plugins::$current['code_folder_full'] . '/' . implode('/', $parts) . '.php';
 | 
						|
 | 
						|
						if( file_exists($path) ){
 | 
						|
							include_once($path);
 | 
						|
						}else{
 | 
						|
							trigger_error('Autoload for addon namespace failed. Class: ' . $class . ' path: ' . $path);
 | 
						|
						}
 | 
						|
 | 
						|
						\gp\tool\Plugins::ClearDataFolder();
 | 
						|
					}
 | 
						|
				}
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			//thirdparty
 | 
						|
			$path = $dataDir . '/include/thirdparty/' . str_replace('\\', '/', $class) . '.php';
 | 
						|
			if( file_exists($path) ){
 | 
						|
				include_once($path);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Reject Invalid Requests
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function CheckRequest(){
 | 
						|
 | 
						|
			if( count($_POST) == 0 ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			if( !isset($_SERVER['CONTENT_LENGTH']) ){
 | 
						|
				header('HTTP/1.1 503 Service Temporarily Unavailable');
 | 
						|
				header('Status: 503 Service Temporarily Unavailable');
 | 
						|
				header('Retry-After: 300');//300 seconds
 | 
						|
				die();
 | 
						|
			}
 | 
						|
 | 
						|
			if( function_exists('getallheaders') ){
 | 
						|
 | 
						|
				$headers = getallheaders();
 | 
						|
				if( !isset($headers['Content-Length']) ){
 | 
						|
					header('HTTP/1.1 503 Service Temporarily Unavailable');
 | 
						|
					header('Status: 503 Service Temporarily Unavailable');
 | 
						|
					header('Retry-After: 300');//300 seconds
 | 
						|
					die();
 | 
						|
				}
 | 
						|
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function SetGlobalPaths($DirectoriesAway, $expecting){
 | 
						|
			global $dataDir, $dirPrefix, $rootDir;
 | 
						|
 | 
						|
			$rootDir = self::DirName(__FILE__, 2);
 | 
						|
 | 
						|
			// dataDir, make sure it contains $expecting. Some servers using cgi do not set this properly
 | 
						|
			// required for the Multi-Site plugin
 | 
						|
			$dataDir = self::GetEnv('SCRIPT_FILENAME', $expecting);
 | 
						|
			if( $dataDir !== false ){
 | 
						|
				$dataDir = self::ReduceGlobalPath($dataDir, $DirectoriesAway);
 | 
						|
			}else{
 | 
						|
				$dataDir = $rootDir;
 | 
						|
			}
 | 
						|
			if( $dataDir == '/' ){
 | 
						|
				$dataDir = '';
 | 
						|
			}
 | 
						|
 | 
						|
			//$dirPrefix
 | 
						|
			$dirPrefix = self::GetEnv('SCRIPT_NAME', $expecting);
 | 
						|
			if( $dirPrefix === false ){
 | 
						|
				$dirPrefix = self::GetEnv('PHP_SELF', $expecting);
 | 
						|
			}
 | 
						|
 | 
						|
			//remove everything after $expecting, $dirPrefix can at times include the PATH_INFO
 | 
						|
			$pos = strpos($dirPrefix,$expecting);
 | 
						|
			$dirPrefix = substr($dirPrefix, 0, $pos+strlen($expecting));
 | 
						|
 | 
						|
			$dirPrefix = self::ReduceGlobalPath($dirPrefix, $DirectoriesAway);
 | 
						|
			if( $dirPrefix == '/' ){
 | 
						|
				$dirPrefix = '';
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Convert backslashes to forward slashes
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function WinPath($path){
 | 
						|
			return str_replace('\\', '/', $path);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Returns parent directory's path with forward slashes
 | 
						|
		 * php's dirname() method may change slashes from / to \
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function DirName($path, $dirs=1){
 | 
						|
			for($i = 0; $i < $dirs; $i++){
 | 
						|
				$path = dirname($path);
 | 
						|
			}
 | 
						|
			return self::WinPath( $path );
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Determine if this installation is supressing index.php in urls or not
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function SetLinkPrefix(){
 | 
						|
			global $linkPrefix, $dirPrefix, $config;
 | 
						|
 | 
						|
			$linkPrefix = $dirPrefix;
 | 
						|
 | 
						|
			// gp_rewrite = 'On' and gp_rewrite = 'gpuniq' are deprecated since 4.1
 | 
						|
			// gp_rewrite = bool will still be used internally
 | 
						|
			if( isset($_SERVER['gp_rewrite']) ){
 | 
						|
 | 
						|
				if( $_SERVER['gp_rewrite'] === true || $_SERVER['gp_rewrite'] == 'On' ){
 | 
						|
					$_SERVER['gp_rewrite'] = true;
 | 
						|
				}elseif( $_SERVER['gp_rewrite'] == @substr($config['gpuniq'], 0, 7) ){
 | 
						|
					$_SERVER['gp_rewrite'] = true;
 | 
						|
				}
 | 
						|
 | 
						|
			}elseif( isset($_REQUEST['gp_rewrite']) ){
 | 
						|
				$_SERVER['gp_rewrite'] = true;
 | 
						|
 | 
						|
			// gp_indexphp is deprecated since 4.1
 | 
						|
			}elseif( defined('gp_indexphp') ){
 | 
						|
 | 
						|
				if( \gp_indexphp === false ){
 | 
						|
					$_SERVER['gp_rewrite'] = true;
 | 
						|
				}
 | 
						|
 | 
						|
			}
 | 
						|
 | 
						|
			unset($_GET['gp_rewrite']);
 | 
						|
			unset($_REQUEST['gp_rewrite']);
 | 
						|
 | 
						|
			if( !isset($_SERVER['gp_rewrite']) ){
 | 
						|
				$_SERVER['gp_rewrite'] = false;
 | 
						|
			}
 | 
						|
 | 
						|
			if( !$_SERVER['gp_rewrite'] ){
 | 
						|
				$linkPrefix .= '/index.php';
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get the environment variable and make sure it contains an expected value
 | 
						|
		 *
 | 
						|
		 * @param string $var The key of the requested environment variable
 | 
						|
		 * @param string $expected Optional string that is expected as part of the environment variable value
 | 
						|
		 *
 | 
						|
		 * @return mixed Returns false if $expected is not found, otherwise it returns the environment value.
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetEnv($var, $expecting=false){
 | 
						|
			$value = false;
 | 
						|
			if( isset($_SERVER[$var]) ){
 | 
						|
				$value = $_SERVER[$var];
 | 
						|
			}else{
 | 
						|
				$value = getenv($var);
 | 
						|
			}
 | 
						|
			if( $expecting && strpos($value, $expecting) === false ){
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
			return $value;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get the ini value and return a boolean casted value when appropriate: On, Off, 1, 0, True, False, Yes, No
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function IniGet($key){
 | 
						|
			$value = ini_get($key);
 | 
						|
			if( empty($value) ){
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			$lower_value = trim(strtolower($value));
 | 
						|
			switch($lower_value){
 | 
						|
				case 'true':
 | 
						|
				case 'yes':
 | 
						|
				case 'on':
 | 
						|
				case '1':
 | 
						|
					return true;
 | 
						|
 | 
						|
				case 'false':
 | 
						|
				case 'no':
 | 
						|
				case 'off':
 | 
						|
				case '0':
 | 
						|
					return false;
 | 
						|
			}
 | 
						|
 | 
						|
			return $value;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function ReduceGlobalPath($path, $DirectoriesAway){
 | 
						|
			return self::DirName($path, $DirectoriesAway + 1);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		//use dirPrefix to find requested level
 | 
						|
		public static function RequestLevel(){
 | 
						|
			global $dirPrefixRel, $dirPrefix;
 | 
						|
 | 
						|
			$path = $_SERVER['REQUEST_URI'];
 | 
						|
 | 
						|
			//strip the query string.. in case it contains "/"
 | 
						|
			$pos = mb_strpos($path, '?');
 | 
						|
			if( $pos > 0 ){
 | 
						|
				$path =  mb_substr($path, 0, $pos);
 | 
						|
			}
 | 
						|
 | 
						|
			//dirPrefix will be percent-decoded
 | 
						|
			$path = rawurldecode($path); //%20 ...
 | 
						|
 | 
						|
			if( !empty($dirPrefix) ){
 | 
						|
				$pos = mb_strpos($path, $dirPrefix);
 | 
						|
				if( $pos !== false ){
 | 
						|
					$path = mb_substr($path, $pos + mb_strlen($dirPrefix));
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			$path = ltrim($path, '/');
 | 
						|
			$count = substr_count($path, '/');
 | 
						|
			if( $count == 0 ){
 | 
						|
				$dirPrefixRel = '.';
 | 
						|
			}else{
 | 
						|
				$dirPrefixRel = str_repeat('../', $count);
 | 
						|
				$dirPrefixRel = rtrim($dirPrefixRel, '/'); //GetDir() arguments always start with /
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Escape ampersands in hyperlink attributes and other html tag attributes
 | 
						|
		 *
 | 
						|
		 * @param string $str The string value of an html attribute
 | 
						|
		 * @return string The escaped string
 | 
						|
		 */
 | 
						|
		public static function Ampersands($str){
 | 
						|
			return preg_replace('/&(?![#a-zA-Z0-9]{2,9};)/S', '&', $str);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Similar to htmlspecialchars, but designed for labels
 | 
						|
		 * Does not convert existing ampersands "&"
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function LabelSpecialChars($string){
 | 
						|
			return str_replace(
 | 
						|
				['<',		'>',	'"',		"'"],
 | 
						|
				['<',	'>',	'"',	'''],
 | 
						|
				$string
 | 
						|
			);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return an html hyperlink
 | 
						|
		 *
 | 
						|
		 * @param string $href The href value relative to the installation root (without index.php)
 | 
						|
		 * @param string $label Text or html to be displayed within the hyperlink
 | 
						|
		 * @param string $query Optional query to be used with the href
 | 
						|
		 * @param string|array $attr Optional string of attributes like title=".." and class=".."
 | 
						|
		 * @param mixed $nonce_action If false, no nonce will be added to the query. Given a string, it will be used as the first argument in \gp\tool\Nonce::Create()
 | 
						|
		 *
 | 
						|
		 * @return string The formatted html hyperlink
 | 
						|
		 */
 | 
						|
		public static function Link($href='', $label='', $query='', $attr='', $nonce_action=false){
 | 
						|
			return '<a href="' . self::GetUrl($href, $query, true, $nonce_action) . '" '
 | 
						|
				. self::LinkAttr($attr,$label) . '>'
 | 
						|
				. self::Ampersands($label)
 | 
						|
				. '</a>';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * @param string|array $attr
 | 
						|
		 * @param string $label
 | 
						|
		 */
 | 
						|
		public static function LinkAttr($attr='', $label=''){
 | 
						|
 | 
						|
			$string		= '';
 | 
						|
			$has_title	= false;
 | 
						|
 | 
						|
			if( is_array($attr) ){
 | 
						|
 | 
						|
				// update old <a name="cmd"> links to <a data-cmd="cmd">
 | 
						|
				// @deprecated
 | 
						|
				$attr = array_change_key_case($attr);
 | 
						|
				$has_title = isset($attr['title']);
 | 
						|
				if( isset($attr['name']) && !isset($attr['data-cmd']) ){
 | 
						|
					trigger_error('deprecated use of name attribute (use data-cmd attribute instead)');
 | 
						|
					$attr['data-cmd'] = $attr['name'];
 | 
						|
					unset($attr['name']);
 | 
						|
				}
 | 
						|
 | 
						|
				$nonce_cmds = ['creq', 'cnreq', 'postlink', 'post'];
 | 
						|
				if( isset($attr['data-cmd']) && in_array($attr['data-cmd'], $nonce_cmds) ){
 | 
						|
					$attr['data-nonce'] = \gp\tool\Nonce::Create('post', true);
 | 
						|
				}
 | 
						|
				$string = \gp\tool\HTML::Attributes($attr);
 | 
						|
 | 
						|
			}else{
 | 
						|
 | 
						|
				$string = $attr;
 | 
						|
				if( strpos($attr, 'title="') !== false){
 | 
						|
					$has_title = true;
 | 
						|
				}
 | 
						|
 | 
						|
				// backwards compatibility hack to be removed in future releases
 | 
						|
				// @since 3.6
 | 
						|
				if( strpos($string, 'name="postlink"') !== false ){
 | 
						|
					trigger_error('deprecated use of name attribute (use data-cmd attribute instead)');
 | 
						|
					$string .= ' data-nonce="' . \gp\tool\Nonce::Create('post', true) . '"';
 | 
						|
 | 
						|
				// @since 4.1
 | 
						|
				}elseif( strpos($string, 'name="cnreq"') !== false || strpos($string, 'name="creq"') !== false ){
 | 
						|
					trigger_error('deprecated use of name attribute (use data-cmd attribute instead)');
 | 
						|
					$string .= ' data-nonce="' . \gp\tool\Nonce::Create('post', true) . '"';
 | 
						|
				}
 | 
						|
 | 
						|
			}
 | 
						|
 | 
						|
			if( !$has_title && !empty($label) ){
 | 
						|
				$string .= ' title="' . self::Ampersands(strip_tags($label)) . '" ';
 | 
						|
			}
 | 
						|
 | 
						|
			return trim($string);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return an html hyperlink for a page
 | 
						|
		 *
 | 
						|
		 * @param string $title The title of the page
 | 
						|
		 * @return string The formatted html hyperlink
 | 
						|
		 */
 | 
						|
		public static function Link_Page($title=''){
 | 
						|
			global $config, $gp_index;
 | 
						|
 | 
						|
			if( empty($title) && !empty($config['homepath']) ){
 | 
						|
				$title = $config['homepath'];
 | 
						|
			}
 | 
						|
 | 
						|
			$label = self::GetLabel($title);
 | 
						|
 | 
						|
			return self::Link($title, $label);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function GetUrl($href='', $query='', $ampersands=true, $nonce_action=false){
 | 
						|
			global $linkPrefix, $config;
 | 
						|
 | 
						|
			$filtered = \gp\tool\Plugins::Filter('GetUrl', [[$href, $query]]);
 | 
						|
			if( is_array($filtered) ){
 | 
						|
				list($href, $query) = $filtered;
 | 
						|
			}
 | 
						|
 | 
						|
			$href = self::SpecialHref($href);
 | 
						|
 | 
						|
			//home page link
 | 
						|
			if( isset($config['homepath']) && $href == $config['homepath'] ){
 | 
						|
				$href = $linkPrefix;
 | 
						|
				if( !$_SERVER['gp_rewrite'] ){
 | 
						|
					$href = self::DirName($href);
 | 
						|
				}
 | 
						|
				$href = rtrim($href, '/') . '/';
 | 
						|
			}else{
 | 
						|
				$href = $linkPrefix . '/' . ltrim($href, '/');
 | 
						|
			}
 | 
						|
 | 
						|
			$query = self::QueryEncode($query,$ampersands);
 | 
						|
 | 
						|
			if( $nonce_action ){
 | 
						|
				$nonce = \gp\tool\Nonce::Create($nonce_action);
 | 
						|
				if( !empty($query) ){
 | 
						|
					$query .= '&'; //in the cases where $ampersands is false, nonces are not used
 | 
						|
				}
 | 
						|
				$query .= '_gpnonce=' . $nonce;
 | 
						|
			}
 | 
						|
			if( !empty($query) ){
 | 
						|
				$query = '?' . ltrim($query, '?');
 | 
						|
			}
 | 
						|
 | 
						|
			return self::HrefEncode($href, $ampersands) . $query;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * translate special pages from key to title
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function SpecialHref($href){
 | 
						|
			global $gp_index;
 | 
						|
 | 
						|
			$href2 = '';
 | 
						|
			$pos = mb_strpos($href, '/');
 | 
						|
			if( $pos !== false ){
 | 
						|
				$href2 = mb_substr($href, $pos);
 | 
						|
				$href = mb_substr($href, 0, $pos);
 | 
						|
			}
 | 
						|
 | 
						|
			$lower = mb_strtolower($href);
 | 
						|
			if( !isset($gp_index[$href]) &&
 | 
						|
				strpos($lower, 'special_') === 0 &&
 | 
						|
				$index_title = self::IndexToTitle($lower)
 | 
						|
			){
 | 
						|
				$href = $index_title;
 | 
						|
			}
 | 
						|
 | 
						|
			return $href . $href2;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * RawUrlEncode but keeps the following characters: &, /, \
 | 
						|
		 * Slash is needed for hierarchical links
 | 
						|
		 * In case you'd like to learn about percent encoding: http://www.blooberry.com/indexdot/html/topics/urlencoding.htm
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function HrefEncode($href, $ampersands=true){
 | 
						|
			$ampersand = '&';
 | 
						|
			if( $ampersands ){
 | 
						|
				$ampersand = '&';
 | 
						|
			}
 | 
						|
			$href = rawurlencode($href);
 | 
						|
			return str_replace(
 | 
						|
				['%26amp%3B',	'%26',		'%2F',	'%5C'],
 | 
						|
				[$ampersand,	$ampersand,	'/',	'\\'],
 | 
						|
				$href
 | 
						|
			);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * RawUrlEncode parts of the query string ( characters except & and = )
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function QueryEncode($query, $ampersands=true){
 | 
						|
 | 
						|
			if( empty($query) ){
 | 
						|
				return '';
 | 
						|
			}
 | 
						|
 | 
						|
			$query = str_replace('+', '%20', $query); //in case urlencode() was used instead of rawurlencode()
 | 
						|
			if( strpos($query, '&') !== false ){
 | 
						|
				$parts = explode('&', $query);
 | 
						|
			}else{
 | 
						|
				$parts = explode('&', $query);
 | 
						|
			}
 | 
						|
 | 
						|
			$ampersand = $query = '';
 | 
						|
			foreach($parts as $part){
 | 
						|
				if( strpos($part, '=') ){
 | 
						|
					list($key,$value) = explode('=', $part, 2);
 | 
						|
					$query .= $ampersand . rawurlencode(rawurldecode($key)) . '=' . rawurlencode(rawurldecode($value));
 | 
						|
				}else{
 | 
						|
					$query .= $ampersand.rawurlencode(rawurldecode($part));
 | 
						|
				}
 | 
						|
				if( $ampersands ){
 | 
						|
					$ampersand = '&';
 | 
						|
				}else{
 | 
						|
					$ampersand = '&';
 | 
						|
				}
 | 
						|
			}
 | 
						|
			return $query;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function AbsoluteLink($href, $label, $query='', $attr=''){
 | 
						|
 | 
						|
			if( strpos($attr,'title="') === false){
 | 
						|
				$attr .= ' title="' . htmlspecialchars(strip_tags($label)) . '" ';
 | 
						|
			}
 | 
						|
 | 
						|
			return '<a href="' . self::AbsoluteUrl($href, $query) . '" ' . $attr . '>' . self::Ampersands($label) . '</a>';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function AbsoluteUrl($href='', $query='', $with_schema=true, $ampersands=true, $with_port=false){
 | 
						|
 | 
						|
			$server = self::ServerName(false, $with_port);
 | 
						|
			if( $server === false ){
 | 
						|
				return self::GetUrl($href, $query, $ampersands);
 | 
						|
			}
 | 
						|
 | 
						|
			$schema = '';
 | 
						|
			if( $with_schema ){
 | 
						|
				$schema = ( isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' ) ? 'https://' : 'http://';
 | 
						|
			}
 | 
						|
 | 
						|
			return $schema.$server.self::GetUrl($href,$query,$ampersands);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return ther server name
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function ServerName($strip_www=false, $with_port=false){
 | 
						|
 | 
						|
			$add_port = '';
 | 
						|
			if( isset($_SERVER['SERVER_NAME']) ){
 | 
						|
				$server = self::UrlChars($_SERVER['SERVER_NAME']);
 | 
						|
				if( $with_port && isset($_SERVER['SERVER_PORT']) ){
 | 
						|
					$port = $_SERVER['SERVER_PORT'];
 | 
						|
					if( $port != 80 && $port != 443 ){
 | 
						|
						$add_port = ':' . $port;
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}else{
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			if( $strip_www && strpos($server, 'www.') === 0 ){
 | 
						|
				$server = substr($server, 4);
 | 
						|
			}
 | 
						|
 | 
						|
			return $server . $add_port;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function UrlChars($string){
 | 
						|
			$string = str_replace(' ', '%20', $string);
 | 
						|
			return preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\[\]\\x80-\\xff]|i', '', $string);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get the full path of a physical file on the server
 | 
						|
		 * The query string component of a path should not be included but will be protected from being encoded
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetDir($dir='', $ampersands=false){
 | 
						|
			global $dirPrefix;
 | 
						|
 | 
						|
			$query = '';
 | 
						|
			$pos = mb_strpos($dir, '?');
 | 
						|
			if( $pos !== false ){
 | 
						|
				$query = mb_substr($dir, $pos);
 | 
						|
				$dir = mb_substr($dir, 0, $pos);
 | 
						|
			}
 | 
						|
			$dir = $dirPrefix . '/' . ltrim($dir, '/');
 | 
						|
			return self::HrefEncode($dir, $ampersands) . $query;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get the label for a page from it's index
 | 
						|
		 * @param string $index
 | 
						|
		 * @param bool $amp Whether or not to escape ampersand characters
 | 
						|
		 */
 | 
						|
		public static function GetLabelIndex($index=null, $amp=false){
 | 
						|
			global $gp_titles,$langmessage;
 | 
						|
 | 
						|
			$info = [];
 | 
						|
			if( isset($gp_titles[$index]) ){
 | 
						|
				$info = $gp_titles[$index];
 | 
						|
			}
 | 
						|
 | 
						|
			if( isset($info['label']) ){
 | 
						|
				$return = $info['label'];
 | 
						|
 | 
						|
			}elseif( isset($info['lang_index']) ){
 | 
						|
				$return = $langmessage[$info['lang_index']];
 | 
						|
 | 
						|
			}else{
 | 
						|
				$return = self::IndexToTitle($index);
 | 
						|
				$return = \gp\tool\Files::CleanLabel($return);
 | 
						|
			}
 | 
						|
			if( $amp ){
 | 
						|
				return str_replace('&', '&', $return);
 | 
						|
			}
 | 
						|
			return $return;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get the label for a page from it's title
 | 
						|
		 * @param string $title
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetLabel($title=null){
 | 
						|
			global $gp_titles, $gp_index, $langmessage;
 | 
						|
 | 
						|
			$return = false;
 | 
						|
			if( isset($gp_index[$title]) ){
 | 
						|
				$id = $gp_index[$title];
 | 
						|
				$info =& $gp_titles[$id];
 | 
						|
 | 
						|
				if( isset($info['label']) ){
 | 
						|
					$return = $info['label'];
 | 
						|
				}elseif( isset($info['lang_index']) ){
 | 
						|
					$return = $langmessage[$info['lang_index']];
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if( $return === false ){
 | 
						|
				$return = \gp\tool\Files::CleanLabel($title);
 | 
						|
			}
 | 
						|
 | 
						|
			return $return;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get the browser title for a page
 | 
						|
		 * @param string $title
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetBrowserTitle($title){
 | 
						|
			global $gp_titles, $gp_index;
 | 
						|
 | 
						|
			if( !isset($gp_index[$title]) ){
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			$index = $gp_index[$title];
 | 
						|
			$title_info = $gp_titles[$index];
 | 
						|
 | 
						|
			if( isset($title_info['browser_title']) ){
 | 
						|
				return $title_info['browser_title'];
 | 
						|
			}
 | 
						|
 | 
						|
			$label = self::GetLabel($title);
 | 
						|
 | 
						|
			return strip_tags($label);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Add js and css components to the current web page
 | 
						|
		 *
 | 
						|
		 * @static
 | 
						|
		 * @since 2.0b1
 | 
						|
		 * @param array|string $names can be either a csv (with or without space characters) or an array. Since 5.1.1
 | 
						|
		 */
 | 
						|
		public static function LoadComponents($names=''){
 | 
						|
			if( gettype($names) == 'array' ){
 | 
						|
				$names = implode(',', $names);
 | 
						|
			}
 | 
						|
			\gp\tool\Output::$components .= ',' . $names . ',';
 | 
						|
			\gp\tool\Output::$components = str_replace(',,', ',', \gp\tool\Output::$components);
 | 
						|
			\gp\tool\Output::$components = str_replace(' ', '', \gp\tool\Output::$components);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Add gallery js and css to the <head> section of a page
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function ShowingGallery(){
 | 
						|
			global $page, $config;
 | 
						|
 | 
						|
			static $showing = false;
 | 
						|
			if( $showing ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
			$showing = true;
 | 
						|
 | 
						|
			self::AddColorBox();
 | 
						|
			$css = \gp\tool\Plugins::OneFilter('Gallery_Style');
 | 
						|
			if( $css === false ){
 | 
						|
 | 
						|
				if( !empty($config['gallery_legacy_style']) ){
 | 
						|
					$page->css_user[] = '/include/css/legacy_gallery.css';
 | 
						|
					return;
 | 
						|
				}
 | 
						|
 | 
						|
				$page->css_user[] = '/include/css/default_gallery.css';
 | 
						|
				self::LoadComponents('dotdotdot');
 | 
						|
				$page->jQueryCode .= "\n" .
 | 
						|
					'$(".filetype-gallery .caption")'.
 | 
						|
						'.dotdotdot({ ' .
 | 
						|
							'watch : "window", ' .
 | 
						|
							'callback : function(isTruncated, orgContent){ ' .
 | 
						|
							'$(this).data("originalContent", orgContent); ' .
 | 
						|
						'}' .
 | 
						|
					'});';
 | 
						|
 | 
						|
				if( \gp\tool::LoggedIn() ){
 | 
						|
					$page->head_script	.= "\n" .
 | 
						|
						'var gallery_editing_options = { legacy_style : false };';
 | 
						|
					$page->jQueryCode	.= "\n" .
 | 
						|
						'$(document).on("editor_area:loaded", function(){ ' .
 | 
						|
							'$(".filetype-gallery .caption").trigger("destroy.dot"); ' .
 | 
						|
						'});';
 | 
						|
				}
 | 
						|
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			$page->head .= "\n" .
 | 
						|
				'<link type="text/css" media="screen" rel="stylesheet" href="' . $css . '" />';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function AddColorBox(){
 | 
						|
			global $page, $config, $dataDir;
 | 
						|
 | 
						|
			static $init = false;
 | 
						|
			if( $init ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
			$init = true;
 | 
						|
 | 
						|
			// use page->lang for colorbox
 | 
						|
			if( isset($page->lang) &&
 | 
						|
				$page->lang != $config['language'] &&
 | 
						|
				file_exists($dataDir . '/include/languages/' . $page->lang . '.main.inc')
 | 
						|
			){
 | 
						|
				include($dataDir . '/include/languages/' . $page->lang . '.main.inc');
 | 
						|
			}else{
 | 
						|
				global $langmessage;
 | 
						|
			}
 | 
						|
 | 
						|
			\gp\tool\Output::$inline_vars['colorbox_lang'] = [
 | 
						|
				'previous'	=> $langmessage['Previous'],
 | 
						|
				'next'		=> $langmessage['Next'],
 | 
						|
				'close'		=> $langmessage['Close'],
 | 
						|
				'caption'	=> $langmessage['caption'],
 | 
						|
				'current'	=> sprintf($langmessage['Image_of'],'{current}','{total}')
 | 
						|
			]; //'Start Slideshow'=>'slideshowStart', 'Stop Slideshow'=>'slideshowStop'
 | 
						|
 | 
						|
			self::LoadComponents('colorbox');
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Set the $config array from /data/_site/config.php
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetConfig(){
 | 
						|
			global $config, $gp_hooks;
 | 
						|
 | 
						|
			$config = \gp\tool\Files::Get('_site/config');
 | 
						|
 | 
						|
			if( !is_array($config) || !array_key_exists('gpversion', $config) ){
 | 
						|
				self::stop();
 | 
						|
			}
 | 
						|
 | 
						|
			//make sure defaults are set
 | 
						|
			$config += [
 | 
						|
				'maximgarea'				=> '2073600',
 | 
						|
				'preserve_icc_profiles'		=> true,		//5.1
 | 
						|
				'preserve_image_metadata'	=> true,		//5.1
 | 
						|
				'maxthumbsize'				=> '300',
 | 
						|
				'maxthumbheight'			=> '',			//5.1
 | 
						|
				'thumbskeepaspect'			=> false,
 | 
						|
				'check_uploads'				=> false,
 | 
						|
				'colorbox_style'			=> 'example1',
 | 
						|
				'gallery_legacy_style'		=> true,
 | 
						|
				'combinecss'				=> true,
 | 
						|
				'combinejs'					=> true,
 | 
						|
				'minifyjs'					=> false,		//5.2
 | 
						|
				'etag_headers'				=> true,
 | 
						|
				'customlang'				=> [],
 | 
						|
				'showgplink'				=> true,
 | 
						|
				'showsitemap'				=> true,
 | 
						|
				'showlogin'					=> true,
 | 
						|
				'auto_redir'				=> 90,			//2.5
 | 
						|
				'history_limit'				=> min(gp_backup_limit, 30),
 | 
						|
				'resize_images'				=> true,		//3.5
 | 
						|
				'addons'					=> [],
 | 
						|
				'themes'					=> [],
 | 
						|
				'gadgets'					=> [],
 | 
						|
				'passhash'					=> 'sha1',
 | 
						|
				'hooks'						=> [],
 | 
						|
				'space_char'				=> '-',			//4.6
 | 
						|
				'cdn'						=> '',
 | 
						|
				'admin_ui_autohide_below'	=> '992',		//5.2
 | 
						|
				'admin_ui_hotkey'			=> 'H',			//5.2
 | 
						|
				'admin_ui_hotkey_code'		=> 'ctrlKey+72',	//5.2
 | 
						|
				'homepath_auto'				=> true,		//5.2
 | 
						|
			];
 | 
						|
 | 
						|
			//cdn settings
 | 
						|
			if( isset($config['jquery']) && $config['jquery'] != 'local' ){
 | 
						|
				$config['cdn'] = 'CloudFlare';
 | 
						|
				unset($config['jquery']);
 | 
						|
			}
 | 
						|
 | 
						|
			//shahash deprecated 4.0
 | 
						|
			if( isset($config['shahash']) && !$config['shahash'] ){
 | 
						|
				$config['passhash'] = 'md5';
 | 
						|
			}
 | 
						|
 | 
						|
			// default gadgets
 | 
						|
			$config['gadgets']['Contact']		= ['class'	=> '\\gp\\special\\ContactGadget'];
 | 
						|
			$config['gadgets']['Search']		= ['method'	=> ['\\gp\\special\\Search', 'gadget']];
 | 
						|
			$config['gadgets']['Admin_Link']	= ['method'	=> ['\\gp\\tool\\Output', 'AdminLinkGadget']];
 | 
						|
			$config['gadgets']['Login_Link']	= ['method'	=> ['\\gp\\tool\\Output', 'LoginLinkGadget']];
 | 
						|
 | 
						|
 | 
						|
			foreach($config['hooks'] as $hook => $hook_info){
 | 
						|
				if( isset($gp_hooks[$hook]) ){
 | 
						|
					$gp_hooks[$hook] += $hook_info;
 | 
						|
				}else{
 | 
						|
					$gp_hooks[$hook] = $hook_info;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			self::GetLangFile();
 | 
						|
			self::GetPagesPHP();
 | 
						|
 | 
						|
			//upgrade?
 | 
						|
			if( version_compare($config['gpversion'], '2.3.4', '<') ){
 | 
						|
				new \gp\tool\Upgrade();
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Stop loading
 | 
						|
		 * Check to see if the cms has already been installed
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function stop(){
 | 
						|
			global $dataDir;
 | 
						|
 | 
						|
			if( !\gp\tool::Installed() ){
 | 
						|
 | 
						|
				if( file_exists($dataDir . '/include/install/install.php') ){
 | 
						|
					self::SetLinkPrefix();
 | 
						|
					includeFile('install/install.php');
 | 
						|
					die();
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			die(
 | 
						|
				'<p>Notice: The site configuration did not load properly.</p>'
 | 
						|
				. '<p>If you are the site administrator, you can troubleshoot the problem turning '
 | 
						|
				. 'debugging "on" or bypass it by enabling ' . \CMS_NAME . ' safe mode.</p>'
 | 
						|
				. '<p>More information is available in the '
 | 
						|
				. '<a href="' . \CMS_DOMAIN . '/Docs/Main/Troubleshooting">Documentation</a>.</p>'
 | 
						|
				. self::ErrorBuffer(true, false)
 | 
						|
			);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return true if
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function Installed(){
 | 
						|
			global $dataDir;
 | 
						|
 | 
						|
			return \gp\tool\Files::Exists($dataDir . '/data/_site/config.php');
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Set global variables ($gp_index, $gp_titles, $gp_menu and $gpLayouts) from _site/pages.php
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetPagesPHP(){
 | 
						|
			global $gp_index, $gp_titles, $gp_menu, $gpLayouts, $config;
 | 
						|
 | 
						|
			$pages			= \gp\tool\Files::Get('_site/pages');
 | 
						|
			$gpLayouts		= $pages['gpLayouts'];
 | 
						|
			$gp_index		= $pages['gp_index'];
 | 
						|
			$gp_titles		= $pages['gp_titles'];
 | 
						|
			$gp_menu		= $pages['gp_menu'];
 | 
						|
 | 
						|
			if( !is_array($gp_menu) ){
 | 
						|
				self::stop();
 | 
						|
			}
 | 
						|
 | 
						|
			//title related configuration settings
 | 
						|
			if( empty($config['homepath_key']) ){
 | 
						|
				$config['homepath_key'] = key($gp_menu);
 | 
						|
			}
 | 
						|
			$config['homepath'] = self::IndexToTitle($config['homepath_key']);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Generate a new file index
 | 
						|
		 * skip indexes that are just numeric
 | 
						|
		 */
 | 
						|
		public static function NewFileIndex(){
 | 
						|
			global $gp_index, $gp_titles, $dataDir, $config;
 | 
						|
 | 
						|
			$last_index		= 'a';
 | 
						|
			$num_index		= 0;
 | 
						|
 | 
						|
			/*prevent reusing old indexes */
 | 
						|
			if( count($gp_index) > 0 ){
 | 
						|
				$max = count($gp_index);
 | 
						|
				$title = end($gp_index);
 | 
						|
				for($i = $max; $i > 0; $i--){
 | 
						|
					$last_index = current($gp_index);
 | 
						|
					$type = self::SpecialOrAdmin($title);
 | 
						|
					if( $type === 'special' ){
 | 
						|
						$title = prev($gp_index);
 | 
						|
						continue;
 | 
						|
					}
 | 
						|
					$i = 0;
 | 
						|
				}
 | 
						|
				reset($gp_index);
 | 
						|
				$num_index = base_convert($last_index, 36, 10);
 | 
						|
				$num_index++;
 | 
						|
			}
 | 
						|
 | 
						|
			do{
 | 
						|
				$index = base_convert($num_index, 10, 36);
 | 
						|
				$num_index++;
 | 
						|
 | 
						|
				//check backup dir
 | 
						|
				$backup_dir = $dataDir . '/data/_backup/pages/' . $index;
 | 
						|
				if( file_exists($backup_dir) ){
 | 
						|
					$index = false;
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
 | 
						|
				//check for page directory
 | 
						|
				$draft_file	= $dataDir . '/data/_pages/' . substr($config['gpuniq'], 0, 7) . '_' . $index;
 | 
						|
				if( file_exists($draft_file) ){
 | 
						|
					$index = false;
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
 | 
						|
			}while( !$index || is_numeric($index) || isset($gp_titles[$index]) );
 | 
						|
 | 
						|
			return $index;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return the title of file using the index
 | 
						|
		 * Will return false for titles that are external links
 | 
						|
		 * @param string $index The index of the file
 | 
						|
		 */
 | 
						|
		public static function IndexToTitle($index){
 | 
						|
			global $gp_index;
 | 
						|
			return array_search($index, $gp_index);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Traverse the $menu upwards looking for the parents of the a title given by it's index
 | 
						|
		 * @param string $index The data index of the child title
 | 
						|
		 * @return array
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function Parents($index, $menu){
 | 
						|
			$parents = [];
 | 
						|
 | 
						|
			if( !isset($menu[$index]) || !isset($menu[$index]['level']) ){
 | 
						|
				return $parents;
 | 
						|
			}
 | 
						|
 | 
						|
			$checkLevel = $menu[$index]['level'];
 | 
						|
			$menu_ids = array_keys($menu);
 | 
						|
			$key = array_search($index, $menu_ids);
 | 
						|
			for($i = ($key-1); $i >= 0; $i--){
 | 
						|
				$id = $menu_ids[$i];
 | 
						|
 | 
						|
				//check the level
 | 
						|
				$level = $menu[$id]['level'];
 | 
						|
				if( $level >= $checkLevel ){
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				$checkLevel = $level;
 | 
						|
 | 
						|
				$parents[] = $id;
 | 
						|
 | 
						|
				//no need to go further
 | 
						|
				if( $level == 0 ){
 | 
						|
					return $parents;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			return $parents;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Traverse the $menu and gather all the descendants of a title given by it's $index
 | 
						|
		 * @param string $index The data index of the child title
 | 
						|
		 * @param array $menu The menu to use to check for descendants
 | 
						|
		 * @param bool $children_only Option to return a list of children instead of all descendants. Since 4.3
 | 
						|
		 * @return array
 | 
						|
		 */
 | 
						|
		public static function Descendants($index, $menu, $children_only=false){
 | 
						|
 | 
						|
			$titles = [];
 | 
						|
 | 
						|
			if( !isset($menu[$index]) || !isset($menu[$index]['level']) ){
 | 
						|
				return $titles;
 | 
						|
			}
 | 
						|
 | 
						|
			$start_level	= $menu[$index]['level'];
 | 
						|
			$menu_ids		= array_keys($menu);
 | 
						|
			$key			= array_search($index, $menu_ids);
 | 
						|
			$count			= count($menu);
 | 
						|
			for($i = ($key+1); $i < $count; $i++){
 | 
						|
				$id = $menu_ids[$i];
 | 
						|
				$level = $menu[$id]['level'];
 | 
						|
 | 
						|
				if( $level <= $start_level ){
 | 
						|
					return $titles;
 | 
						|
				}
 | 
						|
 | 
						|
				if( !$children_only ){
 | 
						|
					$titles[] = $id;
 | 
						|
				}elseif( $level == $start_level + 1 ){
 | 
						|
					$titles[] = $id;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			return $titles;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return the configuration value or default if it's not set
 | 
						|
		 *
 | 
						|
		 * @since 1.7
 | 
						|
		 *
 | 
						|
		 * @param string $key The key to the $config array
 | 
						|
		 * @param mixed $default The value to return if $config[$key] is not set
 | 
						|
		 * @return mixed
 | 
						|
		 */
 | 
						|
		public static function ConfigValue($key, $default=false){
 | 
						|
			global $config;
 | 
						|
			if( !isset($config[$key]) ){
 | 
						|
				return $default;
 | 
						|
			}
 | 
						|
			return $config[$key];
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Generate a random alphanumeric string of variable length
 | 
						|
		 *
 | 
						|
		 * @param int $len length of string to return
 | 
						|
		 * @param bool $cases Whether or not to use upper and lowercase characters
 | 
						|
		 */
 | 
						|
		public static function RandomString($len=40, $cases=true){
 | 
						|
 | 
						|
			$string = 'abcdefghijklmnopqrstuvwxyz1234567890';
 | 
						|
			if( $cases ){
 | 
						|
				$string .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
 | 
						|
			}
 | 
						|
 | 
						|
			$string = str_repeat($string, (int)round($len / 2));
 | 
						|
			$string = str_shuffle($string);
 | 
						|
			$start = mt_rand(1, (strlen($string) - $len));
 | 
						|
 | 
						|
			return substr($string, $start, $len);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Include the main.inc language file for $language
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetLangFile($file='main.inc', $language=false){
 | 
						|
			global $dataDir, $config, $langmessage;
 | 
						|
 | 
						|
			$language	= $language ? $language : $config['language'];
 | 
						|
			$path		= $dataDir.'/include/languages/' . $language . '.main.inc';
 | 
						|
 | 
						|
			if( !file_exists($path) ){
 | 
						|
				include($dataDir . '/include/languages/en.main.inc'); //default to en
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			include($path);
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get translation of a $langmessage key
 | 
						|
		 * @since 5.2
 | 
						|
		 * @param string key to be found in the $langmessage array
 | 
						|
		 * @param string optional language code (de, fr, …) of the language to be loaded.
 | 
						|
		 *					if omitted the current CMS language will be used.
 | 
						|
		 * @return string the translation if it exists, otherwise the passed term
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function Translate($term, $lang=false){
 | 
						|
			global $dataDir;
 | 
						|
 | 
						|
			if( empty($lang) ){
 | 
						|
				// use CMS language
 | 
						|
				global $langmessage;
 | 
						|
			}else{
 | 
						|
				$path = $dataDir . '/include/languages/' . $lang . '.main.inc';
 | 
						|
				if( !file_exists($path) ){
 | 
						|
					return $term;
 | 
						|
				}
 | 
						|
				include($path);
 | 
						|
			}
 | 
						|
 | 
						|
			return isset($langmessage[$term]) ? $langmessage[$term] : $term;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Determine if the $title is a special or admin page
 | 
						|
		 * @param string $title
 | 
						|
		 * @return mixed 'admin','special' or false
 | 
						|
		 */
 | 
						|
		public static function SpecialOrAdmin($title){
 | 
						|
			global $gp_index, $gp_titles;
 | 
						|
 | 
						|
			$lower_title = strtolower($title);
 | 
						|
 | 
						|
			if( $lower_title === 'admin' ){
 | 
						|
				return 'admin';
 | 
						|
			}elseif( strpos($lower_title, 'admin_') === 0 || strpos($lower_title, 'admin/') === 0 ){
 | 
						|
				return 'admin';
 | 
						|
			}
 | 
						|
 | 
						|
			if( strpos($lower_title, 'special_') === 0 ){
 | 
						|
				return 'special';
 | 
						|
			}
 | 
						|
 | 
						|
 | 
						|
			$parts = explode('/', $title);
 | 
						|
			do{
 | 
						|
				$title = implode('/', $parts);
 | 
						|
				if( isset($gp_index[$title]) ){
 | 
						|
					$key = $gp_index[$title];
 | 
						|
					$info = $gp_titles[$key];
 | 
						|
					if( $info['type'] == 'special' ){
 | 
						|
						return 'special';
 | 
						|
					}
 | 
						|
				}
 | 
						|
				array_pop($parts);
 | 
						|
			}while( count($parts) );
 | 
						|
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return the name of the page being requested based on $_SERVER['REQUEST_URI']
 | 
						|
		 * May also redirect the request
 | 
						|
		 *
 | 
						|
		 * @return string The title to display based on the request uri
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function WhichPage(){
 | 
						|
			global $config, $gp_menu;
 | 
						|
 | 
						|
			$path	= \gp\tool\Editing::Sanitize($_SERVER['REQUEST_URI']);
 | 
						|
			$path	= self::CleanRequest($path);
 | 
						|
 | 
						|
			$pos = mb_strpos($path, '?');
 | 
						|
			if( $pos !== false ){
 | 
						|
				$path = mb_substr($path, 0, $pos);
 | 
						|
			}
 | 
						|
 | 
						|
			$path = \gp\tool\Plugins::Filter('WhichPage', [$path]);
 | 
						|
 | 
						|
			//redirect if an "external link" is the first entry of the main menu
 | 
						|
			if( empty($path) && isset($gp_menu[$config['homepath_key']]) ){
 | 
						|
				$homepath_info = $gp_menu[$config['homepath_key']];
 | 
						|
				if( isset($homepath_info['url']) ){
 | 
						|
					self::Redirect($homepath_info['url'], 302);
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if( empty($path) ){
 | 
						|
				return $config['homepath'];
 | 
						|
			}
 | 
						|
 | 
						|
			//redirect to / for homepath request
 | 
						|
			if( isset($config['homepath']) && $path == $config['homepath'] ){
 | 
						|
				self::Redirect(self::GetUrl('', '', false));
 | 
						|
			}
 | 
						|
 | 
						|
			return $path;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Redirect the request to $path with http $code
 | 
						|
		 *
 | 
						|
		 * @param string|array $path url to redirect to
 | 
						|
		 * @param string $code http redirect code: 301 or 302
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function Redirect($path, $code=302){
 | 
						|
			global $wbMessageBuffer, $gpAdmin;
 | 
						|
 | 
						|
			// if $path is an array, generate a url with \gp\tool::GetUrl($path);
 | 
						|
			// add gpreq and jsoncallback to maintain ajax requests
 | 
						|
			if( is_array($path) ){
 | 
						|
				$add_query	= ['gpreq' => 1, 'jsoncallback' => 1];
 | 
						|
				$add_query	= array_intersect_key($_REQUEST, $add_query);
 | 
						|
				$path		+= [1=>[]];
 | 
						|
				$path[1]	+= $add_query;
 | 
						|
 | 
						|
				$path		= \gp\tool::GetUrl($path[0], http_build_query($path[1], '', '&'), false);
 | 
						|
			}
 | 
						|
 | 
						|
 | 
						|
			//store any messages for display after the redirect
 | 
						|
			if( self::LoggedIn() && count($wbMessageBuffer) ){
 | 
						|
				$gpAdmin['message_buffer'] = $wbMessageBuffer;
 | 
						|
			}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
			//prevent a cache from creating an infinite redirect
 | 
						|
			Header('Last-Modified: ' . gmdate('D, j M Y H:i:s') . ' GMT');
 | 
						|
			Header('Expires: ' . gmdate('D, j M Y H:i:s', time()) . ' GMT');
 | 
						|
			Header('Cache-Control: no-store, no-cache, must-revalidate'); // HTTP/1.1
 | 
						|
			Header('Cache-Control: post-check=0, pre-check=0', false);
 | 
						|
			Header('Pragma: no-cache' ); // HTTP/1.0
 | 
						|
 | 
						|
			switch((int)$code){
 | 
						|
				case 301:
 | 
						|
					self::status_header(301, 'Moved Permanently');
 | 
						|
				break;
 | 
						|
				case 302:
 | 
						|
					self::status_header(302, 'Found');
 | 
						|
				break;
 | 
						|
			}
 | 
						|
 | 
						|
			header('Location: ' . $path);
 | 
						|
			die();
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Remove $dirPrefix and index.php from a path to get the page title
 | 
						|
		 *
 | 
						|
		 * @param string $path A full relative url like /install_dir/index.php/request_title
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function CleanRequest($path){
 | 
						|
			global $dirPrefix;
 | 
						|
 | 
						|
			//use dirPrefix to find requested title
 | 
						|
			if( !empty($dirPrefix) ){
 | 
						|
				$pos = strpos($path, $dirPrefix);
 | 
						|
				if( $pos !== false ){
 | 
						|
					$path = substr($path, $pos + strlen($dirPrefix));
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			//remove /index.php/
 | 
						|
			$pos = strpos($path, '/index.php');
 | 
						|
			if( $pos === 0 ){
 | 
						|
				$path = substr($path, 11);
 | 
						|
			}
 | 
						|
 | 
						|
			$path = ltrim($path, '/');
 | 
						|
 | 
						|
			return $path;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Handle admin login/logout/session_start if admin session parameters exist
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function sessions(){
 | 
						|
 | 
						|
			//alternate sessions
 | 
						|
			if( defined('gpcom_sessions') ){
 | 
						|
				include(gpcom_sessions);
 | 
						|
			}
 | 
						|
 | 
						|
			$cmd = '';
 | 
						|
			if( isset($_GET['cmd']) && $_GET['cmd'] == 'logout' ){
 | 
						|
				$cmd = 'logout';
 | 
						|
			}elseif( isset($_POST['cmd']) && $_POST['cmd'] == 'login' ){
 | 
						|
				$cmd = $_POST['cmd'];
 | 
						|
			}elseif( count($_COOKIE) ){
 | 
						|
				foreach($_COOKIE as $key => $value){
 | 
						|
					if( strpos($key, 'gpEasy_') === 0 ){
 | 
						|
						$cmd = 'start';
 | 
						|
						break;
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if( empty($cmd) ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			\gp\tool\Session::Init();
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return true if an administrator is logged in
 | 
						|
		 * @return bool
 | 
						|
		 */
 | 
						|
		public static function LoggedIn(){
 | 
						|
			global $gpAdmin;
 | 
						|
 | 
						|
			$loggedin = false;
 | 
						|
			if( isset($gpAdmin) && is_array($gpAdmin) ){
 | 
						|
				$loggedin = true;
 | 
						|
			}
 | 
						|
 | 
						|
			return \gp\tool\Plugins::Filter('LoggedIn', [$loggedin]);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * @deprecated
 | 
						|
		 * Create a new nonce
 | 
						|
		 * Deprecated as of Typesetter 5.2
 | 
						|
		 * Use \gp\tool\Nonce::Create() instead
 | 
						|
		 */
 | 
						|
		public static function new_nonce($action='none', $anon=false, $factor=43200){
 | 
						|
			// trigger_error('Deprecated: \gp\tool::new_nonce(), use \gp\tool\Nonce::Create() instead', E_USER_WARNING);
 | 
						|
			return \gp\tool\Nonce::Create($action, $anon, $factor);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * @deprecated
 | 
						|
		 * Verify a nonce ($check_nonce)
 | 
						|
		 * Deprecated as of Typesetter 5.2
 | 
						|
		 * Use \gp\tool\Nonce::Verify() instead
 | 
						|
		 *
 | 
						|
		 * @param string $action Should be the same $action that is passed to new_nonce()
 | 
						|
		 * @param mixed $check_nonce The user submitted nonce or false if $_REQUEST['_gpnonce'] can be used
 | 
						|
		 * @param bool $anon True if the nonce is being used for anonymous users
 | 
						|
		 * @param int $factor Determines the length of time the generated nonce will be valid. The default 43200 will result in a 24hr period of time.
 | 
						|
		 * @return mixed Return false if the $check_nonce did not pass. 1 or 2 if it passes.
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function verify_nonce($action='none', $check_nonce=false, $anon=false, $factor=43200){
 | 
						|
			// trigger_error('Deprecated: \gp\tool::verify_nonce(), use \gp\tool\Nonce::Verify() instead', E_USER_WARNING);
 | 
						|
			return \gp\tool\Nonce::Verify($action, $check_nonce, $anon, $factor);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * @deprecated
 | 
						|
		 * Generate a nonce hash
 | 
						|
		 * Deprecated as of Typesetter 5.2
 | 
						|
		 * Use \gp\tool\Nonce::Hash() instead
 | 
						|
		 *
 | 
						|
		 * @param string $nonce
 | 
						|
		 * @param int $tick_offset
 | 
						|
		 * @param int $factor Determines the length of time the generated nonce will be valid. The default 43200 will result in a 24hr period of time.
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function nonce_hash($nonce, $tick_offset=0, $factor=43200){
 | 
						|
			// trigger_error('Deprecated: \gp\tool::nonce_hash(), use \gp\tool\Nonce::Hash() instead', E_USER_WARNING);
 | 
						|
			return \gp\tool\Nonce::Hash($nonce, $tick_offset, $factor);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return the command sent by the user
 | 
						|
		 * Don't use $_REQUEST here because SetCookieArgs() uses $_GET
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function GetCommand($type='cmd'){
 | 
						|
			global $gpAdmin;
 | 
						|
 | 
						|
			if( is_array($gpAdmin) && isset($gpAdmin['locked']) && $gpAdmin['locked'] ){
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			if( isset($_POST[$type]) ){
 | 
						|
				return $_POST[$type];
 | 
						|
			}
 | 
						|
 | 
						|
			if( isset($_GET[$type]) ){
 | 
						|
				return $_GET[$type];
 | 
						|
			}
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Used for receiving arguments from javascript without having to put variables in the $_GET request
 | 
						|
		 * nice for things that shouldn't be repeated!
 | 
						|
		 */
 | 
						|
		public static function SetCookieArgs(){
 | 
						|
			static $done = false;
 | 
						|
 | 
						|
			if( $done || !gp_cookie_cmd ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			self::RawCookies();
 | 
						|
 | 
						|
			//get cookie arguments
 | 
						|
			if( empty($_COOKIE['cookie_cmd']) ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			$test = $_COOKIE['cookie_cmd'];
 | 
						|
			if( $test[0] === '?' ){
 | 
						|
				$test = substr($test, 1);
 | 
						|
			}
 | 
						|
 | 
						|
			parse_str($test,$cookie_args);
 | 
						|
			if( !$cookie_args ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			//parse_str will overwrite values in $_GET/$_REQUEST
 | 
						|
			$_GET = $cookie_args + $_GET;
 | 
						|
			$_REQUEST = $cookie_args + $_REQUEST;
 | 
						|
 | 
						|
			//for requests with verification, we'll set $_POST
 | 
						|
			if( !empty($_GET['verified']) ){
 | 
						|
				$_POST = $cookie_args + $_POST;
 | 
						|
			}
 | 
						|
 | 
						|
			$done = true;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Fix the $_COOKIE array if RAW_HTTP_COOKIE is set
 | 
						|
		 * Some servers encrypt cookie values before sending them to the client
 | 
						|
		 * Since cookies set by the client (with JavaScript) are not encrypted,
 | 
						|
		 * the values won't be set in $_COOOKIE
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function RawCookies(){
 | 
						|
			if( empty($_SERVER['RAW_HTTP_COOKIE']) ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
			$csplit = explode(';', $_SERVER['RAW_HTTP_COOKIE']);
 | 
						|
			foreach($csplit as $pair){
 | 
						|
				if( !strpos($pair, '=') ){
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				list($key, $value) = explode('=', $pair);
 | 
						|
				$key = rawurldecode(trim($key));
 | 
						|
				if( !array_key_exists($key, $_COOKIE) ){
 | 
						|
					$_COOKIE[$key] = rawurldecode(trim($value));
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Output Javascript code to set variable defaults
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function JsStart(){
 | 
						|
			global $linkPrefix;
 | 
						|
 | 
						|
			//default Variables
 | 
						|
			\gp\tool\Output::$inline_vars['isadmin']			= false;
 | 
						|
			\gp\tool\Output::$inline_vars['gpBase']				= rtrim(self::GetDir(''), '/');
 | 
						|
			\gp\tool\Output::$inline_vars['post_nonce']			= '';
 | 
						|
			\gp\tool\Output::$inline_vars['req_type']			= strtolower(htmlspecialchars($_SERVER['REQUEST_METHOD']));
 | 
						|
 | 
						|
			if( \gpdebugjs ){
 | 
						|
				if( is_string(\gpdebugjs) ){
 | 
						|
					\gp\tool\Output::$inline_vars['debugjs']	= 'send';
 | 
						|
				}else{
 | 
						|
					\gp\tool\Output::$inline_vars['debugjs']	= true;
 | 
						|
				}
 | 
						|
			}else{
 | 
						|
				\gp\tool\Output::$inline_vars['debugjs']		= false;
 | 
						|
			}
 | 
						|
 | 
						|
			if( self::LoggedIn() ){
 | 
						|
 | 
						|
				\gp\tool\Output::$inline_vars['isadmin']			= true;
 | 
						|
				\gp\tool\Output::$inline_vars['req_time']			= time();
 | 
						|
				\gp\tool\Output::$inline_vars['gpBLink']			= self::HrefEncode($linkPrefix, false);
 | 
						|
				\gp\tool\Output::$inline_vars['post_nonce']			= \gp\tool\Nonce::Create('post', true);
 | 
						|
				\gp\tool\Output::$inline_vars['gpFinderUrl']		= \gp\tool::GetUrl('Admin/Browser');
 | 
						|
				\gp\tool\Output::$inline_vars['hideAdminUIcfg']		= self::HideAdminUIcfg();
 | 
						|
 | 
						|
				\gp\tool\Session::GPUIVars();
 | 
						|
			}
 | 
						|
 | 
						|
			echo 'var gplinks={}, gpinputs={}, gpresponse={}';
 | 
						|
			foreach(\gp\tool\Output::$inline_vars as $key => $value){
 | 
						|
				echo ',' . $key . '=' . json_encode($value);
 | 
						|
			}
 | 
						|
			echo ';';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get config values for hiding the admin UI
 | 
						|
		 *
 | 
						|
		 * @return array $cfg configuration values
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function HideAdminUIcfg(){
 | 
						|
			global $config, $langmessage;
 | 
						|
			$cfg = [
 | 
						|
				'autohide_below'	=> 0,
 | 
						|
				'hotkey'			=> '',
 | 
						|
				'hotkey_modkeys'	=> [],
 | 
						|
				'hotkey_which'		=> '',
 | 
						|
			];
 | 
						|
 | 
						|
			if( !empty($config['admin_ui_autohide_below']) && is_numeric($config['admin_ui_autohide_below']) ){
 | 
						|
				$cfg['autohide_below'] = (int)$config['admin_ui_autohide_below'];
 | 
						|
			}
 | 
						|
 | 
						|
			if( !empty($config['admin_ui_hotkey']) && !empty($config['admin_ui_hotkey_code']) ){
 | 
						|
				$cfg['hotkey'] = $config['admin_ui_hotkey'];
 | 
						|
				if( strpos($config['admin_ui_hotkey_code'], 'ctrlKey+') !== false ){
 | 
						|
					$cfg['hotkey_modkeys'][] = 'ctrlKey';
 | 
						|
				}
 | 
						|
				if( strpos($config['admin_ui_hotkey_code'], 'shiftKey+') !== false ){
 | 
						|
					$cfg['hotkey_modkeys'][] = 'shiftKey';
 | 
						|
				}
 | 
						|
				if( strpos($config['admin_ui_hotkey_code'], 'altKey+') !== false ){
 | 
						|
					$cfg['hotkey_modkeys'][] = 'altKey';
 | 
						|
				}
 | 
						|
				if( strpos($config['admin_ui_hotkey_code'], 'metaKey+') !== false ){
 | 
						|
					$cfg['hotkey_modkeys'][] = 'metaKey';
 | 
						|
				}
 | 
						|
				$parts 					= explode('+', $config['admin_ui_hotkey_code']);
 | 
						|
				$cfg['hotkey_which']	= array_pop($parts);
 | 
						|
			}
 | 
						|
 | 
						|
			return $cfg;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return the hash of $arg using the appropriate hashing function for the installation
 | 
						|
		 *
 | 
						|
		 * @param string $arg The string to be hashed
 | 
						|
		 * @param string $algo The hashing algorithm to be used
 | 
						|
		 * @param int $loops The number of times to loop the $arg through the algorithm
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function hash($arg, $algo='sha512', $loops=1000){
 | 
						|
			$arg = trim($arg);
 | 
						|
 | 
						|
			switch($algo){
 | 
						|
				//password_hash
 | 
						|
				case 'password_hash':
 | 
						|
				$temp = self::hash($arg, 'sha512', 50); // 50 salted sha512, same as in /include/admin/Settings/Users.php -> SetUserPass
 | 
						|
				return password_hash($temp, PASSWORD_DEFAULT);
 | 
						|
 | 
						|
				//md5
 | 
						|
				case 'md5':
 | 
						|
				trigger_error('md5 should not be used, please reset your password');
 | 
						|
				return md5($arg);
 | 
						|
 | 
						|
				//sha1
 | 
						|
				case 'sha1':
 | 
						|
				return sha1($arg);
 | 
						|
			}
 | 
						|
 | 
						|
			//sha512: looped with dynamic salt
 | 
						|
			for($i = 0; $i < $loops; $i++){
 | 
						|
				$ints			= preg_replace('#[a-f]#', '', $arg);
 | 
						|
				$salt_start		= (int)substr($ints, 0, 1);
 | 
						|
				$salt_len		= (int)substr($ints, 2, 1);
 | 
						|
				$salt			= substr($arg, $salt_start, $salt_len);
 | 
						|
				$arg			= hash($algo, $arg . $salt);
 | 
						|
			}
 | 
						|
 | 
						|
			return $arg;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function AjaxWarning(){
 | 
						|
			global $page,$langmessage;
 | 
						|
			$page->ajaxReplace[] = ['gpabox', '', $langmessage['OOPS_Start_over']];
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function IdUrl($request_cmd='cv'){
 | 
						|
			global $config, $dataDir, $gpLayouts;
 | 
						|
 | 
						|
			//command
 | 
						|
			$args				= [];
 | 
						|
			$args['cmd']		= $request_cmd;
 | 
						|
 | 
						|
			$_SERVER += ['SERVER_SOFTWARE' => ''];
 | 
						|
 | 
						|
			//checkin
 | 
						|
			if( isset($config['gpuniq']) ){
 | 
						|
				$args['mdu']		= substr(md5($config['gpuniq']), 0, 20); // gpuniq won't be set before installation
 | 
						|
			}
 | 
						|
			$args['site']		= self::AbsoluteUrl(''); //keep full path for backwards compat
 | 
						|
			$args['gpv']		= \gpversion;
 | 
						|
			$args['php']		= phpversion();
 | 
						|
			$args['se']			= $_SERVER['SERVER_SOFTWARE'];
 | 
						|
			$args['data']		= $dataDir;
 | 
						|
			//$args['zlib'] = (int)function_exists('gzcompress');
 | 
						|
 | 
						|
			//service provider
 | 
						|
			if( defined('service_provider_id') && is_numeric(\service_provider_id) ){
 | 
						|
				$args['provider'] = \service_provider_id;
 | 
						|
			}
 | 
						|
 | 
						|
			//plugins
 | 
						|
			$addon_ids = [];
 | 
						|
			if( isset($config['addons']) && is_array($config['addons']) ){
 | 
						|
				self::AddonIds($addon_ids, $config['addons']);
 | 
						|
			}
 | 
						|
 | 
						|
			//themes
 | 
						|
			if( isset($config['themes']) && is_array($config['themes']) ){
 | 
						|
				self::AddonIds($addon_ids, $config['themes']);
 | 
						|
			}
 | 
						|
 | 
						|
			//layouts
 | 
						|
			if( is_array($gpLayouts) ){
 | 
						|
				foreach($gpLayouts as $layout_info){
 | 
						|
					if( !isset($layout_info['addon_id']) ){
 | 
						|
						continue;
 | 
						|
					}
 | 
						|
					$addon_ids[] = $layout_info['addon_id'];
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			$addon_ids		= array_unique($addon_ids);
 | 
						|
			$args['as']		= implode('-', $addon_ids);
 | 
						|
 | 
						|
			return \addon_browse_path . '/Resources?' . http_build_query($args, '', '&');
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		public static function AddonIds(&$addon_ids, $array){
 | 
						|
 | 
						|
			foreach($array as $addon_info){
 | 
						|
				if( !isset($addon_info['id']) ){
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				$addon_id = $addon_info['id'];
 | 
						|
				if( isset($addon_info['order']) ){
 | 
						|
					$addon_id .= '.' . $addon_info['order'];
 | 
						|
				}
 | 
						|
				$addon_ids[] = $addon_id;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Used to send error reports without affecting the display of a page
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function IdReq($img_path, $jquery=true){
 | 
						|
			global $page;
 | 
						|
 | 
						|
			// don't send for unit testing
 | 
						|
			if( defined('gp_unit_testing') ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			//using jquery asynchronously doesn't affect page loading
 | 
						|
			//error function defined to prevent the default error function in main.js from firing
 | 
						|
			if( $jquery && is_object($page) ){
 | 
						|
				$page->head_script .= '$.ajax(' . json_encode($img_path) . ', {error:function(){}, dataType: "jsonp"});';
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			return '<img src="' . self::Ampersands($img_path) . '" height="1" width="1" alt="" '
 | 
						|
				. 'style="border:0 none!important; height:1px!important; width:1px!important; '
 | 
						|
				. 'padding:0!important; margin:0!important;"/>';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return a debug message with link to online debug info
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function Debug($lang_key, $debug=[]){
 | 
						|
			global $langmessage, $dataDir;
 | 
						|
 | 
						|
			//add backtrace info
 | 
						|
			$backtrace = debug_backtrace();
 | 
						|
			while( count($backtrace) > 0 && !empty($backtrace[0]['function']) && $backtrace[0]['function'] == 'Debug' ){
 | 
						|
				array_shift($backtrace);
 | 
						|
			}
 | 
						|
 | 
						|
			$debug['trace']	= array_intersect_key(
 | 
						|
				$backtrace[0],
 | 
						|
				[
 | 
						|
					'file'		=> '',
 | 
						|
					'line'		=> '',
 | 
						|
					'function'	=> '',
 | 
						|
					'class'		=> '',
 | 
						|
				]
 | 
						|
			);
 | 
						|
 | 
						|
			if( !empty($debug['trace']['file']) && !empty($dataDir) && strpos($debug['trace']['file'],$dataDir) === 0 ){
 | 
						|
				$debug['trace']['file'] = substr($debug['trace']['file'], strlen($dataDir) );
 | 
						|
			}
 | 
						|
 | 
						|
			//add php and cms info
 | 
						|
			$debug['lang_key']		= $lang_key;
 | 
						|
			$debug['phpversion']	= phpversion();
 | 
						|
			$debug['gpversion']		= \gpversion;
 | 
						|
			$debug['Rewrite']		= $_SERVER['gp_rewrite'];
 | 
						|
			$debug['Server']		= isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : '';
 | 
						|
 | 
						|
			//create string
 | 
						|
			$debug	= json_encode($debug);
 | 
						|
			$debug	= base64_encode($debug);
 | 
						|
			$debug	= trim($debug, '=');
 | 
						|
			$debug	= strtr($debug, '+/', '-_');
 | 
						|
 | 
						|
			$label	= isset($langmessage[$lang_key]) ? $langmessage[$lang_key] : $lang_key;
 | 
						|
 | 
						|
			return ' <span>' . $label . ' <a href="' . \debug_path . '?data=' . $debug . '" target="_blank">More Info...</a></span>';
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		//only include error buffer when admin is logged in
 | 
						|
		public static function ErrorBuffer($check_user=true, $jquery=true){
 | 
						|
			global $wbErrorBuffer, $config, $dataDir, $rootDir;
 | 
						|
 | 
						|
			if( count($wbErrorBuffer) == 0 ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			if( isset($config['Report_Errors']) && !$config['Report_Errors'] ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			if( $check_user && !self::LoggedIn() ){
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			$dataDir_len = strlen($dataDir);
 | 
						|
			$rootDir_len = strlen($rootDir);
 | 
						|
			$img_path = self::IdUrl('er');
 | 
						|
			$i = 0;
 | 
						|
 | 
						|
			foreach($wbErrorBuffer as $error){
 | 
						|
 | 
						|
				//remove $dataDir or $rootDir from the filename
 | 
						|
				$file_name = self::WinPath($error['ef' . $i]);
 | 
						|
				if( $dataDir_len > 1 && strpos($file_name,$dataDir) === 0 ){
 | 
						|
					$file_name = substr($file_name, $dataDir_len);
 | 
						|
				}elseif( $rootDir_len > 1 && strpos($file_name, $rootDir) === 0 ){
 | 
						|
					$file_name = substr($file_name, $rootDir_len);
 | 
						|
				}
 | 
						|
				$error['ef' . $i] = substr($file_name, -100);
 | 
						|
 | 
						|
				$new_path = $img_path . '&' . http_build_query($error, '', '&');
 | 
						|
 | 
						|
				//maximum length of 2000 characters
 | 
						|
				if( strlen($new_path) > 2000 ){
 | 
						|
					break;
 | 
						|
				}
 | 
						|
				$img_path = $new_path;
 | 
						|
				$i++;
 | 
						|
			}
 | 
						|
 | 
						|
			return self::IdReq($img_path, $jquery);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Test if function exists.  Also handles case where function is disabled via Suhosin.
 | 
						|
		 * Modified from: http://dev.piwik.org/trac/browser/trunk/plugins/Installation/Controller.php
 | 
						|
		 *
 | 
						|
		 * @param string $function Function name
 | 
						|
		 * @return bool True if function exists (not disabled); False otherwise.
 | 
						|
		 */
 | 
						|
		public static function function_exists($function){
 | 
						|
			$function = strtolower($function);
 | 
						|
 | 
						|
			// eval() is a language construct
 | 
						|
			if( $function == 'eval' ){
 | 
						|
				// does not check suhosin.executor.eval.whitelist (or blacklist)
 | 
						|
				if( extension_loaded('suhosin') && self::IniGet('suhosin.executor.disable_eval') ){
 | 
						|
					return false;
 | 
						|
				}
 | 
						|
				return true;
 | 
						|
			}
 | 
						|
 | 
						|
			if( !function_exists($function) ){
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			$blacklist = @ini_get('disable_functions');
 | 
						|
			if( extension_loaded('suhosin') ){
 | 
						|
				$blacklist .= ',' . @ini_get('suhosin.executor.func.blacklist');
 | 
						|
			}
 | 
						|
 | 
						|
			$blacklist = explode(',', $blacklist);
 | 
						|
			$blacklist = array_map('trim', $blacklist);
 | 
						|
			$blacklist = array_map('strtolower', $blacklist);
 | 
						|
			if( in_array($function, $blacklist) ){
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * A more functional JSON Encode function
 | 
						|
		 * @param mixed $data
 | 
						|
		 * @return string
 | 
						|
		 */
 | 
						|
		public static function JsonEncode($data){
 | 
						|
 | 
						|
			$search		= ['<script', '<\/script>'];
 | 
						|
			$repl		= ['<"+"script', '<"+"\/script>'];
 | 
						|
 | 
						|
			$type = gettype($data);
 | 
						|
			switch( $type ){
 | 
						|
				case 'NULL':
 | 
						|
					return 'null';
 | 
						|
 | 
						|
				case 'boolean':
 | 
						|
					return ($data ? 'true' : 'false');
 | 
						|
 | 
						|
				case 'integer':
 | 
						|
				case 'double':
 | 
						|
				case 'float':
 | 
						|
					return json_encode($data);
 | 
						|
 | 
						|
				case 'string':
 | 
						|
					$data = htmlspecialchars_decode(htmlspecialchars($data, ENT_SUBSTITUTE, 'UTF-8'));
 | 
						|
					$data = json_encode($data);
 | 
						|
					return str_replace($search, $repl, $data);
 | 
						|
 | 
						|
				case 'object':
 | 
						|
					$data = get_object_vars($data);
 | 
						|
				case 'array':
 | 
						|
					$output_index_count = 0;
 | 
						|
					$output_indexed = [];
 | 
						|
					$output_associative = [];
 | 
						|
					foreach( $data as $key => $value ){
 | 
						|
						$output_indexed[] = self::JsonEncode($value);
 | 
						|
						$output_associative[] = self::JsonEncode($key) . ':' . self::JsonEncode($value);
 | 
						|
						if( $output_index_count !== NULL && $output_index_count++ !== $key ){
 | 
						|
							$output_index_count = NULL;
 | 
						|
						}
 | 
						|
					}
 | 
						|
					if( $output_index_count !== NULL ){
 | 
						|
						return '[' . implode(',', $output_indexed) . ']';
 | 
						|
					}
 | 
						|
					return '{' . implode(',', $output_associative) . '}';
 | 
						|
 | 
						|
			}
 | 
						|
 | 
						|
			return ''; // Not supported
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Date format funciton, uses formatting similar to php's strftime function
 | 
						|
		 * http://php.net/manual/en/function.strftime.php
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function Date($format='', $time=null){
 | 
						|
 | 
						|
			if( empty($format) ){
 | 
						|
				return '';
 | 
						|
			}
 | 
						|
 | 
						|
			if( is_null($time) ){
 | 
						|
				$time = time();
 | 
						|
			}
 | 
						|
			$time = (int)$time;
 | 
						|
 | 
						|
			$match_count = preg_match_all('#%+[^\s]#', $format, $matches, PREG_OFFSET_CAPTURE);
 | 
						|
			if( $match_count ){
 | 
						|
				$matches = array_reverse($matches[0]);
 | 
						|
				foreach($matches as $match){
 | 
						|
					$len = strlen($match[0]);
 | 
						|
					if( $len%2 ){
 | 
						|
						$replacement = strftime($match[0], $time);
 | 
						|
					}else{
 | 
						|
						$piece = substr($match[0], -2, 2);
 | 
						|
						switch($piece){
 | 
						|
							case '%e':
 | 
						|
								$replacement = strftime(substr($match[0], 0, -2), $time) . ltrim(strftime('%d', $time), '0');
 | 
						|
							break;
 | 
						|
							default:
 | 
						|
								$replacement = strftime($match[0], $time);
 | 
						|
							break;
 | 
						|
						}
 | 
						|
					}
 | 
						|
					$format = substr_replace($format, $replacement, $match[1], strlen($match[0]));
 | 
						|
				}
 | 
						|
			}
 | 
						|
			return $format;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get an image's thumbnail path
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function ThumbnailPath($img){
 | 
						|
 | 
						|
			//already thumbnail path
 | 
						|
			if( strpos($img, '/data/_uploaded/image/thumbnails') !== false ){
 | 
						|
				return $img;
 | 
						|
			}
 | 
						|
 | 
						|
			$dir_part = '/data/_uploaded/';
 | 
						|
			$pos = strpos($img, $dir_part);
 | 
						|
			if( $pos === false ){
 | 
						|
				return $img;
 | 
						|
			}
 | 
						|
 | 
						|
			// svg or not svg
 | 
						|
			$nameParts = explode('.', $img);
 | 
						|
			$type = array_pop($nameParts);
 | 
						|
			$type = strtolower($type);
 | 
						|
			if( strpos('svgz', $type) !== 0 ){
 | 
						|
				$type = 'jpg';
 | 
						|
			}
 | 
						|
 | 
						|
			return substr_replace($img, '/data/_uploaded/image/thumbnails/', $pos, strlen($dir_part)) . '.' . $type;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Generate a checksum for the $array
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function ArrayHash($array){
 | 
						|
			return md5(json_encode($array));
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Return the key of an array if found
 | 
						|
		 * Alert if $msg is not null
 | 
						|
		 *
 | 
						|
		 * @param string $key
 | 
						|
		 * @param array $array
 | 
						|
		 * @param string $msg
 | 
						|
		 * @return mixed
 | 
						|
		 */
 | 
						|
		public static function ArrayKey($key, $array, $msg=null){
 | 
						|
			global $langmessage;
 | 
						|
 | 
						|
			if( !isset($array[$key]) ){
 | 
						|
 | 
						|
				if( !is_null($msg) ){
 | 
						|
					msg($langmessage['OOPS'] . ' ' . $msg);
 | 
						|
				}
 | 
						|
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			return array_search($array[$key], $array, true);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Convert a string representation of a byte value to an number
 | 
						|
		 * @param string $value
 | 
						|
		 * @return int
 | 
						|
		 */
 | 
						|
		public static function getByteValue($value){
 | 
						|
 | 
						|
			if( is_numeric($value) ){
 | 
						|
				return (int)$value;
 | 
						|
			}
 | 
						|
 | 
						|
			$lastChar = strtolower(substr($value, -1));
 | 
						|
			$num = (int)substr($value, 0, -1);
 | 
						|
 | 
						|
			switch($lastChar){
 | 
						|
				case 'g':
 | 
						|
					$num *= 1024;
 | 
						|
				case 'm':
 | 
						|
					$num *= 1024;
 | 
						|
				case 'k':
 | 
						|
					$num *= 1024;
 | 
						|
					break;
 | 
						|
			}
 | 
						|
 | 
						|
			return $num;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Get the extension of the $file
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		public static function Ext($file){
 | 
						|
			$ext = pathinfo($file, PATHINFO_EXTENSION);
 | 
						|
			return strtolower($ext);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * @deprecated 3.0
 | 
						|
		 * use \gp\tool\Editing::UseCK();
 | 
						|
		 */
 | 
						|
		public static function UseFCK($contents, $name='gpcontent'){
 | 
						|
			trigger_error('Deprecated Function');
 | 
						|
			\gp\tool\Editing::UseCK($contents, $name);
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		/**
 | 
						|
		 * @deprecated 3.0
 | 
						|
		 * Use \gp\tool\Editing::UseCK();
 | 
						|
		 */
 | 
						|
		public static function UseCK($contents, $name='gpcontent', $options=[]){
 | 
						|
			trigger_error('Deprecated Function');
 | 
						|
			\gp\tool\Editing::UseCK($contents, $name, $options);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
namespace{
 | 
						|
	class common extends \gp\tool{}
 | 
						|
}
 |