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

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

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