<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
// BotBanish 8.0.00
// Randem Systems: https://randemsystems.support
// BotBanish Common File Subroutines
// Date: 06/19/2026
// Usage:
//
///////////////////////////////////////////////////////////////////////////////////////////////////////

function BotBanishReadFile($filename, $bylines = false) {

	global $BotBanishText;

	$data = '';

	if (file_exists($filename) && (filesize($filename) > 0)) {

		if ($bylines)

			$data = file($filename);
		else
			$data = file_get_contents($filename);

	} else {

		echo $filename . $BotBanishText['BotBanish_NotFound'];
	}

	return $data;
}

function BotBanishWriteFile($filename, $data, $append = false, $bylines = false) {

	if (empty($filename)) {

		BotBanishLogError('BotBanishWriteFile() - No filename present', '', 'Error');
		return;
	}

	if (empty($data)) {

		BotBanishLogError('BotBanishWriteFile() - No data present', '', 'Error');
		return;
	}

	$folder = dirname($filename) . '/';
	if (!is_dir($folder)) @mkdir ($folder, 0755, true);

	if (!$bylines) {

		$str = BotBanish_EncodeToUtf8($data);

	} else {

		$str = '';

		foreach ($data as $line)
			$str .= BotBanish_EncodeToUtf8($line);
	}

	if (!file_exists($filename)) $append = false;

	if ($append)

		$bytes = file_put_contents($filename, $str, FILE_APPEND);
	else
		$bytes = file_put_contents($filename, $str);
}

function BotBanishModifyFile($filename, $items) {

	global $BotBanishText;

	$data = BotBanishReadFile($filename);

	if (empty($data))
		return;

	foreach ($items as $item)
		BotBanishModData($data, $item);		// Data is changed in place

	BotBanishWriteFile($filename, $data);

	$data = '';
	$output = '';
}

function BotBanishUnModifyFile($filename) {

	global $BotBanishSettings;

	$items = array(
		array(
			'type' => 'rules',
			'rule' => array('rule_start' => $BotBanishSettings['BOTBANISH_CODE_START'], 'rule_end' => $BotBanishSettings['BOTBANISH_CODE_END']),
		)
	);

	BotBanishUnModifyRuleBlocks($filename, $items);
}

function BotBanishRemoveFileData($data, $filename) {

	$source = BotBanishReadFile($filename);

	if (empty($data))
		return;

	str_replace($data, '', $source);
	BotBanishWriteFile($filename, $source);
}

function BotBanishCheckFileExists($url) {

    $curl = curl_init();
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, 0);
	curl_setopt($curl, CURLOPT_URL, $url);
	curl_setopt($curl, CURLOPT_NOBODY, true);
	$result = curl_exec($curl);
	$ret = false;

    if ($result !== false) {
        //if request was ok, check response code
        $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);

        if ($statusCode == 200)
            $ret = true;
    }

    curl_close($curl);
	return $ret;
}

function BotBanishCompressFolders($selections, $zipfile = 'BotBanish_Backup') {

/////////////////////////////////////////////////////////////////////////////////////
//
// Usage: This routine can place individual files as well as complete folders into a
//			compressed zip file. A date/time stamp will be appended to each filename.
//			do not include the file extension in the call, 'zip' will automatically
//			be appended to the filename.
//
//	$selections = array(
//		$_SERVER['DOCUMENT_ROOT'] . '/smf_2.1rc2/Sources',
//		$_SERVER['DOCUMENT_ROOT'] . '/smf_2.1rc2/Themes',
//		$_SERVER['DOCUMENT_ROOT'] . '/smf_2.1rc2/index.php'
//	);
//
//	BotBanishCompressFolders($selections, 'BotBanish_PreBackup');
/////////////////////////////////////////////////////////////////////////////////////

	if (empty($selections))
		return;

	global $BotBanishSettings;

	// Name the zip file

	$zipfile = $BotBanishSettings['BOTBANISH_STATIC_BACKUPS_DIR'] . $zipfile . '_' . BotBanishGetTimeExtension() . '.zip';

	clearstatcache();

	$dir = $BotBanishSettings['BOTBANISH_STATIC_BACKUPS_DIR'];

	if (!is_dir($dir))
		@mkdir($dir);

	// Initialize archive object
	// Utilize PHP ZipArchive object if it is installed
	// otherwise use a programmed class object to compress the files

	if (function_exists('ZipArchive'))
		ZipArchiveIt($selections, $zipfile);
/*
	} else {

		if (function_exists('zip_add'))
			ZipIt($selections, $zipfile);
	}
*/
}

