* Copyright (C) 2017-2018 Laurent Destailleur * Copyright (C) 2024-2026 Frédéric France * Copyright (C) 2026-2026 Laurent Magnin * Copyright (C) 2026 MDW * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file htdocs/blockedlog/admin/blockedlog.php * \ingroup blockedlog * \brief Page setup for blockedlog module */ // Load Dolibarr environment require '../../main.inc.php'; /** * @var Conf $conf * @var DoliDB $db * @var HookManager $hookmanager * @var Societe $mysoc * @var Translate $langs * @var User $user */ require_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php'; require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; // Load translation files required by the page $langs->loadLangs(array('admin', 'blockedlog', 'other')); // Get Parameters $action = GETPOST('action', 'aZ09'); $backtopage = GETPOST('backtopage', 'alpha'); $withtab = GETPOSTINT('withtab'); $origin = GETPOST('origin'); $withtab = GETPOSTISSET('withtab') ? GETPOSTINT('withtab') : 1; // Access Control if (!$user->admin || !isModEnabled('blockedlog')) { accessforbidden(); } /* * Actions */ $reg = array(); if (preg_match('/set_(.*)/', $action, $reg)) { $code = $reg[1]; $values = GETPOST($code); if (is_array($values)) { $values = implode(',', $values); } if (dolibarr_set_const($db, $code, $values, 'chaine', 0, '', $conf->entity) > 0) { header("Location: ".$_SERVER["PHP_SELF"].($withtab ? '?withtab='.$withtab : '')); exit; } else { dol_print_error($db); } } if (preg_match('/del_(.*)/', $action, $reg)) { $code = $reg[1]; if (dolibarr_del_const($db, $code, 0) > 0) { header("Location: ".$_SERVER["PHP_SELF"].($withtab ? '?withtab='.$withtab : '')); exit; } else { dol_print_error($db); } } /* * View */ $form = new Form($db); $block_static = new BlockedLog($db); $block_static->loadTrackedEvents(); $title = $langs->trans("ModuleSetup").' '.$langs->trans('BlockedLog'); $help_url = "EN:Module_Unalterable_Archives_-_Logs|FR:Module_Archives_-_Logs_Inaltérable"; llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-blockedlog page-admin_blockedlog'); $linkback = ''; if ($withtab) { $linkback = ''.img_picto($langs->trans("BackToModuleList"), 'back', 'class="pictofixedwidth"').''.$langs->trans("BackToModuleList").''; } $morehtmlcenter = ''; $registrationnumber = getHashUniqueIdOfRegistration(); $texttop = ''.$langs->trans("RegistrationNumber").': '.dol_trunc($registrationnumber, 10).''; if (!isRegistrationDataSavedAndPushed()) { $texttop = ''; } print load_fiche_titre($title.'
'.$texttop, $linkback, 'blockedlog', 0, '', '', $morehtmlcenter); if ($withtab) { $head = blockedlogadmin_prepare_head($withtab); print dol_get_fiche_head($head, 'technicalinfo', '', -1); } print ''.$langs->trans("BlockedLogDesc")."
\n"; $versionbadge = ''.getBlockedLogVersionToShow().''; // Special additional message for FR only $infotoshow = ''; if ($mysoc->country_code == 'FR') { $islne = isALNEQualifiedVersion(1, 1); if ($islne) { if (preg_match('/\-/', getBlockedLogVersionToShow())) { // This is an alpha or beta version $infotoshow = $langs->trans("LNECandidateVersionForCertificationFR", $versionbadge); } else { $infotoshow = $langs->trans("LNECertifiedVersionFR", $versionbadge); } } else { $infotoshow = $langs->trans("NotCertifiedVersionFR", $versionbadge); } $infotoshow .= ' - '.img_picto('', 'url', 'class="pictofixedwidth"').$langs->trans("FileCheck").''; } // Show generic message (for countries that need registration) to explain we need registration to collect data and why if (in_array($mysoc->country_code, array('FR'))) { $organization_for_ping = getDolGlobalString('MAIN_ORGANIZATION_FOR_PING', "Association Dolibarr"); $dataprivacy_url = getDolGlobalString('MAIN_ORGANIZATION_URL_PRIVACY', "https://www.dolibarr.org/legal-privacy-gdpr.php"); if (!isRegistrationDataSavedAndPushed() || $origin == 'initmodule') { if ($infotoshow) { print info_admin($infotoshow, 0, 0, 'info'); } /* $htmltext = $langs->trans("UnalterableLogToolRegistrationFR").'
'; $htmltext .= $langs->trans("InformationWillBePublishedTo"); $htmltext .= '
'.$langs->trans("InformationWillBePublishedTo2", $organization_for_ping, $dataprivacy_url); $htmltext .= '
'.$langs->trans("InformationWillBePublishedTo3"); print info_admin($htmltext, 0, 0, 'warning'); */ } else { $htmltext = ($infotoshow ? $infotoshow.'
' : ''); $htmltext .= $langs->trans("ApplicationHasBeenRegistered"); $htmltext .= ' '.$langs->trans("RegistrationNumber").': '.dol_trunc($registrationnumber, 10).''; $htmltext .= '
'; $htmltext .= $langs->trans("LastRegistrationDate").' : '; //$htmltext .= dol_print_date(getDolGlobalString('MAIN_FIRST_REGISTRATION_OK_DATE'), 'dayhour', 'tzuserrel'); $htmltext .= getDolGlobalString('MAIN_FIRST_REGISTRATION_OK_DATE'); print info_admin($htmltext, 0, 0, 'info'); // Show remind on good practices related to archives /* $htmltext = $langs->trans("UnalterableLogTool1FR", $langs->transnoentitiesnoconv("Archives")).'
'; print info_admin($htmltext, 0, 0, 'warning'); */ } } print '
'; print '
'; // You can use div-table-responsive-no-min if you don't need reserved height for your table print ''; print ''; print ''; print ''; print "\n"; // Initial signature // Generated randomly when doing the first insert by blockedlog.class.php, and saved into BLOCKEDLOG_ENTITY_FINGERPRINT print ''; print ''; /* Deprecated if (getDolGlobalString('BLOCKEDLOG_USE_REMOTE_AUTHORITY')) { print ''; print ''; print ''; } print ''; print ''; */ // Show the input of countries not allowed for disabling if ($mysoc->country_code != 'FR' || !isALNERunningVersion() || constant('CERTIF_LNE') != '1') { print ''; print ''; print ''; print ''; } print ''; print ''; print ''; print '
'.$langs->trans("Parameters").'
'; print $langs->trans("CompanyInitialKey").''; print $block_static->getOrInitFirstSignature(); print '
'.$langs->trans("BlockedLogAuthorityUrl").img_info($langs->trans('BlockedLogAuthorityNeededToStoreYouFingerprintsInNonAlterableRemote')).''; print '
'; print ''; print ''; print ''; print ''; print ''; print '
'; print '
'; print "Debug obfuscation key".''; try { $a = $block_static->getObfuscationKey(); print 'block_static->getObfuscationKey(): '.$a; print '
'; print '$_SESSION[obfuscationkey_'.((int) $conf->entity).']: '.$_SESSION['obfuscationkey_'.((int) $conf->entity)]; print '
'; $b = $block_static->getEncodedHMACSecretKey(); print $b; print '
'; if (preg_match('/dolcrypt/', $b)) { print dolDecrypt($b, ''); } elseif (preg_match('/dolobfuscationv1/', $b)) { print dolDecrypt($b, $a); } print '
'; print '$conf->cache[obfuscationkey_'.((int) $conf->entity).']: '.$conf->cache['obfuscationkey_'.((int) $conf->entity)]; } catch (Exception $e) { print $e->getMessage(); } print '
'; print $form->textwithpicto($langs->transnoentitiesnoconv("BlockedLogDisableNotAllowedForCountry"), $langs->transnoentitiesnoconv("BlockedLogDisableNotAllowedForCountry2")); print ''; print '
'; print ''; print ''; print ''; $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite"; $sql .= " FROM ".MAIN_DB_PREFIX."c_country"; $sql .= " WHERE active > 0"; $countryArray = array(); $resql = $db->query($sql); if ($resql) { while ($obj = $db->fetch_object($resql)) { $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 : '')); } } $selected = !getDolGlobalString('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY') ? array() : explode(',', getDolGlobalString('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY')); // Can module be disabled $canbedisabled = $block_static->canBeDisabled(); print $form->multiselectarray('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY', $countryArray, $selected, 0, 0, '', 0, 0, $canbedisabled ? '' : 'disabled'); print ''; print '
'; print '
'; print $langs->trans("ListOfTrackedEvents").''; $arrayoftrackedevents = $block_static->trackedevents; foreach ($arrayoftrackedevents as $key => $val) { if (preg_match('/^separator/i', $key)) { continue; } print $key.' - '; if (is_array($val)) { print $langs->trans($val['labelhtml']).'
'; } else { print $langs->trans($val).'
'; } } print '
'; print '
'; print '

