<?php namespace HashOver;// Copyright (C) 2010-2021 Jacob Barkdull// This file is part of HashOver.//// HashOver is free software: you can redistribute it and/or modify// it under the terms of the GNU Affero General Public License as// published by the Free Software Foundation, either version 3 of the// License, or (at your option) any later version.//// HashOver is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU Affero General Public License for more details.//// You should have received a copy of the GNU Affero General Public License// along with HashOver.  If not, see <http://www.gnu.org/licenses/>.class Misc{	// Allowed JavaScript constructors	protected static $objects = array (		'HashOver',		'HashOverCountLink',		'HashOverLatest'	);	// XSS-unsafe characters to search for	protected static $searchXSS = array (		'&',		'<',		'>',		'"',		"'",		'/',		'\\'	);	// XSS-safe replacement character entities	protected static $replaceXSS = array (		'&amp;',		'&lt;',		'&gt;',		'&quot;',		'&#x27;',		'&#x2F;',		'&#92;'	);	// Return JSON or JSONP function call	public static function jsonData ($data, $self_error = false)	{		// Encode JSON data		$json = json_encode ($data);		// Return JSON as-is if the request isn't for JSONP		if (!isset ($_GET['jsonp']) or !isset ($_GET['jsonp_object'])) {			return $json;		}		// Otherwise, make JSONP callback index XSS safe		$index = self::makeXSSsafe ($_GET['jsonp']);		// Make JSONP object constructor name XSS safe		$object = self::makeXSSsafe ($_GET['jsonp_object']);		// Check if constructor is allowed, if not use default		$allowed_object = in_array ($object, self::$objects, true);		$object = $allowed_object ? $object : 'HashOver';		// Check if the JSONP index contains a numeric value		if (is_numeric ($index) or $self_error === true) {			// If so, cast index to positive integer			$index = ($self_error === true) ? 0 : (int)(abs ($index));			// Construct JSONP function call			$jsonp = sprintf ('%s.jsonp[%d] (%s);', $object, $index, $json);			// And return the JSONP script			return $jsonp;		}		// Otherwise, return an error		return self::jsonData (array (			'message' => 'JSONP index must have a numeric value.',			'type' => 'error'		), true);	}	// Makes a string XSS-safe by removing harmful characters	public static function makeXSSsafe ($string)	{		return str_replace (self::$searchXSS, self::$replaceXSS, $string);	}	// Returns error in HTML paragraph	public static function displayError ($error = 'Something went wrong!', $mode = 'php')	{		// Initial error message data		$data = array ();		// Make error message XSS safe		$xss_safe = self::makeXSSsafe ($error);		// Treat JSONP as JavaScript		if ($mode === 'json' and isset ($_GET['jsonp'])) {			$mode = 'javascript';		}		// Decide how to display error		switch ($mode) {			// Minimal JavaScript to display error message on page			case 'javascript': {				$data[] = 'var hashover = document.getElementById (\'hashover\') || document.body;';				$data[] = 'var error = \'<p><b>HashOver</b>: ' . $xss_safe . '</p>\';' . PHP_EOL;				$data[] = 'hashover.innerHTML += error;';				break;			}			// RSS XML to indicate error			case 'rss': {				$data[] = '<?xml version="1.0" encoding="UTF-8"?>';				$data[] = '<error>HashOver: ' . $xss_safe . '</error>';				break;			}			// JSON to indicate error			case 'json': {				$data[] = self::jsonData (array (					'message' => $error,					'type' => 'error'				));				break;			}			// Default just return the error message			default: {				$data[] = '<p><b>HashOver</b>: ' . $error . '</p>';				break;			}		}		// Convert error message data to string		$message = implode (PHP_EOL, $data);		return $message;	}	// Returns error in HTML paragraph	public static function displayException (\Exception $error, $mode = 'php')	{		return self::displayError ($error->getMessage (), $mode);	}	// Returns an array item or a given default value	public static function getArrayItem (array $data, $key)	{		return !empty ($data[$key]) ? $data[$key] : false;	}}