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 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
28// Load Dolibarr environment
29require '../../main.inc.php';
38require_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
39require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
40require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
41
42// Load translation files required by the page
43$langs->loadLangs(array('admin', 'blockedlog', 'other'));
44
45// Get Parameters
46$action = GETPOST('action', 'aZ09');
47$backtopage = GETPOST('backtopage', 'alpha');
48
49$withtab = GETPOSTINT('withtab');
50$origin = GETPOST('origin');
51$withtab = GETPOSTISSET('withtab') ? GETPOSTINT('withtab') : 1;
52
53// Access Control
54if (!$user->admin || !isModEnabled('blockedlog')) {
56}
57
58
59/*
60 * Actions
61 */
62
63$reg = array();
64if (preg_match('/set_(.*)/', $action, $reg)) {
65 $code = $reg[1];
66 $values = GETPOST($code);
67 if (is_array($values)) {
68 $values = implode(',', $values);
69 }
70
71 if (dolibarr_set_const($db, $code, $values, 'chaine', 0, '', $conf->entity) > 0) {
72 header("Location: ".$_SERVER["PHP_SELF"].($withtab ? '?withtab='.$withtab : ''));
73 exit;
74 } else {
76 }
77}
78
79if (preg_match('/del_(.*)/', $action, $reg)) {
80 $code = $reg[1];
81 if (dolibarr_del_const($db, $code, 0) > 0) {
82 header("Location: ".$_SERVER["PHP_SELF"].($withtab ? '?withtab='.$withtab : ''));
83 exit;
84 } else {
86 }
87}
88
89
90/*
91 * View
92 */
93
94$form = new Form($db);
95$block_static = new BlockedLog($db);
96$block_static->loadTrackedEvents();
97
98$title = $langs->trans("ModuleSetup").' '.$langs->trans('BlockedLog');
99$help_url="EN:Module_Unalterable_Archives_-_Logs|FR:Module_Archives_-_Logs_Inaltérable";
100
101llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-blockedlog page-admin_blockedlog');
102
103$linkback = '';
104if ($withtab) {
105 $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>';
106}
107
108$morehtmlcenter = '';
109
110$registrationnumber = getHashUniqueIdOfRegistration();
111$texttop = '<small class="opacitymedium">'.$langs->trans("RegistrationNumber").':</small> <small>'.dol_trunc($registrationnumber, 10).'</small>';
113 $texttop = '';
114}
115
116print load_fiche_titre($title.'<br>'.$texttop, $linkback, 'blockedlog', 0, '', '', $morehtmlcenter);
117
118if ($withtab) {
119 $head = blockedlogadmin_prepare_head($withtab);
120 print dol_get_fiche_head($head, 'technicalinfo', '', -1);
121}
122
123print '<span class="opacitymedium">'.$langs->trans("BlockedLogDesc")."</span><br>\n";
124
125$versionbadge = '<span class="badge-text badge-secondary">'.getBlockedLogVersionToShow().'</span>';
126
127
128// Special additional message for FR only
129$infotoshow = '';
130if ($mysoc->country_code == 'FR') {
131 $islne = isALNEQualifiedVersion(1, 1);
132 if ($islne) {
133 if (preg_match('/\-/', getBlockedLogVersionToShow())) {
134 // This is an alpha or beta version
135 $infotoshow = $langs->trans("LNECandidateVersionForCertificationFR", $versionbadge);
136 } else {
137 $infotoshow = $langs->trans("LNECertifiedVersionFR", $versionbadge);
138 }
139 } else {
140 $infotoshow = $langs->trans("NotCertifiedVersionFR", $versionbadge);
141 }
142
143 $infotoshow .= ' - <a href="'.DOL_URL_ROOT.'/blockedlog/admin/filecheck.php">'.img_picto('', 'url', 'class="pictofixedwidth"').$langs->trans("FileCheck").'</a>';
144}
145
146// Show generic message (for countries that need registration) to explain we need registration to collect data and why
147if (in_array($mysoc->country_code, array('FR'))) {
148 $organization_for_ping = getDolGlobalString('MAIN_ORGANIZATION_FOR_PING', "Association Dolibarr");
149 $dataprivacy_url = getDolGlobalString('MAIN_ORGANIZATION_URL_PRIVACY', "https://www.dolibarr.org/legal-privacy-gdpr.php");
150
151 if (!isRegistrationDataSavedAndPushed() || $origin == 'initmodule') {
152 if ($infotoshow) {
153 print info_admin($infotoshow, 0, 0, 'info');
154 }
155 /*
156 $htmltext = $langs->trans("UnalterableLogToolRegistrationFR").'<br>';
157 $htmltext .= $langs->trans("InformationWillBePublishedTo");
158 $htmltext .= '<br>'.$langs->trans("InformationWillBePublishedTo2", $organization_for_ping, $dataprivacy_url);
159 $htmltext .= '<br>'.$langs->trans("InformationWillBePublishedTo3");
160
161 print info_admin($htmltext, 0, 0, 'warning');
162 */
163 } else {
164 $htmltext = ($infotoshow ? $infotoshow.'<br>' : '');
165 $htmltext .= $langs->trans("ApplicationHasBeenRegistered");
166 $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>';
167 $htmltext .= '<br>';
168 $htmltext .= $langs->trans("LastRegistrationDate").' : ';
169 //$htmltext .= dol_print_date(getDolGlobalString('MAIN_FIRST_REGISTRATION_OK_DATE'), 'dayhour', 'tzuserrel');
170 $htmltext .= getDolGlobalString('MAIN_FIRST_REGISTRATION_OK_DATE');
171
172 print info_admin($htmltext, 0, 0, 'info');
173
174 // Show remind on good practices related to archives
175 /*
176 $htmltext = $langs->trans("UnalterableLogTool1FR", $langs->transnoentitiesnoconv("Archives")).'<br>';
177 print info_admin($htmltext, 0, 0, 'warning');
178 */
179 }
180}
181
182
183print '<br>';
184
185print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
186print '<table class="noborder centpercent">';
187
188print '<tr class="liste_titre">';
189print '<td>'.$langs->trans("Parameters").'</td>';
190print '<td></td>';
191print "</tr>\n";
192
193// Initial signature
194// Generated randomly when doing the first insert by blockedlog.class.php, and saved into BLOCKEDLOG_ENTITY_FINGERPRINT
195print '<tr class="oddeven">';
196print '<td class="titlefieldmiddle" title="Parameter BLOCKEDLOG_ENTITY_FINGERPRINT">';
197print $langs->trans("CompanyInitialKey").'</td><td title="Parameter BLOCKEDLOG_ENTITY_FINGERPRINT">';
198print $block_static->getOrInitFirstSignature();
199print '</td></tr>';
200
201/* Deprecated
202if (getDolGlobalString('BLOCKEDLOG_USE_REMOTE_AUTHORITY')) {
203 print '<tr class="oddeven">';
204 print '<td>'.$langs->trans("BlockedLogAuthorityUrl").img_info($langs->trans('BlockedLogAuthorityNeededToStoreYouFingerprintsInNonAlterableRemote')).'</td>';
205 print '<td class="right" width="300">';
206
207 print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
208 print '<input type="hidden" name="token" value="'.newToken().'">';
209 print '<input type="hidden" name="action" value="set_BLOCKEDLOG_AUTHORITY_URL">';
210 print '<input type="hidden" name="withtab" value="'.$withtab.'">';
211 print '<input type="text" name="BLOCKEDLOG_AUTHORITY_URL" value="' . getDolGlobalString('BLOCKEDLOG_AUTHORITY_URL').'" size="40" />';
212 print '<input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'">';
213 print '</form>';
214
215 print '</td></tr>';
216}
217
218print '<tr class="oddeven">';
219print '<td class="titlefieldmiddle" title="Debug obfuscation key">';
220print "Debug obfuscation key".'</td><td title="Debug obfuscation key" class="small">';
221try {
222 $a = $block_static->getObfuscationKey();
223 print 'block_static->getObfuscationKey(): '.$a;
224 print '<br>';
225 print '$_SESSION[obfuscationkey_'.((int) $conf->entity).']: '.$_SESSION['obfuscationkey_'.((int) $conf->entity)];
226 print '<br>';
227 $b = $block_static->getEncodedHMACSecretKey();
228 print $b;
229 print '<br>';
230 if (preg_match('/dolcrypt/', $b)) {
231 print dolDecrypt($b, '');
232 } elseif (preg_match('/dolobfuscationv1/', $b)) {
233 print dolDecrypt($b, $a);
234 }
235 print '<br>';
236 print '$conf->cache[obfuscationkey_'.((int) $conf->entity).']: '.$conf->cache['obfuscationkey_'.((int) $conf->entity)];
237} catch (Exception $e) {
238 print $e->getMessage();
239}
240print '</td></tr>';
241*/
242
243
244// Show the input of countries not allowed for disabling
245if ($mysoc->country_code != 'FR' || !isALNERunningVersion() || constant('CERTIF_LNE') != '1') {
246 print '<tr class="oddeven">';
247 print '<td>';
248 print $form->textwithpicto($langs->transnoentitiesnoconv("BlockedLogDisableNotAllowedForCountry"), $langs->transnoentitiesnoconv("BlockedLogDisableNotAllowedForCountry2"));
249 print '</td>';
250 print '<td>';
251
252 print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
253 print '<input type="hidden" name="token" value="'.newToken().'">';
254 print '<input type="hidden" name="action" value="set_BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY">';
255 print '<input type="hidden" name="withtab" value="'.$withtab.'">';
256
257 $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite";
258 $sql .= " FROM ".MAIN_DB_PREFIX."c_country";
259 $sql .= " WHERE active > 0";
260
261 $countryArray = array();
262 $resql = $db->query($sql);
263 if ($resql) {
264 while ($obj = $db->fetch_object($resql)) {
265 $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 : ''));
266 }
267 }
268
269 $selected = !getDolGlobalString('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY') ? array() : explode(',', getDolGlobalString('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY'));
270
271 // Can module be disabled
272 $canbedisabled = $block_static->canBeDisabled();
273
274 print $form->multiselectarray('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY', $countryArray, $selected, 0, 0, '', 0, 0, $canbedisabled ? '' : 'disabled');
275 print '<input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'"'.($canbedisabled ? '' : ' disabled').'>';
276 print '</form>';
277
278 print '</td>';
279 print '</tr>';
280}
281
282print '<tr class="oddeven">';
283print '<td class="">';
284print $langs->trans("ListOfTrackedEvents").'</td><td>';
285$arrayoftrackedevents = $block_static->trackedevents;
286foreach ($arrayoftrackedevents as $key => $val) {
287 if (preg_match('/^separator/i', $key)) {
288 continue;
289 }
290 print $key.' - ';
291 if (is_array($val)) {
292 print $langs->trans($val['labelhtml']).'<br>';
293 } else {
294 print $langs->trans($val).'<br>';
295 }
296}
297
298print '</td></tr>';
299
300print '</tr>';
301
302print '</table>';
303print '</div>';
304
305
306print '<br><br>';
307
308
309print '<!-- Link to pay -->';
310print '<span class="fas fa-external-link-alt" style=""></span> <span class="opacitymedium">'.$langs->trans("DebugTools").'</span><br>';
311print '<br>';
312
313$urlforceregistration = DOL_MAIN_URL_ROOT.'/index.php?forceregistration=1';
314print $langs->trans("URLToForceRegistration").'<br>';
315print '<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>';
316print ajax_autoselect('forceregistration');
317
318print '<br>';
319
320/*
321$urlforcepushcounter = DOL_MAIN_URL_ROOT.'/index.php?forcepushcounter=1';
322print $langs->trans("URLToForcePushOfBlockedLogCounter").'<br>';
323print '<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>';
324print ajax_autoselect('forcepushcounter');
325*/
326
327$urltogetkeyobfuscation = DOL_MAIN_URL_ROOT.'/blockedlog/admin/blockedlog.php?forcegetkeyobfuscation=1&token='.newToken();
328print $langs->trans("URLToGetObfuscationkey").'<br>';
329print '<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>';
330print ajax_autoselect('forcegetkeyobfuscation');
331
332if (GETPOST('forcegetkeyobfuscation')) {
333 unset($_SESSION['hmac_secret_key']);
334 unset($conf->cache['hmac_secret_key']);
335
336 $block_static->entity = $conf->entity;
337
338 try {
339 $hmac_encoded_secret_key = $block_static->getEncodedHMACSecretKey();
340 print "\n<!-- READ TO GET HMAC KEY RETURNED result: ".$hmac_encoded_secret_key." -->\n";
341 } catch (Exception $e) {
342 print '<div class="error">'.$e->getMessage().'</div>';
343 }
344
345 $obfuscationkey = '';
346 try {
347 $obfuscationkey = $block_static->getObfuscationKey(); // Note: use the $mysoc->idprof1 and $registrationnumber. On network trouble, an Exception is thrown to the caller
348 print "\n<!-- API TO GET REMOTE OBFUSCATION KEY RETURNED result: ".$obfuscationkey." -->\n";
349 } catch (Exception $e) {
350 print '<div class="error">'.$e->getMessage().'</div>';
351 }
352
353 // Now test the keyfor debug purpose..
354
355 // Decode the encrypted parameter using the obfuscation key to get the HMAC key in memory.
356 $hmac_secret_key = dolDecrypt($hmac_encoded_secret_key, $obfuscationkey);
357
358 if (!preg_match('/^BLOCKEDLOGHMAC/', (string) $hmac_secret_key)) {
359 print '<!-- Failed to decode the encoded HMAC key using the remote obfuscation key -->';
360 // 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).
361 // Example with the old demo sample database:
362 // dolcrypt:AES-256-CTR:46cb611f00c4cff8:XVfEh15vX/JOYmpiw2QPNamcTQwdbBZJTcXBh9rMpzYJOpVPZubIWcgA8wHMXA==
363 // instance_unique_id=11f3c81e86fc9e3b3fd11d81c9a31bd0
364 // HMAC key=BLOCKEDLOGHMACY3Ewx37RXbSd8gL9JV8p7Wqw7qvq2K2A
365
366 // We fall back on the instance_unique_id (coming from $dolibarr_main_instance_unique_id, for backward compatibility).
367 $oldobfuscationkey = !empty($conf->file->instance_unique_id) ? $conf->file->instance_unique_id : "";
368
369 $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
370
371 if (!preg_match('/^BLOCKEDLOGHMAC/', (string) $hmac_secret_key)) {
372 //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.');
373 print '<!-- HMAC key can t be decoded -->';
374 } else { // $hmac_secret_key start with 'BLOCKEDLOGHMAC...' so it is a valid value
375 print '<!-- Success to decode HMAC key. It is encrypted with an old obfuscation method, we migrate it. -->';
376 print '<!-- '.$hmac_secret_key.' -->';
377 if ($obfuscationkey) {
378 $result = $block_static->saveHMACSecretKey($hmac_secret_key, 'dolobfuscationv1-'.$mysoc->idprof1, $obfuscationkey); // gitleaks:allow Save the HMAC key
379 print '<!-- Result to save the new HMAC key: '.$result.' -->';
380 }
381 }
382 } else {
383 print '<!-- Success to decode HMAC key from the remote obfuscation key, nothing to do more -->';
384 }
385}
386
387
388if ($withtab) {
389 print dol_get_fiche_end();
390}
391
392print '<br><br>';
393
394// End of page
395llxFooter();
396$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.
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.