function BotBanishDecompressFolders($selections, $zipfile = 'BotBanish_Backup') {

/////////////////////////////////////////////////////////////////////////////////////
//
// Usage: This routine can place individual files as well as complete folders into a
//			compressed zip file. A date/time stamp will be appended to each filename.
//			do not include the file extension in the call, 'zip' will automatically
//			be appended to the filename.
//
//	$selections = array(
//		$_SERVER['DOCUMENT_ROOT'] . '/smf_2.1rc2/Sources',
//		$_SERVER['DOCUMENT_ROOT'] . '/smf_2.1rc2/Themes',
//		$_SERVER['DOCUMENT_ROOT'] . '/smf_2.1rc2/index.php'
//	);
//
//	BotBanishCompressFolders($selections, 'BotBanish_PreBackup');
/////////////////////////////////////////////////////////////////////////////////////

	if (empty($selections))
		return;

	global $BotBanishSettings;

	// Name the zip file

	$zipfile = $BotBanishSettings['BOTBANISH_STATIC_BACKUPS_DIR'] . $zipfile . '_' . BotBanishGetTimeExtension() . '.zip';

	clearstatcache();

	$dir = $BotBanishSettings['BOTBANISH_STATIC_BACKUPS_DIR'];

	if (!is_dir($dir))
		@mkdir($dir);

	// Initialize archive object
	// Utilize PHP ZipArchive object if it is installed
	// otherwise use a programmed class object to compress the files

	if (function_exists('ZipArchive'))
		UnZipArchiveIt($selections, $zipfile);

/*	} else {

		if (function_exists('zip_'))
			UnZipIt($selections, $zipfile);
	}
*/
}

function ZipArchiveIt($selections, $zipfile) {

	$zip = new ZipArchive();
	$zip->open($zipfile, ZipArchive::CREATE | ZipArchive::OVERWRITE);

	foreach ($selections as $selection) {

		// Get real path for our folder
		$absPath = str_ireplace('\\', '/', realpath($selection));
		$rootPath = substr($absPath, 0, strrpos($absPath, '/') + 1);

		if (is_dir($selection)) {

			// Create recursive directory iterator
			// @var SplFileInfo[] $files //
			$files = new RecursiveIteratorIterator(
				new RecursiveDirectoryIterator($absPath),
				RecursiveIteratorIterator::SELF_FIRST
			);

			foreach ($files as $name => $file)
			{
				if ($file->isDir())
				{
					$filename = $file->getFileName();

					if (($filename !== '.') && ($filename !== '..')) {

						// Get real and relative path for current file
						$filePath = str_ireplace('\\', '/', $file->getPathName());
						$relativePath = str_ireplace($rootPath, '', $filePath);

						$zip->addGlob($filePath . '/*.*', GLOB_BRACE, array("add_path" => $relativePath . '/', "remove_all_path" => true));
					}
				}
			}

		} else {

			// Get real and relative path for current file
			// Add current file to archive
			$filename = str_ireplace('\\', '/', $selection);
			$relativePath = str_ireplace($rootPath, '', $filename);

			$zip->addFile($filename, $relativePath);
		}
	}

	// Zip archive will be created only after closing object
	$zip->close();
}
/*
function ZipIt($selections, $zipfile) {

/////////////////////////////////////////////////////////////////////////////////////
//	$zip->zip_add("path/to/example.png"); // adding a file
//	$zip->zip_add(array("path/to/example1.png","path/to/example2.png")); // adding two files as an array
//	$zip->zip_add(array("path/to/example1.png","path/to/directory/")); // adding one file and one directory
//	$zip->zip_end();
/////////////////////////////////////////////////////////////////////////////////////

	$zip = new Zip();
	$zip->zip_start($zipfile);
	$zip->zip_add($selections);

	// Zip archive will be created only after closing object
	$zip->zip_end();
}

function UnZipIt($selections, $zipfile) {

/////////////////////////////////////////////////////////////////////////////////////
//	$zip->zip_add("path/to/example.png"); // adding a file
//	$zip->zip_add(array("path/to/example1.png","path/to/example2.png")); // adding two files as an array
//	$zip->zip_add(array("path/to/example1.png","path/to/directory/")); // adding one file and one directory
//	$zip->zip_end();
/////////////////////////////////////////////////////////////////////////////////////

	$zip = new Zip();
	$zip->zip_start($zipfile);
	$zip->zip_add($selections);

	// Zip archive will be created only after closing object
	$zip->zip_end();
}
*/
function ZipUnArchiveIt($source, $destination = '') {

	// Define the source file and target destination folder

	$zipFile = realpath(str_ireplace('\\', '/', $source));

	if (!file_exists($zipFile))
		return;
	
	if (empty($destination))
		$destination = dirname($zipfile);
	
	if (!is_dir($destination))
		mkdir($destination);
	
	// Create an instance of ZipArchive
	$zip = new ZipArchive;

	// Open the archive file
	if ($zip->open($zipFile) === true) {
		
		// Extract the complete archive content to the destination path
		$zip->extractTo($destination);
		
		// Always close the archive to free system resources
		$zip->close();
		
		$flag = true;
		
	} else {
		
		echo $flag = false;
	}
	
	return $flag;
}

