<?php
class Mainframe
{
	private static $url;
	private static $domain;
	private static $querystring;
	private static $protocol;
	private static $port;
	private static $site;
	private static $template;
	private static $page;
	private static $CI;
	private static $module_js;
	private static $initialized = false;

	public static function init()
	{
		if(self::$initialized)
		{
			return true;
		}

		self::$CI =& get_instance();
		self::$CI->load->model("site");

		// Get requested URL and parse relevant information from it.
		self::$domain 		= strtolower(self::$CI->input->server('HTTP_HOST'));
		self::$protocol 	= strtolower(self::$CI->input->server('SERVER_PROTOCOL'));
		self::$querystring = self::$CI->input->server('QUERY_STRING');
		self::$port 		= self::$CI->input->server('SERVER_PORT');
		self::$url 		= (isset($_SERVER['HTTPS']) ? "https://" : "http://") . self::$CI->input->server("HTTP_HOST") . self::$CI->input->server("REQUEST_URI");
		// Remove trailing slash, if it exists.
		self::$url 		= preg_replace('/\/$/', '', self::$url);
		self::$CI->load->model(array("domain", "redirect"));

		$domain_name = str_replace(array("http://", "https://"), "", self::$domain);

		if(($domain = self::$CI->cache->get("domain:" . $domain_name)) === false)
		{
			$domain = new Domain();
			$domain->LoadByDomain($domain_name);
			self::$CI->cache->save("domain:" . $domain_name, $domain, 86400);
		}

		if($domain->redirect_url)
		{
			if(defined("LOGGING")) { error_log(PRODUCT_NAME . ": `" . $domain->domain . "` redirects to `" . $domain->redirect_url . "`."); }
			redirect($domain->redirect_url, "auto", 301);
		}
		else
		{
			self::$site = new Site();

			if(self::$CI->input->get_post("active_site_id") > 0)
			{
				self::$site->Load(self::$CI->input->get_post("active_site_id"));
			}
			else if(self::$CI->input->post("site_id") > 0)
			{
				self::$site->Load(self::$CI->input->post("site_id"));
			}
			else if(self::$CI->router->fetch_class() != "controller" &&
			        self::$CI->input->cookie("active_site_id") > 0)
			{
				self::$site->Load(self::$CI->input->cookie("active_site_id"));
			}
			else
			{
				self::$site->Load((isset($domain->site_id) && $domain->site_id > 0 ? $domain->site_id : 1));
			}

			$redirect = new Redirect();
			$redirect->loadByURL(preg_replace('/^\//', '', $_SERVER["REQUEST_URI"]), self::$site->site_id);
			setcookie("active_site_id", self::$site->site_id, time() + self::$CI->config->item("sess_expiration"), self::$CI->config->item("cookie_path"), self::$CI->config->item("cookie_domain"), self::$CI->config->item("cookie_secure"), self::$CI->config->item("cookie_httponly"));

			if($redirect && $redirect->new_url)
			{
				if(defined("LOGGING")) { error_log(PRODUCT_NAME . ": `" . $redirect->old_url . "` redirects to `" . $redirect->new_url . "`."); }
				redirect($redirect->new_url);
			}
			else
			{
				self::$initialized = (self::$site->site_id > 0);
				return self::$initialized;
			}
		}
	}

