PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 10.10.2
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v10.10.2
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
acymailing / back / Controllers / Configuration / Security.php

Security.php in AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress 10.10.2, at back/Controllers/Configuration/Security.php

601 lines 23.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 }
601