29require
'../../main.inc.php';
30require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
31require_once DOL_DOCUMENT_ROOT.
'/core/lib/geturl.lib.php';
57llxHeader(
'',
'',
'',
'', 0, 0,
'',
'',
'',
'mod-admin page-system_filecheck');
59print
load_fiche_titre($langs->trans(
"FileCheckDolibarr"),
'',
'title_setup');
61print
'<span class="opacitymedium">'.$langs->trans(
"FileCheckDesc").
'</span><br><br>';
64print
'<div class="div-table-responsive-no-min">';
65print
'<table class="noborder centpercent">';
66print
'<tr class="liste_titre"><td>'.$langs->trans(
"Version").
'</td><td></td></tr>'.
"\n";
67print
'<tr class="oddeven"><td width="300">'.$langs->trans(
"VersionLastInstall").
'</td><td>'.
getDolGlobalString(
'MAIN_VERSION_LAST_INSTALL').
'</td></tr>'.
"\n";
68print
'<tr class="oddeven"><td width="300">'.$langs->trans(
"VersionLastUpgrade").
'</td><td>'.
getDolGlobalString(
'MAIN_VERSION_LAST_UPGRADE').
'</td></tr>'.
"\n";
69print
'<tr class="oddeven"><td width="300">'.$langs->trans(
"VersionProgram").
'</td><td>'.DOL_VERSION;
74 print
' '.img_warning($langs->trans(
"RunningUpdateProcessMayBeRequired", DOL_VERSION,
getDolGlobalString(
'MAIN_VERSION_LAST_INSTALL')));
78 if (DOL_VERSION !=
$conf->global->MAIN_VERSION_LAST_UPGRADE) {
79 print
' '.img_warning($langs->trans(
"RunningUpdateProcessMayBeRequired", DOL_VERSION,
getDolGlobalString(
'MAIN_VERSION_LAST_UPGRADE')));
82print
'</td></tr>'.
"\n";
89$file_list = array(
'missing' => array(),
'updated' => array());
94$xmlfile = DOL_DOCUMENT_ROOT.
'/install/'.$xmlshortfile;
95if (!preg_match(
'/\.zip$/i', $xmlfile) &&
dol_is_file($xmlfile.
'.zip')) {
100$xmlremote =
GETPOST(
'xmlremote',
'alphanohtml');
104$param =
'MAIN_FILECHECK_URL_'.DOL_VERSION;
108if (empty($xmlremote)) {
109 $xmlremote =
'https://www.dolibarr.org/files/stable/signatures/filelist-'.DOL_VERSION.
'.xml';
111if ($xmlremote && !preg_match(
'/^https?:\/\//', $xmlremote)) {
112 $langs->load(
"errors");
113 setEventMessages($langs->trans(
"ErrorURLMustStartWithHttp", $xmlremote),
null,
'errors');
115} elseif ($xmlremote && !preg_match(
'/\.xml$/', $xmlremote)) {
116 $langs->load(
"errors");
117 setEventMessages($langs->trans(
"ErrorURLMustEndWith", $xmlremote,
'.xml'),
null,
'errors');
122$enableremotecheck =
true;
123if (preg_match(
'/beta|alpha|rc/i', DOL_VERSION) ||
getDolGlobalString(
'MAIN_ALLOW_INTEGRITY_CHECK_ON_UNSTABLE')) {
124 $enableremotecheck =
false;
126$enableremotecheck =
true;
128print
'<form name="check" action="'.$_SERVER[
"PHP_SELF"].
'">';
129print
'<input type="hidden" name="token" value="'.newToken().
'">';
130print $langs->trans(
"MakeIntegrityAnalysisFrom").
':<br>';
132print
'<div class="divsection">';
133print
'<!-- for a local check target=local&xmlshortfile=... -->'.
"\n";
135 print
'<input type="radio" name="target" id="checkboxlocal" value="local"'.((!
GETPOST(
'target') ||
GETPOST(
'target') ==
'local') ?
'checked="checked"' :
'').
'"> <label for="checkboxlocal">'.$langs->trans(
"LocalSignature").
'</label> = ';
136 print
'<input name="xmlshortfile" class="flat minwidth400" value="'.dol_escape_htmltag($xmlshortfile).
'">';
139 print
'<input type="radio" name="target" id="checkboxlocal" value="local"> <label for="checkboxlocal">'.$langs->trans(
"LocalSignature").
' = ';
140 print
'<input name="xmlshortfile" class="flat minwidth400" value="'.dol_escape_htmltag($xmlshortfile).
'">';
141 print
' <span class="warning">('.$langs->trans(
"AvailableOnlyOnPackagedVersions").
')</span></label>';
144print
'<!-- for a remote target=remote&xmlremote=... -->'.
"\n";
145if ($enableremotecheck) {
146 print
'<input type="radio" name="target" id="checkboxremote" value="remote"'.(GETPOST(
'target') ==
'remote' ?
'checked="checked"' :
'').
'> <label for="checkboxremote">'.$langs->trans(
"RemoteSignature").
'</label> = ';
147 print
'<input name="xmlremote" class="flat minwidth500" value="'.dol_escape_htmltag($xmlremote).
'"><br>';
149 print
'<input type="radio" name="target" id="checkboxremote" value="remote" disabled="disabled"> '.$langs->trans(
"RemoteSignature").
' = '.
dol_escape_htmltag($xmlremote);
151 print
' <span class="warning">('.$langs->trans(
"FeatureAvailableOnlyOnStable").
')</span>';
157print
'<div class="center"><input type="submit" name="check" class="button" value="'.$langs->trans(
"Check").
'"></div>';
162if (
GETPOST(
'target') ==
'local') {
165 if (preg_match(
'/\.zip$/i', $xmlfile)) {
167 $xmlfilenew = preg_replace(
'/\.zip$/i',
'', $xmlfile);
169 if (empty($result[
'error'])) {
170 $xmlfile =
$conf->admin->dir_temp.
'/'.basename($xmlfilenew);
172 print $langs->trans(
'FailedToUncompressFile').
': '.$xmlfile;
176 $xml = simplexml_load_file($xmlfile);
177 if ($xml ===
false) {
178 print
'<div class="warning">'.$langs->trans(
'XmlCorrupted').
': '.$xmlfile.
'</span>';
182 print
'<div class="warning">'.$langs->trans(
'XmlNotFound').
': '.$xmlfile.
'</span>';
186if (
GETPOST(
'target') ==
'remote') {
187 $xmlarray =
getURLContent($xmlremote,
'GET',
'', 1, array(), array(
'http',
'https'), 0);
190 if (!$xmlarray[
'curl_error_no'] && $xmlarray[
'http_code'] !=
'400' && $xmlarray[
'http_code'] !=
'404') {
191 $xmlfile = $xmlarray[
'content'];
193 if (LIBXML_VERSION < 20900) {
197 libxml_disable_entity_loader(
true);
200 $xml = simplexml_load_string($xmlfile,
'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NONET);
202 $errormsg = $langs->trans(
'XmlNotFound').
': '.$xmlremote.
' - '.$xmlarray[
'http_code'].(($xmlarray[
'http_code'] == 400 && $xmlarray[
'content']) ?
' '.$xmlarray[
'content'] :
'').
' '.$xmlarray[
'curl_error_no'].
' '.$xmlarray[
'curl_error_msg'];
209if (empty($error) && !empty($xml)) {
210 $checksumconcat = array();
211 $file_list = array();
215 if (is_object($xml->dolibarr_constants[0])) {
218 $out .=
'<div class="div-table-responsive-no-min">';
219 $out .=
'<table class="noborder">';
220 $out .=
'<tr class="liste_titre">';
221 $out .=
'<td>#</td>';
222 $out .=
'<td>'.$langs->trans(
"Constant").
'</td>';
223 $out .=
'<td class="center">'.$langs->trans(
"ExpectedValue").
'</td>';
224 $out .=
'<td class="center">'.$langs->trans(
"Value").
'</td>';
225 $out .=
'</tr>'.
"\n";
228 foreach ($xml->dolibarr_constants[0]->constant as $constant) {
229 $constname = $constant[
'name'];
230 $constvalue = (string) $constant;
231 $constvalue = (empty($constvalue) ?
'0' : $constvalue);
237 $valueforchecksum = (empty($value) ?
'0' : $value);
239 $checksumconcat[] = $valueforchecksum;
242 $out .=
'<tr class="oddeven">';
243 $out .=
'<td>'.$i.
'</td>'.
"\n";
244 $out .=
'<td>'.dol_escape_htmltag($constname).
'</td>'.
"\n";
245 $out .=
'<td class="center">'.dol_escape_htmltag($constvalue).
'</td>'.
"\n";
246 $out .=
'<td class="center">'.dol_escape_htmltag($valueforchecksum).
'</td>'.
"\n";
251 $out .=
'<tr class="oddeven"><td colspan="4"><span class="opacitymedium">'.$langs->trans(
"None").
'</span></td></tr>';
260 if (is_object($xml->dolibarr_htdocs_dir[0])) {
262 $includecustom = (empty($xml->dolibarr_htdocs_dir[0][
'includecustom']) ? 0 : $xml->dolibarr_htdocs_dir[0][
'includecustom']);
265 $regextoinclude =
'\.(php|php3|php4|php5|phtml|phps|phar|inc|css|scss|html|xml|js|json|tpl|jpg|jpeg|png|gif|ico|sql|lang|txt|yml|bak|md|mp3|mp4|wav|mkv|z|gz|zip|rar|tar|less|svg|eot|woff|woff2|ttf|manifest)$';
266 $regextoexclude =
'('.($includecustom ?
'' :
'custom|').
'documents|conf|install|dejavu-fonts-ttf-.*|public\/test|sabre\/sabre\/.*\/tests|Shared\/PCLZip|nusoap\/lib\/Mail|php\/example|php\/test|geoip\/sample.*\.php|ckeditor\/samples|ckeditor\/adapters)$';
267 $scanfiles =
dol_dir_list(DOL_DOCUMENT_ROOT,
'files', 1, $regextoinclude, $regextoexclude);
270 $ret =
getFilesUpdated($file_list, $xml->dolibarr_htdocs_dir[0],
'', DOL_DOCUMENT_ROOT, $checksumconcat);
271 '@phan-var-force array{insignature:string[],missing?:array<array{filename:string,expectedmd5:string,expectedsize:string}>,updated:array<array{filename:string,expectedmd5:string,expectedsize:string,md5:string}>} $file_list';
273 foreach ($scanfiles as $keyfile => $valfile) {
274 $tmprelativefilename = preg_replace(
'/^'.preg_quote(DOL_DOCUMENT_ROOT,
'/').
'/',
'', $valfile[
'fullname']);
275 if (!in_array($tmprelativefilename, $file_list[
'insignature'])) {
276 $md5newfile = @md5_file($valfile[
'fullname']);
277 $file_list[
'added'][] = array(
'filename' => $tmprelativefilename,
'md5' => $md5newfile);
284 $out .=
'<div class="div-table-responsive-no-min">';
285 $out .=
'<table class="noborder">';
286 $out .=
'<tr class="liste_titre">';
287 $out .=
'<td>#</td>';
288 $out .=
'<td>'.$langs->trans(
"Filename").
'</td>';
289 $out .=
'<td class="right">'.$langs->trans(
"ExpectedSize").
'</td>';
290 $out .=
'<td class="center">'.$langs->trans(
"ExpectedChecksum").
'</td>';
291 $out .=
'</tr>'.
"\n";
293 if (is_array($tmpfilelist) && count($tmpfilelist)) {
295 foreach ($tmpfilelist as $file) {
297 $out .=
'<tr class="oddeven">';
298 $out .=
'<td>'.$i.
'</td>'.
"\n";
299 $out .=
'<td>'.dol_escape_htmltag($file[
'filename']).
'</td>'.
"\n";
300 $out .=
'<td class="right">';
301 if (!empty($file[
'expectedsize'])) {
304 $out .=
'</td>'.
"\n";
305 $out .=
'<td class="center">'.dol_escape_htmltag($file[
'expectedmd5']).
'</td>'.
"\n";
309 $out .=
'<tr class="oddeven"><td colspan="4"><span class="opacitymedium">'.$langs->trans(
"None").
'</span></td></tr>';
320 $out .=
'<div class="div-table-responsive-no-min">';
321 $out .=
'<table class="noborder">';
322 $out .=
'<tr class="liste_titre">';
323 $out .=
'<td>#</td>';
324 $out .=
'<td>'.$langs->trans(
"Filename").
'</td>';
325 $out .=
'<td class="center">'.$langs->trans(
"ExpectedChecksum").
'</td>';
326 $out .=
'<td class="center">'.$langs->trans(
"CurrentChecksum").
'</td>';
327 $out .=
'<td class="right">'.$langs->trans(
"ExpectedSize").
'</td>';
328 $out .=
'<td class="right">'.$langs->trans(
"CurrentSize").
'</td>';
329 $out .=
'<td class="right">'.$langs->trans(
"DateModification").
'</td>';
330 $out .=
'</tr>'.
"\n";
331 $tmpfilelist2 =
dol_sort_array($file_list[
'updated'],
'filename');
332 if (is_array($tmpfilelist2) && count($tmpfilelist2)) {
334 foreach ($tmpfilelist2 as $file) {
336 $out .=
'<tr class="oddeven">';
337 $out .=
'<td>'.$i.
'</td>'.
"\n";
338 $out .=
'<td>'.dol_escape_htmltag($file[
'filename']).
'</td>'.
"\n";
339 $out .=
'<td class="center">'.dol_escape_htmltag($file[
'expectedmd5']).
'</td>'.
"\n";
340 $out .=
'<td class="center">'.dol_escape_htmltag($file[
'md5']).
'</td>'.
"\n";
341 $out .=
'<td class="right">';
342 if ($file[
'expectedsize']) {
345 $out .=
'</td>'.
"\n";
346 $size =
dol_filesize(DOL_DOCUMENT_ROOT.
'/'.$file[
'filename']);
348 $out .=
'<td class="right">'.dol_print_size($size).
'</td>'.
"\n";
349 $out .=
'<td class="right">'.dol_print_date(
dol_filemtime(DOL_DOCUMENT_ROOT.
'/'.$file[
'filename']),
'dayhour').
'</td>'.
"\n";
352 $out .=
'<tr class="liste_total">';
353 $out .=
'<td></td>'.
"\n";
354 $out .=
'<td>'.$langs->trans(
"Total").
'</td>'.
"\n";
355 $out .=
'<td class="center"></td>'.
"\n";
356 $out .=
'<td class="center"></td>'.
"\n";
357 $out .=
'<td class="center"></td>'.
"\n";
358 $out .=
'<td class="right">'.dol_print_size($totalsize).
'</td>'.
"\n";
359 $out .=
'<td class="right"></td>'.
"\n";
362 $out .=
'<tr class="oddeven"><td colspan="7"><span class="opacitymedium">'.$langs->trans(
"None").
'</span></td></tr>';
373 $out .=
'<div class="div-table-responsive-no-min">';
374 $out .=
'<table class="noborder">';
375 $out .=
'<tr class="liste_titre">';
376 $out .=
'<td>#</td>';
377 $out .=
'<td>'.$langs->trans(
"Filename").
'</td>';
378 $out .=
'<td class="center">'.$langs->trans(
"ExpectedChecksum").
'</td>';
379 $out .=
'<td class="center">'.$langs->trans(
"CurrentChecksum").
'</td>';
380 $out .=
'<td class="right">'.$langs->trans(
"Size").
'</td>';
381 $out .=
'<td class="right">'.$langs->trans(
"DateModification").
'</td>';
382 $out .=
'</tr>'.
"\n";
384 if (is_array($tmpfilelist3) && count($tmpfilelist3)) {
386 foreach ($tmpfilelist3 as $file) {
388 $out .=
'<tr class="oddeven">';
389 $out .=
'<td>'.$i.
'</td>'.
"\n";
390 $out .=
'<td>'.dol_escape_htmltag($file[
'filename']);
391 if (!preg_match(
'/^win/i', PHP_OS)) {
392 $htmltext = $langs->trans(
"YouCanDeleteFileOnServerWith",
'rm '.DOL_DOCUMENT_ROOT.$file[
'filename']);
393 $out .=
' '.$form->textwithpicto(
'', $htmltext, 1,
'help',
'', 0, 2,
'helprm'.$i);
395 $out .=
'</td>'.
"\n";
396 $out .=
'<td class="center">'.dol_escape_htmltag($file[
'expectedmd5']).
'</td>'.
"\n";
397 $out .=
'<td class="center">'.dol_escape_htmltag($file[
'md5']).
'</td>'.
"\n";
398 $size =
dol_filesize(DOL_DOCUMENT_ROOT.
'/'.$file[
'filename']);
400 $out .=
'<td class="right">'.dol_print_size($size).
'</td>'.
"\n";
401 $out .=
'<td class="right nowraponall">'.dol_print_date(
dol_filemtime(DOL_DOCUMENT_ROOT.
'/'.$file[
'filename']),
'dayhour').
'</td>'.
"\n";
404 $out .=
'<tr class="liste_total">';
405 $out .=
'<td></td>'.
"\n";
406 $out .=
'<td>'.$langs->trans(
"Total").
'</td>'.
"\n";
407 $out .=
'<td class="center"></td>'.
"\n";
408 $out .=
'<td class="center"></td>'.
"\n";
409 $out .=
'<td class="right">'.dol_print_size($totalsize).
'</td>'.
"\n";
410 $out .=
'<td class="right"></td>'.
"\n";
413 $out .=
'<tr class="oddeven"><td colspan="6"><span class="opacitymedium">'.$langs->trans(
"None").
'</span></td></tr>';
418 print
'<div class="error">';
419 print
'Error: Failed to found <b>dolibarr_htdocs_dir</b> into content of XML file:<br>'.dol_escape_htmltag(
dol_trunc($xmlfile, 500));
435 asort($checksumconcat);
437 $checksumget = md5(implode(
',', $checksumconcat));
438 $checksumtoget = trim((
string) $xml->dolibarr_htdocs_dir_checksum);
447 $outexpectedchecksum = ($checksumtoget ? $checksumtoget : $langs->trans(
"Unknown"));
448 if ($checksumget == $checksumtoget) {
449 if (is_array($file_list[
'added']) && count($file_list[
'added'])) {
450 $resultcode =
'warning';
451 $resultcomment =
'FileIntegrityIsOkButFilesWereAdded';
452 $outcurrentchecksum = $checksumget.
' - <span class="'.$resultcode.
'">'.$langs->trans($resultcomment).
'</span>';
455 $resultcomment =
'Success';
456 $outcurrentchecksum =
'<span class="'.$resultcode.
'">'.$checksumget.
'</span>';
459 $resultcode =
'error';
460 $resultcomment =
'Error';
461 $outcurrentchecksum =
'<span class="'.$resultcode.
'">'.$checksumget.
'</span>';
465 if (empty($tmpfilelist) && empty($tmpfilelist2) && empty($tmpfilelist3) && $resultcode ==
'ok') {
466 setEventMessages($langs->trans(
"FileIntegrityIsStrictlyConformedWithReference"),
null,
'mesgs');
468 if ($resultcode ==
'warning') {
471 setEventMessages($langs->trans(
"FileIntegritySomeFilesWereRemovedOrModified"),
null,
'errors');
476 print $langs->trans(
"ExpectedChecksum").
' = '.$outexpectedchecksum.
'<br>';
477 print $langs->trans(
"CurrentChecksum").
' = '.$outcurrentchecksum;
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.
getFilesUpdated(&$file_list, SimpleXMLElement $dir, $path='', $pathref='', &$checksumconcat=array())
Function to get list of updated or modified files.
dol_filemtime($pathoffile)
Return time of a file.
dol_filesize($pathoffile)
Return size of a file.
dol_uncompress($inputfile, $outputdir)
Uncompress a file.
dol_is_file($pathoffile)
Return if path is a file.
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
dol_print_size($size, $shortvalue=0, $shortunit=0)
Return string with formatted size.
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.
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
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_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
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...
getURLContent($url, $postorget='GET', $param='', $followlocation=1, $addheaders=array(), $allowedschemes=array('http', 'https'), $localurl=0, $ssl_verifypeer=-1)
Function to get a content from an URL (use proxy if proxy defined).
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.