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