"SECRET_EXAMPLE"]); } // === Security settings === // Block duration in seconds (48 hours by default) if (!defined('BLOCK_DURATION_SECONDS')) { define('BLOCK_DURATION_SECONDS', 48 * 3600); // Duration of IP block after failures } } else { // If the file was accessed directly, deny access error_deny(); } /** * Sends a standard 403 Forbidden HTTP response with an HTML message * and terminates the script. */ function error_deny() : void { // Set HTTP response status code to 403 http_response_code(403); // Explicitly send HTTP headers for 403 Forbidden and HTML content type header('HTTP/1.1 403 Forbidden'); header('Content-Type: text/html; charset=utf-8'); // Output a simple HTML page explaining the forbidden access echo "\n"; echo "\n"; echo "403 Forbidden\n"; echo "\n"; echo "\n"; echo "

Forbidden

\n"; echo "You do not have permission to access this document.\n"; echo "

\n"; echo "


\n"; echo "
\n"; echo "Web Server at " . $_SERVER['SERVER_NAME'] . "\n"; echo "
\n"; echo "\n"; echo "\n"; // Exit the script with status code 403 exit(403); } /** * Retrieves a parameter from the request (POST takes precedence over GET). * If the parameter is not found in either, returns the provided default value. * * @param string $name The name of the parameter to retrieve * @param mixed $def The default value to return if parameter is not found * @return mixed The value of the parameter or the default value */ function getQuery(string $name, mixed $def): mixed { $val = $_POST[$name] ?? null; if ($val === null) { $val = $_GET[$name] ?? $def; } return $val; } /** * Checks if a given value is considered "empty". * - Returns true for null, empty strings, empty arrays, 0, "0", etc. (like PHP's `empty()`) * - Additionally, for strings, also trims whitespace before checking emptiness * * @param mixed $val The value to evaluate * @return bool True if the value is empty or whitespace-only, false otherwise */ function isEmpty(mixed $val): bool { // Handle typical empty values (null, "", 0, [], false, etc.) if (empty($val)) { return true; } // If it's a string, trim and check again if (is_string($val)) { if (trim($val) === '') { return true; } } return false; } /** * Loads and parses a JSON file into an associative array. * * Checks if the file exists and is readable before attempting to decode it. * If the JSON is invalid, an error message is printed. * If decoding fails or the result is not an array, an empty array is returned. * * @param string $filename Path to the JSON file * @return array Parsed associative array or empty array on error */ function loadJson(string $filename): array { $result = []; // Attempt to read and decode the file if it exists and is readable if (file_exists($filename) && is_readable($filename)) { $result = json_decode(file_get_contents($filename), true); // Log an error if JSON is invalid if (json_last_error() !== JSON_ERROR_NONE) { echo "Invalid JSON in $filename: " . json_last_error_msg() . "\n"; } } // Ensure the result is an array if (!is_array($result)) { $result = []; } return $result; } /** * Saves a PHP array to a JSON file in pretty format. * * - Ensures the target file is writable if it already exists. * - Automatically replaces null or empty input with an empty array. * - Returns true on success, false on any failure. * * @param string $filename The path to the JSON file to write * @param array|null $val The data to save (null or empty → []) * @return bool True if saved successfully, false otherwise */ function saveJson(string $filename, ?array $val): bool { // If file exists, check for write permissions if (file_exists($filename)) { if (!is_writable($filename)) { echo "No access to write in $filename\n"; return false; } } // Default to empty array if null or empty if (isEmpty($val)) { $val = []; } // Encode to JSON $encoded = json_encode($val, JSON_PRETTY_PRINT); if ($encoded === false) { echo "Failed to encode $filename: " . json_last_error_msg() . "\n"; return false; } // Save to file if (file_put_contents($filename, $encoded) === false) { echo "Failed to write to $filename\n"; return false; } return true; }