�PNG  IHDR22?�� pHYs  �� OiCCPPhotoshop ICC profilexڝSgTS�=���BK���KoR RB���&*! J�!��Q�EEȠ�����Q, � ��!���������{�kּ������>���� �H3Q5� �B�������.@� $p�d!s�#�~<<+"��x� �M��0���B�\���t�8K�@z�B�@F���&S�`�cb�P-`'������{[�!�� e�Dh;��V�EX0fK�9�-0IWfH���� � 0Q��){`�##x��F�W<�+��*x��<�$9E�[-qWW.(�I+6aa�@.�y�2�4���������x����6��_-��"bb���ϫp@�t~��,/��;�m��%�h^ �u��f�@����W�p�~<�5�j>{�-�]c�K'Xt����o��(�h���w��?�G�%�fI�q^D$.Tʳ?�D��*�A��,���� �`6�B$��BB d�r`)��B(�Ͱ*`/�@4�Qh��p.�U�=p�a��(�� A�a!ڈb�X#����!�H�$ ɈQ"K�5H1R�T UH�=r9�\F��;�2����G1���Q=� �C��7�F� �dt1�����r�=�6��Ыhڏ>C�0��3�l0.��B�8, �c˱"� ���V����cϱw�E� 6wB aAHXLXN�H� $4� 7 �Q�'"��K�&���b21�XH,#��/{�C�7$�C2'��I��T��F�nR#�,��4H#���dk�9�, +ȅ����3��!�[ �b@q��S�(R�jJ��4�e�2AU��Rݨ�T5�ZB���R�Q��4u�9̓IK�����hh�i��t�ݕN��W���G���w ��Ljg(�gw��L�Ӌ�T071���oUX*�*|�� �J�&�*/T����ު U�U�T��^S}�FU3S� Ԗ�U��P�SSg�;���g�oT?�~Y��Y�L�OC�Q��_�� c�x,!k ��u�5�&���|v*�����=���9C3J3W�R�f?�q��tN �(���~���)�)�4L�1e\k����X�H�Q�G�6������E�Y��A�J'\'Gg����S�Sݧ �M=:��.�k���Dw�n��^��Lo��y���}/�T�m���G X� $� �<�5qo</���QC]�@C�a�a�ᄑ��<��F�F�i�\�$�m�mƣ&&!&KM�M�RM��)�;L;L���͢�֙5�=1�2��כ߷`ZxZ,����eI��Z�Yn�Z9Y�XUZ]�F���%ֻ�����N�N���gð�ɶ�����ۮ�m�}agbg�Ů��}�}��= ���Z~s�r:V:ޚΜ�?}����/gX���3��)�i�S��Ggg�s�󈋉K��.�>.���Ƚ�Jt�q]�z���������ۯ�6�i�ܟ�4�)�Y3s���C�Q��? ��0k߬~OCO�g��#/c/�W�װ��w��a�>�>r��>�<7�2�Y_�7��ȷ�O�o�_��C#�d�z����%g��A�[��z|!��?:�e����A���AA�������!h�쐭!��Α�i�P~���a�a��~ '���W�?�p�X�1�5w��Cs�D�D�Dޛg1O9�-J5*>�.j<�7�4�?�.fY��X�XIlK9.*�6nl������� �{�/�]py�����.,:�@L�N8��A*��%�w%� y��g"/�6ш�C\*N�H*Mz�쑼5y$�3�,幄'���L Lݛ:��v m2=:�1����qB�!M��g�g�fvˬe����n��/��k���Y- �B��TZ(�*�geWf�͉�9���+��̳�ې7�����ᒶ��KW-X潬j9�������(�x��oʿ�ܔ���Ĺd�f�f���-�[����n �ڴ �V����E�/��(ۻ��C���<��e����;?T�T�T�T6��ݵa��n��{��4���[���>ɾ�UUM�f�e�I���?�������m]�Nmq����#�׹���=TR��+�G�����w- 6 U����#pDy��� �� :�v�{���vg/jB��F�S��[b[�O�>����z�G��499�?r����C�d�&����ˮ/~�����јѡ�򗓿m|������������x31^�V���w�w��O�| (�h���SЧ��������c3-� cHRMz%������u0�`:�o�_�F5IDATx��ytUս�?�;���fN$$��@B�!�k��� -*�gE���j�O�kQ�ʠ`U�B_ �AÐ0%�Ȕ�@r3ޛ;߳��$�@��v����^�s����������$��ߢ !�W��5�̱'-٘������4�>�Rƫ$�G��0U�H}�_ _� #��k�MJ/=�9Du *ڲ�k�PQ;0��j|�*�$�^컂脛y���>�z×� B��� ��(�:$�ʔ_�6��C!B����MVx��a��ζyY����j��ƋY2�9�F�{r��r�딟F��Q��hY6��� x��[l��RC��������nt@��;P��3��� F�w��7��:�P���ɋ'���mj���Bƪ�$�Q�L��y��߷g��\���z����v5�p�v$�v櫻�`6~K �Y�X����,�:��"�o�e0II"(��,������l_�C���/4�+f�E�!q��:����u����c��樼.UE�@� �]K�W���$-�h]�JG���Dz)�`��.�A/ ���mᏣc�3jK� �!�>���$�Q�!�_�? \�C2(E �M$Z I{�U���s�ǣ���=��@Բe ޻��W�����@ �w����}�9v,)��.}*|"�s��di���,���G�]W�AC�������|<����[��ߕ������K�*�G nߴ!��‹��J�!��6(L�a)��Am��������;adf��:�xm��nh�;֦I��(���o�C~ډa?�=��s����h��E������xp����)���_���t��W�����´;8���`dz=(��@@�+,�;�`�fhl��XȌ�3,uI�~z(J����� �ZX�A����H'�À�㜦�82|��a�n�z2��I���� ���EY�h�ε<�0�q�{��C��v�˅��?"@��χ�x�WS+��N�~�KQ�J�8ل�� _.W��� !TU{�����,��"�� �;�������HI S� ��))�o�1�H�D� ���� (� ;����"Ҕ��,���� �F=���O��&�Ph>�`���y��߲ &S��P�<��'��1s�1cĂ�N����2)����@�u��tv��<�+�-&�����h��[!FSG���' � z z0��<����8d&�����E0�,��<��"!P�b4��� �{S�����X����.�囤���T��hEF��X�q0"-<����h���]�Py*����F⩍��@v�˂�Y08�� .q��a��s����(!<̫1�3�L�H��7sYW�`��qtu�\7��?�@�Y�� %Ka�x�GZ�*W�P��y�����N0r9��Z�c�%���q,��k�����!!,��>���IB��� �x1�Xu�Y���v-���ֺ��N������JP��a�2`�e5��w��u;�6�i���̃��(K���ťa��(l51��JL��O'%���]���ٖ뿉!��{*�p+f ���i8��D�ȑ���ܩ�M��V��ӟz��x�7Z�1i}�^͜���6e����x��)u�d�ˏ�V�eG�\�X1�����=n�U'�~Y����L�\,�(d!x ,�:�TW8� M`r���@��r+v�Q0��>^;˴�VbF��('����� �*O��i��j�Ӆ����^�S3&� ���{������.ی�� N;��NU%d0�Ce\r"�C�b��&t7N�7��� �ȪD�[%l�۪�$��'m?�A9tI�9>��NVL ��� 6v~M�����ъ�B���0����9$&=ώm��W�0���L���&��E���f�f��'+�9��hv��7,���M��6�D�&�^� �����8 D֮�����o��k^z��O��hP�8q�5d*��YVq3�{��������#LX4�?��jP=3�~�؅c�ݰ�̱�ұ��8̲��2�G�����j��έ�9��w7���U�X�w�85C��?!I&���o&����L���I#�^�eV�,�^t5�k� �xs˛\��U�8��."���{���ǵ�l4��ݼ�;��r"���G�/~���gJV�N糦��ZZ^k+NN�D��I$�=OE�z����|*�*{��%k���G��>�`9��b;�s���8,�qs��c��.b��q�%�>r��n�R�Ƨ�%�,�A��le#�8���}; 21�0�b�&�QX�f���q�00����$>�h�N�'�a3��A���/�r ��L5�8�GԲ'�����w;��c#�q1���h$*��V^�k��QĽ�b:i������� ����H F#�_���,��]g����Ը����`RUU���� ��"�qD���>-��ϤI�~��3�̴�����NZ[[555�eeek7�m����YF#[��Đ��R��i��L�H�r ��@��J-�Pŝ��_|�-��6y��ks�V�U~��6���w.����(��0A� 4��f��� /���C�xŊ�ٳ����z=6�����rg���mKo��o�/����a�g���?'9%9��P��斓��~���L{�� �H��{AW��B��$����v�1b�&Mb�ر��ر#�0`�`xMBp! )Z�Nmo�mZ�g�}�eذaWTVV ���'99��C5��&�&+5�bT>|8��PUUETT����&���t��~TE%��'������b�tEGG;RSS�S�N�v��ѯ��t����u1@�ޚ"f��͈���r'L�Ph��m��ƌ�74o��`�x�q�P���NRSS�X,�����l&&&��MFFA!-��`��ҷ�n��Yuu�����x<I�LB%����KԒ50�!�3�bz�����ʸKL���;---�l6[��`��������Ȏ;�����egg4��!D�T��jWujyZ��������K����%����p�^���X,6��sV=�ܖ����6�3�X ���4ҿ��A2�&����_k�;d�� �VfOIEND�B`�
Warning: session_start(): Session cannot be started after headers have already been sent in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 124

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 130

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 131

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 132

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 133

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 134

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 135
0x0x
PHP 8.2.31
Preview: wfActivityReport.php Size: 20.55 KB
/home/m/c/i/mciraet/www/wp-content/plugins/wordfence/lib/wfActivityReport.php
<?php
if (defined('WORDFENCE_VERSION')) {

class wfActivityReport {
	const BLOCK_TYPE_COMPLEX = 'complex';
	const BLOCK_TYPE_BRUTE_FORCE = 'bruteforce';
	const BLOCK_TYPE_BLACKLIST = 'blacklist';

	/**
	 * @var int
	 */
	private $limit = 10;

	/**
	 * @var wpdb
	 */
	private $db;

	/**
	 * @param int $limit
	 */
	public function __construct($limit = 10) {
		global $wpdb;
		$this->db = $wpdb;
		$this->limit = $limit;
	}

	/**
	 * Schedule the activity report cron job.
	 */
	public static function scheduleCronJob() {
		self::clearCronJobs();

		if (!wfConfig::get('email_summary_enabled', 1)) {
			return;
		}

		if (is_main_site()) {
			list(, $end_time) = wfActivityReport::getReportDateRange();
			wp_schedule_single_event($end_time, 'wordfence_email_activity_report');
		}
	}

	/**
	 * Remove the activity report cron job.
	 */
	public static function disableCronJob() {
		self::clearCronJobs();
	}

	public static function clearCronJobs() {
		wp_clear_scheduled_hook('wordfence_email_activity_report');
	}

	/**
	 * Send out the report and reschedule the next report's cron job.
	 */
	public static function executeCronJob() {
		if (!wfConfig::get('email_summary_enabled', 1)) {
			return;
		}
		
		$emails = wfConfig::getAlertEmails();
		if (count($emails)) {
			$report = new self();
			$report->sendReportViaEmail($emails);
		}
		self::scheduleCronJob();
	}

	/**
	 * Output a compact version of the email for the WP dashboard.
	 */
	public static function outputDashboardWidget() {
		$report = new self(5);
		echo $report->toWidgetView();
	}

	/**
	 * @return array
	 */
	public static function getReportDateRange() {
		$interval = wfConfig::get('email_summary_interval', 'weekly');
		$offset = get_option('gmt_offset');
		return self::_getReportDateRange($interval, $offset);
	}

	/**
	 * Testable code.
	 *
	 * @param string $interval
	 * @param int    $offset
	 * @param null   $time
	 * @return array
	 */
	public static function _getReportDateRange($interval = 'weekly', $offset = 0, $time = null) {
		if ($time === null) {
			$time = time();
		}

		$day = (int) gmdate('w', $time);
		$month = (int) gmdate("n", $time);
		$day_of_month = (int) gmdate("j", $time);
		$year = (int) gmdate("Y", $time);

		$start_time = 0;
		$end_time = 0;

		switch ($interval) {
			// Send a report 4pm every day
			case 'daily':
				$start_time = gmmktime(16, 0, 0, $month, $day_of_month, $year) + (-$offset * 60 * 60);
				$end_time = $start_time + 86400;
				break;
			
			// Send a report 4pm every Monday
			case 'weekly':
				$start_time = gmmktime(16, 0, 0, $month, $day_of_month - $day + 1, $year) + (-$offset * 60 * 60);
				$end_time = $start_time + (86400 * 7);
				break;

			// Send a report at 4pm the first of every month
			case 'monthly':
				$start_time = gmmktime(16, 0, 0, $month, 1, $year) + (-$offset * 60 * 60);
				$end_time = gmmktime(16, 0, 0, $month + 1, 1, $year) + (-$offset * 60 * 60);
				break;
		}

		return array($start_time, $end_time);
	}

	/**
	 * @return int
	 */
	public static function getReportDateFrom() {
		$interval = wfConfig::get('email_summary_interval', 'weekly');
		return self::_getReportDateFrom($interval);
	}

	/**
	 * @param string $interval
	 * @param null   $time
	 * @return int
	 */
	public static function _getReportDateFrom($interval = 'weekly', $time = null) {
		if ($time === null) {
			$time = time();
		}

		// weekly
		$from = $time - (86400 * 7);
		switch ($interval) {
			case 'daily':
				$from = $time - 86400;
				break;

			// Send a report at 4pm the first of every month
			case 'monthly':
				$from = strtotime('-1 month', $time);
				break;
		}

		return $from;
	}

	/**
	 * @return array
	 */
	public function getFullReport() {
		$start_time = microtime(true);
		$remainder = 0;
		$recent_firewall_activity = $this->getRecentFirewallActivity($this->limit, $remainder);
		return array(
			'top_ips_blocked'          => $this->getTopIPsBlocked($this->limit),
			'top_countries_blocked'    => $this->getTopCountriesBlocked($this->limit),
			'top_failed_logins'        => $this->getTopFailedLogins($this->limit),
			'recent_firewall_activity' => $recent_firewall_activity,
			'omitted_firewall_activity'=> $remainder,
			'recently_modified_files'  => $this->getRecentFilesModified($this->limit),
			'updates_needed'           => $this->getUpdatesNeeded(),
			'microseconds'             => microtime(true) - $start_time,
		);
	}

	/**
	 * @return array
	 */
	public function getWidgetReport() {
		$start_time = microtime(true);
		return array(
			'top_ips_blocked'       => $this->getTopIPsBlocked($this->limit),
			'top_countries_blocked' => $this->getTopCountriesBlocked($this->limit),
			'top_failed_logins'     => $this->getTopFailedLogins($this->limit),
			'updates_needed'        => $this->getUpdatesNeeded(),
			'microseconds'          => microtime(true) - $start_time,
		);
	}
	
	public function getBlockedCount($maxAgeDays = null, $grouping = null) {
		$maxAgeDays = (int) $maxAgeDays;
		if ($maxAgeDays <= 0) {
			$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 7 day)) / 86400)';
			switch (wfConfig::get('email_summary_interval', 'weekly')) {
				case 'daily':
					$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 day)) / 86400)';
					break;
				case 'monthly':
					$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 month)) / 86400)';
					break;
			}
		}
		else {
			$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval ' . $maxAgeDays . ' day)) / 86400)';
		}
		
		//Possible values for blockType: throttle, manual, brute, fakegoogle, badpost, country, advanced, blacklist, waf
		$groupingWHERE = '';
		switch ($grouping) {
			case self::BLOCK_TYPE_COMPLEX:
				$groupingWHERE = ' AND blockType IN ("fakegoogle", "badpost", "country", "advanced", "waf")';
				break;
			case self::BLOCK_TYPE_BRUTE_FORCE:
				$groupingWHERE = ' AND blockType IN ("throttle", "brute")';
				break;
			case self::BLOCK_TYPE_BLACKLIST:
				$groupingWHERE = ' AND blockType IN ("blacklist", "manual")';
				break;
		}
		
		$table_wfBlockedIPLog = wfDB::networkTable('wfBlockedIPLog');
		$count = $this->db->get_var(<<<SQL
SELECT SUM(blockCount) as blockCount
FROM {$table_wfBlockedIPLog}
WHERE unixday >= {$interval}{$groupingWHERE}
SQL
			);
		return $count;
	}

	/**
	 * @param int $limit
	 * @return mixed
	 */
	public function getTopIPsBlocked($limit = 10, $maxAgeDays = null) {
		$maxAgeDays = (int) $maxAgeDays;
		if ($maxAgeDays <= 0) {
			$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 7 day)) / 86400)';
			switch (wfConfig::get('email_summary_interval', 'weekly')) {
				case 'daily':
					$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 day)) / 86400)';
					break;
				case 'monthly':
					$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 month)) / 86400)';
					break;
			}
		}
		else {
			$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval ' . $maxAgeDays . ' day)) / 86400)';
		}
		
		$table_wfBlockedIPLog = wfDB::networkTable('wfBlockedIPLog');
		$query=<<<SQL
