dolibarr  18.0.0-alpha
files.lib.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2008-2012 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2012-2021 Regis Houssin <regis.houssin@inodbox.com>
4  * Copyright (C) 2012-2016 Juanjo Menent <jmenent@2byte.es>
5  * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
6  * Copyright (C) 2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
7  * Copyright (C) 2019 Frédéric France <frederic.france@netlogic.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  * or see https://www.gnu.org/
22  */
23 
36 function dol_basename($pathfile)
37 {
38  return preg_replace('/^.*\/([^\/]+)$/', '$1', rtrim($pathfile, '/'));
39 }
40 
61 function dol_dir_list($path, $types = "all", $recursive = 0, $filter = "", $excludefilter = null, $sortcriteria = "name", $sortorder = SORT_ASC, $mode = 0, $nohook = 0, $relativename = "", $donotfollowsymlinks = 0, $nbsecondsold = 0)
62 {
63  global $db, $hookmanager;
64  global $object;
65 
66  if ($recursive <= 1) { // Avoid too verbose log
67  dol_syslog("files.lib.php::dol_dir_list path=".$path." types=".$types." recursive=".$recursive." filter=".$filter." excludefilter=".json_encode($excludefilter));
68  //print 'xxx'."files.lib.php::dol_dir_list path=".$path." types=".$types." recursive=".$recursive." filter=".$filter." excludefilter=".json_encode($excludefilter);
69  }
70 
71  $loaddate = ($mode == 1 || $mode == 2 || $nbsecondsold) ? true : false;
72  $loadsize = ($mode == 1 || $mode == 3) ?true : false;
73  $loadperm = ($mode == 1 || $mode == 4) ?true : false;
74 
75  // Clean parameters
76  $path = preg_replace('/([\\/]+)$/i', '', $path);
77  $newpath = dol_osencode($path);
78  $now = dol_now();
79 
80  $reshook = 0;
81  $file_list = array();
82 
83  if (is_object($hookmanager) && !$nohook) {
84  $hookmanager->resArray = array();
85 
86  $hookmanager->initHooks(array('fileslib'));
87 
88  $parameters = array(
89  'path' => $newpath,
90  'types'=> $types,
91  'recursive' => $recursive,
92  'filter' => $filter,
93  'excludefilter' => $excludefilter,
94  'sortcriteria' => $sortcriteria,
95  'sortorder' => $sortorder,
96  'loaddate' => $loaddate,
97  'loadsize' => $loadsize,
98  'mode' => $mode
99  );
100  $reshook = $hookmanager->executeHooks('getDirList', $parameters, $object);
101  }
102 
103  // $hookmanager->resArray may contain array stacked by other modules
104  if (empty($reshook)) {
105  if (!is_dir($newpath)) {
106  return array();
107  }
108 
109  if ($dir = opendir($newpath)) {
110  $filedate = '';
111  $filesize = '';
112  $fileperm = '';
113  while (false !== ($file = readdir($dir))) { // $file is always a basename (into directory $newpath)
114  if (!utf8_check($file)) {
115  $file = utf8_encode($file); // To be sure data is stored in utf8 in memory
116  }
117  $fullpathfile = ($newpath ? $newpath.'/' : '').$file;
118 
119  $qualified = 1;
120 
121  // Define excludefilterarray
122  $excludefilterarray = array('^\.');
123  if (is_array($excludefilter)) {
124  $excludefilterarray = array_merge($excludefilterarray, $excludefilter);
125  } elseif ($excludefilter) {
126  $excludefilterarray[] = $excludefilter;
127  }
128  // Check if file is qualified
129  foreach ($excludefilterarray as $filt) {
130  if (preg_match('/'.$filt.'/i', $file) || preg_match('/'.$filt.'/i', $fullpathfile)) {
131  $qualified = 0;
132  break;
133  }
134  }
135  //print $fullpathfile.' '.$file.' '.$qualified.'<br>';
136 
137  if ($qualified) {
138  $isdir = is_dir(dol_osencode($path."/".$file));
139  // Check whether this is a file or directory and whether we're interested in that type
140  if ($isdir && (($types == "directories") || ($types == "all") || $recursive > 0)) {
141  // Add entry into file_list array
142  if (($types == "directories") || ($types == "all")) {
143  if ($loaddate || $sortcriteria == 'date') {
144  $filedate = dol_filemtime($path."/".$file);
145  }
146  if ($loadsize || $sortcriteria == 'size') {
147  $filesize = dol_filesize($path."/".$file);
148  }
149  if ($loadperm || $sortcriteria == 'perm') {
150  $fileperm = dol_fileperm($path."/".$file);
151  }
152 
153  if (!$filter || preg_match('/'.$filter.'/i', $file)) { // We do not search key $filter into all $path, only into $file part
154  $reg = array();
155  preg_match('/([^\/]+)\/[^\/]+$/', $path.'/'.$file, $reg);
156  $level1name = (isset($reg[1]) ? $reg[1] : '');
157  $file_list[] = array(
158  "name" => $file,
159  "path" => $path,
160  "level1name" => $level1name,
161  "relativename" => ($relativename ? $relativename.'/' : '').$file,
162  "fullname" => $path.'/'.$file,
163  "date" => $filedate,
164  "size" => $filesize,
165  "perm" => $fileperm,
166  "type" => 'dir'
167  );
168  }
169  }
170 
171  // if we're in a directory and we want recursive behavior, call this function again
172  if ($recursive > 0) {
173  if (empty($donotfollowsymlinks) || !is_link($path."/".$file)) {
174  //var_dump('eee '. $path."/".$file. ' '.is_dir($path."/".$file).' '.is_link($path."/".$file));
175  $file_list = array_merge($file_list, dol_dir_list($path."/".$file, $types, $recursive + 1, $filter, $excludefilter, $sortcriteria, $sortorder, $mode, $nohook, ($relativename != '' ? $relativename.'/' : '').$file, $donotfollowsymlinks, $nbsecondsold));
176  }
177  }
178  } elseif (!$isdir && (($types == "files") || ($types == "all"))) {
179  // Add file into file_list array
180  if ($loaddate || $sortcriteria == 'date') {
181  $filedate = dol_filemtime($path."/".$file);
182  }
183  if ($loadsize || $sortcriteria == 'size') {
184  $filesize = dol_filesize($path."/".$file);
185  }
186 
187  if (!$filter || preg_match('/'.$filter.'/i', $file)) { // We do not search key $filter into $path, only into $file
188  if (empty($nbsecondsold) || $filedate <= ($now - $nbsecondsold)) {
189  preg_match('/([^\/]+)\/[^\/]+$/', $path.'/'.$file, $reg);
190  $level1name = (isset($reg[1]) ? $reg[1] : '');
191  $file_list[] = array(
192  "name" => $file,
193  "path" => $path,
194  "level1name" => $level1name,
195  "relativename" => ($relativename ? $relativename.'/' : '').$file,
196  "fullname" => $path.'/'.$file,
197  "date" => $filedate,
198  "size" => $filesize,
199  "type" => 'file'
200  );
201  }
202  }
203  }
204  }
205  }
206  closedir($dir);
207 
208  // Obtain a list of columns
209  if (!empty($sortcriteria) && $sortorder) {
210  $file_list = dol_sort_array($file_list, $sortcriteria, ($sortorder == SORT_ASC ? 'asc' : 'desc'));
211  }
212  }
213  }
214 
215  if (is_object($hookmanager) && is_array($hookmanager->resArray)) {
216  $file_list = array_merge($file_list, $hookmanager->resArray);
217  }
218 
219  return $file_list;
220 }
221 
222 
236 function dol_dir_list_in_database($path, $filter = "", $excludefilter = null, $sortcriteria = "name", $sortorder = SORT_ASC, $mode = 0)
237 {
238  global $conf, $db;
239 
240  $sql = " SELECT rowid, label, entity, filename, filepath, fullpath_orig, keywords, cover, gen_or_uploaded, extraparams,";
241  $sql .= " date_c, tms as date_m, fk_user_c, fk_user_m, acl, position, share";
242  if ($mode) {
243  $sql .= ", description";
244  }
245  $sql .= " FROM ".MAIN_DB_PREFIX."ecm_files";
246  $sql .= " WHERE entity = ".$conf->entity;
247  if (preg_match('/%$/', $path)) {
248  $sql .= " AND filepath LIKE '".$db->escape($path)."'";
249  } else {
250  $sql .= " AND filepath = '".$db->escape($path)."'";
251  }
252 
253  $resql = $db->query($sql);
254  if ($resql) {
255  $file_list = array();
256  $num = $db->num_rows($resql);
257  $i = 0;
258  while ($i < $num) {
259  $obj = $db->fetch_object($resql);
260  if ($obj) {
261  $reg = array();
262  preg_match('/([^\/]+)\/[^\/]+$/', DOL_DATA_ROOT.'/'.$obj->filepath.'/'.$obj->filename, $reg);
263  $level1name = (isset($reg[1]) ? $reg[1] : '');
264  $file_list[] = array(
265  "rowid" => $obj->rowid,
266  "label" => $obj->label, // md5
267  "name" => $obj->filename,
268  "path" => DOL_DATA_ROOT.'/'.$obj->filepath,
269  "level1name" => $level1name,
270  "fullname" => DOL_DATA_ROOT.'/'.$obj->filepath.'/'.$obj->filename,
271  "fullpath_orig" => $obj->fullpath_orig,
272  "date_c" => $db->jdate($obj->date_c),
273  "date_m" => $db->jdate($obj->date_m),
274  "type" => 'file',
275  "keywords" => $obj->keywords,
276  "cover" => $obj->cover,
277  "position" => (int) $obj->position,
278  "acl" => $obj->acl,
279  "share" => $obj->share,
280  "description" => ($mode ? $obj->description : '')
281  );
282  }
283  $i++;
284  }
285 
286  // Obtain a list of columns
287  if (!empty($sortcriteria)) {
288  $myarray = array();
289  foreach ($file_list as $key => $row) {
290  $myarray[$key] = (isset($row[$sortcriteria]) ? $row[$sortcriteria] : '');
291  }
292  // Sort the data
293  if ($sortorder) {
294  array_multisort($myarray, $sortorder, $file_list);
295  }
296  }
297 
298  return $file_list;
299  } else {
300  dol_print_error($db);
301  return array();
302  }
303 }
304 
305 
314 function completeFileArrayWithDatabaseInfo(&$filearray, $relativedir)
315 {
316  global $conf, $db, $user;
317 
318  $filearrayindatabase = dol_dir_list_in_database($relativedir, '', null, 'name', SORT_ASC);
319 
320  // TODO Remove this when PRODUCT_USE_OLD_PATH_FOR_PHOTO will be removed
321  global $modulepart;
322  if ($modulepart == 'produit' && getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
323  global $object;
324  if (!empty($object->id)) {
325  if (isModEnabled("product")) {
326  $upload_dirold = $conf->product->multidir_output[$object->entity].'/'.substr(substr("000".$object->id, -2), 1, 1).'/'.substr(substr("000".$object->id, -2), 0, 1).'/'.$object->id."/photos";
327  } else {
328  $upload_dirold = $conf->service->multidir_output[$object->entity].'/'.substr(substr("000".$object->id, -2), 1, 1).'/'.substr(substr("000".$object->id, -2), 0, 1).'/'.$object->id."/photos";
329  }
330 
331  $relativedirold = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $upload_dirold);
332  $relativedirold = preg_replace('/^[\\/]/', '', $relativedirold);
333 
334  $filearrayindatabase = array_merge($filearrayindatabase, dol_dir_list_in_database($relativedirold, '', null, 'name', SORT_ASC));
335  }
336  }
337 
338  //var_dump($relativedir);
339  //var_dump($filearray);
340  //var_dump($filearrayindatabase);
341 
342  // Complete filearray with properties found into $filearrayindatabase
343  foreach ($filearray as $key => $val) {
344  $tmpfilename = preg_replace('/\.noexe$/', '', $filearray[$key]['name']);
345  $found = 0;
346  // Search if it exists into $filearrayindatabase
347  foreach ($filearrayindatabase as $key2 => $val2) {
348  if (($filearrayindatabase[$key2]['path'] == $filearray[$key]['path']) && ($filearrayindatabase[$key2]['name'] == $tmpfilename)) {
349  $filearray[$key]['position_name'] = ($filearrayindatabase[$key2]['position'] ? $filearrayindatabase[$key2]['position'] : '0').'_'.$filearrayindatabase[$key2]['name'];
350  $filearray[$key]['position'] = $filearrayindatabase[$key2]['position'];
351  $filearray[$key]['cover'] = $filearrayindatabase[$key2]['cover'];
352  $filearray[$key]['keywords'] = $filearrayindatabase[$key2]['keywords'];
353  $filearray[$key]['acl'] = $filearrayindatabase[$key2]['acl'];
354  $filearray[$key]['rowid'] = $filearrayindatabase[$key2]['rowid'];
355  $filearray[$key]['label'] = $filearrayindatabase[$key2]['label'];
356  $filearray[$key]['share'] = $filearrayindatabase[$key2]['share'];
357  $found = 1;
358  break;
359  }
360  }
361 
362  if (!$found) { // This happen in transition toward version 6, or if files were added manually into os dir.
363  $filearray[$key]['position'] = '999999'; // File not indexed are at end. So if we add a file, it will not replace an existing position
364  $filearray[$key]['cover'] = 0;
365  $filearray[$key]['acl'] = '';
366 
367  $rel_filename = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $filearray[$key]['fullname']);
368 
369  if (!preg_match('/([\\/]temp[\\/]|[\\/]thumbs|\.meta$)/', $rel_filename)) { // If not a tmp file
370  dol_syslog("list_of_documents We found a file called '".$filearray[$key]['name']."' not indexed into database. We add it");
371  include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
372  $ecmfile = new EcmFiles($db);
373 
374  // Add entry into database
375  $filename = basename($rel_filename);
376  $rel_dir = dirname($rel_filename);
377  $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
378  $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
379 
380  $ecmfile->filepath = $rel_dir;
381  $ecmfile->filename = $filename;
382  $ecmfile->label = md5_file(dol_osencode($filearray[$key]['fullname'])); // $destfile is a full path to file
383  $ecmfile->fullpath_orig = $filearray[$key]['fullname'];
384  $ecmfile->gen_or_uploaded = 'unknown';
385  $ecmfile->description = ''; // indexed content
386  $ecmfile->keywords = ''; // keyword content
387  $result = $ecmfile->create($user);
388  if ($result < 0) {
389  setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
390  } else {
391  $filearray[$key]['rowid'] = $result;
392  }
393  } else {
394  $filearray[$key]['rowid'] = 0; // Should not happened
395  }
396  }
397  }
398  //var_dump($filearray); var_dump($relativedir.' - tmpfilename='.$tmpfilename.' - found='.$found);
399 }
400 
401 
409 function dol_compare_file($a, $b)
410 {
411  global $sortorder;
412  global $sortfield;
413 
414  $sortorder = strtoupper($sortorder);
415 
416  if ($sortorder == 'ASC') {
417  $retup = -1;
418  $retdown = 1;
419  } else {
420  $retup = 1;
421  $retdown = -1;
422  }
423 
424  if ($sortfield == 'name') {
425  if ($a->name == $b->name) {
426  return 0;
427  }
428  return ($a->name < $b->name) ? $retup : $retdown;
429  }
430  if ($sortfield == 'date') {
431  if ($a->date == $b->date) {
432  return 0;
433  }
434  return ($a->date < $b->date) ? $retup : $retdown;
435  }
436  if ($sortfield == 'size') {
437  if ($a->size == $b->size) {
438  return 0;
439  }
440  return ($a->size < $b->size) ? $retup : $retdown;
441  }
442 }
443 
444 
451 function dol_is_dir($folder)
452 {
453  $newfolder = dol_osencode($folder);
454  if (is_dir($newfolder)) {
455  return true;
456  } else {
457  return false;
458  }
459 }
460 
467 function dol_is_dir_empty($dir)
468 {
469  if (!is_readable($dir)) {
470  return false;
471  }
472  return (count(scandir($dir)) == 2);
473 }
474 
481 function dol_is_file($pathoffile)
482 {
483  $newpathoffile = dol_osencode($pathoffile);
484  return is_file($newpathoffile);
485 }
486 
493 function dol_is_link($pathoffile)
494 {
495  $newpathoffile = dol_osencode($pathoffile);
496  return is_link($newpathoffile);
497 }
498 
505 function dol_is_url($url)
506 {
507  $tmpprot = array('file', 'http', 'https', 'ftp', 'zlib', 'data', 'ssh', 'ssh2', 'ogg', 'expect');
508  foreach ($tmpprot as $prot) {
509  if (preg_match('/^'.$prot.':/i', $url)) {
510  return true;
511  }
512  }
513  return false;
514 }
515 
522 function dol_dir_is_emtpy($folder)
523 {
524  $newfolder = dol_osencode($folder);
525  if (is_dir($newfolder)) {
526  $handle = opendir($newfolder);
527  $folder_content = '';
528  while ((gettype($name = readdir($handle)) != "boolean")) {
529  $name_array[] = $name;
530  }
531  foreach ($name_array as $temp) {
532  $folder_content .= $temp;
533  }
534 
535  closedir($handle);
536 
537  if ($folder_content == "...") {
538  return true;
539  } else {
540  return false;
541  }
542  } else {
543  return true; // Dir does not exists
544  }
545 }
546 
554 function dol_count_nb_of_line($file)
555 {
556  $nb = 0;
557 
558  $newfile = dol_osencode($file);
559  //print 'x'.$file;
560  $fp = fopen($newfile, 'r');
561  if ($fp) {
562  while (!feof($fp)) {
563  $line = fgets($fp);
564  // We increase count only if read was success. We need test because feof return true only after fgets so we do n+1 fgets for a file with n lines.
565  if (!$line === false) {
566  $nb++;
567  }
568  }
569  fclose($fp);
570  } else {
571  $nb = -1;
572  }
573 
574  return $nb;
575 }
576 
577 
585 function dol_filesize($pathoffile)
586 {
587  $newpathoffile = dol_osencode($pathoffile);
588  return filesize($newpathoffile);
589 }
590 
597 function dol_filemtime($pathoffile)
598 {
599  $newpathoffile = dol_osencode($pathoffile);
600  return @filemtime($newpathoffile); // @Is to avoid errors if files does not exists
601 }
602 
609 function dol_fileperm($pathoffile)
610 {
611  $newpathoffile = dol_osencode($pathoffile);
612  return fileperms($newpathoffile);
613 }
614 
627 function dolReplaceInFile($srcfile, $arrayreplacement, $destfile = '', $newmask = 0, $indexdatabase = 0, $arrayreplacementisregex = 0)
628 {
629  global $conf;
630 
631  dol_syslog("files.lib.php::dolReplaceInFile srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." indexdatabase=".$indexdatabase." arrayreplacementisregex=".$arrayreplacementisregex);
632 
633  if (empty($srcfile)) {
634  return -1;
635  }
636  if (empty($destfile)) {
637  $destfile = $srcfile;
638  }
639 
640  $destexists = dol_is_file($destfile);
641  if (($destfile != $srcfile) && $destexists) {
642  return 0;
643  }
644 
645  $srcexists = dol_is_file($srcfile);
646  if (!$srcexists) {
647  dol_syslog("files.lib.php::dolReplaceInFile failed to read src file", LOG_WARNING);
648  return -3;
649  }
650 
651  $tmpdestfile = $destfile.'.tmp';
652 
653  $newpathofsrcfile = dol_osencode($srcfile);
654  $newpathoftmpdestfile = dol_osencode($tmpdestfile);
655  $newpathofdestfile = dol_osencode($destfile);
656  $newdirdestfile = dirname($newpathofdestfile);
657 
658  if ($destexists && !is_writable($newpathofdestfile)) {
659  dol_syslog("files.lib.php::dolReplaceInFile failed Permission denied to overwrite target file", LOG_WARNING);
660  return -1;
661  }
662  if (!is_writable($newdirdestfile)) {
663  dol_syslog("files.lib.php::dolReplaceInFile failed Permission denied to write into target directory ".$newdirdestfile, LOG_WARNING);
664  return -2;
665  }
666 
667  dol_delete_file($tmpdestfile);
668 
669  // Create $newpathoftmpdestfile from $newpathofsrcfile
670  $content = file_get_contents($newpathofsrcfile, 'r');
671 
672  if (empty($arrayreplacementisregex)) {
673  $content = make_substitutions($content, $arrayreplacement, null);
674  } else {
675  foreach ($arrayreplacement as $key => $value) {
676  $content = preg_replace($key, $value, $content);
677  }
678  }
679 
680  file_put_contents($newpathoftmpdestfile, $content);
681  dolChmod($newpathoftmpdestfile, $newmask);
682 
683  // Rename
684  $result = dol_move($newpathoftmpdestfile, $newpathofdestfile, $newmask, (($destfile == $srcfile) ? 1 : 0), 0, $indexdatabase);
685  if (!$result) {
686  dol_syslog("files.lib.php::dolReplaceInFile failed to move tmp file to final dest", LOG_WARNING);
687  return -3;
688  }
689  if (empty($newmask) && !empty($conf->global->MAIN_UMASK)) {
690  $newmask = $conf->global->MAIN_UMASK;
691  }
692  if (empty($newmask)) { // This should no happen
693  dol_syslog("Warning: dolReplaceInFile called with empty value for newmask and no default value defined", LOG_WARNING);
694  $newmask = '0664';
695  }
696 
697  dolChmod($newpathofdestfile, $newmask);
698 
699  return 1;
700 }
701 
702 
713 function dol_copy($srcfile, $destfile, $newmask = 0, $overwriteifexists = 1)
714 {
715  global $conf;
716 
717  dol_syslog("files.lib.php::dol_copy srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." overwriteifexists=".$overwriteifexists);
718 
719  if (empty($srcfile) || empty($destfile)) {
720  return -1;
721  }
722 
723  $destexists = dol_is_file($destfile);
724  if (!$overwriteifexists && $destexists) {
725  return 0;
726  }
727 
728  $newpathofsrcfile = dol_osencode($srcfile);
729  $newpathofdestfile = dol_osencode($destfile);
730  $newdirdestfile = dirname($newpathofdestfile);
731 
732  if ($destexists && !is_writable($newpathofdestfile)) {
733  dol_syslog("files.lib.php::dol_copy failed Permission denied to overwrite target file", LOG_WARNING);
734  return -1;
735  }
736  if (!is_writable($newdirdestfile)) {
737  dol_syslog("files.lib.php::dol_copy failed Permission denied to write into target directory ".$newdirdestfile, LOG_WARNING);
738  return -2;
739  }
740  // Copy with overwriting if exists
741  $result = @copy($newpathofsrcfile, $newpathofdestfile);
742  //$result=copy($newpathofsrcfile, $newpathofdestfile); // To see errors, remove @
743  if (!$result) {
744  dol_syslog("files.lib.php::dol_copy failed to copy", LOG_WARNING);
745  return -3;
746  }
747  if (empty($newmask) && !empty($conf->global->MAIN_UMASK)) {
748  $newmask = $conf->global->MAIN_UMASK;
749  }
750  if (empty($newmask)) { // This should no happen
751  dol_syslog("Warning: dol_copy called with empty value for newmask and no default value defined", LOG_WARNING);
752  $newmask = '0664';
753  }
754 
755  dolChmod($newpathofdestfile, $newmask);
756 
757  return 1;
758 }
759 
773 function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayreplacement = null, $excludesubdir = 0, $excludefileext = null)
774 {
775  global $conf;
776 
777  $result = 0;
778 
779  dol_syslog("files.lib.php::dolCopyDir srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." overwriteifexists=".$overwriteifexists);
780 
781  if (empty($srcfile) || empty($destfile)) {
782  return -1;
783  }
784 
785  $destexists = dol_is_dir($destfile);
786  //if (! $overwriteifexists && $destexists) return 0; // The overwriteifexists is for files only, so propagated to dol_copy only.
787 
788  if (!$destexists) {
789  // We must set mask just before creating dir, becaause it can be set differently by dol_copy
790  umask(0);
791  $dirmaskdec = octdec($newmask);
792  if (empty($newmask) && !empty($conf->global->MAIN_UMASK)) {
793  $dirmaskdec = octdec($conf->global->MAIN_UMASK);
794  }
795  $dirmaskdec |= octdec('0200'); // Set w bit required to be able to create content for recursive subdirs files
796  dol_mkdir($destfile, '', decoct($dirmaskdec));
797  }
798 
799  $ossrcfile = dol_osencode($srcfile);
800  $osdestfile = dol_osencode($destfile);
801 
802  // Recursive function to copy all subdirectories and contents:
803  if (is_dir($ossrcfile)) {
804  $dir_handle = opendir($ossrcfile);
805  while ($file = readdir($dir_handle)) {
806  if ($file != "." && $file != ".." && !is_link($ossrcfile."/".$file)) {
807  if (is_dir($ossrcfile."/".$file)) {
808  if (empty($excludesubdir) || ($excludesubdir == 2 && strlen($file) == 2)) {
809  $newfile = $file;
810  // Replace destination filename with a new one
811  if (is_array($arrayreplacement)) {
812  foreach ($arrayreplacement as $key => $val) {
813  $newfile = str_replace($key, $val, $newfile);
814  }
815  }
816  //var_dump("xxx dolCopyDir $srcfile/$file, $destfile/$file, $newmask, $overwriteifexists");
817  $tmpresult = dolCopyDir($srcfile."/".$file, $destfile."/".$newfile, $newmask, $overwriteifexists, $arrayreplacement, $excludesubdir, $excludefileext);
818  }
819  } else {
820  $newfile = $file;
821 
822  if (is_array($excludefileext)) {
823  $extension = pathinfo($file, PATHINFO_EXTENSION);
824  if (in_array($extension, $excludefileext)) {
825  //print "We exclude the file ".$file." because its extension is inside list ".join(', ', $excludefileext); exit;
826  continue;
827  }
828  }
829 
830  // Replace destination filename with a new one
831  if (is_array($arrayreplacement)) {
832  foreach ($arrayreplacement as $key => $val) {
833  $newfile = str_replace($key, $val, $newfile);
834  }
835  }
836  $tmpresult = dol_copy($srcfile."/".$file, $destfile."/".$newfile, $newmask, $overwriteifexists);
837  }
838  // Set result
839  if ($result > 0 && $tmpresult >= 0) {
840  // Do nothing, so we don't set result to 0 if tmpresult is 0 and result was success in a previous pass
841  } else {
842  $result = $tmpresult;
843  }
844  if ($result < 0) {
845  break;
846  }
847  }
848  }
849  closedir($dir_handle);
850  } else {
851  // Source directory does not exists
852  $result = -2;
853  }
854 
855  return $result;
856 }
857 
858 
875 function dol_move($srcfile, $destfile, $newmask = 0, $overwriteifexists = 1, $testvirus = 0, $indexdatabase = 1)
876 {
877  global $user, $db, $conf;
878  $result = false;
879 
880  dol_syslog("files.lib.php::dol_move srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." overwritifexists=".$overwriteifexists);
881  $srcexists = dol_is_file($srcfile);
882  $destexists = dol_is_file($destfile);
883 
884  if (!$srcexists) {
885  dol_syslog("files.lib.php::dol_move srcfile does not exists. we ignore the move request.");
886  return false;
887  }
888 
889  if ($overwriteifexists || !$destexists) {
890  $newpathofsrcfile = dol_osencode($srcfile);
891  $newpathofdestfile = dol_osencode($destfile);
892 
893  // Check virus
894  $testvirusarray = array();
895  if ($testvirus) {
896  $testvirusarray = dolCheckVirus($newpathofsrcfile);
897  if (count($testvirusarray)) {
898  dol_syslog("files.lib.php::dol_move canceled because a virus was found into source file. we ignore the move request.", LOG_WARNING);
899  return false;
900  }
901  }
902 
903  global $dolibarr_main_restrict_os_commands;
904  if (!empty($dolibarr_main_restrict_os_commands)) {
905  $arrayofallowedcommand = explode(',', $dolibarr_main_restrict_os_commands);
906  $arrayofallowedcommand = array_map('trim', $arrayofallowedcommand);
907  if (in_array(basename($destfile), $arrayofallowedcommand)) {
908  //$langs->load("errors"); // key must be loaded because we can't rely on loading during output, we need var substitution to be done now.
909  //setEventMessages($langs->trans("ErrorFilenameReserved", basename($destfile)), null, 'errors');
910  dol_syslog("files.lib.php::dol_move canceled because target filename ".basename($destfile)." is using a reserved command name. we ignore the move request.", LOG_WARNING);
911  return false;
912  }
913  }
914 
915  $result = @rename($newpathofsrcfile, $newpathofdestfile); // To see errors, remove @
916  if (!$result) {
917  if ($destexists) {
918  dol_syslog("files.lib.php::dol_move Failed. We try to delete target first and move after.", LOG_WARNING);
919  // We force delete and try again. Rename function sometimes fails to replace dest file with some windows NTFS partitions.
920  dol_delete_file($destfile);
921  $result = @rename($newpathofsrcfile, $newpathofdestfile); // To see errors, remove @
922  } else {
923  dol_syslog("files.lib.php::dol_move Failed.", LOG_WARNING);
924  }
925  }
926 
927  // Move ok
928  if ($result && $indexdatabase) {
929  // Rename entry into ecm database
930  $rel_filetorenamebefore = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $srcfile);
931  $rel_filetorenameafter = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $destfile);
932  if (!preg_match('/([\\/]temp[\\/]|[\\/]thumbs|\.meta$)/', $rel_filetorenameafter)) { // If not a tmp file
933  $rel_filetorenamebefore = preg_replace('/^[\\/]/', '', $rel_filetorenamebefore);
934  $rel_filetorenameafter = preg_replace('/^[\\/]/', '', $rel_filetorenameafter);
935  //var_dump($rel_filetorenamebefore.' - '.$rel_filetorenameafter);exit;
936 
937  dol_syslog("Try to rename also entries in database for full relative path before = ".$rel_filetorenamebefore." after = ".$rel_filetorenameafter, LOG_DEBUG);
938  include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
939 
940  $ecmfiletarget = new EcmFiles($db);
941  $resultecmtarget = $ecmfiletarget->fetch(0, '', $rel_filetorenameafter);
942  if ($resultecmtarget > 0) { // An entry for target name already exists for target, we delete it, a new one will be created.
943  $ecmfiletarget->delete($user);
944  }
945 
946  $ecmfile = new EcmFiles($db);
947  $resultecm = $ecmfile->fetch(0, '', $rel_filetorenamebefore);
948  if ($resultecm > 0) { // If an entry was found for src file, we use it to move entry
949  $filename = basename($rel_filetorenameafter);
950  $rel_dir = dirname($rel_filetorenameafter);
951  $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
952  $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
953 
954  $ecmfile->filepath = $rel_dir;
955  $ecmfile->filename = $filename;
956 
957  $resultecm = $ecmfile->update($user);
958  } elseif ($resultecm == 0) { // If no entry were found for src files, create/update target file
959  $filename = basename($rel_filetorenameafter);
960  $rel_dir = dirname($rel_filetorenameafter);
961  $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
962  $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
963 
964  $ecmfile->filepath = $rel_dir;
965  $ecmfile->filename = $filename;
966  $ecmfile->label = md5_file(dol_osencode($destfile)); // $destfile is a full path to file
967  $ecmfile->fullpath_orig = $srcfile;
968  $ecmfile->gen_or_uploaded = 'unknown';
969  $ecmfile->description = ''; // indexed content
970  $ecmfile->keywords = ''; // keyword content
971  $resultecm = $ecmfile->create($user);
972  if ($resultecm < 0) {
973  setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
974  }
975  } elseif ($resultecm < 0) {
976  setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
977  }
978 
979  if ($resultecm > 0) {
980  $result = true;
981  } else {
982  $result = false;
983  }
984  }
985  }
986 
987  if (empty($newmask)) {
988  $newmask = empty($conf->global->MAIN_UMASK) ? '0755' : $conf->global->MAIN_UMASK;
989  }
990 
991  // Currently method is restricted to files (dol_delete_files previously used is for files, and mask usage if for files too)
992  // to allow mask usage for dir, we shoul introduce a new param "isdir" to 1 to complete newmask like this
993  // if ($isdir) $newmaskdec |= octdec('0111'); // Set x bit required for directories
994  dolChmod($newpathofdestfile, $newmask);
995  }
996 
997  return $result;
998 }
999 
1011 function dol_move_dir($srcdir, $destdir, $overwriteifexists = 1, $indexdatabase = 1, $renamedircontent = 1)
1012 {
1013 
1014  global $user, $db, $conf;
1015  $result = false;
1016 
1017  dol_syslog("files.lib.php::dol_move_dir srcdir=".$srcdir." destdir=".$destdir." overwritifexists=".$overwriteifexists." indexdatabase=".$indexdatabase." renamedircontent=".$renamedircontent);
1018  $srcexists = dol_is_dir($srcdir);
1019  $srcbasename = basename($srcdir);
1020  $destexists = dol_is_dir($destdir);
1021 
1022  if (!$srcexists) {
1023  dol_syslog("files.lib.php::dol_move_dir srcdir does not exists. we ignore the move request.");
1024  return false;
1025  }
1026 
1027  if ($overwriteifexists || !$destexists) {
1028  $newpathofsrcdir = dol_osencode($srcdir);
1029  $newpathofdestdir = dol_osencode($destdir);
1030 
1031  $result = @rename($newpathofsrcdir, $newpathofdestdir);
1032 
1033  if ($result && $renamedircontent) {
1034  if (file_exists($newpathofdestdir)) {
1035  $destbasename = basename($newpathofdestdir);
1036  $files = dol_dir_list($newpathofdestdir);
1037  if (!empty($files) && is_array($files)) {
1038  foreach ($files as $key => $file) {
1039  if (!file_exists($file["fullname"])) continue;
1040  $filepath = $file["path"];
1041  $oldname = $file["name"];
1042 
1043  $newname = str_replace($srcbasename, $destbasename, $oldname);
1044  if (!empty($newname) && $newname !== $oldname) {
1045  if ($file["type"] == "dir") {
1046  $res = dol_move_dir($filepath.'/'.$oldname, $filepath.'/'.$newname, $overwriteifexists, $indexdatabase, $renamedircontent);
1047  } else {
1048  $res = dol_move($filepath.'/'.$oldname, $filepath.'/'.$newname);
1049  }
1050  if (!$res) {
1051  return $result;
1052  }
1053  }
1054  }
1055  $result = true;
1056  }
1057  }
1058  }
1059  }
1060  return $result;
1061 }
1062 
1070 function dol_unescapefile($filename)
1071 {
1072  // Remove path information and dots around the filename, to prevent uploading
1073  // into different directories or replacing hidden system files.
1074  // Also remove control characters and spaces (\x00..\x20) around the filename:
1075  return trim(basename($filename), ".\x00..\x20");
1076 }
1077 
1078 
1085 function dolCheckVirus($src_file)
1086 {
1087  global $conf, $db;
1088 
1089  if (!empty($conf->global->MAIN_ANTIVIRUS_COMMAND)) {
1090  if (!class_exists('AntiVir')) {
1091  require_once DOL_DOCUMENT_ROOT.'/core/class/antivir.class.php';
1092  }
1093  $antivir = new AntiVir($db);
1094  $result = $antivir->dol_avscan_file($src_file);
1095  if ($result < 0) { // If virus or error, we stop here
1096  $reterrors = $antivir->errors;
1097  return $reterrors;
1098  }
1099  }
1100  return array();
1101 }
1102 
1103 
1124 function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan = 0, $uploaderrorcode = 0, $nohook = 0, $varfiles = 'addedfile', $upload_dir = '')
1125 {
1126  global $conf, $db, $user, $langs;
1127  global $object, $hookmanager;
1128 
1129  $reshook = 0;
1130  $file_name = $dest_file;
1131  $successcode = 1;
1132 
1133  if (empty($nohook)) {
1134  $reshook = $hookmanager->initHooks(array('fileslib'));
1135 
1136  $parameters = array('dest_file' => $dest_file, 'src_file' => $src_file, 'file_name' => $file_name, 'varfiles' => $varfiles, 'allowoverwrite' => $allowoverwrite);
1137  $reshook = $hookmanager->executeHooks('moveUploadedFile', $parameters, $object);
1138  }
1139 
1140  if (empty($reshook)) {
1141  // If an upload error has been reported
1142  if ($uploaderrorcode) {
1143  switch ($uploaderrorcode) {
1144  case UPLOAD_ERR_INI_SIZE: // 1
1145  return 'ErrorFileSizeTooLarge';
1146  case UPLOAD_ERR_FORM_SIZE: // 2
1147  return 'ErrorFileSizeTooLarge';
1148  case UPLOAD_ERR_PARTIAL: // 3
1149  return 'ErrorPartialFile';
1150  case UPLOAD_ERR_NO_TMP_DIR: //
1151  return 'ErrorNoTmpDir';
1152  case UPLOAD_ERR_CANT_WRITE:
1153  return 'ErrorFailedToWriteInDir';
1154  case UPLOAD_ERR_EXTENSION:
1155  return 'ErrorUploadBlockedByAddon';
1156  default:
1157  break;
1158  }
1159  }
1160 
1161  // If we need to make a virus scan
1162  if (empty($disablevirusscan) && file_exists($src_file)) {
1163  $checkvirusarray = dolCheckVirus($src_file);
1164  if (count($checkvirusarray)) {
1165  dol_syslog('Files.lib::dol_move_uploaded_file File "'.$src_file.'" (target name "'.$dest_file.'") KO with antivirus: errors='.join(',', $checkvirusarray), LOG_WARNING);
1166  return 'ErrorFileIsInfectedWithAVirus: '.join(',', $checkvirusarray);
1167  }
1168  }
1169 
1170  // Security:
1171  // Disallow file with some extensions. We rename them.
1172  // Because if we put the documents directory into a directory inside web root (very bad), this allows to execute on demand arbitrary code.
1173  if (isAFileWithExecutableContent($dest_file) && empty($conf->global->MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED)) {
1174  // $upload_dir ends with a slash, so be must be sure the medias dir to compare to ends with slash too.
1175  $publicmediasdirwithslash = $conf->medias->multidir_output[$conf->entity];
1176  if (!preg_match('/\/$/', $publicmediasdirwithslash)) {
1177  $publicmediasdirwithslash .= '/';
1178  }
1179 
1180  if (strpos($upload_dir, $publicmediasdirwithslash) !== 0) { // We never add .noexe on files into media directory
1181  $file_name .= '.noexe';
1182  $successcode = 2;
1183  }
1184  }
1185 
1186  // Security:
1187  // We refuse cache files/dirs, upload using .. and pipes into filenames.
1188  if (preg_match('/^\./', basename($src_file)) || preg_match('/\.\./', $src_file) || preg_match('/[<>|]/', $src_file)) {
1189  dol_syslog("Refused to deliver file ".$src_file, LOG_WARNING);
1190  return -1;
1191  }
1192 
1193  // Security:
1194  // We refuse cache files/dirs, upload using .. and pipes into filenames.
1195  if (preg_match('/^\./', basename($dest_file)) || preg_match('/\.\./', $dest_file) || preg_match('/[<>|]/', $dest_file)) {
1196  dol_syslog("Refused to deliver file ".$dest_file, LOG_WARNING);
1197  return -2;
1198  }
1199  }
1200 
1201  if ($reshook < 0) { // At least one blocking error returned by one hook
1202  $errmsg = join(',', $hookmanager->errors);
1203  if (empty($errmsg)) {
1204  $errmsg = 'ErrorReturnedBySomeHooks'; // Should not occurs. Added if hook is bugged and does not set ->errors when there is error.
1205  }
1206  return $errmsg;
1207  } elseif (empty($reshook)) {
1208  // The file functions must be in OS filesystem encoding.
1209  $src_file_osencoded = dol_osencode($src_file);
1210  $file_name_osencoded = dol_osencode($file_name);
1211 
1212  // Check if destination dir is writable
1213  if (!is_writable(dirname($file_name_osencoded))) {
1214  dol_syslog("Files.lib::dol_move_uploaded_file Dir ".dirname($file_name_osencoded)." is not writable. Return 'ErrorDirNotWritable'", LOG_WARNING);
1215  return 'ErrorDirNotWritable';
1216  }
1217 
1218  // Check if destination file already exists
1219  if (!$allowoverwrite) {
1220  if (file_exists($file_name_osencoded)) {
1221  dol_syslog("Files.lib::dol_move_uploaded_file File ".$file_name." already exists. Return 'ErrorFileAlreadyExists'", LOG_WARNING);
1222  return 'ErrorFileAlreadyExists';
1223  }
1224  } else { // We are allowed to erase
1225  if (is_dir($file_name_osencoded)) { // If there is a directory with name of file to create
1226  dol_syslog("Files.lib::dol_move_uploaded_file A directory with name ".$file_name." already exists. Return 'ErrorDirWithFileNameAlreadyExists'", LOG_WARNING);
1227  return 'ErrorDirWithFileNameAlreadyExists';
1228  }
1229  }
1230 
1231  // Move file
1232  $return = move_uploaded_file($src_file_osencoded, $file_name_osencoded);
1233  if ($return) {
1234  dolChmod($file_name_osencoded);
1235  dol_syslog("Files.lib::dol_move_uploaded_file Success to move ".$src_file." to ".$file_name." - Umask=".$conf->global->MAIN_UMASK, LOG_DEBUG);
1236  return $successcode; // Success
1237  } else {
1238  dol_syslog("Files.lib::dol_move_uploaded_file Failed to move ".$src_file." to ".$file_name, LOG_ERR);
1239  return -3; // Unknown error
1240  }
1241  }
1242 
1243  return $successcode; // Success
1244 }
1245 
1261 function dol_delete_file($file, $disableglob = 0, $nophperrors = 0, $nohook = 0, $object = null, $allowdotdot = false, $indexdatabase = 1, $nolog = 0)
1262 {
1263  global $db, $conf, $user, $langs;
1264  global $hookmanager;
1265 
1266  // Load translation files required by the page
1267  $langs->loadLangs(array('other', 'errors'));
1268 
1269  if (empty($nolog)) {
1270  dol_syslog("dol_delete_file file=".$file." disableglob=".$disableglob." nophperrors=".$nophperrors." nohook=".$nohook);
1271  }
1272 
1273  // Security:
1274  // We refuse transversal using .. and pipes into filenames.
1275  if ((!$allowdotdot && preg_match('/\.\./', $file)) || preg_match('/[<>|]/', $file)) {
1276  dol_syslog("Refused to delete file ".$file, LOG_WARNING);
1277  return false;
1278  }
1279 
1280  $reshook = 0;
1281  if (empty($nohook)) {
1282  $hookmanager->initHooks(array('fileslib'));
1283 
1284  $parameters = array(
1285  'file' => $file,
1286  'disableglob'=> $disableglob,
1287  'nophperrors' => $nophperrors
1288  );
1289  $reshook = $hookmanager->executeHooks('deleteFile', $parameters, $object);
1290  }
1291 
1292  if (empty($nohook) && $reshook != 0) { // reshook = 0 to do standard actions, 1 = ok and replace, -1 = ko
1293  dol_syslog("reshook=".$reshook);
1294  if ($reshook < 0) {
1295  return false;
1296  }
1297  return true;
1298  } else {
1299  $file_osencoded = dol_osencode($file); // New filename encoded in OS filesystem encoding charset
1300  if (empty($disableglob) && !empty($file_osencoded)) {
1301  $ok = true;
1302  $globencoded = str_replace('[', '\[', $file_osencoded);
1303  $globencoded = str_replace(']', '\]', $globencoded);
1304  $listofdir = glob($globencoded);
1305  if (!empty($listofdir) && is_array($listofdir)) {
1306  foreach ($listofdir as $filename) {
1307  if ($nophperrors) {
1308  $ok = @unlink($filename);
1309  } else {
1310  $ok = unlink($filename);
1311  }
1312 
1313  // If it fails and it is because of the missing write permission on parent dir
1314  if (!$ok && file_exists(dirname($filename)) && !(fileperms(dirname($filename)) & 0200)) {
1315  dol_syslog("Error in deletion, but parent directory exists with no permission to write, we try to change permission on parent directory and retry...", LOG_DEBUG);
1316  dolChmod(dirname($filename), decoct(fileperms(dirname($filename)) | 0200));
1317  // Now we retry deletion
1318  if ($nophperrors) {
1319  $ok = @unlink($filename);
1320  } else {
1321  $ok = unlink($filename);
1322  }
1323  }
1324 
1325  if ($ok) {
1326  if (empty($nolog)) {
1327  dol_syslog("Removed file ".$filename, LOG_DEBUG);
1328  }
1329 
1330  // Delete entry into ecm database
1331  $rel_filetodelete = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $filename);
1332  if (!preg_match('/(\/temp\/|\/thumbs\/|\.meta$)/', $rel_filetodelete)) { // If not a tmp file
1333  if (is_object($db) && $indexdatabase) { // $db may not be defined when lib is in a context with define('NOREQUIREDB',1)
1334  $rel_filetodelete = preg_replace('/^[\\/]/', '', $rel_filetodelete);
1335  $rel_filetodelete = preg_replace('/\.noexe$/', '', $rel_filetodelete);
1336 
1337  dol_syslog("Try to remove also entries in database for full relative path = ".$rel_filetodelete, LOG_DEBUG);
1338  include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
1339  $ecmfile = new EcmFiles($db);
1340  $result = $ecmfile->fetch(0, '', $rel_filetodelete);
1341  if ($result >= 0 && $ecmfile->id > 0) {
1342  $result = $ecmfile->delete($user);
1343  }
1344  if ($result < 0) {
1345  setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
1346  }
1347  }
1348  }
1349  } else {
1350  dol_syslog("Failed to remove file ".$filename, LOG_WARNING);
1351  // TODO Failure to remove can be because file was already removed or because of permission
1352  // If error because it does not exists, we should return true, and we should return false if this is a permission problem
1353  }
1354  }
1355  } else {
1356  dol_syslog("No files to delete found", LOG_DEBUG);
1357  }
1358  } else {
1359  $ok = false;
1360  if ($nophperrors) {
1361  $ok = @unlink($file_osencoded);
1362  } else {
1363  $ok = unlink($file_osencoded);
1364  }
1365  if ($ok) {
1366  if (empty($nolog)) {
1367  dol_syslog("Removed file ".$file_osencoded, LOG_DEBUG);
1368  }
1369  } else {
1370  dol_syslog("Failed to remove file ".$file_osencoded, LOG_WARNING);
1371  }
1372  }
1373 
1374  return $ok;
1375  }
1376 }
1377 
1387 function dol_delete_dir($dir, $nophperrors = 0)
1388 {
1389  // Security:
1390  // We refuse transversal using .. and pipes into filenames.
1391  if (preg_match('/\.\./', $dir) || preg_match('/[<>|]/', $dir)) {
1392  dol_syslog("Refused to delete dir ".$dir.' (contains invalid char sequence)', LOG_WARNING);
1393  return false;
1394  }
1395 
1396  $dir_osencoded = dol_osencode($dir);
1397  return ($nophperrors ? @rmdir($dir_osencoded) : rmdir($dir_osencoded));
1398 }
1399 
1412 function dol_delete_dir_recursive($dir, $count = 0, $nophperrors = 0, $onlysub = 0, &$countdeleted = 0, $indexdatabase = 1, $nolog = 0)
1413 {
1414  if (empty($nolog)) {
1415  dol_syslog("functions.lib:dol_delete_dir_recursive ".$dir, LOG_DEBUG);
1416  }
1417  if (dol_is_dir($dir)) {
1418  $dir_osencoded = dol_osencode($dir);
1419  if ($handle = opendir("$dir_osencoded")) {
1420  while (false !== ($item = readdir($handle))) {
1421  if (!utf8_check($item)) {
1422  $item = utf8_encode($item); // should be useless
1423  }
1424 
1425  if ($item != "." && $item != "..") {
1426  if (is_dir(dol_osencode("$dir/$item")) && !is_link(dol_osencode("$dir/$item"))) {
1427  $count = dol_delete_dir_recursive("$dir/$item", $count, $nophperrors, 0, $countdeleted, $indexdatabase, $nolog);
1428  } else {
1429  $result = dol_delete_file("$dir/$item", 1, $nophperrors, 0, null, false, $indexdatabase, $nolog);
1430  $count++;
1431  if ($result) {
1432  $countdeleted++;
1433  }
1434  //else print 'Error on '.$item."\n";
1435  }
1436  }
1437  }
1438  closedir($handle);
1439 
1440  // Delete also the main directory
1441  if (empty($onlysub)) {
1442  $result = dol_delete_dir($dir, $nophperrors);
1443  $count++;
1444  if ($result) {
1445  $countdeleted++;
1446  }
1447  //else print 'Error on '.$dir."\n";
1448  }
1449  }
1450  }
1451 
1452  return $count;
1453 }
1454 
1455 
1464 function dol_delete_preview($object)
1465 {
1466  global $langs, $conf;
1467 
1468  // Define parent dir of elements
1469  $element = $object->element;
1470 
1471  if ($object->element == 'order_supplier') {
1472  $dir = $conf->fournisseur->commande->dir_output;
1473  } elseif ($object->element == 'invoice_supplier') {
1474  $dir = $conf->fournisseur->facture->dir_output;
1475  } elseif ($object->element == 'project') {
1476  $dir = $conf->project->dir_output;
1477  } elseif ($object->element == 'shipping') {
1478  $dir = $conf->expedition->dir_output.'/sending';
1479  } elseif ($object->element == 'delivery') {
1480  $dir = $conf->expedition->dir_output.'/receipt';
1481  } elseif ($object->element == 'fichinter') {
1482  $dir = $conf->ficheinter->dir_output;
1483  } else {
1484  $dir = empty($conf->$element->dir_output) ? '' : $conf->$element->dir_output;
1485  }
1486 
1487  if (empty($dir)) {
1488  return 'ErrorObjectNoSupportedByFunction';
1489  }
1490 
1491  $refsan = dol_sanitizeFileName($object->ref);
1492  $dir = $dir."/".$refsan;
1493  $filepreviewnew = $dir."/".$refsan.".pdf_preview.png";
1494  $filepreviewnewbis = $dir."/".$refsan.".pdf_preview-0.png";
1495  $filepreviewold = $dir."/".$refsan.".pdf.png";
1496 
1497  // For new preview files
1498  if (file_exists($filepreviewnew) && is_writable($filepreviewnew)) {
1499  if (!dol_delete_file($filepreviewnew, 1)) {
1500  $object->error = $langs->trans("ErrorFailedToDeleteFile", $filepreviewnew);
1501  return 0;
1502  }
1503  }
1504  if (file_exists($filepreviewnewbis) && is_writable($filepreviewnewbis)) {
1505  if (!dol_delete_file($filepreviewnewbis, 1)) {
1506  $object->error = $langs->trans("ErrorFailedToDeleteFile", $filepreviewnewbis);
1507  return 0;
1508  }
1509  }
1510  // For old preview files
1511  if (file_exists($filepreviewold) && is_writable($filepreviewold)) {
1512  if (!dol_delete_file($filepreviewold, 1)) {
1513  $object->error = $langs->trans("ErrorFailedToDeleteFile", $filepreviewold);
1514  return 0;
1515  }
1516  } else {
1517  $multiple = $filepreviewold.".";
1518  for ($i = 0; $i < 20; $i++) {
1519  $preview = $multiple.$i;
1520 
1521  if (file_exists($preview) && is_writable($preview)) {
1522  if (!dol_delete_file($preview, 1)) {
1523  $object->error = $langs->trans("ErrorFailedToOpenFile", $preview);
1524  return 0;
1525  }
1526  }
1527  }
1528  }
1529 
1530  return 1;
1531 }
1532 
1541 function dol_meta_create($object)
1542 {
1543  global $conf;
1544 
1545  // Create meta file
1546  if (empty($conf->global->MAIN_DOC_CREATE_METAFILE)) {
1547  return 0; // By default, no metafile.
1548  }
1549 
1550  // Define parent dir of elements
1551  $element = $object->element;
1552 
1553  if ($object->element == 'order_supplier') {
1554  $dir = $conf->fournisseur->dir_output.'/commande';
1555  } elseif ($object->element == 'invoice_supplier') {
1556  $dir = $conf->fournisseur->dir_output.'/facture';
1557  } elseif ($object->element == 'project') {
1558  $dir = $conf->project->dir_output;
1559  } elseif ($object->element == 'shipping') {
1560  $dir = $conf->expedition->dir_output.'/sending';
1561  } elseif ($object->element == 'delivery') {
1562  $dir = $conf->expedition->dir_output.'/receipt';
1563  } elseif ($object->element == 'fichinter') {
1564  $dir = $conf->ficheinter->dir_output;
1565  } else {
1566  $dir = empty($conf->$element->dir_output) ? '' : $conf->$element->dir_output;
1567  }
1568 
1569  if ($dir) {
1570  $object->fetch_thirdparty();
1571 
1572  $objectref = dol_sanitizeFileName($object->ref);
1573  $dir = $dir."/".$objectref;
1574  $file = $dir."/".$objectref.".meta";
1575 
1576  if (!is_dir($dir)) {
1577  dol_mkdir($dir);
1578  }
1579 
1580  if (is_dir($dir)) {
1581  if (is_countable($object->lines) && count($object->lines) > 0) {
1582  $nblines = count($object->lines);
1583  }
1584  $client = $object->thirdparty->name." ".$object->thirdparty->address." ".$object->thirdparty->zip." ".$object->thirdparty->town;
1585  $meta = "REFERENCE=\"".$object->ref."\"
1586  DATE=\"" . dol_print_date($object->date, '')."\"
1587  NB_ITEMS=\"" . $nblines."\"
1588  CLIENT=\"" . $client."\"
1589  AMOUNT_EXCL_TAX=\"" . $object->total_ht."\"
1590  AMOUNT=\"" . $object->total_ttc."\"\n";
1591 
1592  for ($i = 0; $i < $nblines; $i++) {
1593  //Pour les articles
1594  $meta .= "ITEM_".$i."_QUANTITY=\"".$object->lines[$i]->qty."\"
1595  ITEM_" . $i."_AMOUNT_WO_TAX=\"".$object->lines[$i]->total_ht."\"
1596  ITEM_" . $i."_VAT=\"".$object->lines[$i]->tva_tx."\"
1597  ITEM_" . $i."_DESCRIPTION=\"".str_replace("\r\n", "", nl2br($object->lines[$i]->desc))."\"
1598  ";
1599  }
1600  }
1601 
1602  $fp = fopen($file, "w");
1603  fputs($fp, $meta);
1604  fclose($fp);
1605 
1606  dolChmod($file);
1607 
1608  return 1;
1609  } else {
1610  dol_syslog('FailedToDetectDirInDolMetaCreateFor'.$object->element, LOG_WARNING);
1611  }
1612 
1613  return 0;
1614 }
1615 
1616 
1617 
1626 function dol_init_file_process($pathtoscan = '', $trackid = '')
1627 {
1628  $listofpaths = array();
1629  $listofnames = array();
1630  $listofmimes = array();
1631 
1632  if ($pathtoscan) {
1633  $listoffiles = dol_dir_list($pathtoscan, 'files');
1634  foreach ($listoffiles as $key => $val) {
1635  $listofpaths[] = $val['fullname'];
1636  $listofnames[] = $val['name'];
1637  $listofmimes[] = dol_mimetype($val['name']);
1638  }
1639  }
1640  $keytoavoidconflict = empty($trackid) ? '' : '-'.$trackid;
1641  $_SESSION["listofpaths".$keytoavoidconflict] = join(';', $listofpaths);
1642  $_SESSION["listofnames".$keytoavoidconflict] = join(';', $listofnames);
1643  $_SESSION["listofmimes".$keytoavoidconflict] = join(';', $listofmimes);
1644 }
1645 
1646 
1664 function dol_add_file_process($upload_dir, $allowoverwrite = 0, $donotupdatesession = 0, $varfiles = 'addedfile', $savingdocmask = '', $link = null, $trackid = '', $generatethumbs = 1, $object = null)
1665 {
1666 
1667  global $db, $user, $conf, $langs;
1668 
1669  $res = 0;
1670 
1671  if (!empty($_FILES[$varfiles])) { // For view $_FILES[$varfiles]['error']
1672  dol_syslog('dol_add_file_process upload_dir='.$upload_dir.' allowoverwrite='.$allowoverwrite.' donotupdatesession='.$donotupdatesession.' savingdocmask='.$savingdocmask, LOG_DEBUG);
1673  $maxfilesinform = getDolGlobalInt("MAIN_SECURITY_MAX_ATTACHMENT_ON_FORMS", 10);
1674  if (is_array($_FILES[$varfiles]["name"]) && count($_FILES[$varfiles]["name"]) > $maxfilesinform) {
1675  $langs->load("errors"); // key must be loaded because we can't rely on loading during output, we need var substitution to be done now.
1676  setEventMessages($langs->trans("ErrorTooMuchFileInForm", $maxfilesinform), null, "errors");
1677  return -1;
1678  }
1679  $result = dol_mkdir($upload_dir);
1680  // var_dump($result);exit;
1681  if ($result >= 0) {
1682  $TFile = $_FILES[$varfiles];
1683  if (!is_array($TFile['name'])) {
1684  foreach ($TFile as $key => &$val) {
1685  $val = array($val);
1686  }
1687  }
1688 
1689  $nbfile = count($TFile['name']);
1690  $nbok = 0;
1691  for ($i = 0; $i < $nbfile; $i++) {
1692  if (empty($TFile['name'][$i])) {
1693  continue; // For example, when submitting a form with no file name
1694  }
1695 
1696  // Define $destfull (path to file including filename) and $destfile (only filename)
1697  $destfull = $upload_dir."/".$TFile['name'][$i];
1698  $destfile = $TFile['name'][$i];
1699  $destfilewithoutext = preg_replace('/\.[^\.]+$/', '', $destfile);
1700 
1701  if ($savingdocmask && strpos($savingdocmask, $destfilewithoutext) !== 0) {
1702  $destfull = $upload_dir."/".preg_replace('/__file__/', $TFile['name'][$i], $savingdocmask);
1703  $destfile = preg_replace('/__file__/', $TFile['name'][$i], $savingdocmask);
1704  }
1705 
1706  $filenameto = basename($destfile);
1707  if (preg_match('/^\./', $filenameto)) {
1708  $langs->load("errors"); // key must be loaded because we can't rely on loading during output, we need var substitution to be done now.
1709  setEventMessages($langs->trans("ErrorFilenameCantStartWithDot", $filenameto), null, 'errors');
1710  break;
1711  }
1712 
1713  // dol_sanitizeFileName the file name and lowercase extension
1714  $info = pathinfo($destfull);
1715  $destfull = $info['dirname'].'/'.dol_sanitizeFileName($info['filename'].($info['extension'] != '' ? ('.'.strtolower($info['extension'])) : ''));
1716  $info = pathinfo($destfile);
1717  $destfile = dol_sanitizeFileName($info['filename'].($info['extension'] != '' ? ('.'.strtolower($info['extension'])) : ''));
1718 
1719  // We apply dol_string_nohtmltag also to clean file names (this remove duplicate spaces) because
1720  // this function is also applied when we rename and when we make try to download file (by the GETPOST(filename, 'alphanohtml') call).
1721  $destfile = dol_string_nohtmltag($destfile);
1722  $destfull = dol_string_nohtmltag($destfull);
1723 
1724  // Check that filename is not the one of a reserved allowed CLI command
1725  global $dolibarr_main_restrict_os_commands;
1726  if (!empty($dolibarr_main_restrict_os_commands)) {
1727  $arrayofallowedcommand = explode(',', $dolibarr_main_restrict_os_commands);
1728  $arrayofallowedcommand = array_map('trim', $arrayofallowedcommand);
1729  if (in_array($destfile, $arrayofallowedcommand)) {
1730  $langs->load("errors"); // key must be loaded because we can't rely on loading during output, we need var substitution to be done now.
1731  setEventMessages($langs->trans("ErrorFilenameReserved", $destfile), null, 'errors');
1732  return -1;
1733  }
1734  }
1735 
1736  // Move file from temp directory to final directory. A .noexe may also be appended on file name.
1737  $resupload = dol_move_uploaded_file($TFile['tmp_name'][$i], $destfull, $allowoverwrite, 0, $TFile['error'][$i], 0, $varfiles, $upload_dir);
1738 
1739  if (is_numeric($resupload) && $resupload > 0) { // $resupload can be 'ErrorFileAlreadyExists'
1740  global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini;
1741 
1742  include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
1743 
1744  // Generate thumbs.
1745  if ($generatethumbs) {
1746  if (image_format_supported($destfull) == 1) {
1747  // Create thumbs
1748  // We can't use $object->addThumbs here because there is no $object known
1749 
1750  // Used on logon for example
1751  $imgThumbSmall = vignette($destfull, $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs");
1752  // Create mini thumbs for image (Ratio is near 16/9)
1753  // Used on menu or for setup page for example
1754  $imgThumbMini = vignette($destfull, $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs");
1755  }
1756  }
1757 
1758  // Update session
1759  if (empty($donotupdatesession)) {
1760  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
1761  $formmail = new FormMail($db);
1762  $formmail->trackid = $trackid;
1763  $formmail->add_attached_files($destfull, $destfile, $TFile['type'][$i]);
1764  }
1765 
1766  // Update index table of files (llx_ecm_files)
1767  if ($donotupdatesession == 1) {
1768  $sharefile = 0;
1769  if ($TFile['type'][$i] == 'application/pdf' && strpos($_SERVER["REQUEST_URI"], 'product') !== false && !empty($conf->global->PRODUCT_ALLOW_EXTERNAL_DOWNLOAD)) $sharefile = 1;
1770  $result = addFileIntoDatabaseIndex($upload_dir, basename($destfile).($resupload == 2 ? '.noexe' : ''), $TFile['name'][$i], 'uploaded', $sharefile, $object);
1771  if ($result < 0) {
1772  if ($allowoverwrite) {
1773  // Do not show error message. We can have an error due to DB_ERROR_RECORD_ALREADY_EXISTS
1774  } else {
1775  setEventMessages('WarningFailedToAddFileIntoDatabaseIndex', null, 'warnings');
1776  }
1777  }
1778  }
1779 
1780  $nbok++;
1781  } else {
1782  $langs->load("errors");
1783  if ($resupload < 0) { // Unknown error
1784  setEventMessages($langs->trans("ErrorFileNotUploaded"), null, 'errors');
1785  } elseif (preg_match('/ErrorFileIsInfectedWithAVirus/', $resupload)) { // Files infected by a virus
1786  setEventMessages($langs->trans("ErrorFileIsInfectedWithAVirus"), null, 'errors');
1787  } else // Known error
1788  {
1789  setEventMessages($langs->trans($resupload), null, 'errors');
1790  }
1791  }
1792  }
1793  if ($nbok > 0) {
1794  $res = 1;
1795  setEventMessages($langs->trans("FileTransferComplete"), null, 'mesgs');
1796  }
1797  } else {
1798  setEventMessages($langs->trans("ErrorFailedToCreateDir", $upload_dir), null, 'errors');
1799  }
1800  } elseif ($link) {
1801  require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
1802  $linkObject = new Link($db);
1803  $linkObject->entity = $conf->entity;
1804  $linkObject->url = $link;
1805  $linkObject->objecttype = GETPOST('objecttype', 'alpha');
1806  $linkObject->objectid = GETPOST('objectid', 'int');
1807  $linkObject->label = GETPOST('label', 'alpha');
1808  $res = $linkObject->create($user);
1809  $langs->load('link');
1810  if ($res > 0) {
1811  setEventMessages($langs->trans("LinkComplete"), null, 'mesgs');
1812  } else {
1813  setEventMessages($langs->trans("ErrorFileNotLinked"), null, 'errors');
1814  }
1815  } else {
1816  $langs->load("errors");
1817  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("File")), null, 'errors');
1818  }
1819 
1820  return $res;
1821 }
1822 
1823 
1835 function dol_remove_file_process($filenb, $donotupdatesession = 0, $donotdeletefile = 1, $trackid = '')
1836 {
1837  global $db, $user, $conf, $langs, $_FILES;
1838 
1839  $keytodelete = $filenb;
1840  $keytodelete--;
1841 
1842  $listofpaths = array();
1843  $listofnames = array();
1844  $listofmimes = array();
1845  $keytoavoidconflict = empty($trackid) ? '' : '-'.$trackid;
1846  if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
1847  $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
1848  }
1849  if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
1850  $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
1851  }
1852  if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
1853  $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
1854  }
1855 
1856  if ($keytodelete >= 0) {
1857  $pathtodelete = $listofpaths[$keytodelete];
1858  $filetodelete = $listofnames[$keytodelete];
1859  if (empty($donotdeletefile)) {
1860  $result = dol_delete_file($pathtodelete, 1); // The delete of ecm database is inside the function dol_delete_file
1861  } else {
1862  $result = 0;
1863  }
1864  if ($result >= 0) {
1865  if (empty($donotdeletefile)) {
1866  $langs->load("other");
1867  setEventMessages($langs->trans("FileWasRemoved", $filetodelete), null, 'mesgs');
1868  }
1869  if (empty($donotupdatesession)) {
1870  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
1871  $formmail = new FormMail($db);
1872  $formmail->trackid = $trackid;
1873  $formmail->remove_attached_files($keytodelete);
1874  }
1875  }
1876  }
1877 }
1878 
1879 
1893 function addFileIntoDatabaseIndex($dir, $file, $fullpathorig = '', $mode = 'uploaded', $setsharekey = 0, $object = null)
1894 {
1895  global $db, $user, $conf;
1896 
1897  $result = 0;
1898 
1899  $rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $dir);
1900 
1901  if (!preg_match('/[\\/]temp[\\/]|[\\/]thumbs|\.meta$/', $rel_dir)) { // If not a tmp dir
1902  $filename = basename(preg_replace('/\.noexe$/', '', $file));
1903  $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
1904  $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
1905 
1906  include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
1907  $ecmfile = new EcmFiles($db);
1908  $ecmfile->filepath = $rel_dir;
1909  $ecmfile->filename = $filename;
1910  $ecmfile->label = md5_file(dol_osencode($dir.'/'.$file)); // MD5 of file content
1911  $ecmfile->fullpath_orig = $fullpathorig;
1912  $ecmfile->gen_or_uploaded = $mode;
1913  $ecmfile->description = ''; // indexed content
1914  $ecmfile->keywords = ''; // keyword content
1915 
1916  if (is_object($object) && $object->id > 0) {
1917  $ecmfile->src_object_id = $object->id;
1918  if (isset($object->table_element)) {
1919  $ecmfile->src_object_type = $object->table_element;
1920  } else {
1921  dol_syslog('Error: object ' . get_class($object) . ' has no table_element attribute.');
1922  return -1;
1923  }
1924  if (isset($object->src_object_description)) $ecmfile->description = $object->src_object_description;
1925  if (isset($object->src_object_keywords)) $ecmfile->keywords = $object->src_object_keywords;
1926  }
1927 
1928  if (!empty($conf->global->MAIN_FORCE_SHARING_ON_ANY_UPLOADED_FILE)) {
1929  $setsharekey = 1;
1930  }
1931 
1932  if ($setsharekey) {
1933  require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
1934  $ecmfile->share = getRandomPassword(true);
1935  }
1936 
1937  $result = $ecmfile->create($user);
1938  if ($result < 0) {
1939  dol_syslog($ecmfile->error);
1940  }
1941  }
1942 
1943  return $result;
1944 }
1945 
1954 function deleteFilesIntoDatabaseIndex($dir, $file, $mode = 'uploaded')
1955 {
1956  global $conf, $db, $user;
1957 
1958  $error = 0;
1959 
1960  if (empty($dir)) {
1961  dol_syslog("deleteFilesIntoDatabaseIndex: dir parameter can't be empty", LOG_ERR);
1962  return -1;
1963  }
1964 
1965  $db->begin();
1966 
1967  $rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $dir);
1968 
1969  $filename = basename($file);
1970  $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
1971  $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
1972 
1973  if (!$error) {
1974  $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'ecm_files';
1975  $sql .= ' WHERE entity = '.$conf->entity;
1976  $sql .= " AND filepath = '".$db->escape($rel_dir)."'";
1977  if ($file) {
1978  $sql .= " AND filename = '".$db->escape($file)."'";
1979  }
1980  if ($mode) {
1981  $sql .= " AND gen_or_uploaded = '".$db->escape($mode)."'";
1982  }
1983 
1984  $resql = $db->query($sql);
1985  if (!$resql) {
1986  $error++;
1987  dol_syslog(__METHOD__.' '.$db->lasterror(), LOG_ERR);
1988  }
1989  }
1990 
1991  // Commit or rollback
1992  if ($error) {
1993  $db->rollback();
1994  return -1 * $error;
1995  } else {
1996  $db->commit();
1997  return 1;
1998  }
1999 }
2000 
2001 
2013 function dol_convert_file($fileinput, $ext = 'png', $fileoutput = '', $page = '')
2014 {
2015  if (class_exists('Imagick')) {
2016  $image = new Imagick();
2017  try {
2018  $filetoconvert = $fileinput.(($page != '') ? '['.$page.']' : '');
2019  //var_dump($filetoconvert);
2020  $ret = $image->readImage($filetoconvert);
2021  } catch (Exception $e) {
2022  $ext = pathinfo($fileinput, PATHINFO_EXTENSION);
2023  dol_syslog("Failed to read image using Imagick (Try to install package 'apt-get install php-imagick ghostscript' and check there is no policy to disable ".$ext." convertion in /etc/ImageMagick*/policy.xml): ".$e->getMessage(), LOG_WARNING);
2024  return 0;
2025  }
2026  if ($ret) {
2027  $ret = $image->setImageFormat($ext);
2028  if ($ret) {
2029  if (empty($fileoutput)) {
2030  $fileoutput = $fileinput.".".$ext;
2031  }
2032 
2033  $count = $image->getNumberImages();
2034 
2035  if (!dol_is_file($fileoutput) || is_writeable($fileoutput)) {
2036  try {
2037  $ret = $image->writeImages($fileoutput, true);
2038  } catch (Exception $e) {
2039  dol_syslog($e->getMessage(), LOG_WARNING);
2040  }
2041  } else {
2042  dol_syslog("Warning: Failed to write cache preview file '.$fileoutput.'. Check permission on file/dir", LOG_ERR);
2043  }
2044  if ($ret) {
2045  return $count;
2046  } else {
2047  return -3;
2048  }
2049  } else {
2050  return -2;
2051  }
2052  } else {
2053  return -1;
2054  }
2055  } else {
2056  return 0;
2057  }
2058 }
2059 
2060 
2072 function dol_compress_file($inputfile, $outputfile, $mode = "gz", &$errorstring = null)
2073 {
2074  global $conf;
2075 
2076  $foundhandler = 0;
2077 
2078  try {
2079  dol_syslog("dol_compress_file mode=".$mode." inputfile=".$inputfile." outputfile=".$outputfile);
2080 
2081  $data = implode("", file(dol_osencode($inputfile)));
2082  if ($mode == 'gz' && function_exists('gzencode')) {
2083  $foundhandler = 1;
2084  $compressdata = gzencode($data, 9);
2085  } elseif ($mode == 'bz' && function_exists('bzcompress')) {
2086  $foundhandler = 1;
2087  $compressdata = bzcompress($data, 9);
2088  } elseif ($mode == 'zstd' && function_exists('zstd_compress')) {
2089  $foundhandler = 1;
2090  $compressdata = zstd_compress($data, 9);
2091  } elseif ($mode == 'zip') {
2092  if (class_exists('ZipArchive') && !empty($conf->global->MAIN_USE_ZIPARCHIVE_FOR_ZIP_COMPRESS)) {
2093  $foundhandler = 1;
2094 
2095  $rootPath = realpath($inputfile);
2096 
2097  dol_syslog("Class ZipArchive is set so we zip using ZipArchive to zip into ".$outputfile.' rootPath='.$rootPath);
2098  $zip = new ZipArchive;
2099 
2100  if ($zip->open($outputfile, ZipArchive::CREATE) !== true) {
2101  $errorstring = "dol_compress_file failure - Failed to open file ".$outputfile."\n";
2102  dol_syslog($errorstring, LOG_ERR);
2103 
2104  global $errormsg;
2105  $errormsg = $errorstring;
2106 
2107  return -6;
2108  }
2109 
2110  // Create recursive directory iterator
2112  $files = new RecursiveIteratorIterator(
2113  new RecursiveDirectoryIterator($rootPath),
2114  RecursiveIteratorIterator::LEAVES_ONLY
2115  );
2116 
2117  foreach ($files as $name => $file) {
2118  // Skip directories (they would be added automatically)
2119  if (!$file->isDir()) {
2120  // Get real and relative path for current file
2121  $filePath = $file->getPath(); // the full path with filename using the $inputdir root.
2122  $fileName = $file->getFilename();
2123  $fileFullRealPath = $file->getRealPath(); // the full path with name and transformed to use real path directory.
2124 
2125  //$relativePath = substr($fileFullRealPath, strlen($rootPath) + 1);
2126  $relativePath = substr(($filePath ? $filePath.'/' : '').$fileName, strlen($rootPath) + 1);
2127 
2128  // Add current file to archive
2129  $zip->addFile($fileFullRealPath, $relativePath);
2130  }
2131  }
2132 
2133  // Zip archive will be created only after closing object
2134  $zip->close();
2135 
2136  dol_syslog("dol_compress_file success - ".count($zip->numFiles)." files");
2137  return 1;
2138  }
2139 
2140  if (defined('ODTPHP_PATHTOPCLZIP')) {
2141  $foundhandler = 1;
2142 
2143  include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
2144  $archive = new PclZip($outputfile);
2145  $result = $archive->add($inputfile, PCLZIP_OPT_REMOVE_PATH, dirname($inputfile));
2146 
2147  if ($result === 0) {
2148  global $errormsg;
2149  $errormsg = $archive->errorInfo(true);
2150 
2151  if ($archive->errorCode() == PCLZIP_ERR_WRITE_OPEN_FAIL) {
2152  $errorstring = "PCLZIP_ERR_WRITE_OPEN_FAIL";
2153  dol_syslog("dol_compress_file error - archive->errorCode() = PCLZIP_ERR_WRITE_OPEN_FAIL", LOG_ERR);
2154  return -4;
2155  }
2156 
2157  $errorstring = "dol_compress_file error archive->errorCode = ".$archive->errorCode()." errormsg=".$errormsg;
2158  dol_syslog("dol_compress_file failure - ".$errormsg, LOG_ERR);
2159  return -3;
2160  } else {
2161  dol_syslog("dol_compress_file success - ".count($result)." files");
2162  return 1;
2163  }
2164  }
2165  }
2166 
2167  if ($foundhandler) {
2168  $fp = fopen($outputfile, "w");
2169  fwrite($fp, $compressdata);
2170  fclose($fp);
2171  return 1;
2172  } else {
2173  $errorstring = "Try to zip with format ".$mode." with no handler for this format";
2174  dol_syslog($errorstring, LOG_ERR);
2175 
2176  global $errormsg;
2177  $errormsg = $errorstring;
2178  return -2;
2179  }
2180  } catch (Exception $e) {
2181  global $langs, $errormsg;
2182  $langs->load("errors");
2183  $errormsg = $langs->trans("ErrorFailedToWriteInDir");
2184 
2185  $errorstring = "Failed to open file ".$outputfile;
2186  dol_syslog($errorstring, LOG_ERR);
2187  return -1;
2188  }
2189 }
2190 
2199 function dol_uncompress($inputfile, $outputdir)
2200 {
2201  global $conf, $langs, $db;
2202 
2203  $fileinfo = pathinfo($inputfile);
2204  $fileinfo["extension"] = strtolower($fileinfo["extension"]);
2205 
2206  if ($fileinfo["extension"] == "zip") {
2207  if (defined('ODTPHP_PATHTOPCLZIP') && empty($conf->global->MAIN_USE_ZIPARCHIVE_FOR_ZIP_UNCOMPRESS)) {
2208  dol_syslog("Constant ODTPHP_PATHTOPCLZIP for pclzip library is set to ".ODTPHP_PATHTOPCLZIP.", so we use Pclzip to unzip into ".$outputdir);
2209  include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
2210  $archive = new PclZip($inputfile);
2211 
2212  // We create output dir manually, so it uses the correct permission (When created by the archive->extract, dir is rwx for everybody).
2213  dol_mkdir(dol_sanitizePathName($outputdir));
2214 
2215  // Extract into outputdir, but only files that match the regex '/^((?!\.\.).)*$/' that means "does not include .."
2216  $result = $archive->extract(PCLZIP_OPT_PATH, $outputdir, PCLZIP_OPT_BY_PREG, '/^((?!\.\.).)*$/');
2217 
2218  if (!is_array($result) && $result <= 0) {
2219  return array('error'=>$archive->errorInfo(true));
2220  } else {
2221  $ok = 1;
2222  $errmsg = '';
2223  // Loop on each file to check result for unzipping file
2224  foreach ($result as $key => $val) {
2225  if ($val['status'] == 'path_creation_fail') {
2226  $langs->load("errors");
2227  $ok = 0;
2228  $errmsg = $langs->trans("ErrorFailToCreateDir", $val['filename']);
2229  break;
2230  }
2231  }
2232 
2233  if ($ok) {
2234  return array();
2235  } else {
2236  return array('error'=>$errmsg);
2237  }
2238  }
2239  }
2240 
2241  if (class_exists('ZipArchive')) { // Must install php-zip to have it
2242  dol_syslog("Class ZipArchive is set so we unzip using ZipArchive to unzip into ".$outputdir);
2243  $zip = new ZipArchive;
2244  $res = $zip->open($inputfile);
2245  if ($res === true) {
2246  //$zip->extractTo($outputdir.'/');
2247  // We must extract one file at time so we can check that file name does not contains '..' to avoid transversal path of zip built for example using
2248  // python3 path_traversal_archiver.py <Created_file_name> test.zip -l 10 -p tmp/
2249  // with -l is the range of dot to go back in path.
2250  // and path_traversal_archiver.py found at https://github.com/Alamot/code-snippets/blob/master/path_traversal/path_traversal_archiver.py
2251  for ($i = 0; $i < $zip->numFiles; $i++) {
2252  if (preg_match('/\.\./', $zip->getNameIndex($i))) {
2253  dol_syslog("Warning: Try to unzip a file with a transversal path ".$zip->getNameIndex($i), LOG_WARNING);
2254  continue; // Discard the file
2255  }
2256  $zip->extractTo($outputdir.'/', array($zip->getNameIndex($i)));
2257  }
2258 
2259  $zip->close();
2260  return array();
2261  } else {
2262  return array('error'=>'ErrUnzipFails');
2263  }
2264  }
2265 
2266  return array('error'=>'ErrNoZipEngine');
2267  } elseif (in_array($fileinfo["extension"], array('gz', 'bz2', 'zst'))) {
2268  include_once DOL_DOCUMENT_ROOT."/core/class/utils.class.php";
2269  $utils = new Utils($db);
2270 
2271  dol_mkdir(dol_sanitizePathName($outputdir));
2272  $outputfilename = escapeshellcmd(dol_sanitizePathName($outputdir).'/'.dol_sanitizeFileName($fileinfo["filename"]));
2273  dol_delete_file($outputfilename.'.tmp');
2274  dol_delete_file($outputfilename.'.err');
2275 
2276  $extension = strtolower(pathinfo($fileinfo["filename"], PATHINFO_EXTENSION));
2277  if ($extension == "tar") {
2278  $cmd = 'tar -C '.escapeshellcmd(dol_sanitizePathName($outputdir)).' -xvf '.escapeshellcmd(dol_sanitizePathName($fileinfo["dirname"]).'/'.dol_sanitizeFileName($fileinfo["basename"]));
2279 
2280  $resarray = $utils->executeCLI($cmd, $outputfilename.'.tmp', 0, $outputfilename.'.err', 0);
2281  if ($resarray["result"] != 0) {
2282  $resarray["error"] .= file_get_contents($outputfilename.'.err');
2283  }
2284  } else {
2285  $program = "";
2286  if ($fileinfo["extension"] == "gz") {
2287  $program = 'gzip';
2288  } elseif ($fileinfo["extension"] == "bz2") {
2289  $program = 'bzip2';
2290  } elseif ($fileinfo["extension"] == "zst") {
2291  $program = 'zstd';
2292  } else {
2293  return array('error'=>'ErrorBadFileExtension');
2294  }
2295  $cmd = $program.' -dc '.escapeshellcmd(dol_sanitizePathName($fileinfo["dirname"]).'/'.dol_sanitizeFileName($fileinfo["basename"]));
2296  $cmd .= ' > '.$outputfilename;
2297 
2298  $resarray = $utils->executeCLI($cmd, $outputfilename.'.tmp', 0, null, 1, $outputfilename.'.err');
2299  if ($resarray["result"] != 0) {
2300  $errfilecontent = @file_get_contents($outputfilename.'.err');
2301  if ($errfilecontent) {
2302  $resarray["error"] .= " - ".$errfilecontent;
2303  }
2304  }
2305  }
2306  return $resarray["result"] != 0 ? array('error' => $resarray["error"]) : array();
2307  }
2308 
2309  return array('error'=>'ErrorBadFileExtension');
2310 }
2311 
2312 
2325 function dol_compress_dir($inputdir, $outputfile, $mode = "zip", $excludefiles = '', $rootdirinzip = '', $newmask = 0)
2326 {
2327  global $conf;
2328 
2329  $foundhandler = 0;
2330 
2331  dol_syslog("Try to zip dir ".$inputdir." into ".$outputfile." mode=".$mode);
2332 
2333  if (!dol_is_dir(dirname($outputfile)) || !is_writable(dirname($outputfile))) {
2334  global $langs, $errormsg;
2335  $langs->load("errors");
2336  $errormsg = $langs->trans("ErrorFailedToWriteInDir", $outputfile);
2337  return -3;
2338  }
2339 
2340  try {
2341  if ($mode == 'gz') {
2342  $foundhandler = 0;
2343  } elseif ($mode == 'bz') {
2344  $foundhandler = 0;
2345  } elseif ($mode == 'zip') {
2346  /*if (defined('ODTPHP_PATHTOPCLZIP'))
2347  {
2348  $foundhandler=0; // TODO implement this
2349 
2350  include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
2351  $archive = new PclZip($outputfile);
2352  $archive->add($inputfile, PCLZIP_OPT_REMOVE_PATH, dirname($inputfile));
2353  //$archive->add($inputfile);
2354  return 1;
2355  }
2356  else*/
2357  //if (class_exists('ZipArchive') && !empty($conf->global->MAIN_USE_ZIPARCHIVE_FOR_ZIP_COMPRESS))
2358 
2359  if (class_exists('ZipArchive')) {
2360  $foundhandler = 1;
2361 
2362  // Initialize archive object
2363  $zip = new ZipArchive();
2364  $result = $zip->open($outputfile, ZipArchive::CREATE | ZipArchive::OVERWRITE);
2365  if (!$result) {
2366  global $langs, $errormsg;
2367  $langs->load("errors");
2368  $errormsg = $langs->trans("ErrorFailedToWriteInFile", $outputfile);
2369  return -4;
2370  }
2371 
2372  // Create recursive directory iterator
2373  // This does not return symbolic links
2375  $files = new RecursiveIteratorIterator(
2376  new RecursiveDirectoryIterator($inputdir),
2377  RecursiveIteratorIterator::LEAVES_ONLY
2378  );
2379 
2380  //var_dump($inputdir);
2381  foreach ($files as $name => $file) {
2382  // Skip directories (they would be added automatically)
2383  if (!$file->isDir()) {
2384  // Get real and relative path for current file
2385  $filePath = $file->getPath(); // the full path with filename using the $inputdir root.
2386  $fileName = $file->getFilename();
2387  $fileFullRealPath = $file->getRealPath(); // the full path with name and transformed to use real path directory.
2388 
2389  //$relativePath = ($rootdirinzip ? $rootdirinzip.'/' : '').substr($fileFullRealPath, strlen($inputdir) + 1);
2390  $relativePath = ($rootdirinzip ? $rootdirinzip.'/' : '').substr(($filePath ? $filePath.'/' : '').$fileName, strlen($inputdir) + 1);
2391 
2392  //var_dump($filePath);var_dump($fileFullRealPath);var_dump($relativePath);
2393  if (empty($excludefiles) || !preg_match($excludefiles, $fileFullRealPath)) {
2394  // Add current file to archive
2395  $zip->addFile($fileFullRealPath, $relativePath);
2396  }
2397  }
2398  }
2399 
2400  // Zip archive will be created only after closing object
2401  $zip->close();
2402 
2403  if (empty($newmask) && !empty($conf->global->MAIN_UMASK)) {
2404  $newmask = $conf->global->MAIN_UMASK;
2405  }
2406  if (empty($newmask)) { // This should no happen
2407  dol_syslog("Warning: dol_copy called with empty value for newmask and no default value defined", LOG_WARNING);
2408  $newmask = '0664';
2409  }
2410 
2411  dolChmod($outputfile, $newmask);
2412 
2413  return 1;
2414  }
2415  }
2416 
2417  if (!$foundhandler) {
2418  dol_syslog("Try to zip with format ".$mode." with no handler for this format", LOG_ERR);
2419  return -2;
2420  } else {
2421  return 0;
2422  }
2423  } catch (Exception $e) {
2424  global $langs, $errormsg;
2425  $langs->load("errors");
2426  dol_syslog("Failed to open file ".$outputfile, LOG_ERR);
2427  dol_syslog($e->getMessage(), LOG_ERR);
2428  $errormsg = $langs->trans("ErrorFailedToBuildArchive", $outputfile).' - '.$e->getMessage();
2429  return -1;
2430  }
2431 }
2432 
2433 
2434 
2445 function dol_most_recent_file($dir, $regexfilter = '', $excludefilter = array('(\.meta|_preview.*\.png)$', '^\.'), $nohook = false, $mode = '')
2446 {
2447  $tmparray = dol_dir_list($dir, 'files', 0, $regexfilter, $excludefilter, 'date', SORT_DESC, $mode, $nohook);
2448  return isset($tmparray[0])?$tmparray[0]:null;
2449 }
2450 
2464 function dol_check_secure_access_document($modulepart, $original_file, $entity, $fuser = '', $refname = '', $mode = 'read')
2465 {
2466  global $conf, $db, $user, $hookmanager;
2467  global $dolibarr_main_data_root, $dolibarr_main_document_root_alt;
2468  global $object;
2469 
2470  if (!is_object($fuser)) {
2471  $fuser = $user;
2472  }
2473 
2474  if (empty($modulepart)) {
2475  return 'ErrorBadParameter';
2476  }
2477  if (empty($entity)) {
2478  if (!isModEnabled('multicompany')) {
2479  $entity = 1;
2480  } else {
2481  $entity = 0;
2482  }
2483  }
2484  // Fix modulepart for backward compatibility
2485  if ($modulepart == 'users') {
2486  $modulepart = 'user';
2487  }
2488  if ($modulepart == 'tva') {
2489  $modulepart = 'tax-vat';
2490  }
2491 
2492  //print 'dol_check_secure_access_document modulepart='.$modulepart.' original_file='.$original_file.' entity='.$entity;
2493  dol_syslog('dol_check_secure_access_document modulepart='.$modulepart.' original_file='.$original_file.' entity='.$entity);
2494 
2495  // We define $accessallowed and $sqlprotectagainstexternals
2496  $accessallowed = 0;
2497  $sqlprotectagainstexternals = '';
2498  $ret = array();
2499 
2500  // Find the subdirectory name as the reference. For example original_file='10/myfile.pdf' -> refname='10'
2501  if (empty($refname)) {
2502  $refname = basename(dirname($original_file)."/");
2503  if ($refname == 'thumbs') {
2504  // If we get the thumbs directory, we must go one step higher. For example original_file='10/thumbs/myfile_small.jpg' -> refname='10'
2505  $refname = basename(dirname(dirname($original_file))."/");
2506  }
2507  }
2508 
2509  // Define possible keys to use for permission check
2510  $lire = 'lire';
2511  $read = 'read';
2512  $download = 'download';
2513  if ($mode == 'write') {
2514  $lire = 'creer';
2515  $read = 'write';
2516  $download = 'upload';
2517  }
2518 
2519  // Wrapping for miscellaneous medias files
2520  if ($modulepart == 'medias' && !empty($dolibarr_main_data_root)) {
2521  if (empty($entity) || empty($conf->medias->multidir_output[$entity])) {
2522  return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
2523  }
2524  $accessallowed = 1;
2525  $original_file = $conf->medias->multidir_output[$entity].'/'.$original_file;
2526  } elseif ($modulepart == 'logs' && !empty($dolibarr_main_data_root)) {
2527  // Wrapping for *.log files, like when used with url http://.../document.php?modulepart=logs&file=dolibarr.log
2528  $accessallowed = ($user->admin && basename($original_file) == $original_file && preg_match('/^dolibarr.*\.log$/', basename($original_file)));
2529  $original_file = $dolibarr_main_data_root.'/'.$original_file;
2530  } elseif ($modulepart == 'doctemplates' && !empty($dolibarr_main_data_root)) {
2531  // Wrapping for doctemplates
2532  $accessallowed = $user->admin;
2533  $original_file = $dolibarr_main_data_root.'/doctemplates/'.$original_file;
2534  } elseif ($modulepart == 'doctemplateswebsite' && !empty($dolibarr_main_data_root)) {
2535  // Wrapping for doctemplates of websites
2536  $accessallowed = ($fuser->rights->website->write && preg_match('/\.jpg$/i', basename($original_file)));
2537  $original_file = $dolibarr_main_data_root.'/doctemplates/websites/'.$original_file;
2538  } elseif ($modulepart == 'packages' && !empty($dolibarr_main_data_root)) {
2539  // Wrapping for *.zip package files, like when used with url http://.../document.php?modulepart=packages&file=module_myfile.zip
2540  // Dir for custom dirs
2541  $tmp = explode(',', $dolibarr_main_document_root_alt);
2542  $dirins = $tmp[0];
2543 
2544  $accessallowed = ($user->admin && preg_match('/^module_.*\.zip$/', basename($original_file)));
2545  $original_file = $dirins.'/'.$original_file;
2546  } elseif ($modulepart == 'mycompany' && !empty($conf->mycompany->dir_output)) {
2547  // Wrapping for some images
2548  $accessallowed = 1;
2549  $original_file = $conf->mycompany->dir_output.'/'.$original_file;
2550  } elseif ($modulepart == 'userphoto' && !empty($conf->user->dir_output)) {
2551  // Wrapping for users photos (user photos are allowed to any connected users)
2552  $accessallowed = 0;
2553  if (preg_match('/^\d+\/photos\//', $original_file)) {
2554  $accessallowed = 1;
2555  }
2556  $original_file = $conf->user->dir_output.'/'.$original_file;
2557  } elseif ($modulepart == 'userphotopublic' && !empty($conf->user->dir_output)) {
2558  // Wrapping for users photos that were set to public by their owner (public user photos can be read with the public link and securekey)
2559  $accessok = false;
2560  $reg = array();
2561  if (preg_match('/^(\d+)\/photos\//', $original_file, $reg)) {
2562  if ($reg[0]) {
2563  $tmpobject = new User($db);
2564  $tmpobject->fetch($reg[0], '', '', 1);
2565  if (getDolUserInt('USER_ENABLE_PUBLIC', 0, $tmpobject)) {
2566  $securekey = GETPOST('securekey', 'alpha', 1);
2567  // Security check
2568  global $dolibarr_main_instance_unique_id;
2569  $encodedsecurekey = dol_hash($dolibarr_main_instance_unique_id.'uservirtualcard'.$tmpobject->id.'-'.$tmpobject->login, 'md5');
2570  if ($encodedsecurekey == $securekey) {
2571  $accessok = true;
2572  }
2573  }
2574  }
2575  }
2576  if ($accessok) {
2577  $accessallowed = 1;
2578  }
2579  $original_file = $conf->user->dir_output.'/'.$original_file;
2580  } elseif (($modulepart == 'companylogo') && !empty($conf->mycompany->dir_output)) {
2581  // Wrapping for company logos (company logos are allowed to anyboby, they are public)
2582  $accessallowed = 1;
2583  $original_file = $conf->mycompany->dir_output.'/logos/'.$original_file;
2584  } elseif ($modulepart == 'memberphoto' && !empty($conf->adherent->dir_output)) {
2585  // Wrapping for members photos
2586  $accessallowed = 0;
2587  if (preg_match('/^\d+\/photos\//', $original_file)) {
2588  $accessallowed = 1;
2589  }
2590  $original_file = $conf->adherent->dir_output.'/'.$original_file;
2591  } elseif ($modulepart == 'apercufacture' && !empty($conf->facture->multidir_output[$entity])) {
2592  // Wrapping for invoices (user need permission to read invoices)
2593  if ($fuser->hasRight('facture', $lire)) {
2594  $accessallowed = 1;
2595  }
2596  $original_file = $conf->facture->multidir_output[$entity].'/'.$original_file;
2597  } elseif ($modulepart == 'apercupropal' && !empty($conf->propal->multidir_output[$entity])) {
2598  // Wrapping pour les apercu propal
2599  if ($fuser->hasRight('propal', $lire)) {
2600  $accessallowed = 1;
2601  }
2602  $original_file = $conf->propal->multidir_output[$entity].'/'.$original_file;
2603  } elseif ($modulepart == 'apercucommande' && !empty($conf->commande->multidir_output[$entity])) {
2604  // Wrapping pour les apercu commande
2605  if ($fuser->hasRight('commande', $lire)) {
2606  $accessallowed = 1;
2607  }
2608  $original_file = $conf->commande->multidir_output[$entity].'/'.$original_file;
2609  } elseif (($modulepart == 'apercufichinter' || $modulepart == 'apercuficheinter') && !empty($conf->ficheinter->dir_output)) {
2610  // Wrapping pour les apercu intervention
2611  if ($fuser->hasRight('ficheinter', $lire)) {
2612  $accessallowed = 1;
2613  }
2614  $original_file = $conf->ficheinter->dir_output.'/'.$original_file;
2615  } elseif (($modulepart == 'apercucontract') && !empty($conf->contrat->multidir_output[$entity])) {
2616  // Wrapping pour les apercu contrat
2617  if ($fuser->hasRight('contrat', $lire)) {
2618  $accessallowed = 1;
2619  }
2620  $original_file = $conf->contrat->multidir_output[$entity].'/'.$original_file;
2621  } elseif (($modulepart == 'apercusupplier_proposal' || $modulepart == 'apercusupplier_proposal') && !empty($conf->supplier_proposal->dir_output)) {
2622  // Wrapping pour les apercu supplier proposal
2623  if ($fuser->hasRight('supplier_proposal', $lire)) {
2624  $accessallowed = 1;
2625  }
2626  $original_file = $conf->supplier_proposal->dir_output.'/'.$original_file;
2627  } elseif (($modulepart == 'apercusupplier_order' || $modulepart == 'apercusupplier_order') && !empty($conf->fournisseur->commande->dir_output)) {
2628  // Wrapping pour les apercu supplier order
2629  if ($fuser->hasRight('fournisseur', 'commande', $lire)) {
2630  $accessallowed = 1;
2631  }
2632  $original_file = $conf->fournisseur->commande->dir_output.'/'.$original_file;
2633  } elseif (($modulepart == 'apercusupplier_invoice' || $modulepart == 'apercusupplier_invoice') && !empty($conf->fournisseur->facture->dir_output)) {
2634  // Wrapping pour les apercu supplier invoice
2635  if ($fuser->hasRight('fournisseur', $lire)) {
2636  $accessallowed = 1;
2637  }
2638  $original_file = $conf->fournisseur->facture->dir_output.'/'.$original_file;
2639  } elseif (($modulepart == 'holiday') && !empty($conf->holiday->dir_output)) {
2640  if ($fuser->hasRight('holiday', $read) || !empty($fuser->rights->holiday->readall) || preg_match('/^specimen/i', $original_file)) {
2641  $accessallowed = 1;
2642  // If we known $id of holiday, call checkUserAccessToObject to check permission on properties and hierarchy of leave request
2643  if ($refname && empty($fuser->rights->holiday->readall) && !preg_match('/^specimen/i', $original_file)) {
2644  include_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
2645  $tmpholiday = new Holiday($db);
2646  $tmpholiday->fetch('', $refname);
2647  $accessallowed = checkUserAccessToObject($user, array('holiday'), $tmpholiday, 'holiday', '', '', 'rowid', '');
2648  }
2649  }
2650  $original_file = $conf->holiday->dir_output.'/'.$original_file;
2651  } elseif (($modulepart == 'expensereport') && !empty($conf->expensereport->dir_output)) {
2652  if ($fuser->hasRight('expensereport', $lire) || !empty($fuser->rights->expensereport->readall) || preg_match('/^specimen/i', $original_file)) {
2653  $accessallowed = 1;
2654  // If we known $id of expensereport, call checkUserAccessToObject to check permission on properties and hierarchy of expense report
2655  if ($refname && empty($fuser->rights->expensereport->readall) && !preg_match('/^specimen/i', $original_file)) {
2656  include_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
2657  $tmpexpensereport = new ExpenseReport($db);
2658  $tmpexpensereport->fetch('', $refname);
2659  $accessallowed = checkUserAccessToObject($user, array('expensereport'), $tmpexpensereport, 'expensereport', '', '', 'rowid', '');
2660  }
2661  }
2662  $original_file = $conf->expensereport->dir_output.'/'.$original_file;
2663  } elseif (($modulepart == 'apercuexpensereport') && !empty($conf->expensereport->dir_output)) {
2664  // Wrapping pour les apercu expense report
2665  if ($fuser->hasRight('expensereport', $lire)) {
2666  $accessallowed = 1;
2667  }
2668  $original_file = $conf->expensereport->dir_output.'/'.$original_file;
2669  } elseif ($modulepart == 'propalstats' && !empty($conf->propal->multidir_temp[$entity])) {
2670  // Wrapping pour les images des stats propales
2671  if ($fuser->hasRight('propal', $lire)) {
2672  $accessallowed = 1;
2673  }
2674  $original_file = $conf->propal->multidir_temp[$entity].'/'.$original_file;
2675  } elseif ($modulepart == 'orderstats' && !empty($conf->commande->dir_temp)) {
2676  // Wrapping pour les images des stats commandes
2677  if ($fuser->hasRight('commande', $lire)) {
2678  $accessallowed = 1;
2679  }
2680  $original_file = $conf->commande->dir_temp.'/'.$original_file;
2681  } elseif ($modulepart == 'orderstatssupplier' && !empty($conf->fournisseur->dir_output)) {
2682  if ($fuser->hasRight('fournisseur', 'commande', $lire)) {
2683  $accessallowed = 1;
2684  }
2685  $original_file = $conf->fournisseur->commande->dir_temp.'/'.$original_file;
2686  } elseif ($modulepart == 'billstats' && !empty($conf->facture->dir_temp)) {
2687  // Wrapping pour les images des stats factures
2688  if ($fuser->hasRight('facture', $lire)) {
2689  $accessallowed = 1;
2690  }
2691  $original_file = $conf->facture->dir_temp.'/'.$original_file;
2692  } elseif ($modulepart == 'billstatssupplier' && !empty($conf->fournisseur->dir_output)) {
2693  if ($fuser->hasRight('fournisseur', 'facture', $lire)) {
2694  $accessallowed = 1;
2695  }
2696  $original_file = $conf->fournisseur->facture->dir_temp.'/'.$original_file;
2697  } elseif ($modulepart == 'expeditionstats' && !empty($conf->expedition->dir_temp)) {
2698  // Wrapping pour les images des stats expeditions
2699  if ($fuser->hasRight('expedition', $lire)) {
2700  $accessallowed = 1;
2701  }
2702  $original_file = $conf->expedition->dir_temp.'/'.$original_file;
2703  } elseif ($modulepart == 'tripsexpensesstats' && !empty($conf->deplacement->dir_temp)) {
2704  // Wrapping pour les images des stats expeditions
2705  if ($fuser->hasRight('deplacement', $lire)) {
2706  $accessallowed = 1;
2707  }
2708  $original_file = $conf->deplacement->dir_temp.'/'.$original_file;
2709  } elseif ($modulepart == 'memberstats' && !empty($conf->adherent->dir_temp)) {
2710  // Wrapping pour les images des stats expeditions
2711  if ($fuser->hasRight('adherent', $lire)) {
2712  $accessallowed = 1;
2713  }
2714  $original_file = $conf->adherent->dir_temp.'/'.$original_file;
2715  } elseif (preg_match('/^productstats_/i', $modulepart) && !empty($conf->product->dir_temp)) {
2716  // Wrapping pour les images des stats produits
2717  if ($fuser->hasRight('produit', $lire) || $fuser->hasRight('service', $lire)) {
2718  $accessallowed = 1;
2719  }
2720  $original_file = (!empty($conf->product->multidir_temp[$entity]) ? $conf->product->multidir_temp[$entity] : $conf->service->multidir_temp[$entity]).'/'.$original_file;
2721  } elseif (in_array($modulepart, array('tax', 'tax-vat', 'tva')) && !empty($conf->tax->dir_output)) {
2722  // Wrapping for taxes
2723  if ($fuser->hasRight('tax', 'charges', $lire)) {
2724  $accessallowed = 1;
2725  }
2726  $modulepartsuffix = str_replace('tax-', '', $modulepart);
2727  $original_file = $conf->tax->dir_output.'/'.($modulepartsuffix != 'tax' ? $modulepartsuffix.'/' : '').$original_file;
2728  } elseif ($modulepart == 'actions' && !empty($conf->agenda->dir_output)) {
2729  // Wrapping for events
2730  if ($fuser->hasRight('agenda', 'myactions', $read)) {
2731  $accessallowed = 1;
2732  // If we known $id of project, call checkUserAccessToObject to check permission on the given agenda event on properties and assigned users
2733  if ($refname && !preg_match('/^specimen/i', $original_file)) {
2734  include_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
2735  $tmpobject = new ActionComm($db);
2736  $tmpobject->fetch((int) $refname);
2737  $accessallowed = checkUserAccessToObject($user, array('agenda'), $tmpobject->id, 'actioncomm&societe', 'myactions|allactions', 'fk_soc', 'id', '');
2738  if ($user->socid && $tmpobject->socid) {
2739  $accessallowed = checkUserAccessToObject($user, array('societe'), $tmpobject->socid);
2740  }
2741  }
2742  }
2743  $original_file = $conf->agenda->dir_output.'/'.$original_file;
2744  } elseif ($modulepart == 'category' && !empty($conf->categorie->multidir_output[$entity])) {
2745  // Wrapping for categories (categories are allowed if user has permission to read categories or to work on TakePos)
2746  if (empty($entity) || empty($conf->categorie->multidir_output[$entity])) {
2747  return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
2748  }
2749  if ($fuser->hasRight("categorie", $lire) || $fuser->hasRight("takepos", "run")) {
2750  $accessallowed = 1;
2751  }
2752  $original_file = $conf->categorie->multidir_output[$entity].'/'.$original_file;
2753  } elseif ($modulepart == 'prelevement' && !empty($conf->prelevement->dir_output)) {
2754  // Wrapping pour les prelevements
2755  if ($fuser->rights->prelevement->bons->{$lire} || preg_match('/^specimen/i', $original_file)) {
2756  $accessallowed = 1;
2757  }
2758  $original_file = $conf->prelevement->dir_output.'/'.$original_file;
2759  } elseif ($modulepart == 'graph_stock' && !empty($conf->stock->dir_temp)) {
2760  // Wrapping pour les graph energie
2761  $accessallowed = 1;
2762  $original_file = $conf->stock->dir_temp.'/'.$original_file;
2763  } elseif ($modulepart == 'graph_fourn' && !empty($conf->fournisseur->dir_temp)) {
2764  // Wrapping pour les graph fournisseurs
2765  $accessallowed = 1;
2766  $original_file = $conf->fournisseur->dir_temp.'/'.$original_file;
2767  } elseif ($modulepart == 'graph_product' && !empty($conf->product->dir_temp)) {
2768  // Wrapping pour les graph des produits
2769  $accessallowed = 1;
2770  $original_file = $conf->product->multidir_temp[$entity].'/'.$original_file;
2771  } elseif ($modulepart == 'barcode') {
2772  // Wrapping pour les code barre
2773  $accessallowed = 1;
2774  // If viewimage is called for barcode, we try to output an image on the fly, with no build of file on disk.
2775  //$original_file=$conf->barcode->dir_temp.'/'.$original_file;
2776  $original_file = '';
2777  } elseif ($modulepart == 'iconmailing' && !empty($conf->mailing->dir_temp)) {
2778  // Wrapping pour les icones de background des mailings
2779  $accessallowed = 1;
2780  $original_file = $conf->mailing->dir_temp.'/'.$original_file;
2781  } elseif ($modulepart == 'scanner_user_temp' && !empty($conf->scanner->dir_temp)) {
2782  // Wrapping pour le scanner
2783  $accessallowed = 1;
2784  $original_file = $conf->scanner->dir_temp.'/'.$fuser->id.'/'.$original_file;
2785  } elseif ($modulepart == 'fckeditor' && !empty($conf->fckeditor->dir_output)) {
2786  // Wrapping pour les images fckeditor
2787  $accessallowed = 1;
2788  $original_file = $conf->fckeditor->dir_output.'/'.$original_file;
2789  } elseif ($modulepart == 'user' && !empty($conf->user->dir_output)) {
2790  // Wrapping for users
2791  $canreaduser = (!empty($fuser->admin) || $fuser->rights->user->user->{$lire});
2792  if ($fuser->id == (int) $refname) {
2793  $canreaduser = 1;
2794  } // A user can always read its own card
2795  if ($canreaduser || preg_match('/^specimen/i', $original_file)) {
2796  $accessallowed = 1;
2797  }
2798  $original_file = $conf->user->dir_output.'/'.$original_file;
2799  } elseif (($modulepart == 'company' || $modulepart == 'societe' || $modulepart == 'thirdparty') && !empty($conf->societe->multidir_output[$entity])) {
2800  // Wrapping for third parties
2801  if (empty($entity) || empty($conf->societe->multidir_output[$entity])) {
2802  return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
2803  }
2804  if ($fuser->rights->societe->{$lire} || preg_match('/^specimen/i', $original_file)) {
2805  $accessallowed = 1;
2806  }
2807  $original_file = $conf->societe->multidir_output[$entity].'/'.$original_file;
2808  $sqlprotectagainstexternals = "SELECT rowid as fk_soc FROM ".MAIN_DB_PREFIX."societe WHERE rowid='".$db->escape($refname)."' AND entity IN (".getEntity('societe').")";
2809  } elseif ($modulepart == 'contact' && !empty($conf->societe->multidir_output[$entity])) {
2810  // Wrapping for contact
2811  if (empty($entity) || empty($conf->societe->multidir_output[$entity])) {
2812  return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
2813  }
2814  if ($fuser->hasRight('societe', $lire)) {
2815  $accessallowed = 1;
2816  }
2817  $original_file = $conf->societe->multidir_output[$entity].'/contact/'.$original_file;
2818  } elseif (($modulepart == 'facture' || $modulepart == 'invoice') && !empty($conf->facture->multidir_output[$entity])) {
2819  // Wrapping for invoices
2820  if ($fuser->hasRight('facture', $lire) || preg_match('/^specimen/i', $original_file)) {
2821  $accessallowed = 1;
2822  }
2823  $original_file = $conf->facture->multidir_output[$entity].'/'.$original_file;
2824  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('invoice').")";
2825  } elseif ($modulepart == 'massfilesarea_proposals' && !empty($conf->propal->multidir_output[$entity])) {
2826  // Wrapping for mass actions
2827  if ($fuser->hasRight('propal', $lire) || preg_match('/^specimen/i', $original_file)) {
2828  $accessallowed = 1;
2829  }
2830  $original_file = $conf->propal->multidir_output[$entity].'/temp/massgeneration/'.$user->id.'/'.$original_file;
2831  } elseif ($modulepart == 'massfilesarea_orders') {
2832  if ($fuser->hasRight('commande', $lire) || preg_match('/^specimen/i', $original_file)) {
2833  $accessallowed = 1;
2834  }
2835  $original_file = $conf->commande->multidir_output[$entity].'/temp/massgeneration/'.$user->id.'/'.$original_file;
2836  } elseif ($modulepart == 'massfilesarea_sendings') {
2837  if ($fuser->hasRight('expedition', $lire) || preg_match('/^specimen/i', $original_file)) {
2838  $accessallowed = 1;
2839  }
2840  $original_file = $conf->expedition->dir_output.'/sending/temp/massgeneration/'.$user->id.'/'.$original_file;
2841  } elseif ($modulepart == 'massfilesarea_invoices') {
2842  if ($fuser->hasRight('facture', $lire) || preg_match('/^specimen/i', $original_file)) {
2843  $accessallowed = 1;
2844  }
2845  $original_file = $conf->facture->multidir_output[$entity].'/temp/massgeneration/'.$user->id.'/'.$original_file;
2846  } elseif ($modulepart == 'massfilesarea_expensereport') {
2847  if ($fuser->hasRight('facture', $lire) || preg_match('/^specimen/i', $original_file)) {
2848  $accessallowed = 1;
2849  }
2850  $original_file = $conf->expensereport->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2851  } elseif ($modulepart == 'massfilesarea_interventions') {
2852  if ($fuser->hasRight('ficheinter', $lire) || preg_match('/^specimen/i', $original_file)) {
2853  $accessallowed = 1;
2854  }
2855  $original_file = $conf->ficheinter->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2856  } elseif ($modulepart == 'massfilesarea_supplier_proposal' && !empty($conf->supplier_proposal->dir_output)) {
2857  if ($fuser->hasRight('supplier_proposal', $lire) || preg_match('/^specimen/i', $original_file)) {
2858  $accessallowed = 1;
2859  }
2860  $original_file = $conf->supplier_proposal->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2861  } elseif ($modulepart == 'massfilesarea_supplier_order') {
2862  if ($fuser->hasRight('fournisseur', 'commande', $lire) || preg_match('/^specimen/i', $original_file)) {
2863  $accessallowed = 1;
2864  }
2865  $original_file = $conf->fournisseur->commande->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2866  } elseif ($modulepart == 'massfilesarea_supplier_invoice') {
2867  if ($fuser->hasRight('fournisseur', 'facture', $lire) || preg_match('/^specimen/i', $original_file)) {
2868  $accessallowed = 1;
2869  }
2870  $original_file = $conf->fournisseur->facture->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2871  } elseif ($modulepart == 'massfilesarea_contract' && !empty($conf->contrat->dir_output)) {
2872  if ($fuser->hasRight('contrat', $lire) || preg_match('/^specimen/i', $original_file)) {
2873  $accessallowed = 1;
2874  }
2875  $original_file = $conf->contrat->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2876  } elseif (($modulepart == 'fichinter' || $modulepart == 'ficheinter') && !empty($conf->ficheinter->dir_output)) {
2877  // Wrapping for interventions
2878  if ($fuser->hasRight('ficheinter', $lire) || preg_match('/^specimen/i', $original_file)) {
2879  $accessallowed = 1;
2880  }
2881  $original_file = $conf->ficheinter->dir_output.'/'.$original_file;
2882  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2883  } elseif ($modulepart == 'deplacement' && !empty($conf->deplacement->dir_output)) {
2884  // Wrapping pour les deplacements et notes de frais
2885  if ($fuser->hasRight('deplacement', $lire) || preg_match('/^specimen/i', $original_file)) {
2886  $accessallowed = 1;
2887  }
2888  $original_file = $conf->deplacement->dir_output.'/'.$original_file;
2889  //$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2890  } elseif (($modulepart == 'propal' || $modulepart == 'propale') && isset($conf->propal->multidir_output[$entity])) {
2891  // Wrapping pour les propales
2892  if ($fuser->hasRight('propal', $lire) || preg_match('/^specimen/i', $original_file)) {
2893  $accessallowed = 1;
2894  }
2895  $original_file = $conf->propal->multidir_output[$entity].'/'.$original_file;
2896  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."propal WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('propal').")";
2897  } elseif (($modulepart == 'commande' || $modulepart == 'order') && !empty($conf->commande->multidir_output[$entity])) {
2898  // Wrapping pour les commandes
2899  if ($fuser->rights->commande->{$lire} || preg_match('/^specimen/i', $original_file)) {
2900  $accessallowed = 1;
2901  }
2902  $original_file = $conf->commande->multidir_output[$entity].'/'.$original_file;
2903  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('order').")";
2904  } elseif ($modulepart == 'project' && !empty($conf->project->dir_output)) {
2905  // Wrapping pour les projets
2906  if ($fuser->hasRight('projet', $lire) || preg_match('/^specimen/i', $original_file)) {
2907  $accessallowed = 1;
2908  // If we known $id of project, call checkUserAccessToObject to check permission on properties and contact of project
2909  if ($refname && !preg_match('/^specimen/i', $original_file)) {
2910  include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
2911  $tmpproject = new Project($db);
2912  $tmpproject->fetch('', $refname);
2913  $accessallowed = checkUserAccessToObject($user, array('projet'), $tmpproject->id, 'projet&project', '', '', 'rowid', '');
2914  }
2915  }
2916  $original_file = $conf->project->dir_output.'/'.$original_file;
2917  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project').")";
2918  } elseif ($modulepart == 'project_task' && !empty($conf->project->dir_output)) {
2919  if ($fuser->hasRight('projet', $lire) || preg_match('/^specimen/i', $original_file)) {
2920  $accessallowed = 1;
2921  // If we known $id of project, call checkUserAccessToObject to check permission on properties and contact of project
2922  if ($refname && !preg_match('/^specimen/i', $original_file)) {
2923  include_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
2924  $tmptask = new Task($db);
2925  $tmptask->fetch('', $refname);
2926  $accessallowed = checkUserAccessToObject($user, array('projet_task'), $tmptask->id, 'projet_task&project', '', '', 'rowid', '');
2927  }
2928  }
2929  $original_file = $conf->project->dir_output.'/'.$original_file;
2930  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project').")";
2931  } elseif (($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') && !empty($conf->fournisseur->commande->dir_output)) {
2932  // Wrapping pour les commandes fournisseurs
2933  if ($fuser->rights->fournisseur->commande->{$lire} || preg_match('/^specimen/i', $original_file)) {
2934  $accessallowed = 1;
2935  }
2936  $original_file = $conf->fournisseur->commande->dir_output.'/'.$original_file;
2937  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande_fournisseur WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2938  } elseif (($modulepart == 'facture_fournisseur' || $modulepart == 'invoice_supplier') && !empty($conf->fournisseur->facture->dir_output)) {
2939  // Wrapping pour les factures fournisseurs
2940  if ($fuser->rights->fournisseur->facture->{$lire} || preg_match('/^specimen/i', $original_file)) {
2941  $accessallowed = 1;
2942  }
2943  $original_file = $conf->fournisseur->facture->dir_output.'/'.$original_file;
2944  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture_fourn WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2945  } elseif ($modulepart == 'supplier_payment') {
2946  // Wrapping pour les rapport de paiements
2947  if ($fuser->rights->fournisseur->facture->{$lire} || preg_match('/^specimen/i', $original_file)) {
2948  $accessallowed = 1;
2949  }
2950  $original_file = $conf->fournisseur->payment->dir_output.'/'.$original_file;
2951  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."paiementfournisseur WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2952  } elseif ($modulepart == 'facture_paiement' && !empty($conf->facture->dir_output)) {
2953  // Wrapping pour les rapport de paiements
2954  if ($fuser->hasRight('facture', $lire) || preg_match('/^specimen/i', $original_file)) {
2955  $accessallowed = 1;
2956  }
2957  if ($fuser->socid > 0) {
2958  $original_file = $conf->facture->dir_output.'/payments/private/'.$fuser->id.'/'.$original_file;
2959  } else {
2960  $original_file = $conf->facture->dir_output.'/payments/'.$original_file;
2961  }
2962  } elseif ($modulepart == 'export_compta' && !empty($conf->accounting->dir_output)) {
2963  // Wrapping for accounting exports
2964  if ($fuser->rights->accounting->bind->write || preg_match('/^specimen/i', $original_file)) {
2965  $accessallowed = 1;
2966  }
2967  $original_file = $conf->accounting->dir_output.'/'.$original_file;
2968  } elseif (($modulepart == 'expedition' || $modulepart == 'shipment') && !empty($conf->expedition->dir_output)) {
2969  // Wrapping pour les expedition
2970  if ($fuser->hasRight('expedition', $lire) || preg_match('/^specimen/i', $original_file)) {
2971  $accessallowed = 1;
2972  }
2973  $original_file = $conf->expedition->dir_output."/".(strpos('sending/', $original_file) === 0 ? '' : 'sending/').$original_file;
2974  //$original_file = $conf->expedition->dir_output."/".$original_file;
2975  } elseif (($modulepart == 'livraison' || $modulepart == 'delivery') && !empty($conf->expedition->dir_output)) {
2976  // Delivery Note Wrapping
2977  if ($fuser->hasRight('expedition', 'delivery', $lire) || preg_match('/^specimen/i', $original_file)) {
2978  $accessallowed = 1;
2979  }
2980  $original_file = $conf->expedition->dir_output."/".(strpos('receipt/', $original_file) === 0 ? '' : 'receipt/').$original_file;
2981  } elseif ($modulepart == 'actions' && !empty($conf->agenda->dir_output)) {
2982  // Wrapping pour les actions
2983  if ($fuser->hasRight('agenda', 'myactions', $read) || preg_match('/^specimen/i', $original_file)) {
2984  $accessallowed = 1;
2985  }
2986  $original_file = $conf->agenda->dir_output.'/'.$original_file;
2987  } elseif ($modulepart == 'actionsreport' && !empty($conf->agenda->dir_temp)) {
2988  // Wrapping pour les actions
2989  if ($fuser->hasRight('agenda', 'allactions', $read) || preg_match('/^specimen/i', $original_file)) {
2990  $accessallowed = 1;
2991  }
2992  $original_file = $conf->agenda->dir_temp."/".$original_file;
2993  } elseif ($modulepart == 'product' || $modulepart == 'produit' || $modulepart == 'service' || $modulepart == 'produit|service') {
2994  // Wrapping pour les produits et services
2995  if (empty($entity) || (empty($conf->product->multidir_output[$entity]) && empty($conf->service->multidir_output[$entity]))) {
2996  return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
2997  }
2998  if (($fuser->hasRight('produit', $lire) || $fuser->hasRight('service', $lire)) || preg_match('/^specimen/i', $original_file)) {
2999  $accessallowed = 1;
3000  }
3001  if (isModEnabled("product")) {
3002  $original_file = $conf->product->multidir_output[$entity].'/'.$original_file;
3003  } elseif (isModEnabled("service")) {
3004  $original_file = $conf->service->multidir_output[$entity].'/'.$original_file;
3005  }
3006  } elseif ($modulepart == 'product_batch' || $modulepart == 'produitlot') {
3007  // Wrapping pour les lots produits
3008  if (empty($entity) || (empty($conf->productbatch->multidir_output[$entity]))) {
3009  return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
3010  }
3011  if (($fuser->hasRight('produit', $lire)) || preg_match('/^specimen/i', $original_file)) {
3012  $accessallowed = 1;
3013  }
3014  if (isModEnabled('productbatch')) {
3015  $original_file = $conf->productbatch->multidir_output[$entity].'/'.$original_file;
3016  }
3017  } elseif ($modulepart == 'movement' || $modulepart == 'mouvement') {
3018  // Wrapping for stock movements
3019  if (empty($entity) || empty($conf->stock->multidir_output[$entity])) {
3020  return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
3021  }
3022  if (($fuser->hasRight('stock', $lire) || $fuser->hasRight('stock', 'movement', $lire) || $fuser->hasRight('stock', 'mouvement', $lire)) || preg_match('/^specimen/i', $original_file)) {
3023  $accessallowed = 1;
3024  }
3025  if (isModEnabled('stock')) {
3026  $original_file = $conf->stock->multidir_output[$entity].'/movement/'.$original_file;
3027  }
3028  } elseif ($modulepart == 'contract' && !empty($conf->contrat->multidir_output[$entity])) {
3029  // Wrapping pour les contrats
3030  if ($fuser->rights->contrat->{$lire} || preg_match('/^specimen/i', $original_file)) {
3031  $accessallowed = 1;
3032  }
3033  $original_file = $conf->contrat->multidir_output[$entity].'/'.$original_file;
3034  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."contrat WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('contract').")";
3035  } elseif ($modulepart == 'donation' && !empty($conf->don->dir_output)) {
3036  // Wrapping pour les dons
3037  if ($fuser->hasRight('don', $lire) || preg_match('/^specimen/i', $original_file)) {
3038  $accessallowed = 1;
3039  }
3040  $original_file = $conf->don->dir_output.'/'.$original_file;
3041  } elseif ($modulepart == 'dolresource' && !empty($conf->resource->dir_output)) {
3042  // Wrapping pour les dons
3043  if ($fuser->hasRight('resource', $read) || preg_match('/^specimen/i', $original_file)) {
3044  $accessallowed = 1;
3045  }
3046  $original_file = $conf->resource->dir_output.'/'.$original_file;
3047  } elseif (($modulepart == 'remisecheque' || $modulepart == 'chequereceipt') && !empty($conf->bank->dir_output)) {
3048  // Wrapping pour les remises de cheques
3049  if ($fuser->hasRight('banque', $lire) || preg_match('/^specimen/i', $original_file)) {
3050  $accessallowed = 1;
3051  }
3052 
3053  $original_file = $conf->bank->dir_output.'/checkdeposits/'.$original_file; // original_file should contains relative path so include the get_exdir result
3054  } elseif (($modulepart == 'banque' || $modulepart == 'bank') && !empty($conf->bank->dir_output)) {
3055  // Wrapping for bank
3056  if ($fuser->hasRight('banque', $lire)) {
3057  $accessallowed = 1;
3058  }
3059  $original_file = $conf->bank->dir_output.'/'.$original_file;
3060  } elseif ($modulepart == 'export' && !empty($conf->export->dir_temp)) {
3061  // Wrapping for export module
3062  // Note that a test may not be required because we force the dir of download on the directory of the user that export
3063  $accessallowed = $user->rights->export->lire;
3064  $original_file = $conf->export->dir_temp.'/'.$fuser->id.'/'.$original_file;
3065  } elseif ($modulepart == 'import' && !empty($conf->import->dir_temp)) {
3066  // Wrapping for import module
3067  $accessallowed = $user->rights->import->run;
3068  $original_file = $conf->import->dir_temp.'/'.$original_file;
3069  } elseif ($modulepart == 'recruitment' && !empty($conf->recruitment->dir_output)) {
3070  // Wrapping for recruitment module
3071  $accessallowed = $user->rights->recruitment->recruitmentjobposition->read;
3072  $original_file = $conf->recruitment->dir_output.'/'.$original_file;
3073  } elseif ($modulepart == 'editor' && !empty($conf->fckeditor->dir_output)) {
3074  // Wrapping for wysiwyg editor
3075  $accessallowed = 1;
3076  $original_file = $conf->fckeditor->dir_output.'/'.$original_file;
3077  } elseif ($modulepart == 'systemtools' && !empty($conf->admin->dir_output)) {
3078  // Wrapping for backups
3079  if ($fuser->admin) {
3080  $accessallowed = 1;
3081  }
3082  $original_file = $conf->admin->dir_output.'/'.$original_file;
3083  } elseif ($modulepart == 'admin_temp' && !empty($conf->admin->dir_temp)) {
3084  // Wrapping for upload file test
3085  if ($fuser->admin) {
3086  $accessallowed = 1;
3087  }
3088  $original_file = $conf->admin->dir_temp.'/'.$original_file;
3089  } elseif ($modulepart == 'bittorrent' && !empty($conf->bittorrent->dir_output)) {
3090  // Wrapping pour BitTorrent
3091  $accessallowed = 1;
3092  $dir = 'files';
3093  if (dol_mimetype($original_file) == 'application/x-bittorrent') {
3094  $dir = 'torrents';
3095  }
3096  $original_file = $conf->bittorrent->dir_output.'/'.$dir.'/'.$original_file;
3097  } elseif ($modulepart == 'member' && !empty($conf->adherent->dir_output)) {
3098  // Wrapping pour Foundation module
3099  if ($fuser->hasRight('adherent', $lire) || preg_match('/^specimen/i', $original_file)) {
3100  $accessallowed = 1;
3101  }
3102  $original_file = $conf->adherent->dir_output.'/'.$original_file;
3103  } elseif ($modulepart == 'scanner_user_temp' && !empty($conf->scanner->dir_temp)) {
3104  // Wrapping for Scanner
3105  $accessallowed = 1;
3106  $original_file = $conf->scanner->dir_temp.'/'.$fuser->id.'/'.$original_file;
3107  // If modulepart=module_user_temp Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/temp/iduser
3108  // If modulepart=module_temp Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/temp
3109  // If modulepart=module_user Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/iduser
3110  // If modulepart=module Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart
3111  // If modulepart=module-abc Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart
3112  } else {
3113  // GENERIC Wrapping
3114  //var_dump($modulepart);
3115  //var_dump($original_file);
3116  if (preg_match('/^specimen/i', $original_file)) {
3117  $accessallowed = 1; // If link to a file called specimen. Test must be done before changing $original_file int full path.
3118  }
3119  if ($fuser->admin) {
3120  $accessallowed = 1; // If user is admin
3121  }
3122 
3123  $tmpmodulepart = explode('-', $modulepart);
3124  if (!empty($tmpmodulepart[1])) {
3125  $modulepart = $tmpmodulepart[0];
3126  $original_file = $tmpmodulepart[1].'/'.$original_file;
3127  }
3128 
3129  // Define $accessallowed
3130  $reg = array();
3131  if (preg_match('/^([a-z]+)_user_temp$/i', $modulepart, $reg)) {
3132  if (empty($conf->{$reg[1]}->dir_temp)) { // modulepart not supported
3133  dol_print_error('', 'Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')');
3134  exit;
3135  }
3136  if ($fuser->rights->{$reg[1]}->{$lire} || $fuser->rights->{$reg[1]}->{$read} || ($fuser->rights->{$reg[1]}->{$download})) {
3137  $accessallowed = 1;
3138  }
3139  $original_file = $conf->{$reg[1]}->dir_temp.'/'.$fuser->id.'/'.$original_file;
3140  } elseif (preg_match('/^([a-z]+)_temp$/i', $modulepart, $reg)) {
3141  if (empty($conf->{$reg[1]}->dir_temp)) { // modulepart not supported
3142  dol_print_error('', 'Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')');
3143  exit;
3144  }
3145  if ($fuser->rights->{$reg[1]}->{$lire} || $fuser->rights->{$reg[1]}->{$read} || ($fuser->rights->{$reg[1]}->{$download})) {
3146  $accessallowed = 1;
3147  }
3148  $original_file = $conf->{$reg[1]}->dir_temp.'/'.$original_file;
3149  } elseif (preg_match('/^([a-z]+)_user$/i', $modulepart, $reg)) {
3150  if (empty($conf->{$reg[1]}->dir_output)) { // modulepart not supported
3151  dol_print_error('', 'Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')');
3152  exit;
3153  }
3154  if ($fuser->rights->{$reg[1]}->{$lire} || $fuser->rights->{$reg[1]}->{$read} || ($fuser->rights->{$reg[1]}->{$download})) {
3155  $accessallowed = 1;
3156  }
3157  $original_file = $conf->{$reg[1]}->dir_output.'/'.$fuser->id.'/'.$original_file;
3158  } elseif (preg_match('/^massfilesarea_([a-z]+)$/i', $modulepart, $reg)) {
3159  if (empty($conf->{$reg[1]}->dir_output)) { // modulepart not supported
3160  dol_print_error('', 'Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')');
3161  exit;
3162  }
3163  if ($fuser->rights->{$reg[1]}->{$lire} || preg_match('/^specimen/i', $original_file)) {
3164  $accessallowed = 1;
3165  }
3166  $original_file = $conf->{$reg[1]}->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
3167  } else {
3168  if (empty($conf->$modulepart->dir_output)) { // modulepart not supported
3169  dol_print_error('', 'Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.'). The module for this modulepart value may not be activated.');
3170  exit;
3171  }
3172 
3173  // Check fuser->rights->modulepart->myobject->read and fuser->rights->modulepart->read
3174  $partsofdirinoriginalfile = explode('/', $original_file);
3175  if (!empty($partsofdirinoriginalfile[1])) { // If original_file is xxx/filename (xxx is a part we will use)
3176  $partofdirinoriginalfile = $partsofdirinoriginalfile[0];
3177  if ($partofdirinoriginalfile && !empty($fuser->rights->$modulepart->$partofdirinoriginalfile) && ($fuser->rights->$modulepart->$partofdirinoriginalfile->{$lire} || $fuser->rights->$modulepart->$partofdirinoriginalfile->{$read})) {
3178  $accessallowed = 1;
3179  }
3180  }
3181  if (!empty($fuser->rights->$modulepart->{$lire}) || !empty($fuser->rights->$modulepart->{$read})) {
3182  $accessallowed = 1;
3183  }
3184 
3185  if (is_array($conf->$modulepart->multidir_output) && !empty($conf->$modulepart->multidir_output[$entity])) {
3186  $original_file = $conf->$modulepart->multidir_output[$entity].'/'.$original_file;
3187  } else {
3188  $original_file = $conf->$modulepart->dir_output.'/'.$original_file;
3189  }
3190  }
3191 
3192  $parameters = array(
3193  'modulepart' => $modulepart,
3194  'original_file' => $original_file,
3195  'entity' => $entity,
3196  'fuser' => $fuser,
3197  'refname' => '',
3198  'mode' => $mode
3199  );
3200  $reshook = $hookmanager->executeHooks('checkSecureAccess', $parameters, $object);
3201  if ($reshook > 0) {
3202  if (!empty($hookmanager->resArray['original_file'])) {
3203  $original_file = $hookmanager->resArray['original_file'];
3204  }
3205  if (!empty($hookmanager->resArray['accessallowed'])) {
3206  $accessallowed = $hookmanager->resArray['accessallowed'];
3207  }
3208  if (!empty($hookmanager->resArray['sqlprotectagainstexternals'])) {
3209  $sqlprotectagainstexternals = $hookmanager->resArray['sqlprotectagainstexternals'];
3210  }
3211  }
3212  }
3213 
3214  $ret = array(
3215  'accessallowed' => ($accessallowed ? 1 : 0),
3216  'sqlprotectagainstexternals' => $sqlprotectagainstexternals,
3217  'original_file' => $original_file
3218  );
3219 
3220  return $ret;
3221 }
3222 
3231 function dol_filecache($directory, $filename, $object)
3232 {
3233  if (!dol_is_dir($directory)) {
3234  dol_mkdir($directory);
3235  }
3236  $cachefile = $directory.$filename;
3237  file_put_contents($cachefile, serialize($object), LOCK_EX);
3238  dolChmod($cachefile, '0644');
3239 }
3240 
3249 function dol_cache_refresh($directory, $filename, $cachetime)
3250 {
3251  $now = dol_now();
3252  $cachefile = $directory.$filename;
3253  $refresh = !file_exists($cachefile) || ($now - $cachetime) > dol_filemtime($cachefile);
3254  return $refresh;
3255 }
3256 
3264 function dol_readcachefile($directory, $filename)
3265 {
3266  $cachefile = $directory.$filename;
3267  $object = unserialize(file_get_contents($cachefile));
3268  return $object;
3269 }
3270 
3271 
3283 function getFilesUpdated(&$file_list, SimpleXMLElement $dir, $path = '', $pathref = '', &$checksumconcat = array())
3284 {
3285  global $conffile;
3286 
3287  $exclude = 'install';
3288 
3289  foreach ($dir->md5file as $file) { // $file is a simpleXMLElement
3290  $filename = $path.$file['name'];
3291  $file_list['insignature'][] = $filename;
3292  $expectedsize = (empty($file['size']) ? '' : $file['size']);
3293  $expectedmd5 = (string) $file;
3294 
3295  //if (preg_match('#'.$exclude.'#', $filename)) continue;
3296 
3297  if (!file_exists($pathref.'/'.$filename)) {
3298  $file_list['missing'][] = array('filename'=>$filename, 'expectedmd5'=>$expectedmd5, 'expectedsize'=>$expectedsize);
3299  } else {
3300  $md5_local = md5_file($pathref.'/'.$filename);
3301 
3302  if ($conffile == '/etc/dolibarr/conf.php' && $filename == '/filefunc.inc.php') { // For install with deb or rpm, we ignore test on filefunc.inc.php that was modified by package
3303  $checksumconcat[] = $expectedmd5;
3304  } else {
3305  if ($md5_local != $expectedmd5) {
3306  $file_list['updated'][] = array('filename'=>$filename, 'expectedmd5'=>$expectedmd5, 'expectedsize'=>$expectedsize, 'md5'=>(string) $md5_local);
3307  }
3308  $checksumconcat[] = $md5_local;
3309  }
3310  }
3311  }
3312 
3313  foreach ($dir->dir as $subdir) { // $subdir['name'] is '' or '/accountancy/admin' for example
3314  getFilesUpdated($file_list, $subdir, $path.$subdir['name'].'/', $pathref, $checksumconcat);
3315  }
3316 
3317  return $file_list;
3318 }
dol_move_dir
dol_move_dir($srcdir, $destdir, $overwriteifexists=1, $indexdatabase=1, $renamedircontent=1)
Move a directory into another name.
Definition: files.lib.php:1011
make_substitutions
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
Definition: functions.lib.php:8210
dol_fileperm
dol_fileperm($pathoffile)
Return permissions of a file.
Definition: files.lib.php:609
dol_is_url
dol_is_url($url)
Return if path is an URL.
Definition: files.lib.php:505
dol_sanitizePathName
dol_sanitizePathName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a path name.
Definition: functions.lib.php:1262
dol_basename
dol_basename($pathfile)
Make a basename working with all page code (default PHP basenamed fails with cyrillic).
Definition: files.lib.php:36
dol_sanitizeFileName
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
Definition: functions.lib.php:1236
Project
Class to manage projects.
Definition: project.class.php:35
ActionComm
Class to manage agenda events (actions)
Definition: actioncomm.class.php:38
dol_delete_dir_recursive
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
Definition: files.lib.php:1412
dol_count_nb_of_line
dol_count_nb_of_line($file)
Count number of lines in a file.
Definition: files.lib.php:554
dol_osencode
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
Definition: functions.lib.php:8875
dol_filemtime
dol_filemtime($pathoffile)
Return time of a file.
Definition: files.lib.php:597
$sql
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:745
GETPOST
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
Definition: functions.lib.php:530
dol_print_error
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
Definition: functions.lib.php:4994
dol_uncompress
dol_uncompress($inputfile, $outputdir)
Uncompress a file.
Definition: files.lib.php:2199
dolReplaceInFile
dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, $indexdatabase=0, $arrayreplacementisregex=0)
Make replacement of strings into a file.
Definition: files.lib.php:627
dol_sort_array
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...
Definition: functions.lib.php:8758
Utils
Class to manage utility methods.
Definition: utils.class.php:30
dol_add_file_process
dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesession=0, $varfiles='addedfile', $savingdocmask='', $link=null, $trackid='', $generatethumbs=1, $object=null)
Get and save an upload file (for example after submitting a new file a mail form).
Definition: files.lib.php:1664
dol_dir_list
dol_dir_list($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.
Definition: files.lib.php:61
Task
Class to manage tasks.
Definition: task.class.php:37
dol_mimetype
dol_mimetype($file, $default='application/octet-stream', $mode=0)
Return MIME type of a file from its name with extension.
Definition: functions.lib.php:10170
image_format_supported
image_format_supported($file, $acceptsvg=0)
Return if a filename is file name of a supported image format.
Definition: images.lib.php:58
dol_most_recent_file
dol_most_recent_file($dir, $regexfilter='', $excludefilter=array('(\.meta|_preview.*\.png)$', '^\.'), $nohook=false, $mode='')
Return file(s) into a directory (by default most recent)
Definition: files.lib.php:2445
dol_is_link
dol_is_link($pathoffile)
Return if path is a symbolic link.
Definition: files.lib.php:493
dol_is_file
dol_is_file($pathoffile)
Return if path is a file.
Definition: files.lib.php:481
getRandomPassword
getRandomPassword($generic=false, $replaceambiguouschars=null, $length=32)
Return a generated password using default module.
Definition: security2.lib.php:482
dol_readcachefile
dol_readcachefile($directory, $filename)
Read object from cachefile.
Definition: files.lib.php:3264
dol_print_date
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
Definition: functions.lib.php:2566
dolChmod
dolChmod($filepath, $newmask='')
Change mod of a file.
Definition: functions.lib.php:6882
dol_compare_file
dol_compare_file($a, $b)
Fast compare of 2 files identified by their properties ->name, ->date and ->size.
Definition: files.lib.php:409
getDolUserInt
getDolUserInt($key, $default=0, $tmpuser=null)
Return Dolibarr user constant int value.
Definition: functions.lib.php:130
dol_unescapefile
dol_unescapefile($filename)
Unescape a file submitted by upload.
Definition: files.lib.php:1070
utf8_check
utf8_check($str)
Check if a string is in UTF8.
Definition: functions.lib.php:8814
dol_init_file_process
dol_init_file_process($pathtoscan='', $trackid='')
Scan a directory and init $_SESSION to manage uploaded files with list of all found files.
Definition: files.lib.php:1626
dol_delete_file
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
Definition: files.lib.php:1261
deleteFilesIntoDatabaseIndex
deleteFilesIntoDatabaseIndex($dir, $file, $mode='uploaded')
Delete files into database index using search criterias.
Definition: files.lib.php:1954
dol_hash
dol_hash($chain, $type='0')
Returns a hash (non reversible encryption) of a string.
Definition: security.lib.php:210
Exception
getFilesUpdated
getFilesUpdated(&$file_list, SimpleXMLElement $dir, $path='', $pathref='', &$checksumconcat=array())
Function to get list of updated or modified files.
Definition: files.lib.php:3283
dol_move_uploaded_file
dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles='addedfile', $upload_dir='')
Make control on an uploaded file from an GUI page and move it to final destination.
Definition: files.lib.php:1124
dol_is_dir_empty
dol_is_dir_empty($dir)
Return if path is empty.
Definition: files.lib.php:467
addFileIntoDatabaseIndex
addFileIntoDatabaseIndex($dir, $file, $fullpathorig='', $mode='uploaded', $setsharekey=0, $object=null)
Add a file into database index.
Definition: files.lib.php:1893
dol_copy
dol_copy($srcfile, $destfile, $newmask=0, $overwriteifexists=1)
Copy a file to another file.
Definition: files.lib.php:713
getEntity
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
Definition: functions.lib.php:190
dol_convert_file
dol_convert_file($fileinput, $ext='png', $fileoutput='', $page='')
Convert an image file or a PDF into another image format.
Definition: files.lib.php:2013
Holiday
Class of the module paid holiday.
Definition: holiday.class.php:34
dol_filecache
dol_filecache($directory, $filename, $object)
Store object in file.
Definition: files.lib.php:3231
dol_meta_create
dol_meta_create($object)
Create a meta file with document file into same directory.
Definition: files.lib.php:1541
AntiVir
Class to scan for virus.
Definition: antivir.class.php:30
dol_delete_dir
dol_delete_dir($dir, $nophperrors=0)
Remove a directory (not recursive, so content must be empty).
Definition: files.lib.php:1387
dol_dir_is_emtpy
dol_dir_is_emtpy($folder)
Test if a folder is empty.
Definition: files.lib.php:522
completeFileArrayWithDatabaseInfo
completeFileArrayWithDatabaseInfo(&$filearray, $relativedir)
Complete $filearray with data from database.
Definition: files.lib.php:314
dol_string_nohtmltag
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
Definition: functions.lib.php:6921
dol_syslog
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
Definition: functions.lib.php:1639
dolCopyDir
dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayreplacement=null, $excludesubdir=0, $excludefileext=null)
Copy a dir to another dir.
Definition: files.lib.php:773
dol_cache_refresh
dol_cache_refresh($directory, $filename, $cachetime)
Test if Refresh needed.
Definition: files.lib.php:3249
EcmFiles
Class to manage ECM files.
Definition: ecmfiles.class.php:35
isAFileWithExecutableContent
isAFileWithExecutableContent($filename)
Return if a file can contains executable content.
Definition: functions.lib.php:11302
dol_check_secure_access_document
dol_check_secure_access_document($modulepart, $original_file, $entity, $fuser='', $refname='', $mode='read')
Security check when accessing to a document (used by document.php, viewimage.php and webservices to g...
Definition: files.lib.php:2464
dol_dir_list_in_database
dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:236
isModEnabled
isModEnabled($module)
Is Dolibarr module enabled.
Definition: functions.lib.php:147
dol_remove_file_process
dol_remove_file_process($filenb, $donotupdatesession=0, $donotdeletefile=1, $trackid='')
Remove an uploaded file (for example after submitting a new file a mail form).
Definition: files.lib.php:1835
User
Class to manage Dolibarr users.
Definition: user.class.php:44
dol_filesize
dol_filesize($pathoffile)
Return size of a file.
Definition: files.lib.php:585
dolCheckVirus
dolCheckVirus($src_file)
Check virus into a file.
Definition: files.lib.php:1085
dol_delete_preview
dol_delete_preview($object)
Delete all preview files linked to object instance.
Definition: files.lib.php:1464
ExpenseReport
Class to manage Trips and Expenses.
Definition: expensereport.class.php:36
dol_now
dol_now($mode='auto')
Return date for now.
Definition: functions.lib.php:2947
checkUserAccessToObject
checkUserAccessToObject($user, array $featuresarray, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='', $dbt_select='rowid', $parenttableforentity='')
Check that access by a given user to an object is ok.
Definition: security.lib.php:773
setEventMessages
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
Definition: functions.lib.php:8509
dol_is_dir
dol_is_dir($folder)
Test if filename is a directory.
Definition: files.lib.php:451
FormMail
Classe permettant la generation du formulaire html d'envoi de mail unitaire Usage: $formail = new For...
Definition: html.formmail.class.php:38
dol_mkdir
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
Definition: functions.lib.php:6811
vignette
vignette($file, $maxWidth=160, $maxHeight=120, $extName='_small', $quality=50, $outdir='thumbs', $targetformat=0)
Create a thumbnail from an image file (Supported extensions are gif, jpg, png and bmp).
Definition: images.lib.php:487
getDolGlobalInt
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
Definition: functions.lib.php:96
dol_move
dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvirus=0, $indexdatabase=1)
Move a file into another name.
Definition: files.lib.php:875