27 require
'../../main.inc.php';
28 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
29 require_once DOL_DOCUMENT_ROOT.
'/core/lib/geturl.lib.php';
31 $langs->load(
"admin");
48 print
load_fiche_titre($langs->trans(
"FileCheckDolibarr"),
'',
'title_setup');
50 print
'<span class="opacitymedium">'.$langs->trans(
"FileCheckDesc").
'</span><br><br>';
53 print
'<div class="div-table-responsive-no-min">';
54 print
'<table class="noborder centpercent">';
55 print
'<tr class="liste_titre"><td>'.$langs->trans(
"Version").
'</td><td>'.$langs->trans(
"Value").
'</td></tr>'.
"\n";
56 print
'<tr class="oddeven"><td width="300">'.$langs->trans(
"VersionLastInstall").
'</td><td>'.
getDolGlobalString(
'MAIN_VERSION_LAST_INSTALL').
'</td></tr>'.
"\n";
57 print
'<tr class="oddeven"><td width="300">'.$langs->trans(
"VersionLastUpgrade").
'</td><td>'.
getDolGlobalString(
'MAIN_VERSION_LAST_UPGRADE').
'</td></tr>'.
"\n";
58 print
'<tr class="oddeven"><td width="300">'.$langs->trans(
"VersionProgram").
'</td><td>'.DOL_VERSION;
60 if (empty($conf->global->MAIN_VERSION_LAST_UPGRADE)) {
62 if (DOL_VERSION != $conf->global->MAIN_VERSION_LAST_INSTALL) {
63 print
' '.img_warning($langs->trans(
"RunningUpdateProcessMayBeRequired", DOL_VERSION, $conf->global->MAIN_VERSION_LAST_INSTALL));
67 if (DOL_VERSION != $conf->global->MAIN_VERSION_LAST_UPGRADE) {
68 print
' '.img_warning($langs->trans(
"RunningUpdateProcessMayBeRequired", DOL_VERSION, $conf->global->MAIN_VERSION_LAST_UPGRADE));
71 print
'</td></tr>'.
"\n";
78 $file_list = array(
'missing' => array(),
'updated' => array());
81 $xmlshortfile =
dol_sanitizeFileName(
GETPOST(
'xmlshortfile',
'alpha') ?
GETPOST(
'xmlshortfile',
'alpha') :
'filelist-'.DOL_VERSION.(empty($conf->global->MAIN_FILECHECK_LOCAL_SUFFIX) ?
'' : $conf->global->MAIN_FILECHECK_LOCAL_SUFFIX).
'.xml'.(empty($conf->global->MAIN_FILECHECK_LOCAL_EXT) ?
'' : $conf->global->MAIN_FILECHECK_LOCAL_EXT));
83 $xmlfile = DOL_DOCUMENT_ROOT.
'/install/'.$xmlshortfile;
84 if (!preg_match(
'/\.zip$/i', $xmlfile) &&
dol_is_file($xmlfile.
'.zip')) {
85 $xmlfile = $xmlfile.
'.zip';
89 $xmlremote =
GETPOST(
'xmlremote',
'alphanohtml');
90 if (empty($xmlremote) && !empty($conf->global->MAIN_FILECHECK_URL)) {
91 $xmlremote = $conf->global->MAIN_FILECHECK_URL;
93 $param =
'MAIN_FILECHECK_URL_'.DOL_VERSION;
94 if (empty($xmlremote) && !empty($conf->global->$param)) {
95 $xmlremote = $conf->global->$param;
97 if (empty($xmlremote)) {
98 $xmlremote =
'https://www.dolibarr.org/files/stable/signatures/filelist-'.DOL_VERSION.
'.xml';
100 if ($xmlremote && !preg_match(
'/^https?:\/\//', $xmlremote)) {
101 $langs->load(
"errors");
102 setEventMessages($langs->trans(
"ErrorURLMustStartWithHttp", $xmlremote),
'',
'errors');
104 } elseif ($xmlremote && !preg_match(
'/\.xml$/', $xmlremote)) {
105 $langs->load(
"errors");
106 setEventMessages($langs->trans(
"ErrorURLMustEndWith", $xmlremote,
'.xml'),
'',
'errors');
111 $enableremotecheck =
true;
112 if (preg_match(
'/beta|alpha|rc/i', DOL_VERSION) || !empty($conf->global->MAIN_ALLOW_INTEGRITY_CHECK_ON_UNSTABLE)) {
113 $enableremotecheck =
false;
115 $enableremotecheck =
true;
117 print
'<form name="check" action="'.$_SERVER[
"PHP_SELF"].
'">';
118 print
'<input type="hidden" name="token" value="'.newToken().
'">';
119 print $langs->trans(
"MakeIntegrityAnalysisFrom").
':<br>';
120 print
'<!-- for a local check target=local&xmlshortfile=... -->'.
"\n";
122 print
'<input type="radio" name="target" id="checkboxlocal" value="local"'.((!
GETPOST(
'target') ||
GETPOST(
'target') ==
'local') ?
'checked="checked"' :
'').
'"> <label for="checkboxlocal">'.$langs->trans(
"LocalSignature").
'</label> = ';
123 print
'<input name="xmlshortfile" class="flat minwidth400" value="'.dol_escape_htmltag($xmlshortfile).
'">';
126 print
'<input type="radio" name="target" id="checkboxlocal" value="local"> <label for="checkboxlocal">'.$langs->trans(
"LocalSignature").
' = ';
127 print
'<input name="xmlshortfile" class="flat minwidth400" value="'.dol_escape_htmltag($xmlshortfile).
'">';
128 print
' <span class="warning">('.$langs->trans(
"AvailableOnlyOnPackagedVersions").
')</span></label>';
131 print
'<!-- for a remote target=remote&xmlremote=... -->'.
"\n";
132 if ($enableremotecheck) {
133 print
'<input type="radio" name="target" id="checkboxremote" value="remote"'.(GETPOST(
'target') ==
'remote' ?
'checked="checked"' :
'').
'> <label for="checkboxremote">'.$langs->trans(
"RemoteSignature").
'</label> = ';
134 print
'<input name="xmlremote" class="flat minwidth500" value="'.dol_escape_htmltag($xmlremote).
'"><br>';
136 print
'<input type="radio" name="target" id="checkboxremote" value="remote" disabled="disabled"> '.$langs->trans(
"RemoteSignature").
' = '.
dol_escape_htmltag($xmlremote);
138 print
' <span class="warning">('.$langs->trans(
"FeatureAvailableOnlyOnStable").
')</span>';
142 print
'<br><div class="center"><input type="submit" name="check" class="button" value="'.$langs->trans(
"Check").
'"></div>';
147 if (
GETPOST(
'target') ==
'local') {
150 if (preg_match(
'/\.zip$/i', $xmlfile)) {
152 $xmlfilenew = preg_replace(
'/\.zip$/i',
'', $xmlfile);
154 if (empty($result[
'error'])) {
155 $xmlfile = $conf->admin->dir_temp.
'/'.basename($xmlfilenew);
157 print $langs->trans(
'FailedToUncompressFile').
': '.$xmlfile;
161 $xml = simplexml_load_file($xmlfile);
162 if ($xml ===
false) {
163 print
'<div class="warning">'.$langs->trans(
'XmlCorrupted').
': '.$xmlfile.
'</span>';
167 print
'<div class="warning">'.$langs->trans(
'XmlNotFound').
': '.$xmlfile.
'</span>';
171 if (
GETPOST(
'target') ==
'remote') {
172 $xmlarray =
getURLContent($xmlremote,
'GET',
'', 1, array(), array(
'http',
'https'), 0);
175 if (!$xmlarray[
'curl_error_no'] && $xmlarray[
'http_code'] !=
'400' && $xmlarray[
'http_code'] !=
'404') {
176 $xmlfile = $xmlarray[
'content'];
178 $xml = simplexml_load_string($xmlfile,
'SimpleXMLElement', LIBXML_NOCDATA|LIBXML_NONET);
180 $errormsg = $langs->trans(
'XmlNotFound').
': '.$xmlremote.
' - '.$xmlarray[
'http_code'].(($xmlarray[
'http_code'] == 400 && $xmlarray[
'content']) ?
' '.$xmlarray[
'content'] :
'').
' '.$xmlarray[
'curl_error_no'].
' '.$xmlarray[
'curl_error_msg'];
187 if (empty($error) && !empty($xml)) {
188 $checksumconcat = array();
189 $file_list = array();
193 if (is_object($xml->dolibarr_constants[0])) {
196 $out .=
'<div class="div-table-responsive-no-min">';
197 $out .=
'<table class="noborder">';
198 $out .=
'<tr class="liste_titre">';
199 $out .=
'<td>#</td>';
200 $out .=
'<td>'.$langs->trans(
"Constant").
'</td>';
201 $out .=
'<td class="center">'.$langs->trans(
"ExpectedValue").
'</td>';
202 $out .=
'<td class="center">'.$langs->trans(
"Value").
'</td>';
203 $out .=
'</tr>'.
"\n";
206 foreach ($xml->dolibarr_constants[0]->constant as $constant) {
207 $constname = $constant[
'name'];
208 $constvalue = (string) $constant;
209 $constvalue = (empty($constvalue) ?
'0' : $constvalue);
215 $valueforchecksum = (empty($value) ?
'0' : $value);
217 $checksumconcat[] = $valueforchecksum;
220 $out .=
'<tr class="oddeven">';
221 $out .=
'<td>'.$i.
'</td>'.
"\n";
222 $out .=
'<td>'.dol_escape_htmltag($constname).
'</td>'.
"\n";
223 $out .=
'<td class="center">'.dol_escape_htmltag($constvalue).
'</td>'.
"\n";
224 $out .=
'<td class="center">'.dol_escape_htmltag($valueforchecksum).
'</td>'.
"\n";
229 $out .=
'<tr class="oddeven"><td colspan="4" class="opacitymedium">'.$langs->trans(
"None").
'</td></tr>';
238 if (is_object($xml->dolibarr_htdocs_dir[0])) {
240 $includecustom = (empty($xml->dolibarr_htdocs_dir[0][
'includecustom']) ? 0 : $xml->dolibarr_htdocs_dir[0][
'includecustom']);
243 $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)$';
244 $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)$';
245 $scanfiles =
dol_dir_list(DOL_DOCUMENT_ROOT,
'files', 1, $regextoinclude, $regextoexclude);
248 $ret =
getFilesUpdated($file_list, $xml->dolibarr_htdocs_dir[0],
'', DOL_DOCUMENT_ROOT, $checksumconcat);
250 foreach ($scanfiles as $keyfile => $valfile) {
251 $tmprelativefilename = preg_replace(
'/^'.preg_quote(DOL_DOCUMENT_ROOT,
'/').
'/',
'', $valfile[
'fullname']);
252 if (!in_array($tmprelativefilename, $file_list[
'insignature'])) {
253 $md5newfile = @md5_file($valfile[
'fullname']);
254 $file_list[
'added'][] = array(
'filename'=>$tmprelativefilename,
'md5'=>$md5newfile);
261 $out .=
'<div class="div-table-responsive-no-min">';
262 $out .=
'<table class="noborder">';
263 $out .=
'<tr class="liste_titre">';
264 $out .=
'<td>#</td>';
265 $out .=
'<td>'.$langs->trans(
"Filename").
'</td>';
266 $out .=
'<td class="right">'.$langs->trans(
"ExpectedSize").
'</td>';
267 $out .=
'<td class="center">'.$langs->trans(
"ExpectedChecksum").
'</td>';
268 $out .=
'</tr>'.
"\n";
270 if (is_array($tmpfilelist) && count($tmpfilelist)) {
272 foreach ($tmpfilelist as $file) {
274 $out .=
'<tr class="oddeven">';
275 $out .=
'<td>'.$i.
'</td>'.
"\n";
276 $out .=
'<td>'.dol_escape_htmltag($file[
'filename']).
'</td>'.
"\n";
277 $out .=
'<td class="right">';
278 if (!empty($file[
'expectedsize'])) {
281 $out .=
'</td>'.
"\n";
282 $out .=
'<td class="center">'.dol_escape_htmltag($file[
'expectedmd5']).
'</td>'.
"\n";
286 $out .=
'<tr class="oddeven"><td colspan="4" class="opacitymedium">'.$langs->trans(
"None").
'</td></tr>';
297 $out .=
'<div class="div-table-responsive-no-min">';
298 $out .=
'<table class="noborder">';
299 $out .=
'<tr class="liste_titre">';
300 $out .=
'<td>#</td>';
301 $out .=
'<td>'.$langs->trans(
"Filename").
'</td>';
302 $out .=
'<td class="center">'.$langs->trans(
"ExpectedChecksum").
'</td>';
303 $out .=
'<td class="center">'.$langs->trans(
"CurrentChecksum").
'</td>';
304 $out .=
'<td class="right">'.$langs->trans(
"ExpectedSize").
'</td>';
305 $out .=
'<td class="right">'.$langs->trans(
"CurrentSize").
'</td>';
306 $out .=
'<td class="right">'.$langs->trans(
"DateModification").
'</td>';
307 $out .=
'</tr>'.
"\n";
308 $tmpfilelist2 =
dol_sort_array($file_list[
'updated'],
'filename');
309 if (is_array($tmpfilelist2) && count($tmpfilelist2)) {
311 foreach ($tmpfilelist2 as $file) {
313 $out .=
'<tr class="oddeven">';
314 $out .=
'<td>'.$i.
'</td>'.
"\n";
315 $out .=
'<td>'.dol_escape_htmltag($file[
'filename']).
'</td>'.
"\n";
316 $out .=
'<td class="center">'.dol_escape_htmltag($file[
'expectedmd5']).
'</td>'.
"\n";
317 $out .=
'<td class="center">'.dol_escape_htmltag($file[
'md5']).
'</td>'.
"\n";
318 $out .=
'<td class="right">';
319 if ($file[
'expectedsize']) {
322 $out .=
'</td>'.
"\n";
323 $size =
dol_filesize(DOL_DOCUMENT_ROOT.
'/'.$file[
'filename']);
325 $out .=
'<td class="right">'.dol_print_size($size).
'</td>'.
"\n";
326 $out .=
'<td class="right">'.dol_print_date(
dol_filemtime(DOL_DOCUMENT_ROOT.
'/'.$file[
'filename']),
'dayhour').
'</td>'.
"\n";
329 $out .=
'<tr class="liste_total">';
330 $out .=
'<td></td>'.
"\n";
331 $out .=
'<td>'.$langs->trans(
"Total").
'</td>'.
"\n";
332 $out .=
'<td class="center"></td>'.
"\n";
333 $out .=
'<td class="center"></td>'.
"\n";
334 $out .=
'<td class="center"></td>'.
"\n";
335 $out .=
'<td class="right">'.dol_print_size($totalsize).
'</td>'.
"\n";
336 $out .=
'<td class="right"></td>'.
"\n";
339 $out .=
'<tr class="oddeven"><td colspan="7" class="opacitymedium">'.$langs->trans(
"None").
'</td></tr>';
350 $out .=
'<div class="div-table-responsive-no-min">';
351 $out .=
'<table class="noborder">';
352 $out .=
'<tr class="liste_titre">';
353 $out .=
'<td>#</td>';
354 $out .=
'<td>'.$langs->trans(
"Filename").
'</td>';
355 $out .=
'<td class="center">'.$langs->trans(
"ExpectedChecksum").
'</td>';
356 $out .=
'<td class="center">'.$langs->trans(
"CurrentChecksum").
'</td>';
357 $out .=
'<td class="right">'.$langs->trans(
"Size").
'</td>';
358 $out .=
'<td class="right">'.$langs->trans(
"DateModification").
'</td>';
359 $out .=
'</tr>'.
"\n";
361 if (is_array($tmpfilelist3) && count($tmpfilelist3)) {
363 foreach ($tmpfilelist3 as $file) {
365 $out .=
'<tr class="oddeven">';
366 $out .=
'<td>'.$i.
'</td>'.
"\n";
367 $out .=
'<td>'.dol_escape_htmltag($file[
'filename']);
368 if (!preg_match(
'/^win/i', PHP_OS)) {
369 $htmltext = $langs->trans(
"YouCanDeleteFileOnServerWith",
'rm '.DOL_DOCUMENT_ROOT.$file[
'filename']);
370 $out .=
' '.$form->textwithpicto(
'', $htmltext, 1,
'help',
'', 0, 2,
'helprm'.$i);
372 $out .=
'</td>'.
"\n";
373 $out .=
'<td class="center">'.dol_escape_htmltag($file[
'expectedmd5']).
'</td>'.
"\n";
374 $out .=
'<td class="center">'.dol_escape_htmltag($file[
'md5']).
'</td>'.
"\n";
375 $size =
dol_filesize(DOL_DOCUMENT_ROOT.
'/'.$file[
'filename']);
377 $out .=
'<td class="right">'.dol_print_size($size).
'</td>'.
"\n";
378 $out .=
'<td class="right">'.dol_print_date(
dol_filemtime(DOL_DOCUMENT_ROOT.
'/'.$file[
'filename']),
'dayhour').
'</td>'.
"\n";
381 $out .=
'<tr class="liste_total">';
382 $out .=
'<td></td>'.
"\n";
383 $out .=
'<td>'.$langs->trans(
"Total").
'</td>'.
"\n";
384 $out .=
'<td class="center"></td>'.
"\n";
385 $out .=
'<td class="center"></td>'.
"\n";
386 $out .=
'<td class="right">'.dol_print_size($totalsize).
'</td>'.
"\n";
387 $out .=
'<td class="right"></td>'.
"\n";
390 $out .=
'<tr class="oddeven"><td colspan="6" class="opacitymedium">'.$langs->trans(
"None").
'</td></tr>';
395 print
'<div class="error">';
396 print
'Error: Failed to found <b>dolibarr_htdocs_dir</b> into content of XML file:<br>'.dol_escape_htmltag(
dol_trunc($xmlfile, 500));
411 asort($checksumconcat);
413 $checksumget = md5(join(
',', $checksumconcat));
414 $checksumtoget = trim((
string) $xml->dolibarr_htdocs_dir_checksum);
423 $outexpectedchecksum = ($checksumtoget ? $checksumtoget : $langs->trans(
"Unknown"));
424 if ($checksumget == $checksumtoget) {
425 if (is_array($file_list[
'added']) && count($file_list[
'added'])) {
426 $resultcode =
'warning';
427 $resultcomment =
'FileIntegrityIsOkButFilesWereAdded';
428 $outcurrentchecksum = $checksumget.
' - <span class="'.$resultcode.
'">'.$langs->trans($resultcomment).
'</span>';
431 $resultcomment =
'Success';
432 $outcurrentchecksum =
'<span class="'.$resultcode.
'">'.$checksumget.
'</span>';
435 $resultcode =
'error';
436 $resultcomment =
'Error';
437 $outcurrentchecksum =
'<span class="'.$resultcode.
'">'.$checksumget.
'</span>';
441 if (empty($tmpfilelist) && empty($tmpfilelist2) && empty($tmpfilelist3) && $resultcode ==
'ok') {
442 setEventMessages($langs->trans(
"FileIntegrityIsStrictlyConformedWithReference"),
null,
'mesgs');
444 if ($resultcode ==
'warning') {
447 setEventMessages($langs->trans(
"FileIntegritySomeFilesWereRemovedOrModified"),
null,
'errors');
452 print $langs->trans(
"ExpectedChecksum").
' = '.$outexpectedchecksum.
'<br>';
453 print $langs->trans(
"CurrentChecksum").
' = '.$outcurrentchecksum;