mirror of
https://github.com/djav1985/v-wordpress-plugin-updater.git
synced 2025-08-17 18:11:17 +08:00
modified: .gitignore modified: LICENSE modified: README.md modified: update-api/classes/HomeHelper.php modified: update-api/classes/LogsHelper.php modified: update-api/classes/PlHelper.php modified: update-api/classes/ThHelper.php renamed: update-api/classes/SecurityHandler.php -> update-api/classes/UtilityHandler.php modified: update-api/config.php modified: update-api/lib/auth-lib.php modified: update-api/lib/load-lib.php modified: update-api/public/.htaccess modified: update-api/public/api.php modified: update-api/public/assets/css/styles.css modified: update-api/public/assets/js/header-scripts.js modified: update-api/public/index.php modified: update-api/public/login.php modified: update-api/public/robots.txt
171 lines
5.1 KiB
PHP
171 lines
5.1 KiB
PHP
<?php
|
|
|
|
// @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
|
|
|
/*
|
|
* Project: Update API
|
|
* Author: Vontainment
|
|
* URL: https://vontainment.com
|
|
* File: UtilityHandler.php
|
|
* Description: Security utilities (moved from waf-lib.php)
|
|
*/
|
|
|
|
|
|
class UtilityHandler
|
|
{
|
|
/**
|
|
* Validate a domain string
|
|
*/
|
|
public static function validateDomain(string $domain): ?string
|
|
{
|
|
$domain = strtolower(trim($domain));
|
|
return filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) ? $domain : null;
|
|
}
|
|
|
|
/**
|
|
* Validate an API key or generic token
|
|
*/
|
|
public static function validateKey(string $key): ?string
|
|
{
|
|
$key = trim($key);
|
|
return preg_match('/^[A-Za-z0-9_-]+$/', $key) ? $key : null;
|
|
}
|
|
|
|
/**
|
|
* Validate plugin or theme names and slugs
|
|
*/
|
|
public static function validateSlug(string $slug): ?string
|
|
{
|
|
$slug = basename(trim($slug));
|
|
return preg_match('/^[A-Za-z0-9._-]+$/', $slug) ? $slug : null;
|
|
}
|
|
|
|
/**
|
|
* Validate uploaded file names
|
|
*/
|
|
public static function validateFilename(string $filename): ?string
|
|
{
|
|
$filename = basename(trim($filename));
|
|
return preg_match('/^[A-Za-z0-9._-]+$/', $filename) ? $filename : null;
|
|
}
|
|
|
|
/**
|
|
* Validate a version number such as 1.0.0
|
|
*/
|
|
public static function validateVersion(string $version): ?string
|
|
{
|
|
$version = trim($version);
|
|
return preg_match('/^\d+(?:\.\d+)*$/', $version) ? $version : null;
|
|
}
|
|
|
|
/**
|
|
* Validate usernames for the admin interface
|
|
*/
|
|
public static function validateUsername(string $username): ?string
|
|
{
|
|
$username = trim($username);
|
|
return preg_match('/^[A-Za-z0-9._-]{3,30}$/', $username) ? $username : null;
|
|
}
|
|
|
|
/**
|
|
* Basic password validation
|
|
*/
|
|
public static function validatePassword(string $password): ?string
|
|
{
|
|
$password = trim($password);
|
|
return strlen($password) >= 6 ? $password : null;
|
|
}
|
|
|
|
/**
|
|
* Update the number of failed login attempts for an IP address and blacklist if necessary.
|
|
* Handles file errors and uses file locking for concurrency.
|
|
*
|
|
* @param string $ip
|
|
* @return void
|
|
*/
|
|
public static function updateFailedAttempts(string $ip): void
|
|
{
|
|
$blacklist_file = BLACKLIST_DIR . "/BLACKLIST.json";
|
|
$content = [];
|
|
if (file_exists($blacklist_file)) {
|
|
$raw = @file_get_contents($blacklist_file);
|
|
if ($raw !== false) {
|
|
$json = json_decode($raw, true);
|
|
if (is_array($json)) {
|
|
$content = $json;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isset($content[$ip])) {
|
|
$content[$ip]['login_attempts'] += 1;
|
|
if ($content[$ip]['login_attempts'] >= 3) {
|
|
$content[$ip]['blacklisted'] = true;
|
|
$content[$ip]['timestamp'] = time();
|
|
}
|
|
} else {
|
|
$content[$ip] = [
|
|
'login_attempts' => 1,
|
|
'blacklisted' => false,
|
|
'timestamp' => time(),
|
|
];
|
|
}
|
|
|
|
$fp = fopen($blacklist_file, 'c+');
|
|
if ($fp) {
|
|
if (flock($fp, LOCK_EX)) {
|
|
ftruncate($fp, 0);
|
|
rewind($fp);
|
|
fwrite($fp, json_encode($content));
|
|
fflush($fp);
|
|
flock($fp, LOCK_UN);
|
|
}
|
|
fclose($fp);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if an IP address is blacklisted. If the blacklist has expired, reset blacklist and login_attempts.
|
|
* Handles file errors and uses file locking for concurrency.
|
|
*
|
|
* @param string $ip
|
|
* @return bool
|
|
*/
|
|
public static function isBlacklisted(string $ip): bool
|
|
{
|
|
$blacklist_file = BLACKLIST_DIR . "/BLACKLIST.json";
|
|
$blacklist = [];
|
|
if (file_exists($blacklist_file)) {
|
|
$raw = @file_get_contents($blacklist_file);
|
|
if ($raw !== false) {
|
|
$json = json_decode($raw, true);
|
|
if (is_array($json)) {
|
|
$blacklist = $json;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isset($blacklist[$ip]) && $blacklist[$ip]['blacklisted']) {
|
|
// Check if the timestamp is older than three days
|
|
if (time() - $blacklist[$ip]['timestamp'] > (3 * 24 * 60 * 60)) {
|
|
// Remove the IP address from the blacklist and reset login_attempts
|
|
$blacklist[$ip]['blacklisted'] = false;
|
|
$blacklist[$ip]['login_attempts'] = 0;
|
|
$fp = fopen($blacklist_file, 'c+');
|
|
if ($fp) {
|
|
if (flock($fp, LOCK_EX)) {
|
|
ftruncate($fp, 0);
|
|
rewind($fp);
|
|
fwrite($fp, json_encode($blacklist));
|
|
fflush($fp);
|
|
flock($fp, LOCK_UN);
|
|
}
|
|
fclose($fp);
|
|
}
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|