SELECT IP, countryCode, unixday, blockType,
SUM(blockCount) as blockCount
FROM {$table_wfBlockedIPLog}
WHERE unixday >= {$interval}
GROUP BY IP
ORDER BY blockCount DESC
LIMIT %d
SQL;
		$results = $this->db->get_results($this->db->prepare($query, $limit));
		if ($results) {
			foreach ($results as &$row) {
				$row->countryName = $this->getCountryNameByCode($row->countryCode);
			}
		}
		return $results;
	}

	/**
	 * @param int $limit
	 * @return array
	 */
	public function getTopCountriesBlocked($limit = 10, $maxAgeDays = null) {
		$maxAgeDays = (int) $maxAgeDays;
		if ($maxAgeDays <= 0) {
			$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 7 day)) / 86400)';
			switch (wfConfig::get('email_summary_interval', 'weekly')) {
				case 'daily':
					$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 day)) / 86400)';
					break;
				case 'monthly':
					$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 month)) / 86400)';
					break;
			}
		}
		else {
			$interval = 'FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval ' . $maxAgeDays . ' day)) / 86400)';
		}
	  	
		$table_wfBlockedIPLog = wfDB::networkTable('wfBlockedIPLog');
		$query=<<<SQL
SELECT *, COUNT(IP) as totalIPs, SUM(ipBlockCount) as totalBlockCount
FROM (SELECT *, SUM(blockCount) AS ipBlockCount FROM {$table_wfBlockedIPLog} WHERE unixday >= {$interval} GROUP BY IP) t
GROUP BY countryCode
ORDER BY totalBlockCount DESC
LIMIT %d
SQL;
		$results = $this->db->get_results($this->db->prepare($query, $limit));
		if ($results) {
			foreach ($results as &$row) {
				$row->countryName = $this->getCountryNameByCode($row->countryCode);
			}
		}
		return $results;
	}

	/**
	 * @param int $limit
	 * @return mixed
	 */
	public function getTopFailedLogins($limit = 10) {
		$interval = 'UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 7 day))';
		switch (wfConfig::get('email_summary_interval', 'weekly')) {
			case 'daily':
				$interval = 'UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 day))';
				break;
			case 'monthly':
				$interval = 'UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 month))';
				break;
		}
	  
		$table_wfLogins = wfDB::networkTable('wfLogins');
		$failedLogins = $this->db->get_results($this->db->prepare(<<<SQL
SELECT wfl.*,
sum(wfl.fail) as fail_count
FROM {$table_wfLogins} wfl
WHERE wfl.fail = 1
AND wfl.ctime > $interval
GROUP BY wfl.username
ORDER BY fail_count DESC
LIMIT %d
SQL
			, $limit));
		
		foreach ($failedLogins as &$login) {
			$exists = $this->db->get_var($this->db->prepare(<<<SQL
SELECT !ISNULL(ID) FROM {$this->db->users} WHERE user_login = '%s' OR user_email = '%s'
SQL
			, $login->username, $login->username));
			$login->is_valid_user = $exists;
		}
		
		return $failedLogins;
	}

	/**
	 * Returns any updates needs or false if everything is up to date.
	 *
	 * @return array|bool
	 */
	public function getUpdatesNeeded($useCachedValued = true) {
		$update_check = new wfUpdateCheck();
		$needs_update = $update_check->checkAllUpdates($useCachedValued)
			->needsAnyUpdates();
		if ($needs_update) {
			return array(
				'core'    => $update_check->getCoreUpdateVersion(),
				'plugins' => $update_check->getPluginUpdates(),
				'themes'  => $update_check->getThemeUpdates(),
			);
		}
		return false;
	}

	/**
	 * Returns list of firewall activity up to $limit number of entries.
	 *
	 * @param int $limit Max events to return in results
	 * @param int $remainder
	 * @return array
	 */
	public function getRecentFirewallActivity($limit, &$remainder) {
		$dateRange = wfActivityReport::getReportDateRange();
		$recent_firewall_activity = new wfRecentFirewallActivity(null, max(604800, $dateRange[1] - $dateRange[0]));
		$recent_firewall_activity->run();
		return $recent_firewall_activity->mostRecentActivity($limit, $remainder);
	}

	/**
	 * Returns list of files modified within given timeframe.
	 *
	 * @todo Add option to configure the regex used to filter files allowed in this list.
	 * @todo Add option to exclude directories (such as cache directories).
	 *
	 * @param string $directory Search for files within this directory
	 * @param int    $time_range One week
	 * @param int    $limit Max files to return in results
	 * @param int    $directory_limit Hard limit for number of files to search within a directory.
	 * @return array
	 */
	public function getRecentFilesModified($limit = 300, $directory = ABSPATH, $time_range = 604800, $directory_limit = 20000) {
		$recently_modified = new wfRecentlyModifiedFiles($directory);
		$recently_modified->run();
		return $recently_modified->mostRecentFiles($limit);
	}

	/**
	 * Remove entries older than a month in the IP log.
	 */
	public function rotateIPLog() {
		$table_wfBlockedIPLog = wfDB::networkTable('wfBlockedIPLog');
		$this->db->query(<<<SQL
DELETE FROM {$table_wfBlockedIPLog}
WHERE unixday < FLOOR(UNIX_TIMESTAMP(DATE_SUB(NOW(), interval 1 month)) / 86400)
SQL
		);
	}

	/**
	 * @param mixed $ip_address
	 * @param int|null $unixday
	 */
	public static function logBlockedIP($ip_address, $unixday = null, $type = null) {
		/** @var wpdb $wpdb */
		global $wpdb;
		
		//Possible values for $type: throttle, manual, brute, fakegoogle, badpost, country, advanced, blacklist, waf

		if (wfUtils::isValidIP($ip_address)) {
			$ip_bin = wfUtils::inet_pton($ip_address);
		} else {
			$ip_bin = $ip_address;
			$ip_address = wfUtils::inet_ntop($ip_bin);
		}
		
		$blocked_table = wfDB::networkTable('wfBlockedIPLog');

		$unixday_insert = 'FLOOR(UNIX_TIMESTAMP() / 86400)';
		if (is_int($unixday)) {
			$unixday_insert = absint($unixday);
		}
		
		if ($type === null) {
			$type = 'generic';
		}

		$country = wfUtils::IP2Country($ip_address);
		
		$ipHex = wfDB::binaryValueToSQLHex($ip_bin);
		$wpdb->query($wpdb->prepare(<<<SQL
INSERT INTO $blocked_table (IP, countryCode, blockCount, unixday, blockType)
VALUES ({$ipHex}, %s, 1, $unixday_insert, %s)
ON DUPLICATE KEY UPDATE blockCount = blockCount + 1
SQL
			, $country, $type));
	}

	/**
	 * @param $code
	 * @return string
	 */
	public function getCountryNameByCode($code) {
		static $wfBulkCountries;
		if (!isset($wfBulkCountries)) {
			include(dirname(__FILE__) . '/wfBulkCountries.php');
		}
		return array_key_exists($code, $wfBulkCountries) ? $wfBulkCountries[$code] : "";
	}

	/**
	 * @return wfActivityReportView
	 */
	public function toView() {
		return new wfActivityReportView('reports/activity-report', $this->getFullReport() + array(
				'limit' => $this->getLimit(),
			));
	}

	/**
	 * @return wfActivityReportView
	 */
	public function toWidgetView() {
		return new wfActivityReportView('reports/activity-report', $this->getWidgetReport() + array(
				'limit' => $this->getLimit(),
			));
	}

	/**
	 * @return wfActivityReportView
	 */
	public function toEmailView() {
		return new wfActivityReportView('reports/activity-report-email-inline', $this->getFullReport());
	}

	/**
	 * @param $email_addresses string|array
	 * @return bool
	 */
	public function sendReportViaEmail($email_addresses) {
		$shortSiteURL = preg_replace('/^https?:\/\//i', '', site_url());
		
		$content = $this->toEmailView()->__toString();
		
		$success = true;
		if (is_string($email_addresses)) { $email_addresses = explode(',', $email_addresses); }
		foreach ($email_addresses as $email) {
			$uniqueContent = str_replace('<!-- ##UNSUBSCRIBE## -->', wp_kses(sprintf(/* translators: URL to the WordPress admin panel. */ __('No longer an administrator for this site? <a href="%s" target="_blank">Click here</a> to stop receiving security alerts.', 'wordfence'), wfUtils::getSiteBaseURL() . '?_wfsf=removeAlertEmail&jwt=' . wfUtils::generateJWT(array('email' => $email))), array('a'=>array('href'=>array(), 'target'=>array()))), $content);
			if (!wp_mail($email, sprintf(/* translators: 1. Site URL. 2. Localized date. */ __('Wordfence activity for %1$s on %2$s', 'wordfence'), date_i18n(get_option('date_format')), $shortSiteURL), $uniqueContent, 'Content-Type: text/html')) {
				$success = false;
			}
		}
		
		return $success;
	}

	/**
	 * @return string
	 * @throws wfViewNotFoundException
	 */
	public function render() {
		return $this->toView()
			->render();
	}

	/**
	 * @return string
	 */
	public function __toString() {
		return $this->toView()
			->__toString();
	}

	/**
	 * @return int
	 */
	public function getLimit() {
		return $this->limit;
	}

	/**
	 * @param int $limit
	 */
	public function setLimit($limit) {
		$this->limit = $limit;
	}
}