	public static function adminInit()
	{
		if(self::$initialized)
		{
			return true;
		}

		self::$CI =& get_instance();
		self::$CI->load->model("site");

		// Get requested URL and parse relevant information from it.
		self::$domain 		= strtolower(self::$CI->input->server('HTTP_HOST'));
		self::$protocol 	= strtolower(self::$CI->input->server('SERVER_PROTOCOL'));
		self::$querystring = self::$CI->input->server('QUERY_STRING');
		self::$port 		= self::$CI->input->server('SERVER_PORT');
		self::$url 		= (isset($_SERVER['HTTPS']) ? "https://" : "http://") . self::$CI->input->server("HTTP_HOST") . self::$CI->input->server("REQUEST_URI");
		// Remove trailing slash, if it exists.
		self::$url 		= preg_replace('/\/$/', '', self::$url);
		self::$CI->load->model("domain");
		self::$site = new Site();

		if(self::$CI->input->get_post("active_site_id") > 0)
		{
			self::$site->Load(self::$CI->input->get_post("active_site_id"));
		}
		else if(self::$CI->input->post("site_id") > 0)
		{
			self::$site->Load(self::$CI->input->post("site_id"));
		}
		else if(self::$CI->router->fetch_class() != "controller" &&
		        self::$CI->input->cookie("active_site_id") > 0)
		{
			self::$site->Load(self::$CI->input->cookie("active_site_id"));
		}
		else
		{
			$domain_name = str_replace(array("http://", "https://"), "", self::$domain);
			$domain = new Domain();
			$domain->LoadByDomain($domain_name);

			self::$site->Load((isset($domain->site_id) && $domain->site_id > 0 ? $domain->site_id : 1));
		}

		setcookie("active_site_id", self::$site->site_id, time() + self::$CI->config->item("sess_expiration"), self::$CI->config->item("cookie_path"), self::$CI->config->item("cookie_domain"), self::$CI->config->item("cookie_secure"), self::$CI->config->item("cookie_httponly"));

		self::$initialized = (self::$site->site_id > 0);
		return self::$initialized;
	}

	static function url()
	{
		return self::$url;
	}

	static function active_site_id()
	{
		return (self::$CI->input->cookie("active_site_id") > 0 ? self::$CI->input->cookie("active_site_id") : self::$site->site_id);
	}

	static function domain()
	{
		return self::$domain;
	}

	static function querystring()
	{
		return self::$querystring;
	}

	static function protocol()
	{
		return self::$protocol;
	}

	static function port()
	{
		return self::$port;
	}

	static function site()
	{
		return self::$site;
	}

	static function template()
	{
		return self::$template;
	}

	static function setTemplate($template)
	{
		self::$template = $template;
	}

	static function moduleJS()
	{
		return (self::$module_js ? self::$module_js : "null");
	}

	static function setModuleJS($module_js)
	{
		self::$module_js = $module_js;
	}

	static function page()
	{
		return self::$page;
	}

	static function user()
	{
		return get_user();
	}

	static function loggedin()
	{
		$user = get_user();

		return ($user->user_id > 0);
	}

	static function CountModules($page_id, $position)
	{
		$count = 0;
		$modules = self::LoadModules($page_id);

		foreach($modules as $module)
		{
			if($module->published == 1 && $module->position == $position)
			{
				$count++;
			}
		}

		return $count;
	}

	static function LoadModules($page_id)
	{
		self::$CI->load->model("moduleinstance");

		return self::$CI->moduleinstance->LoadByPageID($page_id, self::user());
	}

	static function LoadModulesBySiteID($site_id)
	{
		self::$CI->load->model("moduleinstance");

		return self::$CI->moduleinstance->LoadBySiteID($site_id, "published DESC, mi.sort, mi.tag", self::user());
	}

	static function LoadPage($site_id, $page_id)
	{
		self::$CI->load->model("page");
		self::$page = new Page();

		if(self::$page->LoadBySitePageID($site_id, $page_id))
		{
			return self::$page;
		}
		else
		{
			if(defined("LOGGING")) { error_log(PRODUCT_NAME . ": Could not determine which page to load for site: `" . $site_id . "`, page: `" . $page_id . "`."); }
			self::$page = null;
			return false;
		}
	}

	static function GetModulePositions($template_id="")
	{
		self::$CI->load->model("template");

		if(!$template_id)
		{
			$template_id = self::site()->template_id;
		}

		$template_id_override = self::$CI->input->get_post("template_id");

		$template = new Template();
		$template->Load(($template_id_override ? $template_id_override : $template_id));

		$content = file_get_contents(ABSOLUTE_PATH . "/templates/$template->directory/index.php");
		preg_match_all("/[\"\']module_position_(.*)[\"\']/", $content, $matches);

		$positions = array_unique($matches[1]);
		sort($positions);

		return $positions;
	}

