Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <fabien@symfony.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
 
12
namespace Symfony\Component\Translation\Loader;
13
 
14
use Symfony\Component\Translation\Exception\InvalidResourceException;
15
 
16
/**
17
 * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/)
18
 */
19
class MoFileLoader extends FileLoader
20
{
21
    /**
22
     * Magic used for validating the format of an MO file as well as
23
     * detecting if the machine used to create that file was little endian.
24
     */
25
    public const MO_LITTLE_ENDIAN_MAGIC = 0x950412DE;
26
 
27
    /**
28
     * Magic used for validating the format of an MO file as well as
29
     * detecting if the machine used to create that file was big endian.
30
     */
31
    public const MO_BIG_ENDIAN_MAGIC = 0xDE120495;
32
 
33
    /**
34
     * The size of the header of an MO file in bytes.
35
     */
36
    public const MO_HEADER_SIZE = 28;
37
 
38
    /**
39
     * Parses machine object (MO) format, independent of the machine's endian it
40
     * was created on. Both 32bit and 64bit systems are supported.
41
     */
42
    protected function loadResource(string $resource): array
43
    {
44
        $stream = fopen($resource, 'r');
45
 
46
        $stat = fstat($stream);
47
 
48
        if ($stat['size'] < self::MO_HEADER_SIZE) {
49
            throw new InvalidResourceException('MO stream content has an invalid format.');
50
        }
51
        $magic = unpack('V1', fread($stream, 4));
52
        $magic = hexdec(substr(dechex(current($magic)), -8));
53
 
54
        if (self::MO_LITTLE_ENDIAN_MAGIC == $magic) {
55
            $isBigEndian = false;
56
        } elseif (self::MO_BIG_ENDIAN_MAGIC == $magic) {
57
            $isBigEndian = true;
58
        } else {
59
            throw new InvalidResourceException('MO stream content has an invalid format.');
60
        }
61
 
62
        // formatRevision
63
        $this->readLong($stream, $isBigEndian);
64
        $count = $this->readLong($stream, $isBigEndian);
65
        $offsetId = $this->readLong($stream, $isBigEndian);
66
        $offsetTranslated = $this->readLong($stream, $isBigEndian);
67
        // sizeHashes
68
        $this->readLong($stream, $isBigEndian);
69
        // offsetHashes
70
        $this->readLong($stream, $isBigEndian);
71
 
72
        $messages = [];
73
 
74
        for ($i = 0; $i < $count; ++$i) {
75
            $pluralId = null;
76
            $translated = null;
77
 
78
            fseek($stream, $offsetId + $i * 8);
79
 
80
            $length = $this->readLong($stream, $isBigEndian);
81
            $offset = $this->readLong($stream, $isBigEndian);
82
 
83
            if ($length < 1) {
84
                continue;
85
            }
86
 
87
            fseek($stream, $offset);
88
            $singularId = fread($stream, $length);
89
 
90
            if (str_contains($singularId, "\000")) {
91
                [$singularId, $pluralId] = explode("\000", $singularId);
92
            }
93
 
94
            fseek($stream, $offsetTranslated + $i * 8);
95
            $length = $this->readLong($stream, $isBigEndian);
96
            $offset = $this->readLong($stream, $isBigEndian);
97
 
98
            if ($length < 1) {
99
                continue;
100
            }
101
 
102
            fseek($stream, $offset);
103
            $translated = fread($stream, $length);
104
 
105
            if (str_contains($translated, "\000")) {
106
                $translated = explode("\000", $translated);
107
            }
108
 
109
            $ids = ['singular' => $singularId, 'plural' => $pluralId];
110
            $item = compact('ids', 'translated');
111
 
112
            if (!empty($item['ids']['singular'])) {
113
                $id = $item['ids']['singular'];
114
                if (isset($item['ids']['plural'])) {
115
                    $id .= '|'.$item['ids']['plural'];
116
                }
117
                $messages[$id] = stripcslashes(implode('|', (array) $item['translated']));
118
            }
119
        }
120
 
121
        fclose($stream);
122
 
123
        return array_filter($messages);
124
    }
125
 
126
    /**
127
     * Reads an unsigned long from stream respecting endianness.
128
     *
129
     * @param resource $stream
130
     */
131
    private function readLong($stream, bool $isBigEndian): int
132
    {
133
        $result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4));
134
        $result = current($result);
135
 
136
        return (int) substr($result, -8);
137
    }
138
}