PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.3.0
Defender Security – Malware Scanner, Login Security & Firewall v6.3.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / vendor / gettext / gettext / src / Loader / MoLoader.php

MoLoader.php in Defender Security – Malware Scanner, Login Security & Firewall 6.3.0, at vendor/gettext/gettext/src/Loader/MoLoader.php

142 lines 3.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 declare(strict_types = 1);
3
4 namespace Gettext\Loader;
5
6 use Exception;
7 use Gettext\Translations;
8
9 /**
10 * Class to load a MO file.
11 */
12 final class MoLoader extends Loader
13 {
14 private $string;
15 private $position;
16 private $length;
17
18 private const MAGIC1 = -1794895138;
19 private const MAGIC2 = -569244523;
20 private const MAGIC3 = 2500072158;
21
22 public function loadString(string $string, ?Translations $translations = null): Translations
23 {
24 $translations = parent::loadString($string, $translations);
25 $this->init($string);
26
27 $magic = $this->readInt('V');
28
29 if (($magic === self::MAGIC1) || ($magic === self::MAGIC3)) { //to make sure it works for 64-bit platforms
30 $byteOrder = 'V'; //low endian
31 } elseif ($magic === (self::MAGIC2 & 0xFFFFFFFF)) {
32 $byteOrder = 'N'; //big endian
33 } else {
34 throw new Exception('Not MO file');
35 }
36
37 $this->readInt($byteOrder);
38
39 $total = $this->readInt($byteOrder); //total string count
40 $originals = $this->readInt($byteOrder); //offset of original table
41 $tran = $this->readInt($byteOrder); //offset of translation table
42
43 $this->seekto($originals);
44 $table_originals = $this->readIntArray($byteOrder, $total * 2);
45
46 $this->seekto($tran);
47 $table_translations = $this->readIntArray($byteOrder, $total * 2);
48
49 for ($i = 0; $i < $total; ++$i) {
50 $next = $i * 2;
51
52 $this->seekto($table_originals[$next + 2]);
53 $original = $this->read($table_originals[$next + 1]);
54
55 $this->seekto($table_translations[$next + 2]);
56 $translated = $this->read($table_translations[$next + 1]);
57
58 // Headers
59 if ($original === '') {
60 foreach (explode("\n", $translated) as $headerLine) {
61 if ($headerLine === '') {
62 continue;
63 }
64
65 $headerChunks = preg_split('/:\s*/', $headerLine, 2);
66 $translations->getHeaders()->set($headerChunks[0], isset($headerChunks[1]) ? $headerChunks[1] : '');
67 }
68
69 continue;
70 }
71
72 $context = $plural = null;
73 $chunks = explode("\x04", $original, 2);
74
75 if (isset($chunks[1])) {
76 list($context, $original) = $chunks;
77 }
78
79 $chunks = explode("\x00", $original, 2);
80
81 if (isset($chunks[1])) {
82 list($original, $plural) = $chunks;
83 }
84
85 $translation = $this->createTranslation($context, $original, $plural);
86 $translations->add($translation);
87
88 if ($translated === '') {
89 continue;
90 }
91
92 if ($plural === null) {
93 $translation->translate($translated);
94 continue;
95 }
96
97 $v = explode("\x00", $translated);
98 $translation->translate(array_shift($v));
99 $translation->translatePlural(...array_filter($v));
100 }
101
102 return $translations;
103 }
104
105 private function init(string $string): void
106 {
107 $this->string = $string;
108 $this->position = 0;
109 $this->length = strlen($string);
110 }
111
112 private function read(int $bytes): string
113 {
114 $data = substr($this->string, $this->position, $bytes);
115
116 $this->seekTo($this->position + $bytes);
117
118 return $data;
119 }
120
121 private function seekTo(int $position): void
122 {
123 $this->position = ($this->length < $position) ? $this->length : $position;
124 }
125
126 private function readInt(string $byteOrder): int
127 {
128 if (($read = $this->read(4)) === false) {
129 return 0;
130 }
131
132 $read = (array) unpack($byteOrder, $read);
133
134 return (int) array_shift($read);
135 }
136
137 private function readIntArray(string $byteOrder, int $count): array
138 {
139 return unpack($byteOrder.$count, $this->read(4 * $count)) ?: [];
140 }
141 }
142