	public static function filter_html_for_accessibility($original_html)
	{
		$CI =& get_instance();
		$CI->load->model("metadata_page");
		$pageURL = (isset($_SERVER["HTTPS"]) ? "https://" : "http://") . self::$CI->input->server("HTTP_HOST").self::$CI->input->server("REQUEST_URI");

		//replace valign=x with CSS
		//replace br/hr clear with CSS
		//replace href="#" with the current URL
		$find 		= array('/valign=[\'"](.*)?[\'"]/',
		                	'/br clear="all"/',
		                	'/hr clear="all"/',
		                	'/href="#"/',
		                	'/href=\'#\'/');
		$replace 	= array('style="vertical-align: $1;"',
		                  	'br style="clear: both;"',
		                  	'hr style="clear: both;"',
		                  	'href="' . $pageURL . '"',
		                  	'href=\'' . $pageURL . '\'');

		$original_html = preg_replace($find, $replace, $original_html);

		//check title and description meta data
		$url_to_check = str_ireplace(LIVE_SITE, "", $pageURL);
		if(substr($url_to_check, 0, 1) == "/")
		{
			$url_to_check = substr($url_to_check, 1);
		}
		if($url_to_check == "")
		{
			$url_to_check = "index";
		}
		$meta_page = $CI->metadata_page->LoadByURL(self::site()->site_id, $url_to_check);

		if($meta_page != false)
		{
			if($meta_page->title != "")
			{
				$original_html = preg_replace('/<title>.*<\/title>/i', '<title>' . $meta_page->title . '</title>', $original_html);
			}
			if($meta_page->description != "")
			{
				$original_html = preg_replace('/<meta name="description" content=".*?" \/>/i', '<meta name="description" content="' . $meta_page->description . '" />', $original_html);
			}
		}

		//get all images
		preg_match_all('/<img .*?>/', $original_html, $matches, PREG_SET_ORDER);

		foreach($matches as $match)
		{
			//extract the src, alt, title, and longdesc (if they exist)
			preg_match_all('/src=[\'"](.*?)[\'"]/', 		$match[0], 	$matches_src, 	PREG_SET_ORDER);
			preg_match_all('/alt=[\'"](.*?)[\'"]/', 		$match[0], 	$matches_alt, 	PREG_SET_ORDER);
			preg_match_all('/title=[\'"](.*?)[\'"]/', 		$match[0], 	$matches_title, PREG_SET_ORDER);
			preg_match_all('/longdesc=[\'"](.*?)[\'"]/', 	$match[0], 	$matches_long, 	PREG_SET_ORDER);

			//grab the values (if they existed)
			$src 		= isset($matches_src[0][1]) 	? $matches_src[0][1] 	: false;
			$alt 		= isset($matches_alt[0][1]) 	? $matches_alt[0][1] 	: false;
			$title 		= isset($matches_title[0][1]) 	? $matches_title[0][1] 	: false;
			$longdesc 	= isset($matches_long[0][1]) 	? $matches_long[0][1] 	: false;
			$new_alt 		= htmlspecialchars_decode($alt, ENT_COMPAT | ENT_HTML5 | ENT_QUOTES);
			$new_title 		= htmlspecialchars_decode($title, ENT_COMPAT | ENT_HTML5 | ENT_QUOTES);
			$new_longdesc 	= htmlspecialchars_decode($longdesc, ENT_COMPAT | ENT_HTML5 | ENT_QUOTES);

			if($src == false)
			{
				//something's wrong here
				continue;
			}

			//remove the live site and leading slash
			$url_to_check = str_ireplace(LIVE_SITE, "", $src);
			if(substr($url_to_check, 0, 1) == "/")
			{
				$url_to_check = substr($url_to_check, 1);
			}

			//remove any thumbnail resizing (100x50) from the end of the filename
			$url_to_check = preg_replace('/resized\//', '', $url_to_check);
			$url_to_check = preg_replace('/(_thumb)?_?(\d+)x(\d+)\./', '.', $url_to_check);

			if(file_exists(ABSOLUTE_PATH . "/" . $url_to_check .".json"))
			{
				$data         = json_decode(file_get_contents(ABSOLUTE_PATH . "/" . $url_to_check . ".json"));
				$new_alt      = htmlentities($data->alt);
				$new_title    = htmlentities($data->title);
				$new_longdesc = htmlentities($data->description);
			}
			else
			{
				// Take the directory names, reverse them, and add them to the end of the image name.
				$dir_parts = explode("/", str_ireplace(ABSOLUTE_PATH, "", dirname($src)));
				$dir_parts = array_reverse($dir_parts);
				$dir = implode(" ", $dir_parts);

				// Create a cleaned up version of the file name as a default alt/title.
				$src = str_replace("%20", " ", basename($src))	 . "/" . $dir;
				//remove file extension
				$src = str_ireplace(array(".jpg", ".jpeg", ".gif", ".png", ".bmp", ".tiff", "/thumbnails/"), "", $src);
				//put a space before all capital letters (camel case)
				$src = preg_replace('/([A-Z][a-z0-9])/', ' $1', $src);
				//remove any thumbnail resizing (100x50) from the end of the filename
				$src = preg_replace('/(_thumb)?_?(\d+)x(\d+)/', '', $src);
				//remove @2x from the end of the filename
				$src = preg_replace('/@2x/', '', $src);
				//replace remaining underscores, dashes, and slashes with spaces
				$src = str_replace(array("_", "/", "\\"), " ", $src);
				$src = trim($src);

				$original_src = str_replace(" $dir", "", $src);

				// If there is no alt, use the original filename.
				$new_alt 		= ($alt === false ? $original_src : $alt);
				// If there is no title, use alt if available, otherwise the cleaned up filename.
				$new_title 		= ($title === false ? ($alt === false ? $src : $alt) : $title);
				// If there is no longdesc, do nothing.
				$new_longdesc 	= ($longdesc === false ? "" : $longdesc);
			}
			$new_html = $match[0];

			// Image had no alt before, but now it does.
			if($alt == false && $new_alt != false && !preg_match('/\<.*\>/', $new_alt))
			{
				//set alt to filename
				$new_html = str_replace('<img ', '<img alt="' . htmlspecialchars($new_alt, ENT_COMPAT | ENT_HTML5 | ENT_QUOTES) . '" ', $new_html);
			}

			// Image had no title before, but now it does.
			if($title == false && $new_title != false && !preg_match('/\<.*\>/', $new_title))
			{
				//set title to alt or filename
				$new_html = str_replace('<img ', '<img title="' . htmlspecialchars($new_title, ENT_COMPAT | ENT_HTML5 | ENT_QUOTES) . '" ', $new_html);
			}

			// Image had no longdesc before, but now it does.
			if($longdesc == false && $new_longdesc != false)
			{
				//set longdesc to alt or filename
				$new_html = str_replace('<img ', '<img longdesc="' . htmlspecialchars($new_longdesc, ENT_COMPAT | ENT_HTML5 | ENT_QUOTES) . '" ', $new_html);
			}

			$original_html = str_replace($match[0], $new_html, $original_html);
		}

		//get all anchors with images inside
		preg_match_all('/<a (.*?)?>\s*<img (.*?)?>\s*<\/a>/', $original_html, $matches, PREG_SET_ORDER);

		foreach($matches as $match)
		{
			//get title from the image
			preg_match_all('/title=[\'"](.*?)[\'"]/', 		$match[2], 	$img_matches_title, PREG_SET_ORDER);

			//grab the value
			$img_title 		= isset($img_matches_title[0][1]) 	? htmlspecialchars_decode($img_matches_title[0][1], ENT_COMPAT | ENT_HTML5 | ENT_QUOTES) 	: false;

			//extract the href, alt, and title (if they exist) from the anchor
			preg_match_all('/href=[\'"](.*?)[\'"]/', 		$match[1], 	$matches_href, 	PREG_SET_ORDER);
			preg_match_all('/title=[\'"](.*?)[\'"]/', 		$match[1], 	$matches_title, PREG_SET_ORDER);

			//grab the values (if they existed)
			$href 		= isset($matches_href[0][1]) 	? $matches_href[0][1] 	: false;
			$title 		= isset($matches_title[0][1]) 	? htmlspecialchars_decode($matches_title[0][1], ENT_COMPAT | ENT_HTML5 | ENT_QUOTES) 	: false;

			if($href == false)
			{
				//something's wrong here
				continue;
			}

			$new_title = ($title != false ? $title : $img_title);

			$new_html = $match[0];

			// Link had no title before but now it does.
			if($title == false && $new_title != false)
			{
				//set new title
				$new_html = str_replace('<a ', '<a title="' . htmlspecialchars($new_title, ENT_COMPAT | ENT_HTML5 | ENT_QUOTES) . '" ', $new_html);
			}

			$original_html = str_replace($match[0], $new_html, $original_html);
		}

		return $original_html;
	}