function BotBanishModifyHTMLFiles($records = array()) {

	global $BotBanishSettings, $context, $BotBanishText;

	if (empty($records)) {

		$records = array(
			'updated' => 0,
			'filecount' => 0,
			'ip' => '',
			'bot' => '',
			'files' => array(),
		);
	}

	if (!$BotBanishSettings['BOTBANISH_UPDATE_HTML_ACTIVE']) {

		return $records;

	} else {

		if (defined('SMF')) {

			$context['BotBanishMsg'] = $BotBanishText['BotBanishModifyHTMLInComplete'];
			return $records;
		}
	}

	$Website_Code = PHP_EOL . $BotBanishSettings['BOTBANISH_HIDDEN_HONEYPOT_LINK'] . PHP_EOL;

	if (isset($BotBanishSettings['BOTBANISH_ANALYTICS_WEBSITE']) && ($BotBanishSettings['BOTBANISH_ANALYTICS_WEBSITE']))
		$Website_Code .= PHP_EOL . $BotBanishSettings['BOTBANISH_ANALYTICS_HTML'] . PHP_EOL;

	$body_tag = '</body>';

	$path = rtrim($BotBanishSettings['BOTBANISH_UPDATE_HTML_FOLDER'], '/') . '/';

	if (stripos($path, $_SERVER['DOCUMENT_ROOT']) === false)
		$path = $_SERVER['DOCUMENT_ROOT'] . '/' . $path;

    $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));

    foreach ($rii as $file) {

        if (!$file->isDir()) {

            $htmlfile = $file->getPathname();
			$len = strlen($htmlfile);
			$found = false;

			// Check for either type of HTML files extensions

			if ((stripos($htmlfile, '.html') === ($len - 5)) ||	(stripos($htmlfile, '.htm') === ($len - 4)))
				$found = true;

			if ($found) {

				$data = file_get_contents($htmlfile);
				$pos = stripos($data, $body_tag);

				if ($pos !== false) {

					$data = substr($data, 0, $pos - 1) . PHP_EOL . '<br><!-- ' . $BotBanishSettings['BOTBANISH_CODE_START'] . ' --><br>' . $Website_Code . '<br><!-- ' . $BotBanishSettings['BOTBANISH_CODE_END'] . ' --><br>' . PHP_EOL . substr($data, $pos);
					BotBanishWriteFile($htmlfile, $data);
					$records['updated']++;
					$records['files'][] = str_ireplace(array('\\', $_SERVER['DOCUMENT_ROOT']) , array('/', '') , $htmlfile);
				}

				$records['filecount']++;
			}
		}
	}

	if ($records['updated'] > 0) {

		BotBanishSettingsTablePutValues(array('BOTBANISH_UPDATE_HTML_ACTIVE' => 1));
		BotBanishWriteFile($BotBanishSettings['BOTBANISH_STATIC_LOGS_DIR'] . 'BotBanish_htmlfiles_modified.log', BotBanishGrabDump($records['files']));
	}

	if (defined('SMF')) {

		$str = $records['updated'] > 0 ? '<br>' . BotBanishGrabArray($records['files']) : '';;
		$context['BotBanishRows'] = $records['updated'] + 3;
		$context['BotBanishMsg'] = sprintf($BotBanishText['BotBanishModifyHTMLComplete'], $records['filecount'], $records['updated']) . $str;
		BotBanishUpdatePrettyURLs();
	}

	return $records;
}

