�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`� 0x0x
PHP 8.1.34
Preview: BotStatsExporter.php Size: 13.17 KB
/home2/astrociv/www/avadhutholidays.in/wp-content/plugins/imunify-security/inc/App/Bot/BotStatsExporter.php
<?php
/**
 * Copyright (с) Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2025 All Rights Reserved
 *
 * Licensed under CLOUD LINUX LICENSE AGREEMENT
 * https://www.cloudlinux.com/legal/
 *
 * phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged
 * phpcs:disable WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
 */

namespace CloudLinux\Imunify\App\Bot;

/**
 * Daily bot-traffic export: aggregate the previous full calendar day from the
 * durable hourly tables, write it as a single file for the Imunify agent to
 * pick up, cap the on-disk backlog, and prune the local tables.
 *
 * File layout mirrors the incident export (see IncidentRecorder): a
 * `<?php __halt_compiler();` guard line, then one record per line as
 * `#` + base64(wp_json_encode(record)). The first record is `meta`; each
 * remaining line is one `rollup` record per (category, bot) — humans included,
 * sharing the rollup schema so the agent parses every line the same way.
 *
 * Filename is `bot-stats/YYYY-MM-DD.php`, where the date is the exported
 * (previous) day. Unlike the incident export the whole day is written at once,
 * so this uses AtomicFileWriter::write() (temp file + rename) rather than an
 * incremental append.
 *
 * Every path is fail-open: aggregation or write errors are suppressed so the
 * site and dashboard are never affected, and each terminal failure is buffered
 * to Sentry via StorageEventBuffer. A failed hourly read aborts the run rather
 * than exporting the day as zero-traffic, so the rows survive for a retry.
 * The export is best-effort — it only ever
 * targets the immediately previous day and never retries a missed one, so a day
 * whose single run fails, or on which WP-Cron never fires, is not recovered and
 * is pruned by the next day's retention floor.
 *
 * @since 4.1.0
 */
class BotStatsExporter {

	/**
	 * Export directory relative to wp-content.
	 */
	const EXPORT_SUBDIR = 'imunify-security/bot-stats';

	/**
	 * Export record schema version, carried in the meta record.
	 */
	const SCHEMA_VERSION = 1;

	/**
	 * Maximum export files retained on disk. When a new file is written the
	 * oldest beyond this count are dropped — a backstop against an agent that
	 * never consumes.
	 */
	const MAX_FILES = 3;

	/**
	 * Age, by mtime, past which a file the agent renamed out of the export set
	 * is deleted — the agent's own TTL for `.stored` / `.failed`. A live agent
	 * only reaches a `.sending` aside this old after a month of failed sends, and
	 * by then it no longer stamps the day; losing that stale day is the worst a
	 * racing delete can cost, since the agent tolerates the file vanishing.
	 */
	const RETIRED_TTL = 30 * DAY_IN_SECONDS;

	/**
	 * Longest version string carried in the meta record. Bounds the record for a
	 * version that did not come from a release build — the plugin version is a
	 * constant in a file the site can edit — so one odd install cannot emit an
	 * outsized export line.
	 */
	const MAX_VERSION_LENGTH = 64;

	/**
	 * Absolute path to wp-content.
	 *
	 * @var string
	 */
	private $wpContentDir;

	/**
	 * Hourly rollup storage, or null when no DB handle is available.
	 *
	 * @var HourlyStatsStorage|null
	 */
	private $hourly;

	/**
	 * Per-IP hourly storage, or null when no DB handle is available.
	 *
	 * @var HourlyIpStatsStorage|null
	 */
	private $ipStats;

	/**
	 * Bind the exporter to wp-content and its storage collaborators.
	 *
	 * @param string                    $wp_content_dir Absolute path to wp-content.
	 * @param HourlyStatsStorage|null   $hourly         Rollup storage (nullable for fail-open / tests).
	 * @param HourlyIpStatsStorage|null $ip_stats       Per-IP storage (nullable for fail-open / tests).
	 */
	public function __construct( $wp_content_dir, $hourly, $ip_stats ) {
		$this->wpContentDir = (string) $wp_content_dir;
		$this->hourly       = $hourly;
		$this->ipStats      = $ip_stats;
	}