	public static function filter_html_links($original_html)
	{
		// Get all anchors with target="_blank" and display a confirm() dialog.
		preg_match_all('/<a ([^<>]*?)target="_blank"([^<>]*?)>/', $original_html, $matches, PREG_SET_ORDER);

		foreach($matches as $match)
		{
			// Extract the href.
			preg_match_all('/href=[\'"](.*?)[\'"]/', $match[1] . " " . $match[2], $matches_href, PREG_SET_ORDER);

			// Grab the values (if they existed).
			$href = isset($matches_href[0][1]) ? $matches_href[0][1] : false;

			if($href == false)
			{
				// Something's wrong here
				continue;
			}

			$new_html = '<a ' . $match[1] . ' ' . $match[2] . ' onclick="if(confirm(\'This link will open in a new tab. Continue?\')){window.open(\'' . $href . '\');} return false;">';
			$original_html = str_replace($match[0], $new_html, $original_html);
		}

		return $original_html;
	}

	public static function optimize_html_for_webp($original_html)
	{
		//get all images
		preg_match_all('/<img .*?>/', $original_html, $matches, PREG_SET_ORDER);

		foreach($matches as $match)
		{
			//extract the src, alt, title, and longdesc (if they exist)
			preg_match_all('/src=[\'"](.*?)[\'"]/', 		$match[0], 	$matches_src, 	PREG_SET_ORDER);

			//grab the values (if they existed)
			$src = isset($matches_src[0][1]) ? $matches_src[0][1] : false;

			if($src == false)
			{
				//something's wrong here
				continue;
			}

			// If there's a protocol, but LIVE_SITE doesn't exist, this is an external image.
			if(stripos($src, "://") !== false && stripos($src, LIVE_SITE) == false)
			{
				continue;
			}

			//remove the live site and leading slash
			$src = str_ireplace(LIVE_SITE, "", $src);
			if(substr($src, 0, 1) == "/")
			{
				$src = substr($src, 1);
			}

			//remove any thumbnail resizing (100x50) from the end of the filename
			$src = preg_replace('/resized\//', '', $src);
			$src = preg_replace('/(_thumb)?_?(\d+)x(\d+)\./', '.', $src);

			$webp = Mainframe::webp($src);

			if($webp !== false && file_exists(ABSOLUTE_PATH . $webp))
			{
				// $source = str_ireplace(array("<img", "src=", $src), array("<source", "srcset=", $webp), $match[0]);
				$source = '<source srcset="' . $webp . '" type="image/webp">';
				$new_html = '<picture>' . $source . $match[0] . '</picture>';

				$original_html = str_replace($match[0], $new_html, $original_html);
			}
		}

		return $original_html;
	}