class wfRecentFirewallActivity {
	private $activity = array();
	
	private $max_fetch = 2000;
	private $time_range = 604800;
	
	public function __construct($max_fetch = null, $time_range = null) {
		if ($max_fetch !== null) {
			$this->max_fetch = $max_fetch;
		}
		
		if ($time_range !== null) {
			$this->time_range = $time_range;
		}
	}
	
	public function run() {
		global $wpdb;
		
		$table_wfHits = wfDB::networkTable('wfHits');
		$results = $wpdb->get_results($wpdb->prepare(<<<SQL
SELECT attackLogTime, IP, URL, UA, actionDescription, actionData
FROM {$table_wfHits}
WHERE action = 'blocked:waf' AND attackLogTime > (UNIX_TIMESTAMP() - %d)
ORDER BY attackLogTime DESC
LIMIT %d
SQL
			, $this->time_range, $this->max_fetch));
		if ($results) {
			foreach ($results as &$row) {
				$actionData = json_decode($row->actionData, true);
				$row->actionDescription = wfWAFBlockI18n::getTranslatedBlockDescription($row->actionDescription);
				if (!is_array($actionData) || !isset($actionData['paramKey']) || !isset($actionData['paramValue'])) {
					continue;
				}
				
				if (isset($actionData['failedRules']) && $actionData['failedRules'] == 'blocked') {
					$row->longDescription = __("Blocked because the IP is blocklisted", 'wordfence');
				}
				else {
					$row->longDescription = sprintf(__("Blocked for %s", 'wordfence'), $row->actionDescription);
				}
				
				$paramKey = base64_decode($actionData['paramKey']);
				$paramValue = base64_decode($actionData['paramValue']);
				if (strlen($paramValue) > 100) {
					$paramValue = substr($paramValue, 0, 100) . '...';
				}
				
				if (preg_match('/([a-z0-9_]+\.[a-z0-9_]+)(?:\[(.+?)\](.*))?/i', $paramKey, $matches)) {
					switch ($matches[1]) {
						case 'request.queryString':
							$row->longDescription = sprintf(__('Blocked for %1$s in query string: %2$s = %3$s', 'wordfence'), $row->actionDescription, $matches[2], $paramValue);
							break;
						case 'request.body':
							$row->longDescription = sprintf(__('Blocked for %1$s in POST body: %2$s = %3$s', 'wordfence'), $row->actionDescription, $matches[2], $paramValue);
							break;
						case 'request.cookie':
							$row->longDescription = sprintf(__('Blocked for %1$s in cookie: %2$s = %3$s', 'wordfence'), $row->actionDescription, $matches[2], $paramValue);
							break;
						case 'request.fileNames':
							$row->longDescription = sprintf(__('Blocked for %1$s in file: %2$s = %3$s', 'wordfence'), $row->actionDescription, $matches[2], $paramValue);
							break;
					}
				}
			}
		}
		
		$this->activity = $results;
	}
	
