[TASK] Use strict comparison for strings
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Classes / Utility / Connection / TerUtility.php
1 <?php
2 namespace TYPO3\CMS\Extensionmanager\Utility\Connection;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Core\Bootstrap;
18 use TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException;
19
20 /**
21 * TER2 connection handling class for the TYPO3 Extension Manager.
22 *
23 * It contains methods for downloading and uploading extensions and related code
24 */
25 class TerUtility
26 {
27 /**
28 * @var string
29 */
30 public $wsdlUrl;
31
32 /**
33 * @var \TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility
34 */
35 protected $configurationUtility;
36
37 /**
38 * @param \TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility $configurationUtility
39 */
40 public function injectConfigurationUtility(\TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility $configurationUtility)
41 {
42 $this->configurationUtility = $configurationUtility;
43 }
44
45 /**
46 * Fetches an extension from the given mirror
47 *
48 * @param string $extensionKey Extension Key
49 * @param string $version Version to install
50 * @param string $expectedMd5 Expected MD5 hash of extension file
51 * @param string $mirrorUrl URL of mirror to use
52 * @throws ExtensionManagerException
53 * @return array T3X data
54 */
55 public function fetchExtension($extensionKey, $version, $expectedMd5, $mirrorUrl)
56 {
57 if (
58 !empty($this->configurationUtility->getCurrentConfiguration('extensionmanager')['offlineMode']['value'])
59 || Bootstrap::usesComposerClassLoading()
60 ) {
61 throw new ExtensionManagerException('Extension Manager is in offline mode. No TER connection available.', 1437078620);
62 }
63 $extensionPath = strtolower($extensionKey);
64 $mirrorUrl .= $extensionPath[0] . '/' . $extensionPath[1] . '/' . $extensionPath . '_' . $version . '.t3x';
65 $t3x = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($mirrorUrl);
66 $md5 = md5($t3x);
67 if ($t3x === false) {
68 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);
69 }
70 if ($md5 === $expectedMd5) {
71 // Fetch and return:
72 $extensionData = $this->decodeExchangeData($t3x);
73 } else {
74 throw new ExtensionManagerException('Error: MD5 hash of downloaded file not as expected: ' . $md5 . ' != ' . $expectedMd5, 1334426098);
75 }
76 return $extensionData;
77 }
78
79 /**
80 * Decode server data
81 * This is information like the extension list, extension
82 * information etc., return data after uploads (new em_conf)
83 * On success, returns an array with data array and stats
84 * array as key 0 and 1.
85 *
86 * @param string $externalData Data stream from remove server
87 * @throws ExtensionManagerException
88 * @return array $externalData
89 * @see fetchServerData(), processRepositoryReturnData()
90 */
91 public function decodeServerData($externalData)
92 {
93 $parts = explode(':', $externalData, 4);
94 $dat = base64_decode($parts[2]);
95 gzuncompress($dat);
96 // compare hashes ignoring any leading whitespace. See bug #0000365.
97 if (ltrim($parts[0]) == md5($dat)) {
98 if ($parts[1] === 'gzcompress') {
99 if (function_exists('gzuncompress')) {
100 $dat = gzuncompress($dat);
101 } else {
102 throw new ExtensionManagerException('Decoding Error: No decompressor available for compressed content. gzuncompress() function is not available!', 1342859463);
103 }
104 }
105 $listArr = unserialize($dat);
106 if (!is_array($listArr)) {
107 throw new ExtensionManagerException('Error: Unserialized information was not an array - strange!', 1342859489);
108 }
109 } else {
110 throw new ExtensionManagerException('Error: MD5 hashes in T3X data did not match!', 1342859505);
111 }
112 return $listArr;
113 }
114
115 /**
116 * Decodes extension upload array.
117 * This kind of data is when an extension is uploaded to TER
118 *
119 * @param string $stream Data stream
120 * @throws ExtensionManagerException
121 * @return array Array with result on success, otherwise an error string.
122 */
123 public function decodeExchangeData($stream)
124 {
125 $parts = explode(':', $stream, 3);
126 if ($parts[1] === 'gzcompress') {
127 if (function_exists('gzuncompress')) {
128 $parts[2] = gzuncompress($parts[2]);
129 } else {
130 throw new ExtensionManagerException('Decoding Error: No decompressor available for compressed content. gzcompress()/gzuncompress() ' . 'functions are not available!', 1344761814);
131 }
132 }
133 if (md5($parts[2]) === $parts[0]) {
134 $output = unserialize($parts[2]);
135 if (!is_array($output)) {
136 throw new ExtensionManagerException('Error: Content could not be unserialized to an array. Strange (since MD5 hashes match!)', 1344761938);
137 }
138 } else {
139 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);
140 }
141 return $output;
142 }
143 }