This commit is contained in:
2025-11-24 02:12:49 +01:00
parent 71b0a4c72a
commit b2584bc828
8 changed files with 656 additions and 0 deletions

40
api/index.php Normal file
View File

@@ -0,0 +1,40 @@
<?php
// api/index.php
// Optional: zentrale Config laden (wenn du magst)
// require __DIR__ . '/../config/fileload.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
// Pfad aus der URL holen, z.B. /quickcheck?...
$uri = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
$path = rtrim($uri, '/');
if ($path === '') {
$path = '/';
}
// Routing
switch ($path) {
case '/quickcheck':
require __DIR__ . '/target/quickcheck.php';
$result = quickcheck_handle_request(); // Funktion in quickcheck.php
echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
break;
default:
http_response_code(404);
echo json_encode([
'success' => false,
'error' => 'Unknown endpoint',
'path' => $path,
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
break;
}

9
api/target/.htaccess Normal file
View File

@@ -0,0 +1,9 @@
# api/target/.htaccess
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
</IfModule>

314
api/target/quickcheck.php Normal file
View File

@@ -0,0 +1,314 @@
<?php
// api/target/quickcheck.php
/**
* Diese Funktion wird von api/index.php aufgerufen.
* Sie liest die Eingaben, prüft Seriennummer + VID, und gibt ein Array zurück,
* das dann als JSON ausgegeben wird.
*/
function quickcheck_handle_request(): array
{
// JSON Body hat Priorität
$source = quickcheck_get_input();
$vid = isset($source['vid']) ? trim((string)$source['vid']) : '';
$pid = isset($source['pid']) ? trim((string)$source['pid']) : '';
$manufacturer = isset($source['manufacturer']) ? trim((string)$source['manufacturer']) : '';
$serial = isset($source['serial']) ? trim((string)$source['serial']) : '';
if ($serial === '') {
http_response_code(400);
return [
'success' => false,
'error' => 'Missing required parameter: serial',
];
}
// Mini-VID-Datenbank (kannst du später aus Datei/DB laden)
$VID_DB = [
'0781' => 'SanDisk Corp.',
'0951' => 'Kingston Technology',
'054C' => 'Sony Corp.',
'1B1C' => 'Corsair',
'13FE' => 'Phison Electronics',
'8564' => 'Transcend Information, Inc.',
'090C' => 'Silicon Motion, Inc.',
'174C' => 'ASMedia Technology',
'0BC2' => 'Seagate',
// ... nach Bedarf ergänzen
];
$vendorInfo = quickcheck_lookup_vendor($vid, $VID_DB);
$serialAnalysis = quickcheck_analyze_serial($serial);
$consistencyInfo = quickcheck_evaluate_consistency($vendorInfo['vendor'] ?? null, $manufacturer, $serialAnalysis);
// Gesamtrating
$rating = 'ok';
if ($serialAnalysis['category'] === 'invalid') {
$rating = 'invalid';
} elseif ($serialAnalysis['category'] === 'very_suspicious' || $consistencyInfo['manufacturer_match'] === 'mismatch') {
$rating = 'suspicious';
} elseif ($serialAnalysis['category'] === 'suspicious') {
$rating = 'needs_review';
}
return [
'success' => true,
'rating' => $rating,
'input' => [
'vid' => $vid,
'pid' => $pid,
'manufacturer' => $manufacturer,
'serial' => $serial,
],
'vendor_detected' => $vendorInfo,
'serial_analysis' => $serialAnalysis,
'consistency' => $consistencyInfo,
'messages' => [
'de' => [
'Hinweis: Diese Prüfung kann keine Echtheit garantieren, sondern bewertet nur Plausibilität und Auffälligkeiten.',
],
],
];
}
/**
* Eingaben lesen: JSON-Body > POST > GET
*/
function quickcheck_get_input(): array
{
$contentType = $_SERVER['CONTENT_TYPE'] ?? $_SERVER['HTTP_CONTENT_TYPE'] ?? '';
$contentType = strtolower(trim(explode(';', $contentType)[0]));
if ($contentType === 'application/json') {
$raw = file_get_contents('php://input');
if ($raw !== false && $raw !== '') {
$data = json_decode($raw, true);
if (json_last_error() === JSON_ERROR_NONE && is_array($data)) {
return $data;
}
}
}
if (!empty($_POST)) {
return $_POST;
}
if (!empty($_GET)) {
return $_GET;
}
return [];
}
/**
* VID normalisieren + Lookup
*/
function quickcheck_normalize_vid(string $vid): ?string
{
$vid = strtoupper(trim($vid));
$vid = preg_replace('/^0X/i', '', $vid);
if ($vid === '' || !preg_match('/^[0-9A-F]{1,4}$/', $vid)) {
return null;
}
return str_pad($vid, 4, '0', STR_PAD_LEFT);
}
function quickcheck_lookup_vendor(?string $vid, array $VID_DB): array
{
if (!$vid) {
return [
'vid' => null,
'found' => false,
'vendor' => null,
'confidence' => 0,
];
}
$norm = quickcheck_normalize_vid($vid);
if (!$norm) {
return [
'vid' => $vid,
'found' => false,
'vendor' => null,
'confidence' => 0,
'issue' => 'Invalid VID format',
];
}
if (isset($VID_DB[$norm])) {
return [
'vid' => $norm,
'found' => true,
'vendor' => $VID_DB[$norm],
'confidence' => 1.0,
];
}
return [
'vid' => $norm,
'found' => false,
'vendor' => null,
'confidence' => 0.2,
];
}
/**
* Seriennummer grob analysieren (Plausibilität)
*/
function quickcheck_analyze_serial(string $serial): array
{
$serial = trim($serial);
$length = strlen($serial);
$issues = [];
$score = 100;
if ($length === 0) {
return [
'serial' => $serial,
'length' => 0,
'issues' => ['empty'],
'score' => 0,
'category' => 'invalid',
];
}
if ($length < 4) {
$issues[] = 'too_short_critical';
$score -= 60;
} elseif ($length < 8) {
$issues[] = 'short_suspicious';
$score -= 30;
}
if ($length > 32) {
$issues[] = 'very_long';
$score -= 10;
}
if (quickcheck_is_all_same_char($serial)) {
$issues[] = 'all_same_char';
$score -= 50;
}
$simplePatterns = [
'000000', '00000000', '000000000000',
'111111', '123456', '12345678', 'ABCDEF', 'AABBCC'
];
if (in_array(strtoupper($serial), $simplePatterns, true)) {
$issues[] = 'simple_pattern';
$score -= 40;
}
if (quickcheck_is_simple_sequence($serial)) {
$issues[] = 'sequence_pattern';
$score -= 25;
}
$isNumeric = preg_match('/^[0-9]+$/', $serial) === 1;
$isAlpha = preg_match('/^[A-Za-z]+$/', $serial) === 1;
$isHex = preg_match('/^[0-9A-Fa-f]+$/', $serial) === 1;
$isAlnum = preg_match('/^[A-Za-z0-9]+$/', $serial) === 1;
if ($isNumeric) {
$issues[] = 'numeric_only';
$score -= 10;
} elseif ($isAlpha) {
$issues[] = 'letters_only';
$score -= 10;
}
if ($isHex && !$isNumeric && $length >= 8 && $length <= 24) {
$issues[] = 'hex_pattern_plausible';
$score += 5;
}
if ($isAlnum && !$isNumeric && !$isAlpha && $length >= 8) {
$issues[] = 'alnum_mixed_plausible';
$score += 5;
}
if ($score > 100) $score = 100;
if ($score < 0) $score = 0;
if ($length === 0) {
$category = 'invalid';
} elseif ($score >= 80) {
$category = 'plausible';
} elseif ($score >= 50) {
$category = 'suspicious';
} else {
$category = 'very_suspicious';
}
return [
'serial' => $serial,
'length' => $length,
'issues' => array_values(array_unique($issues)),
'score' => $score,
'category' => $category,
];
}
function quickcheck_is_all_same_char(string $s): bool
{
return strlen($s) > 1 && preg_match('/^(.)\1+$/', $s) === 1;
}
function quickcheck_is_simple_sequence(string $s): bool
{
$seqs = [
'123456', '1234567', '12345678', '234567', '345678',
'ABCDEFG', 'ABCDEF', 'ABCDE'
];
$ls = strtoupper($s);
foreach ($seqs as $pattern) {
if (strpos($ls, $ls) !== false && strpos($ls, $pattern) !== false) {
return true;
}
}
return false;
}
/**
* Herstellerangabe vs. Vendor-Name bewerten
*/
function quickcheck_evaluate_consistency(?string $vendorName, string $userManufacturer, array $serialAnalysis): array
{
$vendorName = $vendorName ? trim($vendorName) : '';
$userManufacturer = trim($userManufacturer);
$matchStatus = 'unknown';
$notes = [];
if ($vendorName !== '' && $userManufacturer !== '') {
$v = mb_strtolower($vendorName);
$u = mb_strtolower($userManufacturer);
if (strpos($v, $u) !== false || strpos($u, $v) !== false) {
$matchStatus = 'match';
$notes[] = 'Herstellerangabe passt zur ermittelten Vendor-ID.';
} else {
$matchStatus = 'mismatch';
$notes[] = 'Herstellerangabe weicht von der Vendor-ID ab.';
}
} elseif ($vendorName !== '') {
$notes[] = 'Hersteller über Vendor-ID bekannt, aber keine Herstellerangabe des Nutzers.';
} elseif ($userManufacturer !== '') {
$notes[] = 'Hersteller vom Nutzer angegeben, aber keine oder unbekannte Vendor-ID.';
} else {
$notes[] = 'Keine Herstellerinformationen vorhanden.';
}
$ratingHint = 'neutral';
if ($serialAnalysis['category'] === 'very_suspicious' || $matchStatus === 'mismatch') {
$ratingHint = 'suspicious';
} elseif ($serialAnalysis['category'] === 'plausible' && $matchStatus === 'match') {
$ratingHint = 'good';
}
return [
'manufacturer_match' => $matchStatus,
'notes' => $notes,
'consistency_hint' => $ratingHint,
];
}