	public static function thumbnail($path, $width, $height, $crop=false, $output_format=null)
	{
		// Swap out our images directory for images/thumbnails
		$thumbnail 	= str_ireplace(ABSOLUTE_PATH, "", $path);
		$thumbnail 	= preg_replace('/^\/?images\//', ABSOLUTE_PATH . '/images/thumbnails/', $thumbnail);
		$thumbnail 	= preg_replace('/\.(jpe?g|png|gif|webp|JPE?G|PNG|GIF|WEBP)$/', '_' . $width . 'x' . $height . ($crop ? "_" . str_replace(":", "_", $crop) : "") . '.\1', $thumbnail);

		// Ensure that the file has the correct extension.
		$expected_extension = "";
		if($output_format == IMAGETYPE_JPEG)
		{
			$expected_extension = "jpg";
		}
		else if($output_format == IMAGETYPE_PNG)
		{
			$expected_extension = "png";
		}
		else if($output_format == IMAGETYPE_WEBP && function_exists("imagecreatefromwebp"))
		{
			$expected_extension = "webp";
		}
		else if($output_format == IMAGETYPE_GIF)
		{
			$expected_extension = "gif";
		}

		if($expected_extension) {
			$thumbnail = preg_replace('/\.(jpe?g|png|gif|webp|JPE?G|PNG|GIF|WEBP)$/', '.' . $expected_extension, $thumbnail);
		}

		// Create our thumbnail.  This will already check for pre-existence of the thumbnail for us.
		if(createThumbnail($path, $thumbnail, $width, $height, true, $crop, $output_format) === false) {
			return $path;
		}

		// Return the thumbnail's RELATIVE PUBLIC path starting with a slash.
		$thumbnail = str_ireplace(ABSOLUTE_PATH, "", $thumbnail);

		if(strpos($thumbnail, "/") !== 0)
		{
			$thumbnail = "/" . $thumbnail;
		}

		return $thumbnail;
	}

