dolibarr 25.0.0-alpha
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 {
76 dol_print_error($db);
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 {
86 dol_print_error($db);
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// Show the input of countries not allowed for disabling
203if ($mysoc->country_code != 'FR' || !isALNERunningVersion() || constant('CERTIF_LNE') != '1') {
204 print '<tr class="oddeven">';
205 print '<td>';
206 print $form->textwithpicto($langs->transnoentitiesnoconv("BlockedLogDisableNotAllowedForCountry"), $langs->transnoentitiesnoconv("BlockedLogDisableNotAllowedForCountry2"));
207 print '</td>';
208 print '<td>';
209
210 print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
211 print '<input type="hidden" name="token" value="'.newToken().'">';
212 print '<input type="hidden" name="action" value="set_BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY">';
213 print '<input type="hidden" name="withtab" value="'.$withtab.'">';
214
215 $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite";
216 $sql .= " FROM ".MAIN_DB_PREFIX."c_country";
217 $sql .= " WHERE active > 0";
218
219 $countryArray = array();
220 $resql = $db->query($sql);
221 if ($resql) {
222 while ($obj = $db->fetch_object($resql)) {
223 $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 : ''));
224 }
225 }
226
227 $selected = !getDolGlobalString('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY') ? array() : explode(',', getDolGlobalString('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY'));
228
229 // Can module be disabled
230 $canbedisabled = $block_static->canBeDisabled();
231
232 print $form->multiselectarray('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY', $countryArray, $selected, 0, 0, '', 0, 0, $canbedisabled ? '' : 'disabled');
233 print '<input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'"'.($canbedisabled ? '' : ' disabled').'>';
234 print '</form>';
235
236 print '</td>';
237 print '</tr>';
238}
239
240print '<tr class="oddeven">';
241print '<td class="">';
242print $langs->trans("ListOfTrackedEvents").'</td><td>';
243$arrayoftrackedevents = $block_static->trackedevents;
244foreach ($arrayoftrackedevents as $key => $val) {
245 if (preg_match('/^separator/i', $key)) {
246 continue;
247 }
248 print $key.' - ';
249 if (is_array($val)) {
250 print $langs->trans($val['labelhtml']).'<br>';
251 } else {
252 print $langs->trans($val).'<br>';
253 }
254}
255
256print '</td></tr>';
257
258print '</tr>';
259
260print '</table>';
261print '</div>';
262
263
264print '<br><br>';
265
266
267print '<!-- Link to pay -->';
268print '<span class="fas fa-external-link-alt" style=""></span> <span class="opacitymedium">'.$langs->trans("DebugTools").'</span><br>';
269print '<br>';
270
271$urlforceregistration = DOL_MAIN_URL_ROOT.'/index.php?forceregistration=1';
272print $langs->trans("URLToForceRegistration").'<br>';
273print '<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>';
274print ajax_autoselect('forceregistration');
275
276print '<br>';
277
278/*
279$urlforcepushcounter = DOL_MAIN_URL_ROOT.'/index.php?forcepushcounter=1';
280print $langs->trans("URLToForcePushOfBlockedLogCounter").'<br>';
281print '<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>';
282print ajax_autoselect('forcepushcounter');
283*/
284
285$urltogetkeyobfuscation = DOL_MAIN_URL_ROOT.'/blockedlog/admin/blockedlog.php?forcegetkeyobfuscation=1&token='.newToken();
286print $langs->trans("URLToGetObfuscationkey").'<br>';
287print '<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>';
288print ajax_autoselect('forcegetkeyobfuscation');
289
290if (GETPOST('forcegetkeyobfuscation')) { // Mode to force the retrieval and recording of HMAC with obfuscation.
291 unset($_SESSION['hmac_secret_key']);
292 unset($conf->cache['hmac_secret_key']);
293
294 $block_static->entity = $conf->entity;
295
296 $hmac_encoded_secret_key = '';
297 try {
298 $hmac_encoded_secret_key = $block_static->getEncodedHMACSecretKey();
299 print "\n<!-- READ TO GET HMAC KEY RETURNED result: ".$hmac_encoded_secret_key." -->\n";
300 } catch (Exception $e) {
301 print '<div class="error">'.$e->getMessage().'</div>';
302 }
303
304 $obfuscationkey = '';
305 try {
306 $obfuscationkey = $block_static->getObfuscationKey(); // Note: use the $mysoc->idprof1 and $registrationnumber. On network trouble, an Exception is thrown to the caller
307 print "\n<!-- API TO GET REMOTE OBFUSCATION KEY RETURNED result: ".$obfuscationkey." -->\n";
308 } catch (Exception $e) {
309 print '<div class="error">'.$e->getMessage().'</div>';
310 }
311
312 // Now test the keyfor debug purpose..
313
314 // Decode the encrypted parameter using the obfuscation key to get the HMAC key in memory.
315 $hmac_secret_key = dolDecrypt($hmac_encoded_secret_key, $obfuscationkey);
316
317 if (!preg_match('/^BLOCKEDLOGHMAC/', (string) $hmac_secret_key)) {
318 print '<!-- Failed to decode the encoded HMAC key using the remote obfuscation key -->';
319 // 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).
320 // Example with the old demo sample database:
321 // dolcrypt:AES-256-CTR:46cb611f00c4cff8:XVfEh15vX/JOYmpiw2QPNamcTQwdbBZJTcXBh9rMpzYJOpVPZubIWcgA8wHMXA==
322 // instance_unique_id=11f3c81e86fc9e3b3fd11d81c9a31bd0
323 // HMAC key=BLOCKEDLOGHMACY3Ewx37RXbSd8gL9JV8p7Wqw7qvq2K2A
324
325 // We fall back on the instance_unique_id (coming from $dolibarr_main_instance_unique_id, for backward compatibility).
326 $oldobfuscationkey = !empty($conf->file->instance_unique_id) ? $conf->file->instance_unique_id : "";
327
328 $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
329
330 if (!preg_match('/^BLOCKEDLOGHMAC/', (string) $hmac_secret_key)) {
331 //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.');
332 print '<!-- HMAC key can t be decoded -->';
333 } else { // $hmac_secret_key start with 'BLOCKEDLOGHMAC...' so it is a valid value
334 print '<!-- Success to decode HMAC key. It is encrypted with an old obfuscation method, we migrate it. -->';
335 print '<!-- '.$hmac_secret_key.' -->';
336 if ($obfuscationkey) {
337 $result = $block_static->saveHMACSecretKey($hmac_secret_key, 'dolobfuscationv1-'.$mysoc->idprof1, $obfuscationkey); // gitleaks:allow Save the HMAC key
338 print '<!-- Result to save the new HMAC key: '.$result.' -->';
339 }
340 }
341 } else {
342 print '<!-- Success to decode HMAC key from the remote obfuscation key, nothing to do more -->';
343 }
344}
345
346
347if ($withtab) {
348 print dol_get_fiche_end();
349}
350
351print '<br><br>';
352
353// End of page
354llxFooter();
355$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($blockedlogusagealreadychecked=0, $blockedlogmoduleonalreadychecked=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:
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, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
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.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
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.
Definition html.lib.php:540
dol_get_fiche_end($notab=0)
Return tab footer of a card.
Definition html.lib.php:738
ajax_autoselect($htmlname, $addlink='', $textonlink='Link')
Make content of an input box selected when we click into input field.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='', $cssfordropdown='info_admin')
Show information in HTML for admin users or standard users.
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.