	/**
	 * Build the exporter over the global $wpdb. Returns null when no DB handle
	 * is available so the caller can no-op.
	 *
	 * @param string $wp_content_dir Absolute path to wp-content.
	 * @return self|null
	 */
	public static function forGlobalWpdb( $wp_content_dir ) {
		$hourly  = HourlyStatsStorage::forGlobalWpdb();
		$ipStats = HourlyIpStatsStorage::forGlobalWpdb();
		if ( null === $hourly || null === $ipStats ) {
			return null;
		}
		return new self( $wp_content_dir, $hourly, $ipStats );
	}

	/**
	 * Aggregate the previous full calendar day, write its export file, cap the
	 * backlog, and prune the local tables. Fail-open throughout.
	 *
	 * @param int|null $now Unix timestamp; defaults to time(). Injectable for tests.
	 * @return bool Whether an export file was written.
	 */
	public function export( $now = null ) {
		if ( null === $this->hourly || null === $this->ipStats ) {
			return false;
		}
		// Fail-open on both PHP 5.6 (Exception only) and PHP 7+ (Throwable), so a
		// storage or filesystem failure never surfaces to the request or cron.
		if ( interface_exists( 'Throwable' ) ) {
			try {
				return $this->doExport( $now );
			} catch ( \Throwable $t ) {
				$this->recordFailure( $t );
				return false;
			}
		}
		try {
			return $this->doExport( $now );
		} catch ( \Exception $e ) {
			$this->recordFailure( $e );
			return false;
		}
	}

	/**
	 * Buffer a Sentry event for a terminal export failure. The rest of the
	 * storage layer reports its structural failures the same way, so a
	 * permanently-failing export leaves a trace rather than silently dropping a
	 * day (the export is best-effort and never retries a missed day).
	 *
	 * @param \Throwable|\Exception $error Swallowed failure.
	 * @return void
	 */
	private function recordFailure( $error ) {
		StorageEventBuffer::record(
			'Bot stats export failed: ' . $error->getMessage(),
			'bot_export_exception',
			array( 'bot_stats_export_failed', get_class( $error ) )
		);
	}

	/**
	 * The export body, wrapped by {@see export()}'s fail-open guard.
	 *
	 * @param int|null $now Unix timestamp; defaults to time().
	 * @return bool Whether an export file was written.
	 */
	private function doExport( $now ) {
		$now = null === $now ? time() : (int) $now;

		$today_midnight = $now - ( $now % DAY_IN_SECONDS );
		$prev_day_start = $today_midnight - DAY_IN_SECONDS;
		$day            = gmdate( 'Y-m-d', $prev_day_start );
		$path           = $this->exportDir() . '/' . $day . '.php';

		// The written file is the idempotency marker: a second run the same UTC
		// day would re-read tables pruneLocal() has since trimmed and overwrite
		// the file with a short day, so bail once it exists.
		if ( is_file( $path ) ) {
			return true;
		}

		$first_bucket = HourlyStatsStorage::hourBucket( $prev_day_start );
		$last_bucket  = $first_bucket + 23;

		$hourly_rows = $this->hourly->fetchSince( $first_bucket );
		$ip_rows     = $this->ipStats->fetchSince( $first_bucket );

		// A failed read is null, an empty day is an empty array. Publishing the
		// former would assert zero traffic for a day that had some, so bail. The
		// day is not retried: the next run exports the day after it.
		if ( null === $hourly_rows || null === $ip_rows ) {
			StorageEventBuffer::record(
				'Bot stats export: hourly read failed, day not exported',
				'bot_export_read_failed',
				array( 'bot_stats_export_failed', 'read' ),
				array(
					'day'      => $day,
					'db_error' => null === $hourly_rows ? $this->hourly->lastError() : $this->ipStats->lastError(),
				)
			);
			return false;
		}

		$aggregator = new DailyBotAggregator( $hourly_rows, $ip_rows, $first_bucket, $last_bucket );
		$body       = $this->buildFileBody( $aggregator->rollups(), $day );

		if ( ! $this->ensureDirectory() ) {
			StorageEventBuffer::record(
				'Bot stats export: could not create or protect the export directory',
				'bot_export_dir_failed',
				array( 'bot_stats_export_failed', 'directory' ),
				array( 'dir' => $this->exportDir() )
			);
			return false;
		}

		$written = AtomicFileWriter::write( $path, $body, 0600 );
		if ( ! $written ) {
			StorageEventBuffer::record(
				'Bot stats export: atomic write failed',
				'bot_export_write_failed',
				array( 'bot_stats_export_failed', 'write' ),
				array( 'path' => $path )
			);
			return false;
		}

		$this->enforceBacklogCap();
		$this->pruneRetired( $now );
		$this->pruneLocal( $now );

		return true;
	}

