dolibarr 25.0.0-alpha
blockedlog.lib.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr>
3 * Copyright (C) 2018 Destailleur Laurent <eldy@users.sourceforge.net>
4 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
5 * Copyright (C) 2026 Frédéric France <frederic.france@free.fr>
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
27include_once DOL_DOCUMENT_ROOT.'/blockedlog/versionmod.inc.php';
28
29
36{
37 $versionbadge = constant('DOLCERT_VERSION');
38
39 // Protection if we used a past old version not yet certified, we change version shown.
40 if (!constant('CERTIF_LNE')) { // Hard coded in version
41 // $versionbadge = preg_replace('/^(\d)\./', '\1b.', $versionbadge); // Not yet required.
42 }
43
44 if (constant('DOLCERT_NAME') != 'BlockedLog') { // Can add a prefix namevefore version text for clarity.
45 $versionbadge = constant('DOLCERT_NAME').'-'.$versionbadge;
46 }
47
48 return $versionbadge;
49}
50
51
58function blockedlogadmin_prepare_head($withtabsetup)
59{
60 global $db, $langs, $conf, $mysoc;
61
62 $langs->load("blockedlog");
63
64 require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
65
66 $param = '';
67 $param .= ($withtabsetup? "?withtab=".$withtabsetup : "");
68 $param .= (GETPOST('origin') ? ($param ? '&' : '?').'origin='.GETPOST('origin') : '');
69
70 $h = 0;
71 $head = array();
72
73 if (!userIsTaxAuditor()) {
74 $head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/registration.php".$param;
75 $head[$h][1] = $langs->trans("UserRegistration");
76 $head[$h][2] = 'registration';
77 $h++;
78 }
79
80 if (!userIsTaxAuditor()) {
81 $b = new BlockedLog($db);
82 $head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/blockedlog_list.php".$param;
83 $head[$h][1] = $langs->trans("BrowseBlockedLog");
84 if ($b->alreadyUsed()) {
85 $head[$h][1] .= (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER') ? '<span class="badge marginleftonlyshort">...</span>' : '');
86 }
87 $head[$h][2] = 'fingerprints';
88 $h++;
89 }
90
91 $head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/blockedlog_archives.php".$param;
92 $head[$h][1] = $langs->trans("Archives");
93 // Add badge on nb of files
94 $block_static = new BlockedLog($db);
95 $upload_dir = getMultidirOutput($block_static, 'blockedlog').'/archives';
96 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
97 require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
98 $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
99 $nbLinks = 0;
100 if (($nbFiles + $nbLinks) > 0) {
101 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>';
102 }
103 $head[$h][2] = 'archives';
104 $h++;
105
106 if (userIsTaxAuditor()) {
107 $head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/blockedlog_control.php".$param;
108 $head[$h][1] = $langs->trans("OtherControl");
109 $head[$h][2] = 'control';
110 $h++;
111 }
112
113 if ($mysoc->country_code == 'FR') {
114 $head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/documentation.php".$param;
115 $head[$h][1] = $langs->trans("Documentation");
116 $head[$h][2] = 'documentation';
117 $h++;
118 }
119
120 if ($withtabsetup && !userIsTaxAuditor()) {
121 $head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/blockedlog.php".$param;
122 $head[$h][1] = $langs->trans("TechnicalInformation");
123 $head[$h][2] = 'technicalinfo';
124 $h++;
125 }
126
127
128 $object = new stdClass();
129
130 // Show more tabs from modules
131 // Entries must be declared in modules descriptor with line
132 // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
133 // $this->tabs = array('entity:-tabname); to remove a tab
134 complete_head_from_modules($conf, $langs, $object, $head, $h, 'blockedlog');
135
136 complete_head_from_modules($conf, $langs, $object, $head, $h, 'blockedlog', 'remove');
137
138 return $head;
139}
140
141
149{
150 global $mysoc;
151
152 $companyname = getDolGlobalString('BLOCKEDLOG_REGISTRATION_NAME', $mysoc->name);
153 $companyemail = getDolGlobalString('BLOCKEDLOG_REGISTRATION_EMAIL', $mysoc->email);
154 $companycountrycode = $mysoc->country_code;
155 $companyidprof1 = getDolGlobalString('MAIN_INFO_SIREN', $mysoc->idprof1);
156 $companyidprof2 = getDolGlobalString('MAIN_INFO_SIRET', $mysoc->idprof2);
157 //$companytel = getDolGlobalString('BLOCKEDLOG_REGISTRATION_TEL', $mysoc->phone);
158
159 if (empty($companyname) || empty($companycountrycode) || empty($companyidprof1) || empty($companyidprof2) || empty($companyemail)) {
160 return false;
161 }
162 /*
163 $providerset = getDolGlobalString('MAIN_INFO_ITPROVIDER_NAME'); // Can be 'myself'
164
165 if (empty($providerset)) {
166 return false;
167 }
168 */
169
170 return true;
171}
172
173
180{
181 return isRegistrationDataSaved() && (bool) getDolGlobalString('MAIN_FIRST_REGISTRATION_OK_DATE');
182}
183
184
191function getHashUniqueIdOfRegistration($algo = 'sha256')
192{
193 global $conf;
194
195 return dol_hash('dolibarr'.$conf->file->instance_unique_id.($conf->entity > 1 ? $conf->entity : ''), $algo, 1);
196}
197
198
209function isALNEQualifiedVersion($ignoredev = 0, $ignoremodule = 0)
210{
211 global $mysoc;
212
213 // For Dev/Debug purpose: Constant set by developer to force all LNE restrictions even if country is not France so we can test them on any dev instance.
214 // Note that you can force, with this option, the enabling of the LNE restrictions, but there is no way to force the disabling of the LNE restriction.
215 if (defined('CERTIF_LNE') && (int) constant('CERTIF_LNE') === 2) {
216 return 'CERTIF_LNE_IS_2';
217 }
218
219 if (!$ignoredev && preg_match('/\-/', DOL_VERSION)) { // This is not a stable version (dev version), it can't be the certified versions.
220 return '';
221 }
222 if ($mysoc->country_code != 'FR') {
223 return '';
224 }
225 if (!defined('CERTIF_LNE') || (int) constant('CERTIF_LNE') === 0) {
226 return '';
227 }
228 if (!$ignoremodule && !isModEnabled('blockedlog')) {
229 return '';
230 }
231
232 // All conditions are ok to become a LNE certified version
233 return ($ignoredev ? '' : 'NOT_BETA+').'FR+CERTIF_LNE_IS_1'.($ignoremodule ? '' : '+MODENABLED');
234}
235
236
245function isALNERunningVersion($blockedlogusagealreadychecked = 0, $blockedlogmoduleonalreadychecked = 0)
246{
247 // For Debug help: Constant CERTIF_LNE can be set 2 by developers get mode 1 compliant with dev env.
248 // Note that you can force, with this constant, the enabling of the restrictions,
249 // but there is no way to force the disabling of a restriction.
250 if (defined('CERTIF_LNE') && (int) constant('CERTIF_LNE') === 2 // Value is 2 for debug purpose to enable restriction except https for dev env.
251 && ($blockedlogmoduleonalreadychecked || isModEnabled('blockedlog'))
252 && ($blockedlogusagealreadychecked || isBlockedLogUsed())) {
253 return true;
254 }
255 if (defined('CERTIF_LNE') && (int) constant('CERTIF_LNE') === 1 // Value is 1 when version is certified
256 && ($blockedlogmoduleonalreadychecked || isModEnabled('blockedlog'))
257 && ($blockedlogusagealreadychecked || isBlockedLogUsed())) {
258 return true;
259 }
260
261 return false;
262}
263
270function isBlockedLogUsed($ignoresystem = 0)
271{
272 global $conf, $db;
273
274 $result = true; // by default restrictions are on, so we can't disable them
275
276 // Note: if module on, we suppose it is used, if not, we check in case of it was disabled.
277 if (!isModEnabled('blockedlog')) {
278 // Test the cache key
279 if (array_key_exists('isblockedlogused', $conf->cache)) {
280 return $conf->cache['isblockedlogused'.$ignoresystem];
281 }
282
283 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog";
284 $sql .= " WHERE entity = ".((int) $conf->entity); // Sharing entity in blocked log will never be allowed
285 if ($ignoresystem) {
286 $sql .= " AND action NOT IN ('MODULE_SET', 'MODULE_RESET')";
287 }
288 $sql .= $db->plimit(1);
289
290 $resql = $db->query($sql);
291 if ($resql !== false) {
292 $obj = $db->fetch_object($resql);
293 if (!$obj) {
294 $result = false;
295 }
296 } else {
297 dol_print_error($db);
298 }
299
300 $conf->cache['isblockedlogused'.$ignoresystem] = $result;
301 }
302
303 dol_syslog("isBlockedLogUsed: ignoresystem=".$ignoresystem." returns ".(string) $result);
304
305 return $result;
306}
307
308
320function pdfCertifMentionblockedLog(&$pdf, $outputlangs, $seller, $default_font_size, &$posy, $pdftemplate)
321{
322 $result = 0;
323
324 if (in_array($seller->country_code, array('FR'))) {
325 $outputlangs->load("blockedlog");
326 $blockedlog_mention = '';
327
328 $isalne = isALNEQualifiedVersion(); // If necessary, we could replace with "if isALNERunningVersion()"
329 if ($isalne == 'CERTIF_LNE_IS_2') {
330 $blockedlog_mention = $outputlangs->transnoentitiesnoconv("InvoiceGeneratedWithLNECandidatePOSSystem");
331 } elseif ($isalne) {
332 $blockedlog_mention = $outputlangs->transnoentitiesnoconv("InvoiceGeneratedWithLNECertifiedPOSSystem");
333 }
334
335 if ($blockedlog_mention) {
336 $pdf->SetFont('', '', $default_font_size - 2);
337 $pdf->SetXY($pdftemplate->marge_gauche, $posy);
338 $pdf->MultiCell(100, 3, $blockedlog_mention, 0, 'L', false);
339 $posy = $pdf->GetY();
340 $result = 1;
341 }
342 }
343
344 return $result;
345}
346
360function sumAmountsForUnalterableEvent($block, &$refinvoicefound, &$totalhtamount, &$totalvatamount, &$totalamount, &$total_ht, &$total_vat, &$total_ttc)
361{
362 if ($block->action == 'BILL_VALIDATE') {
363 $total_ht = $block->object_data->total_ht;
364 $total_vat = $block->object_data->total_tva;
365 $total_ttc = $block->object_data->total_ttc;
366
367 // Init to avoid warnings if not initialized yet
368 if (!isset($totalamount[$block->action][$block->module_source])) {
369 $totalhtamount[$block->action][$block->module_source] = 0;
370 $totalvatamount[$block->action][$block->module_source] = 0;
371 $totalamount[$block->action][$block->module_source] = 0;
372 }
373
374 // We add total for the invoice if "invoice validate event" not yet met.
375 // If we already met the event for this object, we keep only first one but this should not happen because edition of validated invoice is not allowed on secured versions.
376 if (empty($refinvoicefound[$block->ref_object])) {
377 $totalhtamount[$block->action][$block->module_source] += $total_ht;
378 $totalvatamount[$block->action][$block->module_source] += $total_vat;
379 $totalamount[$block->action][$block->module_source] += $total_ttc;
380 }
381 $refinvoicefound[$block->ref_object] = 1;
382 } elseif ($block->action == 'PAYMENT_CUSTOMER_CREATE' || $block->action == 'PAYMENT_CUSTOMER_DELETE') {
383 $total_ht = $block->object_data->amount;
384 $total_vat = 0;
385 $total_ttc = $block->object_data->amount;
386
387 //$actionkey = $block->action;
388 $actionkey = 'PAYMENT_CUSTOMER';
389
390 // Init to avoid warnings if not initialized yet
391 if (!isset($totalamount[$actionkey][$block->module_source])) {
392 $totalhtamount[$actionkey][$block->module_source] = 0;
393 $totalvatamount[$actionkey][$block->module_source] = 0;
394 $totalamount[$actionkey][$block->module_source] = 0;
395 }
396
397 $totalhtamount[$actionkey][$block->module_source] += $total_ht;
398 $totalvatamount[$actionkey][$block->module_source] += $total_vat;
399 $totalamount[$actionkey][$block->module_source] += $total_ttc;
400 } else {
401 $total_ttc = $block->amounts;
402 }
403
404 return 1;
405}
406
407
417function callApiToGetObfuscationKey($idprof1, $registrationnumber, $force = false)
418{
419 global $mysoc, $conf;
420
421 $obfuscationkey = 'ERROR';
422
423 if (empty($idprof1)) {
424 dol_syslog("callApiToGetObfuscationKey was called with empty idprof1", LOG_DEBUG);
425 return 'ERROR callApiToGetObfuscationKey was called with empty idprof1';
426 }
427
428 //if ((isALNERunningVersion(1) || $force) && $mysoc->country_code == 'FR') {
429 $url_for_ping = getDolGlobalString('MAIN_URL_FOR_PING', "https://ping.dolibarr.org/");
430
431 $algo = 'sha256';
432 $hash_unique_id = getHashUniqueIdOfRegistration($algo); // The hash of the unique IDof instance
433
434 $t = microtime(true);
435 $micro = sprintf("%06d", (int) (($t - floor($t)) * 1000000));
436
437 $data = '';
438 $data .= 'hash_algo=dol_hash-'.urlencode($algo);
439 $data .= '&hash_unique_id='.urlencode($hash_unique_id);
440 $data .= '&action=dolibarrgetkeyobfuscation';
441 $data .= '&datesys='.urlencode(dol_print_date(dol_now('gmt'), 'standard', 'gmt').'.'.$micro);
442 $data .= '&version='.(float) DOL_VERSION;
443 $data .= '&version_full='.urlencode(DOL_VERSION);
444 $data .= '&versionblockedlog='.(float) getBlockedLogVersionToShow();
445 $data .= '&versionblockedlog_full='.urlencode(getBlockedLogVersionToShow());
446
447 $data .= '&entity='.(int) $conf->entity;
448
449 $data .= '&company_idprof1='.urlencode(dol_sanitizeKeyCode($idprof1));
450 $data .= '&registrationnumber='.urlencode(dol_sanitizeKeyCode($registrationnumber));
451
452 $addheaders = array();
453 $timeoutconnect = 3;
454 $timeoutresponse = 3;
455
456 dol_syslog("callApiToGetObfuscationKey call remote URL idprod1=".dol_sanitizeKeyCode($idprof1), LOG_DEBUG);
457 dol_syslog("callApiToGetObfuscationKey call remote URL idprod1=".dol_sanitizeKeyCode($idprof1), LOG_DEBUG, 0, '_dolibarrgetkeyobfuscation');
458
459 include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
460
461 $maxretry = getDolGlobalInt('BLOCKEDLOG_MAX_TRY_FOR_REMOTE_OBFUSCATION_KEY', 2);
462 $retrydelay = 300000; // 300ms, in microseconds
463
464 for ($tryid = 1; $tryid <= $maxretry; $tryid++) {
465 $retryable = false;
466
467 try {
468 $tmpresult = getURLContent($url_for_ping, 'POST', $data, 1, $addheaders, array('https'), 0, -1, $timeoutconnect, $timeoutresponse, array());
469 usleep(10000);
470
471 // Add a warning in log in case of error
472 if ($tmpresult['http_code'] == 0 && !empty($tmpresult['curl_error_msg'])) {
473 $logerrormessage = 'Error: '.$tmpresult['curl_error_msg'];
474 $obfuscationkey = 'ERROR '.$tmpresult['curl_error_msg'];
475 dol_syslog("callApiToGetObfuscationKey result error when getting obfuscation key (try ".$tryid."/".$maxretry."): ".$logerrormessage, LOG_WARNING);
476 dol_syslog("callApiToGetObfuscationKey result error when getting obfuscation key (try ".$tryid."/".$maxretry."): ".$logerrormessage, LOG_WARNING, 0, '_dolibarrgetkeyobfuscation');
477 $retryable = true; // No connection / timeout, worth retrying
478 } elseif ($tmpresult['http_code'] >= 500) {
479 $logerrormessage = 'Error: '.$tmpresult['http_code'].' '.$tmpresult['content'];
480 $obfuscationkey = 'ERROR '.$tmpresult['http_code'].' '.$tmpresult['content'];
481 dol_syslog("callApiToGetObfuscationKey result error when getting obfuscation key (try ".$tryid."/".$maxretry."): ".$logerrormessage, LOG_WARNING);
482 dol_syslog("callApiToGetObfuscationKey result error when getting obfuscation key (try ".$tryid."/".$maxretry."): ".$logerrormessage, LOG_WARNING, 0, '_dolibarrgetkeyobfuscation');
483 $retryable = true; // Remote server error, may be transient
484 } elseif ($tmpresult['http_code'] == 403) {
485 $logerrormessage = 'Error: '.$tmpresult['http_code'].' '.$tmpresult['content'];
486 $obfuscationkey = 'ERROR '.$tmpresult['http_code'].' '.$tmpresult['content'];
487 dol_syslog("callApiToGetObfuscationKey result error when getting obfuscation key (try ".$tryid."/".$maxretry."): ".$logerrormessage, LOG_WARNING);
488 dol_syslog("callApiToGetObfuscationKey result error when getting obfuscation key (try ".$tryid."/".$maxretry."): ".$logerrormessage, LOG_WARNING, 0, '_dolibarrgetkeyobfuscation');
489 $retryable = true; // ping.dolibarr.org is Cloudflare-fronted; a 403 from a
490 // shared/CI IP is far more likely bot-mitigation on that
491 // specific request than a permanent application-level
492 // rejection, so it is worth a retry too
493 } elseif ($tmpresult['http_code'] != 200) {
494 $logerrormessage = 'Error: '.$tmpresult['http_code'].' '.$tmpresult['content'];
495 $obfuscationkey = 'ERROR '.$tmpresult['http_code'].' '.$tmpresult['content'];
496 dol_syslog("callApiToGetObfuscationKey result error when getting obfuscation key: ".$logerrormessage, LOG_WARNING);
497 dol_syslog("callApiToGetObfuscationKey result error when getting obfuscation key: ".$logerrormessage, LOG_WARNING, 0, '_dolibarrgetkeyobfuscation');
498 } else {
499 $reg = array();
500 if (preg_match('/(DOLOBFUSCKEY.*)/', $tmpresult['content'], $reg)) { // gitleaks:allow $tmpresult['content'] may contains text comments before the line 'DOLOBFUSCKEY1...,DOLOBFUSCKEY2...'
501 $obfuscationkey = $reg[1];
502 dol_syslog("callApiToGetObfuscationKey we got the remote obfuscation key", LOG_DEBUG);
503 dol_syslog("callApiToGetObfuscationKey we got the remote obfuscation key", LOG_DEBUG, 0, '_dolibarrgetkeyobfuscation');
504 } else {
505 $obfuscationkey = 'ERROR '.$tmpresult['content'];
506 dol_syslog("callApiToGetObfuscationKey result error when getting obfuscation key: ".$tmpresult['content'], LOG_WARNING);
507 dol_syslog("callApiToGetObfuscationKey result error when getting obfuscation key: ".$tmpresult['content'], LOG_WARNING, 0, '_dolibarrgetkeyobfuscation');
508 }
509 }
510 } catch (Exception $e) {
511 $obfuscationkey = 'ERROR '.$e->getMessage();
512 dol_syslog("callApiToGetObfuscationKey result error (try ".$tryid."/".$maxretry."): ".$e->getMessage(), LOG_ERR);
513 dol_syslog("callApiToGetObfuscationKey result error (try ".$tryid."/".$maxretry."): ".$e->getMessage(), LOG_ERR, 0, '_dolibarrgetkeyobfuscation');
514 $retryable = true; // Network exception, worth retrying
515 }
516
517 if (!$retryable || $tryid == $maxretry) {
518 break;
519 }
520
521 usleep($retrydelay);
522 }
523
524 return $obfuscationkey;
525}
526
527
540/*
541function callApiToPushCounter($id, $signature, $datecreation, $test, $previousid, $previoussignature, $previousdatecreation)
542{
543 global $mysoc, $conf;
544
545 if (isALNERunningVersion(1) && $mysoc->country_code == 'FR') {
546 // Push last rowid + signature to remote dolibarr server
547 // Do it only for selected events: BILL_VALIDATE ?
548
549 // Code here is similar to the one into printCodeForPing(), except that message code/properties/fields may differ.
550 $url_for_ping = getDolGlobalString('MAIN_URL_FOR_PING', "https://ping.dolibarr.org/");
551
552 $algo = 'sha256';
553 $hash_unique_id = getHashUniqueIdOfRegistration($algo); // The hash of the unique IDof instance
554
555 $t = microtime(true);
556 $micro = sprintf("%06d", (int) (($t - floor($t)) * 1000000));
557
558 $data = '';
559 $data .= 'hash_algo=dol_hash-'.urlencode($algo);
560 $data .= '&hash_unique_id='.urlencode($hash_unique_id);
561 $data .= '&action=dolibarrpushcounter';
562 $data .= '&datesys='.urlencode(dol_print_date(dol_now('gmt'), 'standard', 'gmt').'.'.$micro);
563 $data .= '&version='.(float) DOL_VERSION;
564 $data .= '&version_full='.urlencode(DOL_VERSION);
565 $data .= '&versionblockedlog='.(float) getBlockedLogVersionToShow();
566 $data .= '&versionblockedlog_full='.urlencode(getBlockedLogVersionToShow());
567
568 $data .= '&entity='.(int) $conf->entity;
569
570 $data .= '&lastrowid='.(int) $id;
571 $data .= '&lastsignature='.urlencode($signature);
572 $data .= '&lastdatecreation='.urlencode(dol_print_date($datecreation, 'standard', 'gmt'));
573 $data .= '&previousrowid='.(int) $previousid;
574 $data .= '&previoussignature='.urlencode($previoussignature);
575 $data .= '&previousdatecreation='.urlencode(dol_print_date($previousdatecreation, 'standard', 'gmt'));
576 if ($test) {
577 $data .= '&test=1';
578 }
579
580 $addheaders = array();
581 $timeoutconnect = 1;
582 $timeoutresponse = 1;
583
584 $conf->global->BLOCKEDLOG_RANDOMRANGE_FOR_TRACKING = 1; // Force probability to 1
585
586 // Probability will be between 1/10 by default and 1/1 if const BLOCKEDLOG_RANDOMRANGE_FOR_TRACKING is set to 1. Can't be lower than 1/10.
587 $BLOCKEDLOG_RANDOMRANGE_FOR_TRACKING = min(10, getDolGlobalInt('BLOCKEDLOG_RANDOMRANGE_FOR_TRACKING', 10));
588 $random = 1;
589 //$BLOCKEDLOG_RANDOMRANGE_FOR_TRACKING = 1; // To force track at every call
590 if ($BLOCKEDLOG_RANDOMRANGE_FOR_TRACKING > 1) {
591 $random = random_int(1, (int) $BLOCKEDLOG_RANDOMRANGE_FOR_TRACKING);
592 }
593
594 if ($random == 1) { // 1 chance on BLOCKEDLOG_RANDOMRANGE_FOR_TRACKING
595 dol_syslog("callApiToPushCounter create Record is selected to be remotely pushed for tracking", LOG_DEBUG);
596
597 include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
598 try {
599 $tmpresult = getURLContent($url_for_ping, 'POST', $data, 1, $addheaders, array('https'), 0, -1, $timeoutconnect, $timeoutresponse, array(), '_dolibarrpushcounter');
600 usleep(1000);
601
602 // Add a warning in log in case of error
603 if ($tmpresult['http_code'] != 200) {
604 $logerrormessage = 'Error: '.$tmpresult['http_code'].' '.$tmpresult['content'];
605 dol_syslog("callApiToPushCounter create Error when pushing track info: ".$logerrormessage, LOG_WARNING);
606 }
607 } catch (Exception $e) {
608 dol_syslog("callApiToPushCounter create Error ".$e->getMessage(), LOG_ERR);
609 }
610 } else {
611 dol_syslog("callApiToPushCounter create Record is NOT selected to be remotely pushed for tracking", LOG_DEBUG);
612 }
613
614 return 1;
615 }
616
617 return 0;
618}
619*/
620
621
630{
631 global $user;
632
633 return (((getDolGlobalString('BLOCKEDLOG_FOR_TAX_AUDITOR') && $user->socid) || getDolGlobalString('BLOCKEDLOG_FOR_TAX_AUDITOR') == '2') ? 1 : 0);
634}
635
636
637
650function pdfWriteBlockedLogSignature(&$pdf, $outputlangs, $page_height, $object, &$w, &$posx, &$posy)
651{
652 global $db;
653
654 // Transaction ID
655 if (isALNERunningVersion() && isModEnabled('blockedlog')) {
656 if ($object->status > $object::STATUS_DRAFT) {
657 $unalterablelogid = 'UNDEFINED'; // By default
658
659 $sql = "SELECT signature FROM ".MAIN_DB_PREFIX."blockedlog";
660 $sql .= " WHERE action = 'BILL_VALIDATE' AND element = 'facture' AND ref_object = '".$db->escape($object->ref)."'";
661 $sql .= $db->order('rowid', 'DESC');
662 $sql .= $db->plimit(1);
663
664 $resql = $db->query($sql);
665 if ($resql) {
666 $obj = $db->fetch_object($resql);
667 if ($obj) {
668 $unalterablelogid = $obj->signature;
669 }
670 }
671
672 if ($unalterablelogid != 'UNDEFINED') {
673 $pdf->SetXY($posx, $posy);
674 $pdf->SetTextColor(0, 0, 60);
675 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SignatureID")." : ".dol_trunc(strtoupper($unalterablelogid), 10), '', 'R');
676 $posy += 3;
677 }
678
679 $isADuplicata = ($object->pos_print_counter >= 2);
680 if ($isADuplicata) {
681 $pdf->SetXY($posx, $posy);
682 $pdf->SetTextColor(0, 0, 60);
683 $pdf->MultiCell($w, 3, '*** '.$outputlangs->trans("DUPLICATA").(getDolGlobalString('TAKEPOS_SHOW_PRINT_COUNTER_ON_RECEIPT') ? ' (no '.($object->pos_print_counter - 1).')' : '').' ***', '', 'R');
684 $posy += 3;
685 }
686 }
687
688 if ($object->status == $object::STATUS_DRAFT) {
689 $pdf->SetXY($posx, $posy);
690 $pdf->SetTextColor(0, 0, 60);
691 $pdf->MultiCell($w, 3, '*** '.strtoupper($outputlangs->trans("TemporaryReceipt")).' ***', '', 'R');
692 $posy += 3;
693 }
694 }
695}
696
697
698
705{
706 global $conf, $db, $langs, $mysoc;
707
708 include_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
709
710 $blocklog_static = new BlockedLog($db);
711
712 // Loop on all entities found in llx_blockedlog
713 $listofentities = array();
714 $sql = "SELECT DISTINCT entity FROM ".MAIN_DB_PREFIX."blockedlog";
715 $resql = $db->query($sql);
716 if ($resql) {
717 while ($obj = $db->fetch_object($resql)) {
718 $listofentities[] = $obj->entity;
719 }
720 } else {
721 print '<tr class="trforrunsql"><td colspan="4">';
722 print '<b>'.$langs->trans('InitEndFlagFile')."</b>:\n";
723 print 'Error: Failed to get list of entities in blockedlog table';
724 print '</td></tr>';
725 return -1;
726 }
727
728 foreach ($listofentities as $entity) {
729 print '<tr class="trforrunsql"><td colspan="4">';
730 print '<b>'.$langs->trans('InitEndFlagFile')." (entity = ".$entity.")</b>:\n";
731
732 // Load the data of company (country, ...). Erase current one so this function can be used by migration script only.
733 $conf->setEntityValues($db, $entity);
734 $mysoc = new Societe($db);
735 $mysoc->setMysoc($conf);
736
737 $maxid = 0;
738 $sql = "SELECT MAX(rowid) as maxid FROM ".MAIN_DB_PREFIX."blockedlog WHERE entity = ".((int) $entity);
739 $resql = $db->query($sql);
740 if ($resql) {
741 $obj = $db->fetch_object($resql);
742 if ($obj) {
743 $maxid = $obj->maxid;
744 }
745 } else {
746 print 'Error: Failed to get max id of blockedlog table';
747 print '</td></tr>';
748 return -1;
749 }
750
751 $blocklog_static->fetch($maxid);
752
753 $lockfile = $blocklog_static->getEndOfChainFlagFile();
754
755 // Lock acquired, we can now write the new .end file
756 $stringtowrite = 'BLOCKEDLOGHEAD '.$blocklog_static->id." ".dol_print_date($blocklog_static->date_creation, 'dayhourrfc', 'gmt')." ".(string) $blocklog_static->signature;
757
758 if (isALNERunningVersion(1) && $mysoc->country_code == 'FR') {
759 $remoteobfuscationkey = $blocklog_static->getObfuscationKey();
760 if (empty($remoteobfuscationkey)) {
761 print "Error: Failed to get the remote obfuscation key. We can't record the end of chain flag file so we abort the transaction.";
762 print '</td></tr>';
763 return -1;
764 }
765
766 $stringtowriteencoded = dolEncrypt($stringtowrite, $remoteobfuscationkey, '', '', 'dolobfuscationv1-'.$mysoc->idprof1.'-'.$blocklog_static->id);
767 } else {
768 $stringtowriteencoded = dolEncrypt($stringtowrite, '', '', '', 'dolcrypt-'.$mysoc->idprof1.'-'.$blocklog_static->id);
769 }
770
771 // Update or create the .end flag file.
772 if (defined('BLOCKEDLOG_END_FLAG_IN_A_FILE')) { // If we want to store the .end flag into a files instead of database (not used, may be for a future need)
773 $lockhandle = fopen($lockfile, 'w+');
774 if ($lockhandle) {
775 if (fwrite($lockhandle, $stringtowriteencoded."\n") === false) {
776 print "Cannot write to the blockedlog .end file ".$lockfile;
777 print '</td></tr>';
778 return -1;
779 }
780
781 fclose($lockhandle); // Remove the lock
782 dolChmod($lockfile);
783 } else {
784 print "Cannot open for writing the blockedlog .end file ".$lockfile;
785 print '</td></tr>';
786 return -1;
787 }
788 } else {
789 $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
790 $sql .= " WHERE name = '".$db->escape(basename($lockfile))."' AND entity = ".((int) $conf->entity);
791 $resql = $db->query($sql);
792
793 $sql = "INSERT INTO ".MAIN_DB_PREFIX."const(name, value, type, visible, note, entity)";
794 $sql .= " VALUES('".$db->escape(basename($lockfile))."', '".$db->escape($stringtowriteencoded)."', 'chaine', 0, 'Blockedlog end of chain flag', ".((int) $conf->entity).")";
795 $resql = $db->query($sql);
796 if (!$resql) {
797 print "Cannot open for writing the blockedlog .end file ".basename($lockfile);
798 print '</td></tr>';
799 return -1;
800 }
801 }
802
803 print $langs->trans("Done");
804 print '</td></tr>';
805 }
806
807 return 1;
808}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
migrate_blockedlog_add_end_file()
Migrate an old database to add the .end flag.
sumAmountsForUnalterableEvent($block, &$refinvoicefound, &$totalhtamount, &$totalvatamount, &$totalamount, &$total_ht, &$total_vat, &$total_ttc)
sumAmountsForUnalterableEvent
getBlockedLogVersionToShow()
Define head array for tabs of blockedlog tools setup pages.
pdfWriteBlockedLogSignature(&$pdf, $outputlangs, $page_height, $object, &$w, &$posx, &$posy)
Add some information from the blockedlog module.
isALNEQualifiedVersion($ignoredev=0, $ignoremodule=0)
Return if the version is a candidate version to get the LNE certification and if the prerequisites ar...
isRegistrationDataSaved()
Return if the KYC mandatory parameters are set Must be the same fields than the one defined as mandat...
userIsTaxAuditor()
Call remote API service to push the last counter and signature.
pdfCertifMentionblockedLog(&$pdf, $outputlangs, $seller, $default_font_size, &$posy, $pdftemplate)
Add legal mention.
isBlockedLogUsed($ignoresystem=0)
Return if the blocked log was already used to block some events.
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.
callApiToGetObfuscationKey($idprof1, $registrationnumber, $force=false)
Call remote API service to get the obfuscation key.
Class to manage Blocked Log.
Class to manage third parties objects (customers, suppliers, prospects...)
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:
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:65
dol_now($mode='gmt')
Return date for now.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getMultidirOutput($object, $module='', $forobject=0, $mode='output')
Return the full path of the directory where a module (or an object of a module) stores its files.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
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.
complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode='add', $filterorigmodule='')
Complete or removed entries into a head array (used to build tabs).
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_sanitizeKeyCode($str)
Clean a string to use it as a key or code.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getURLContent($url, $postorget='GET', $param='', $followlocation=1, $addheaders=array(), $allowedschemes=array('http', 'https'), $localurl=0, $ssl_verifypeer=-1, $timeoutconnect=0, $timeoutresponse=0, $otherCurlOptions=array(), $morelogsuffix='')
Function to get a content from an URL (use proxy if proxy defined).
dol_hash($chain, $type='0', $nosalt=0, $mode=0)
Returns a hash (non reversible encryption) of a string.
dolEncrypt($chain, $key='', $ciphering='', $forceseed='', $obfuscationmode='dolcrypt')
Encode a string with a symmetric encryption.