PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.1.1
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.1.1
11.1.1 11.1.0 11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 All 62 releases
← All changes | back/Controllers/Configuration/Security.php +0 -600 10.10.2 → 11.1.1 View file →
@@ -1,600 +1,0 @@
1 -<?php
2 -
3 -namespace AcyMailing\Controllers\Configuration;
4 -
5 -use AcyMailing\Classes\UrlClass;
6 -use AcyMailing\Classes\UserClass;
7 -
8 -trait Security
9 -{
10 - private array $messagesNoHtml = [];
11 -
12 - public function checkDBAjax(): void
13 - {
14 - $this->checkDB();
15 -
16 - if (empty($this->messagesNoHtml)) {
17 - echo '<i class="acymicon-check-circle acym__color__green"></i>';
18 - } else {
19 - $nbMessages = count($this->messagesNoHtml);
20 - foreach ($this->messagesNoHtml as $i => $oneMsg) {
21 - echo '<span style="color:'.$oneMsg['color'].'">'.$oneMsg['msg'].'</span>';
22 -
23 - if ($i < $nbMessages) {
24 - echo '<br />';
25 - }
26 - }
27 - }
28 -
29 - exit;
30 - }
31 -
32 - public function checkDB(bool $fromConfiguration = true): array
33 - {
34 - $correctTablesStructure = $this->getCorrectTablesStructure();
35 - $currentTablesStructure = $this->getCurrentTablesStructure($correctTablesStructure);
36 - $this->fixCurrentStructure($correctTablesStructure, $currentTablesStructure);
37 -
38 - $this->cleanDuplicatedUrls($fromConfiguration);
39 - $this->addMissingUserKeys();
40 -
41 - return $this->messagesNoHtml;
42 - }
43 -
44 - private function getCorrectTablesStructure(): array
45 - {
46 - $correctTablesStructure = [
47 - 'structure' => [],
48 - 'createTable' => [],
49 - 'indexes' => [],
50 - 'constraints' => [],
51 - ];
52 -
53 - $queries = file_get_contents(ACYM_BACK.'tables.sql');
54 - $tables = explode('CREATE TABLE IF NOT EXISTS ', $queries);
55 -
56 - foreach ($tables as $oneTable) {
57 - if (strpos($oneTable, '`#__') !== 0) {
58 - continue;
59 - }
60 -
61 - $tableName = substr($oneTable, 1, strpos($oneTable, '`', 1) - 1);
62 - $correctTablesStructure['createTable'][$tableName] = 'CREATE TABLE IF NOT EXISTS '.$oneTable;
63 - $correctTablesStructure['indexes'][$tableName] = [];
64 - $correctTablesStructure['constraints'][$tableName] = [];
65 -
66 - $fields = explode("\n", $oneTable);
67 - foreach ($fields as $key => $oneField) {
68 - if (strpos($oneField, '#__') === 1) {
69 - continue;
70 - }
71 - $oneField = rtrim(trim($oneField), ',');
72 -
73 - if (substr($oneField, 0, 1) === '`') {
74 - $columnName = substr($oneField, 1, strpos($oneField, '`', 1) - 1);
75 - $correctTablesStructure['structure'][$tableName][$columnName] = trim($oneField, ',');
76 - continue;
77 - }
78 -
79 - if (strpos($oneField, 'PRIMARY KEY') === 0) {
80 - $correctTablesStructure['indexes'][$tableName]['PRIMARY'] = $oneField;
81 - } elseif (strpos($oneField, 'INDEX') === 0) {
82 - $firstBackquotePos = strpos($oneField, '`');
83 - $indexName = substr($oneField, $firstBackquotePos + 1, strpos($oneField, '`', $firstBackquotePos + 1) - $firstBackquotePos - 1);
84 -
85 - $correctTablesStructure['indexes'][$tableName][$indexName] = $oneField;
86 - } elseif (strpos($oneField, 'FOREIGN KEY') !== false) {
87 - preg_match('/(#__fk.*)\`/Uis', $fields[$key - 1], $matchesConstraints);
88 - preg_match('/(#__.*)\`\(`(.*)`\)/Uis', $fields[$key + 1], $matchesTable);
89 - preg_match('/\`(.*)\`/Uis', $oneField, $matchesColumn);
90 - if (!empty($matchesConstraints) && !empty($matchesTable) && !empty($matchesColumn)) {
91 - $correctTablesStructure['constraints'][$tableName][$matchesConstraints[1]] = [
92 - 'table' => $matchesTable[1],
93 - 'column' => $matchesColumn[1],
94 - 'table_column' => $matchesTable[2],
95 - ];
96 - }
97 - }
98 - }
99 - }
100 -
101 - $correctTablesStructure['tableNames'] = array_keys($correctTablesStructure['structure']);
102 -
103 - return $correctTablesStructure;
104 - }
105 -
106 - private function getCurrentTablesStructure(array $correctTablesStructure): array
107 - {
108 - $currentTablesStructure = [];
109 -
110 - foreach ($correctTablesStructure['tableNames'] as $oneTableName) {
111 - try {
112 - $columns = acym_loadObjectList('SHOW COLUMNS FROM '.$oneTableName);
113 - } catch (\Exception $e) {
114 - $columns = null;
115 - }
116 -
117 - if (!empty($columns)) {
118 - foreach ($columns as $oneField) {
119 - $currentTablesStructure[$oneTableName][$oneField->Field] = $oneField->Field;
120 - }
121 - continue;
122 - }
123 -
124 - $errorMessage = (isset($e) ? $e->getMessage() : substr(strip_tags(acym_getDBError()), 0, 200));
125 - $this->messagesNoHtml[] = [
126 - 'error' => false,
127 - 'color' => 'blue',
128 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_LOAD_COLUMNS_ERROR', $oneTableName, $errorMessage),
129 - ];
130 -
131 - if (strpos($errorMessage, 'marked as crashed')) {
132 - try {
133 - $isError = acym_query('REPAIR TABLE '.$oneTableName);
134 - } catch (\Exception $e) {
135 - $isError = null;
136 - }
137 -
138 - if ($isError === null) {
139 - $errorMessage = (isset($e) ? $e->getMessage() : substr(strip_tags(acym_getDBError()), 0, 200));
140 - $this->messagesNoHtml[] = [
141 - 'error' => true,
142 - 'color' => 'red',
143 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_REPAIR_TABLE_ERROR', $oneTableName, $errorMessage),
144 - ];
145 - } else {
146 - $this->messagesNoHtml[] = [
147 - 'error' => false,
148 - 'color' => 'green',
149 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_REPAIR_TABLE_SUCCESS', $oneTableName),
150 - ];
151 - }
152 - continue;
153 - } else {
154 - try {
155 - $isError = acym_query($correctTablesStructure['createTable'][$oneTableName]);
156 - } catch (\Exception $e) {
157 - $isError = null;
158 - }
159 -
160 - if ($isError === null) {
161 - $errorMessage = (isset($e) ? $e->getMessage() : substr(strip_tags(acym_getDBError()), 0, 200));
162 - $this->messagesNoHtml[] = [
163 - 'error' => true,
164 - 'color' => 'red',
165 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_CREATE_TABLE_ERROR', $oneTableName, $errorMessage),
166 - ];
167 - } else {
168 - $this->messagesNoHtml[] = [
169 - 'error' => false,
170 - 'color' => 'green',
171 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_CREATE_TABLE_SUCCESS', $oneTableName),
172 - ];
173 - }
174 - }
175 - }
176 -
177 - return $currentTablesStructure;
178 - }
179 -
180 - private function fixCurrentStructure(array $correctTablesStructure, array $currentTablesStructure): void
181 - {
182 - foreach ($correctTablesStructure['tableNames'] as $oneTableName) {
183 - if (empty($currentTablesStructure[$oneTableName])) {
184 - continue;
185 - }
186 -
187 - $this->addMissingColumns($correctTablesStructure['structure'][$oneTableName], $currentTablesStructure[$oneTableName], $oneTableName);
188 - $this->removeExtraColumns($correctTablesStructure['structure'][$oneTableName], $currentTablesStructure[$oneTableName], $oneTableName);
189 - $this->fixDefaultValues($correctTablesStructure['structure'][$oneTableName], $oneTableName);
190 - $this->addMissingTableKeys($correctTablesStructure['indexes'][$oneTableName], $oneTableName);
191 - $this->addMissingTableConstraints($correctTablesStructure['constraints'][$oneTableName], $oneTableName);
192 - }
193 - }
194 -
195 - private function addMissingColumns(array $correctTableColumns, array $currentTableColumnNames, string $oneTableName): void
196 - {
197 - $idealColumnNames = array_keys($correctTableColumns);
198 - $missingColumns = array_diff($idealColumnNames, $currentTableColumnNames);
199 -
200 - if (empty($missingColumns)) {
201 - return;
202 - }
203 -
204 - foreach ($missingColumns as $oneColumn) {
205 - $this->messagesNoHtml[] = [
206 - 'error' => false,
207 - 'color' => 'blue',
208 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_MISSING_COLUMN', $oneColumn, $oneTableName),
209 - ];
210 -
211 - try {
212 - $isError = acym_query('ALTER TABLE '.$oneTableName.' ADD '.$correctTableColumns[$oneColumn]);
213 - } catch (\Exception $e) {
214 - $isError = null;
215 - }
216 -
217 - if ($isError === null) {
218 - $errorMessage = (isset($e) ? $e->getMessage() : substr(strip_tags(acym_getDBError()), 0, 200));
219 - $this->messagesNoHtml[] = [
220 - 'error' => true,
221 - 'color' => 'red',
222 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_ADD_COLUMN_ERROR', $oneColumn, $oneTableName, $errorMessage),
223 - ];
224 - } else {
225 - $this->messagesNoHtml[] = [
226 - 'error' => false,
227 - 'color' => 'green',
228 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_ADD_COLUMN_SUCCESS', $oneColumn, $oneTableName),
229 - ];
230 - }
231 - }
232 - }
233 -
234 - private function removeExtraColumns(array $correctTableColumns, array $currentTableColumnNames, string $oneTableName): void
235 - {
236 - $idealColumnNames = array_keys($correctTableColumns);
237 - $extraColumns = array_diff($currentTableColumnNames, $idealColumnNames);
238 -
239 - if (empty($extraColumns)) {
240 - return;
241 - }
242 -
243 - foreach ($extraColumns as $oneColumn) {
244 - $this->messagesNoHtml[] = [
245 - 'error' => false,
246 - 'color' => 'blue',
247 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_EXTRA_COLUMN', $oneColumn, $oneTableName),
248 - ];
249 -
250 - try {
251 - $isError = acym_query('ALTER TABLE '.$oneTableName.' DROP COLUMN `'.acym_secureDBColumn($oneColumn).'`');
252 - } catch (\Exception $e) {
253 - $isError = null;
254 - }
255 -
256 - if ($isError === null) {
257 - $errorMessage = (isset($e) ? $e->getMessage() : substr(strip_tags(acym_getDBError()), 0, 200));
258 - $this->messagesNoHtml[] = [
259 - 'error' => true,
260 - 'color' => 'red',
261 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_EXTRA_COLUMN_ERROR', $oneColumn, $oneTableName, $errorMessage),
262 - ];
263 - } else {
264 - $this->messagesNoHtml[] = [
265 - 'error' => false,
266 - 'color' => 'green',
267 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_EXTRA_COLUMN_SUCCESS', $oneColumn, $oneTableName),
268 - ];
269 - }
270 - }
271 - }
272 -
273 - private function fixDefaultValues(array $correctTableColumns, string $oneTableName): void
274 - {
275 - $oneTableName = str_replace('#__', acym_getPrefix(), $oneTableName);
276 - try {
277 - $currentTableColumns = acym_loadObjectList(
278 - 'SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, COLUMN_TYPE
279 - FROM information_schema.COLUMNS
280 - WHERE TABLE_SCHEMA = DATABASE()
281 - AND TABLE_NAME = '.acym_escapeDB($oneTableName),
282 - 'COLUMN_NAME'
283 - );
284 -
285 - if (empty($currentTableColumns)) {
286 - return;
287 - }
288 - } catch (\Exception $e) {
289 - $this->messagesNoHtml[] = [
290 - 'error' => true,
291 - 'color' => 'orange',
292 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_ERROR_GET_COLUMNS', $oneTableName, $e->getMessage()),
293 - ];
294 -
295 - return;
296 - }
297 -
298 - foreach ($correctTableColumns as $oneColumn => $oneColumnDefinition) {
299 - $defaultValue = '';
300 - if (preg_match('#DEFAULT ([^ ]+)$#Ui', $oneColumnDefinition, $matches)) {
301 - $defaultValue = $matches[1];
302 - }
303 -
304 - if (strlen($defaultValue) === 0) {
305 - continue;
306 - }
307 - $currentDefault = $currentTableColumns[$oneColumn]->COLUMN_DEFAULT;
308 - if (!empty($currentDefault)) {
309 - $currentDefault = trim($currentDefault, "'\"");
310 - }
311 - $expectedDefault = trim($defaultValue, "'\"");
312 -
313 - if (strtoupper($expectedDefault) === 'NULL') {
314 - $expectedDefault = null;
315 - }
316 -
317 - $isNullable = strtoupper($currentTableColumns[$oneColumn]->IS_NULLABLE) === 'YES';
318 -
319 - if ($isNullable && $currentDefault === '') {
320 - $currentDefault = null;
321 - }
322 -
323 - if (!$isNullable && $currentDefault === null) {
324 - $currentDefault = '';
325 - }
326 -
327 - if ($currentDefault === $expectedDefault) {
328 - continue;
329 - }
330 -
331 - if (!empty($currentTableColumns[$oneColumn]->COLUMN_DEFAULT) && substr($currentTableColumns[$oneColumn]->COLUMN_DEFAULT, 0, 1) === '"') {
332 - $currentTableColumns[$oneColumn]->COLUMN_DEFAULT = '\''.substr($currentTableColumns[$oneColumn]->COLUMN_DEFAULT, 1, -1).'\'';
333 - }
334 -
335 - $isColumnDefaultEmpty = empty($currentTableColumns[$oneColumn]->COLUMN_DEFAULT) && $currentTableColumns[$oneColumn]->COLUMN_DEFAULT !== '0';
336 -
337 - if (!$isColumnDefaultEmpty && $currentTableColumns[$oneColumn]->COLUMN_DEFAULT === $defaultValue) {
338 - continue;
339 - }
340 -
341 - $this->messagesNoHtml[] = [
342 - 'error' => false,
343 - 'color' => 'blue',
344 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_WRONG_DEFAULT_VALUE', $oneColumn, $oneTableName),
345 - ];
346 -
347 - try {
348 - $isError = acym_query('ALTER TABLE '.$oneTableName.' CHANGE `'.acym_secureDBColumn($oneColumn).'` '.$oneColumnDefinition);
349 - } catch (\Exception $e) {
350 - $isError = null;
351 - }
352 -
353 - if ($isError === null) {
354 - $errorMessage = (isset($e) ? $e->getMessage() : substr(strip_tags(acym_getDBError()), 0, 200));
355 - $this->messagesNoHtml[] = [
356 - 'error' => true,
357 - 'color' => 'red',
358 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_WRONG_DEFAULT_VALUE_ERROR', $oneColumn, $oneTableName, $errorMessage),
359 - ];
360 - } else {
361 - $this->messagesNoHtml[] = [
362 - 'error' => false,
363 - 'color' => 'green',
364 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_WRONG_DEFAULT_VALUE_SUCCESS', $oneColumn, $oneTableName),
365 - ];
366 - }
367 - }
368 - }
369 -
370 - private function addMissingTableKeys(array $correctTableIndexes, string $oneTableName): void
371 - {
372 - $results = acym_loadObjectList('SHOW INDEX FROM '.$oneTableName, 'Key_name');
373 - if (empty($results)) {
374 - $results = [];
375 - }
376 -
377 - foreach ($correctTableIndexes as $name => $query) {
378 - $name = acym_prepareQuery($name);
379 - if (in_array($name, array_keys($results))) {
380 - continue;
381 - }
382 -
383 -
384 - $keyName = $name === 'PRIMARY' ? 'primary key' : 'index '.$name;
385 -
386 - $this->messagesNoHtml[] = [
387 - 'error' => false,
388 - 'color' => 'blue',
389 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_MISSING_INDEX', $keyName, $oneTableName),
390 - ];
391 -
392 - try {
393 - $isError = acym_query('ALTER TABLE '.$oneTableName.' ADD '.$query);
394 - } catch (\Exception $e) {
395 - $isError = null;
396 - }
397 -
398 - if ($isError === null) {
399 - $errorMessage = (isset($e) ? $e->getMessage() : substr(strip_tags(acym_getDBError()), 0, 200));
400 - $this->messagesNoHtml[] = [
401 - 'error' => true,
402 - 'color' => 'red',
403 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_ADD_INDEX_ERROR', $keyName, $oneTableName, $errorMessage),
404 - ];
405 - } else {
406 - $this->messagesNoHtml[] = [
407 - 'error' => false,
408 - 'color' => 'green',
409 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_ADD_INDEX_SUCCESS', $keyName, $oneTableName),
410 - ];
411 - }
412 - }
413 - }
414 -
415 - private function addMissingTableConstraints(array $correctTableConstraints, string $oneTableName): void
416 - {
417 - if (empty($correctTableConstraints)) {
418 - return;
419 - }
420 -
421 - $tableNameQuery = str_replace('#__', acym_getPrefix(), $oneTableName);
422 - $databaseName = acym_loadResult('SELECT DATABASE();');
423 - $foreignKeys = acym_loadObjectList(
424 - 'SELECT i.CONSTRAINT_NAME, k.REFERENCED_TABLE_NAME, k.REFERENCED_COLUMN_NAME, k.COLUMN_NAME
425 - FROM information_schema.TABLE_CONSTRAINTS AS i
426 - JOIN information_schema.KEY_COLUMN_USAGE AS k ON i.CONSTRAINT_NAME = k.CONSTRAINT_NAME
427 - WHERE i.TABLE_NAME = '.acym_escapeDB($tableNameQuery).' AND i.CONSTRAINT_TYPE = "FOREIGN KEY" AND i.TABLE_SCHEMA = '.acym_escapeDB($databaseName),
428 - 'CONSTRAINT_NAME'
429 - );
430 -
431 - acym_query('SET foreign_key_checks = 0');
432 -
433 - foreach ($correctTableConstraints as $constraintName => $constraintInfo) {
434 - $constraintTableNamePrefix = str_replace('#__', acym_getPrefix(), $constraintInfo['table']);
435 - $constraintName = str_replace('#__', acym_getPrefix(), $constraintName);
436 -
437 - if (!empty($foreignKeys[$constraintName]) && $foreignKeys[$constraintName]->REFERENCED_TABLE_NAME === $constraintTableNamePrefix && $foreignKeys[$constraintName]->REFERENCED_COLUMN_NAME === $constraintInfo['table_column'] && $foreignKeys[$constraintName]->COLUMN_NAME === $constraintInfo['column']) {
438 - continue;
439 - }
440 -
441 - $this->messagesNoHtml[] = [
442 - 'error' => false,
443 - 'color' => 'blue',
444 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_WRONG_FOREIGN_KEY', $constraintName, $oneTableName),
445 - ];
446 -
447 - if (!empty($foreignKeys[$constraintName])) {
448 - try {
449 - $isError = acym_query('ALTER TABLE `'.$oneTableName.'` DROP FOREIGN KEY `'.$constraintName.'`');
450 - } catch (\Exception $e) {
451 - $isError = null;
452 - }
453 -
454 - if ($isError === null) {
455 - $errorMessage = (isset($e) ? $e->getMessage() : substr(strip_tags(acym_getDBError()), 0, 200));
456 - $this->messagesNoHtml[] = [
457 - 'error' => true,
458 - 'color' => 'red',
459 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_ADD_FOREIGN_KEY_ERROR', $constraintName, $oneTableName, $errorMessage),
460 - ];
461 - continue;
462 - }
463 - }
464 -
465 - try {
466 - $isError = acym_query(
467 - 'ALTER TABLE `'.$oneTableName.'` ADD CONSTRAINT `'.$constraintName.'` FOREIGN KEY (`'.$constraintInfo['column'].'`) REFERENCES `'.$constraintInfo['table'].'` (`'.$constraintInfo['table_column'].'`) ON DELETE NO ACTION ON UPDATE NO ACTION;'
468 - );
469 - } catch (\Exception $e) {
470 - $isError = null;
471 - }
472 -
473 - if ($isError === null) {
474 - $errorMessage = (isset($e) ? $e->getMessage() : substr(strip_tags(acym_getDBError()), 0, 200));
475 - $this->messagesNoHtml[] = [
476 - 'error' => true,
477 - 'color' => 'red',
478 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_ADD_FOREIGN_KEY_ERROR', $constraintName, $oneTableName, $errorMessage),
479 - ];
480 - } else {
481 - $this->messagesNoHtml[] = [
482 - 'error' => false,
483 - 'color' => 'green',
484 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_ADD_FOREIGN_KEY_SUCCESS', $constraintName, $oneTableName),
485 - ];
486 - }
487 - }
488 -
489 - acym_query('SET foreign_key_checks = 1');
490 - }
491 -
492 - private function cleanDuplicatedUrls(bool $fromConfiguration): void
493 - {
494 - if (!$fromConfiguration) {
495 - return;
496 - }
497 -
498 - $urlClass = new UrlClass();
499 - $duplicatedUrls = $urlClass->getDuplicatedUrls();
500 -
501 - if (empty($duplicatedUrls)) {
502 - return;
503 - }
504 -
505 - $maxExecutionTime = intval(ini_get('max_execution_time'));
506 - $time = time();
507 - $interrupted = false;
508 - $this->messagesNoHtml[] = [
509 - 'error' => false,
510 - 'color' => 'blue',
511 - 'msg' => acym_translation('ACYM_CHECKDB_DUPLICATED_URLS'),
512 - ];
513 -
514 - if (empty($maxExecutionTime) || $maxExecutionTime - 20 < 20) {
515 - $maxExecutionTime = 20;
516 - } else {
517 - $maxExecutionTime -= 20;
518 - }
519 -
520 - acym_increasePerf();
521 - while (!empty($duplicatedUrls)) {
522 - $urlClass->delete($duplicatedUrls);
523 -
524 - if (time() - $time > $maxExecutionTime) {
525 - $interrupted = true;
526 - break;
527 - }
528 -
529 - $duplicatedUrls = $urlClass->getDuplicatedUrls();
530 - }
531 -
532 - if (empty($interrupted)) {
533 - $this->messagesNoHtml[] = [
534 - 'error' => false,
535 - 'color' => 'green',
536 - 'msg' => acym_translation('ACYM_CHECKDB_DUPLICATED_URLS_SUCCESS'),
537 - ];
538 - } else {
539 - $this->messagesNoHtml[] = [
540 - 'error' => false,
541 - 'color' => 'blue',
542 - 'msg' => acym_translation('ACYM_CHECKDB_DUPLICATED_URLS_REMAINING'),
543 - ];
544 - }
545 - }
546 -
547 - private function addMissingUserKeys(): void
548 - {
549 - $userClass = new UserClass();
550 - $nbAddedKeys = $userClass->addMissingKeys();
551 -
552 - if (!empty($nbAddedKeys)) {
553 - $this->messagesNoHtml[] = [
554 - 'error' => false,
555 - 'color' => 'green',
556 - 'msg' => acym_translationSprintf('ACYM_CHECKDB_ADDED_KEYS', $nbAddedKeys),
557 - ];
558 - }
559 - }
560 -
561 - public function redomigration(): void
562 - {
563 - $this->config->saveConfig(['migration' => 0]);
564 - acym_redirect(acym_completeLink('dashboard', false, true));
565 - }
566 -
567 - public function scanSiteFiles(): void
568 - {
569 - $maliciousFiles = [];
570 - $siteFiles = acym_getFiles(ACYM_ROOT, '.', true, true);
571 - foreach ($siteFiles as $oneFilePath) {
572 - $lastSlashPos = strrpos($oneFilePath, '/');
573 - if (
574 - !empty($lastSlashPos)
575 - && strpos($oneFilePath, ACYM_UPLOAD_FOLDER_THUMBNAIL) !== false
576 - && preg_match('/.*thumbnail.*php.*$/', substr($oneFilePath, $lastSlashPos + 1))
577 - ) {
578 - $maliciousFiles[] = $oneFilePath;
579 - } elseif (filesize($oneFilePath) < 10000) {
580 - $fileContent = file_get_contents($oneFilePath);
581 - if (preg_match('/^<\?php echo "jm"\."te"\."st"; \?>$/U', $fileContent)) {
582 - $maliciousFiles[] = $oneFilePath;
583 - } elseif (preg_match('/^<\?php\n\$[a-z]+\s*=\s*\$_COOKIE\s*;/Ui', $fileContent)) {
584 - $maliciousFiles[] = $oneFilePath;
585 - }
586 - }
587 - }
588 -
589 - ob_start();
590 - if (!empty($maliciousFiles)) {
591 - $message = acym_translation('ACYM_MALICIOUS_FILES');
592 - $message .= '<ul><li>'.implode('</li><li>', $maliciousFiles).'</li></ul>';
593 - acym_display($message, 'error', false);
594 - } else {
595 - acym_display(acym_translation('ACYM_NO_MALICIOUS_FILES'), 'success', false);
596 - }
597 - $message = ob_get_clean();
598 - acym_sendAjaxResponse($message);
599 - }
600 -}