'; print ''; print ' '.$langs->trans("DebugTools").'
'; print '
'; $urlforceregistration = DOL_MAIN_URL_ROOT.'/index.php?forceregistration=1'; print $langs->trans("URLToForceRegistration").'
'; print ''; print ajax_autoselect('forceregistration'); print '
'; /* $urlforcepushcounter = DOL_MAIN_URL_ROOT.'/index.php?forcepushcounter=1'; print $langs->trans("URLToForcePushOfBlockedLogCounter").'
'; print ''; print ajax_autoselect('forcepushcounter'); */ $urltogetkeyobfuscation = DOL_MAIN_URL_ROOT.'/blockedlog/admin/blockedlog.php?forcegetkeyobfuscation=1&token='.newToken(); print $langs->trans("URLToGetObfuscationkey").'
'; print ''; print ajax_autoselect('forcegetkeyobfuscation'); if (GETPOST('forcegetkeyobfuscation')) { unset($_SESSION['hmac_secret_key']); unset($conf->cache['hmac_secret_key']); $block_static->entity = $conf->entity; $hmac_encoded_secret_key = ''; try { $hmac_encoded_secret_key = $block_static->getEncodedHMACSecretKey(); print "\n\n"; } catch (Exception $e) { print '
'.$e->getMessage().'
'; } $obfuscationkey = ''; try { $obfuscationkey = $block_static->getObfuscationKey(); // Note: use the $mysoc->idprof1 and $registrationnumber. On network trouble, an Exception is thrown to the caller print "\n\n"; } catch (Exception $e) { print '
'.$e->getMessage().'
'; } // Now test the keyfor debug purpose.. // Decode the encrypted parameter using the obfuscation key to get the HMAC key in memory. $hmac_secret_key = dolDecrypt($hmac_encoded_secret_key, $obfuscationkey); if (!preg_match('/^BLOCKEDLOGHMAC/', (string) $hmac_secret_key)) { print ''; // 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). // Example with the old demo sample database: // dolcrypt:AES-256-CTR:46cb611f00c4cff8:XVfEh15vX/JOYmpiw2QPNamcTQwdbBZJTcXBh9rMpzYJOpVPZubIWcgA8wHMXA== // instance_unique_id=11f3c81e86fc9e3b3fd11d81c9a31bd0 // HMAC key=BLOCKEDLOGHMACY3Ewx37RXbSd8gL9JV8p7Wqw7qvq2K2A // We fall back on the instance_unique_id (coming from $dolibarr_main_instance_unique_id, for backward compatibility). $oldobfuscationkey = !empty($conf->file->instance_unique_id) ? $conf->file->instance_unique_id : ""; $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 if (!preg_match('/^BLOCKEDLOGHMAC/', (string) $hmac_secret_key)) { //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.'); print ''; } else { // $hmac_secret_key start with 'BLOCKEDLOGHMAC...' so it is a valid value print ''; print ''; if ($obfuscationkey) { $result = $block_static->saveHMACSecretKey($hmac_secret_key, 'dolobfuscationv1-'.$mysoc->idprof1, $obfuscationkey); // gitleaks:allow Save the HMAC key print ''; } } } else { print ''; } } if ($withtab) { print dol_get_fiche_end(); } print '

'; // End of page llxFooter(); $db->close();