TerUtility.php 3.92 KB
Newer Older
1
<?php
2

3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
7
8
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, either version 2
 * of the License, or any later version.
9
 *
10
11
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
14
 * The TYPO3 project - inspiring people to share!
 */
15

16
17
namespace TYPO3\CMS\Extensionmanager\Utility\Connection;

18
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
19
use TYPO3\CMS\Core\Core\Environment;
20
use TYPO3\CMS\Core\Utility\GeneralUtility;
21
22
use TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException;

23
24
25
26
/**
 * TER2 connection handling class for the TYPO3 Extension Manager.
 *
 * It contains methods for downloading and uploading extensions and related code
27
 * @internal This class is a specific TER implementation and is not part of the Public TYPO3 API.
28
 */
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class TerUtility
{
    /**
     * Fetches an extension from the given mirror
     *
     * @param string $extensionKey Extension Key
     * @param string $version Version to install
     * @param string $expectedMd5 Expected MD5 hash of extension file
     * @param string $mirrorUrl URL of mirror to use
     * @throws ExtensionManagerException
     * @return array T3X data
     */
    public function fetchExtension($extensionKey, $version, $expectedMd5, $mirrorUrl)
    {
43
        if (
44
            (bool)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('extensionmanager', 'offlineMode')
45
            || Environment::isComposerMode()
46
        ) {
47
48
            throw new ExtensionManagerException('Extension Manager is in offline mode. No TER connection available.', 1437078620);
        }
49
        $extensionPath = strtolower($extensionKey);
50
        $mirrorUrl .= $extensionPath[0] . '/' . $extensionPath[1] . '/' . $extensionPath . '_' . $version . '.t3x';
51
        $t3x = GeneralUtility::getUrl($mirrorUrl);
52
53
54
55
56
57
58
59
60
61
62
63
        $md5 = md5($t3x);
        if ($t3x === false) {
            throw new ExtensionManagerException(sprintf('The T3X file "%s" could not be fetched. Possible reasons: network problems, allow_url_fopen is off, cURL is not enabled in Install Tool.', $mirrorUrl), 1334426097);
        }
        if ($md5 === $expectedMd5) {
            // Fetch and return:
            $extensionData = $this->decodeExchangeData($t3x);
        } else {
            throw new ExtensionManagerException('Error: MD5 hash of downloaded file not as expected: ' . $md5 . ' != ' . $expectedMd5, 1334426098);
        }
        return $extensionData;
    }
64

65
66
67
68
69
70
71
72
73
74
75
    /**
     * Decodes extension upload array.
     * This kind of data is when an extension is uploaded to TER
     *
     * @param string $stream Data stream
     * @throws ExtensionManagerException
     * @return array Array with result on success, otherwise an error string.
     */
    public function decodeExchangeData($stream)
    {
        $parts = explode(':', $stream, 3);
76
        if ($parts[1] === 'gzcompress') {
77
78
79
            if (function_exists('gzuncompress')) {
                $parts[2] = gzuncompress($parts[2]);
            } else {
80
                throw new ExtensionManagerException('Decoding Error: No decompressor available for compressed content. gzcompress()/gzuncompress() functions are not available!', 1344761814);
81
82
            }
        }
83
        if (hash_equals($parts[0], md5($parts[2]))) {
84
            $output = unserialize($parts[2], ['allowed_classes' => false]);
85
86
87
88
            if (!is_array($output)) {
                throw new ExtensionManagerException('Error: Content could not be unserialized to an array. Strange (since MD5 hashes match!)', 1344761938);
            }
        } else {
89
            throw new ExtensionManagerException('Error: MD5 mismatch. Maybe the extension file was downloaded and saved as a text file by the browser and thereby corrupted!? (Always select "All" filetype when saving extensions)', 1344761991);
90
91
92
        }
        return $output;
    }
93
}