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