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