dolibarr 24.0.0-beta
blockedlog.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr>
3 * Copyright (C) 2017-2018 Laurent Destailleur <eldy@destailleur.fr>
4 * Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
5 * Copyright (C) 2026-2026 Laurent Magnin <laurent.magnin@evarisk.com>
6 * Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
29// Load Dolibarr environment
30require '../../main.inc.php';
39require_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
40require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
41require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
42
43// Load translation files required by the page
44$langs->loadLangs(array('admin', 'blockedlog', 'other'));
45
46// Get Parameters
47$action = GETPOST('action', 'aZ09');
48$backtopage = GETPOST('backtopage', 'alpha');
49
50$withtab = GETPOSTINT('withtab');
51$origin = GETPOST('origin');
52$withtab = GETPOSTISSET('withtab') ? GETPOSTINT('withtab') : 1;
53
54// Access Control
55if (!$user->admin || !isModEnabled('blockedlog')) {
57}
58
59
60/*
61 * Actions
62 */
63
64$reg = array();
65if (preg_match('/set_(.*)/', $action, $reg)) {
66 $code = $reg[1];
67 $values = GETPOST($code);
68 if (is_array($values)) {
69 $values = implode(',', $values);
70 }
71
72 if (dolibarr_set_const($db, $code, $values, 'chaine', 0, '', $conf->entity) > 0) {
73 header("Location: ".$_SERVER["PHP_SELF"].($withtab ? '?withtab='.$withtab : ''));
74 exit;
75 } else {
77 }
78}
79
80if (preg_match('/del_(.*)/', $action, $reg)) {
81 $code = $reg[1];
82 if (dolibarr_del_const($db, $code, 0) > 0) {
83 header("Location: ".$_SERVER["PHP_SELF"].($withtab ? '?withtab='.$withtab : ''));
84 exit;
85 } else {
87 }
88}
89
90
91/*
92 * View
93 */
94
95$form = new Form($db);
96$block_static = new BlockedLog($db);
97$block_static->loadTrackedEvents();
98
99$title = $langs->trans("ModuleSetup").' '.$langs->trans('BlockedLog');
100$help_url = "EN:Module_Unalterable_Archives_-_Logs|FR:Module_Archives_-_Logs_Inaltérable";
101
102llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-blockedlog page-admin_blockedlog');
103
104$linkback = '';
105if ($withtab) {
106 $linkback = '<a href="'.dolBuildUrl($backtopage ? $backtopage : DOL_URL_ROOT.'/admin/modules.php', ['restore_lastsearch_values' => 1]).'">'.img_picto($langs->trans("BackToModuleList"), 'back', 'class="pictofixedwidth"').'<span class="hideonsmartphone">'.$langs->trans("BackToModuleList").'</span></a>';
107}
108
109$morehtmlcenter = '';
110
111$registrationnumber = getHashUniqueIdOfRegistration();
112$texttop = '<small class="opacitymedium">'.$langs->trans("RegistrationNumber").':</small> <small>'.dol_trunc($registrationnumber, 10).'</small>';
114 $texttop = '';
115}
116
117print load_fiche_titre($title.'<br>'.$texttop, $linkback, 'blockedlog', 0, '', '', $morehtmlcenter);
118
119if ($withtab) {
120 $head = blockedlogadmin_prepare_head($withtab);
121 print dol_get_fiche_head($head, 'technicalinfo', '', -1);
122}
123
124print '<span class="opacitymedium">'.$langs->trans("BlockedLogDesc")."</span><br>\n";
125
126$versionbadge = '<span class="badge-text badge-secondary">'.getBlockedLogVersionToShow().'</span>';
127
128
129// Special additional message for FR only
130$infotoshow = '';
131if ($mysoc->country_code == 'FR') {
132 $islne = isALNEQualifiedVersion(1, 1);
133 if ($islne) {
134 if (preg_match('/\-/', getBlockedLogVersionToShow())) {
135 // This is an alpha or beta version
136 $infotoshow = $langs->trans("LNECandidateVersionForCertificationFR", $versionbadge);
137 } else {
138 $infotoshow = $langs->trans("LNECertifiedVersionFR", $versionbadge);
139 }
140 } else {
141 $infotoshow = $langs->trans("NotCertifiedVersionFR", $versionbadge);
142 }
143
144 $infotoshow .= ' - <a href="'.DOL_URL_ROOT.'/blockedlog/admin/filecheck.php">'.img_picto('', 'url', 'class="pictofixedwidth"').$langs->trans("FileCheck").'</a>';
145}
146
147// Show generic message (for countries that need registration) to explain we need registration to collect data and why
148if (in_array($mysoc->country_code, array('FR'))) {
149 $organization_for_ping = getDolGlobalString('MAIN_ORGANIZATION_FOR_PING', "Association Dolibarr");
150 $dataprivacy_url = getDolGlobalString('MAIN_ORGANIZATION_URL_PRIVACY', "https://www.dolibarr.org/legal-privacy-gdpr.php");
151
152 if (!isRegistrationDataSavedAndPushed() || $origin == 'initmodule') {
153 if ($infotoshow) {
154 print info_admin($infotoshow, 0, 0, 'info');
155 }
156 /*
157 $htmltext = $langs->trans("UnalterableLogToolRegistrationFR").'<br>';
158 $htmltext .= $langs->trans("InformationWillBePublishedTo");
159 $htmltext .= '<br>'.$langs->trans("InformationWillBePublishedTo2", $organization_for_ping, $dataprivacy_url);
160 $htmltext .= '<br>'.$langs->trans("InformationWillBePublishedTo3");
161
162 print info_admin($htmltext, 0, 0, 'warning');
163 */
164 } else {
165 $htmltext = ($infotoshow ? $infotoshow.'<br>' : '');
166 $htmltext .= $langs->trans("ApplicationHasBeenRegistered");
167 $htmltext .= ' '.$langs->trans("RegistrationNumber").': <span class="badge-text badge-secondary" title="Flag stored into MAIN_FIRST_REGISTRATION_OK_DATE. Registered data saved into BLOCKEDLOG_REGISTRATION_...">'.dol_trunc($registrationnumber, 10).'</span>';
168 $htmltext .= '<br>';
169 $htmltext .= $langs->trans("LastRegistrationDate").' : ';
170 //$htmltext .= dol_print_date(getDolGlobalString('MAIN_FIRST_REGISTRATION_OK_DATE'), 'dayhour', 'tzuserrel');
171 $htmltext .= getDolGlobalString('MAIN_FIRST_REGISTRATION_OK_DATE');
172
173 print info_admin($htmltext, 0, 0, 'info');
174
175 // Show remind on good practices related to archives
176 /*
177 $htmltext = $langs->trans("UnalterableLogTool1FR", $langs->transnoentitiesnoconv("Archives")).'<br>';
178 print info_admin($htmltext, 0, 0, 'warning');
179 */
180 }
181}
182
183
184print '<br>';
185
186print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
187print '<table class="noborder centpercent">';
188
189print '<tr class="liste_titre">';
190print '<td>'.$langs->trans("Parameters").'</td>';
191print '<td></td>';
192print "</tr>\n";
193
194// Initial signature
195// Generated randomly when doing the first insert by blockedlog.class.php, and saved into BLOCKEDLOG_ENTITY_FINGERPRINT
196print '<tr class="oddeven">';
197print '<td class="titlefieldmiddle" title="Parameter BLOCKEDLOG_ENTITY_FINGERPRINT">';
198print $langs->trans("CompanyInitialKey").'</td><td title="Parameter BLOCKEDLOG_ENTITY_FINGERPRINT">';
199print $block_static->getOrInitFirstSignature();
200print '</td></tr>';
201
202/* Deprecated
203if (getDolGlobalString('BLOCKEDLOG_USE_REMOTE_AUTHORITY')) {
204 print '<tr class="oddeven">';
205 print '<td>'.$langs->trans("BlockedLogAuthorityUrl").img_info($langs->trans('BlockedLogAuthorityNeededToStoreYouFingerprintsInNonAlterableRemote')).'</td>';
206 print '<td class="right" width="300">';
207
208 print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
209 print '<input type="hidden" name="token" value="'.newToken().'">';
210 print '<input type="hidden" name="action" value="set_BLOCKEDLOG_AUTHORITY_URL">';
211 print '<input type="hidden" name="withtab" value="'.$withtab.'">';
212 print '<input type="text" name="BLOCKEDLOG_AUTHORITY_URL" value="' . getDolGlobalString('BLOCKEDLOG_AUTHORITY_URL').'" size="40" />';
213 print '<input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'">';
214 print '</form>';
215
216 print '</td></tr>';
217}
218
219print '<tr class="oddeven">';
220print '<td class="titlefieldmiddle" title="Debug obfuscation key">';
221print "Debug obfuscation key".'</td><td title="Debug obfuscation key" class="small">';
222try {
223 $a = $block_static->getObfuscationKey();
224 print 'block_static->getObfuscationKey(): '.$a;
225 print '<br>';
226 print '$_SESSION[obfuscationkey_'.((int) $conf->entity).']: '.$_SESSION['obfuscationkey_'.((int) $conf->entity)];
227 print '<br>';
228 $b = $block_static->getEncodedHMACSecretKey();
229 print $b;
230 print '<br>';
231 if (preg_match('/dolcrypt/', $b)) {
232 print dolDecrypt($b, '');
233 } elseif (preg_match('/dolobfuscationv1/', $b)) {
234 print dolDecrypt($b, $a);
235 }
236 print '<br>';
237 print '$conf->cache[obfuscationkey_'.((int) $conf->entity).']: '.$conf->cache['obfuscationkey_'.((int) $conf->entity)];
238} catch (Exception $e) {
239 print $e->getMessage();
240}
241print '</td></tr>';
242*/
243
244
245// Show the input of countries not allowed for disabling
246if ($mysoc->country_code != 'FR' || !isALNERunningVersion() || constant('CERTIF_LNE') != '1') {
247 print '<tr class="oddeven">';
248 print '<td>';
249 print $form->textwithpicto($langs->transnoentitiesnoconv("BlockedLogDisableNotAllowedForCountry"), $langs->transnoentitiesnoconv("BlockedLogDisableNotAllowedForCountry2"));
250 print '</td>';
251 print '<td>';
252
253 print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
254 print '<input type="hidden" name="token" value="'.newToken().'">';
255 print '<input type="hidden" name="action" value="set_BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY">';
256 print '<input type="hidden" name="withtab" value="'.$withtab.'">';
257
258 $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite";
259 $sql .= " FROM ".MAIN_DB_PREFIX."c_country";
260 $sql .= " WHERE active > 0";
261
262 $countryArray = array();
263 $resql = $db->query($sql);
264 if ($resql) {
265 while ($obj = $db->fetch_object($resql)) {
266 $countryArray[$obj->code_iso] = ($obj->code_iso && $langs->transnoentitiesnoconv("Country".$obj->code_iso) != "Country".$obj->code_iso ? $langs->transnoentitiesnoconv("Country".$obj->code_iso) : ($obj->label != '-' ? $obj->label : ''));
267 }
268 }
269
270 $selected = !getDolGlobalString('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY') ? array() : explode(',', getDolGlobalString('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY'));
271
272 // Can module be disabled
273 $canbedisabled = $block_static->canBeDisabled();
274
275 print $form->multiselectarray('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY', $countryArray, $selected, 0, 0, '', 0, 0, $canbedisabled ? '' : 'disabled');
276 print '<input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'"'.($canbedisabled ? '' : ' disabled').'>';
277 print '</form>';
278
279 print '</td>';
280 print '</tr>';
281}
282
283print '<tr class="oddeven">';
284print '<td class="">';
285print $langs->trans("ListOfTrackedEvents").'</td><td>';
286$arrayoftrackedevents = $block_static->trackedevents;
287foreach ($arrayoftrackedevents as $key => $val) {
288 if (preg_match('/^separator/i', $key)) {
289 continue;
290 }
291 print $key.' - ';
292 if (is_array($val)) {
293 print $langs->trans($val['labelhtml']).'<br>';
294 } else {
295 print $langs->trans($val).'<br>';
296 }
297}
298
299print '</td></tr>';
300
301print '</tr>';
302
303print '</table>';
304print '</div>';
305
306
307print '<br><br>';
308
309
310print '<!-- Link to pay -->';
311print '<span class="fas fa-external-link-alt" style=""></span> <span class="opacitymedium">'.$langs->trans("DebugTools").'</span><br>';
312print '<br>';
313
314$urlforceregistration = DOL_MAIN_URL_ROOT.'/index.php?forceregistration=1';
315print $langs->trans("URLToForceRegistration").'<br>';
316print '<div class="urllink"><input type="text" id="forceregistration" spellcheck="false" class="quatrevingtpercentminusx" value="'.$urlforceregistration.'"><a class="" href="'.$urlforceregistration.'" target="_blank" rel="noopener noreferrer"><span class="fas fa-external-link-alt paddingleft" style=""></span></a></div>';
317print ajax_autoselect('forceregistration');
318
319print '<br>';
320
321/*
322$urlforcepushcounter = DOL_MAIN_URL_ROOT.'/index.php?forcepushcounter=1';
323print $langs->trans("URLToForcePushOfBlockedLogCounter").'<br>';
324print '<div class="urllink"><input type="text" id="forcepushcounter" spellcheck="false" class="quatrevingtpercentminusx" value="'.$urlforcepushcounter.'"><a class="" href="'.$urlforcepushcounter.'" target="_blank" rel="noopener noreferrer"><span class="fas fa-external-link-alt paddingleft" style=""></span></a></div>';
325print ajax_autoselect('forcepushcounter');
326*/
327
328$urltogetkeyobfuscation = DOL_MAIN_URL_ROOT.'/blockedlog/admin/blockedlog.php?forcegetkeyobfuscation=1&token='.newToken();
329print $langs->trans("URLToGetObfuscationkey").'<br>';
330print '<div class="urllink"><input type="text" id="forcegetkeyobfuscation" spellcheck="false" class="quatrevingtpercentminusx" value="'.$urltogetkeyobfuscation.'"><a class="reposition" href="'.$urltogetkeyobfuscation.'" target="_blank" rel="noopener noreferrer"><span class="fas fa-external-link-alt paddingleft" style=""></span></a></div>';
331print ajax_autoselect('forcegetkeyobfuscation');
332
333if (GETPOST('forcegetkeyobfuscation')) {
334 unset($_SESSION['hmac_secret_key']);
335 unset($conf->cache['hmac_secret_key']);
336
337 $block_static->entity = $conf->entity;
338
339 $hmac_encoded_secret_key = '';
340 try {
341 $hmac_encoded_secret_key = $block_static->getEncodedHMACSecretKey();
342 print "\n<!-- READ TO GET HMAC KEY RETURNED result: ".$hmac_encoded_secret_key." -->\n";
343 } catch (Exception $e) {
344 print '<div class="error">'.$e->getMessage().'</div>';
345 }
346
347 $obfuscationkey = '';
348 try {
349 $obfuscationkey = $block_static->getObfuscationKey(); // Note: use the $mysoc->idprof1 and $registrationnumber. On network trouble, an Exception is thrown to the caller
350 print "\n<!-- API TO GET REMOTE OBFUSCATION KEY RETURNED result: ".$obfuscationkey." -->\n";
351 } catch (Exception $e) {
352 print '<div class="error">'.$e->getMessage().'</div>';
353 }
354
355 // Now test the keyfor debug purpose..
356
357 // Decode the encrypted parameter using the obfuscation key to get the HMAC key in memory.
358 $hmac_secret_key = dolDecrypt($hmac_encoded_secret_key, $obfuscationkey);
359
360 if (!preg_match('/^BLOCKEDLOGHMAC/', (string) $hmac_secret_key)) {
361 print '<!-- Failed to decode the encoded HMAC key using the remote obfuscation key -->';
362 // Failed to get the clear HMAC value. May be we are using an old obfuscated HMAC key, so we retry with the old method (used by webhosting providers using the attestation with previous versions).
363 // Example with the old demo sample database:
364 // dolcrypt:AES-256-CTR:46cb611f00c4cff8:XVfEh15vX/JOYmpiw2QPNamcTQwdbBZJTcXBh9rMpzYJOpVPZubIWcgA8wHMXA==
365 // instance_unique_id=11f3c81e86fc9e3b3fd11d81c9a31bd0
366 // HMAC key=BLOCKEDLOGHMACY3Ewx37RXbSd8gL9JV8p7Wqw7qvq2K2A
367
368 // We fall back on the instance_unique_id (coming from $dolibarr_main_instance_unique_id, for backward compatibility).
369 $oldobfuscationkey = !empty($conf->file->instance_unique_id) ? $conf->file->instance_unique_id : "";
370
371 $hmac_secret_key = dolDecrypt($hmac_encoded_secret_key, $oldobfuscationkey); // Decode the encrypted parameter using the obfuscation key from ping.dolibarr.org to decode HMAC key
372
373 if (!preg_match('/^BLOCKEDLOGHMAC/', (string) $hmac_secret_key)) {
374 //throw new Exception('blockedlog.php Error: Failed to decode the crypted value of the parameter BLOCKEDLOG_HMAC_KEY using the obfuscation key. A value was found but decoding failed. May be the database data were restored onto another environment and the coding/decoding key $dolibarr_main_dolcrypt_key or $dolibarr_main_instance_unique_id was not restored with the same value in conf.php file.');
375 print '<!-- HMAC key can t be decoded -->';
376 } else { // $hmac_secret_key start with 'BLOCKEDLOGHMAC...' so it is a valid value
377 print '<!-- Success to decode HMAC key. It is encrypted with an old obfuscation method, we migrate it. -->';
378 print '<!-- '.$hmac_secret_key.' -->';
379 if ($obfuscationkey) {
380 $result = $block_static->saveHMACSecretKey($hmac_secret_key, 'dolobfuscationv1-'.$mysoc->idprof1, $obfuscationkey); // gitleaks:allow Save the HMAC key
381 print '<!-- Result to save the new HMAC key: '.$result.' -->';
382 }
383 }
384 } else {
385 print '<!-- Success to decode HMAC key from the remote obfuscation key, nothing to do more -->';
386 }
387}
388
389
390if ($withtab) {
391 print dol_get_fiche_end();
392}
393
394print '<br><br>';
395
396// End of page
397llxFooter();
398$db->close();
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
dolibarr_del_const($db, $name, $entity=1)
Delete a constant.
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
getBlockedLogVersionToShow()
Define head array for tabs of blockedlog tools setup pages.
isALNEQualifiedVersion($ignoredev=0, $ignoremodule=0)
Return if the version is a candidate version to get the LNE certification and if the prerequisites ar...
blockedlogadmin_prepare_head($withtabsetup)
Define head array for tabs of blockedlog tools setup pages.
isRegistrationDataSavedAndPushed()
Return if the KYC mandatory parameters are set AND pushed/registered centralized server.
getHashUniqueIdOfRegistration($algo='sha256')
Return a hash unique identifier of the registration (used to identify the registration of instance wi...
isALNERunningVersion($blockedlogtestalreadydone=0, $blockedlogmodulealreadydone=0)
Return if the application is executed with the LNE requirements on.
Class to manage Blocked Log.
Class to manage generation of HTML components Only common components must be here.
global $mysoc
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='')
Show information in HTML for admin users or standard users.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
ajax_autoselect($htmlname, $addlink='', $textonlink='Link')
Make content of an input box selected when we click into input field.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '...' if string larger than length.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
dolDecrypt($chain, $key='', $patterntotest='')
Decode a string with a symmetric encryption.