	public function mostRecentActivity($limit, &$remainder = null) {
		if ($remainder !== null) {
			$remainder = count($this->activity) - $limit;
		}
		return array_slice($this->activity, 0, $limit);
	}
}

class wfRecentlyModifiedFiles extends wfDirectoryIterator {

	/**
	 * @var int
	 */
	private $time_range = 604800;

	/**
	 * @var array
	 */
	private $files = array();
	private $excluded_directories;

	/**
	 * @param string $directory
	 * @param int    $max_files_per_directory
	 * @param int    $max_iterations
	 * @param int    $time_range
	 */
	public function __construct($directory = ABSPATH, $max_files_per_directory = 20000, $max_iterations = 250000, $time_range = 604800) {
		parent::__construct($directory, $max_files_per_directory, $max_iterations);
		$this->time_range = $time_range;
		$excluded_directories = explode("\n", wfUtils::cleanupOneEntryPerLine(wfConfig::get('email_summary_excluded_directories', '')));
		$this->excluded_directories = array();
		foreach ($excluded_directories  as $index => $path) {
			if (($dir = realpath(ABSPATH . $path)) !== false) {
				$this->excluded_directories[$dir] = 1;
			}
		}
	}

	/**
	 * @param $dir
	 * @return bool
	 */
	protected function scan($dir) {
		if (!array_key_exists(realpath($dir), $this->excluded_directories)) {
			return parent::scan($dir);
		}
		return true;
	}


