Skip to content

Commit f483814

Browse files
committed
refactor: ottimizzazione controlli su integrità
1 parent 0c24d5b commit f483814

9 files changed

Lines changed: 1139 additions & 826 deletions

File tree

modules/aggiornamenti/actions.php

Lines changed: 89 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -34,65 +34,102 @@
3434
use Modules\Aggiornamenti\Controlli\TabelleLanguage;
3535
use Modules\Aggiornamenti\UpdateHook;
3636

37+
// ========================================================================
38+
// FUNZIONI HELPER PER VALIDAZIONE QUERY
39+
// ========================================================================
40+
41+
/**
42+
* Definisce i pattern SQL sicuri per la validazione
43+
*/
44+
function getAllowedSqlPatterns()
45+
{
46+
return [
47+
'/^ALTER\s+TABLE\s+`?[\w]+`?\s+(ADD|MODIFY|CHANGE|DROP)\s+(COLUMN\s+)?`?[\w]+`?/i',
48+
'/^CREATE\s+(UNIQUE\s+)?INDEX\s+`?[\w]+`?\s+ON\s+`?[\w]+`?\s*\(/i',
49+
'/^DROP\s+INDEX\s+`?[\w]+`?\s+ON\s+`?[\w]+`?$/i',
50+
'/^UPDATE\s+`?zz_views`?\s+SET\s+/i',
51+
'/^INSERT\s+INTO\s+`?zz_\w+`?\s*\(/i',
52+
'/^DELETE\s+FROM\s+`?zz_\w+`?\s+WHERE\s+/i',
53+
];
54+
}
55+
56+
/**
57+
* Valida una singola query rispetto ai pattern sicuri
58+
*/
59+
function isQuerySafe($query, $allowed_patterns)
60+
{
61+
foreach ($allowed_patterns as $pattern) {
62+
if (preg_match($pattern, trim((string) $query))) {
63+
return true;
64+
}
65+
}
66+
return false;
67+
}
68+
69+
/**
70+
* Filtra le query sicure da quelle pericolose
71+
*/
72+
function filterSafeQueries($queries, $allowed_patterns)
73+
{
74+
$safe_queries = [];
75+
$rejected = [];
76+
77+
foreach ($queries as $query) {
78+
if (isQuerySafe($query, $allowed_patterns)) {
79+
$safe_queries[] = $query;
80+
} else {
81+
$rejected[] = $query;
82+
}
83+
}
84+
85+
return compact('safe_queries', 'rejected');
86+
}
87+
88+
/**
89+
* Esegue le query sicure e ritorna i risultati
90+
*/
91+
function executeQueries($safe_queries, $dbo)
92+
{
93+
$errors = [];
94+
$executed = 0;
95+
96+
foreach ($safe_queries as $query) {
97+
try {
98+
$dbo->query($query);
99+
++$executed;
100+
} catch (Exception) {
101+
$errors[] = tr('Errore durante l\'esecuzione di una query.');
102+
}
103+
}
104+
105+
return compact('errors', 'executed');
106+
}
107+
108+
// ========================================================================
109+
// LOGICA PRINCIPALE
110+
// ========================================================================
111+
37112
$id = post('id');
38113

