- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
154 lines
5.0 KiB
PHP
154 lines
5.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
|
|
use App\Framework\QrCode\QrCodeGenerator;
|
|
use App\Framework\QrCode\ValueObjects\ErrorCorrectionLevel;
|
|
use App\Framework\QrCode\ValueObjects\QrCodeConfig;
|
|
use App\Framework\QrCode\ValueObjects\QrCodeVersion;
|
|
use App\Framework\QrCode\ValueObjects\EncodingMode;
|
|
use App\Framework\QrCode\Masking\MaskPattern;
|
|
use App\Framework\QrCode\Structure\FormatInformation;
|
|
|
|
echo "=== QR Code Unmask Debug ===\n\n";
|
|
|
|
$data = "HELLO";
|
|
$config = new QrCodeConfig(
|
|
version: QrCodeVersion::fromNumber(1),
|
|
errorCorrectionLevel: ErrorCorrectionLevel::M,
|
|
encodingMode: EncodingMode::BYTE
|
|
);
|
|
|
|
$matrix = QrCodeGenerator::generate($data, $config);
|
|
$size = $matrix->getSize();
|
|
|
|
echo "Generated QR Code for: '{$data}'\n";
|
|
echo "Matrix Size: {$size}x{$size}\n\n";
|
|
|
|
// Extract format information to determine mask pattern
|
|
echo "=== Format Information Analysis ===\n";
|
|
|
|
// Read format bits from horizontal position
|
|
$formatBitsHorizontal = '';
|
|
for ($col = 0; $col < 9; $col++) {
|
|
if ($col === 6) continue; // Skip timing column
|
|
$formatBitsHorizontal .= $matrix->getModuleAt(8, $col)->isDark() ? '1' : '0';
|
|
}
|
|
echo "Horizontal format bits: {$formatBitsHorizontal}\n";
|
|
|
|
// Decode format information
|
|
// Format info is 15 bits with error correction
|
|
// Bits 0-4 contain EC level (2 bits) and mask pattern (3 bits)
|
|
$formatInt = bindec($formatBitsHorizontal);
|
|
|
|
// Try to find matching format pattern
|
|
echo "\nSearching for matching format pattern...\n";
|
|
|
|
$formatTable = [
|
|
'M' => [
|
|
0 => 0b101010000010010,
|
|
1 => 0b101000100100101,
|
|
2 => 0b101111001111100,
|
|
3 => 0b101101101001011,
|
|
4 => 0b100010111111001,
|
|
5 => 0b100000011001110,
|
|
6 => 0b100111110010111,
|
|
7 => 0b100101010100000,
|
|
],
|
|
];
|
|
|
|
$detectedMask = null;
|
|
foreach ($formatTable['M'] as $maskNum => $formatValue) {
|
|
$formatBits = str_pad(decbin($formatValue), 15, '0', STR_PAD_LEFT);
|
|
$firstByte = substr($formatBits, 0, 8);
|
|
|
|
if ($formatBitsHorizontal === $firstByte) {
|
|
echo "Found match! Mask Pattern: {$maskNum}\n";
|
|
$detectedMask = $maskNum;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($detectedMask === null) {
|
|
echo "Could not determine mask pattern from format info.\n";
|
|
echo "Trying all masks...\n\n";
|
|
|
|
// Try all 8 mask patterns
|
|
for ($maskNum = 0; $maskNum < 8; $maskNum++) {
|
|
echo "=== Testing Mask Pattern {$maskNum} ===\n";
|
|
|
|
$maskPattern = MaskPattern::from($maskNum);
|
|
$unmaskedBits = '';
|
|
$bitIndex = 0;
|
|
|
|
// Unmask data region
|
|
for ($col = $size - 1; $col >= 1; $col -= 2) {
|
|
if ($col === 6) {
|
|
$col--;
|
|
}
|
|
|
|
$upward = ((int) (($size - 1 - $col) / 2) % 2) === 0;
|
|
|
|
for ($i = 0; $i < $size; $i++) {
|
|
$row = $upward ? ($size - 1 - $i) : $i;
|
|
|
|
for ($c = 0; $c < 2; $c++) {
|
|
$currentCol = $col - $c;
|
|
|
|
// Skip function patterns
|
|
if ($row <= 8 && $currentCol <= 8) continue;
|
|
if ($row <= 8 && $currentCol >= $size - 8) continue;
|
|
if ($row >= $size - 8 && $currentCol <= 8) continue;
|
|
if ($row === 6 || $currentCol === 6) continue;
|
|
if ($row === 8 || $currentCol === 8) continue;
|
|
|
|
$maskedBit = $matrix->getModuleAt($row, $currentCol)->isDark() ? '1' : '0';
|
|
|
|
// Apply mask to reverse it
|
|
$shouldInvert = $maskPattern->shouldInvert($row, $currentCol);
|
|
$originalBit = $shouldInvert ? ($maskedBit === '1' ? '0' : '1') : $maskedBit;
|
|
|
|
$unmaskedBits .= $originalBit;
|
|
$bitIndex++;
|
|
|
|
if ($bitIndex >= 64) {
|
|
break 4; // Break all loops
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Decode first bytes
|
|
echo "First 64 unmasked bits: " . substr($unmaskedBits, 0, 64) . "\n";
|
|
echo "Bytes:\n";
|
|
for ($i = 0; $i < min(8, strlen($unmaskedBits) / 8); $i++) {
|
|
$byte = substr($unmaskedBits, $i * 8, 8);
|
|
$decimal = bindec($byte);
|
|
$char = $decimal >= 32 && $decimal < 127 ? chr($decimal) : '.';
|
|
echo " Byte " . ($i + 1) . ": {$byte} = {$decimal} ('{$char}')\n";
|
|
}
|
|
|
|
// Check if it matches expected pattern
|
|
$expected = '0100' . '00000101' . '01001000' . '01000101' . '01001100' . '01001100' . '01001111';
|
|
if (str_starts_with($unmaskedBits, $expected)) {
|
|
echo "✅ MATCH! This is the correct mask pattern!\n";
|
|
break;
|
|
} else {
|
|
echo "❌ No match.\n";
|
|
}
|
|
echo "\n";
|
|
}
|
|
}
|
|
|
|
echo "\n=== Expected Unmasked Data ===\n";
|
|
echo "Mode (Byte): 0100\n";
|
|
echo "Count (5): 00000101\n";
|
|
echo "H (72): 01001000\n";
|
|
echo "E (69): 01000101\n";
|
|
echo "L (76): 01001100\n";
|
|
echo "L (76): 01001100\n";
|
|
echo "O (79): 01001111\n";
|
|
echo "Combined: 010000000101010010000100010101001100010011000100111100...\n";
|