	/**
	 * Serialise the export records into the on-disk file body: guard line, then
	 * the meta record, then one line per rollup, each `#` + base64(json).
	 *
	 * @param array  $rollups Rollup records from DailyBotAggregator::rollups().
	 * @param string $day     Exported day, gmdate('Y-m-d').
	 * @return string
	 */
	public function buildFileBody( $rollups, $day ) {
		// An unknown version is an empty string, never a missing key — the
		// agent-side parser relies on a stable record shape.
		$meta = array(
			'type'                  => 'meta',
			'day'                   => $day,
			'schema_version'        => self::SCHEMA_VERSION,
			'plugin_version'        => $this->boundedVersion( defined( 'IMUNIFY_SECURITY_VERSION' ) ? IMUNIFY_SECURITY_VERSION : '' ),
			'crawler_intel_version' => $this->boundedVersion( SignatureRefresher::intelVersion() ),
		);

		$body  = "<?php __halt_compiler();\n";
		$body .= $this->encodeRecord( $meta );
		foreach ( $rollups as $rollup ) {
			$body .= $this->encodeRecord( $rollup );
		}
		return $body;
	}

	/**
	 * A version string for the meta record, or '' when it exceeds
	 * MAX_VERSION_LENGTH. An over-long value is dropped rather than truncated —
	 * '' already means "unknown" to the consumer, while a shortened version would
	 * read as a real one and silently skew a split by version.
	 *
	 * @param string $version Raw version value.
	 * @return string
	 */
	private function boundedVersion( $version ) {
		$version = (string) $version;
		return strlen( $version ) <= self::MAX_VERSION_LENGTH ? $version : '';
	}

	/**
	 * Encode a single record as its on-disk line: `#` + base64(json) + newline.
	 * Returns an empty string when the record fails JSON encoding — wp_json_encode
	 * signals that by returning false rather than throwing, so the caller's
	 * fail-open guard would miss it and emit a bare `#` line otherwise.
	 *
	 * @param array $record Record to encode.
	 * @return string
	 */
	private function encodeRecord( $record ) {
		$json = wp_json_encode( $record );
		if ( false === $json ) {
			return '';
		}
		return '#' . base64_encode( $json ) . "\n";
	}

	/**
	 * Ensure the export directory exists and carries the same listing-protection
	 * trio as the incident export.
	 *
	 * @return bool
	 */
	private function ensureDirectory() {
		$dir = $this->exportDir();
		if ( ! is_dir( $dir ) && ! wp_mkdir_p( $dir ) ) {
			return false;
		}
		AtomicFileWriter::ensureDirectoryProtection( $dir );
		// Owner-only: the export holds per-site top-IP telemetry and the agent
		// reads it as root, so no group/other access is needed. Also repairs the
		// mode on a directory created by an older build.
		// @phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
		@chmod( $dir, 0700 );
		return true;
	}