39114
switch (filter('op')) {
40115
case 'risolvi-conflitti-database':
41116
$queries_json = post('queries');
42117
if (empty($queries_json)) {
43-
echo json_encode([
44-
'success' => false,
45-
'message' => tr('Nessuna query ricevuta.'),
46-
]);
118+
echo json_encode(['success' => false, 'message' => tr('Nessuna query ricevuta.')]);
47119
break;
48120
}
49121

50122
$queries = json_decode($queries_json, true);
51123
if (empty($queries)) {
52-
echo json_encode([
53-
'success' => false,
54-
'message' => tr('Nessuna query da eseguire.'),
55-
]);
124+
echo json_encode(['success' => false, 'message' => tr('Nessuna query da eseguire.')]);
56125
break;
57126
}
58127

59-
if (empty($queries)) {
60-
echo json_encode([
61-
'success' => false,
62-
'message' => tr('Nessuna query valida da eseguire.'),
63-
]);
64-
break;
65-
}
66-
67-
// TODO: Blindare maggiormente le query che il gestionale ha generato per la correzione dei conflitti a database
68-
// WHITELIST: Permetti solo pattern SQL sicuri
69-
$allowed_patterns = [
70-
'/^ALTER\s+TABLE\s+`?[\w]+`?\s+(ADD|MODIFY|CHANGE|DROP)\s+(COLUMN\s+)?`?[\w]+`?/i',
71-
'/^CREATE\s+(UNIQUE\s+)?INDEX\s+`?[\w]+`?\s+ON\s+`?[\w]+`?\s*\(/i',
72-
'/^DROP\s+INDEX\s+`?[\w]+`?\s+ON\s+`?[\w]+`?$/i',
73-
'/^UPDATE\s+`?zz_views`?\s+SET\s+/i',
74-
'/^INSERT\s+INTO\s+`?zz_\w+`?\s*\(/i',
75-
'/^DELETE\s+FROM\s+`?zz_\w+`?\s+WHERE\s+/i',
76-
];
77-
78-
$safe_queries = [];
79-
$rejected = [];
80-
81-
foreach ($queries as $query) {
82-
$is_safe = false;
83-
foreach ($allowed_patterns as $pattern) {
84-
if (preg_match($pattern, trim($query))) {
85-
$is_safe = true;
86-
break;
87-
}
88-
}
89-
90-
if ($is_safe) {
91-
$safe_queries[] = $query;
92-
} else {
93-
$rejected[] = $query;
94-
}
95-
}
128+
// Valida le query
129+
$allowed_patterns = getAllowedSqlPatterns();
130+
$filter_result = filterSafeQueries($queries, $allowed_patterns);
131+
$safe_queries = $filter_result['safe_queries'];
132+
$rejected = $filter_result['rejected'];
96133

97134
if (!empty($rejected)) {
98135
echo json_encode([
@@ -104,36 +141,21 @@
104141
}
105142

106143
if (empty($safe_queries)) {
107-
echo json_encode([
108-
'success' => false,
109-
'message' => tr('Nessuna query valida da eseguire dopo la validazione.'),
110-
]);
144+
echo json_encode(['success' => false, 'message' => tr('Nessuna query valida da eseguire dopo la validazione.')]);
111145
break;
112146
}
113147

148+
// Esegui le query
114149
$debug_queries = implode('<br>', $safe_queries);
115-
116-
$errors = [];
117-
$executed = 0;
118-
119-
foreach ($safe_queries as $query) {
120-
try {
121-
$dbo->query($query);
122-
++$executed;
123-
} catch (Exception $e) {
124-
// Sanifica il messaggio di errore per evitare leak di informazioni
125-
$errors[] = tr('Errore durante l\'esecuzione di una query.');
126-
}
127-
}
150+
$execution_result = executeQueries($safe_queries, $dbo);
151+
$errors = $execution_result['errors'];
152+
$executed = $execution_result['executed'];
128153

129154
if (empty($errors)) {
130-
$success_message = tr('Tutte le query sono state eseguite con successo (_NUM_ query).', [
131-
'_NUM_' => $executed,
132-
]);
133-
155+
$success_message = tr('Tutte le query sono state eseguite con successo (_NUM_ query).', ['_NUM_' => $executed]);
134156
flash()->info($success_message);
135157

136-
// Log dell'operazione di risoluzione conflitti database
158+
// Log dell'operazione
137159
OperationLog::setInfo('id_module', $id_module ?? null);
138160
OperationLog::setInfo('options', json_encode([
139161
'queries_executed' => $executed,

modules/aggiornamenti/checksum.php

Lines changed: 82 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -21,119 +21,123 @@
2121

2222
include_once __DIR__.'/../../core.php';
2323

24-
// Aggiunta della classe per il modulo
24+
// ========================================================================
25+
// FUNZIONI HELPER PER CONTROLLO CHECKSUM
26+
// ========================================================================
27+
28+
/**
29+
* Carica i checksum dal file principale e dai moduli premium
30+
*/
31+
function loadAllChecksums()
32+
{
33+
$checksum = [];
34+
35+
// Carica checksum principale
36+
$main_checksum_file = base_dir().'/checksum.json';
37+
if (file_exists($main_checksum_file)) {
38+
$contents = file_get_contents($main_checksum_file);
39+
$checksum = json_decode($contents, true) ?: [];
40+
}
41+
42+
// Carica checksum dai moduli premium
43+
$module_checksum_files = glob(base_dir().'/modules/*/checksum.json') ?: [];
44+
foreach ($module_checksum_files as $module_checksum_file) {
45+
$module_contents = file_get_contents($module_checksum_file);
46+
$module_checksum = json_decode($module_contents, true);
47+
if (!empty($module_checksum)) {
48+
$checksum = array_merge($checksum, $module_checksum);
49+
}
50+
}
51+
52+
return $checksum;
53+
}
54+
55+
/**
56+
* Verifica l'integrità dei file rispetto ai checksum
57+
*/
58+
function verifyFileIntegrity($checksum)
59+
{
60+
$errors = [];
61+
foreach ($checksum as $file => $md5) {
62+
$verifica = md5_file(base_dir().'/'.$file);
63+
if ($verifica != $md5) {
64+
$errors[] = $file;
65+
}
66+
}
67+
return $errors;
68+
}
69+
70+
/**
71+
* Renderizza la tabella degli errori di integrità
72+
*/
73+
function renderIntegrityErrorsTable($errors)
74+
{
75+
$html = '<p>'.tr("Segue l'elenco dei file che presentano checksum diverso rispetto a quello registrato nella versione ufficiale").'.</p>';
76+
$html .= '<div class="alert alert-warning"><i class="fa fa-exclamation-triangle"></i> '.tr('Attenzione: questa funzionalità può presentare dei risultati falsamente positivi, sulla base del contenuto del file _FILE_', ['_FILE_' => '<b>checksum.json</b>']).'.'.
77+
'</div>';
78+
$html .= '<table class="table table-bordered table-striped table-hover"><thead><tr><th>'.tr('File con integrità errata').'</th></tr></thead><tbody>';
79+
80+
foreach ($errors as $error) {
81+
$html .= '<tr><td class="file-integrity-error"><i class="fa fa-exclamation-triangle"></i> '.$error.'</td></tr>';
82+
}
83+
84+
$html .= '</tbody></table>';
85+
return $html;
86+
}
87+
88+
// ========================================================================
89+
// LOGICA PRINCIPALE
90+
// ========================================================================
91+
2592
echo '<div class="module-aggiornamenti">';
2693

2794
$file = basename(__FILE__);
2895
$effettua_controllo = filter('effettua_controllo');
2996

30-
// Schermata di caricamento delle informazioni
97+
// Schermata di caricamento
3198
if (empty($effettua_controllo)) {
3299
echo '
33-
<div id="righe_controlli">
34-
35-
</div>
36-
100+
<div id="righe_controlli"></div>
37101
<div class="alert alert-info" id="card-loading">
38102
<i class="fa fa-spinner fa-spin"></i> '.tr('Caricamento in corso').'...
39103
</div>
40-
41104
<script>
42105
var content = $("#righe_controlli");
43106
var loader = $("#card-loading");
44107
$(document).ready(function () {
45108
loader.show();
46-
47109
content.html("");
48110
content.load("'.$structure->fileurl($file).'?effettua_controllo=1&id_module='.$id_module.'", function() {
49111
loader.hide();
50112
});
51113
})
52114
</script>';
53-
115+
echo '</div>';
54116
return;
55117
}
56118

57-
$contents = file_get_contents(base_dir().'/checksum.json');
58-
$checksum = json_decode($contents, true);
59-
60-
// Carica e accoda i checksum dei moduli premium
61-
$modules_dir = base_dir().'/modules/';
62-
$module_checksum_files = glob($modules_dir.'*/checksum.json');
63-
64-
if (!empty($module_checksum_files)) {
65-
foreach ($module_checksum_files as $module_checksum_file) {
66-
$module_contents = file_get_contents($module_checksum_file);
67-
$module_checksum = json_decode($module_contents, true);
68-
69-
if (!empty($module_checksum)) {
70-
// Accoda i checksum del modulo a quello principale
71-
$checksum = array_merge($checksum, $module_checksum);
72-
}
73-
}
74-
}
119+
// Carica checksum
120+
$checksum = loadAllChecksums();
75121

76122
if (empty($checksum)) {
77-
echo '
78-
<div class="alert alert-warning">
79-
<i class="fa fa-warning"></i> '.tr('Impossibile effettuare controlli di integrità in assenza del file _FILE_', [
80-
'_FILE_' => '<b>checksum.json</b>',
81-
]).'.
82-
</div>';
83-
123+
echo '<div class="alert alert-warning"><i class="fa fa-warning"></i> '.tr('Impossibile effettuare controlli di integrità in assenza del file _FILE_', ['_FILE_' => '<b>checksum.json</b>']).'.'.
124+
'</div></div>';
84125
return;
85126
}
86127

87-
// Controllo degli errori
88-
$errors = [];
89-
foreach ($checksum as $file => $md5) {
90-
$verifica = md5_file(base_dir().'/'.$file);
91-
if ($verifica != $md5) {
92-
$errors[] = $file;
93-
}
94-
}
128+
// Verifica integrità
129+
$errors = verifyFileIntegrity($checksum);
95130
OperationLog::setInfo('id_module', $id_module);
96131

97-
// Schermata di visualizzazione degli errori
132+
// Renderizza risultati
98133
if (!empty($errors)) {
99-
echo '
100-
<p>'.tr("Segue l'elenco dei file che presentano checksum diverso rispetto a quello registrato nella versione ufficiale").'.</p>
101-
<div class="alert alert-warning">
102-
<i class="fa fa-exclamation-triangle"></i>
103-
'.tr('Attenzione: questa funzionalità può presentare dei risultati falsamente positivi, sulla base del contenuto del file _FILE_', [
104-
'_FILE_' => '<b>checksum.json</b>',
105-
]).'.
106-
</div>
107-
108-
<table class="table table-bordered table-striped table-hover">
109-
<thead>
110-
<tr>
111-
<th>'.tr('File con integrità errata').'</th>
112-
</tr>
113-
</thead>
114-
115-
<tbody>';
116-
117-
foreach ($errors as $error) {
118-
echo '
119-
<tr>
120-
<td class="file-integrity-error">
121-
<i class="fa fa-exclamation-triangle"></i> '.$error.'
122-
</td>
123-
</tr>';
124-
}
125-
126-
echo '
127-
</tbody>
128-
</table>';
134+
echo renderIntegrityErrorsTable($errors);
129135
} else {
130-
echo '
131-
<div class="alert alert-info">
132-
<i class="fa fa-info-circle"></i> '.tr('Nessun file con problemi di integrità').'.
133-
</div>';
136+
echo '<div class="alert alert-info"><i class="fa fa-info-circle"></i> '.tr('Nessun file con problemi di integrità').'.'.
137+
'</div>';
134138
}
139+
135140
OperationLog::setInfo('options', json_encode(['controllo_name' => 'Controllo file'], JSON_UNESCAPED_UNICODE));
136141
OperationLog::build('effettua_controllo');
137142

138-
// Chiusura del div module-aggiornamenti
139143
echo '</div>';

0 commit comments

Comments
 (0)