dolibarr 22.0.5
blockedlog_list.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) 2018-2024 Frédéric France <frederic.france@free.fr>
5 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
6 * Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.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
28// Load Dolibarr environment
29require '../../main.inc.php';
30require_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
31require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
32require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/authority.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
34require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
35require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
36
47// Load translation files required by the page
48$langs->loadLangs(array('admin', 'bills', 'blockedlog', 'other'));
49
50// Access Control
51if ((!$user->admin && !$user->hasRight('blockedlog', 'read')) || empty($conf->blockedlog->enabled)) {
53}
54
55// Get Parameters
56$action = GETPOST('action', 'aZ09');
57$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'blockedloglist'; // To manage different context of search
58$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
59$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
60
61$search_showonlyerrors = GETPOSTINT('search_showonlyerrors');
62if ($search_showonlyerrors < 0) {
63 $search_showonlyerrors = 0;
64}
65
66$search_startyear = GETPOSTINT('search_startyear');
67$search_startmonth = GETPOSTINT('search_startmonth');
68$search_startday = GETPOSTINT('search_startday');
69$search_endyear = GETPOSTINT('search_endyear');
70$search_endmonth = GETPOSTINT('search_endmonth');
71$search_endday = GETPOSTINT('search_endday');
72$search_id = GETPOST('search_id', 'alpha');
73$search_fk_user = GETPOST('search_fk_user', 'intcomma');
74$search_start = -1;
75if (GETPOST('search_startyear') != '') {
76 $search_start = dol_mktime(0, 0, 0, $search_startmonth, $search_startday, $search_startyear);
77}
78$search_end = -1;
79if (GETPOST('search_endyear') != '') {
80 $search_end = dol_mktime(23, 59, 59, $search_endmonth, $search_endday, $search_endyear);
81}
82$search_code = GETPOST('search_code', 'array:alpha');
83$search_ref = GETPOST('search_ref', 'alpha');
84$search_amount = GETPOST('search_amount', 'alpha');
85$search_signature = GETPOST('search_signature', 'alpha');
86
87if (($search_start == -1 || empty($search_start)) && !GETPOSTISSET('search_startmonth') && !GETPOSTISSET('begin')) {
88 $search_start = dol_time_plus_duree(dol_now(), -1, 'w');
89 $tmparray = dol_getdate($search_start);
90 $search_startday = $tmparray['mday'];
91 $search_startmonth = $tmparray['mon'];
92 $search_startyear = $tmparray['year'];
93}
94
95// Load variable for pagination
96$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
97$sortfield = GETPOST('sortfield', 'aZ09comma');
98$sortorder = GETPOST('sortorder', 'aZ09comma');
99$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
100if (empty($page) || $page == -1) {
101 $page = 0;
102} // If $page is not defined, or '' or -1
103$offset = $limit * $page;
104$pageprev = $page - 1;
105$pagenext = $page + 1;
106
107if (empty($sortfield)) {
108 $sortfield = 'rowid';
109}
110if (empty($sortorder)) {
111 $sortorder = 'DESC';
112}
113
114$block_static = new BlockedLog($db);
115$block_static->loadTrackedEvents();
116
117$result = restrictedArea($user, 'blockedlog', 0, '');
118
119// Execution Time
120$max_execution_time_for_importexport = getDolGlobalInt('EXPORT_MAX_EXECUTION_TIME', 300); // 5mn if not defined
121$max_time = @ini_get("max_execution_time");
122if ($max_time && $max_time < $max_execution_time_for_importexport) {
123 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.");
124 @ini_set("max_execution_time", $max_execution_time_for_importexport); // This work only if safe mode is off. also web servers has timeout of 300
125}
126
127$MAXLINES = getDolGlobalInt('BLOCKEDLOG_MAX_LINES', 10000);
128$MAXFORSHOWNLINKS = getDolGlobalInt('BLOCKEDLOG_MAX_FOR_SHOWN_LINKS', 100);
129
130
131/*
132 * Actions
133 */
134
135// Purge search criteria
136if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
137 $search_id = '';
138 $search_fk_user = '';
139 $search_start = -1;
140 $search_end = -1;
141 $search_code = array();
142 $search_ref = '';
143 $search_amount = '';
144 $search_signature = '';
145 $search_showonlyerrors = 0;
146 $search_startyear = '';
147 $search_startmonth = '';
148 $search_startday = '';
149 $search_endyear = '';
150 $search_endmonth = '';
151 $search_endday = '';
152 $toselect = array();
153 $search_array_options = array();
154}
155
156if ($action === 'downloadblockchain') {
157 $auth = new BlockedLogAuthority($db);
158
159 $bc = $auth->getLocalBlockChain();
160
161 header('Content-Type: application/octet-stream');
162 header("Content-Transfer-Encoding: Binary");
163 header("Content-disposition: attachment; filename=\"".$auth->signature.".certif\"");
164
165 echo $bc;
166
167 exit;
168} elseif (GETPOST('downloadcsv', 'alpha')) {
169 $error = 0;
170
171 $previoushash = '';
172 $firstid = '';
173
174 if (! (GETPOSTINT('yeartoexport') > 0)) {
175 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Year")), null, "errors");
176 $error++;
177 } else {
178 // Get the ID of the first line qualified
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 = ".((int) $conf->entity);
182 if (GETPOSTINT('monthtoexport') > 0 || GETPOSTINT('yeartoexport') > 0) {
183 $dates = dol_get_first_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 1);
184 $datee = dol_get_last_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 12);
185 $sql .= " AND date_creation BETWEEN '".$db->idate($dates)."' AND '".$db->idate($datee)."'";
186 }
187 $sql .= " ORDER BY rowid ASC"; // Required so we get the first one
188 $sql .= $db->plimit(1);
189
190 $res = $db->query($sql);
191 if ($res) {
192 // Make the first fetch to get first line
193 $obj = $db->fetch_object($res);
194 if ($obj) {
195 $firstid = $obj->rowid;
196 $previoushash = $block_static->getPreviousHash(0, $firstid);
197 } else { // If not data found for filter, we do not need previoushash neither firstid
198 $firstid = '';
199 $previoushash = 'nodata';
200 }
201 } else {
202 $error++;
203 setEventMessages($db->lasterror, null, 'errors');
204 }
205 }
206
207 if (! $error) {
208 // We record the export as a new line into the unalterable logs
209 require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
210 $b = new BlockedLog($db);
211
212 $object = new stdClass();
213 $object->id = 0;
214 $object->element = 'module';
215 $object->ref = 'systemevent';
216 $object->entity = $conf->entity;
217 $object->date = dol_now();
218
219 $object->label = 'Export unalterable logs - Period: year='.GETPOSTINT('yeartoexport').(GETPOSTINT('monthtoexport') ? ' month='.GETPOSTINT('monthtoexport') : '');
220
221 $action = 'BLOCKEDLOG_EXPORT';
222 $result = $b->setObjectData($object, $action, 0, $user);
223 //var_dump($b); exit;
224
225 if ($result < 0) {
226 setEventMessages('Failed to insert the export int the unalterable log', null, 'errors');
227 $error++;
228 }
229
230 $res = $b->create($user);
231
232 if ($res < 0) {
233 setEventMessages('Failed to insert the export int the unalterable log', null, 'errors');
234 $error++;
235 }
236 }
237
238 if (!$error) {
239 // Now restart request with all data = no limit(1) in sql request
240 $sql = "SELECT rowid, date_creation, tms, user_fullname, action, amounts, element, fk_object, date_object, ref_object, signature, fk_user, object_data, object_version, debuginfo";
241 $sql .= " FROM ".MAIN_DB_PREFIX."blockedlog";
242 $sql .= " WHERE entity = ".((int) $conf->entity);
243 if (GETPOSTINT('monthtoexport') > 0 || GETPOSTINT('yeartoexport') > 0) {
244 $dates = dol_get_first_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 1);
245 $datee = dol_get_last_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 12);
246 $sql .= " AND date_creation BETWEEN '".$db->idate($dates)."' AND '".$db->idate($datee)."'";
247 }
248 $sql .= " ORDER BY rowid ASC"; // Required so later we can use the parameter $previoushash of checkSignature()
249
250 $resql = $db->query($sql);
251 if ($resql) {
252 $nameofdownoadedfile = "unalterable-log-archive-".$dolibarr_main_db_name."-".(GETPOSTINT('yeartoexport') > 0 ? GETPOSTINT('yeartoexport').(GETPOSTINT('monthtoexport') > 0 ? sprintf("%02d", GETPOSTINT('monthtoexport')) : '').'-' : '').dol_print_date(dol_now(), 'dayhourlog', 'gmt').'UTC-DONOTMODIFY';
253
254 $tmpfile = $conf->admin->dir_temp.'/unalterable-log-archive-tmp-'.$user->id.'.csv';
255
256 $fh = fopen($tmpfile, 'w');
257
258 // Print line with title
259 fwrite($fh, $langs->transnoentities('Id')
260 .';'.$langs->transnoentities('Date')
261 .';'.$langs->transnoentities('User')
262 .';'.$langs->transnoentities('Action')
263 .';'.$langs->transnoentities('Element')
264 .';'.$langs->transnoentities('Amounts')
265 .';'.$langs->transnoentities('ObjectId')
266 .';'.$langs->transnoentities('Date')
267 .';'.$langs->transnoentities('Ref')
268 .';'.$langs->transnoentities('Fingerprint')
269 .';'.$langs->transnoentities('Status')
270 .';'.$langs->transnoentities('Note')
271 .';'.$langs->transnoentities('Version')
272 .';'.$langs->transnoentities('FullData')
273 .';'.$langs->transnoentities('DebugInfo')
274 ."\n");
275
276 $loweridinerror = 0;
277 $i = 0;
278
279 while ($obj = $db->fetch_object($resql)) {
280 // We set here all data used into signature calculation (see checkSignature method) and more
281 // IMPORTANT: We must have here, the same rule for transformation of data than into the fetch method (db->jdate for date, ...)
282 $block_static->id = $obj->rowid;
283 $block_static->date_creation = $db->jdate($obj->date_creation);
284 $block_static->date_modification = $db->jdate($obj->tms);
285 $block_static->action = $obj->action;
286 $block_static->fk_object = $obj->fk_object;
287 $block_static->element = $obj->element;
288 $block_static->amounts = (float) $obj->amounts;
289 $block_static->ref_object = $obj->ref_object;
290 $block_static->date_object = $db->jdate($obj->date_object);
291 $block_static->user_fullname = $obj->user_fullname;
292 $block_static->fk_user = $obj->fk_user;
293 $block_static->signature = $obj->signature;
294 $block_static->object_data = $block_static->dolDecodeBlockedData($obj->object_data);
295 $block_static->object_version = $obj->object_version;
296 $block_static->debuginfo = $obj->debuginfo;
297
298 $checksignature = $block_static->checkSignature($previoushash); // If $previoushash is not defined, checkSignature will search it
299
300 if ($checksignature) {
301 $statusofrecord = 'Valid';
302 if ($loweridinerror > 0) {
303 $statusofrecordnote = 'ValidButFoundAPreviousKO';
304 } else {
305 $statusofrecordnote = '';
306 }
307 } else {
308 $statusofrecord = 'KO';
309 $statusofrecordnote = 'LineCorruptedOrNotMatchingPreviousOne';
310 $loweridinerror = $obj->rowid;
311 }
312
313 if ($i == 0) {
314 $statusofrecordnote = $langs->trans("PreviousFingerprint").': '.$previoushash.($statusofrecordnote ? ' - '.$statusofrecordnote : '');
315 }
316 fwrite($fh, $obj->rowid
317 .';'.$obj->date_creation
318 .';"'.str_replace('"', '""', $obj->user_fullname).'";'
319 .$obj->action
320 .';'.$obj->element
321 .';'.$obj->amounts
322 .';'.$obj->fk_object
323 .';'.$obj->date_object
324 .';"'.str_replace('"', '""', $obj->ref_object).'";'
325 .$obj->signature
326 .';'.$statusofrecord
327 .';'.$statusofrecordnote
328 .';'.$obj->object_version
329 .';"'.str_replace('"', '""', $obj->object_data).'";'
330 .str_replace('"', '""', $obj->debuginfo).'"'
331 ."\n");
332
333 // Set new previous hash for next fetch
334 $previoushash = $obj->signature;
335
336 $i++;
337 }
338
339 fclose($fh);
340
341 // Calculate the md5 of the file (the last line has a return line)
342 $md5value = md5_file($tmpfile);
343
344 // Now add a signature to check integrity at end of file
345 file_put_contents($tmpfile, 'END - md5='.$md5value, FILE_APPEND);
346
347 header('Content-Type: application/octet-stream');
348 header("Content-Transfer-Encoding: Binary");
349 header("Content-disposition: attachment; filename=\"".$nameofdownoadedfile.".csv\"");
350
351 readfile($tmpfile);
352
353 exit;
354 } else {
355 setEventMessages($db->lasterror, null, 'errors');
356 }
357 }
358}
359
360
361/*
362 * View
363 */
364
365$form = new Form($db);
366$formother = new FormOther($db);
367
368if (GETPOST('withtab', 'alpha')) {
369 $title = $langs->trans("ModuleSetup").' '.$langs->trans('BlockedLog');
370} else {
371 $title = $langs->trans("BrowseBlockedLog");
372}
373$help_url = "EN:Module_Unalterable_Archives_-_Logs|FR:Module_Archives_-_Logs_Inaltérable";
374
375llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'bodyforlist mod-blockedlog page-admin_blockedlog_list');
376
377$blocks = $block_static->getLog('all', (int) $search_id, $MAXLINES, $sortfield, $sortorder, (int) $search_fk_user, $search_start, $search_end, $search_ref, $search_amount, $search_code, $search_signature);
378if (!is_array($blocks)) {
379 if ($blocks == -2) {
380 setEventMessages($langs->trans("TooManyRecordToScanRestrictFilters", $MAXLINES), null, 'errors');
381 } else {
382 dol_print_error($block_static->db, $block_static->error, $block_static->errors);
383 exit;
384 }
385}
386
387$linkback = '';
388if (GETPOST('withtab', 'alpha')) {
389 $linkback = '<a href="'.($backtopage ? $backtopage : DOL_URL_ROOT.'/admin/modules.php').'">'.$langs->trans("BackToModuleList").'</a>';
390}
391
392print load_fiche_titre($title, $linkback);
393
394if (GETPOST('withtab', 'alpha')) {
396 print dol_get_fiche_head($head, 'fingerprints', '', -1);
397}
398
399print '<div class="opacitymedium hideonsmartphone justify">';
400
401print $langs->trans("FingerprintsDesc")."<br>";
402
403print '<br>';
404
405$s = $langs->trans("FilesIntegrityDesc", '{s}');
406$s = str_replace('{s}', DOL_URL_ROOT.'/admin/system/filecheck.php', $s);
407print $s;
408print "<br>\n";
409
410print "</div>\n";
411
412print '<br>';
413
414$param = '';
415if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
416 $param .= '&contextpage='.urlencode($contextpage);
417}
418if ($limit > 0 && $limit != $conf->liste_limit) {
419 $param .= '&limit='.((int) $limit);
420}
421if ($search_id != '') {
422 $param .= '&search_id='.urlencode($search_id);
423}
424if ($search_fk_user > 0) {
425 $param .= '&search_fk_user='.urlencode($search_fk_user);
426}
427if ($search_startyear > 0) {
428 $param .= '&search_startyear='.((int) $search_startyear);
429}
430if ($search_startmonth > 0) {
431 $param .= '&search_startmonth='.((int) $search_startmonth);
432}
433if ($search_startday > 0) {
434 $param .= '&search_startday='.((int) $search_startday);
435}
436if ($search_endyear > 0) {
437 $param .= '&search_endyear='.((int) $search_endyear);
438}
439if ($search_endmonth > 0) {
440 $param .= '&search_endmonth='.((int) $search_endmonth);
441}
442if ($search_endday > 0) {
443 $param .= '&search_endday='.((int) $search_endday);
444}
445if ($search_amount) {
446 $param .= '&search_amount='.urlencode($search_amount);
447}
448if ($search_signature) {
449 $param .= '&search_signature='.urlencode($search_signature);
450}
451if ($search_showonlyerrors > 0) {
452 $param .= '&search_showonlyerrors='.((int) $search_showonlyerrors);
453}
454if ($optioncss != '') {
455 $param .= '&optioncss='.urlencode($optioncss);
456}
457if (GETPOST('withtab', 'alpha')) {
458 $param .= '&withtab='.urlencode(GETPOST('withtab', 'alpha'));
459}
460
461// Add $param from extra fields
462//include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
463
464print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'?output=file">';
465print '<input type="hidden" name="token" value="'.newToken().'">';
466
467print '<div class="right">';
468print $langs->trans("RestrictYearToExport").': ';
469// Month
470print $formother->select_month((string) GETPOSTINT('monthtoexport'), 'monthtoexport', 1, 0, 'minwidth50 maxwidth75imp valignmiddle', true);
471print '<input type="text" name="yeartoexport" class="valignmiddle maxwidth75imp" value="'.GETPOST('yeartoexport').'" placeholder="'.$langs->trans("Year").'">';
472print '<input type="hidden" name="withtab" value="'.GETPOST('withtab', 'alpha').'">';
473print '<input type="submit" name="downloadcsv" class="button" value="'.$langs->trans('DownloadLogCSV').'">';
474if (getDolGlobalString('BLOCKEDLOG_USE_REMOTE_AUTHORITY')) {
475 print ' | <a href="?action=downloadblockchain'.(GETPOST('withtab', 'alpha') ? '&withtab='.GETPOST('withtab', 'alpha') : '').'">'.$langs->trans('DownloadBlockChain').'</a>';
476}
477print ' </div><br>';
478
479print '</form>';
480
481print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">';
482
483if ($optioncss != '') {
484 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
485}
486print '<input type="hidden" name="token" value="'.newToken().'">';
487print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
488print '<input type="hidden" name="action" value="list">';
489print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
490print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
491print '<input type="hidden" name="page" value="'.$page.'">';
492print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
493print '<input type="hidden" name="withtab" value="'.GETPOST('withtab', 'alpha').'">';
494
495print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
496print '<table class="noborder centpercent liste">';
497
498// Line of filters
499print '<tr class="liste_titre_filter">';
500
501// Action column
502if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
503 print '<td class="liste_titre center">';
504 $searchpicto = $form->showFilterButtons();
505 print $searchpicto;
506 print '</td>';
507}
508
509print '<td class="liste_titre"><input type="text" class="maxwidth50" name="search_id" value="'.dol_escape_htmltag($search_id).'"></td>';
510
511print '<td class="liste_titre">';
512//print $langs->trans("from").': ';
513print $form->selectDate($search_start, 'search_start');
514//print '<br>';
515//print $langs->trans("to").': ';
516print $form->selectDate($search_end, 'search_end');
517print '</td>';
518
519// User
520print '<td class="liste_titre">';
521print $form->select_dolusers($search_fk_user, 'search_fk_user', 1, null, 0, '', '', '0', 0, 0, '', 0, '', 'maxwidth150');
522print '</td>';
523
524// Actions code
525print '<td class="liste_titre">';
526print $form->multiselectarray('search_code', $block_static->trackedevents, $search_code, 0, 0, 'maxwidth150', 1);
527print '</td>';
528
529// Ref
530print '<td class="liste_titre"><input type="text" class="maxwidth50" name="search_ref" value="'.dol_escape_htmltag($search_ref).'"></td>';
531
532// Amount
533print '<td class="liste_titre right"><input type="text" class="maxwidth50" name="search_amount" value="'.dol_escape_htmltag($search_amount).'"></td>';
534
535// Full data
536print '<td class="liste_titre"></td>';
537
538// Fingerprint
539print '<td class="liste_titre"><input type="text" class="maxwidth50" name="search_signature" value="'.dol_escape_htmltag($search_signature).'"></td>';
540
541// Status
542print '<td class="liste_titre center minwidth75imp parentonrightofpage">';
543$array = array("1" => "OnlyNonValid");
544print $form->selectarray('search_showonlyerrors', $array, $search_showonlyerrors, 1, 0, 0, '', 1, 0, 0, 'ASC', 'search_status width100 onrightofpage', 1);
545print '</td>';
546
547// Status note
548//print '<td class="liste_titre"></td>';
549
550// Link to original ref into business software
551print '<td class="liste_titre"></td>';
552
553// Action column
554if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
555 print '<td class="liste_titre center">';
556 $searchpicto = $form->showFilterButtons();
557 print $searchpicto;
558 print '</td>';
559}
560
561print '</tr>';
562
563print '<tr class="liste_titre">';
564// Action column
565if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
566 print getTitleFieldOfList('<span id="blockchainstatus"></span>', 0, $_SERVER["PHP_SELF"], '', '', $param, 'class="center"', $sortfield, $sortorder, '')."\n";
567}
568print getTitleFieldOfList($langs->trans('#'), 0, $_SERVER["PHP_SELF"], 'rowid', '', $param, '', $sortfield, $sortorder, 'minwidth50 ')."\n";
569print getTitleFieldOfList($langs->trans('Date'), 0, $_SERVER["PHP_SELF"], 'date_creation', '', $param, '', $sortfield, $sortorder, '')."\n";
570print getTitleFieldOfList($langs->trans('Author'), 0, $_SERVER["PHP_SELF"], 'user_fullname', '', $param, '', $sortfield, $sortorder, '')."\n";
571print getTitleFieldOfList($langs->trans('Action'), 0, $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, '')."\n";
572print getTitleFieldOfList($langs->trans('Ref'), 0, $_SERVER["PHP_SELF"], 'ref_object', '', $param, '', $sortfield, $sortorder, '')."\n";
573print getTitleFieldOfList($langs->trans('Amount'), 0, $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ')."\n";
574print getTitleFieldOfList($langs->trans('DataOfArchivedEvent'), 0, $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'center ', 0, $langs->trans('DataOfArchivedEventHelp'), 1)."\n";
575print getTitleFieldOfList($langs->trans('Fingerprint'), 0, $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, '')."\n";
576print getTitleFieldOfList($form->textwithpicto($langs->trans('Status'), $langs->trans('DataOfArchivedEventHelp2')), 0, $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'center ')."\n";
577//print getTitleFieldOfList('', 0, $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'center ')."\n";
578print getTitleFieldOfList('', 0, $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, '')."\n";
579// Action column
580if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
581 print getTitleFieldOfList('<span id="blockchainstatus"></span>', 0, $_SERVER["PHP_SELF"], '', '', $param, 'class="center"', $sortfield, $sortorder, '')."\n";
582}
583print '</tr>';
584
585$checkresult = array();
586$checkdetail = array();
587$loweridinerror = 0;
588
589if (getDolGlobalString('BLOCKEDLOG_SCAN_ALL_FOR_LOWERIDINERROR')) {
590 // This is version that is faster but require more memory and report errors that are outside the filter range
591
592 // TODO Make a full scan of table in reverse order of id of $block, so we can use the parameter $previoushash into checkSignature to save requests
593 // to find the $loweridinerror.
594} else {
595 // This is version that optimize the memory (but will not report errors that are outside the filter range)
596 if (is_array($blocks)) {
597 foreach ($blocks as &$block) {
598 $tmpcheckresult = $block->checkSignature('', 1); // Note: this make a sql request at each call, we can't avoid this as the sorting order is various
599
600 $checksignature = $tmpcheckresult['checkresult'];
601
602 $checkresult[$block->id] = $checksignature; // false if error
603 $checkdetail[$block->id] = $tmpcheckresult;
604
605 if (!$checksignature) {
606 if (empty($loweridinerror)) {
607 $loweridinerror = $block->id;
608 } else {
609 $loweridinerror = min($loweridinerror, $block->id);
610 }
611 }
612 }
613 }
614}
615
616if (is_array($blocks)) {
617 $nbshown = 0;
618 $object_link = '';
619 $object_link_title = '';
620
621 foreach ($blocks as &$block) {
622 //if (empty($search_showonlyerrors) || ! $checkresult[$block->id] || ($loweridinerror && $block->id >= $loweridinerror))
623 if (empty($search_showonlyerrors) || !$checkresult[$block->id]) {
624 $nbshown++;
625
626 if ($nbshown < $MAXFORSHOWNLINKS) { // For performance and memory purpose, we get/show the link of objects only for the 100 first output
627 $object_link = $block->getObjectLink();
628 $object_link_title = '';
629 } else {
630 $object_link = $block->element.'/'.$block->fk_object;
631 $object_link_title = $langs->trans('LinkHasBeenDisabledForPerformancePurpose');
632 }
633
634 print '<tr class="oddeven">';
635
636 // Action column
637 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
638 print '<td class="liste_titre">';
639 print '</td>';
640 }
641
642 // ID
643 print '<td>'.dol_escape_htmltag((string) $block->id).'</td>';
644
645 // Date
646 print '<td class="nowraponall">'.dol_print_date($block->date_creation, 'dayhour').'</td>';
647
648 // User
649 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($block->user_fullname).'">';
650 //print $block->getUser()
651 print dol_escape_htmltag($block->user_fullname);
652 print '</td>';
653
654 // Action
655 $labelofaction = $langs->transnoentitiesnoconv('log'.$block->action);
656 print '<td class="tdoverflowmax250" title="'.dol_escape_htmltag($labelofaction).'">'.dolPrintHTML($labelofaction).'</td>';
657
658 // Ref
659 print '<td class="nowraponall">';
660 print dol_escape_htmltag($block->ref_object);
661 print '</td>';
662
663 // Amount
664 print '<td class="right nowraponall">'.price($block->amounts).'</td>';
665
666 // Details link
667 print '<td class="center"><a href="#" data-blockid="'.$block->id.'" rel="show-info">'.img_info($langs->trans('ShowDetails')).'</a></td>';
668
669 // Fingerprint
670 print '<td class="nowraponall">';
671 // Note: the previous line id is not necessarily id-1, so in texttoshow we say "on previous line" without giving id to avoid a search/fetch to get previous id.
672 $texttoshow = $langs->trans("Fingerprint").' - '.$langs->trans("SavedOnLine").' =<br>'.$block->signature;
673 $texttoshow .= '<br><br>'.$langs->trans("Fingerprint").' - Recalculated sha256('.$langs->trans("PreviousHash").' on previous line + data) =<br>'.$checkdetail[$block->id]['calculatedsignature'];
674 $texttoshow .= '<br><span class="opacitymedium">'.$langs->trans("PreviousHash").'='.$checkdetail[$block->id]['previoushash'].'</span>';
675 //$texttoshow .= '<br>keyforsignature='.$checkdetail[$block->id]['keyforsignature'];
676 print $form->textwithpicto(dol_trunc($block->signature, 8), $texttoshow, 1, 'help', '', 0, 2, 'fingerprint'.$block->id);
677 print '</td>';
678
679 // Status
680 print '<td class="center">';
681 if (!$checkresult[$block->id] || ($loweridinerror && $block->id >= $loweridinerror)) { // If error
682 if ($checkresult[$block->id]) {
683 print '<span class="badge badge-status4 badge-status" title="'.$langs->trans('OkCheckFingerprintValidityButChainIsKo').'">OK</span>';
684 } else {
685 print '<span class="badge badge-status8 badge-status" title="'.$langs->trans('KoCheckFingerprintValidity').'">KO</span>';
686 }
687 } else {
688 print '<span class="badge badge-status4 badge-status" title="'.$langs->trans('OkCheckFingerprintValidity').'">OK</span>';
689 }
690 //print '</td>';
691
692 // Note
693 //print '<td class="center">';
694 if (!$checkresult[$block->id] || ($loweridinerror && $block->id >= $loweridinerror)) { // If error
695 if ($checkresult[$block->id]) {
696 print $form->textwithpicto('', $langs->trans('OkCheckFingerprintValidityButChainIsKo'));
697 } else {
698 //print $form->textwithpicto('', $langs->trans('KoCheckFingerprintValidity'));
699 }
700 } else {
701 //print $form->textwithpicto('', $langs->trans('DataOfArchivedEventHelp2'));
702 }
703
704 if (getDolGlobalString('BLOCKEDLOG_USE_REMOTE_AUTHORITY') && getDolGlobalString('BLOCKEDLOG_AUTHORITY_URL')) {
705 print ' '.($block->certified ? img_picto($langs->trans('AddedByAuthority'), 'info') : img_picto($langs->trans('NotAddedByAuthorityYet'), 'info_black'));
706 }
707 print '</td>';
708
709 // Link to source object
710 print '<td class="tdoverflowmax150"'.(preg_match('/<a/', $object_link) ? '' : 'title="'.dol_escape_htmltag(dol_string_nohtmltag($object_link.($object_link_title ? ' - '.$object_link_title : ''))).'"').'>';
711 print '<!-- object_link -->'; // $object_link can be a '<a href' link or a text
712 print $object_link;
713 print '</td>';
714
715 // Action column
716 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
717 print '<td class="liste_titre">';
718 print '</td>';
719 }
720
721 print '</tr>';
722 }
723 }
724
725 if ($nbshown == 0) {
726 print '<tr><td colspan="12"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
727 }
728}
729
730print '</table>';
731
732print '</div>';
733
734print '</form>';
735
736// Javascript to manage the showinfo popup
737print '<script type="text/javascript">
738
739jQuery(document).ready(function () {
740 jQuery("#dialogforpopup").dialog(
741 { closeOnEscape: true, classes: { "ui-dialog": "highlight" },
742 maxHeight: window.innerHeight-60, height: window.innerHeight-60, width: '.($conf->browser->layout == 'phone' ? 400 : 700).',
743 modal: true,
744 autoOpen: false }).css("z-index: 5000");
745
746 $("a[rel=show-info]").click(function() {
747
748 console.log("We click on tooltip, we open popup and get content using an ajax call");
749
750 var fk_block = $(this).attr("data-blockid");
751
752 $.ajax({
753 method: "GET",
754 data: { token: \''.currentToken().'\' },
755 url: "'.DOL_URL_ROOT.'/blockedlog/ajax/block-info.php?id="+fk_block,
756 dataType: "html"
757 }).done(function(data) {
758 jQuery("#dialogforpopup").html(data);
759 });
760
761 jQuery("#dialogforpopup").dialog("open");
762 });
763})
764</script>'."\n";
765
766
767if (getDolGlobalString('BLOCKEDLOG_USE_REMOTE_AUTHORITY') && getDolGlobalString('BLOCKEDLOG_AUTHORITY_URL')) {
768 ?>
769 <script type="text/javascript">
770
771 $.ajax({
772 method: "GET",
773 data: { token: '<?php echo currentToken() ?>' },
774 url: '<?php echo DOL_URL_ROOT.'/blockedlog/ajax/check_signature.php' ?>',
775 dataType: 'html'
776 }).done(function(data) {
777 if(data == 'hashisok') {
778 $('#blockchainstatus').html('<?php echo $langs->trans('AuthorityReconizeFingerprintConformity').' '.img_picto($langs->trans('SignatureOK'), 'on') ?>');
779 }
780 else{
781 $('#blockchainstatus').html('<?php echo $langs->trans('AuthorityDidntReconizeFingerprintConformity').' '.img_picto($langs->trans('SignatureKO'), 'off') ?>');
782 }
783
784 });
785
786 </script>
787 <?php
788}
789
790if (GETPOST('withtab', 'alpha')) {
791 print dol_get_fiche_end();
792}
793
794print '<br><br>';
795
796// End of page
797llxFooter();
798$db->close();
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:67
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
blockedlogadmin_prepare_head()
Define head array for tabs of blockedlog tools setup pages.
Class to manage certif authority.
Class to manage Blocked Log.
Class to manage generation of HTML components Only common components must be here.
Class permettant la generation de composants html autre Only common components are here.
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:600
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:125
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:619
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
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.
dolPrintHTML($s, $allowiframe=0)
Return a string (that can be on several lines) ready to be output on a HTML page.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
currentToken()
Return the value of token currently saved into session with name 'token'.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip='', $forcenowrapcolumntitle=0)
Get title line of an array.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
img_info($titlealt='default')
Show info logo.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.