dolibarr  9.0.0
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-2015 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  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  * or see http://www.gnu.org/
21  */
22 
35 function dol_basename($pathfile)
36 {
37  return preg_replace('/^.*\/([^\/]+)$/','$1',rtrim($pathfile,'/'));
38 }
39 
59 function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0)
60 {
61  global $db, $hookmanager;
62  global $object;
63 
64  dol_syslog("files.lib.php::dol_dir_list path=".$path." types=".$types." recursive=".$recursive." filter=".$filter." excludefilter=".json_encode($excludefilter));
65  //print 'xxx'."files.lib.php::dol_dir_list path=".$path." types=".$types." recursive=".$recursive." filter=".$filter." excludefilter=".json_encode($excludefilter);
66 
67  $loaddate=($mode==1||$mode==2)?true:false;
68  $loadsize=($mode==1||$mode==3)?true:false;
69 
70  // Clean parameters
71  $path=preg_replace('/([\\/]+)$/i','',$path);
72  $newpath=dol_osencode($path);
73 
74  $reshook = 0;
75  $file_list = array();
76 
77  if (is_object($hookmanager) && ! $nohook)
78  {
79  $hookmanager->resArray=array();
80 
81  $hookmanager->initHooks(array('fileslib'));
82 
83  $parameters=array(
84  'path' => $newpath,
85  'types'=> $types,
86  'recursive' => $recursive,
87  'filter' => $filter,
88  'excludefilter' => $excludefilter,
89  'sortcriteria' => $sortcriteria,
90  'sortorder' => $sortorder,
91  'loaddate' => $loaddate,
92  'loadsize' => $loadsize,
93  'mode' => $mode
94  );
95  $reshook=$hookmanager->executeHooks('getDirList', $parameters, $object);
96  }
97 
98  // $hookmanager->resArray may contain array stacked by other modules
99  if (empty($reshook))
100  {
101  if (! is_dir($newpath)) return array();
102 
103  if ($dir = opendir($newpath))
104  {
105  $filedate='';
106  $filesize='';
107 
108  while (false !== ($file = readdir($dir))) // $file is always a basename (into directory $newpath)
109  {
110  if (! utf8_check($file)) $file=utf8_encode($file); // To be sure data is stored in utf8 in memory
111  $fullpathfile=($newpath?$newpath.'/':'').$file;
112 
113  $qualified=1;
114 
115  // Define excludefilterarray
116  $excludefilterarray=array('^\.');
117  if (is_array($excludefilter))
118  {
119  $excludefilterarray=array_merge($excludefilterarray,$excludefilter);
120  }
121  else if ($excludefilter) $excludefilterarray[]=$excludefilter;
122  // Check if file is qualified
123  foreach($excludefilterarray as $filt)
124  {
125  if (preg_match('/'.$filt.'/i', $file) || preg_match('/'.$filt.'/i', $fullpathfile)) {
126  $qualified=0; break;
127  }
128  }
129  //print $fullpathfile.' '.$file.' '.$qualified.'<br>';
130 
131  if ($qualified)
132  {
133  $isdir=is_dir(dol_osencode($path."/".$file));
134  // Check whether this is a file or directory and whether we're interested in that type
135  if ($isdir && (($types=="directories") || ($types=="all") || $recursive))
136  {
137  // Add entry into file_list array
138  if (($types=="directories") || ($types=="all"))
139  {
140  if ($loaddate || $sortcriteria == 'date') $filedate=dol_filemtime($path."/".$file);
141  if ($loadsize || $sortcriteria == 'size') $filesize=dol_filesize($path."/".$file);
142 
143  if (! $filter || preg_match('/'.$filter.'/i',$file)) // We do not search key $filter into all $path, only into $file part
144  {
145  preg_match('/([^\/]+)\/[^\/]+$/',$path.'/'.$file,$reg);
146  $level1name=(isset($reg[1])?$reg[1]:'');
147  $file_list[] = array(
148  "name" => $file,
149  "path" => $path,
150  "level1name" => $level1name,
151  "relativename" => ($relativename?$relativename.'/':'').$file,
152  "fullname" => $path.'/'.$file,
153  "date" => $filedate,
154  "size" => $filesize,
155  "type" => 'dir'
156  );
157  }
158  }
159 
160  // if we're in a directory and we want recursive behavior, call this function again
161  if ($recursive)
162  {
163  if (empty($donotfollowsymlinks) || ! is_link($path."/".$file))
164  {
165  //var_dump('eee '. $path."/".$file. ' '.is_dir($path."/".$file).' '.is_link($path."/".$file));
166  $file_list = array_merge($file_list, dol_dir_list($path."/".$file, $types, $recursive, $filter, $excludefilter, $sortcriteria, $sortorder, $mode, $nohook, ($relativename!=''?$relativename.'/':'').$file, $donotfollowsymlinks));
167  }
168  }
169  }
170  else if (! $isdir && (($types == "files") || ($types == "all")))
171  {
172  // Add file into file_list array
173  if ($loaddate || $sortcriteria == 'date') $filedate=dol_filemtime($path."/".$file);
174  if ($loadsize || $sortcriteria == 'size') $filesize=dol_filesize($path."/".$file);
175 
176  if (! $filter || preg_match('/'.$filter.'/i',$file)) // We do not search key $filter into $path, only into $file
177  {
178  preg_match('/([^\/]+)\/[^\/]+$/',$path.'/'.$file,$reg);
179  $level1name=(isset($reg[1])?$reg[1]:'');
180  $file_list[] = array(
181  "name" => $file,
182  "path" => $path,
183  "level1name" => $level1name,
184  "relativename" => ($relativename?$relativename.'/':'').$file,
185  "fullname" => $path.'/'.$file,
186  "date" => $filedate,
187  "size" => $filesize,
188  "type" => 'file'
189  );
190  }
191  }
192  }
193  }
194  closedir($dir);
195 
196  // Obtain a list of columns
197  if (! empty($sortcriteria))
198  {
199  $myarray=array();
200  foreach ($file_list as $key => $row)
201  {
202  $myarray[$key] = (isset($row[$sortcriteria])?$row[$sortcriteria]:'');
203  }
204  // Sort the data
205  if ($sortorder) array_multisort($myarray, $sortorder, $file_list);
206  }
207  }
208  }
209 
210  if (is_object($hookmanager) && is_array($hookmanager->resArray)) $file_list = array_merge($file_list, $hookmanager->resArray);
211 
212  return $file_list;
213 }
214 
215 
229 function dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0)
230 {
231  global $conf, $db;
232 
233  $sql =" SELECT rowid, label, entity, filename, filepath, fullpath_orig, keywords, cover, gen_or_uploaded, extraparams, date_c, date_m, fk_user_c, fk_user_m,";
234  $sql.=" acl, position, share";
235  if ($mode) $sql.=", description";
236  $sql.=" FROM ".MAIN_DB_PREFIX."ecm_files";
237  $sql.=" WHERE filepath = '".$db->escape($path)."'";
238  $sql.=" AND entity = ".$conf->entity;
239 
240  $resql = $db->query($sql);
241  if ($resql)
242  {
243  $file_list=array();
244  $num = $db->num_rows($resql);
245  $i = 0;
246  while ($i < $num)
247  {
248  $obj = $db->fetch_object($resql);
249  if ($obj)
250  {
251  preg_match('/([^\/]+)\/[^\/]+$/',DOL_DATA_ROOT.'/'.$obj->filepath.'/'.$obj->filename,$reg);
252  $level1name=(isset($reg[1])?$reg[1]:'');
253  $file_list[] = array(
254  "rowid" => $obj->rowid,
255  "label" => $obj->label, // md5
256  "name" => $obj->filename,
257  "path" => DOL_DATA_ROOT.'/'.$obj->filepath,
258  "level1name" => $level1name,
259  "fullname" => DOL_DATA_ROOT.'/'.$obj->filepath.'/'.$obj->filename,
260  "fullpath_orig" => $obj->fullpath_orig,
261  "date_c" => $db->jdate($obj->date_c),
262  "date_m" => $db->jdate($obj->date_m),
263  "type" => 'file',
264  "keywords" => $obj->keywords,
265  "cover" => $obj->cover,
266  "position" => (int) $obj->position,
267  "acl" => $obj->acl,
268  "share" => $obj->share
269  );
270  }
271  $i++;
272  }
273 
274  // Obtain a list of columns
275  if (! empty($sortcriteria))
276  {
277  $myarray=array();
278  foreach ($file_list as $key => $row)
279  {
280  $myarray[$key] = (isset($row[$sortcriteria])?$row[$sortcriteria]:'');
281  }
282  // Sort the data
283  if ($sortorder) array_multisort($myarray, $sortorder, $file_list);
284  }
285 
286  return $file_list;
287  }
288  else
289  {
290  dol_print_error($db);
291  return array();
292  }
293 }
294 
295 
304 function completeFileArrayWithDatabaseInfo(&$filearray, $relativedir)
305 {
306  global $conf, $db, $user;
307 
308  $filearrayindatabase = dol_dir_list_in_database($relativedir, '', null, 'name', SORT_ASC);
309 
310  // TODO Remove this when PRODUCT_USE_OLD_PATH_FOR_PHOTO will be removed
311  global $modulepart;
312  if ($modulepart == 'produit' && ! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) {
313  global $object;
314  if (! empty($object->id))
315  {
316  if (! empty($conf->product->enabled)) $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";
317  else $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";
318 
319  $relativedirold = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $upload_dirold);
320  $relativedirold = preg_replace('/^[\\/]/','',$relativedirold);
321 
322  $filearrayindatabase = array_merge($filearrayindatabase, dol_dir_list_in_database($relativedirold, '', null, 'name', SORT_ASC));
323  }
324  }
325 
326  //var_dump($filearray);
327  //var_dump($filearrayindatabase);
328 
329  // Complete filearray with properties found into $filearrayindatabase
330  foreach($filearray as $key => $val)
331  {
332  $found=0;
333  // Search if it exists into $filearrayindatabase
334  foreach($filearrayindatabase as $key2 => $val2)
335  {
336  if ($filearrayindatabase[$key2]['name'] == $filearray[$key]['name'])
337  {
338  $filearray[$key]['position_name']=($filearrayindatabase[$key2]['position']?$filearrayindatabase[$key2]['position']:'0').'_'.$filearrayindatabase[$key2]['name'];
339  $filearray[$key]['position']=$filearrayindatabase[$key2]['position'];
340  $filearray[$key]['cover']=$filearrayindatabase[$key2]['cover'];
341  $filearray[$key]['acl']=$filearrayindatabase[$key2]['acl'];
342  $filearray[$key]['rowid']=$filearrayindatabase[$key2]['rowid'];
343  $filearray[$key]['label']=$filearrayindatabase[$key2]['label'];
344  $filearray[$key]['share']=$filearrayindatabase[$key2]['share'];
345  $found=1;
346  break;
347  }
348  }
349 
350  if (! $found) // This happen in transition toward version 6, or if files were added manually into os dir.
351  {
352  $filearray[$key]['position']='999999'; // File not indexed are at end. So if we add a file, it will not replace an existing position
353  $filearray[$key]['cover']=0;
354  $filearray[$key]['acl']='';
355 
356  $rel_filename = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $filearray[$key]['fullname']);
357  if (! preg_match('/([\\/]temp[\\/]|[\\/]thumbs|\.meta$)/', $rel_filetorenameafter)) // If not a tmp file
358  {
359  dol_syslog("list_of_documents We found a file called '".$filearray[$key]['name']."' not indexed into database. We add it");
360  include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
361  $ecmfile=new EcmFiles($db);
362 
363  // Add entry into database
364  $filename = basename($rel_filename);
365  $rel_dir = dirname($rel_filename);
366  $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
367  $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
368 
369  $ecmfile->filepath = $rel_dir;
370  $ecmfile->filename = $filename;
371  $ecmfile->label = md5_file(dol_osencode($filearray[$key]['fullname'])); // $destfile is a full path to file
372  $ecmfile->fullpath_orig = $filearray[$key]['fullname'];
373  $ecmfile->gen_or_uploaded = 'unknown';
374  $ecmfile->description = ''; // indexed content
375  $ecmfile->keyword = ''; // keyword content
376  $result = $ecmfile->create($user);
377  if ($result < 0)
378  {
379  setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
380  }
381  else
382  {
383  $filearray[$key]['rowid']=$result;
384  }
385  }
386  else
387  {
388  $filearray[$key]['rowid']=0; // Should not happened
389  }
390  }
391  }
392 
393  /*var_dump($filearray);*/
394 }
395 
396 
404 function dol_compare_file($a, $b)
405 {
406  global $sortorder;
407  global $sortfield;
408 
409  $sortorder=strtoupper($sortorder);
410 
411  if ($sortorder == 'ASC') { $retup=-1; $retdown=1; }
412  else { $retup=1; $retdown=-1; }
413 
414  if ($sortfield == 'name')
415  {
416  if ($a->name == $b->name) return 0;
417  return ($a->name < $b->name) ? $retup : $retdown;
418  }
419  if ($sortfield == 'date')
420  {
421  if ($a->date == $b->date) return 0;
422  return ($a->date < $b->date) ? $retup : $retdown;
423  }
424  if ($sortfield == 'size')
425  {
426  if ($a->size == $b->size) return 0;
427  return ($a->size < $b->size) ? $retup : $retdown;
428  }
429 }
430 
431 
438 function dol_is_dir($folder)
439 {
440  $newfolder=dol_osencode($folder);
441  if (is_dir($newfolder)) return true;
442  else return false;
443 }
444 
451 function dol_is_file($pathoffile)
452 {
453  $newpathoffile=dol_osencode($pathoffile);
454  return is_file($newpathoffile);
455 }
456 
463 function dol_is_link($pathoffile)
464 {
465  $newpathoffile=dol_osencode($pathoffile);
466  return is_link($newpathoffile);
467 }
468 
475 function dol_is_url($url)
476 {
477  $tmpprot=array('file','http','https','ftp','zlib','data','ssh','ssh2','ogg','expect');
478  foreach($tmpprot as $prot)
479  {
480  if (preg_match('/^'.$prot.':/i',$url)) return true;
481  }
482  return false;
483 }
484 
491 function dol_dir_is_emtpy($folder)
492 {
493  $newfolder=dol_osencode($folder);
494  if (is_dir($newfolder))
495  {
496  $handle = opendir($newfolder);
497  $folder_content = '';
498  while ((gettype($name = readdir($handle)) != "boolean"))
499  {
500  $name_array[] = $name;
501  }
502  foreach($name_array as $temp) $folder_content .= $temp;
503 
504  closedir($handle);
505 
506  if ($folder_content == "...") return true;
507  else return false;
508  }
509  else
510  return true; // Dir does not exists
511 }
512 
520 function dol_count_nb_of_line($file)
521 {
522  $nb=0;
523 
524  $newfile=dol_osencode($file);
525  //print 'x'.$file;
526  $fp=fopen($newfile,'r');
527  if ($fp)
528  {
529  while (!feof($fp))
530  {
531  $line=fgets($fp);
532  // 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.
533  if (! $line === false) $nb++;
534  }
535  fclose($fp);
536  }
537  else
538  {
539  $nb=-1;
540  }
541 
542  return $nb;
543 }
544 
545 
552 function dol_filesize($pathoffile)
553 {
554  $newpathoffile=dol_osencode($pathoffile);
555  return filesize($newpathoffile);
556 }
557 
564 function dol_filemtime($pathoffile)
565 {
566  $newpathoffile=dol_osencode($pathoffile);
567  return @filemtime($newpathoffile); // @Is to avoid errors if files does not exists
568 }
569 
581 function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, $indexdatabase=0)
582 {
583  global $conf;
584 
585  dol_syslog("files.lib.php::dolReplaceInFile srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." indexdatabase=".$indexdatabase);
586 
587  if (empty($srcfile)) return -1;
588  if (empty($destfile)) $destfile=$srcfile;
589 
590  $destexists=dol_is_file($destfile);
591  if (($destfile != $srcfile) && $destexists) return 0;
592 
593  $tmpdestfile=$destfile.'.tmp';
594 
595  $newpathofsrcfile=dol_osencode($srcfile);
596  $newpathoftmpdestfile=dol_osencode($tmpdestfile);
597  $newpathofdestfile=dol_osencode($destfile);
598  $newdirdestfile=dirname($newpathofdestfile);
599 
600  if ($destexists && ! is_writable($newpathofdestfile))
601  {
602  dol_syslog("files.lib.php::dolReplaceInFile failed Permission denied to overwrite target file", LOG_WARNING);
603  return -1;
604  }
605  if (! is_writable($newdirdestfile))
606  {
607  dol_syslog("files.lib.php::dolReplaceInFile failed Permission denied to write into target directory ".$newdirdestfile, LOG_WARNING);
608  return -2;
609  }
610 
611  dol_delete_file($tmpdestfile);
612 
613  // Create $newpathoftmpdestfile from $newpathofsrcfile
614  $content = file_get_contents($newpathofsrcfile, 'r');
615 
616  $content = make_substitutions($content, $arrayreplacement, null);
617 
618  file_put_contents($newpathoftmpdestfile, $content);
619  @chmod($newpathoftmpdestfile, octdec($newmask));
620 
621  // Rename
622  $result=dol_move($newpathoftmpdestfile, $newpathofdestfile, $newmask, (($destfile == $srcfile)?1:0), 0, $indexdatabase);
623  if (! $result)
624  {
625  dol_syslog("files.lib.php::dolReplaceInFile failed to move tmp file to final dest", LOG_WARNING);
626  return -3;
627  }
628  if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $newmask=$conf->global->MAIN_UMASK;
629  if (empty($newmask)) // This should no happen
630  {
631  dol_syslog("Warning: dolReplaceInFile called with empty value for newmask and no default value defined", LOG_WARNING);
632  $newmask='0664';
633  }
634 
635  @chmod($newpathofdestfile, octdec($newmask));
636 
637  return 1;
638 }
639 
651 function dolReplaceRegExInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, $indexdatabase=0)
652 {
653  // TODO
654 }
655 
666 function dol_copy($srcfile, $destfile, $newmask=0, $overwriteifexists=1)
667 {
668  global $conf;
669 
670  dol_syslog("files.lib.php::dol_copy srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." overwriteifexists=".$overwriteifexists);
671 
672  if (empty($srcfile) || empty($destfile)) return -1;
673 
674  $destexists=dol_is_file($destfile);
675  if (! $overwriteifexists && $destexists) return 0;
676 
677  $newpathofsrcfile=dol_osencode($srcfile);
678  $newpathofdestfile=dol_osencode($destfile);
679  $newdirdestfile=dirname($newpathofdestfile);
680 
681  if ($destexists && ! is_writable($newpathofdestfile))
682  {
683  dol_syslog("files.lib.php::dol_copy failed Permission denied to overwrite target file", LOG_WARNING);
684  return -1;
685  }
686  if (! is_writable($newdirdestfile))
687  {
688  dol_syslog("files.lib.php::dol_copy failed Permission denied to write into target directory ".$newdirdestfile, LOG_WARNING);
689  return -2;
690  }
691  // Copy with overwriting if exists
692  $result=@copy($newpathofsrcfile, $newpathofdestfile);
693  //$result=copy($newpathofsrcfile, $newpathofdestfile); // To see errors, remove @
694  if (! $result)
695  {
696  dol_syslog("files.lib.php::dol_copy failed to copy", LOG_WARNING);
697  return -3;
698  }
699  if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $newmask=$conf->global->MAIN_UMASK;
700  if (empty($newmask)) // This should no happen
701  {
702  dol_syslog("Warning: dol_copy called with empty value for newmask and no default value defined", LOG_WARNING);
703  $newmask='0664';
704  }
705 
706  @chmod($newpathofdestfile, octdec($newmask));
707 
708  return 1;
709 }
710 
722 function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayreplacement=null)
723 {
724  global $conf;
725 
726  $result=0;
727 
728  dol_syslog("files.lib.php::dolCopyDir srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." overwriteifexists=".$overwriteifexists);
729 
730  if (empty($srcfile) || empty($destfile)) return -1;
731 
732  $destexists=dol_is_dir($destfile);
733  //if (! $overwriteifexists && $destexists) return 0; // The overwriteifexists is for files only, so propagated to dol_copy only.
734 
735  if (! $destexists)
736  {
737  // We must set mask just before creating dir, becaause it can be set differently by dol_copy
738  umask(0);
739  $dirmaskdec=octdec($newmask);
740  if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $dirmaskdec=octdec($conf->global->MAIN_UMASK);
741  $dirmaskdec |= octdec('0200'); // Set w bit required to be able to create content for recursive subdirs files
742  dol_mkdir($destfile, '', decoct($dirmaskdec));
743  }
744 
745  $ossrcfile=dol_osencode($srcfile);
746  $osdestfile=dol_osencode($destfile);
747 
748  // Recursive function to copy all subdirectories and contents:
749  if (is_dir($ossrcfile))
750  {
751  $dir_handle=opendir($ossrcfile);
752  while ($file=readdir($dir_handle))
753  {
754  if ($file != "." && $file != ".." && ! is_link($ossrcfile."/".$file))
755  {
756  if (is_dir($ossrcfile."/".$file))
757  {
758  //var_dump("xxx dolCopyDir $srcfile/$file, $destfile/$file, $newmask, $overwriteifexists");
759  $tmpresult=dolCopyDir($srcfile."/".$file, $destfile."/".$file, $newmask, $overwriteifexists, $arrayreplacement);
760  }
761  else
762  {
763  $newfile = $file;
764  // Replace destination filename with a new one
765  if (is_array($arrayreplacement))
766  {
767  foreach($arrayreplacement as $key => $val)
768  {
769  $newfile = str_replace($key, $val, $newfile);
770  }
771  }
772  $tmpresult=dol_copy($srcfile."/".$file, $destfile."/".$newfile, $newmask, $overwriteifexists);
773  }
774  // Set result
775  if ($result > 0 && $tmpresult >= 0)
776  {
777  // Do nothing, so we don't set result to 0 if tmpresult is 0 and result was success in a previous pass
778  }
779  else
780  {
781  $result=$tmpresult;
782  }
783  if ($result < 0) break;
784  }
785  }
786  closedir($dir_handle);
787  }
788  else
789  {
790  // Source directory does not exists
791  $result = -2;
792  }
793 
794  return $result;
795 }
796 
797 
814 function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvirus=0, $indexdatabase=1)
815 {
816  global $user, $db, $conf;
817  $result=false;
818 
819  dol_syslog("files.lib.php::dol_move srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." overwritifexists=".$overwriteifexists);
820  $srcexists=dol_is_file($srcfile);
821  $destexists=dol_is_file($destfile);
822 
823  if (! $srcexists)
824  {
825  dol_syslog("files.lib.php::dol_move srcfile does not exists. we ignore the move request.");
826  return false;
827  }
828 
829  if ($overwriteifexists || ! $destexists)
830  {
831  $newpathofsrcfile=dol_osencode($srcfile);
832  $newpathofdestfile=dol_osencode($destfile);
833 
834  // Check virus
835  $testvirusarray=array();
836  if ($testvirus)
837  {
838  $testvirusarray=dolCheckVirus($newpathofsrcfile);
839  if (count($testvirusarray))
840  {
841  dol_syslog("files.lib.php::dol_move canceled because a virus was found into source file. we ignore the move request.", LOG_WARNING);
842  return false;
843  }
844  }
845 
846  $result=@rename($newpathofsrcfile, $newpathofdestfile); // To see errors, remove @
847  if (! $result)
848  {
849  if ($destexists)
850  {
851  dol_syslog("files.lib.php::dol_move Failed. We try to delete target first and move after.", LOG_WARNING);
852  // We force delete and try again. Rename function sometimes fails to replace dest file with some windows NTFS partitions.
853  dol_delete_file($destfile);
854  $result=@rename($newpathofsrcfile, $newpathofdestfile); // To see errors, remove @
855  }
856  else dol_syslog("files.lib.php::dol_move Failed.", LOG_WARNING);
857  }
858 
859  // Move ok
860  if ($result && $indexdatabase)
861  {
862  // Rename entry into ecm database
863  $rel_filetorenamebefore = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $srcfile);
864  $rel_filetorenameafter = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $destfile);
865  if (! preg_match('/([\\/]temp[\\/]|[\\/]thumbs|\.meta$)/', $rel_filetorenameafter)) // If not a tmp file
866  {
867  $rel_filetorenamebefore = preg_replace('/^[\\/]/', '', $rel_filetorenamebefore);
868  $rel_filetorenameafter = preg_replace('/^[\\/]/', '', $rel_filetorenameafter);
869  //var_dump($rel_filetorenamebefore.' - '.$rel_filetorenameafter);
870 
871  dol_syslog("Try to rename also entries in database for full relative path before = ".$rel_filetorenamebefore." after = ".$rel_filetorenameafter, LOG_DEBUG);
872  include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
873 
874  $ecmfiletarget=new EcmFiles($db);
875  $resultecmtarget = $ecmfiletarget->fetch(0, '', $rel_filetorenameafter);
876  if ($resultecmtarget > 0) // An entry for target name already exists for target, we delete it, a new one will be created.
877  {
878  $ecmfiletarget->delete($user);
879  }
880 
881  $ecmfile=new EcmFiles($db);
882  $resultecm = $ecmfile->fetch(0, '', $rel_filetorenamebefore);
883  if ($resultecm > 0) // If an entry was found for src file, we use it to move entry
884  {
885  $filename = basename($rel_filetorenameafter);
886  $rel_dir = dirname($rel_filetorenameafter);
887  $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
888  $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
889 
890  $ecmfile->filepath = $rel_dir;
891  $ecmfile->filename = $filename;
892  $resultecm = $ecmfile->update($user);
893  }
894  elseif ($resultecm == 0) // If no entry were found for src files, create/update target file
895  {
896  $filename = basename($rel_filetorenameafter);
897  $rel_dir = dirname($rel_filetorenameafter);
898  $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
899  $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
900 
901  $ecmfile->filepath = $rel_dir;
902  $ecmfile->filename = $filename;
903  $ecmfile->label = md5_file(dol_osencode($destfile)); // $destfile is a full path to file
904  $ecmfile->fullpath_orig = $srcfile;
905  $ecmfile->gen_or_uploaded = 'unknown';
906  $ecmfile->description = ''; // indexed content
907  $ecmfile->keyword = ''; // keyword content
908  $resultecm = $ecmfile->create($user);
909  if ($resultecm < 0)
910  {
911  setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
912  }
913  }
914  elseif ($resultecm < 0)
915  {
916  setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
917  }
918 
919  if ($resultecm > 0) $result=true;
920  else $result = false;
921  }
922  }
923 
924  if (empty($newmask)) $newmask=empty($conf->global->MAIN_UMASK)?'0755':$conf->global->MAIN_UMASK;
925  $newmaskdec=octdec($newmask);
926  // Currently method is restricted to files (dol_delete_files previously used is for files, and mask usage if for files too)
927  // to allow mask usage for dir, we shoul introduce a new param "isdir" to 1 to complete newmask like this
928  // if ($isdir) $newmaskdec |= octdec('0111'); // Set x bit required for directories
929  @chmod($newpathofdestfile, $newmaskdec);
930  }
931 
932  return $result;
933 }
934 
942 function dol_unescapefile($filename)
943 {
944  // Remove path information and dots around the filename, to prevent uploading
945  // into different directories or replacing hidden system files.
946  // Also remove control characters and spaces (\x00..\x20) around the filename:
947  return trim(basename($filename), ".\x00..\x20");
948 }
949 
950 
957 function dolCheckVirus($src_file)
958 {
959  global $conf;
960 
961  if (! empty($conf->global->MAIN_ANTIVIRUS_COMMAND))
962  {
963  if (! class_exists('AntiVir')) {
964  require_once DOL_DOCUMENT_ROOT.'/core/class/antivir.class.php';
965  }
966  $antivir=new AntiVir($db);
967  $result = $antivir->dol_avscan_file($src_file);
968  if ($result < 0) // If virus or error, we stop here
969  {
970  $reterrors=$antivir->errors;
971  return $reterrors;
972  }
973  }
974  return array();
975 }
976 
977 
996 function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles='addedfile')
997 {
998  global $conf, $db, $user, $langs;
999  global $object, $hookmanager;
1000 
1001  $reshook=0;
1002  $file_name = $dest_file;
1003 
1004  if (empty($nohook))
1005  {
1006  $reshook=$hookmanager->initHooks(array('fileslib'));
1007 
1008  $parameters=array('dest_file' => $dest_file, 'src_file' => $src_file, 'file_name' => $file_name, 'varfiles' => $varfiles, 'allowoverwrite' => $allowoverwrite);
1009  $reshook=$hookmanager->executeHooks('moveUploadedFile', $parameters, $object);
1010  }
1011 
1012  if (empty($reshook))
1013  {
1014  // If an upload error has been reported
1015  if ($uploaderrorcode)
1016  {
1017  switch($uploaderrorcode)
1018  {
1019  case UPLOAD_ERR_INI_SIZE: // 1
1020  return 'ErrorFileSizeTooLarge';
1021  break;
1022  case UPLOAD_ERR_FORM_SIZE: // 2
1023  return 'ErrorFileSizeTooLarge';
1024  break;
1025  case UPLOAD_ERR_PARTIAL: // 3
1026  return 'ErrorPartialFile';
1027  break;
1028  case UPLOAD_ERR_NO_TMP_DIR: //
1029  return 'ErrorNoTmpDir';
1030  break;
1031  case UPLOAD_ERR_CANT_WRITE:
1032  return 'ErrorFailedToWriteInDir';
1033  break;
1034  case UPLOAD_ERR_EXTENSION:
1035  return 'ErrorUploadBlockedByAddon';
1036  break;
1037  default:
1038  break;
1039  }
1040  }
1041 
1042  // If we need to make a virus scan
1043  if (empty($disablevirusscan) && file_exists($src_file))
1044  {
1045  $checkvirusarray=dolCheckVirus($src_file);
1046  if (count($checkvirusarray))
1047  {
1048  dol_syslog('Files.lib::dol_move_uploaded_file File "'.$src_file.'" (target name "'.$dest_file.'") KO with antivirus: result='.$result.' errors='.join(',',$checkvirusarray), LOG_WARNING);
1049  return 'ErrorFileIsInfectedWithAVirus: '.join(',',$checkvirusarray);
1050  }
1051  }
1052 
1053  // Security:
1054  // Disallow file with some extensions. We rename them.
1055  // Because if we put the documents directory into a directory inside web root (very bad), this allows to execute on demand arbitrary code.
1056  if (preg_match('/\.htm|\.html|\.php|\.pl|\.cgi$/i',$dest_file) && empty($conf->global->MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED))
1057  {
1058  $file_name.= '.noexe';
1059  }
1060 
1061  // Security:
1062  // We refuse cache files/dirs, upload using .. and pipes into filenames.
1063  if (preg_match('/^\./',$src_file) || preg_match('/\.\./',$src_file) || preg_match('/[<>|]/',$src_file))
1064  {
1065  dol_syslog("Refused to deliver file ".$src_file, LOG_WARNING);
1066  return -1;
1067  }
1068 
1069  // Security:
1070  // On interdit fichiers caches, remontees de repertoire ainsi que les pipe dans les noms de fichiers.
1071  if (preg_match('/^\./',$dest_file) || preg_match('/\.\./',$dest_file) || preg_match('/[<>|]/',$dest_file))
1072  {
1073  dol_syslog("Refused to deliver file ".$dest_file, LOG_WARNING);
1074  return -2;
1075  }
1076  }
1077 
1078  if ($reshook < 0) // At least one blocking error returned by one hook
1079  {
1080  $errmsg = join(',', $hookmanager->errors);
1081  if (empty($errmsg)) $errmsg = 'ErrorReturnedBySomeHooks'; // Should not occurs. Added if hook is bugged and does not set ->errors when there is error.
1082  return $errmsg;
1083  }
1084  elseif (empty($reshook))
1085  {
1086  // The file functions must be in OS filesystem encoding.
1087  $src_file_osencoded=dol_osencode($src_file);
1088  $file_name_osencoded=dol_osencode($file_name);
1089 
1090  // Check if destination dir is writable
1091  if (! is_writable(dirname($file_name_osencoded)))
1092  {
1093  dol_syslog("Files.lib::dol_move_uploaded_file Dir ".dirname($file_name_osencoded)." is not writable. Return 'ErrorDirNotWritable'", LOG_WARNING);
1094  return 'ErrorDirNotWritable';
1095  }
1096 
1097  // Check if destination file already exists
1098  if (! $allowoverwrite)
1099  {
1100  if (file_exists($file_name_osencoded))
1101  {
1102  dol_syslog("Files.lib::dol_move_uploaded_file File ".$file_name." already exists. Return 'ErrorFileAlreadyExists'", LOG_WARNING);
1103  return 'ErrorFileAlreadyExists';
1104  }
1105  }
1106 
1107  // Move file
1108  $return=move_uploaded_file($src_file_osencoded, $file_name_osencoded);
1109  if ($return)
1110  {
1111  if (! empty($conf->global->MAIN_UMASK)) @chmod($file_name_osencoded, octdec($conf->global->MAIN_UMASK));
1112  dol_syslog("Files.lib::dol_move_uploaded_file Success to move ".$src_file." to ".$file_name." - Umask=".$conf->global->MAIN_UMASK, LOG_DEBUG);
1113  return 1; // Success
1114  }
1115  else
1116  {
1117  dol_syslog("Files.lib::dol_move_uploaded_file Failed to move ".$src_file." to ".$file_name, LOG_ERR);
1118  return -3; // Unknown error
1119  }
1120  }
1121 
1122  return 1; // Success
1123 }
1124 
1139 function dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1)
1140 {
1141  global $db, $conf, $user, $langs;
1142  global $hookmanager;
1143 
1144  // Load translation files required by the page
1145  $langs->loadLangs(array('other', 'errors'));
1146 
1147  dol_syslog("dol_delete_file file=".$file." disableglob=".$disableglob." nophperrors=".$nophperrors." nohook=".$nohook);
1148 
1149  // Security:
1150  // We refuse transversal using .. and pipes into filenames.
1151  if ((! $allowdotdot && preg_match('/\.\./',$file)) || preg_match('/[<>|]/',$file))
1152  {
1153  dol_syslog("Refused to delete file ".$file, LOG_WARNING);
1154  return false;
1155  }
1156 
1157  if (empty($nohook))
1158  {
1159  $hookmanager->initHooks(array('fileslib'));
1160 
1161  $parameters=array(
1162  'GET' => $_GET,
1163  'file' => $file,
1164  'disableglob'=> $disableglob,
1165  'nophperrors' => $nophperrors
1166  );
1167  $reshook=$hookmanager->executeHooks('deleteFile', $parameters, $object);
1168  }
1169 
1170  if (empty($nohook) && $reshook != 0) // reshook = 0 to do standard actions, 1 = ok, -1 = ko
1171  {
1172  if ($reshook < 0) return false;
1173  return true;
1174  }
1175  else
1176  {
1177  $error=0;
1178 
1179  //print "x".$file." ".$disableglob;exit;
1180  $file_osencoded=dol_osencode($file); // New filename encoded in OS filesystem encoding charset
1181  if (empty($disableglob) && ! empty($file_osencoded))
1182  {
1183  $ok=true;
1184  $globencoded=str_replace('[','\[',$file_osencoded);
1185  $globencoded=str_replace(']','\]',$globencoded);
1186  $listofdir=glob($globencoded);
1187  if (! empty($listofdir) && is_array($listofdir))
1188  {
1189  foreach ($listofdir as $filename)
1190  {
1191  if ($nophperrors) $ok=@unlink($filename);
1192  else $ok=unlink($filename);
1193  if ($ok)
1194  {
1195  dol_syslog("Removed file ".$filename, LOG_DEBUG);
1196 
1197  // Delete entry into ecm database
1198  $rel_filetodelete = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $filename);
1199  if (! preg_match('/(\/temp\/|\/thumbs\/|\.meta$)/', $rel_filetodelete)) // If not a tmp file
1200  {
1201  $rel_filetodelete = preg_replace('/^[\\/]/', '', $rel_filetodelete);
1202 
1203  if (is_object($db) && $indexdatabase) // $db may not be defined when lib is in a context with define('NOREQUIREDB',1)
1204  {
1205  dol_syslog("Try to remove also entries in database for full relative path = ".$rel_filetodelete, LOG_DEBUG);
1206  include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
1207  $ecmfile=new EcmFiles($db);
1208  $result = $ecmfile->fetch(0, '', $rel_filetodelete);
1209  if ($result >= 0 && $ecmfile->id > 0)
1210  {
1211  $result = $ecmfile->delete($user);
1212  }
1213  if ($result < 0)
1214  {
1215  setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
1216  }
1217  }
1218  }
1219  }
1220  else dol_syslog("Failed to remove file ".$filename, LOG_WARNING);
1221  // TODO Failure to remove can be because file was already removed or because of permission
1222  // If error because it does not exists, we should return true, and we should return false if this is a permission problem
1223  }
1224  }
1225  else dol_syslog("No files to delete found", LOG_DEBUG);
1226  }
1227  else
1228  {
1229  $ok=false;
1230  if ($nophperrors) $ok=@unlink($file_osencoded);
1231  else $ok=unlink($file_osencoded);
1232  if ($ok) dol_syslog("Removed file ".$file_osencoded, LOG_DEBUG);
1233  else dol_syslog("Failed to remove file ".$file_osencoded, LOG_WARNING);
1234  }
1235 
1236  return $ok;
1237  }
1238 }
1239 
1249 function dol_delete_dir($dir,$nophperrors=0)
1250 {
1251  // Security:
1252  // We refuse transversal using .. and pipes into filenames.
1253  if (preg_match('/\.\./',$dir) || preg_match('/[<>|]/',$dir))
1254  {
1255  dol_syslog("Refused to delete dir ".$dir, LOG_WARNING);
1256  return false;
1257  }
1258 
1259  $dir_osencoded=dol_osencode($dir);
1260  return ($nophperrors?@rmdir($dir_osencoded):rmdir($dir_osencoded));
1261 }
1262 
1273 function dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0)
1274 {
1275  dol_syslog("functions.lib:dol_delete_dir_recursive ".$dir,LOG_DEBUG);
1276  if (dol_is_dir($dir))
1277  {
1278  $dir_osencoded=dol_osencode($dir);
1279  if ($handle = opendir("$dir_osencoded"))
1280  {
1281  while (false !== ($item = readdir($handle)))
1282  {
1283  if (! utf8_check($item)) $item=utf8_encode($item); // should be useless
1284 
1285  if ($item != "." && $item != "..")
1286  {
1287  if (is_dir(dol_osencode("$dir/$item")) && ! is_link(dol_osencode("$dir/$item")))
1288  {
1289  $count=dol_delete_dir_recursive("$dir/$item", $count, $nophperrors, 0, $countdeleted);
1290  }
1291  else
1292  {
1293  $result=dol_delete_file("$dir/$item", 1, $nophperrors);
1294  $count++;
1295  if ($result) $countdeleted++;
1296  //else print 'Error on '.$item."\n";
1297  }
1298  }
1299  }
1300  closedir($handle);
1301 
1302  if (empty($onlysub))
1303  {
1304  $result=dol_delete_dir($dir, $nophperrors);
1305  $count++;
1306  if ($result) $countdeleted++;
1307  //else print 'Error on '.$dir."\n";
1308  }
1309  }
1310  }
1311 
1312  return $count;
1313 }
1314 
1315 
1324 function dol_delete_preview($object)
1325 {
1326  global $langs,$conf;
1327 
1328  // Define parent dir of elements
1329  $element = $object->element;
1330 
1331  if ($object->element == 'order_supplier') $dir = $conf->fournisseur->commande->dir_output;
1332  elseif ($object->element == 'invoice_supplier') $dir = $conf->fournisseur->facture->dir_output;
1333  elseif ($object->element == 'project') $dir = $conf->projet->dir_output;
1334  elseif ($object->element == 'shipping') $dir = $conf->expedition->dir_output.'/sending';
1335  elseif ($object->element == 'delivery') $dir = $conf->expedition->dir_output.'/receipt';
1336  elseif ($object->element == 'fichinter') $dir = $conf->ficheinter->dir_output;
1337  else $dir=empty($conf->$element->dir_output)?'':$conf->$element->dir_output;
1338 
1339  if (empty($dir)) return 'ErrorObjectNoSupportedByFunction';
1340 
1341  $refsan = dol_sanitizeFileName($object->ref);
1342  $dir = $dir . "/" . $refsan ;
1343  $filepreviewnew = $dir . "/" . $refsan . ".pdf_preview.png";
1344  $filepreviewnewbis = $dir . "/" . $refsan . ".pdf_preview-0.png";
1345  $filepreviewold = $dir . "/" . $refsan . ".pdf.png";
1346 
1347  // For new preview files
1348  if (file_exists($filepreviewnew) && is_writable($filepreviewnew))
1349  {
1350  if (! dol_delete_file($filepreviewnew,1))
1351  {
1352  $object->error=$langs->trans("ErrorFailedToDeleteFile",$filepreviewnew);
1353  return 0;
1354  }
1355  }
1356  if (file_exists($filepreviewnewbis) && is_writable($filepreviewnewbis))
1357  {
1358  if (! dol_delete_file($filepreviewnewbis,1))
1359  {
1360  $object->error=$langs->trans("ErrorFailedToDeleteFile",$filepreviewnewbis);
1361  return 0;
1362  }
1363  }
1364  // For old preview files
1365  if (file_exists($filepreviewold) && is_writable($filepreviewold))
1366  {
1367  if (! dol_delete_file($filepreviewold,1))
1368  {
1369  $object->error=$langs->trans("ErrorFailedToDeleteFile",$filepreviewold);
1370  return 0;
1371  }
1372  }
1373  else
1374  {
1375  $multiple = $filepreviewold . ".";
1376  for ($i = 0; $i < 20; $i++)
1377  {
1378  $preview = $multiple.$i;
1379 
1380  if (file_exists($preview) && is_writable($preview))
1381  {
1382  if ( ! dol_delete_file($preview,1) )
1383  {
1384  $object->error=$langs->trans("ErrorFailedToOpenFile",$preview);
1385  return 0;
1386  }
1387  }
1388  }
1389  }
1390 
1391  return 1;
1392 }
1393 
1402 function dol_meta_create($object)
1403 {
1404  global $conf;
1405 
1406  // Create meta file
1407  if (empty($conf->global->MAIN_DOC_CREATE_METAFILE)) return 0; // By default, no metafile.
1408 
1409  // Define parent dir of elements
1410  $element=$object->element;
1411 
1412  if ($object->element == 'order_supplier') $dir = $conf->fournisseur->dir_output.'/commande';
1413  elseif ($object->element == 'invoice_supplier') $dir = $conf->fournisseur->dir_output.'/facture';
1414  elseif ($object->element == 'project') $dir = $conf->projet->dir_output;
1415  elseif ($object->element == 'shipping') $dir = $conf->expedition->dir_output.'/sending';
1416  elseif ($object->element == 'delivery') $dir = $conf->expedition->dir_output.'/receipt';
1417  elseif ($object->element == 'fichinter') $dir = $conf->ficheinter->dir_output;
1418  else $dir=empty($conf->$element->dir_output)?'':$conf->$element->dir_output;
1419 
1420  if ($dir)
1421  {
1422  $object->fetch_thirdparty();
1423 
1424  $objectref = dol_sanitizeFileName($object->ref);
1425  $dir = $dir . "/" . $objectref;
1426  $file = $dir . "/" . $objectref . ".meta";
1427 
1428  if (! is_dir($dir))
1429  {
1430  dol_mkdir($dir);
1431  }
1432 
1433  if (is_dir($dir))
1434  {
1435  $nblignes = count($object->lines);
1436  $client = $object->thirdparty->name . " " . $object->thirdparty->address . " " . $object->thirdparty->zip . " " . $object->thirdparty->town;
1437  $meta = "REFERENCE=\"" . $object->ref . "\"
1438  DATE=\"" . dol_print_date($object->date,'') . "\"
1439  NB_ITEMS=\"" . $nblignes . "\"
1440  CLIENT=\"" . $client . "\"
1441  AMOUNT_EXCL_TAX=\"" . $object->total_ht . "\"
1442  AMOUNT=\"" . $object->total_ttc . "\"\n";
1443 
1444  for ($i = 0 ; $i < $nblignes ; $i++)
1445  {
1446  //Pour les articles
1447  $meta .= "ITEM_" . $i . "_QUANTITY=\"" . $object->lines[$i]->qty . "\"
1448  ITEM_" . $i . "_AMOUNT_WO_TAX=\"" . $object->lines[$i]->total_ht . "\"
1449  ITEM_" . $i . "_VAT=\"" .$object->lines[$i]->tva_tx . "\"
1450  ITEM_" . $i . "_DESCRIPTION=\"" . str_replace("\r\n","",nl2br($object->lines[$i]->desc)) . "\"
1451  ";
1452  }
1453  }
1454 
1455  $fp = fopen($file,"w");
1456  fputs($fp,$meta);
1457  fclose($fp);
1458  if (! empty($conf->global->MAIN_UMASK))
1459  @chmod($file, octdec($conf->global->MAIN_UMASK));
1460 
1461  return 1;
1462  }
1463  else
1464  {
1465  dol_syslog('FailedToDetectDirInDolMetaCreateFor'.$object->element, LOG_WARNING);
1466  }
1467 
1468  return 0;
1469 }
1470 
1471 
1472 
1481 function dol_init_file_process($pathtoscan='', $trackid='')
1482 {
1483  $listofpaths=array();
1484  $listofnames=array();
1485  $listofmimes=array();
1486 
1487  if ($pathtoscan)
1488  {
1489  $listoffiles=dol_dir_list($pathtoscan,'files');
1490  foreach($listoffiles as $key => $val)
1491  {
1492  $listofpaths[]=$val['fullname'];
1493  $listofnames[]=$val['name'];
1494  $listofmimes[]=dol_mimetype($val['name']);
1495  }
1496  }
1497  $keytoavoidconflict = empty($trackid)?'':'-'.$trackid;
1498  $_SESSION["listofpaths".$keytoavoidconflict]=join(';',$listofpaths);
1499  $_SESSION["listofnames".$keytoavoidconflict]=join(';',$listofnames);
1500  $_SESSION["listofmimes".$keytoavoidconflict]=join(';',$listofmimes);
1501 }
1502 
1503 
1519 function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesession=0, $varfiles='addedfile', $savingdocmask='', $link=null, $trackid='', $generatethumbs=1)
1520 {
1521  global $db,$user,$conf,$langs;
1522 
1523  $res = 0;
1524 
1525  if (! empty($_FILES[$varfiles])) // For view $_FILES[$varfiles]['error']
1526  {
1527  dol_syslog('dol_add_file_process upload_dir='.$upload_dir.' allowoverwrite='.$allowoverwrite.' donotupdatesession='.$donotupdatesession.' savingdocmask='.$savingdocmask, LOG_DEBUG);
1528  if (dol_mkdir($upload_dir) >= 0)
1529  {
1530  $TFile = $_FILES[$varfiles];
1531  if (!is_array($TFile['name']))
1532  {
1533  foreach ($TFile as $key => &$val)
1534  {
1535  $val = array($val);
1536  }
1537  }
1538 
1539  $nbfile = count($TFile['name']);
1540  $nbok = 0;
1541  for ($i = 0; $i < $nbfile; $i++)
1542  {
1543  // Define $destfull (path to file including filename) and $destfile (only filename)
1544  $destfull=$upload_dir . "/" . $TFile['name'][$i];
1545  $destfile=$TFile['name'][$i];
1546 
1547  if ($savingdocmask)
1548  {
1549  $destfull=$upload_dir . "/" . preg_replace('/__file__/',$TFile['name'][$i],$savingdocmask);
1550  $destfile=preg_replace('/__file__/',$TFile['name'][$i],$savingdocmask);
1551  }
1552 
1553  // dol_sanitizeFileName the file name and lowercase extension
1554  $info = pathinfo($destfull);
1555  $destfull = $info['dirname'].'/'.dol_sanitizeFileName($info['filename'].'.'.strtolower($info['extension']));
1556  $info = pathinfo($destfile);
1557  $destfile = dol_sanitizeFileName($info['filename'].'.'.strtolower($info['extension']));
1558 
1559  $resupload = dol_move_uploaded_file($TFile['tmp_name'][$i], $destfull, $allowoverwrite, 0, $TFile['error'][$i], 0, $varfiles);
1560 
1561  if (is_numeric($resupload) && $resupload > 0) // $resupload can be 'ErrorFileAlreadyExists'
1562  {
1563  global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini;
1564 
1565  include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
1566 
1567  // Generate thumbs.
1568  if ($generatethumbs)
1569  {
1570  if (image_format_supported($destfull) == 1)
1571  {
1572  // Create thumbs
1573  // We can't use $object->addThumbs here because there is no $object known
1574 
1575  // Used on logon for example
1576  $imgThumbSmall = vignette($destfull, $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs");
1577  // Create mini thumbs for image (Ratio is near 16/9)
1578  // Used on menu or for setup page for example
1579  $imgThumbMini = vignette($destfull, $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs");
1580  }
1581  }
1582 
1583  // Update session
1584  if (empty($donotupdatesession))
1585  {
1586  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
1587  $formmail = new FormMail($db);
1588  $formmail->trackid = $trackid;
1589  $formmail->add_attached_files($destfull, $destfile, $TFile['type'][$i]);
1590  }
1591 
1592  // Update table of files
1593  if ($donotupdatesession == 1)
1594  {
1595  $result = addFileIntoDatabaseIndex($upload_dir, basename($destfile), $TFile['name'][$i], 'uploaded', 0);
1596  if ($result < 0)
1597  {
1598  setEventMessages('FailedToAddFileIntoDatabaseIndex', '', 'warnings');
1599  }
1600  }
1601 
1602  $nbok++;
1603  }
1604  else
1605  {
1606  $langs->load("errors");
1607  if ($resupload < 0) // Unknown error
1608  {
1609  setEventMessages($langs->trans("ErrorFileNotUploaded"), null, 'errors');
1610  }
1611  else if (preg_match('/ErrorFileIsInfectedWithAVirus/',$resupload)) // Files infected by a virus
1612  {
1613  setEventMessages($langs->trans("ErrorFileIsInfectedWithAVirus"), null, 'errors');
1614  }
1615  else // Known error
1616  {
1617  setEventMessages($langs->trans($resupload), null, 'errors');
1618  }
1619  }
1620  }
1621  if ($nbok > 0)
1622  {
1623  $res = 1;
1624  setEventMessages($langs->trans("FileTransferComplete"), null, 'mesgs');
1625  }
1626  }
1627  } elseif ($link) {
1628  require_once DOL_DOCUMENT_ROOT . '/core/class/link.class.php';
1629  $linkObject = new Link($db);
1630  $linkObject->entity = $conf->entity;
1631  $linkObject->url = $link;
1632  $linkObject->objecttype = GETPOST('objecttype', 'alpha');
1633  $linkObject->objectid = GETPOST('objectid', 'int');
1634  $linkObject->label = GETPOST('label', 'alpha');
1635  $res = $linkObject->create($user);
1636  $langs->load('link');
1637  if ($res > 0) {
1638  setEventMessages($langs->trans("LinkComplete"), null, 'mesgs');
1639  } else {
1640  setEventMessages($langs->trans("ErrorFileNotLinked"), null, 'errors');
1641  }
1642  }
1643  else
1644  {
1645  $langs->load("errors");
1646  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("File")), null, 'errors');
1647  }
1648 
1649  return $res;
1650 }
1651 
1652 
1663 function dol_remove_file_process($filenb,$donotupdatesession=0,$donotdeletefile=1,$trackid='')
1664 {
1665  global $db,$user,$conf,$langs,$_FILES;
1666 
1667  $keytodelete=$filenb;
1668  $keytodelete--;
1669 
1670  $listofpaths=array();
1671  $listofnames=array();
1672  $listofmimes=array();
1673  $keytoavoidconflict = empty($trackid)?'':'-'.$trackid;
1674  if (! empty($_SESSION["listofpaths".$keytoavoidconflict])) $listofpaths=explode(';',$_SESSION["listofpaths".$keytoavoidconflict]);
1675  if (! empty($_SESSION["listofnames".$keytoavoidconflict])) $listofnames=explode(';',$_SESSION["listofnames".$keytoavoidconflict]);
1676  if (! empty($_SESSION["listofmimes".$keytoavoidconflict])) $listofmimes=explode(';',$_SESSION["listofmimes".$keytoavoidconflict]);
1677 
1678  if ($keytodelete >= 0)
1679  {
1680  $pathtodelete=$listofpaths[$keytodelete];
1681  $filetodelete=$listofnames[$keytodelete];
1682  if (empty($donotdeletefile)) $result = dol_delete_file($pathtodelete,1); // The delete of ecm database is inside the function dol_delete_file
1683  else $result=0;
1684  if ($result >= 0)
1685  {
1686  if (empty($donotdeletefile))
1687  {
1688  $langs->load("other");
1689  setEventMessages($langs->trans("FileWasRemoved",$filetodelete), null, 'mesgs');
1690  }
1691  if (empty($donotupdatesession))
1692  {
1693  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
1694  $formmail = new FormMail($db);
1695  $formmail->trackid = $trackid;
1696  $formmail->remove_attached_files($keytodelete);
1697  }
1698  }
1699  }
1700 }
1701 
1702 
1715 function addFileIntoDatabaseIndex($dir, $file, $fullpathorig='', $mode='uploaded', $setsharekey=0)
1716 {
1717  global $db, $user;
1718 
1719  $result = 0;
1720 
1721  $rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $dir);
1722 
1723  if (! preg_match('/[\\/]temp[\\/]|[\\/]thumbs|\.meta$/', $rel_dir)) // If not a tmp dir
1724  {
1725  $filename = basename($file);
1726  $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
1727  $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
1728 
1729  include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
1730  $ecmfile=new EcmFiles($db);
1731  $ecmfile->filepath = $rel_dir;
1732  $ecmfile->filename = $filename;
1733  $ecmfile->label = md5_file(dol_osencode($dir.'/'.$file)); // MD5 of file content
1734  $ecmfile->fullpath_orig = $fullpathorig;
1735  $ecmfile->gen_or_uploaded = $mode;
1736  $ecmfile->description = ''; // indexed content
1737  $ecmfile->keyword = ''; // keyword content
1738  if ($setsharekey)
1739  {
1740  require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
1741  $ecmfile->share = getRandomPassword(true);
1742  }
1743 
1744  $result = $ecmfile->create($user);
1745  if ($result < 0)
1746  {
1747  dol_syslog($ecmfile->error);
1748  }
1749  }
1750 
1751  return $result;
1752 }
1753 
1754 
1763 function deleteFilesIntoDatabaseIndex($dir, $file, $mode='uploaded')
1764 {
1765  global $conf, $db, $user;
1766 
1767  $error = 0;
1768 
1769  if (empty($dir))
1770  {
1771  dol_syslog("deleteFilesIntoDatabaseIndex: dir parameter can't be empty", LOG_ERR);
1772  return -1;
1773  }
1774 
1775  $db->begin();
1776 
1777  $rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $dir);
1778 
1779  $filename = basename($file);
1780  $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
1781  $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
1782 
1783  if (! $error)
1784  {
1785  $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . 'ecm_files';
1786  $sql.= ' WHERE entity = '.$conf->entity;
1787  $sql.= " AND filepath = '" . $db->escape($rel_dir) . "'";
1788  if ($file) $sql.= " AND filename = '" . $db->escape($file) . "'";
1789  if ($mode) $sql.= " AND gen_or_uploaded = '" . $db->escape($mode) . "'";
1790 
1791  $resql = $db->query($sql);
1792  if (!$resql)
1793  {
1794  $error++;
1795  dol_syslog(__METHOD__ . ' ' . $db->lasterror(), LOG_ERR);
1796  }
1797  }
1798 
1799  // Commit or rollback
1800  if ($error) {
1801  $db->rollback();
1802  return - 1 * $error;
1803  } else {
1804  $db->commit();
1805  return 1;
1806  }
1807 }
1808 
1809 
1819 function dol_convert_file($fileinput, $ext='png', $fileoutput='')
1820 {
1821  global $langs;
1822 
1823  if (class_exists('Imagick'))
1824  {
1825  $image=new Imagick();
1826  try {
1827  $ret = $image->readImage($fileinput);
1828  } catch(Exception $e) {
1829  dol_syslog("Failed to read image using Imagick. Try to install package 'apt-get install ghostscript'.", LOG_WARNING);
1830  return 0;
1831  }
1832  if ($ret)
1833  {
1834  $ret = $image->setImageFormat($ext);
1835  if ($ret)
1836  {
1837  if (empty($fileoutput)) $fileoutput=$fileinput.".".$ext;
1838 
1839  $count = $image->getNumberImages();
1840 
1841  if (! dol_is_file($fileoutput) || is_writeable($fileoutput))
1842  {
1843  $ret = $image->writeImages($fileoutput, true);
1844  }
1845  else
1846  {
1847  dol_syslog("Warning: Failed to write cache preview file '.$fileoutput.'. Check permission on file/dir", LOG_ERR);
1848  }
1849  if ($ret) return $count;
1850  else return -3;
1851  }
1852  else
1853  {
1854  return -2;
1855  }
1856  }
1857  else
1858  {
1859  return -1;
1860  }
1861  }
1862  else
1863  {
1864  return 0;
1865  }
1866 }
1867 
1868 
1877 function dol_compress_file($inputfile, $outputfile, $mode="gz")
1878 {
1879  $foundhandler=0;
1880 
1881  try
1882  {
1883  $data = implode("", file(dol_osencode($inputfile)));
1884  if ($mode == 'gz') { $foundhandler=1; $compressdata = gzencode($data, 9); }
1885  elseif ($mode == 'bz') { $foundhandler=1; $compressdata = bzcompress($data, 9); }
1886  elseif ($mode == 'zip')
1887  {
1888  if (defined('ODTPHP_PATHTOPCLZIP'))
1889  {
1890  $foundhandler=1;
1891 
1892  include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
1893  $archive = new PclZip($outputfile);
1894  $archive->add($inputfile, PCLZIP_OPT_REMOVE_PATH, dirname($inputfile));
1895  //$archive->add($inputfile);
1896  return 1;
1897  }
1898  }
1899 
1900  if ($foundhandler)
1901  {
1902  $fp = fopen($outputfile, "w");
1903  fwrite($fp, $compressdata);
1904  fclose($fp);
1905  return 1;
1906  }
1907  else
1908  {
1909  dol_syslog("Try to zip with format ".$mode." with no handler for this format",LOG_ERR);
1910  return -2;
1911  }
1912  }
1913  catch (Exception $e)
1914  {
1915  global $langs, $errormsg;
1916  $langs->load("errors");
1917  dol_syslog("Failed to open file ".$outputfile,LOG_ERR);
1918  $errormsg=$langs->trans("ErrorFailedToWriteInDir");
1919  return -1;
1920  }
1921 }
1922 
1930 function dol_uncompress($inputfile,$outputdir)
1931 {
1932  global $langs;
1933 
1934  if (defined('ODTPHP_PATHTOPCLZIP'))
1935  {
1936  dol_syslog("Constant ODTPHP_PATHTOPCLZIP for pclzip library is set to ".ODTPHP_PATHTOPCLZIP.", so we use Pclzip to unzip into ".$outputdir);
1937  include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
1938  $archive = new PclZip($inputfile);
1939  $result=$archive->extract(PCLZIP_OPT_PATH, $outputdir);
1940  //var_dump($result);
1941  if (! is_array($result) && $result <= 0) return array('error'=>$archive->errorInfo(true));
1942  else
1943  {
1944  $ok=1; $errmsg='';
1945  // Loop on each file to check result for unzipping file
1946  foreach($result as $key => $val)
1947  {
1948  if ($val['status'] == 'path_creation_fail')
1949  {
1950  $langs->load("errors");
1951  $ok=0;
1952  $errmsg=$langs->trans("ErrorFailToCreateDir", $val['filename']);
1953  break;
1954  }
1955  }
1956 
1957  if ($ok) return array();
1958  else return array('error'=>$errmsg);
1959  }
1960  }
1961 
1962  if (class_exists('ZipArchive'))
1963  {
1964  dol_syslog("Class ZipArchive is set so we unzip using ZipArchive to unzip into ".$outputdir);
1965  $zip = new ZipArchive;
1966  $res = $zip->open($inputfile);
1967  if ($res === true)
1968  {
1969  $zip->extractTo($outputdir.'/');
1970  $zip->close();
1971  return array();
1972  }
1973  else
1974  {
1975  return array('error'=>'ErrUnzipFails');
1976  }
1977  }
1978 
1979  return array('error'=>'ErrNoZipEngine');
1980 }
1981 
1982 
1991 function dol_compress_dir($inputdir, $outputfile, $mode="zip")
1992 {
1993  $foundhandler=0;
1994 
1995  dol_syslog("Try to zip dir ".$inputdir." into ".$outputdir." mode=".$mode);
1996 
1997  if (! dol_is_dir(dirname($outputfile)) || ! is_writable(dirname($outputfile)))
1998  {
1999  global $langs, $errormsg;
2000  $langs->load("errors");
2001  $errormsg=$langs->trans("ErrorFailedToWriteInDir",$outputfile);
2002  return -3;
2003  }
2004 
2005  try
2006  {
2007  if ($mode == 'gz') { $foundhandler=0; }
2008  elseif ($mode == 'bz') { $foundhandler=0; }
2009  elseif ($mode == 'zip')
2010  {
2011  /*if (defined('ODTPHP_PATHTOPCLZIP'))
2012  {
2013  $foundhandler=0; // TODO implement this
2014 
2015  include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
2016  $archive = new PclZip($outputfile);
2017  $archive->add($inputfile, PCLZIP_OPT_REMOVE_PATH, dirname($inputfile));
2018  //$archive->add($inputfile);
2019  return 1;
2020  }
2021  else*/
2022  if (class_exists('ZipArchive'))
2023  {
2024  $foundhandler=1;
2025 
2026  // Initialize archive object
2027  $zip = new ZipArchive();
2028  $result = $zip->open($outputfile, ZipArchive::CREATE | ZipArchive::OVERWRITE);
2029 
2030  // Create recursive directory iterator
2032  $files = new RecursiveIteratorIterator(
2033  new RecursiveDirectoryIterator($inputdir),
2034  RecursiveIteratorIterator::LEAVES_ONLY
2035  );
2036 
2037  foreach ($files as $name => $file)
2038  {
2039  // Skip directories (they would be added automatically)
2040  if (!$file->isDir())
2041  {
2042  // Get real and relative path for current file
2043  $filePath = $file->getRealPath();
2044  $relativePath = substr($filePath, strlen($inputdir) + 1);
2045 
2046  // Add current file to archive
2047  $zip->addFile($filePath, $relativePath);
2048  }
2049  }
2050 
2051  // Zip archive will be created only after closing object
2052  $zip->close();
2053 
2054  return 1;
2055  }
2056  }
2057 
2058  if (! $foundhandler)
2059  {
2060  dol_syslog("Try to zip with format ".$mode." with no handler for this format",LOG_ERR);
2061  return -2;
2062  }
2063  else
2064  {
2065  return 0;
2066  }
2067  }
2068  catch (Exception $e)
2069  {
2070  global $langs, $errormsg;
2071  $langs->load("errors");
2072  dol_syslog("Failed to open file ".$outputfile, LOG_ERR);
2073  dol_syslog($e->getMessage(), LOG_ERR);
2074  $errormsg=$langs->trans("ErrorFailedToWriteInDir",$outputfile);
2075  return -1;
2076  }
2077 }
2078 
2079 
2080 
2091 function dol_most_recent_file($dir,$regexfilter='',$excludefilter=array('(\.meta|_preview.*\.png)$','^\.'),$nohook=false,$mode='')
2092 {
2093  $tmparray=dol_dir_list($dir,'files',0,$regexfilter,$excludefilter,'date',SORT_DESC,$mode,$nohook);
2094  return $tmparray[0];
2095 }
2096 
2109 function dol_check_secure_access_document($modulepart, $original_file, $entity, $fuser='', $refname='', $mode='read')
2110 {
2111  global $conf, $db, $user;
2112  global $dolibarr_main_data_root, $dolibarr_main_document_root_alt;
2113 
2114  if (! is_object($fuser)) $fuser=$user;
2115 
2116  if (empty($modulepart)) return 'ErrorBadParameter';
2117  if (empty($entity))
2118  {
2119  if (empty($conf->multicompany->enabled)) $entity=1;
2120  else $entity=0;
2121  }
2122  // Fix modulepart
2123  if ($modulepart == 'users') $modulepart='user';
2124 
2125  dol_syslog('modulepart='.$modulepart.' original_file='.$original_file.' entity='.$entity);
2126  // We define $accessallowed and $sqlprotectagainstexternals
2127  $accessallowed=0;
2128  $sqlprotectagainstexternals='';
2129  $ret=array();
2130 
2131  // Find the subdirectory name as the reference. For exemple original_file='10/myfile.pdf' -> refname='10'
2132  if (empty($refname)) $refname=basename(dirname($original_file)."/");
2133 
2134  $relative_original_file = $original_file;
2135 
2136  // Define possible keys to use for permission check
2137  $lire='lire'; $read='read'; $download='download';
2138  if ($mode == 'write')
2139  {
2140  $lire='creer'; $read='write'; $download='upload';
2141  }
2142 
2143  // Wrapping for miscellaneous medias files
2144  if ($modulepart == 'medias' && !empty($dolibarr_main_data_root))
2145  {
2146  if (empty($entity) || empty($conf->medias->multidir_output[$entity])) return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
2147  $accessallowed=1;
2148  $original_file=$conf->medias->multidir_output[$entity].'/'.$original_file;
2149  }
2150  // Wrapping for *.log files, like when used with url http://.../document.php?modulepart=logs&file=dolibarr.log
2151  elseif ($modulepart == 'logs' && !empty($dolibarr_main_data_root))
2152  {
2153  $accessallowed=($user->admin && basename($original_file) == $original_file && preg_match('/^dolibarr.*\.log$/', basename($original_file)));
2154  $original_file=$dolibarr_main_data_root.'/'.$original_file;
2155  }
2156  // Wrapping for *.zip files, like when used with url http://.../document.php?modulepart=packages&file=module_myfile.zip
2157  elseif ($modulepart == 'packages' && !empty($dolibarr_main_data_root))
2158  {
2159  // Dir for custom dirs
2160  $tmp=explode(',', $dolibarr_main_document_root_alt);
2161  $dirins = $tmp[0];
2162 
2163  $accessallowed=($user->admin && preg_match('/^module_.*\.zip$/', basename($original_file)));
2164  $original_file=$dirins.'/'.$original_file;
2165  }
2166  // Wrapping for some images
2167  elseif ($modulepart == 'mycompany' && !empty($conf->mycompany->dir_output))
2168  {
2169  $accessallowed=1;
2170  $original_file=$conf->mycompany->dir_output.'/'.$original_file;
2171  }
2172  // Wrapping for users photos
2173  elseif ($modulepart == 'userphoto' && !empty($conf->user->dir_output))
2174  {
2175  $accessallowed=1;
2176  $original_file=$conf->user->dir_output.'/'.$original_file;
2177  }
2178  // Wrapping for members photos
2179  elseif ($modulepart == 'memberphoto' && !empty($conf->adherent->dir_output))
2180  {
2181  $accessallowed=1;
2182  $original_file=$conf->adherent->dir_output.'/'.$original_file;
2183  }
2184  // Wrapping pour les apercu factures
2185  elseif ($modulepart == 'apercufacture' && !empty($conf->facture->dir_output))
2186  {
2187  if ($fuser->rights->facture->{$lire}) $accessallowed=1;
2188  $original_file=$conf->facture->dir_output.'/'.$original_file;
2189  }
2190  // Wrapping pour les apercu propal
2191  elseif ($modulepart == 'apercupropal' && !empty($conf->propal->multidir_output[$entity]))
2192  {
2193  if ($fuser->rights->propale->{$lire}) $accessallowed=1;
2194  $original_file=$conf->propal->multidir_output[$entity].'/'.$original_file;
2195  }
2196  // Wrapping pour les apercu commande
2197  elseif ($modulepart == 'apercucommande' && !empty($conf->commande->dir_output))
2198  {
2199  if ($fuser->rights->commande->{$lire}) $accessallowed=1;
2200  $original_file=$conf->commande->dir_output.'/'.$original_file;
2201  }
2202  // Wrapping pour les apercu intervention
2203  elseif (($modulepart == 'apercufichinter' || $modulepart == 'apercuficheinter') && !empty($conf->ficheinter->dir_output))
2204  {
2205  if ($fuser->rights->ficheinter->{$lire}) $accessallowed=1;
2206  $original_file=$conf->ficheinter->dir_output.'/'.$original_file;
2207  }
2208  // Wrapping pour les apercu conat
2209  elseif (($modulepart == 'apercucontract') && !empty($conf->contrat->dir_output))
2210  {
2211  if ($fuser->rights->contrat->{$lire}) $accessallowed=1;
2212  $original_file=$conf->contrat->dir_output.'/'.$original_file;
2213  }
2214  // Wrapping pour les apercu supplier proposal
2215  elseif (($modulepart == 'apercusupplier_proposal' || $modulepart == 'apercusupplier_proposal') && !empty($conf->supplier_proposal->dir_output))
2216  {
2217  if ($fuser->rights->supplier_proposal->{$lire}) $accessallowed=1;
2218  $original_file=$conf->supplier_proposal->dir_output.'/'.$original_file;
2219  }
2220  // Wrapping pour les apercu supplier order
2221  elseif (($modulepart == 'apercusupplier_order' || $modulepart == 'apercusupplier_order') && !empty($conf->fournisseur->commande->dir_output))
2222  {
2223  if ($fuser->rights->fournisseur->commande->{$lire}) $accessallowed=1;
2224  $original_file=$conf->fournisseur->commande->dir_output.'/'.$original_file;
2225  }
2226  // Wrapping pour les apercu supplier invoice
2227  elseif (($modulepart == 'apercusupplier_invoice' || $modulepart == 'apercusupplier_invoice') && !empty($conf->fournisseur->facture->dir_output))
2228  {
2229  if ($fuser->rights->fournisseur->facture->{$lire}) $accessallowed=1;
2230  $original_file=$conf->fournisseur->facture->dir_output.'/'.$original_file;
2231  }
2232  // Wrapping pour les apercu supplier invoice
2233  elseif (($modulepart == 'apercuexpensereport') && !empty($conf->expensereport->dir_output))
2234  {
2235  if ($fuser->rights->expensereport->{$lire}) $accessallowed=1;
2236  $original_file=$conf->expensereport->dir_output.'/'.$original_file;
2237  }
2238  // Wrapping pour les images des stats propales
2239  elseif ($modulepart == 'propalstats' && !empty($conf->propal->multidir_temp[$entity]))
2240  {
2241  if ($fuser->rights->propale->{$lire}) $accessallowed=1;
2242  $original_file=$conf->propal->multidir_temp[$entity].'/'.$original_file;
2243  }
2244  // Wrapping pour les images des stats commandes
2245  elseif ($modulepart == 'orderstats' && !empty($conf->commande->dir_temp))
2246  {
2247  if ($fuser->rights->commande->{$lire}) $accessallowed=1;
2248  $original_file=$conf->commande->dir_temp.'/'.$original_file;
2249  }
2250  elseif ($modulepart == 'orderstatssupplier' && !empty($conf->fournisseur->dir_output))
2251  {
2252  if ($fuser->rights->fournisseur->commande->{$lire}) $accessallowed=1;
2253  $original_file=$conf->fournisseur->commande->dir_temp.'/'.$original_file;
2254  }
2255  // Wrapping pour les images des stats factures
2256  elseif ($modulepart == 'billstats' && !empty($conf->facture->dir_temp))
2257  {
2258  if ($fuser->rights->facture->{$lire}) $accessallowed=1;
2259  $original_file=$conf->facture->dir_temp.'/'.$original_file;
2260  }
2261  elseif ($modulepart == 'billstatssupplier' && !empty($conf->fournisseur->dir_output))
2262  {
2263  if ($fuser->rights->fournisseur->facture->{$lire}) $accessallowed=1;
2264  $original_file=$conf->fournisseur->facture->dir_temp.'/'.$original_file;
2265  }
2266  // Wrapping pour les images des stats expeditions
2267  elseif ($modulepart == 'expeditionstats' && !empty($conf->expedition->dir_temp))
2268  {
2269  if ($fuser->rights->expedition->{$lire}) $accessallowed=1;
2270  $original_file=$conf->expedition->dir_temp.'/'.$original_file;
2271  }
2272  // Wrapping pour les images des stats expeditions
2273  elseif ($modulepart == 'tripsexpensesstats' && !empty($conf->deplacement->dir_temp))
2274  {
2275  if ($fuser->rights->deplacement->{$lire}) $accessallowed=1;
2276  $original_file=$conf->deplacement->dir_temp.'/'.$original_file;
2277  }
2278  // Wrapping pour les images des stats expeditions
2279  elseif ($modulepart == 'memberstats' && !empty($conf->adherent->dir_temp))
2280  {
2281  if ($fuser->rights->adherent->{$lire}) $accessallowed=1;
2282  $original_file=$conf->adherent->dir_temp.'/'.$original_file;
2283  }
2284  // Wrapping pour les images des stats produits
2285  elseif (preg_match('/^productstats_/i',$modulepart) && !empty($conf->product->dir_temp))
2286  {
2287  if ($fuser->rights->produit->{$lire} || $fuser->rights->service->{$lire}) $accessallowed=1;
2288  $original_file=(!empty($conf->product->multidir_temp[$entity])?$conf->product->multidir_temp[$entity]:$conf->service->multidir_temp[$entity]).'/'.$original_file;
2289  }
2290  // Wrapping for taxes
2291  elseif ($modulepart == 'tax' && !empty($conf->tax->dir_output))
2292  {
2293  if ($fuser->rights->tax->charges->{$lire}) $accessallowed=1;
2294  $original_file=$conf->tax->dir_output.'/'.$original_file;
2295  }
2296  // Wrapping for events
2297  elseif ($modulepart == 'actions' && !empty($conf->agenda->dir_output))
2298  {
2299  if ($fuser->rights->agenda->myactions->{$read}) $accessallowed=1;
2300  $original_file=$conf->agenda->dir_output.'/'.$original_file;
2301  }
2302  // Wrapping for categories
2303  elseif ($modulepart == 'category' && !empty($conf->categorie->dir_output))
2304  {
2305  if (empty($entity) || empty($conf->categorie->multidir_output[$entity])) return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
2306  if ($fuser->rights->categorie->{$lire}) $accessallowed=1;
2307  $original_file=$conf->categorie->multidir_output[$entity].'/'.$original_file;
2308  }
2309  // Wrapping pour les prelevements
2310  elseif ($modulepart == 'prelevement' && !empty($conf->prelevement->dir_output))
2311  {
2312  if ($fuser->rights->prelevement->bons->{$lire} || preg_match('/^specimen/i',$original_file)) $accessallowed=1;
2313  $original_file=$conf->prelevement->dir_output.'/'.$original_file;
2314  }
2315  // Wrapping pour les graph energie
2316  elseif ($modulepart == 'graph_stock' && !empty($conf->stock->dir_temp))
2317  {
2318  $accessallowed=1;
2319  $original_file=$conf->stock->dir_temp.'/'.$original_file;
2320  }
2321  // Wrapping pour les graph fournisseurs
2322  elseif ($modulepart == 'graph_fourn' && !empty($conf->fournisseur->dir_temp))
2323  {
2324  $accessallowed=1;
2325  $original_file=$conf->fournisseur->dir_temp.'/'.$original_file;
2326  }
2327  // Wrapping pour les graph des produits
2328  elseif ($modulepart == 'graph_product' && !empty($conf->product->dir_temp))
2329  {
2330  $accessallowed=1;
2331  $original_file=$conf->product->multidir_temp[$entity].'/'.$original_file;
2332  }
2333  // Wrapping pour les code barre
2334  elseif ($modulepart == 'barcode')
2335  {
2336  $accessallowed=1;
2337  // If viewimage is called for barcode, we try to output an image on the fly, with no build of file on disk.
2338  //$original_file=$conf->barcode->dir_temp.'/'.$original_file;
2339  $original_file='';
2340  }
2341  // Wrapping pour les icones de background des mailings
2342  elseif ($modulepart == 'iconmailing' && !empty($conf->mailing->dir_temp))
2343  {
2344  $accessallowed=1;
2345  $original_file=$conf->mailing->dir_temp.'/'.$original_file;
2346  }
2347  // Wrapping pour le scanner
2348  elseif ($modulepart == 'scanner_user_temp' && !empty($conf->scanner->dir_temp))
2349  {
2350  $accessallowed=1;
2351  $original_file=$conf->scanner->dir_temp.'/'.$fuser->id.'/'.$original_file;
2352  }
2353  // Wrapping pour les images fckeditor
2354  elseif ($modulepart == 'fckeditor' && !empty($conf->fckeditor->dir_output))
2355  {
2356  $accessallowed=1;
2357  $original_file=$conf->fckeditor->dir_output.'/'.$original_file;
2358  }
2359 
2360  // Wrapping for users
2361  else if ($modulepart == 'user' && !empty($conf->user->dir_output))
2362  {
2363  $canreaduser=(! empty($fuser->admin) || $fuser->rights->user->user->{$lire});
2364  if ($fuser->id == (int) $refname) { $canreaduser=1; } // A user can always read its own card
2365  if ($canreaduser || preg_match('/^specimen/i',$original_file))
2366  {
2367  $accessallowed=1;
2368  }
2369  $original_file=$conf->user->dir_output.'/'.$original_file;
2370  }
2371 
2372  // Wrapping for third parties
2373  else if (($modulepart == 'company' || $modulepart == 'societe') && !empty($conf->societe->dir_output))
2374  {
2375  if (empty($entity) || empty($conf->societe->multidir_output[$entity])) return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
2376  if ($fuser->rights->societe->{$lire} || preg_match('/^specimen/i',$original_file))
2377  {
2378  $accessallowed=1;
2379  }
2380  $original_file=$conf->societe->multidir_output[$entity].'/'.$original_file;
2381  $sqlprotectagainstexternals = "SELECT rowid as fk_soc FROM ".MAIN_DB_PREFIX."societe WHERE rowid='".$db->escape($refname)."' AND entity IN (".getEntity('societe').")";
2382  }
2383 
2384  // Wrapping for contact
2385  else if ($modulepart == 'contact' && !empty($conf->societe->dir_output))
2386  {
2387  if (empty($entity) || empty($conf->societe->multidir_output[$entity])) return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
2388  if ($fuser->rights->societe->{$lire})
2389  {
2390  $accessallowed=1;
2391  }
2392  $original_file=$conf->societe->multidir_output[$entity].'/contact/'.$original_file;
2393  }
2394 
2395  // Wrapping for invoices
2396  else if (($modulepart == 'facture' || $modulepart == 'invoice') && !empty($conf->facture->dir_output))
2397  {
2398  if ($fuser->rights->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2399  {
2400  $accessallowed=1;
2401  }
2402  $original_file=$conf->facture->dir_output.'/'.$original_file;
2403  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2404  }
2405  // Wrapping for mass actions
2406  else if ($modulepart == 'massfilesarea_proposals' && !empty($conf->propal->multidir_output[$entity]))
2407  {
2408  if ($fuser->rights->propal->{$lire} || preg_match('/^specimen/i',$original_file))
2409  {
2410  $accessallowed=1;
2411  }
2412  $original_file=$conf->propal->multidir_output[$entity].'/temp/massgeneration/'.$user->id.'/'.$original_file;
2413  }
2414  else if ($modulepart == 'massfilesarea_orders')
2415  {
2416  if ($fuser->rights->commande->{$lire} || preg_match('/^specimen/i',$original_file))
2417  {
2418  $accessallowed=1;
2419  }
2420  $original_file=$conf->commande->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2421  }
2422  else if ($modulepart == 'massfilesarea_invoices')
2423  {
2424  if ($fuser->rights->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2425  {
2426  $accessallowed=1;
2427  }
2428  $original_file=$conf->facture->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2429  }
2430  else if ($modulepart == 'massfilesarea_expensereport')
2431  {
2432  if ($fuser->rights->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2433  {
2434  $accessallowed=1;
2435  }
2436  $original_file=$conf->expensereport->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2437  }
2438  else if ($modulepart == 'massfilesarea_interventions')
2439  {
2440  if ($fuser->rights->ficheinter->{$lire} || preg_match('/^specimen/i',$original_file))
2441  {
2442  $accessallowed=1;
2443  }
2444  $original_file=$conf->ficheinter->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2445  }
2446  else if ($modulepart == 'massfilesarea_supplier_proposal' && !empty($conf->supplier_proposal->dir_output))
2447  {
2448  if ($fuser->rights->supplier_proposal->{$lire} || preg_match('/^specimen/i',$original_file))
2449  {
2450  $accessallowed=1;
2451  }
2452  $original_file=$conf->supplier_proposal->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2453  }
2454  else if ($modulepart == 'massfilesarea_supplier_order')
2455  {
2456  if ($fuser->rights->fournisseur->commande->{$lire} || preg_match('/^specimen/i',$original_file))
2457  {
2458  $accessallowed=1;
2459  }
2460  $original_file=$conf->fournisseur->commande->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2461  }
2462  else if ($modulepart == 'massfilesarea_supplier_invoice')
2463  {
2464  if ($fuser->rights->fournisseur->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2465  {
2466  $accessallowed=1;
2467  }
2468  $original_file=$conf->fournisseur->facture->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2469  }
2470  else if ($modulepart == 'massfilesarea_contract' && !empty($conf->contrat->dir_output))
2471  {
2472  if ($fuser->rights->contrat->{$lire} || preg_match('/^specimen/i',$original_file))
2473  {
2474  $accessallowed=1;
2475  }
2476  $original_file=$conf->contrat->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2477  }
2478 
2479  // Wrapping for interventions
2480  else if (($modulepart == 'fichinter' || $modulepart == 'ficheinter') && !empty($conf->ficheinter->dir_output))
2481  {
2482  if ($fuser->rights->ficheinter->{$lire} || preg_match('/^specimen/i',$original_file))
2483  {
2484  $accessallowed=1;
2485  }
2486  $original_file=$conf->ficheinter->dir_output.'/'.$original_file;
2487  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2488  }
2489 
2490  // Wrapping pour les deplacements et notes de frais
2491  else if ($modulepart == 'deplacement' && !empty($conf->deplacement->dir_output))
2492  {
2493  if ($fuser->rights->deplacement->{$lire} || preg_match('/^specimen/i',$original_file))
2494  {
2495  $accessallowed=1;
2496  }
2497  $original_file=$conf->deplacement->dir_output.'/'.$original_file;
2498  //$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2499  }
2500  // Wrapping pour les propales
2501  else if (($modulepart == 'propal' || $modulepart == 'propale') && !empty($conf->propal->multidir_output[$entity]))
2502  {
2503  if ($fuser->rights->propale->{$lire} || preg_match('/^specimen/i',$original_file))
2504  {
2505  $accessallowed=1;
2506  }
2507  $original_file=$conf->propal->multidir_output[$entity].'/'.$original_file;
2508  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."propal WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2509  }
2510 
2511  // Wrapping pour les commandes
2512  else if (($modulepart == 'commande' || $modulepart == 'order') && !empty($conf->commande->dir_output))
2513  {
2514  if ($fuser->rights->commande->{$lire} || preg_match('/^specimen/i',$original_file))
2515  {
2516  $accessallowed=1;
2517  }
2518  $original_file=$conf->commande->dir_output.'/'.$original_file;
2519  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2520  }
2521 
2522  // Wrapping pour les projets
2523  else if ($modulepart == 'project' && !empty($conf->projet->dir_output))
2524  {
2525  if ($fuser->rights->projet->{$lire} || preg_match('/^specimen/i',$original_file))
2526  {
2527  $accessallowed=1;
2528  }
2529  $original_file=$conf->projet->dir_output.'/'.$original_file;
2530  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project').")";
2531  }
2532  else if ($modulepart == 'project_task' && !empty($conf->projet->dir_output))
2533  {
2534  if ($fuser->rights->projet->{$lire} || preg_match('/^specimen/i',$original_file))
2535  {
2536  $accessallowed=1;
2537  }
2538  $original_file=$conf->projet->dir_output.'/'.$original_file;
2539  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project').")";
2540  }
2541 
2542  // Wrapping pour les commandes fournisseurs
2543  else if (($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') && !empty($conf->fournisseur->commande->dir_output))
2544  {
2545  if ($fuser->rights->fournisseur->commande->{$lire} || preg_match('/^specimen/i',$original_file))
2546  {
2547  $accessallowed=1;
2548  }
2549  $original_file=$conf->fournisseur->commande->dir_output.'/'.$original_file;
2550  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande_fournisseur WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2551  }
2552 
2553  // Wrapping pour les factures fournisseurs
2554  else if (($modulepart == 'facture_fournisseur' || $modulepart == 'invoice_supplier') && !empty($conf->fournisseur->facture->dir_output))
2555  {
2556  if ($fuser->rights->fournisseur->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2557  {
2558  $accessallowed=1;
2559  }
2560  $original_file=$conf->fournisseur->facture->dir_output.'/'.$original_file;
2561  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture_fourn WHERE facnumber='".$db->escape($refname)."' AND entity=".$conf->entity;
2562  }
2563  // Wrapping pour les rapport de paiements
2564  else if ($modulepart == 'supplier_payment')
2565  {
2566  if ($fuser->rights->fournisseur->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2567  {
2568  $accessallowed=1;
2569  }
2570  $original_file=$conf->fournisseur->payment->dir_output.'/'.$original_file;
2571  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."paiementfournisseur WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2572  }
2573 
2574  // Wrapping pour les rapport de paiements
2575  else if ($modulepart == 'facture_paiement' && !empty($conf->facture->dir_output))
2576  {
2577  if ($fuser->rights->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2578  {
2579  $accessallowed=1;
2580  }
2581  if ($fuser->societe_id > 0) $original_file=$conf->facture->dir_output.'/payments/private/'.$fuser->id.'/'.$original_file;
2582  else $original_file=$conf->facture->dir_output.'/payments/'.$original_file;
2583  }
2584 
2585  // Wrapping for accounting exports
2586  else if ($modulepart == 'export_compta' && !empty($conf->accounting->dir_output))
2587  {
2588  if ($fuser->rights->accounting->bind->write || preg_match('/^specimen/i',$original_file))
2589  {
2590  $accessallowed=1;
2591  }
2592  $original_file=$conf->accounting->dir_output.'/'.$original_file;
2593  }
2594 
2595  // Wrapping pour les expedition
2596  else if ($modulepart == 'expedition' && !empty($conf->expedition->dir_output))
2597  {
2598  if ($fuser->rights->expedition->{$lire} || preg_match('/^specimen/i',$original_file))
2599  {
2600  $accessallowed=1;
2601  }
2602  $original_file=$conf->expedition->dir_output."/sending/".$original_file;
2603  }
2604  // Wrapping pour les bons de livraison
2605  else if ($modulepart == 'livraison' && !empty($conf->expedition->dir_output))
2606  {
2607  if ($fuser->rights->expedition->livraison->{$lire} || preg_match('/^specimen/i',$original_file))
2608  {
2609  $accessallowed=1;
2610  }
2611  $original_file=$conf->expedition->dir_output."/receipt/".$original_file;
2612  }
2613 
2614  // Wrapping pour les actions
2615  else if ($modulepart == 'actions' && !empty($conf->agenda->dir_output))
2616  {
2617  if ($fuser->rights->agenda->myactions->{$read} || preg_match('/^specimen/i',$original_file))
2618  {
2619  $accessallowed=1;
2620  }
2621  $original_file=$conf->agenda->dir_output.'/'.$original_file;
2622  }
2623 
2624  // Wrapping pour les actions
2625  else if ($modulepart == 'actionsreport' && !empty($conf->agenda->dir_temp))
2626  {
2627  if ($fuser->rights->agenda->allactions->{$read} || preg_match('/^specimen/i',$original_file))
2628  {
2629  $accessallowed=1;
2630  }
2631  $original_file = $conf->agenda->dir_temp."/".$original_file;
2632  }
2633 
2634  // Wrapping pour les produits et services
2635  else if ($modulepart == 'product' || $modulepart == 'produit' || $modulepart == 'service' || $modulepart == 'produit|service')
2636  {
2637  if (empty($entity) || (empty($conf->product->multidir_output[$entity]) && empty($conf->service->multidir_output[$entity]))) return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
2638  if (($fuser->rights->produit->{$lire} || $fuser->rights->service->{$lire}) || preg_match('/^specimen/i',$original_file))
2639  {
2640  $accessallowed=1;
2641  }
2642  if (! empty($conf->product->enabled)) $original_file=$conf->product->multidir_output[$entity].'/'.$original_file;
2643  elseif (! empty($conf->service->enabled)) $original_file=$conf->service->multidir_output[$entity].'/'.$original_file;
2644  }
2645 
2646  // Wrapping pour les lots produits
2647  else if ($modulepart == 'product_batch' || $modulepart == 'produitlot')
2648  {
2649  if (empty($entity) || (empty($conf->productbatch->multidir_output[$entity]))) return array('accessallowed'=>0, 'error'=>'Value entity must be provided');
2650  if (($fuser->rights->produit->{$lire} ) || preg_match('/^specimen/i',$original_file))
2651  {
2652  $accessallowed=1;
2653  }
2654  if (! empty($conf->productbatch->enabled)) $original_file=$conf->productbatch->multidir_output[$entity].'/'.$original_file;
2655  }
2656 
2657  // Wrapping pour les contrats
2658  else if ($modulepart == 'contract' && !empty($conf->contrat->dir_output))
2659  {
2660  if ($fuser->rights->contrat->{$lire} || preg_match('/^specimen/i',$original_file))
2661  {
2662  $accessallowed=1;
2663  }
2664  $original_file=$conf->contrat->dir_output.'/'.$original_file;
2665  $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."contrat WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('contract').")";
2666  }
2667 
2668  // Wrapping pour les dons
2669  else if ($modulepart == 'donation' && !empty($conf->don->dir_output))
2670  {
2671  if ($fuser->rights->don->{$lire} || preg_match('/^specimen/i',$original_file))
2672  {
2673  $accessallowed=1;
2674  }
2675  $original_file=$conf->don->dir_output.'/'.$original_file;
2676  }
2677 
2678  // Wrapping pour les dons
2679  else if ($modulepart == 'dolresource' && !empty($conf->resource->dir_output))
2680  {
2681  if ($fuser->rights->resource->{$read} || preg_match('/^specimen/i',$original_file))
2682  {
2683  $accessallowed=1;
2684  }
2685  $original_file=$conf->resource->dir_output.'/'.$original_file;
2686  }
2687 
2688  // Wrapping pour les remises de cheques
2689  else if ($modulepart == 'remisecheque' && !empty($conf->banque->dir_output))
2690  {
2691  if ($fuser->rights->banque->{$lire} || preg_match('/^specimen/i',$original_file))
2692  {
2693  $accessallowed=1;
2694  }
2695 
2696  $original_file=$conf->bank->dir_output.'/checkdeposits/'.$original_file; // original_file should contains relative path so include the get_exdir result
2697  }
2698 
2699  // Wrapping for bank
2700  else if ($modulepart == 'bank' && !empty($conf->bank->dir_output))
2701  {
2702  if ($fuser->rights->banque->{$lire})
2703  {
2704  $accessallowed=1;
2705  }
2706  $original_file=$conf->bank->dir_output.'/'.$original_file;
2707  }
2708 
2709  // Wrapping for export module
2710  else if ($modulepart == 'export' && !empty($conf->export->dir_temp))
2711  {
2712  // Aucun test necessaire car on force le rep de download sur
2713  // le rep export qui est propre a l'utilisateur
2714  $accessallowed=1;
2715  $original_file=$conf->export->dir_temp.'/'.$fuser->id.'/'.$original_file;
2716  }
2717 
2718  // Wrapping for import module
2719  else if ($modulepart == 'import' && !empty($conf->import->dir_temp))
2720  {
2721  $accessallowed=1;
2722  $original_file=$conf->import->dir_temp.'/'.$original_file;
2723  }
2724 
2725  // Wrapping pour l'editeur wysiwyg
2726  else if ($modulepart == 'editor' && !empty($conf->fckeditor->dir_output))
2727  {
2728  $accessallowed=1;
2729  $original_file=$conf->fckeditor->dir_output.'/'.$original_file;
2730  }
2731 
2732  // Wrapping for backups
2733  else if ($modulepart == 'systemtools' && !empty($conf->admin->dir_output))
2734  {
2735  if ($fuser->admin) $accessallowed=1;
2736  $original_file=$conf->admin->dir_output.'/'.$original_file;
2737  }
2738 
2739  // Wrapping for upload file test
2740  else if ($modulepart == 'admin_temp' && !empty($conf->admin->dir_temp))
2741  {
2742  if ($fuser->admin) $accessallowed=1;
2743  $original_file=$conf->admin->dir_temp.'/'.$original_file;
2744  }
2745 
2746  // Wrapping pour BitTorrent
2747  else if ($modulepart == 'bittorrent' && !empty($conf->bittorrent->dir_output))
2748  {
2749  $accessallowed=1;
2750  $dir='files';
2751  if (dol_mimetype($original_file) == 'application/x-bittorrent') $dir='torrents';
2752  $original_file=$conf->bittorrent->dir_output.'/'.$dir.'/'.$original_file;
2753  }
2754 
2755  // Wrapping pour Foundation module
2756  else if ($modulepart == 'member' && !empty($conf->adherent->dir_output))
2757  {
2758  if ($fuser->rights->adherent->{$lire} || preg_match('/^specimen/i',$original_file))
2759  {
2760  $accessallowed=1;
2761  }
2762  $original_file=$conf->adherent->dir_output.'/'.$original_file;
2763  }
2764 
2765  // Wrapping for Scanner
2766  else if ($modulepart == 'scanner_user_temp' && !empty($conf->scanner->dir_temp))
2767  {
2768  $accessallowed=1;
2769  $original_file=$conf->scanner->dir_temp.'/'.$fuser->id.'/'.$original_file;
2770  }
2771 
2772  // GENERIC Wrapping
2773  // If modulepart=module_user_temp Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/temp/iduser
2774  // If modulepart=module_temp Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/temp
2775  // If modulepart=module_user Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/iduser
2776  // If modulepart=module Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart
2777  else
2778  {
2779  if (preg_match('/^specimen/i',$original_file)) $accessallowed=1; // If link to a file called specimen. Test must be done before changing $original_file int full path.
2780  if ($fuser->admin) $accessallowed=1; // If user is admin
2781 
2782  // Define $accessallowed
2783  if (preg_match('/^([a-z]+)_user_temp$/i',$modulepart,$reg))
2784  {
2785  if (empty($conf->{$reg[1]}->dir_temp)) // modulepart not supported
2786  {
2787  dol_print_error('','Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')');
2788  exit;
2789  }
2790  if ($fuser->rights->{$reg[1]}->{$lire} || $fuser->rights->{$reg[1]}->{$read} || ($fuser->rights->{$reg[1]}->{$download})) $accessallowed=1;
2791  $original_file=$conf->{$reg[1]}->dir_temp.'/'.$fuser->id.'/'.$original_file;
2792  }
2793  else if (preg_match('/^([a-z]+)_temp$/i',$modulepart,$reg))
2794  {
2795  if (empty($conf->{$reg[1]}->dir_temp)) // modulepart not supported
2796  {
2797  dol_print_error('','Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')');
2798  exit;
2799  }
2800  if ($fuser->rights->{$reg[1]}->{$lire} || $fuser->rights->{$reg[1]}->{$read} || ($fuser->rights->{$reg[1]}->{$download})) $accessallowed=1;
2801  $original_file=$conf->{$reg[1]}->dir_temp.'/'.$original_file;
2802  }
2803  else if (preg_match('/^([a-z]+)_user$/i',$modulepart,$reg))
2804  {
2805  if (empty($conf->{$reg[1]}->dir_output)) // modulepart not supported
2806  {
2807  dol_print_error('','Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')');
2808  exit;
2809  }
2810  if ($fuser->rights->{$reg[1]}->{$lire} || $fuser->rights->{$reg[1]}->{$read} || ($fuser->rights->{$reg[1]}->{$download})) $accessallowed=1;
2811  $original_file=$conf->{$reg[1]}->dir_output.'/'.$fuser->id.'/'.$original_file;
2812  }
2813  else
2814  {
2815  if (empty($conf->$modulepart->dir_output)) // modulepart not supported
2816  {
2817  dol_print_error('','Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')');
2818  exit;
2819  }
2820 
2821  $perm=GETPOST('perm');
2822  $subperm=GETPOST('subperm');
2823  if ($perm || $subperm)
2824  {
2825  if (($perm && ! $subperm && $fuser->rights->$modulepart->$perm) || ($perm && $subperm && $fuser->rights->$modulepart->$perm->$subperm)) $accessallowed=1;
2826  $original_file=$conf->$modulepart->dir_output.'/'.$original_file;
2827  }
2828  else
2829  {
2830  if ($fuser->rights->$modulepart->{$lire} || $fuser->rights->$modulepart->{$read}) $accessallowed=1;
2831  $original_file=$conf->$modulepart->dir_output.'/'.$original_file;
2832  }
2833  }
2834 
2835  // For modules who wants to manage different levels of permissions for documents
2836  $subPermCategoryConstName = strtoupper($modulepart).'_SUBPERMCATEGORY_FOR_DOCUMENTS';
2837  if (! empty($conf->global->$subPermCategoryConstName))
2838  {
2839  $subPermCategory = $conf->global->$subPermCategoryConstName;
2840  if (! empty($subPermCategory) && (($fuser->rights->$modulepart->$subPermCategory->{$lire}) || ($fuser->rights->$modulepart->$subPermCategory->{$read}) || ($fuser->rights->$modulepart->$subPermCategory->{$download})))
2841  {
2842  $accessallowed=1;
2843  }
2844  }
2845 
2846  // Define $sqlprotectagainstexternals for modules who want to protect access using a SQL query.
2847  $sqlProtectConstName = strtoupper($modulepart).'_SQLPROTECTAGAINSTEXTERNALS_FOR_DOCUMENTS';
2848  if (! empty($conf->global->$sqlProtectConstName)) // If module want to define its own $sqlprotectagainstexternals
2849  {
2850  // Example: mymodule__SQLPROTECTAGAINSTEXTERNALS_FOR_DOCUMENTS = "SELECT fk_soc FROM ".MAIN_DB_PREFIX.$modulepart." WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2851  eval('$sqlprotectagainstexternals = "'.$conf->global->$sqlProtectConstName.'";');
2852  }
2853  }
2854 
2855  $ret = array(
2856  'accessallowed' => $accessallowed,
2857  'sqlprotectagainstexternals'=>$sqlprotectagainstexternals,
2858  'original_file'=>$original_file
2859  );
2860 
2861  return $ret;
2862 }
2863 
2872 function dol_filecache($directory, $filename, $object)
2873 {
2874  if (! dol_is_dir($directory)) dol_mkdir($directory);
2875  $cachefile = $directory . $filename;
2876  file_put_contents($cachefile, serialize($object), LOCK_EX);
2877  @chmod($cachefile, 0644);
2878 }
2879 
2888 function dol_cache_refresh($directory, $filename, $cachetime)
2889 {
2890  $now = dol_now();
2891  $cachefile = $directory . $filename;
2892  $refresh = !file_exists($cachefile) || ($now-$cachetime) > dol_filemtime($cachefile);
2893  return $refresh;
2894 }
2895 
2903 function dol_readcachefile($directory, $filename)
2904 {
2905  $cachefile = $directory . $filename;
2906  $object = unserialize(file_get_contents($cachefile));
2907  return $object;
2908 }
2909 
2910 
2922 function getFilesUpdated(&$file_list, SimpleXMLElement $dir, $path = '', $pathref = '', &$checksumconcat = array())
2923 {
2924  global $conffile;
2925 
2926  $exclude = 'install';
2927 
2928  foreach ($dir->md5file as $file) // $file is a simpleXMLElement
2929  {
2930  $filename = $path.$file['name'];
2931  $file_list['insignature'][] = $filename;
2932  $expectedmd5 = (string) $file;
2933 
2934  //if (preg_match('#'.$exclude.'#', $filename)) continue;
2935 
2936  if (!file_exists($pathref.'/'.$filename))
2937  {
2938  $file_list['missing'][] = array('filename'=>$filename, 'expectedmd5'=>$expectedmd5);
2939  }
2940  else
2941  {
2942  $md5_local = md5_file($pathref.'/'.$filename);
2943 
2944  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
2945  {
2946  $checksumconcat[] = $expectedmd5;
2947  }
2948  else
2949  {
2950  if ($md5_local != $expectedmd5) $file_list['updated'][] = array('filename'=>$filename, 'expectedmd5'=>$expectedmd5, 'md5'=>(string) $md5_local);
2951  $checksumconcat[] = $md5_local;
2952  }
2953  }
2954  }
2955 
2956  foreach ($dir->dir as $subdir) // $subdir['name'] is '' or '/accountancy/admin' for example
2957  {
2958  getFilesUpdated($file_list, $subdir, $path.$subdir['name'].'/', $pathref, $checksumconcat);
2959  }
2960 
2961  return $file_list;
2962 }
2963 
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
image_format_supported($file)
Return if a filename is file name of a supported image format.
Definition: images.lib.php:38
dol_compare_file($a, $b)
Fast compare of 2 files identified by their properties ->name, ->date and ->size. ...
Definition: files.lib.php:404
dol_copy($srcfile, $destfile, $newmask=0, $overwriteifexists=1)
Copy a file to another file.
Definition: files.lib.php:666
dol_compress_file($inputfile, $outputfile, $mode="gz")
Compress a file.
Definition: files.lib.php:1877
GETPOST($paramname, $check='none', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
Classe permettant la generation du formulaire html d&#39;envoi de mail unitaire Usage: $formail = new For...
dol_unescapefile($filename)
Unescape a file submitted by upload.
Definition: files.lib.php:942
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:229
dol_cache_refresh($directory, $filename, $cachetime)
Test if Refresh needed.
Definition: files.lib.php:2888
dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles='addedfile')
Make control on an uploaded file from an GUI page and move it to final destination.
Definition: files.lib.php:996
setEventMessages($mesg, $mesgs, $style='mesgs')
Set event messages in dol_events session object.
if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) if(! empty($conf->don->enabled) && $user->rights->societe->lire) if(! empty($conf->tax->enabled) && $user->rights->tax->charges->lire) if(! empty($conf->facture->enabled) &&! empty($conf->commande->enabled) && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1053
dolReplaceRegExInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, $indexdatabase=0)
Make replacement of strings into a file.
Definition: files.lib.php:651
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
completeFileArrayWithDatabaseInfo(&$filearray, $relativedir)
Complete $filearray with data from database.
Definition: files.lib.php:304
dol_delete_preview($object)
Delete all preview files linked to object instance.
Definition: files.lib.php:1324
dol_mimetype($file, $default='application/octet-stream', $mode=0)
Return mime type of a file.
Class to scan for virus.
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:1663
dol_filesize($pathoffile)
Return size of a file.
Definition: files.lib.php:552
dol_print_error($db='', $error='', $errors=null)
Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remonte...
dol_is_dir($folder)
Test if filename is a directory.
Definition: files.lib.php:438
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) ...
Definition: files.lib.php:2109
dolCheckVirus($src_file)
Check virus into a file.
Definition: files.lib.php:957
addFileIntoDatabaseIndex($dir, $file, $fullpathorig='', $mode='uploaded', $setsharekey=0)
Add a file into database index.
Definition: files.lib.php:1715
dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayreplacement=null)
Copy a dir to another dir.
Definition: files.lib.php:722
dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvirus=0, $indexdatabase=1)
Move a file into another name.
Definition: files.lib.php:814
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
dol_is_url($url)
Return if path is an URL.
Definition: files.lib.php:475
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesession=0, $varfiles='addedfile', $savingdocmask='', $link=null, $trackid='', $generatethumbs=1)
Get and save an upload file (for example after submitting a new file a mail form).
Definition: files.lib.php:1519
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories) ...
Definition: files.lib.php:1273
dol_basename($pathfile)
Make a basename working with all page code (default PHP basenamed fails with cyrillic).
Definition: files.lib.php:35
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1)
Remove a file or several files with a mask.
Definition: files.lib.php:1139
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:2091
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:59
dol_now($mode='gmt')
Return date for now.
utf8_check($str)
Check if a string is in UTF8.
dol_count_nb_of_line($file)
Count number of lines in a file.
Definition: files.lib.php:520
dol_is_file($pathoffile)
Return if path is a file.
Definition: files.lib.php:451
getRandomPassword($generic=false)
Return a generated password using default module.
dol_print_date($time, $format='', $tzoutput='tzserver', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_uncompress($inputfile, $outputdir)
Uncompress a file.
Definition: files.lib.php:1930
dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, $indexdatabase=0)
Make replacement of strings into a file.
Definition: files.lib.php:581
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:1481
dol_filemtime($pathoffile)
Return time of a file.
Definition: files.lib.php:564
dol_mkdir($dir, $dataroot='', $newmask=null)
Creation of a directory (this can create recursive subdir)
getFilesUpdated(&$file_list, SimpleXMLElement $dir, $path='', $pathref='', &$checksumconcat=array())
Function to get list of updated or modified files.
Definition: files.lib.php:2922
dol_readcachefile($directory, $filename)
Read object from cachefile.
Definition: files.lib.php:2903
dol_is_link($pathoffile)
Return if path is a symbolic link.
Definition: files.lib.php:463
make_substitutions($text, $substitutionarray, $outputlangs=null)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
dol_dir_is_emtpy($folder)
Test if a folder is empty.
Definition: files.lib.php:491
dol_convert_file($fileinput, $ext='png', $fileoutput='')
Convert an image file into another format.
Definition: files.lib.php:1819
dol_delete_dir($dir, $nophperrors=0)
Remove a directory (not recursive, so content must be empty).
Definition: files.lib.php:1249
Class to manage ECM files.
dol_meta_create($object)
Create a meta file with document file into same directory.
Definition: files.lib.php:1402
deleteFilesIntoDatabaseIndex($dir, $file, $mode='uploaded')
Delete files into database index using search criterias.
Definition: files.lib.php:1763
dol_filecache($directory, $filename, $object)
Store object in file.
Definition: files.lib.php:2872
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:352