Fix deleting content from moderation report page
[GitHub/WoltLab/WCF.git] / com.woltlab.wcf / files_pre.tar
CommitLineData
5b0a72f1
TD
1acp/update_com.woltlab.wcf_5.4_session_1_cookies.php\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000770\00001750\00000056\000000011660\014043741472\0023050\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0timwolla\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0plugdev\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<?php
2
3/**
4 * Sets the new session cookies.
5 *
6 * @author Tim Duesterhus
7 * @copyright 2001-2021 WoltLab GmbH
8 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
9 * @package WoltLabSuite\Core
10 */
11
12use wcf\system\application\ApplicationHandler;
13use wcf\system\form\container\GroupFormElementContainer;
14use wcf\system\form\element\LabelFormElement;
15use wcf\system\form\FormDocument;
16use wcf\system\request\RouteHandler;
17use wcf\system\WCF;
18use wcf\util\CryptoUtil;
19use wcf\util\HeaderUtil;
20
21// 1) Check whether the cookies are already in place.
22$hasValidSessionCookie = false;
23if (!empty($_COOKIE[COOKIE_PREFIX . "user_session"])) {
24 $cookieValue = CryptoUtil::getValueFromSignedString($_COOKIE[COOKIE_PREFIX . "user_session"]);
25 if ($cookieValue && \mb_strlen($cookieValue, '8bit') === 22) {
26 $sessionID = \bin2hex(\mb_substr($cookieValue, 1, 20, '8bit'));
27 if ($sessionID === WCF::getSession()->sessionID) {
28 $hasValidSessionCookie = true;
29 }
30 }
31}
32
33$hasValidXsrfToken = false;
34if (!empty($_COOKIE['XSRF-TOKEN'])) {
35 if (
36 // Check that the XSRF-TOKEN cookie is correctly signed.
37 CryptoUtil::validateSignedString($_COOKIE['XSRF-TOKEN'])
38 // Check that the current session value matches the cookie value.
39 && WCF::getSession()->checkSecurityToken($_COOKIE['XSRF-TOKEN'])
40 // Check that the 't' used for this request matches the cookie value.
41 && (
42 !empty($_REQUEST['t'])
43 && \hash_equals($_COOKIE['XSRF-TOKEN'], $_REQUEST['t'])
44 )
45 ) {
46 $hasValidXsrfToken = true;
47 }
48}
49
50if ($hasValidSessionCookie && $hasValidXsrfToken) {
51 // The process may continue;
52 return;
53}
54
55// 2) Set new session cookie.
56HeaderUtil::setCookie(
57 "user_session",
58 CryptoUtil::createSignedString(
59 \pack(
60 'CA20C',
61 1,
62 \hex2bin(WCF::getSession()->sessionID),
63 0
64 )
65 )
66);
67
68// 3) Set new XSRF-TOKEN cookie.
69$sameSite = $cookieDomain = '';
70if (ApplicationHandler::getInstance()->isMultiDomainSetup()) {
71 // We need to specify the cookieDomain in a multi domain set-up, because
72 // otherwise no cookies are sent to subdomains.
73 $cookieDomain = HeaderUtil::getCookieDomain();
74 $cookieDomain = ($cookieDomain !== null ? '; domain=' . $cookieDomain : '');
75} else {
76 // SameSite=strict is not supported in a multi domain set-up, because
77 // it breaks cross-application requests.
78 $sameSite = '; SameSite=strict';
79}
80
81do {
82 $bytes = \bin2hex(\random_bytes(16));
83} while (\strpos(\base64_encode($bytes), '+') !== false);
84$xsrfToken = CryptoUtil::createSignedString($bytes);
85WCF::getSession()->register('__SECURITY_TOKEN', $xsrfToken);
86\header(
87 'set-cookie: XSRF-TOKEN=' . \rawurlencode($xsrfToken) . '; path=/' . $cookieDomain . (RouteHandler::secureConnection() ? '; secure' : '') . $sameSite,
88 false
89);
90
91// 4) Adjust the SECURITY_TOKEN.
92$container = new GroupFormElementContainer();
93if (WCF::getLanguage()->getFixedLanguageCode() === 'de') {
94 $container->setLabel("Sitzungs-Vorbereitung");
95 $container->setDescription('');
96} else {
97 $container->setLabel("Session Preparation");
98 $container->setDescription('');
99}
100
101$label = new LabelFormElement($container);
102if (WCF::getLanguage()->getFixedLanguageCode() === 'de') {
103 $label->setLabel('');
104 $label->setText(
105 <<<'EOT'
106WoltLab Suite 5.4 aktualisiert das Sitzungs-System.
107Dieser Schritt des Upgrades bereitet Ihre aktive Sitzung auf die Aktualisierung vor und stellt sicher, dass Sie dauerhaft eingeloggt bleiben.
108Falls Sie dieses Fenster nach dem Fortfahren erneut sehen, konnte Ihre Sitzung nicht vorbereitet werden.
109Bitte leeren Sie in diesem Fall die Cookies in Ihrem Webbrowser, melden sich erneut in der Administrationsoberfläche an und versuchen das Upgrade erneut.
110EOT
111 );
112} else {
113 $label->setLabel('');
114 $label->setText(
115 <<<'EOT'
116WoltLab Suite 5.4 updates the session handling.
117This step of the upgrade prepares your active session for this upgrade and ensures that you will continously stay logged in.
118If you see this window again after proceeding then your session could not be prepared.
119Please clear your web browser's cookies in this case.
120Afterwards log back into the Administrator's Control Panel and restart the upgrade.
121EOT
122 );
123}
124
125$label->setDescription(
126 <<<EOT
127<script>(function() {
128var oldToken = SECURITY_TOKEN;
129SECURITY_TOKEN = encodeURIComponent("{$xsrfToken}");
130var oldExecute = WCF.ACP.Package.Installation.prototype._executeStep;
131WCF.ACP.Package.Installation.prototype._executeStep = function (step, node, additionalData) {
132 var request = this._proxy._ajaxRequest;
133 request.setOption('url', request.getOption('url').replace(oldToken, SECURITY_TOKEN));
134
135 return oldExecute.call(this, step, node, additionalData);
136}
137})();
138</script>
139EOT
140);
141
142$container->appendChild($label);
143
144$document = new FormDocument("cookies_set");
145$document->appendContainer($container);
146
147return $document;
148\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0acp/database/update_com.woltlab.wcf_5.4_session_2_user_session.php\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000770\00001750\00000056\000000004173\014043741470\0025701\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0timwolla\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0plugdev\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<?php
149
150/**
151 * Creates the user_session table.
152 *
153 * @author Tim Duesterhus
154 * @copyright 2001-2020 WoltLab GmbH
155 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
156 * @package WoltLabSuite\Core
157 */
158
159use wcf\system\database\table\column\CharDatabaseTableColumn;
160use wcf\system\database\table\column\IntDatabaseTableColumn;
161use wcf\system\database\table\column\MediumblobDatabaseTableColumn;
162use wcf\system\database\table\column\NotNullInt10DatabaseTableColumn;
163use wcf\system\database\table\column\NotNullVarchar255DatabaseTableColumn;
164use wcf\system\database\table\column\VarcharDatabaseTableColumn;
165use wcf\system\database\table\DatabaseTable;
166use wcf\system\database\table\index\DatabaseTableForeignKey;
167use wcf\system\database\table\index\DatabaseTableIndex;
168
169return [
170 DatabaseTable::create('wcf1_user_session')
171 ->columns([
172 CharDatabaseTableColumn::create('sessionID')
173 ->length(40)
174 ->notNull(),
175 IntDatabaseTableColumn::create('userID')
176 ->length(10),
177 NotNullVarchar255DatabaseTableColumn::create('userAgent')
178 ->defaultValue(''),
179 VarcharDatabaseTableColumn::create('ipAddress')
180 ->length(39)
181 ->defaultValue(''),
182 NotNullInt10DatabaseTableColumn::create('creationTime'),
183 NotNullInt10DatabaseTableColumn::create('lastActivityTime')
184 ->defaultValue(0),
185 MediumblobDatabaseTableColumn::create('sessionVariables'),
186 ])
187 ->indices([
188 DatabaseTableIndex::create()
189 ->type(DatabaseTableIndex::PRIMARY_TYPE)
190 ->columns(['sessionID']),
191 DatabaseTableIndex::create()
192 ->columns(['userID']),
193 DatabaseTableIndex::create()
194 ->columns(['lastActivityTime']),
195 ])
196 ->foreignKeys([
197 DatabaseTableForeignKey::create()
198 ->columns(['userID'])
199 ->referencedTable('wcf1_user')
200 ->referencedColumns(['userID'])
201 ->onDelete('CASCADE'),
202 ]),
203];
204\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0acp/update_com.woltlab.wcf_5.4_session_3_migrate_session.php\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000770\00001750\00000056\000000003115\014043741472\0024605\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0timwolla\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0plugdev\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<?php
205
206/**
207 * Creates a 5.4+ session matching the current ACP session.
208 *
209 * @author Tim Duesterhus
210 * @copyright 2001-2020 WoltLab GmbH
211 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
212 * @package WoltLabSuite\Core
213 */
214
215use wcf\system\session\SessionHandler;
216use wcf\system\WCF;
217
218$sql = "SELECT userID
219 FROM wcf" . WCF_N . "_user_session
220 WHERE sessionID = ?";
221$statement = WCF::getDB()->prepareStatement($sql);
222$statement->execute([
223 SessionHandler::getInstance()->sessionID,
224]);
225
226// Check if a matching session already exists.
227if ($statement->fetchSingleColumn() == SessionHandler::getInstance()->userID) {
228 return;
229}
230
231$sql = "INSERT INTO wcf" . WCF_N . "_user_session
232 (sessionID, userID, userAgent, ipAddress, creationTime, lastActivityTime, sessionVariables)
233 VALUES (?, ?, ?, ?, ?, ?, ?)";
234$statement = WCF::getDB()->prepareStatement($sql);
235
236$klass = new \ReflectionClass(SessionHandler::getInstance());
237$property = $klass->getProperty('variables');
238$property->setAccessible(true);
239$variables = $property->getValue(SessionHandler::getInstance());
240
241$variables[SessionHandler::class . "\0__reauthentication__"] = [
242 'lastAuthentication' => TIME_NOW,
243 'lastCheck' => TIME_NOW,
244];
245
246$statement->execute([
247 SessionHandler::getInstance()->sessionID,
248 SessionHandler::getInstance()->userID,
249 SessionHandler::getInstance()->userAgent,
250 SessionHandler::getInstance()->ipAddress,
251 TIME_NOW,
252 TIME_NOW,
253 \serialize([
254 'acp' => $variables,
255 'frontend' => [],
256 ]),
257]);
258\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0lib/util/HeaderUtil.class.php\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000770\00001750\00000056\000000014624\014043741532\0016534\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0timwolla\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0plugdev\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<?php
259
260namespace wcf\util;
261
262use wcf\system\application\ApplicationHandler;
263use wcf\system\event\EventHandler;
264use wcf\system\request\RequestHandler;
265use wcf\system\request\RouteHandler;
266use wcf\system\session\SessionHandler;
267use wcf\system\WCF;
268
269/**
270 * Contains header-related functions.
271 *
272 * @author Marcel Werk
273 * @copyright 2001-2019 WoltLab GmbH
274 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
275 * @package WoltLabSuite\Core\Util
276 */
277final class HeaderUtil
278{
279 /**
280 * @deprecated 5.4 - gzip support was removed.
281 */
282 const GZIP_LEVEL = 1;
283
284 /**
285 * output HTML
286 * @var string
287 */
288 public static $output = '';
289
290 /**
291 * Alias to php setcookie() function.
292 *
293 * @param string $name
294 * @param string $value
295 * @param int $expire
296 */
297 public static function setCookie($name, $value = '', $expire = 0)
298 {
299 $cookieDomain = self::getCookieDomain();
300
301 @\header(
302 'Set-Cookie: ' . \rawurlencode(COOKIE_PREFIX . $name) . '=' . \rawurlencode((string)$value) . ($expire ? '; expires=' . \gmdate(
303 'D, d-M-Y H:i:s',
304 $expire
305 ) . ' GMT; max-age=' . ($expire - TIME_NOW) : '') . '; path=/' . ($cookieDomain !== null ? '; domain=' . $cookieDomain : '') . (RouteHandler::secureConnection() ? '; secure' : '') . '; HttpOnly',
306 false
307 );
308 }
309
310 /**
311 * Returns the cookie domain for the active application or 'null' if no domain should be specified.
312 */
313 public static function getCookieDomain(): ?string
314 {
315 $application = ApplicationHandler::getInstance()->getActiveApplication();
316 $addDomain = (\mb_strpos(
317 $application->cookieDomain,
318 '.'
319 ) === false || StringUtil::endsWith(
320 $application->cookieDomain,
321 '.lan'
322 ) || StringUtil::endsWith($application->cookieDomain, '.local')) ? false : true;
323
324 if (!$addDomain) {
325 return null;
326 }
327
328 $cookieDomain = $application->cookieDomain;
329 if ($addDomain && \strpos($cookieDomain, ':') !== false) {
330 $cookieDomain = \explode(':', $cookieDomain, 2)[0];
331 }
332
333 return $cookieDomain;
334 }
335
336 /**
337 * Sends the headers of a page.
338 */
339 public static function sendHeaders()
340 {
341 // send content type
342 @\header('Content-Type: text/html; charset=UTF-8');
343
344 // send no cache headers
345 if (!PACKAGE_ID || !WCF::getSession()->spiderID) {
346 self::sendNoCacheHeaders();
347 }
348
349 // send X-Frame-Options
350 if (HTTP_SEND_X_FRAME_OPTIONS) {
351 @\header('X-Frame-Options: SAMEORIGIN');
352 }
353
354 \ob_start([self::class, 'parseOutput']);
355 }
356
357 /**
358 * Sends no cache headers.
359 */
360 public static function sendNoCacheHeaders()
361 {
362 @\header('Last-Modified: ' . \gmdate('D, d M Y H:i:s') . ' GMT');
363 @\header('Cache-Control: max-age=0, no-cache, no-store, must-revalidate');
364 }
365
366 /**
367 * @deprecated 5.4 - This method is a no-op, as gzip support was removed.
368 */
369 public static function exceptionDisableGzip()
370 {
371 }
372
373 /**
374 * Parses the rendered output.
375 *
376 * @param string $output
377 * @return string
378 */
379 public static function parseOutput($output)
380 {
381 self::$output = $output;
382
383 if (!PACKAGE_ID || RequestHandler::getInstance()->isACPRequest()) {
384 // force javascript relocation
385 self::$output = \preg_replace('~<script([^>]*)>~', '<script data-relocate="true"\\1>', self::$output);
386 }
387
388 // move script tags to the bottom of the page
389 $javascript = [];
390 self::$output = \preg_replace_callback(
391 '~(?P<conditionBefore><!--\[IF [^<]+\s*)?<script data-relocate="true"(?P<script>.*?</script>\s*)(?P<conditionAfter><!\[ENDIF]-->\s*)?~s',
392 static function ($matches) use (&$javascript) {
393 $match = '';
394 if (isset($matches['conditionBefore'])) {
395 $match .= $matches['conditionBefore'];
396 }
397 $match .= '<script' . $matches['script'];
398 if (isset($matches['conditionAfter'])) {
399 $match .= $matches['conditionAfter'];
400 }
401
402 $javascript[] = $match;
403
404 return '';
405 },
406 self::$output
407 );
408
409 self::$output = \str_replace(
410 '<!-- JAVASCRIPT_RELOCATE_POSITION -->',
411 \implode("\n", $javascript),
412 self::$output
413 );
414
415 // 3rd party plugins may differ the actual output before it is sent to the browser
416 // please be aware, that $eventObj is not available here due to this being a static
417 // class. Use HeaderUtil::$output to modify it.
418 if (!\defined('NO_IMPORTS')) {
419 EventHandler::getInstance()->fireAction(self::class, 'parseOutput');
420 }
421
422 return self::$output;
423 }
424
425 /**
426 * Redirects the user agent to given location.
427 *
428 * @param string $location
429 * @param bool $sendStatusCode
430 * @param bool $temporaryRedirect
431 */
432 public static function redirect($location, $sendStatusCode = false, $temporaryRedirect = true)
433 {
434 // https://github.com/WoltLab/WCF/issues/2568
435 if (SessionHandler::getInstance()->isFirstVisit()) {
436 SessionHandler::getInstance()->register('__wcfIsFirstVisit', true);
437 }
438
439 if ($sendStatusCode) {
440 if ($temporaryRedirect) {
441 @\header('HTTP/1.1 307 Temporary Redirect');
442 } else {
443 @\header('HTTP/1.1 301 Moved Permanently');
444 }
445 }
446
447 \header('Location: ' . $location);
448 }
449
450 /**
451 * Does a delayed redirect.
452 *
453 * @param string $location
454 * @param string $message
455 * @param int $delay
456 * @param string $status
457 */
458 public static function delayedRedirect($location, $message, $delay = 5, $status = 'success')
459 {
460 WCF::getTPL()->assign([
461 'url' => $location,
462 'message' => $message,
463 'wait' => $delay,
464 'templateName' => 'redirect',
465 'templateNameApplication' => 'wcf',
466 'status' => $status,
467 ]);
468 WCF::getTPL()->display('redirect');
469 }
470
471 /**
472 * Forbid creation of HeaderUtil objects.
473 */
474 private function __construct()
475 {
476 // does nothing
477 }
478}
479\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0lib/system/package/plugin/AbstractPackageInstallationPlugin.class.php\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000770\00001750\00000056\000000006165\014043741530\0026525\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0timwolla\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0plugdev\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<?php
480
481namespace wcf\system\package\plugin;
482
483use wcf\system\event\EventHandler;
484use wcf\system\package\PackageArchive;
485use wcf\system\package\PackageInstallationDispatcher;
486use wcf\system\WCF;
487
488/**
489 * Abstract implementation of a package installation plugin.
490 *
491 * @author Alexander Ebert
492 * @copyright 2001-2019 WoltLab GmbH
493 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
494 * @package WoltLabSuite\Core\System\Package\Plugin
495 */
496abstract class AbstractPackageInstallationPlugin implements IPackageInstallationPlugin
497{
498 /**
499 * table application prefix
500 * @var string
501 */
502 public $application = 'wcf';
503
504 /**
505 * database table name
506 * @var string
507 */
508 public $tableName = '';
509
510 /**
511 * active instance of PackageInstallationDispatcher
512 * @var PackageInstallationDispatcher
513 */
514 public $installation;
515
516 /**
517 * install/update instructions
518 * @var array
519 */
520 public $instruction = [];
521
522 /**
523 * Creates a new AbstractPackageInstallationPlugin object.
524 *
525 * @param PackageInstallationDispatcher $installation
526 * @param array $instruction
527 */
528 public function __construct(PackageInstallationDispatcher $installation, $instruction = [])
529 {
530 $this->installation = $installation;
531 $this->instruction = $instruction;
532
533 // call 'construct' event
534 EventHandler::getInstance()->fireAction($this, 'construct');
535 }
536
537 /**
538 * @inheritDoc
539 */
540 public function install()
541 {
542 // call 'install' event
543 EventHandler::getInstance()->fireAction($this, 'install');
544 }
545
546 /**
547 * @inheritDoc
548 */
549 public function update()
550 {
551 // call 'update' event
552 EventHandler::getInstance()->fireAction($this, 'update');
553
554 return $this->install();
555 }
556
557 /**
558 * @inheritDoc
559 */
560 public function hasUninstall()
561 {
562 // call 'hasUninstall' event
563 EventHandler::getInstance()->fireAction($this, 'hasUninstall');
564
565 $sql = "SELECT COUNT(*)
566 FROM " . $this->application . WCF_N . "_" . $this->tableName . "
567 WHERE packageID = ?";
568 $statement = WCF::getDB()->prepareStatement($sql);
569 $statement->execute([$this->installation->getPackageID()]);
570
571 return $statement->fetchSingleColumn() > 0;
572 }
573
574 /**
575 * @inheritDoc
576 */
577 public function uninstall()
578 {
579 // call 'uninstall' event
580 EventHandler::getInstance()->fireAction($this, 'uninstall');
581
582 $sql = "DELETE FROM " . $this->application . WCF_N . "_" . $this->tableName . "
583 WHERE packageID = ?";
584 $statement = WCF::getDB()->prepareStatement($sql);
585 $statement->execute([$this->installation->getPackageID()]);
586 }
587
588 /**
589 * @see \wcf\system\package\plugin\IPackageInstallationPlugin::getDefaultFilename()
590 * @since 3.0
591 */
592 public static function getDefaultFilename()
593 {
594 return null;
595 }
596
597 /**
598 * @inheritDoc
599 */
600 public static function isValid(PackageArchive $archive, $instruction)
601 {
602 return true;
603 }
604}
605\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0lib/system/package/plugin/DatabasePackageInstallationPlugin.class.php\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000770\00001750\00000056\000000006030\014043741530\0026455\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0timwolla\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0plugdev\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<?php
606
607namespace wcf\system\package\plugin;
608
609use wcf\system\database\table\DatabaseTableChangeProcessor;
610use wcf\system\devtools\pip\IIdempotentPackageInstallationPlugin;
611use wcf\system\WCF;
612use wcf\util\FileUtil;
613
614/**
615 * Executes individual database scripts during installation.
616 *
617 * @author Matthias Schmidt
618 * @copyright 2001-2021 WoltLab GmbH
619 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
620 * @package WoltLabSuite\Core\System\Package\Plugin
621 */
622class DatabasePackageInstallationPlugin extends AbstractPackageInstallationPlugin implements IIdempotentPackageInstallationPlugin
623{
624 public const SCRIPT_DIR = 'acp/database/';
625
626 /**
627 * @inheritDoc
628 */
629 public function install()
630 {
631 parent::install();
632
633 $abbreviation = 'wcf';
634 $path = '';
635 if (isset($this->instruction['attributes']['application'])) {
636 $abbreviation = $this->instruction['attributes']['application'];
637 } elseif ($this->installation->getPackage()->isApplication) {
638 $path = FileUtil::getRealPath(WCF_DIR . $this->installation->getPackage()->packageDir);
639 }
640
641 if (empty($path)) {
642 $dirConstant = \strtoupper($abbreviation) . '_DIR';
643 if (!\defined($dirConstant)) {
644 throw new \InvalidArgumentException("Cannot execute database PIP, abbreviation '{$abbreviation}' is unknown.");
645 }
646
647 $path = \constant($dirConstant);
648 }
649
650 $scriptPath = $path . $this->instruction['value'];
651
652 $this->updateDatabase($scriptPath);
653
654 if (@\unlink($scriptPath)) {
655 $sql = "DELETE FROM wcf" . WCF_N . "_package_installation_file_log
656 WHERE packageID = ?
657 AND filename = ?";
658 $statement = WCF::getDB()->prepareStatement($sql);
659 $statement->execute([
660 $this->installation->getPackageID(),
661 $this->instruction['value'],
662 ]);
663 }
664 }
665
666 /**
667 * Runs the database script at the given path.
668 *
669 * @param string $scriptPath
670 */
671 private function updateDatabase(string $scriptPath): void
672 {
673 $tables = include($scriptPath);
674 if (!\is_array($tables)) {
675 throw new \UnexpectedValueException("A database script must return an array.");
676 }
677
678 (new DatabaseTableChangeProcessor(
679 $this->installation->getPackage(),
680 $tables,
681 WCF::getDB()->getEditor()
682 ))->process();
683 }
684
685 /**
686 * @inheritDoc
687 */
688 public function hasUninstall()
689 {
690 // Database scripts cannot be uninstalled.
691 return false;
692 }
693
694 /**
695 * @inheritDoc
696 */
697 public function uninstall()
698 {
699 // does nothing
700 }
701
702 /**
703 * @inheritDoc
704 */
705 public static function getDefaultFilename()
706 {
707 return static::SCRIPT_DIR . '*.php';
708 }
709
710 /**
711 * @inheritDoc
712 */
713 public static function getSyncDependencies()
714 {
715 return ['file'];
716 }
717}
718\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0lib/system/package/plugin/FilePackageInstallationPlugin.class.php\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000770\00001750\00000056\000000011740\014043741530\0025634\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0timwolla\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0plugdev\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<?php
719
720namespace wcf\system\package\plugin;
721
722use wcf\data\application\Application;
723use wcf\data\package\Package;
724use wcf\system\devtools\pip\IIdempotentPackageInstallationPlugin;
725use wcf\system\exception\SystemException;
726use wcf\system\package\FilesFileHandler;
727use wcf\system\package\PackageArchive;
728use wcf\system\package\PackageInstallationDispatcher;
729use wcf\system\style\StyleHandler;
730use wcf\system\WCF;
731
732/**
733 * Installs, updates and deletes files.
734 *
735 * @author Matthias Schmidt, Marcel Werk
736 * @copyright 2001-2019 WoltLab GmbH
737 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
738 * @package WoltLabSuite\Core\System\Package\Plugin
739 */
740class FilePackageInstallationPlugin extends AbstractPackageInstallationPlugin implements
741 IIdempotentPackageInstallationPlugin
742{
743 /**
744 * @inheritDoc
745 */
746 public $tableName = 'package_installation_file_log';
747
748 /**
749 * @inheritDoc
750 */
751 public function install()
752 {
753 parent::install();
754
755 $abbreviation = 'wcf';
756 if (isset($this->instruction['attributes']['application'])) {
757 $abbreviation = $this->instruction['attributes']['application'];
758 } elseif ($this->installation->getPackage()->isApplication) {
759 $abbreviation = Package::getAbbreviation($this->installation->getPackage()->package);
760 }
761
762 // absolute path to package dir
763 $packageDir = Application::getDirectory($abbreviation);
764
765 // extract files.tar to temp folder
766 $sourceFile = $this->installation->getArchive()->extractTar($this->instruction['value'], 'files_');
767
768 // create file handler
769 $fileHandler = new FilesFileHandler($this->installation, $abbreviation);
770
771 // extract content of files.tar
772 $fileInstaller = $this->installation->extractFiles($packageDir, $sourceFile, $fileHandler);
773
774 // if this is an application, write config.inc.php for this package
775 if (
776 $this->installation->getPackage()->isApplication == 1
777 && $this->installation->getPackage()->package != 'com.woltlab.wcf'
778 && $this->installation->getAction() == 'install'
779 && $abbreviation != 'wcf'
780 ) {
781 // touch file
782 $fileInstaller->touchFile(PackageInstallationDispatcher::CONFIG_FILE);
783
784 // create file
785 Package::writeConfigFile($this->installation->getPackageID());
786
787 // log files
788 $sql = "INSERT INTO wcf" . WCF_N . "_package_installation_file_log
789 (packageID, filename, application)
790 VALUES (?, ?, ?)";
791 $statement = WCF::getDB()->prepareStatement($sql);
792 $statement->execute([
793 $this->installation->getPackageID(),
794 'config.inc.php',
795 Package::getAbbreviation($this->installation->getPackage()->package),
796 ]);
797 $statement->execute([
798 $this->installation->getPackageID(),
799 PackageInstallationDispatcher::CONFIG_FILE,
800 Package::getAbbreviation($this->installation->getPackage()->package),
801 ]);
802
803 // load application
804 WCF::loadRuntimeApplication($this->installation->getPackageID());
805 }
806
807 // delete temporary sourceArchive
808 @\unlink($sourceFile);
809
810 StyleHandler::resetStylesheets(true);
811 }
812
813 /**
814 * @inheritDoc
815 */
816 public function uninstall()
817 {
818 // fetch files from log
819 $sql = "SELECT filename, application
820 FROM wcf" . WCF_N . "_package_installation_file_log
821 WHERE packageID = ?";
822 $statement = WCF::getDB()->prepareStatement($sql);
823 $statement->execute([$this->installation->getPackageID()]);
824 $files = $statement->fetchMap('application', 'filename', false);
825
826 foreach ($files as $application => $filenames) {
827 /** @noinspection PhpUndefinedMethodInspection */
828 $this->installation->deleteFiles(Application::getDirectory($application), $filenames);
829
830 // delete log entries
831 parent::uninstall();
832 }
833 }
834
835 /**
836 * @inheritDoc
837 */
838 public static function getDefaultFilename()
839 {
840 return 'files.tar';
841 }
842
843 /**
844 * @inheritDoc
845 */
846 public static function isValid(PackageArchive $archive, $instruction)
847 {
848 if (!$instruction) {
849 $instruction = static::getDefaultFilename();
850 }
851
852 if (\preg_match('~\.(tar(\.gz)?|tgz)$~', $instruction)) {
853 // check if file actually exists
854 try {
855 if ($archive->getTar()->getIndexByFilename($instruction) === false) {
856 return false;
857 }
858 } catch (SystemException $e) {
859 return false;
860 }
861
862 return true;
863 }
864
865 return false;
866 }
867
868 /**
869 * @inheritDoc
870 */
871 public static function getSyncDependencies()
872 {
873 return ['option'];
874 }
875}
876\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0lib/system/package/plugin/ScriptPackageInstallationPlugin.class.php\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000770\00001750\00000056\000000005426\014043741531\0026226\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0timwolla\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0plugdev\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<?php
877
878namespace wcf\system\package\plugin;
879
880use wcf\system\cache\CacheHandler;
881use wcf\system\exception\SystemException;
882use wcf\system\form\FormDocument;
883use wcf\system\WCF;
884use wcf\util\FileUtil;
885
886/**
887 * Executes individual PHP scripts during installation.
888 *
889 * @author Alexander Ebert
890 * @copyright 2001-2019 WoltLab GmbH
891 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
892 * @package WoltLabSuite\Core\System\Package\Plugin
893 */
894class ScriptPackageInstallationPlugin extends AbstractPackageInstallationPlugin
895{
896 /**
897 * @inheritDoc
898 */
899 public function install()
900 {
901 parent::install();
902
903 $abbreviation = 'wcf';
904 $path = '';
905 if (isset($this->instruction['attributes']['application'])) {
906 $abbreviation = $this->instruction['attributes']['application'];
907 } elseif ($this->installation->getPackage()->isApplication) {
908 $path = FileUtil::getRealPath(WCF_DIR . $this->installation->getPackage()->packageDir);
909 }
910
911 if (empty($path)) {
912 $dirConstant = \strtoupper($abbreviation) . '_DIR';
913 if (!\defined($dirConstant)) {
914 throw new SystemException("Cannot execute script-PIP, abbreviation '" . $abbreviation . "' is unknown");
915 }
916
917 $path = \constant($dirConstant);
918 }
919
920 $flushCache = true;
921 if (
922 isset($this->instruction['attributes']['flushCache'])
923 && $this->instruction['attributes']['flushCache'] === 'false'
924 ) {
925 $flushCache = false;
926 }
927
928 // reset WCF cache
929 if ($flushCache) {
930 CacheHandler::getInstance()->flushAll();
931 }
932
933 // run script
934 $result = $this->run($path . $this->instruction['value']);
935
936 // delete script
937 if (!($result instanceof FormDocument) && @\unlink($path . $this->instruction['value'])) {
938 // delete file log entry
939 $sql = "DELETE FROM wcf" . WCF_N . "_package_installation_file_log
940 WHERE packageID = ?
941 AND filename = ?";
942 $statement = WCF::getDB()->prepareStatement($sql);
943 $statement->execute([
944 $this->installation->getPackageID(),
945 $this->instruction['value'],
946 ]);
947 }
948
949 return $result;
950 }
951
952 /**
953 * Runs the script with the given path.
954 *
955 * @param string $scriptPath
956 */
957 private function run($scriptPath)
958 {
959 return include($scriptPath);
960 }
961
962 /**
963 * @inheritDoc
964 */
965 public function hasUninstall()
966 {
967 // scripts can't be uninstalled
968 return false;
969 }
970
971 /**
972 * @inheritDoc
973 */
974 public function uninstall()
975 {
976 // does nothing
977 }
978}
979\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0