Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
<?php
2
 
3
namespace PhpOffice\PhpSpreadsheet\Worksheet;
4
 
5
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
6
use ZipArchive;
7
 
8
class Drawing extends BaseDrawing
9
{
10
    const IMAGE_TYPES_CONVERTION_MAP = [
11
        IMAGETYPE_GIF => IMAGETYPE_PNG,
12
        IMAGETYPE_JPEG => IMAGETYPE_JPEG,
13
        IMAGETYPE_PNG => IMAGETYPE_PNG,
14
        IMAGETYPE_BMP => IMAGETYPE_PNG,
15
    ];
16
 
17
    /**
18
     * Path.
19
     */
20
    private string $path;
21
 
22
    /**
23
     * Whether or not we are dealing with a URL.
24
     */
25
    private bool $isUrl;
26
 
27
    /**
28
     * Create a new Drawing.
29
     */
30
    public function __construct()
31
    {
32
        // Initialise values
33
        $this->path = '';
34
        $this->isUrl = false;
35
 
36
        // Initialize parent
37
        parent::__construct();
38
    }
39
 
40
    /**
41
     * Get Filename.
42
     */
43
    public function getFilename(): string
44
    {
45
        return basename($this->path);
46
    }
47
 
48
    /**
49
     * Get indexed filename (using image index).
50
     */
51
    public function getIndexedFilename(): string
52
    {
53
        return md5($this->path) . '.' . $this->getExtension();
54
    }
55
 
56
    /**
57
     * Get Extension.
58
     */
59
    public function getExtension(): string
60
    {
61
        $exploded = explode('.', basename($this->path));
62
 
63
        return $exploded[count($exploded) - 1];
64
    }
65
 
66
    /**
67
     * Get full filepath to store drawing in zip archive.
68
     */
69
    public function getMediaFilename(): string
70
    {
71
        if (!array_key_exists($this->type, self::IMAGE_TYPES_CONVERTION_MAP)) {
72
            throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
73
        }
74
 
75
        return sprintf('image%d%s', $this->getImageIndex(), $this->getImageFileExtensionForSave());
76
    }
77
 
78
    /**
79
     * Get Path.
80
     */
81
    public function getPath(): string
82
    {
83
        return $this->path;
84
    }
85
 
86
    /**
87
     * Set Path.
88
     *
89
     * @param string $path File path
90
     * @param bool $verifyFile Verify file
91
     * @param ?ZipArchive $zip Zip archive instance
92
     *
93
     * @return $this
94
     */
95
    public function setPath(string $path, bool $verifyFile = true, ?ZipArchive $zip = null): static
96
    {
97
        $this->isUrl = false;
98
        if (preg_match('~^data:image/[a-z]+;base64,~', $path) === 1) {
99
            $this->path = $path;
100
 
101
            return $this;
102
        }
103
 
104
        $this->path = '';
105
        // Check if a URL has been passed. https://stackoverflow.com/a/2058596/1252979
106
        if (filter_var($path, FILTER_VALIDATE_URL) || (preg_match('/^([\w\s\x00-\x1f]+):/u', $path) && !preg_match('/^([\w]+):/u', $path))) {
107
            if (!preg_match('/^(http|https|file|ftp|s3):/', $path)) {
108
                throw new PhpSpreadsheetException('Invalid protocol for linked drawing');
109
            }
110
            // Implicit that it is a URL, rather store info than running check above on value in other places.
111
            $this->isUrl = true;
112
            $ctx = null;
113
            // https://github.com/php/php-src/issues/16023
114
            // https://github.com/php/php-src/issues/17121
115
            if (str_starts_with($path, 'https:') || str_starts_with($path, 'http:')) {
116
                $ctxArray = [
117
                    'http' => [
118
                        'user_agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
119
                        'header' => [
120
                            //'Connection: keep-alive', // unacceptable performance
121
                            'Accept: image/*;q=0.9,*/*;q=0.8',
122
                        ],
123
                    ],
124
                ];
125
                if (str_starts_with($path, 'https:')) {
126
                    $ctxArray['ssl'] = ['crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT];
127
                }
128
                $ctx = stream_context_create($ctxArray);
129
            }
130
            $imageContents = @file_get_contents($path, false, $ctx);
131
            if ($imageContents !== false) {
132
                $filePath = tempnam(sys_get_temp_dir(), 'Drawing');
133
                if ($filePath) {
134
                    $put = @file_put_contents($filePath, $imageContents);
135
                    if ($put !== false) {
136
                        if ($this->isImage($filePath)) {
137
                            $this->path = $path;
138
                            $this->setSizesAndType($filePath);
139
                        }
140
                        unlink($filePath);
141
                    }
142
                }
143
            }
144
        } elseif ($zip instanceof ZipArchive) {
145
            $zipPath = explode('#', $path)[1];
146
            $locate = @$zip->locateName($zipPath);
147
            if ($locate !== false) {
148
                if ($this->isImage($path)) {
149
                    $this->path = $path;
150
                    $this->setSizesAndType($path);
151
                }
152
            }
153
        } else {
154
            $exists = @file_exists($path);
155
            if ($exists !== false && $this->isImage($path)) {
156
                $this->path = $path;
157
                $this->setSizesAndType($path);
158
            }
159
        }
160
        if ($this->path === '' && $verifyFile) {
161
            throw new PhpSpreadsheetException("File $path not found!");
162
        }
163
 
164
        if ($this->worksheet !== null) {
165
            if ($this->path !== '') {
166
                $this->worksheet->getCell($this->coordinates);
167
            }
168
        }
169
 
170
        return $this;
171
    }
172
 
173
    private function isImage(string $path): bool
174
    {
175
        $mime = (string) @mime_content_type($path);
176
        $retVal = false;
177
        if (str_starts_with($mime, 'image/')) {
178
            $retVal = true;
179
        } elseif ($mime === 'application/octet-stream') {
180
            $extension = pathinfo($path, PATHINFO_EXTENSION);
181
            $retVal = in_array($extension, ['bin', 'emf'], true);
182
        }
183
 
184
        return $retVal;
185
    }
186
 
187
    /**
188
     * Get isURL.
189
     */
190
    public function getIsURL(): bool
191
    {
192
        return $this->isUrl;
193
    }
194
 
195
    /**
196
     * Get hash code.
197
     *
198
     * @return string Hash code
199
     */
200
    public function getHashCode(): string
201
    {
202
        return md5(
203
            $this->path
204
            . parent::getHashCode()
205
            . __CLASS__
206
        );
207
    }
208
 
209
    /**
210
     * Get Image Type for Save.
211
     */
212
    public function getImageTypeForSave(): int
213
    {
214
        if (!array_key_exists($this->type, self::IMAGE_TYPES_CONVERTION_MAP)) {
215
            throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
216
        }
217
 
218
        return self::IMAGE_TYPES_CONVERTION_MAP[$this->type];
219
    }
220
 
221
    /**
222
     * Get Image file extention for Save.
223
     */
224
    public function getImageFileExtensionForSave(bool $includeDot = true): string
225
    {
226
        if (!array_key_exists($this->type, self::IMAGE_TYPES_CONVERTION_MAP)) {
227
            throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
228
        }
229
 
230
        $result = image_type_to_extension(self::IMAGE_TYPES_CONVERTION_MAP[$this->type], $includeDot);
231
 
232
        return "$result";
233
    }
234
 
235
    /**
236
     * Get Image mime type.
237
     */
238
    public function getImageMimeType(): string
239
    {
240
        if (!array_key_exists($this->type, self::IMAGE_TYPES_CONVERTION_MAP)) {
241
            throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
242
        }
243
 
244
        return image_type_to_mime_type(self::IMAGE_TYPES_CONVERTION_MAP[$this->type]);
245
    }
246
}