26 require
'../../main.inc.php';
27 require_once DOL_DOCUMENT_ROOT.
'/blockedlog/lib/blockedlog.lib.php';
28 require_once DOL_DOCUMENT_ROOT.
'/blockedlog/class/blockedlog.class.php';
29 require_once DOL_DOCUMENT_ROOT.
'/blockedlog/class/authority.class.php';
30 require_once DOL_DOCUMENT_ROOT.
'/core/lib/admin.lib.php';
31 require_once DOL_DOCUMENT_ROOT.
'/core/lib/date.lib.php';
34 $langs->loadLangs(array(
"admin",
"other",
"blockedlog",
"bills"));
36 if ((!$user->admin && empty($user->rights->blockedlog->read)) || empty($conf->blockedlog->enabled)) {
40 $action =
GETPOST(
'action',
'aZ09');
41 $contextpage =
GETPOST(
'contextpage',
'aZ') ?
GETPOST(
'contextpage',
'aZ') :
'blockedloglist';
42 $backtopage =
GETPOST(
'backtopage',
'alpha');
43 $optioncss =
GETPOST(
'optioncss',
'aZ');
45 $search_showonlyerrors =
GETPOST(
'search_showonlyerrors',
'int');
46 if ($search_showonlyerrors < 0) {
47 $search_showonlyerrors = 0;
50 $search_startyear =
GETPOST(
'search_startyear',
'int');
51 $search_startmonth =
GETPOST(
'search_startmonth',
'int');
52 $search_startday =
GETPOST(
'search_startday',
'int');
53 $search_endyear =
GETPOST(
'search_endyear',
'int');
54 $search_endmonth =
GETPOST(
'search_endmonth',
'int');
55 $search_endday =
GETPOST(
'search_endday',
'int');
56 $search_id =
GETPOST(
'search_id',
'alpha');
57 $search_fk_user =
GETPOST(
'search_fk_user',
'intcomma');
59 if ($search_startyear !=
'') {
60 $search_start =
dol_mktime(0, 0, 0, $search_startmonth, $search_startday, $search_startyear);
63 if (
GETPOST(
'search_endyear') !=
'') {
66 $search_code =
GETPOST(
'search_code',
'alpha');
67 $search_ref =
GETPOST(
'search_ref',
'alpha');
68 $search_amount =
GETPOST(
'search_amount',
'alpha');
70 if (($search_start == -1 || empty($search_start)) && !
GETPOSTISSET(
'search_startmonth')) {
75 $limit =
GETPOST(
'limit',
'int') ?
GETPOST(
'limit',
'int') : $conf->liste_limit;
76 $sortfield =
GETPOST(
'sortfield',
'aZ09comma');
77 $sortorder =
GETPOST(
'sortorder',
'aZ09comma');
79 if (empty($page) || $page == -1) {
82 $offset = $limit * $page;
83 $pageprev = $page - 1;
84 $pagenext = $page + 1;
86 if (empty($sortfield)) {
89 if (empty($sortorder)) {
94 $block_static->loadTrackedEvents();
99 $max_execution_time_for_importexport = (empty($conf->global->EXPORT_MAX_EXECUTION_TIME) ? 300 : $conf->global->EXPORT_MAX_EXECUTION_TIME);
100 $max_time = @ini_get(
"max_execution_time");
101 if ($max_time && $max_time < $max_execution_time_for_importexport) {
102 dol_syslog(
"max_execution_time=".$max_time.
" is lower than max_execution_time_for_importexport=".$max_execution_time_for_importexport.
". We try to increase it dynamically.");
103 @ini_set(
"max_execution_time", $max_execution_time_for_importexport);
112 if (
GETPOST(
'button_removefilter_x',
'alpha') ||
GETPOST(
'button_removefilter.x',
'alpha') ||
GETPOST(
'button_removefilter',
'alpha')) {
114 $search_fk_user =
'';
120 $search_showonlyerrors = 0;
122 $search_array_options = array();
125 if ($action ===
'downloadblockchain') {
128 $bc = $auth->getLocalBlockChain();
130 header(
'Content-Type: application/octet-stream');
131 header(
"Content-Transfer-Encoding: Binary");
132 header(
"Content-disposition: attachment; filename=\"".$auth->signature.
".certif\"");
137 } elseif (
GETPOST(
'downloadcsv',
'alpha')) {
145 $sql =
"SELECT rowid,date_creation,tms,user_fullname,action,amounts,element,fk_object,date_object,ref_object,signature,fk_user,object_data";
146 $sql .=
" FROM ".MAIN_DB_PREFIX.
"blockedlog";
147 $sql .=
" WHERE entity = ".$conf->entity;
148 if (
GETPOST(
'monthtoexport',
'int') > 0 ||
GETPOST(
'yeartoexport',
'int') > 0) {
151 $sql .=
" AND date_creation BETWEEN '".$db->idate($dates).
"' AND '".$db->idate($datee).
"'";
153 $sql .=
" ORDER BY rowid ASC";
154 $sql .= $db->plimit(1);
156 $res = $db->query($sql);
159 $obj = $db->fetch_object($res);
161 $previoushash = $block_static->getPreviousHash(0, $obj->rowid);
162 $firstid = $obj->rowid;
164 $previoushash =
'nodata';
175 $sql =
"SELECT rowid,date_creation,tms,user_fullname,action,amounts,element,fk_object,date_object,ref_object,signature,fk_user,object_data";
176 $sql .=
" FROM ".MAIN_DB_PREFIX.
"blockedlog";
177 $sql .=
" WHERE entity = ".$conf->entity;
178 if (
GETPOST(
'monthtoexport',
'int') > 0 ||
GETPOST(
'yeartoexport',
'int') > 0) {
181 $sql .=
" AND date_creation BETWEEN '".$db->idate($dates).
"' AND '".$db->idate($datee).
"'";
183 $sql .=
" ORDER BY rowid ASC";
185 $res = $db->query($sql);
187 header(
'Content-Type: application/octet-stream');
188 header(
"Content-Transfer-Encoding: Binary");
189 header(
"Content-disposition: attachment; filename=\"unalterable-log-archive-".$dolibarr_main_db_name.
"-".(
GETPOST(
'yeartoexport',
'int') > 0 ?
GETPOST(
'yeartoexport',
'int').(
GETPOST(
'monthtoexport',
'int') > 0 ?sprintf(
"%02d",
GETPOST(
'monthtoexport',
'int')) :
'').
'-' :
'').$previoushash.
".csv\"");
191 print $langs->transnoentities(
'Id')
192 .
';'.$langs->transnoentities(
'Date')
193 .
';'.$langs->transnoentities(
'User')
194 .
';'.$langs->transnoentities(
'Action')
195 .
';'.$langs->transnoentities(
'Element')
196 .
';'.$langs->transnoentities(
'Amounts')
197 .
';'.$langs->transnoentities(
'ObjectId')
198 .
';'.$langs->transnoentities(
'Date')
199 .
';'.$langs->transnoentities(
'Ref')
200 .
';'.$langs->transnoentities(
'Fingerprint')
201 .
';'.$langs->transnoentities(
'Status')
202 .
';'.$langs->transnoentities(
'Note')
203 .
';'.$langs->transnoentities(
'FullData')
209 while ($obj = $db->fetch_object($res)) {
212 $block_static->id = $obj->rowid;
213 $block_static->date_creation = $db->jdate($obj->date_creation);
214 $block_static->date_modification = $db->jdate($obj->tms);
215 $block_static->action = $obj->action;
216 $block_static->fk_object = $obj->fk_object;
217 $block_static->element = $obj->element;
218 $block_static->amounts = (double) $obj->amounts;
219 $block_static->ref_object = $obj->ref_object;
220 $block_static->date_object = $db->jdate($obj->date_object);
221 $block_static->user_fullname = $obj->user_fullname;
222 $block_static->fk_user = $obj->fk_user;
223 $block_static->signature = $obj->signature;
224 $block_static->object_data = $block_static->dolDecodeBlockedData($obj->object_data);
226 $checksignature = $block_static->checkSignature($previoushash);
228 if ($checksignature) {
229 $statusofrecord =
'Valid';
230 if ($loweridinerror > 0) {
231 $statusofrecordnote =
'ValidButFoundAPreviousKO';
233 $statusofrecordnote =
'';
236 $statusofrecord =
'KO';
237 $statusofrecordnote =
'LineCorruptedOrNotMatchingPreviousOne';
238 $loweridinerror = $obj->rowid;
242 $statusofrecordnote = $langs->trans(
"PreviousFingerprint").
': '.$previoushash.($statusofrecordnote ?
' - '.$statusofrecordnote :
'');
245 print
';'.$obj->date_creation;
246 print
';"'.str_replace(
'"',
'""', $obj->user_fullname).
'"';
247 print
';'.$obj->action;
248 print
';'.$obj->element;
249 print
';'.$obj->amounts;
250 print
';'.$obj->fk_object;
251 print
';'.$obj->date_object;
252 print
';"'.str_replace(
'"',
'""', $obj->ref_object).
'"';
253 print
';'.$obj->signature;
254 print
';'.$statusofrecord;
255 print
';'.$statusofrecordnote;
256 print
';"'.str_replace(
'"',
'""', $obj->object_data).
'"';
260 $previoushash = $obj->signature;
279 if (
GETPOST(
'withtab',
'alpha')) {
280 $title = $langs->trans(
"ModuleSetup").
' '.$langs->trans(
'BlockedLog');
282 $title = $langs->trans(
"BrowseBlockedLog");
284 $help_url=
"EN:Module_Unalterable_Archives_-_Logs|FR:Module_Archives_-_Logs_Inaltérable";
290 $blocks = $block_static->getLog(
'all', $search_id, $MAXLINES, $sortfield, $sortorder, $search_fk_user, $search_start, $search_end, $search_ref, $search_amount, $search_code);
291 if (!is_array($blocks)) {
293 setEventMessages($langs->trans(
"TooManyRecordToScanRestrictFilters", $MAXLINES),
null,
'errors');
295 dol_print_error($block_static->db, $block_static->error, $block_static->errors);
301 if (
GETPOST(
'withtab',
'alpha')) {
302 $linkback =
'<a href="'.($backtopage ? $backtopage : DOL_URL_ROOT.
'/admin/modules.php').
'">'.$langs->trans(
"BackToModuleList").
'</a>';
307 if (
GETPOST(
'withtab',
'alpha')) {
312 print
'<span class="opacitymedium hideonsmartphone">'.$langs->trans(
"FingerprintsDesc").
"<br></span>\n";
317 if (!empty($contextpage) && $contextpage != $_SERVER[
"PHP_SELF"]) {
318 $param .=
'&contextpage='.urlencode($contextpage);
320 if ($limit > 0 && $limit != $conf->liste_limit) {
321 $param .=
'&limit='.urlencode($limit);
323 if ($search_id !=
'') {
324 $param .=
'&search_id='.urlencode($search_id);
326 if ($search_fk_user > 0) {
327 $param .=
'&search_fk_user='.urlencode($search_fk_user);
329 if ($search_startyear > 0) {
330 $param .=
'&search_startyear='.urlencode($search_startyear);
332 if ($search_startmonth > 0) {
333 $param .=
'&search_startmonth='.urlencode($search_startmonth);
335 if ($search_startday > 0) {
336 $param .=
'&search_startday='.urlencode($search_startday);
338 if ($search_endyear > 0) {
339 $param .=
'&search_endyear='.urlencode($search_endyear);
341 if ($search_endmonth > 0) {
342 $param .=
'&search_endmonth='.urlencode($search_endmonth);
344 if ($search_endday > 0) {
345 $param .=
'&search_endday='.urlencode($search_endday);
347 if ($search_showonlyerrors > 0) {
348 $param .=
'&search_showonlyerrors='.urlencode($search_showonlyerrors);
350 if ($optioncss !=
'') {
351 $param .=
'&optioncss='.urlencode($optioncss);
353 if (
GETPOST(
'withtab',
'alpha')) {
354 $param .=
'&withtab='.urlencode(
GETPOST(
'withtab',
'alpha'));
360 print
'<form method="POST" id="searchFormList" action="'.$_SERVER[
"PHP_SELF"].
'">';
361 print
'<input type="hidden" name="token" value="'.newToken().
'">';
363 print
'<div class="right">';
364 print $langs->trans(
"RestrictYearToExport").
': ';
365 $smonth =
GETPOST(
'monthtoexport',
'int');
368 $retstring .=
'<select class="flat valignmiddle maxwidth75imp marginrightonly" id="monthtoexport" name="monthtoexport">';
369 $retstring .=
'<option value="0" selected> </option>';
370 for ($month = 1; $month <= 12; $month++) {
371 $retstring .=
'<option value="'.$month.
'"'.($month == $smonth ?
' selected' :
'').
'>';
372 $retstring .=
dol_print_date(mktime(12, 0, 0, $month, 1, 2000),
"%b");
373 $retstring .=
"</option>";
375 $retstring .=
"</select>";
377 print
'<input type="text" name="yeartoexport" class="valignmiddle maxwidth50imp" value="'.GETPOST(
'yeartoexport',
'int').
'">';
378 print
'<input type="hidden" name="withtab" value="'.GETPOST(
'withtab',
'alpha').
'">';
379 print
'<input type="submit" name="downloadcsv" class="button" value="'.$langs->trans(
'DownloadLogCSV').
'">';
380 if (!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY)) {
381 print
' | <a href="?action=downloadblockchain'.(GETPOST(
'withtab',
'alpha') ?
'&withtab='.GETPOST(
'withtab',
'alpha') :
'').
'">'.$langs->trans(
'DownloadBlockChain').
'</a>';
387 print
'<form method="POST" id="searchFormList" action="'.$_SERVER[
"PHP_SELF"].
'">';
389 print
'<div class="div-table-responsive">';
391 if ($optioncss !=
'') {
392 print
'<input type="hidden" name="optioncss" value="'.$optioncss.
'">';
394 print
'<input type="hidden" name="token" value="'.newToken().
'">';
395 print
'<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
396 print
'<input type="hidden" name="action" value="list">';
397 print
'<input type="hidden" name="sortfield" value="'.$sortfield.
'">';
398 print
'<input type="hidden" name="sortorder" value="'.$sortorder.
'">';
399 print
'<input type="hidden" name="page" value="'.$page.
'">';
400 print
'<input type="hidden" name="contextpage" value="'.$contextpage.
'">';
401 print
'<input type="hidden" name="withtab" value="'.GETPOST(
'withtab',
'alpha').
'">';
403 print
'<table class="noborder centpercent">';
406 print
'<tr class="liste_titre_filter">';
408 print
'<td class="liste_titre"><input type="text" class="maxwidth50" name="search_id" value="'.dol_escape_htmltag($search_id).
'"></td>';
410 print
'<td class="liste_titre">';
412 print
$form->selectDate($search_start,
'search_start');
415 print
$form->selectDate($search_end,
'search_end');
419 print
'<td class="liste_titre">';
420 print
$form->select_dolusers($search_fk_user,
'search_fk_user', 1,
null, 0,
'',
'', 0, 0, 0,
'', 0,
'',
'maxwidth200');
425 $langs->load(
"blockedlog");
426 print
'<td class="liste_titre">';
427 print
$form->selectarray(
'search_code', $block_static->trackedevents, $search_code, 1, 0, 0,
'', 1, 0, 0,
'ASC',
'maxwidth200', 1);
431 print
'<td class="liste_titre"><input type="text" class="maxwidth50" name="search_ref" value="'.dol_escape_htmltag($search_ref).
'"></td>';
434 print
'<td class="liste_titre"></td>';
437 print
'<td class="liste_titre right"><input type="text" class="maxwidth50" name="search_amount" value="'.dol_escape_htmltag($search_amount).
'"></td>';
440 print
'<td class="liste_titre"></td>';
443 print
'<td class="liste_titre"></td>';
446 print
'<td class="liste_titre">';
447 $array = array(
"1"=>$langs->trans(
"OnlyNonValid"));
448 print
$form->selectarray(
'search_showonlyerrors', $array, $search_showonlyerrors, 1);
452 print
'<td class="liste_titre"></td>';
455 print
'<td class="liste_titre" align="middle">';
456 $searchpicto =
$form->showFilterButtons();
462 print
'<tr class="liste_titre">';
463 print
getTitleFieldOfList($langs->trans(
'#'), 0, $_SERVER[
"PHP_SELF"],
'rowid',
'', $param,
'', $sortfield, $sortorder,
'minwidth50 ').
"\n";
464 print
getTitleFieldOfList($langs->trans(
'Date'), 0, $_SERVER[
"PHP_SELF"],
'date_creation',
'', $param,
'', $sortfield, $sortorder,
'').
"\n";
465 print
getTitleFieldOfList($langs->trans(
'Author'), 0, $_SERVER[
"PHP_SELF"],
'user_fullname',
'', $param,
'', $sortfield, $sortorder,
'').
"\n";
466 print
getTitleFieldOfList($langs->trans(
'Action'), 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'', $sortfield, $sortorder,
'').
"\n";
467 print
getTitleFieldOfList($langs->trans(
'Ref'), 0, $_SERVER[
"PHP_SELF"],
'ref_object',
'', $param,
'', $sortfield, $sortorder,
'').
"\n";
468 print
getTitleFieldOfList(
'', 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'', $sortfield, $sortorder,
'').
"\n";
469 print
getTitleFieldOfList($langs->trans(
'Amount'), 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'class="right"', $sortfield, $sortorder,
'').
"\n";
470 print
getTitleFieldOfList($langs->trans(
'DataOfArchivedEvent'), 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'align="center"', $sortfield, $sortorder,
'').
"\n";
471 print
getTitleFieldOfList($langs->trans(
'Fingerprint'), 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'', $sortfield, $sortorder,
'').
"\n";
472 print
getTitleFieldOfList($langs->trans(
'Status'), 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'align="center"', $sortfield, $sortorder,
'').
"\n";
473 print
getTitleFieldOfList(
'', 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'align="center"', $sortfield, $sortorder,
'').
"\n";
474 print
getTitleFieldOfList(
'<span id="blockchainstatus"></span>', 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'align="center"', $sortfield, $sortorder,
'').
"\n";
477 if (!empty($conf->global->BLOCKEDLOG_SCAN_ALL_FOR_LOWERIDINERROR)) {
485 $checkresult = array();
486 $checkdetail = array();
487 if (is_array($blocks)) {
488 foreach ($blocks as &$block) {
489 $tmpcheckresult = $block->checkSignature(
'', 1);
491 $checksignature = $tmpcheckresult[
'checkresult'];
493 $checkresult[$block->id] = $checksignature;
494 $checkdetail[$block->id] = $tmpcheckresult;
496 if (!$checksignature) {
497 if (empty($loweridinerror)) {
498 $loweridinerror = $block->id;
500 $loweridinerror = min($loweridinerror, $block->id);
507 if (is_array($blocks)) {
509 $MAXFORSHOWLINK = 100;
512 foreach ($blocks as &$block) {
514 if (empty($search_showonlyerrors) || !$checkresult[$block->id]) {
517 if ($nbshown < $MAXFORSHOWLINK) {
518 $object_link = $block->getObjectLink();
520 $object_link = $block->element.
'/'.$block->fk_object;
523 print
'<tr class="oddeven">';
526 print
'<td>'.$block->id.
'</td>';
529 print
'<td>'.dol_print_date($block->date_creation,
'dayhour').
'</td>';
534 print $block->user_fullname;
538 print
'<td>'.$langs->trans(
'log'.$block->action).
'</td>';
541 print
'<td class="nowraponall">';
542 print $block->ref_object;
546 print
'<td'.(preg_match(
'/<a/', $object_link) ?
' class="nowrap"' :
'').
'><!-- object_link -->'.$object_link.
'</td>';
549 print
'<td class="right nowraponall">'.price($block->amounts).
'</td>';
552 print
'<td align="center"><a href="#" data-blockid="'.$block->id.
'" rel="show-info">'.
img_info($langs->trans(
'ShowDetails')).
'</a></td>';
555 print
'<td class="nowrap">';
556 $texttoshow = $langs->trans(
"Fingerprint").
' - '.$langs->trans(
"Saved").
':<br>'.$block->signature;
557 $texttoshow .=
'<br><br>'.$langs->trans(
"Fingerprint").
' - Recalculated sha256(previoushash * data):<br>'.$checkdetail[$block->id][
'calculatedsignature'];
558 $texttoshow .=
'<br><span class="opacitymedium">'.$langs->trans(
"PreviousHash").
'='.$checkdetail[$block->id][
'previoushash'].
'</span>';
560 print
$form->textwithpicto(
dol_trunc($block->signature,
'8'), $texttoshow, 1,
'help',
'', 0, 2,
'fingerprint'.$block->id);
564 print
'<td class="center">';
565 if (!$checkresult[$block->id] || ($loweridinerror && $block->id >= $loweridinerror)) {
566 if ($checkresult[$block->id]) {
567 print
'<span class="badge badge-status4 badge-status" title="'.$langs->trans(
'OkCheckFingerprintValidityButChainIsKo').
'">OK</span>';
569 print
'<span class="badge badge-status8 badge-status" title="'.$langs->trans(
'KoCheckFingerprintValidity').
'">KO</span>';
572 print
'<span class="badge badge-status4 badge-status" title="'.$langs->trans(
'OkCheckFingerprintValidity').
'">OK</span>';
577 print
'<td class="center">';
578 if (!$checkresult[$block->id] || ($loweridinerror && $block->id >= $loweridinerror)) {
579 if ($checkresult[$block->id]) {
580 print
$form->textwithpicto(
'', $langs->trans(
'OkCheckFingerprintValidityButChainIsKo'));
584 if (!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY) && !empty($conf->global->BLOCKEDLOG_AUTHORITY_URL)) {
585 print
' '.($block->certified ?
img_picto($langs->trans(
'AddedByAuthority'),
'info') :
img_picto($langs->trans(
'NotAddedByAuthorityYet'),
'info_black'));
596 print
'<tr><td colspan="12"><span class="opacitymedium">'.$langs->trans(
"NoRecordFound").
'</span></td></tr>';
607 print
'<script type="text/javascript">
609 jQuery(document).ready(function () {
610 jQuery("#dialogforpopup").dialog(
611 { closeOnEscape: true, classes: { "ui-dialog": "highlight" },
612 maxHeight: window.innerHeight-60, height: window.innerHeight-60, width: '.($conf->browser->layout ==
'phone' ? 400 : 700).
',
614 autoOpen: false }).css("z-index: 5000");
616 $("a[rel=show-info]").click(function() {
618 console.log("We click on tooltip, we open popup and get content using an ajax call");
620 var fk_block = $(this).attr("data-blockid");
625 url:
"'.DOL_URL_ROOT.'/blockedlog/ajax/block-info.php?id="+fk_block,
627 }).done(
function(data) {
628 jQuery(
"#dialogforpopup").html(data);
631 jQuery(
"#dialogforpopup").dialog(
"open");
637 if (!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY) && !empty($conf->global->BLOCKEDLOG_AUTHORITY_URL)) {
639 <script type="text/javascript">
644 url: '<?php echo DOL_URL_ROOT.
'/blockedlog/ajax/check_signature.php' ?>
',
646 }).done(function(data) {
647 if(data == 'hashisok
') {
648 $('#blockchainstatus
').html('<?php echo $langs->trans(
'AuthorityReconizeFingerprintConformity').
' '.
img_picto($langs->trans(
'SignatureOK'),
'on') ?>
');
651 $('#blockchainstatus
').html('<?php echo $langs->trans(
'AuthorityDidntReconizeFingerprintConformity').
' '.
img_picto($langs->trans(
'SignatureKO'),
'off') ?>
');
660 if (GETPOST('withtab
', 'alpha
')) {
661 print dol_get_fiche_end();