	/**
	 * @param string $file
	 */
	public function file($file) {
		$mtime = filemtime($file);
		if (time() - $mtime < $this->time_range) {
			$this->files[] = array($file, $mtime);
		}
	}

	/**
	 * @param int $limit
	 * @return array
	 */
	public function mostRecentFiles($limit = 300) {
		usort($this->files, array(
			$this,
			'_sortMostRecentFiles',
		));
		return array_slice($this->files, 0, $limit);
	}

	/**
	 * Sort in descending order.
	 *
	 * @param $a
	 * @param $b
	 * @return int
	 */
	private function _sortMostRecentFiles($a, $b) {
		if ($a[1] > $b[1]) {
			return -1;
		}
		if ($a[1] < $b[1]) {
			return 1;
		}
		return 0;
	}

	/**
	 * @return mixed
	 */
	public function getFiles() {
		return $this->files;
	}
}


class wfActivityReportView extends wfView {

	/**
	 * @param $file
	 * @return string
	 */
	public function displayFile($file) {
		$realPath = realpath($file);
		if (stripos($realPath, ABSPATH) === 0) {
			return substr($realPath, strlen(ABSPATH));
		}
		return $realPath;
	}

	/**
	 * @param null $unix_time
	 * @return string
	 */
	public function modTime($unix_time = null) {
		if ($unix_time === null) {
			$unix_time = time();
		}
		return wfUtils::formatLocalTime('F j, Y g:ia', $unix_time);
	}
	