	/**
	 * Drop the oldest export files beyond MAX_FILES. Only `YYYY-MM-DD.php` files
	 * are considered — the protection index.php / index.html are never counted
	 * or deleted.
	 *
	 * @return void
	 */
	private function enforceBacklogCap() {
		$files = glob( $this->exportDir() . '/*.php' );
		if ( ! is_array( $files ) ) {
			return;
		}
		$dated = array();
		foreach ( $files as $file ) {
			if ( preg_match( '/^\d{4}-\d{2}-\d{2}\.php$/', basename( $file ) ) ) {
				$dated[] = $file;
			}
		}
		if ( count( $dated ) <= self::MAX_FILES ) {
			return;
		}
		// Ascending by name — Y-m-d sorts chronologically — so the leading
		// slice is the oldest.
		sort( $dated );
		$excess = array_slice( $dated, 0, count( $dated ) - self::MAX_FILES );
		foreach ( $excess as $file ) {
			@unlink( $file );
		}
	}

	/**
	 * Delete files the agent renamed out of the export set — the in-flight
	 * `.sending.php` aside and the `.stored.php` / `.failed.php` retirements —
	 * once older than RETIRED_TTL. A live agent sweeps these itself; this covers
	 * a server where the agent is gone but the plugin keeps exporting.
	 *
	 * @param int $now Unix timestamp.
	 * @return void
	 */
	private function pruneRetired( $now ) {
		$files = glob( $this->exportDir() . '/*.php' );
		if ( ! is_array( $files ) ) {
			return;
		}
		foreach ( $files as $file ) {
			if ( ! preg_match( '/^\d{4}-\d{2}-\d{2}(?:\.sending(?:\.stored|\.failed)?|\.stored|\.failed)\.php$/', basename( $file ) ) ) {
				continue;
			}
			// mtime, as the agent's sweep uses: it restamps a file when retiring it.
			$mtime = @filemtime( $file );
			if ( false !== $mtime && $now - $mtime > self::RETIRED_TTL ) {
				@unlink( $file );
			}
		}
	}

	/**
	 * Prune the local hourly tables back to the tight 24h + current-hour window
	 * now that the previous day has been exported.
	 *
	 * @param int $now Unix timestamp.
	 * @return void
	 */
	private function pruneLocal( $now ) {
		$oldest_kept = HourlyStatsStorage::hourBucket( $now - BotLifecycle::STATS_RETENTION_SECONDS );
		$this->hourly->prune( $oldest_kept );
		$this->ipStats->prune( $oldest_kept );
		$this->ipStats->trim();
	}

	/**
	 * Absolute export directory path.
	 *
	 * @return string
	 */
	private function exportDir() {
		return rtrim( $this->wpContentDir, '/' ) . '/' . self::EXPORT_SUBDIR;
	}
}

Directory Contents

Dirs: 1 × Files: 77
Name Size Perms Modified Actions
data DIR
- drwxr-xr-x 2026-11-03 01:06:32
Edit Download
11.48 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
2.43 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.47 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.38 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
4.45 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.17 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
2.01 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
21.21 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
7.34 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
17.81 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
3.38 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
2.79 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
13.17 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
8.77 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
5.67 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
14.53 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
4.25 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.72 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
7.58 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.55 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
14.00 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.58 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
5.99 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
2.88 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.41 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.53 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
2.61 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
4.73 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
7.49 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
17.86 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
14.97 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.47 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
4.76 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
2.06 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
5.26 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
5.64 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
2.68 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
10.47 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
2.49 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
17.09 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
8.51 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
12.60 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
3.46 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
835 B lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.71 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
22.44 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
5.65 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
7.33 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
892 B lrw-r--r-- 2026-11-03 01:06:32
Edit Download
924 B lrw-r--r-- 2026-11-03 01:06:32
Edit Download
4.69 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
18.57 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
6.92 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
3.87 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
7.94 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
18.17 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
8.48 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.80 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
9.49 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
2.84 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
7.45 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.28 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
2.27 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
9.90 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
15.82 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
20.41 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
7.79 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
5.61 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.80 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
30.46 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
2.79 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
1.41 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
3.72 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
9.60 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
5.05 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
6.56 KB lrw-r--r-- 2026-11-03 01:06:32
Edit Download
5.16 KB lrw-r--r-- 2026-11-03 01:06:32
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