	public static function webp($path)
	{
		$size = getimagesize($path);
		return Mainframe::thumbnail($path, $size[0], $size[1], false, IMAGETYPE_WEBP);
	}

	public static function deleteThumbnails($path)
	{
		// Swap out our images directory for images/thumbnails
		$thumbnail 	= preg_replace('/\.(jpe?g|png|gif|webp|JPE?G|PNG|GIF|WEBP)$/', '', basename($path));
		$path 		= dirname(preg_replace('/\/images\//', '/images/thumbnails/', $path));
		$files 		= scandir($path);

		foreach($files as $f)
		{
			// Delete any files in the same directory that start with the same name as our file.
			if(preg_match('/^' . $thumbnail . '/', $f))
			{
				unlink($path . "/" . $f);
			}
		}
	}

	public static function preview($forced_page=null, $output=true, $heading=true)
    {
    	// Use global page.
    	$p = self::page();

    	// Unless a page was passed in.
    	if($forced_page)
    	{
    		$p = $forced_page;
    	}

    	// If no preview view exists, load the regular content view.
    	if(!file_exists(APPLICATION_PATH . "/views/content/" . $p->content_type_filename . "_preview.php"))
    	{
    		$forced_page->show_date = false;
    		return self::content($forced_page, $output, $heading);
    	}

    	ob_start();
		self::$CI->load->view("content/" . $p->content_type_filename . "_preview", array("page" => $p));
		$content = ob_get_contents();
		ob_end_clean();

		if($heading && $p->title_heading_level > 0)
		{
			$content = "<h" . $p->title_heading_level . ">" . $p->title . "</h" . $p->title_heading_level . ">" . $content;
		}

    	if($output)
    	{
    		echo($content);
    	}
    	else
    	{
			return $content;
		}
    }

	public static function content($forced_page=null, $output=true, $heading=true)
    {
    	// Use global page.
    	$p = self::page();

    	// Unless a page was passed in.
    	if($forced_page)
    	{
    		$p = $forced_page;
    	}

    	ob_start();
		self::$CI->load->view("content/" . $p->content_type_filename, array("page" => $p));
		$content = ob_get_contents();
		ob_end_clean();

		if($p->show_date)
		{
			$strtotime = strtotime($p->created);
			$content = '<time datetime="' . date("Y-m-d H:i:s", $strtotime) . '">' . date("l, F jS, Y", $strtotime) . '</time>' . $content;
		}

		if($heading && $p->title_heading_level > 0)
		{
			$content = "<h" . $p->title_heading_level . ">" . $p->title . "</h" . $p->title_heading_level . ">" . $content;
		}

    	if($output)
    	{
    		echo($content);
    	}
    	else
    	{
			return $content;
		}
    }

