Explorar el Código

текущее состояние

ilg2005 hace 3 meses
padre
commit
2c01471e2c
Se han modificado 1 ficheros con 48 adiciones y 6 borrados
  1. 48 6
      app/Models/Char/CharMail.php

+ 48 - 6
app/Models/Char/CharMail.php

@@ -74,13 +74,22 @@ class CharMail extends Model
 
     private function decodeBinaryValue(?string $value): ?string
     {
+        // Удаляем завершающие нули – они часто встречаются в char( n ) столбцах
         $value = $this->stripNulls($value);
         if ($value === null || $value === '') {
             return $value;
         }
 
-        $decoded = $this->decodeBase64($this->decodeBase64($value));
-        $decoded = $this->stripNulls($decoded);
+        // Пробуем декодировать максимум два раза (схема хранения – двойной base64)
+        $decoded = $value;
+        for ($i = 0; $i < 2; $i++) {
+            $tmp = base64_decode($decoded, true);
+            if ($tmp === false) {
+                // Строка не похожа на base64 – прекращаем попытки
+                break;
+            }
+            $decoded = $this->stripNulls($tmp);
+        }
 
         return $decoded === null ? null : $this->ensureUtf8($decoded);
     }
@@ -92,11 +101,23 @@ class CharMail extends Model
             return $value;
         }
 
+        // Если строка уже дважды закодирована – ничего не делаем
+        if ($this->isBase64($value)) {
+            $inner = base64_decode($value, true);
+            if ($inner !== false && $this->isBase64($inner)) {
+                return $value; // уже двойной base64
+            }
+            // Если только один слой – добавляем ещё один
+            return base64_encode($value);
+        }
+
+        // Конвертируем в CP1251 (игровой клиент ожидает именно эту кодировку)
         $prepared = @iconv('UTF-8', 'CP1251//IGNORE', $value);
         if ($prepared === false) {
-            $prepared = $value;
+            $prepared = $value; // если iconv не смог – используем как есть
         }
 
+        // Двойное кодирование base64
         return base64_encode(base64_encode($prepared));
     }
 
@@ -105,10 +126,17 @@ class CharMail extends Model
         return $value === null ? null : rtrim($value, "\0");
     }
 
-    private function decodeBase64(string $value): string
+    // Более лояльная проверка base64 (без строгого ===, учитываем отсутствие отступов и символы \r\n)
+    private function isBase64(string $value): bool
     {
-        $decoded = base64_decode($value, true);
-        return $decoded === false ? $value : $decoded;
+        if ($value === '') {
+            return false;
+        }
+        // Проверяем набор допустимых символов и кратность 4
+        if (preg_match('/^[A-Za-z0-9+\/\r\n]+=*$/', $value) !== 1) {
+            return false;
+        }
+        return (strlen($value) % 4 === 0);
     }
 
     private function ensureUtf8(string $value): string
@@ -160,6 +188,20 @@ class CharMail extends Model
     public function toArray()
     {
         $array = parent::toArray();
+
+        // Явно декодируем бинарные поля, на случай если accessor не сработал при сериализации
+        if (array_key_exists('binTitle', $this->attributes)) {
+            $array['binTitle'] = $this->decodeBinaryValue($this->attributes['binTitle']);
+        } elseif (array_key_exists('binTitle', $array)) {
+            $array['binTitle'] = $this->decodeBinaryValue($array['binTitle']);
+        }
+
+        if (array_key_exists('binLetter', $this->attributes)) {
+            $array['binLetter'] = $this->decodeBinaryValue($this->attributes['binLetter']);
+        } elseif (array_key_exists('binLetter', $array)) {
+            $array['binLetter'] = $this->decodeBinaryValue($array['binLetter']);
+        }
+
         array_walk_recursive($array, function (&$v) {
             if (is_string($v)) {
                 $v = $this->ensureUtf8($v);