File manager - Edit - /home/webapp69.cm.in.th/u69319090033/Shop/tools_backup/fix_smart.php
Back
<?php /** * Fix mojibake in app.js * * The problem: Thai UTF-8 text was re-interpreted as Windows-1252/Latin1 * and then re-encoded to UTF-8, causing double-encoding. * * Solution: Read raw bytes, find sequences that are double-encoded UTF-8, * and reverse the process. * * A double-encoded UTF-8 Thai character looks like: * Original UTF-8 byte E0 -> C3 A0 in double-encoded UTF-8 * Original UTF-8 byte B8 -> C2 B8 in double-encoded UTF-8 * etc. * * We detect and fix these patterns byte-by-byte. */ $inputFile = 'app.js'; $outputFile = 'app.js'; $content = file_get_contents($inputFile); // Strategy: We know the mojibake comes from UTF-8 bytes being misinterpreted // as CP1252/Latin1 and then re-encoded to UTF-8. // // To reverse: take each "character" that is in the C2-C3 range (2-byte UTF-8 // for codepoints 0x80-0xFF), decode it back to the single byte it represents, // then check if the resulting byte sequence forms valid UTF-8 Thai. $output = ''; $len = strlen($content); $i = 0; $fixCount = 0; while ($i < $len) { $byte = ord($content[$i]); // Check if this could be start of a double-encoded sequence // Double-encoded UTF-8 Thai starts with: C3 A0 (which is UTF-8 for U+00E0, // but originally was byte 0xE0, the start of a 3-byte UTF-8 sequence for Thai) // OR C2 xx (UTF-8 for bytes 0x80-0xBF which are continuation bytes) if ($byte == 0xC3 || $byte == 0xC2 || $byte == 0xC5 || $byte == 0xC4) { // This is a 2-byte UTF-8 sequence encoding a byte in 0x80-0xFF range if ($i + 1 < $len) { $next = ord($content[$i + 1]); if ($next >= 0x80 && $next <= 0xBF) { // Decode back to original byte $origByte = (($byte & 0x1F) << 6) | ($next & 0x3F); // Check if this original byte could be part of a Thai UTF-8 sequence // Thai UTF-8 starts with E0 B8 xx or E0 B9 xx if ($origByte == 0xE0) { // Potential start of a 3-byte UTF-8 Thai char // We need 2 more "decoded" bytes $decoded = chr($origByte); $j = $i + 2; $consumed = 2; $validThai = false; // Try to decode next 2 bytes for ($k = 0; $k < 2 && $j < $len; $k++) { $b = ord($content[$j]); if ($b == 0xC2 || $b == 0xC3) { if ($j + 1 < $len) { $n = ord($content[$j + 1]); if ($n >= 0x80 && $n <= 0xBF) { $orig = (($b & 0x1F) << 6) | ($n & 0x3F); $decoded .= chr($orig); $j += 2; $consumed += 2; } else { break; } } else { break; } } elseif ($b >= 0x80 && $b <= 0xBF) { // Already a raw continuation byte (shouldn't happen in valid UTF-8 standalone) break; } else { break; } } if (strlen($decoded) == 3) { // Check if decoded bytes form valid Thai UTF-8 $decoded_str = mb_convert_encoding($decoded, 'UTF-8', 'UTF-8'); $cp = mb_ord($decoded_str, 'UTF-8'); // Thai range: U+0E00 to U+0E7F, also check U+0E80+ for Lao // Also allow Thai baht sign U+0E3F if ($cp >= 0x0E00 && $cp <= 0x0E7F) { $output .= $decoded; $i = $j; $fixCount++; continue; } } } // Check for other double-encoded patterns // E2 80 xx sequences (smart quotes, bullets, em-dash etc.) if ($origByte == 0xE2) { $decoded = chr($origByte); $j = $i + 2; for ($k = 0; $k < 2 && $j < $len; $k++) { $b = ord($content[$j]); if ($b == 0xC2 || $b == 0xC3) { if ($j + 1 < $len) { $n = ord($content[$j + 1]); if ($n >= 0x80 && $n <= 0xBF) { $orig = (($b & 0x1F) << 6) | ($n & 0x3F); $decoded .= chr($orig); $j += 2; } else { break; } } else { break; } } else { break; } } if (strlen($decoded) == 3) { $decoded_str = mb_convert_encoding($decoded, 'UTF-8', 'UTF-8'); if ($decoded_str !== false && mb_check_encoding($decoded, 'UTF-8')) { $cp = mb_ord($decoded_str, 'UTF-8'); // Common typographic characters: bullets, dashes, quotes // U+2000-U+206F (general punctuation), U+2190-U+21FF, etc if (($cp >= 0x2000 && $cp <= 0x206F) || ($cp >= 0x2190 && $cp <= 0x21FF) || ($cp >= 0x2500 && $cp <= 0x257F)) { $output .= $decoded; $i = $j; $fixCount++; continue; } } } } } } } // Not a double-encoded sequence, keep original byte $output .= $content[$i]; $i++; } file_put_contents($outputFile, $output); echo "Fixed $fixCount double-encoded characters in app.js\n"; // Verify: count remaining non-ASCII suspicious patterns $remaining = 0; $lines = explode("\n", $output); foreach ($lines as $lineNum => $line) { // Check for C2/C3 followed by Thai-range bytes (signs of remaining mojibake) if (preg_match('/[\xC2\xC3][\x80-\xBF]/', $line)) { // This could be legitimate UTF-8, so check if it's in Thai context // Just count for reporting if (preg_match('/[\x{0E00}-\x{0E7F}]/u', $line) || preg_match('/[\xC2][\x80-\x9F]/', $line)) { // Lines with Thai AND suspicious C2 bytes $remaining++; } } } echo "Lines with potential remaining issues: $remaining\n";
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.25 |
proxy
|
phpinfo
|
Settings