77 lines
3.1 KiB
PHP
77 lines
3.1 KiB
PHP
<?php
|
|
/**
|
|
* File: SubmissionCheck.php
|
|
* Version: 1.3
|
|
* Purpose: Helper to detect and block repeated or abusive contact form submissions
|
|
* Project: Wizdom Networks Website
|
|
*/
|
|
|
|
namespace WizdomNetworks\WizeWeb\Utilities;
|
|
|
|
use PDO;
|
|
use WizdomNetworks\WizeWeb\Utilities\Logger;
|
|
|
|
class SubmissionCheck
|
|
{
|
|
private const LOOKBACK_DAYS = 30;
|
|
|
|
/**
|
|
* Evaluates whether a submission is likely spam or abuse.
|
|
*
|
|
* @param PDO $pdo
|
|
* @param string $email
|
|
* @param string|null $phone
|
|
* @param string|null $ip
|
|
* @return array [action: accept|flag|block|notify, reason: string, count: int]
|
|
*/
|
|
public static function evaluate(PDO $pdo, string $email, ?string $phone, ?string $ip): array
|
|
{
|
|
try {
|
|
// MySQL cannot bind inside INTERVAL, so we inject LOOKBACK_DAYS directly
|
|
$lookback = (int) self::LOOKBACK_DAYS;
|
|
|
|
$query = "
|
|
SELECT
|
|
(SELECT COUNT(*) FROM submission_logs WHERE email = :email AND created_at >= NOW() - INTERVAL $lookback DAY) AS email_hits,
|
|
(SELECT COUNT(*) FROM submission_logs WHERE phone = :phone AND created_at >= NOW() - INTERVAL $lookback DAY) AS phone_hits,
|
|
(SELECT COUNT(*) FROM submission_logs WHERE ip_address = :ip1 AND created_at >= NOW() - INTERVAL $lookback DAY) AS ip_hits,
|
|
(SELECT COUNT(*) FROM submission_logs WHERE ip_address = :ip2 AND created_at >= NOW() - INTERVAL 1 HOUR) AS ip_hourly
|
|
";
|
|
|
|
$stmt = $pdo->prepare($query);
|
|
$stmt->bindValue(':email', $email);
|
|
$stmt->bindValue(':phone', $phone);
|
|
$stmt->bindValue(':ip1', $ip);
|
|
$stmt->bindValue(':ip2', $ip);
|
|
$stmt->execute();
|
|
$data = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
$emailHits = (int)($data['email_hits'] ?? 0);
|
|
$phoneHits = (int)($data['phone_hits'] ?? 0);
|
|
$ipHits = (int)($data['ip_hits'] ?? 0);
|
|
$ipHourly = (int)($data['ip_hourly'] ?? 0);
|
|
|
|
$totalScore = $emailHits + $phoneHits + $ipHits;
|
|
|
|
if ($emailHits >= 4 || $phoneHits >= 4 || $ipHits >= 5) {
|
|
return ['action' => 'block', 'reason' => 'IP/email/phone threshold exceeded', 'count' => $totalScore];
|
|
}
|
|
if ($ipHourly >= 3) {
|
|
return ['action' => 'flag', 'reason' => 'Multiple submissions from IP in last hour', 'count' => $ipHourly];
|
|
}
|
|
if ($totalScore >= 6) {
|
|
return ['action' => 'notify', 'reason' => 'Cumulative signal from all identifiers', 'count' => $totalScore];
|
|
}
|
|
if ($emailHits >= 2 || $phoneHits >= 2 || $ipHits >= 2) {
|
|
return ['action' => 'flag', 'reason' => 'Repeated pattern detected', 'count' => $totalScore];
|
|
}
|
|
|
|
return ['action' => 'accept', 'reason' => 'accepted', 'count' => $totalScore];
|
|
|
|
} catch (\Throwable $e) {
|
|
Logger::error("SubmissionCheck evaluation failed: " . $e->getMessage());
|
|
return ['action' => 'error', 'reason' => 'Evaluation error', 'count' => 0];
|
|
}
|
|
}
|
|
}
|