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