    public static function generateCSP(string &$content): string
    {
    	$site          = Mainframe::site();
    	$csp           = "base-uri 'self'; default-src 'self'; frame-ancestors 'self'";
    	$form_action   = "form-action 'self'";
    	$font_src      = "font-src 'self' fonts.gstatic.com";
    	$script_src    = "script-src 'self'";
    	$img_src       = "img-src 'self'";
    	$child_src     = "child-src 'self'";
    	$media_src     = "media-src 'self'";
    	$style_src     = "style-src 'self' fonts.googleapis.com";
    	$frame_src     = "frame-src 'self'";
    	$clean_content = str_replace("'", '"', $content);

		if(($site->recaptcha && $site->recaptcha_public_key) || $site->ga_code != "")
		{
			// Google claims to support passing a nonce to their script, but it doesn't seem to work.
			// We have to use 'unsafe-inline' to avoid breaking Google.
			$script_src .= " 'unsafe-inline' www.google.com www.gstatic.com www.googletagmanager.com";
			$child_src .= " www.google.com www.gstatic.com www.googletagmanager.com";
			$frame_src .= " www.google.com recaptcha.google.com www.googletagmanager.com";
		}

		if($site->fontawesome == 1)
		{
			$font_src .= " use.fontawesome.com";
			$style_src .= " use.fontawesome.com";
		}
		else if($site->fontawesome == 2)
		{
			$font_src .= " pro.fontawesome.com";
			$style_src .= " pro.fontawesome.com";
		}

    	// Look for all script tags.
    	preg_match_all('/<(script.*?)>/i', $clean_content, $matches);

		foreach($matches[1] as $match)
		{
			preg_match_all('/src="(.*?)"/i', $match, $sources);

			if(count($sources[1]) > 0)
			{
				$src = $sources[1][0];

				// Add external links to CSP.
				if(preg_match('/^http/i', $src))
				{
					// Only include the domain name.
					$src = str_replace(array("http://", "https://"), "", $src);
					$src = substr($src, 0, strpos($src, "/"));
					if(strpos($script_src, " " . $src) === false) {
						$script_src .= " " . $src;
					}
				}
				else
				{
					// Local src values are handled by 'self'
				}
			}

			// Create a nonce for all scripts.
			// This is supposed to make Google scripts respect the nonce.
			$nonce = generatePassword(16, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
			if(strpos($script_src, " nonce-" . $nonce) === false) {
				$script_src .= " nonce-" . $nonce;
			}
			$limit = 1;
			// Replace one of the script tags with its nonce.
			$content = str_replace("<" . $match . ">", '<' . $match . ' nonce="' . $nonce . '">', $content, $limit);
		}

		// Look for all link tags.
    	preg_match_all('/<link .*?href="(.*?)"/i', $clean_content, $matches);

		foreach($matches[1] as $match)
		{
			// Add external styles to CSP.
			if(preg_match('/^http/i', $match))
			{
				// Only include the domain name.
				$match = str_replace(array("http://", "https://"), "", $match);
				$match = substr($match, 0, strpos($match, "/"));
				if(strpos($style_src, " " . $match) === false) {
					$style_src .= " " . $match;
				}
			}
		}

		// Look for inline styles. If any are found, enable unsafe-inline.
		preg_match_all('/style="(.*?)">/i', $content, $matches);

		if(count($matches[1]) > 0)
		{
			$style_src .= " 'unsafe-inline'";
		}

		// Look for all style tags.
    	preg_match_all('/<(style.*?)>/i', $content, $matches);

		foreach($matches[1] as $match)
		{
			$nonce = generatePassword(16, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
			if(strpos($style_src, " nonce-" . $nonce) === false) {
				$style_src .= " nonce-" . $nonce;
			}
			$limit = 1;
			// Replace one of the inline style tags with its nonce.
			$content = str_replace("<" . $match . ">", '<style nonce="' . $nonce . '">', $content, $limit);
		}

		// Look for all iframe tags.
    	preg_match_all('/<iframe .*?src="(.*?)"/i', $clean_content, $matches);

		foreach($matches[1] as $match)
		{
			// Add iframe sources to CSP.
			if(preg_match('/^http/i', $match))
			{
				// Only include the domain name.
				$match = str_replace(array("http://", "https://"), "", $match);
				$match = substr($match, 0, strpos($match, "/"));
				if(strpos($child_src, " " . $match) === false) {
					$child_src .= " " . $match;
				}
				if(strpos($frame_src, " " . $match) === false) {
					$frame_src .= " " . $match;
				}
			}
		}

		// Look for all img tags.
    	preg_match_all('/<img .*?src="(.*?)"/i', $clean_content, $matches);

		foreach($matches[1] as $match)
		{
			// Add img sources to CSP.
			if(preg_match('/^http/i', $match))
			{
				// Only include the domain name.
				$match = str_replace(array("http://", "https://"), "", $match);
				$match = substr($match, 0, strpos($match, "/"));
				if(strpos($img_src, " " . $match) === false) {
					$img_src .= " " . $match;
				}
			}
		}

    	return  $csp 			. "; " .
    			$font_src 		. "; " .
    			$form_action 	. "; " .
    			$script_src 	. "; " .
    			$img_src 		. "; " .
    			$media_src 		. "; " .
    			$child_src 		. "; " .
    			$style_src 		. "; " .
    			$frame_src 		. ";";
    }
}
