28 require
'../../main.inc.php';
29 require_once DOL_DOCUMENT_ROOT.
'/blockedlog/lib/blockedlog.lib.php';
30 require_once DOL_DOCUMENT_ROOT.
'/blockedlog/class/blockedlog.class.php';
31 require_once DOL_DOCUMENT_ROOT.
'/blockedlog/class/authority.class.php';
32 require_once DOL_DOCUMENT_ROOT.
'/core/lib/admin.lib.php';
33 require_once DOL_DOCUMENT_ROOT.
'/core/lib/date.lib.php';
36 $langs->loadLangs(array(
'admin',
'bills',
'blockedlog',
'other'));
39 if ((!$user->admin && empty($user->rights->blockedlog->read)) || empty($conf->blockedlog->enabled)) {
44 $action =
GETPOST(
'action',
'aZ09');
45 $contextpage =
GETPOST(
'contextpage',
'aZ') ?
GETPOST(
'contextpage',
'aZ') :
'blockedloglist';
46 $backtopage =
GETPOST(
'backtopage',
'alpha');
47 $optioncss =
GETPOST(
'optioncss',
'aZ');
49 $search_showonlyerrors =
GETPOST(
'search_showonlyerrors',
'int');
50 if ($search_showonlyerrors < 0) {
51 $search_showonlyerrors = 0;
54 $search_startyear =
GETPOST(
'search_startyear',
'int');
55 $search_startmonth =
GETPOST(
'search_startmonth',
'int');
56 $search_startday =
GETPOST(
'search_startday',
'int');
57 $search_endyear =
GETPOST(
'search_endyear',
'int');
58 $search_endmonth =
GETPOST(
'search_endmonth',
'int');
59 $search_endday =
GETPOST(
'search_endday',
'int');
60 $search_id =
GETPOST(
'search_id',
'alpha');
61 $search_fk_user =
GETPOST(
'search_fk_user',
'intcomma');
63 if ($search_startyear !=
'') {
64 $search_start =
dol_mktime(0, 0, 0, $search_startmonth, $search_startday, $search_startyear);
67 if (
GETPOST(
'search_endyear') !=
'') {
70 $search_code =
GETPOST(
'search_code',
'alpha');
71 $search_ref =
GETPOST(
'search_ref',
'alpha');
72 $search_amount =
GETPOST(
'search_amount',
'alpha');
74 if (($search_start == -1 || empty($search_start)) && !
GETPOSTISSET(
'search_startmonth')) {
79 $limit =
GETPOST(
'limit',
'int') ?
GETPOST(
'limit',
'int') : $conf->liste_limit;
80 $sortfield =
GETPOST(
'sortfield',
'aZ09comma');
81 $sortorder =
GETPOST(
'sortorder',
'aZ09comma');
83 if (empty($page) || $page == -1) {
86 $offset = $limit * $page;
87 $pageprev = $page - 1;
88 $pagenext = $page + 1;
90 if (empty($sortfield)) {
93 if (empty($sortorder)) {
98 $block_static->loadTrackedEvents();
103 $max_execution_time_for_importexport = (empty($conf->global->EXPORT_MAX_EXECUTION_TIME) ? 300 : $conf->global->EXPORT_MAX_EXECUTION_TIME);
104 $max_time = @ini_get(
"max_execution_time");
105 if ($max_time && $max_time < $max_execution_time_for_importexport) {
106 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.");
107 @ini_set(
"max_execution_time", $max_execution_time_for_importexport);
116 if (
GETPOST(
'button_removefilter_x',
'alpha') ||
GETPOST(
'button_removefilter.x',
'alpha') ||
GETPOST(
'button_removefilter',
'alpha')) {
118 $search_fk_user =
'';
124 $search_showonlyerrors = 0;
126 $search_array_options = array();
129 if ($action ===
'downloadblockchain') {
132 $bc = $auth->getLocalBlockChain();
134 header(
'Content-Type: application/octet-stream');
135 header(
"Content-Transfer-Encoding: Binary");
136 header(
"Content-disposition: attachment; filename=\"".$auth->signature.
".certif\"");
141 } elseif (
GETPOST(
'downloadcsv',
'alpha')) {
149 $sql =
"SELECT rowid,date_creation,tms,user_fullname,action,amounts,element,fk_object,date_object,ref_object,signature,fk_user,object_data";
150 $sql .=
" FROM ".MAIN_DB_PREFIX.
"blockedlog";
151 $sql .=
" WHERE entity = ".$conf->entity;
152 if (
GETPOST(
'monthtoexport',
'int') > 0 ||
GETPOST(
'yeartoexport',
'int') > 0) {
155 $sql .=
" AND date_creation BETWEEN '".$db->idate($dates).
"' AND '".$db->idate($datee).
"'";
157 $sql .=
" ORDER BY rowid ASC";
158 $sql .= $db->plimit(1);
160 $res = $db->query($sql);
163 $obj = $db->fetch_object($res);
165 $previoushash = $block_static->getPreviousHash(0, $obj->rowid);
166 $firstid = $obj->rowid;
168 $previoushash =
'nodata';
179 $sql =
"SELECT rowid,date_creation,tms,user_fullname,action,amounts,element,fk_object,date_object,ref_object,signature,fk_user,object_data";
180 $sql .=
" FROM ".MAIN_DB_PREFIX.
"blockedlog";
181 $sql .=
" WHERE entity = ".$conf->entity;
182 if (
GETPOST(
'monthtoexport',
'int') > 0 ||
GETPOST(
'yeartoexport',
'int') > 0) {
185 $sql .=
" AND date_creation BETWEEN '".$db->idate($dates).
"' AND '".$db->idate($datee).
"'";
187 $sql .=
" ORDER BY rowid ASC";
189 $res = $db->query($sql);
191 header(
'Content-Type: application/octet-stream');
192 header(
"Content-Transfer-Encoding: Binary");
193 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\"");
195 print $langs->transnoentities(
'Id')
196 .
';'.$langs->transnoentities(
'Date')
197 .
';'.$langs->transnoentities(
'User')
198 .
';'.$langs->transnoentities(
'Action')
199 .
';'.$langs->transnoentities(
'Element')
200 .
';'.$langs->transnoentities(
'Amounts')
201 .
';'.$langs->transnoentities(
'ObjectId')
202 .
';'.$langs->transnoentities(
'Date')
203 .
';'.$langs->transnoentities(
'Ref')
204 .
';'.$langs->transnoentities(
'Fingerprint')
205 .
';'.$langs->transnoentities(
'Status')
206 .
';'.$langs->transnoentities(
'Note')
207 .
';'.$langs->transnoentities(
'FullData')
213 while ($obj = $db->fetch_object($res)) {
216 $block_static->id = $obj->rowid;
217 $block_static->date_creation = $db->jdate($obj->date_creation);
218 $block_static->date_modification = $db->jdate($obj->tms);
219 $block_static->action = $obj->action;
220 $block_static->fk_object = $obj->fk_object;
221 $block_static->element = $obj->element;
222 $block_static->amounts = (double) $obj->amounts;
223 $block_static->ref_object = $obj->ref_object;
224 $block_static->date_object = $db->jdate($obj->date_object);
225 $block_static->user_fullname = $obj->user_fullname;
226 $block_static->fk_user = $obj->fk_user;
227 $block_static->signature = $obj->signature;
228 $block_static->object_data = $block_static->dolDecodeBlockedData($obj->object_data);
230 $checksignature = $block_static->checkSignature($previoushash);
232 if ($checksignature) {
233 $statusofrecord =
'Valid';
234 if ($loweridinerror > 0) {
235 $statusofrecordnote =
'ValidButFoundAPreviousKO';
237 $statusofrecordnote =
'';
240 $statusofrecord =
'KO';
241 $statusofrecordnote =
'LineCorruptedOrNotMatchingPreviousOne';
242 $loweridinerror = $obj->rowid;
246 $statusofrecordnote = $langs->trans(
"PreviousFingerprint").
': '.$previoushash.($statusofrecordnote ?
' - '.$statusofrecordnote :
'');
249 print
';'.$obj->date_creation;
250 print
';"'.str_replace(
'"',
'""', $obj->user_fullname).
'"';
251 print
';'.$obj->action;
252 print
';'.$obj->element;
253 print
';'.$obj->amounts;
254 print
';'.$obj->fk_object;
255 print
';'.$obj->date_object;
256 print
';"'.str_replace(
'"',
'""', $obj->ref_object).
'"';
257 print
';'.$obj->signature;
258 print
';'.$statusofrecord;
259 print
';'.$statusofrecordnote;
260 print
';"'.str_replace(
'"',
'""', $obj->object_data).
'"';
264 $previoushash = $obj->signature;
283 if (
GETPOST(
'withtab',
'alpha')) {
284 $title = $langs->trans(
"ModuleSetup").
' '.$langs->trans(
'BlockedLog');
286 $title = $langs->trans(
"BrowseBlockedLog");
288 $help_url=
"EN:Module_Unalterable_Archives_-_Logs|FR:Module_Archives_-_Logs_Inaltérable";
294 $blocks = $block_static->getLog(
'all', $search_id, $MAXLINES, $sortfield, $sortorder, $search_fk_user, $search_start, $search_end, $search_ref, $search_amount, $search_code);
295 if (!is_array($blocks)) {
297 setEventMessages($langs->trans(
"TooManyRecordToScanRestrictFilters", $MAXLINES),
null,
'errors');
299 dol_print_error($block_static->db, $block_static->error, $block_static->errors);
305 if (
GETPOST(
'withtab',
'alpha')) {
306 $linkback =
'<a href="'.($backtopage ? $backtopage : DOL_URL_ROOT.
'/admin/modules.php').
'">'.$langs->trans(
"BackToModuleList").
'</a>';
311 if (
GETPOST(
'withtab',
'alpha')) {
316 print
'<span class="opacitymedium hideonsmartphone">'.$langs->trans(
"FingerprintsDesc").
"<br></span>\n";
321 if (!empty($contextpage) && $contextpage != $_SERVER[
"PHP_SELF"]) {
322 $param .=
'&contextpage='.urlencode($contextpage);
324 if ($limit > 0 && $limit != $conf->liste_limit) {
325 $param .=
'&limit='.urlencode($limit);
327 if ($search_id !=
'') {
328 $param .=
'&search_id='.urlencode($search_id);
330 if ($search_fk_user > 0) {
331 $param .=
'&search_fk_user='.urlencode($search_fk_user);
333 if ($search_startyear > 0) {
334 $param .=
'&search_startyear='.urlencode($search_startyear);
336 if ($search_startmonth > 0) {
337 $param .=
'&search_startmonth='.urlencode($search_startmonth);
339 if ($search_startday > 0) {
340 $param .=
'&search_startday='.urlencode($search_startday);
342 if ($search_endyear > 0) {
343 $param .=
'&search_endyear='.urlencode($search_endyear);
345 if ($search_endmonth > 0) {
346 $param .=
'&search_endmonth='.urlencode($search_endmonth);
348 if ($search_endday > 0) {
349 $param .=
'&search_endday='.urlencode($search_endday);
351 if ($search_showonlyerrors > 0) {
352 $param .=
'&search_showonlyerrors='.urlencode($search_showonlyerrors);
354 if ($optioncss !=
'') {
355 $param .=
'&optioncss='.urlencode($optioncss);
357 if (
GETPOST(
'withtab',
'alpha')) {
358 $param .=
'&withtab='.urlencode(
GETPOST(
'withtab',
'alpha'));
364 print
'<form method="POST" id="searchFormList" action="'.$_SERVER[
"PHP_SELF"].
'">';
365 print
'<input type="hidden" name="token" value="'.newToken().
'">';
367 print
'<div class="right">';
368 print $langs->trans(
"RestrictYearToExport").
': ';
369 $smonth =
GETPOST(
'monthtoexport',
'int');
372 $retstring .=
'<select class="flat valignmiddle maxwidth75imp marginrightonly" id="monthtoexport" name="monthtoexport">';
373 $retstring .=
'<option value="0" selected> </option>';
374 for ($month = 1; $month <= 12; $month++) {
375 $retstring .=
'<option value="'.$month.
'"'.($month == $smonth ?
' selected' :
'').
'>';
376 $retstring .=
dol_print_date(mktime(12, 0, 0, $month, 1, 2000),
"%b");
377 $retstring .=
"</option>";
379 $retstring .=
"</select>";
381 print
'<input type="text" name="yeartoexport" class="valignmiddle maxwidth50imp" value="'.GETPOST(
'yeartoexport',
'int').
'">';
382 print
'<input type="hidden" name="withtab" value="'.GETPOST(
'withtab',
'alpha').
'">';
383 print
'<input type="submit" name="downloadcsv" class="button" value="'.$langs->trans(
'DownloadLogCSV').
'">';
384 if (!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY)) {
385 print
' | <a href="?action=downloadblockchain'.(GETPOST(
'withtab',
'alpha') ?
'&withtab='.GETPOST(
'withtab',
'alpha') :
'').
'">'.$langs->trans(
'DownloadBlockChain').
'</a>';
391 print
'<form method="POST" id="searchFormList" action="'.$_SERVER[
"PHP_SELF"].
'">';
393 print
'<div class="div-table-responsive">';
395 if ($optioncss !=
'') {
396 print
'<input type="hidden" name="optioncss" value="'.$optioncss.
'">';
398 print
'<input type="hidden" name="token" value="'.newToken().
'">';
399 print
'<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
400 print
'<input type="hidden" name="action" value="list">';
401 print
'<input type="hidden" name="sortfield" value="'.$sortfield.
'">';
402 print
'<input type="hidden" name="sortorder" value="'.$sortorder.
'">';
403 print
'<input type="hidden" name="page" value="'.$page.
'">';
404 print
'<input type="hidden" name="contextpage" value="'.$contextpage.
'">';
405 print
'<input type="hidden" name="withtab" value="'.GETPOST(
'withtab',
'alpha').
'">';
407 print
'<table class="noborder centpercent">';
410 print
'<tr class="liste_titre_filter">';
412 print
'<td class="liste_titre"><input type="text" class="maxwidth50" name="search_id" value="'.dol_escape_htmltag($search_id).
'"></td>';
414 print
'<td class="liste_titre">';
416 print
$form->selectDate($search_start,
'search_start');
419 print
$form->selectDate($search_end,
'search_end');
423 print
'<td class="liste_titre">';
424 print
$form->select_dolusers($search_fk_user,
'search_fk_user', 1,
null, 0,
'',
'', 0, 0, 0,
'', 0,
'',
'maxwidth200');
429 $langs->load(
"blockedlog");
430 print
'<td class="liste_titre">';
431 print
$form->selectarray(
'search_code', $block_static->trackedevents, $search_code, 1, 0, 0,
'', 1, 0, 0,
'ASC',
'maxwidth200', 1);
435 print
'<td class="liste_titre"><input type="text" class="maxwidth50" name="search_ref" value="'.dol_escape_htmltag($search_ref).
'"></td>';
438 print
'<td class="liste_titre"></td>';
441 print
'<td class="liste_titre right"><input type="text" class="maxwidth50" name="search_amount" value="'.dol_escape_htmltag($search_amount).
'"></td>';
444 print
'<td class="liste_titre"></td>';
447 print
'<td class="liste_titre"></td>';
450 print
'<td class="liste_titre">';
451 $array = array(
"1" =>
"OnlyNonValid");
452 print
$form->selectarray(
'search_showonlyerrors', $array, $search_showonlyerrors, 1, 0, 0,
'', 1, 0, 0,
'ASC',
'search_status maxwidth200 onrightofpage', 1);
456 print
'<td class="liste_titre"></td>';
459 print
'<td class="liste_titre" align="middle">';
460 $searchpicto =
$form->showFilterButtons();
466 print
'<tr class="liste_titre">';
467 print
getTitleFieldOfList($langs->trans(
'#'), 0, $_SERVER[
"PHP_SELF"],
'rowid',
'', $param,
'', $sortfield, $sortorder,
'minwidth50 ').
"\n";
468 print
getTitleFieldOfList($langs->trans(
'Date'), 0, $_SERVER[
"PHP_SELF"],
'date_creation',
'', $param,
'', $sortfield, $sortorder,
'').
"\n";
469 print
getTitleFieldOfList($langs->trans(
'Author'), 0, $_SERVER[
"PHP_SELF"],
'user_fullname',
'', $param,
'', $sortfield, $sortorder,
'').
"\n";
470 print
getTitleFieldOfList($langs->trans(
'Action'), 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'', $sortfield, $sortorder,
'').
"\n";
471 print
getTitleFieldOfList($langs->trans(
'Ref'), 0, $_SERVER[
"PHP_SELF"],
'ref_object',
'', $param,
'', $sortfield, $sortorder,
'').
"\n";
472 print
getTitleFieldOfList(
'', 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'', $sortfield, $sortorder,
'').
"\n";
473 print
getTitleFieldOfList($langs->trans(
'Amount'), 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'class="right"', $sortfield, $sortorder,
'').
"\n";
474 print
getTitleFieldOfList($langs->trans(
'DataOfArchivedEvent'), 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'align="center"', $sortfield, $sortorder,
'').
"\n";
475 print
getTitleFieldOfList($langs->trans(
'Fingerprint'), 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'', $sortfield, $sortorder,
'').
"\n";
476 print
getTitleFieldOfList($langs->trans(
'Status'), 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'align="center"', $sortfield, $sortorder,
'').
"\n";
477 print
getTitleFieldOfList(
'', 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'align="center"', $sortfield, $sortorder,
'').
"\n";
478 print
getTitleFieldOfList(
'<span id="blockchainstatus"></span>', 0, $_SERVER[
"PHP_SELF"],
'',
'', $param,
'align="center"', $sortfield, $sortorder,
'').
"\n";
481 if (!empty($conf->global->BLOCKEDLOG_SCAN_ALL_FOR_LOWERIDINERROR)) {
489 $checkresult = array();
490 $checkdetail = array();
491 if (is_array($blocks)) {
492 foreach ($blocks as &$block) {
493 $tmpcheckresult = $block->checkSignature(
'', 1);
495 $checksignature = $tmpcheckresult[
'checkresult'];
497 $checkresult[$block->id] = $checksignature;
498 $checkdetail[$block->id] = $tmpcheckresult;
500 if (!$checksignature) {
501 if (empty($loweridinerror)) {
502 $loweridinerror = $block->id;
504 $loweridinerror = min($loweridinerror, $block->id);
511 if (is_array($blocks)) {
513 $MAXFORSHOWLINK = 100;
516 foreach ($blocks as &$block) {
518 if (empty($search_showonlyerrors) || !$checkresult[$block->id]) {
521 if ($nbshown < $MAXFORSHOWLINK) {
522 $object_link = $block->getObjectLink();
524 $object_link = $block->element.
'/'.$block->fk_object;
527 print
'<tr class="oddeven">';
530 print
'<td>'.dol_escape_htmltag($block->id).
'</td>';
533 print
'<td class="nowraponall">'.dol_print_date($block->date_creation,
'dayhour').
'</td>';
542 print
'<td class="tdoverflowmax250" title="'.dol_escape_htmltag($langs->trans(
'log'.$block->action)).
'">'.$langs->trans(
'log'.$block->action).
'</td>';
545 print
'<td class="nowraponall">';
546 print $block->ref_object;
550 print
'<td'.(preg_match(
'/<a/', $object_link) ?
' class="nowrap"' :
'').
'><!-- object_link -->'.$object_link.
'</td>';
553 print
'<td class="right nowraponall">'.price($block->amounts).
'</td>';
556 print
'<td align="center"><a href="#" data-blockid="'.$block->id.
'" rel="show-info">'.
img_info($langs->trans(
'ShowDetails')).
'</a></td>';
559 print
'<td class="nowrap">';
560 $texttoshow = $langs->trans(
"Fingerprint").
' - '.$langs->trans(
"Saved").
':<br>'.$block->signature;
561 $texttoshow .=
'<br><br>'.$langs->trans(
"Fingerprint").
' - Recalculated sha256(previoushash * data):<br>'.$checkdetail[$block->id][
'calculatedsignature'];
562 $texttoshow .=
'<br><span class="opacitymedium">'.$langs->trans(
"PreviousHash").
'='.$checkdetail[$block->id][
'previoushash'].
'</span>';
564 print
$form->textwithpicto(
dol_trunc($block->signature,
'8'), $texttoshow, 1,
'help',
'', 0, 2,
'fingerprint'.$block->id);
568 print
'<td class="center">';
569 if (!$checkresult[$block->id] || ($loweridinerror && $block->id >= $loweridinerror)) {
570 if ($checkresult[$block->id]) {
571 print
'<span class="badge badge-status4 badge-status" title="'.$langs->trans(
'OkCheckFingerprintValidityButChainIsKo').
'">OK</span>';
573 print
'<span class="badge badge-status8 badge-status" title="'.$langs->trans(
'KoCheckFingerprintValidity').
'">KO</span>';
576 print
'<span class="badge badge-status4 badge-status" title="'.$langs->trans(
'OkCheckFingerprintValidity').
'">OK</span>';
581 print
'<td class="center">';
582 if (!$checkresult[$block->id] || ($loweridinerror && $block->id >= $loweridinerror)) {
583 if ($checkresult[$block->id]) {
584 print
$form->textwithpicto(
'', $langs->trans(
'OkCheckFingerprintValidityButChainIsKo'));
588 if (!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY) && !empty($conf->global->BLOCKEDLOG_AUTHORITY_URL)) {
589 print
' '.($block->certified ?
img_picto($langs->trans(
'AddedByAuthority'),
'info') :
img_picto($langs->trans(
'NotAddedByAuthorityYet'),
'info_black'));
600 print
'<tr><td colspan="12"><span class="opacitymedium">'.$langs->trans(
"NoRecordFound").
'</span></td></tr>';
611 print
'<script type="text/javascript">
613 jQuery(document).ready(function () {
614 jQuery("#dialogforpopup").dialog(
615 { closeOnEscape: true, classes: { "ui-dialog": "highlight" },
616 maxHeight: window.innerHeight-60, height: window.innerHeight-60, width: '.($conf->browser->layout ==
'phone' ? 400 : 700).
',
618 autoOpen: false }).css("z-index: 5000");
620 $("a[rel=show-info]").click(function() {
622 console.log("We click on tooltip, we open popup and get content using an ajax call");
624 var fk_block = $(this).attr("data-blockid");
629 url:
"'.DOL_URL_ROOT.'/blockedlog/ajax/block-info.php?id="+fk_block,
631 }).done(
function(data) {
632 jQuery(
"#dialogforpopup").html(data);
635 jQuery(
"#dialogforpopup").dialog(
"open");
641 if (!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY) && !empty($conf->global->BLOCKEDLOG_AUTHORITY_URL)) {
643 <script type="text/javascript">
648 url: '<?php echo DOL_URL_ROOT.
'/blockedlog/ajax/check_signature.php' ?>
',
650 }).done(function(data) {
651 if(data == 'hashisok
') {
652 $('#blockchainstatus
').html('<?php echo $langs->trans(
'AuthorityReconizeFingerprintConformity').
' '.
img_picto($langs->trans(
'SignatureOK'),
'on') ?>
');
655 $('#blockchainstatus
').html('<?php echo $langs->trans(
'AuthorityDidntReconizeFingerprintConformity').
' '.
img_picto($langs->trans(
'SignatureKO'),
'off') ?>
');
664 if (GETPOST('withtab
', 'alpha
')) {
665 print dol_get_fiche_end();