function BotBanishUnModifyHTMLFiles($records = array(), $write_log = true) {

	global $BotBanishSettings, $context, $BotBanishText;

	if (empty($records)) {

		$records = array(
			'updated' => 0,
			'filecount' => 0,
			'ip' => '',
			'bot' => '',
			'files' => array(),
		);
	}

	if (!$BotBanishSettings['BOTBANISH_UPDATE_HTML_ACTIVE']) {

		return $records;

	} else {

		if (defined('SMF')) {

			$context['BotBanishMsg'] = $BotBanishText['BotBanishUnModifyHTMLInComplete'];
			return $records;
		}
	}

	$code_start = '<br><!-- ' . $BotBanishSettings['BOTBANISH_CODE_START'] . ' --><br>';
	$code_end = '<br><!-- ' . $BotBanishSettings['BOTBANISH_CODE_END'] . ' --><br>';
	$code_end_lth = strlen($code_end);

	$path = rtrim($BotBanishSettings['BOTBANISH_UPDATE_HTML_FOLDER'], '/') . '/';

	if (stripos($path, $_SERVER['DOCUMENT_ROOT']) === false)
		$path = $_SERVER['DOCUMENT_ROOT'] . '/' . $path;

	$rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));

    foreach ($rii as $file) {

        if (!$file->isDir()) {

            $htmlfile = $file->getPathname();
			$len = strlen($htmlfile);
			$found = false;

			// Check for either type of HTML files extensions

			if ((stripos($htmlfile, '.html') === ($len - 5)) ||	(stripos($htmlfile, '.htm') === ($len - 4)))
				$found = true;

			if ($found) {

				$data = file_get_contents($htmlfile);
				$found = false;

				// Remove all code placed into HTML files. Sometimes a failure can place code into files multiple times.
				// We need to remove all previous instances of our code!!!

				$records['filecount']++;

				while (true) {

					$pos_start = stripos($data, $code_start);
					$pos_end = stripos($data, $code_end);

					if (($pos_start !== false) && ($pos_end !== false)) {

						$data = substr($data, 0, $pos_start - 1) . substr($data, $pos_end + $code_end_lth);
						$found = true;

					} else {

						if ($found) {

							BotBanishWriteFile($htmlfile, $data);
							$records['updated']++;
							$records['files'][] = str_ireplace(array('\\', $_SERVER['DOCUMENT_ROOT']) , array('/', '') , $htmlfile);
						}

						break;
					}
				}
			}
		}
	}

	if ($records['updated'] > 0) {

		BotBanishSettingsTablePutValues(array('BOTBANISH_UPDATE_HTML_ACTIVE' => 0));

		// Do not write the log if we are uninstalling. The folder will be deleted or has already been deleted

		if ($write_log == true)
			BotBanishWriteFile($BotBanishSettings['BOTBANISH_STATIC_LOGS_DIR'] . 'BotBanish_htmlfiles_unmodified.log', BotBanishGrabDump($records['files']));
	}

	if (defined('SMF')) {

		$str = $records['updated'] > 0 ? '<br>' . BotBanishGrabArray($records['files']) : '';
		$context['BotBanishRows'] = $records['updated'] + 3;
		$context['BotBanishMsg'] = sprintf($BotBanishText['BotBanishUnModifyHTMLComplete'], $records['filecount'], $records['updated']) . $str;
		BotBanishUpdatePrettyURLs();
	}

	return $records;
}
?>