	public function attackTime($unix_time = null) {
		if ($unix_time === null) {
			$unix_time = time();
		}
		return wfUtils::formatLocalTime('F j, Y', $unix_time) . "<br>" . wfUtils::formatLocalTime('g:ia', $unix_time);
	}
	
	public function displayIP($binaryIP) {
		$readableIP = wfUtils::inet_ntop($binaryIP);
		$country = wfUtils::countryCode2Name(wfUtils::IP2Country($readableIP));
		return "{$readableIP} (" . ($country ? $country : __('Unknown', 'wordfence')) . ")";
	}
}
}

Directory Contents

Dirs: 4 × Files: 108
Name Size Perms Modified Actions
audit-log DIR
- drwxr-xr-x 2026-08-11 10:23:26
Edit Download
dashboard DIR
- drwxr-xr-x 2026-08-11 10:23:26
Edit Download
Diff DIR
- drwxr-xr-x 2026-08-11 10:23:26
Edit Download
rest-api DIR
- drwxr-xr-x 2026-08-11 10:23:26
Edit Download
425 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
5.63 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
2.85 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.39 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
8.82 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
2.34 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.02 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
6.62 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
8.31 MB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.17 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
580 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
4.46 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.69 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.94 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
317 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
3.07 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
4.01 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
2.02 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
2.05 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
9.15 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
3.60 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
2.86 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
3.33 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
10.87 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.68 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
12.49 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
40.95 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.33 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
408 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
991 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.30 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
9.80 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.64 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
185 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.51 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.47 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
9.72 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
20.55 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
13.27 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
8.19 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
10.10 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
47.13 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.02 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
3.90 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
256.83 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
9.77 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
6.02 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
25.94 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.25 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
127.17 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
6.92 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
10.31 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
4.05 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.02 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
9.25 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
352.13 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
11.49 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
2.13 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
69.43 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.89 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
2.72 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.97 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
2.13 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
878 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
3.23 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
303 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
266 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.80 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
2.70 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.56 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
29.14 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
200.80 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
5.33 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
10.95 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
9.81 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
58.47 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.27 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
5.20 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
754 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
6.70 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
8.93 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.40 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
377 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
15.98 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
128.27 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.04 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.01 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
403 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
408 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.07 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
4.09 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.77 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
11.93 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.21 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
24.95 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.14 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
27.23 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
131.69 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
15.59 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
535 B lrw-r--r-- 2026-08-11 10:23:26
Edit Download
2.22 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.47 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
1.75 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
400.80 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
3.35 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
42.60 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
28.19 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
18.35 KB lrw-r--r-- 2026-08-11 10:23:26
Edit Download
If ZipArchive is unavailable, a .tar will be created (no compression).
© 2026 0xNothings — Secure File Manager. All rights reserved. Built with ❤️ & Tailwind x Dark UI