dolibarr  7.0.0-beta
filecheck.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2005-2016 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
4  * Copyright (C) 2007-2012 Regis Houssin <regis.houssin@capnetworks.com>
5  * Copyright (C) 2015 Frederic France <frederic.france@free.fr>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
26 require '../../main.inc.php';
27 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
28 require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
29 
30 $langs->load("admin");
31 
32 if (!$user->admin)
34 
35 $error=0;
36 
37 
38 /*
39  * View
40  */
41 
42 llxHeader();
43 
44 print load_fiche_titre($langs->trans("FileCheckDolibarr"),'','title_setup');
45 
46 print $langs->trans("FileCheckDesc").'<br><br>';
47 
48 // Version
49 print '<div class="div-table-responsive-no-min">';
50 print '<table class="noborder" width="100%">';
51 print '<tr class="liste_titre"><td>'.$langs->trans("Version").'</td><td>'.$langs->trans("Value").'</td></tr>'."\n";
52 print '<tr class="oddeven"><td width="300">'.$langs->trans("VersionLastInstall").'</td><td>'.$conf->global->MAIN_VERSION_LAST_INSTALL.'</td></tr>'."\n";
53 print '<tr class="oddeven"><td width="300">'.$langs->trans("VersionLastUpgrade").'</td><td>'.$conf->global->MAIN_VERSION_LAST_UPGRADE.'</td></tr>'."\n";
54 print '<tr class="oddeven"><td width="300">'.$langs->trans("VersionProgram").'</td><td>'.DOL_VERSION;
55 // If current version differs from last upgrade
56 if (empty($conf->global->MAIN_VERSION_LAST_UPGRADE)) {
57  // Compare version with last install database version (upgrades never occured)
58  if (DOL_VERSION != $conf->global->MAIN_VERSION_LAST_INSTALL)
59  print ' '.img_warning($langs->trans("RunningUpdateProcessMayBeRequired",DOL_VERSION,$conf->global->MAIN_VERSION_LAST_INSTALL));
60 } else {
61  // Compare version with last upgrade database version
62  if (DOL_VERSION != $conf->global->MAIN_VERSION_LAST_UPGRADE)
63  print ' '.img_warning($langs->trans("RunningUpdateProcessMayBeRequired",DOL_VERSION,$conf->global->MAIN_VERSION_LAST_UPGRADE));
64 }
65 print '</td></tr>'."\n";
66 print '</table>';
67 print '</div>';
68 print '<br>';
69 
70 
71 // Modified or missing files
72 $file_list = array('missing' => array(), 'updated' => array());
73 
74 // Local file to compare to
75 $xmlshortfile = GETPOST('xmlshortfile')?GETPOST('xmlshortfile'):'/install/filelist-'.DOL_VERSION.'.xml';
76 $xmlfile = DOL_DOCUMENT_ROOT.$xmlshortfile;
77 // Remote file to compare to
78 $xmlremote = GETPOST('xmlremote');
79 if (empty($xmlremote) && ! empty($conf->global->MAIN_FILECHECK_URL)) $xmlremote = $conf->global->MAIN_FILECHECK_URL;
80 $param='MAIN_FILECHECK_URL_'.DOL_VERSION;
81 if (empty($xmlremote) && ! empty($conf->global->$param)) $xmlremote = $conf->global->$param;
82 if (empty($xmlremote)) $xmlremote = 'https://www.dolibarr.org/files/stable/signatures/filelist-'.DOL_VERSION.'.xml';
83 
84 
85 // Test if remote test is ok
86 $enableremotecheck = True;
87 if (preg_match('/beta|alpha|rc/i', DOL_VERSION) || ! empty($conf->global->MAIN_ALLOW_INTEGRITY_CHECK_ON_UNSTABLE)) $enableremotecheck=False;
88 $enableremotecheck = true;
89 
90 print '<form name="check" action="'.$_SERVER["PHP_SELF"].'">';
91 print $langs->trans("MakeIntegrityAnalysisFrom").':<br>';
92 print '<!-- for a local check target=local&xmlshortfile=... -->'."\n";
93 if (dol_is_file($xmlfile))
94 {
95  print '<input type="radio" name="target" value="local"'.((! GETPOST('target') || GETPOST('target') == 'local') ? 'checked="checked"':'').'"> '.$langs->trans("LocalSignature").' = ';
96  print '<input name="xmlshortfile" class="flat minwidth400" value="'.dol_escape_htmltag($xmlshortfile).'">';
97  print '<br>';
98 }
99 else
100 {
101  print '<input type="radio" name="target" value="local"> '.$langs->trans("LocalSignature").' = ';
102  print '<input name="xmlshortfile" class="flat minwidth400" value="'.dol_escape_htmltag($xmlshortfile).'">';
103  print ' <span class="warning">('.$langs->trans("AvailableOnlyOnPackagedVersions").')</span>';
104  print '<br>';
105 }
106 print '<!-- for a remote target=remote&xmlremote=... -->'."\n";
107 if ($enableremotecheck)
108 {
109  print '<input type="radio" name="target" value="remote"'.(GETPOST('target') == 'remote' ? 'checked="checked"':'').'> '.$langs->trans("RemoteSignature").' = ';
110  print '<input name="xmlremote" class="flat minwidth400" value="'.dol_escape_htmltag($xmlremote).'"><br>';
111 }
112 else
113 {
114  print '<input type="radio" name="target" value="remote" disabled="disabled"> '.$langs->trans("RemoteSignature").' = '.$xmlremote;
115  if (! GETPOST('xmlremote')) print ' <span class="warning">('.$langs->trans("FeatureAvailableOnlyOnStable").')</span>';
116  print '<br>';
117 }
118 print '<br><div class="center"><input type="submit" name="check" class="button" value="'.$langs->trans("Check").'"></div>';
119 print '</form>';
120 print '<br>';
121 print '<br>';
122 
123 if (GETPOST('target') == 'local')
124 {
125  if (dol_is_file($xmlfile))
126  {
127  $xml = simplexml_load_file($xmlfile);
128  }
129  else
130  {
131  print $langs->trans('XmlNotFound') . ': ' . $xmlfile;
132  $error++;
133  }
134 }
135 if (GETPOST('target') == 'remote')
136 {
137  $xmlarray = getURLContent($xmlremote);
138 
139  // Return array('content'=>response,'curl_error_no'=>errno,'curl_error_msg'=>errmsg...)
140  if (! $xmlarray['curl_error_no'] && $xmlarray['http_code'] != '404')
141  {
142  $xmlfile = $xmlarray['content'];
143  //print "eee".$xmlfile."eee";
144  $xml = simplexml_load_string($xmlfile);
145  }
146  else
147  {
148  $errormsg=$langs->trans('XmlNotFound') . ': ' . $xmlremote.' - '.$xmlarray['http_code'].' '.$xmlarray['curl_error_no'].' '.$xmlarray['curl_error_msg'];
149  setEventMessages($errormsg, null, 'errors');
150  $error++;
151  }
152 }
153 
154 
155 if (! $error && $xml)
156 {
157  $checksumconcat = array();
158  $file_list = array();
159  $out = '';
160 
161  // Forced constants
162  if (is_object($xml->dolibarr_constants[0]))
163  {
164  $out.=load_fiche_titre($langs->trans("ForcedConstants"));
165 
166  $out.='<div class="div-table-responsive-no-min">';
167  $out.='<table class="noborder">';
168  $out.='<tr class="liste_titre">';
169  $out.='<td>#</td>';
170  $out.='<td>' . $langs->trans("Constant") . '</td>';
171  $out.='<td align="center">' . $langs->trans("ExpectedValue") . '</td>';
172  $out.='<td align="center">' . $langs->trans("Value") . '</td>';
173  $out.='</tr>'."\n";
174 
175  $i = 0;
176  foreach ($xml->dolibarr_constants[0]->constant as $constant) // $constant is a simpleXMLElement
177  {
178  $constname=$constant['name'];
179  $constvalue=(string) $constant;
180  $constvalue = (empty($constvalue)?'0':$constvalue);
181  // Value found
182  $value='';
183  if ($constname && $conf->global->$constname != '') $value=$conf->global->$constname;
184  $valueforchecksum=(empty($value)?'0':$value);
185 
186  $checksumconcat[]=$valueforchecksum;
187 
188  $i++;
189  $out.='<tr class="oddeven">';
190  $out.='<td>'.$i.'</td>' . "\n";
191  $out.='<td>'.$constname.'</td>' . "\n";
192  $out.='<td align="center">'.$constvalue.'</td>' . "\n";
193  $out.='<td align="center">'.$valueforchecksum.'</td>' . "\n";
194  $out.="</tr>\n";
195  }
196 
197  if ($i==0)
198  {
199  $out.='<tr class="oddeven"><td colspan="4" class="opacitymedium">'.$langs->trans("None").'</td></tr>';
200  }
201  $out.='</table>';
202  $out.='</div>';
203 
204  $out.='<br>';
205  }
206 
207  // Scan htdocs
208  if (is_object($xml->dolibarr_htdocs_dir[0]))
209  {
210  //var_dump($xml->dolibarr_htdocs_dir[0]['includecustom']);exit;
211  $includecustom=(empty($xml->dolibarr_htdocs_dir[0]['includecustom'])?0:$xml->dolibarr_htdocs_dir[0]['includecustom']);
212 
213  // Defined qualified files (must be same than into generate_filelist_xml.php)
214  $regextoinclude='\.(php|css|html|js|json|tpl|jpg|png|gif|sql|lang)$';
215  $regextoexclude='('.($includecustom?'':'custom|').'documents|conf|install|public\/test|Shared\/PCLZip|nusoap\/lib\/Mail|php\/example|php\/test|geoip\/sample.*\.php|ckeditor\/samples|ckeditor\/adapters)$'; // Exclude dirs
216  $scanfiles = dol_dir_list(DOL_DOCUMENT_ROOT, 'files', 1, $regextoinclude, $regextoexclude);
217 
218  // Fill file_list with files in signature, new files, modified files
219  $ret = getFilesUpdated($file_list, $xml->dolibarr_htdocs_dir[0], '', DOL_DOCUMENT_ROOT, $checksumconcat, $scanfiles); // Fill array $file_list
220  // Complete with list of new files
221  foreach ($scanfiles as $keyfile => $valfile)
222  {
223  $tmprelativefilename=preg_replace('/^'.preg_quote(DOL_DOCUMENT_ROOT,'/').'/','', $valfile['fullname']);
224  if (! in_array($tmprelativefilename, $file_list['insignature']))
225  {
226  $md5newfile=@md5_file($valfile['fullname']); // Can fails if we don't have permission to open/read file
227  $file_list['added'][]=array('filename'=>$tmprelativefilename, 'md5'=>$md5newfile);
228  }
229  }
230 
231  // Files missings
232  $out.=load_fiche_titre($langs->trans("FilesMissing"));
233 
234  $out.='<div class="div-table-responsive-no-min">';
235  $out.='<table class="noborder">';
236  $out.='<tr class="liste_titre">';
237  $out.='<td>#</td>';
238  $out.='<td>' . $langs->trans("Filename") . '</td>';
239  $out.='<td align="center">' . $langs->trans("ExpectedChecksum") . '</td>';
240  $out.='</tr>'."\n";
241  $tmpfilelist = dol_sort_array($file_list['missing'], 'filename');
242  if (is_array($tmpfilelist) && count($tmpfilelist))
243  {
244  $i = 0;
245  foreach ($tmpfilelist as $file)
246  {
247  $i++;
248  $out.='<tr class="oddeven">';
249  $out.='<td>'.$i.'</td>' . "\n";
250  $out.='<td>'.$file['filename'].'</td>' . "\n";
251  $out.='<td align="center">'.$file['expectedmd5'].'</td>' . "\n";
252  $out.="</tr>\n";
253  }
254  }
255  else
256  {
257  $out.='<tr class="oddeven"><td colspan="3" class="opacitymedium">'.$langs->trans("None").'</td></tr>';
258  }
259  $out.='</table>';
260  $out.='</div>';
261 
262  $out.='<br>';
263 
264  // Files modified
265  $out.=load_fiche_titre($langs->trans("FilesModified"));
266 
267  $totalsize=0;
268  $out.='<div class="div-table-responsive-no-min">';
269  $out.='<table class="noborder">';
270  $out.='<tr class="liste_titre">';
271  $out.='<td>#</td>';
272  $out.='<td>' . $langs->trans("Filename") . '</td>';
273  $out.='<td align="center">' . $langs->trans("ExpectedChecksum") . '</td>';
274  $out.='<td align="center">' . $langs->trans("CurrentChecksum") . '</td>';
275  $out.='<td align="right">' . $langs->trans("Size") . '</td>';
276  $out.='<td align="right">' . $langs->trans("DateModification") . '</td>';
277  $out.='</tr>'."\n";
278  $tmpfilelist2 = dol_sort_array($file_list['updated'], 'filename');
279  if (is_array($tmpfilelist2) && count($tmpfilelist2))
280  {
281  $i = 0;
282  foreach ($tmpfilelist2 as $file)
283  {
284  $i++;
285  $out.='<tr class="oddeven">';
286  $out.='<td>'.$i.'</td>' . "\n";
287  $out.='<td>'.$file['filename'].'</td>' . "\n";
288  $out.='<td align="center">'.$file['expectedmd5'].'</td>' . "\n";
289  $out.='<td align="center">'.$file['md5'].'</td>' . "\n";
290  $size = dol_filesize(DOL_DOCUMENT_ROOT.'/'.$file['filename']);
291  $totalsize += $size;
292  $out.='<td align="right">'.dol_print_size($size).'</td>' . "\n";
293  $out.='<td align="right">'.dol_print_date(dol_filemtime(DOL_DOCUMENT_ROOT.'/'.$file['filename']),'dayhour').'</td>' . "\n";
294  $out.="</tr>\n";
295  }
296  $out.='<tr class="liste_total">';
297  $out.='<td></td>' . "\n";
298  $out.='<td>'.$langs->trans("Total").'</td>' . "\n";
299  $out.='<td align="center"></td>' . "\n";
300  $out.='<td align="center"></td>' . "\n";
301  $out.='<td align="right">'.dol_print_size($totalsize).'</td>' . "\n";
302  $out.='<td align="right"></td>' . "\n";
303  $out.="</tr>\n";
304  }
305  else
306  {
307  $out.='<tr class="oddeven"><td colspan="5" class="opacitymedium">'.$langs->trans("None").'</td></tr>';
308  }
309  $out.='</table>';
310  $out.='</div>';
311 
312  $out.='<br>';
313 
314  // Files added
315  $out.=load_fiche_titre($langs->trans("FilesAdded"));
316 
317  $totalsize = 0;
318  $out.='<div class="div-table-responsive-no-min">';
319  $out.='<table class="noborder">';
320  $out.='<tr class="liste_titre">';
321  $out.='<td>#</td>';
322  $out.='<td>' . $langs->trans("Filename") . '</td>';
323  $out.='<td align="center">' . $langs->trans("ExpectedChecksum") . '</td>';
324  $out.='<td align="center">' . $langs->trans("CurrentChecksum") . '</td>';
325  $out.='<td align="right">' . $langs->trans("Size") . '</td>';
326  $out.='<td align="right">' . $langs->trans("DateModification") . '</td>';
327  $out.='</tr>'."\n";
328  $tmpfilelist3 = dol_sort_array($file_list['added'], 'filename');
329  if (is_array($tmpfilelist3) && count($tmpfilelist3))
330  {
331  $i = 0;
332  foreach ($tmpfilelist3 as $file)
333  {
334  $i++;
335  $out.='<tr class="oddeven">';
336  $out.='<td>'.$i.'</td>' . "\n";
337  $out.='<td>'.$file['filename'].'</td>' . "\n";
338  $out.='<td align="center">'.$file['expectedmd5'].'</td>' . "\n";
339  $out.='<td align="center">'.$file['md5'].'</td>' . "\n";
340  $size = dol_filesize(DOL_DOCUMENT_ROOT.'/'.$file['filename']);
341  $totalsize += $size;
342  $out.='<td align="right">'.dol_print_size($size).'</td>' . "\n";
343  $out.='<td align="right">'.dol_print_date(dol_filemtime(DOL_DOCUMENT_ROOT.'/'.$file['filename']),'dayhour').'</td>' . "\n";
344  $out.="</tr>\n";
345  }
346  $out.='<tr class="liste_total">';
347  $out.='<td></td>' . "\n";
348  $out.='<td>'.$langs->trans("Total").'</td>' . "\n";
349  $out.='<td align="center"></td>' . "\n";
350  $out.='<td align="center"></td>' . "\n";
351  $out.='<td align="right">'.dol_print_size($totalsize).'</td>' . "\n";
352  $out.='<td align="right"></td>' . "\n";
353  $out.="</tr>\n";
354  }
355  else
356  {
357  $out.='<tr class="oddeven"><td colspan="5" class="opacitymedium">'.$langs->trans("None").'</td></tr>';
358  }
359  $out.='</table>';
360  $out.='</div>';
361 
362 
363  // Show warning
364  if (empty($tmpfilelist) && empty($tmpfilelist2) && empty($tmpfilelist3))
365  {
366  setEventMessage($langs->trans("FileIntegrityIsStrictlyConformedWithReference"));
367  }
368  else
369  {
370  setEventMessage($langs->trans("FileIntegritySomeFilesWereRemovedOrModified"), 'warnings');
371  }
372  }
373  else
374  {
375  print 'Error: Failed to found dolibarr_htdocs_dir into XML file '.$xmlfile;
376  $error++;
377  }
378 
379 
380  // Scan scripts
381  /*
382  if (is_object($xml->dolibarr_script_dir[0]))
383  {
384  $file_list = array();
385  $ret = getFilesUpdated($file_list, $xml->dolibarr_htdocs_dir[0], '', ???, $checksumconcat); // Fill array $file_list
386  }*/
387 
388 
389  asort($checksumconcat); // Sort list of checksum
390  //var_dump($checksumconcat);
391  $checksumget = md5(join(',',$checksumconcat));
392  $checksumtoget = trim((string) $xml->dolibarr_htdocs_dir_checksum);
393 
394  /*var_dump(count($file_list['added']));
395  var_dump($checksumget);
396  var_dump($checksumtoget);
397  var_dump($checksumget == $checksumtoget);*/
398 
399  $outexpectedchecksum = ($checksumtoget ? $checksumtoget : $langs->trans("Unknown"));
400  if ($checksumget == $checksumtoget)
401  {
402  if (count($file_list['added']))
403  {
404  $resultcode = 'warning';
405  $resultcomment='FileIntegrityIsOkButFilesWereAdded';
406  $outcurrentchecksum = $checksumget.' - <span class="'.$resultcode.'">'.$langs->trans("FileIntegrityIsOkButFilesWereAdded").'</span>';
407  }
408  else
409  {
410  $resultcode = 'ok';
411  $resultcomment='Success';
412  $outcurrentchecksum = '<span class="'.$resultcode.'">'.$checksumget.'</span>';
413  }
414  }
415  else
416  {
417  $resultcode = 'error';
418  $resultcomment='Error';
419  $outcurrentchecksum = '<span class="'.$resultcode.'">'.$checksumget.'</span>';
420  }
421 
422  print_fiche_titre($langs->trans("GlobalChecksum")).'<br>';
423  print $langs->trans("ExpectedChecksum").' = '. $outexpectedchecksum .'<br>';
424  print $langs->trans("CurrentChecksum").' = '. $outcurrentchecksum;
425 
426  print '<br>';
427  print '<br>';
428 
429  // Output detail
430  print $out;
431 }
432 
433 
434 
435 
436 llxFooter();
437 
438 $db->close();
439 
440 exit($error);
441 
llxFooter()
Empty footer.
Definition: wrapper.php:58
getFilesUpdated(&$file_list, SimpleXMLElement $dir, $path= '', $pathref= '', &$checksumconcat=array())
Function to get list of updated or modified files.
Definition: files.lib.php:2770
setEventMessages($mesg, $mesgs, $style='mesgs')
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 second index function, which produces ascending (default) or descending output...
dol_filesize($pathoffile)
Return size of a file.
Definition: files.lib.php:516
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="")
Scan a directory and return a list of files/directories.
Definition: files.lib.php:58
GETPOST($paramname, $check='none', $method=0, $filter=NULL, $options=NULL, $noreplace=0)
Return value of a param into GET or POST supervariable.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0)
Show a message to say access is forbidden and stop program Calling this function terminate execution ...
getURLContent($url, $postorget='GET', $param='', $followlocation=1, $addheaders=array())
Function get content from an URL (use proxy if proxy defined)
Definition: geturl.lib.php:34
load_fiche_titre($titre, $morehtmlright='', $picto='title_generic.png', $pictoisfullpath=0, $id=0, $morecssontable='', $morehtmlcenter='')
Load a title with picto.
llxHeader()
Empty header.
Definition: wrapper.php:46
dol_is_file($pathoffile)
Return if path is a file.
Definition: files.lib.php:427
print_fiche_titre($title, $mesg='', $picto='title_generic.png', $pictoisfullpath=0, $id='')
Show a title with picto.
print
Draft customers invoices.
Definition: index.php:91
setEventMessage($mesgs, $style='mesgs')
Set event message in dol_events session object.
dol_filemtime($pathoffile)
Return time of a file.
Definition: files.lib.php:528