PageRenderTime 66ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/htdocs/core/lib/files.lib.php

https://bitbucket.org/speedealing/speedealing
PHP | 1190 lines | 771 code | 117 blank | 302 comment | 253 complexity | fbb3fb6e1b6249be4322aff2feadbbaf MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, GPL-3.0, MIT
  1. <?php
  2. /* Copyright (C) 2008-2012 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2012 Regis Houssin <regis.houssin@capnetworks.com>
  4. * Copyright (C) 2012 Juanjo Menent <jmenent@2byte.es>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. * or see http://www.gnu.org/
  19. */
  20. /**
  21. * \file htdocs/core/lib/files.lib.php
  22. * \brief Library for file managing functions
  23. */
  24. /**
  25. * Make a basename working with all page code (default PHP basenamed fails with cyrillic).
  26. * We supose dir separator for input is '/'.
  27. *
  28. * @param string $pathfile String to find basename.
  29. * @return string Basename of input
  30. */
  31. function dol_basename($pathfile)
  32. {
  33. return preg_replace('/^.*\/([^\/]+)$/','$1',rtrim($pathfile,'/'));
  34. }
  35. /**
  36. * Scan a directory and return a list of files/directories.
  37. * Content for string is UTF8 and dir separator is "/".
  38. *
  39. * @param string $path Starting path from which to search
  40. * @param string $types Can be "directories", "files", or "all"
  41. * @param int $recursive Determines whether subdirectories are searched
  42. * @param string $filter Regex for include filter
  43. * @param string $excludefilter Array of Regex for exclude filter (example: array('\.meta$','^\.'))
  44. * @param string $sortcriteria Sort criteria ("","fullname","name","date","size")
  45. * @param string $sortorder Sort order (SORT_ASC, SORT_DESC)
  46. * @param int $mode 0=Return array minimum keys loaded (faster), 1=Force all keys like date and size to be loaded (slower), 2=Force load of date only, 3=Force load of size only
  47. * @return array Array of array('name'=>'xxx','fullname'=>'/abc/xxx','date'=>'yyy','size'=>99,'type'=>'dir|file')
  48. */
  49. function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter="", $sortcriteria="name", $sortorder=SORT_ASC, $mode=0)
  50. {
  51. $loaddate=($mode==1||$mode==2)?true:false;
  52. $loadsize=($mode==1||$mode==3)?true:false;
  53. // Clean parameters
  54. $path=preg_replace('/([\\/]+)$/i','',$path);
  55. $newpath=dol_osencode($path);
  56. if (! is_dir($newpath)) return array();
  57. if ($dir = opendir($newpath))
  58. {
  59. $filedate='';
  60. $filesize='';
  61. $file_list = array();
  62. while (false !== ($file = readdir($dir)))
  63. {
  64. if (! utf8_check($file)) $file=utf8_encode($file); // To be sure data is stored in utf8 in memory
  65. $qualified=1;
  66. // Define excludefilterarray
  67. $excludefilterarray=array('^\.');
  68. if (is_array($excludefilter))
  69. {
  70. $excludefilterarray=array_merge($excludefilterarray,$excludefilter);
  71. }
  72. else if ($excludefilter) $excludefilterarray[]=$excludefilter;
  73. // Check if file is qualified
  74. foreach($excludefilterarray as $filt)
  75. {
  76. if (preg_match('/'.$filt.'/i',$file)) {
  77. $qualified=0; break;
  78. }
  79. }
  80. if ($qualified)
  81. {
  82. $isdir=is_dir(dol_osencode($path."/".$file));
  83. // Check whether this is a file or directory and whether we're interested in that type
  84. if ($isdir && (($types=="directories") || ($types=="all") || $recursive))
  85. {
  86. // Add entry into file_list array
  87. if (($types=="directories") || ($types=="all"))
  88. {
  89. if ($loaddate || $sortcriteria == 'date') $filedate=dol_filemtime($path."/".$file);
  90. if ($loadsize || $sortcriteria == 'size') $filesize=dol_filesize($path."/".$file);
  91. if (! $filter || preg_match('/'.$filter.'/i',$path.'/'.$file))
  92. {
  93. $file_list[] = array(
  94. "name" => $file,
  95. "fullname" => $path.'/'.$file,
  96. "date" => $filedate,
  97. "size" => $filesize,
  98. "type" => 'dir'
  99. );
  100. }
  101. }
  102. // if we're in a directory and we want recursive behavior, call this function again
  103. if ($recursive)
  104. {
  105. $file_list = array_merge($file_list,dol_dir_list($path."/".$file, $types, $recursive, $filter, $excludefilter, $sortcriteria, $sortorder, $mode));
  106. }
  107. }
  108. else if (! $isdir && (($types == "files") || ($types == "all")))
  109. {
  110. // Add file into file_list array
  111. if ($loaddate || $sortcriteria == 'date') $filedate=dol_filemtime($path."/".$file);
  112. if ($loadsize || $sortcriteria == 'size') $filesize=dol_filesize($path."/".$file);
  113. if (! $filter || preg_match('/'.$filter.'/i',$path.'/'.$file))
  114. {
  115. $file_list[] = array(
  116. "name" => $file,
  117. "fullname" => $path.'/'.$file,
  118. "date" => $filedate,
  119. "size" => $filesize,
  120. "type" => 'file'
  121. );
  122. }
  123. }
  124. }
  125. }
  126. closedir($dir);
  127. // Obtain a list of columns
  128. if (! empty($sortcriteria))
  129. {
  130. $myarray=array();
  131. foreach ($file_list as $key => $row)
  132. {
  133. $myarray[$key] = (isset($row[$sortcriteria])?$row[$sortcriteria]:'');
  134. }
  135. // Sort the data
  136. if ($sortorder) array_multisort($myarray, $sortorder, $file_list);
  137. }
  138. return $file_list;
  139. }
  140. else
  141. {
  142. return array();
  143. }
  144. }
  145. /**
  146. * Fast compare of 2 files identified by their properties ->name, ->date and ->size
  147. *
  148. * @param string $a File 1
  149. * @param string $b File 2
  150. * @return int 1, 0, 1
  151. */
  152. function dol_compare_file($a, $b)
  153. {
  154. global $sortorder;
  155. global $sortfield;
  156. $sortorder=strtoupper($sortorder);
  157. if ($sortorder == 'ASC') { $retup=-1; $retdown=1; }
  158. else { $retup=1; $retdown=-1; }
  159. if ($sortfield == 'name')
  160. {
  161. if ($a->name == $b->name) return 0;
  162. return ($a->name < $b->name) ? $retup : $retdown;
  163. }
  164. if ($sortfield == 'date')
  165. {
  166. if ($a->date == $b->date) return 0;
  167. return ($a->date < $b->date) ? $retup : $retdown;
  168. }
  169. if ($sortfield == 'size')
  170. {
  171. if ($a->size == $b->size) return 0;
  172. return ($a->size < $b->size) ? $retup : $retdown;
  173. }
  174. }
  175. /**
  176. * Return mime type of a file
  177. *
  178. * @param string $file Filename we looking for MIME type
  179. * @param string $default Default mime type if extension not found in known list
  180. * @param int $mode 0=Return full mime, 1=otherwise short mime string, 2=image for mime type, 3=source language
  181. * @return string Return a mime type family (text/xxx, application/xxx, image/xxx, audio, video, archive)
  182. * @see image_format_supported (images.lib.php)
  183. */
  184. function dol_mimetype($file,$default='application/octet-stream',$mode=0)
  185. {
  186. $mime=$default;
  187. $imgmime='other.png';
  188. $srclang='';
  189. $tmpfile=preg_replace('/\.noexe$/','',$file);
  190. // Text files
  191. if (preg_match('/\.txt$/i',$tmpfile)) { $mime='text/plain'; $imgmime='text.png'; }
  192. if (preg_match('/\.rtx$/i',$tmpfile)) { $mime='text/richtext'; $imgmime='text.png'; }
  193. if (preg_match('/\.csv$/i',$tmpfile)) { $mime='text/csv'; $imgmime='text.png'; }
  194. if (preg_match('/\.tsv$/i',$tmpfile)) { $mime='text/tab-separated-values'; $imgmime='text.png'; }
  195. if (preg_match('/\.(cf|conf|log)$/i',$tmpfile)) { $mime='text/plain'; $imgmime='text.png'; }
  196. if (preg_match('/\.ini$/i',$tmpfile)) { $mime='text/plain'; $imgmime='text.png'; $srclang='ini'; }
  197. if (preg_match('/\.css$/i',$tmpfile)) { $mime='text/css'; $imgmime='css.png'; $srclang='css'; }
  198. // Certificate files
  199. if (preg_match('/\.(crt|cer|key|pub)$/i',$tmpfile)) { $mime='text/plain'; $imgmime='text.png'; }
  200. // HTML/XML
  201. if (preg_match('/\.(html|htm|shtml)$/i',$tmpfile)) { $mime='text/html'; $imgmime='html.png'; $srclang='html'; }
  202. if (preg_match('/\.(xml|xhtml)$/i',$tmpfile)) { $mime='text/xml'; $imgmime='other.png'; $srclang='xml'; }
  203. // Languages
  204. if (preg_match('/\.bas$/i',$tmpfile)) { $mime='text/plain'; $imgmime='text.png'; $srclang='bas'; }
  205. if (preg_match('/\.(c)$/i',$tmpfile)) { $mime='text/plain'; $imgmime='text.png'; $srclang='c'; }
  206. if (preg_match('/\.(cpp)$/i',$tmpfile)) { $mime='text/plain'; $imgmime='text.png'; $srclang='cpp'; }
  207. if (preg_match('/\.(h)$/i',$tmpfile)) { $mime='text/plain'; $imgmime='text.png'; $srclang='h'; }
  208. if (preg_match('/\.(java|jsp)$/i',$tmpfile)) { $mime='text/plain'; $imgmime='text.png'; $srclang='java'; }
  209. if (preg_match('/\.php([0-9]{1})?$/i',$tmpfile)) { $mime='text/plain'; $imgmime='php.png'; $srclang='php'; }
  210. if (preg_match('/\.(pl|pm)$/i',$tmpfile)) { $mime='text/plain'; $imgmime='pl.png'; $srclang='perl'; }
  211. if (preg_match('/\.sql$/i',$tmpfile)) { $mime='text/plain'; $imgmime='text.png'; $srclang='sql'; }
  212. if (preg_match('/\.js$/i',$tmpfile)) { $mime='text/x-javascript'; $imgmime='jscript.png'; $srclang='js'; }
  213. // Open office
  214. if (preg_match('/\.odp$/i',$tmpfile)) { $mime='application/vnd.oasis.opendocument.presentation'; $imgmime='ooffice.png'; }
  215. if (preg_match('/\.ods$/i',$tmpfile)) { $mime='application/vnd.oasis.opendocument.spreadsheet'; $imgmime='ooffice.png'; }
  216. if (preg_match('/\.odt$/i',$tmpfile)) { $mime='application/vnd.oasis.opendocument.text'; $imgmime='ooffice.png'; }
  217. // MS Office
  218. if (preg_match('/\.mdb$/i',$tmpfile)) { $mime='application/msaccess'; $imgmime='mdb.png'; }
  219. if (preg_match('/\.doc(x|m)?$/i',$tmpfile)) { $mime='application/msword'; $imgmime='doc.png'; }
  220. if (preg_match('/\.dot(x|m)?$/i',$tmpfile)) { $mime='application/msword'; $imgmime='doc.png'; }
  221. if (preg_match('/\.xlt(x)?$/i',$tmpfile)) { $mime='application/vnd.ms-excel'; $imgmime='xls.png'; }
  222. if (preg_match('/\.xla(m)?$/i',$tmpfile)) { $mime='application/vnd.ms-excel'; $imgmime='xls.png'; }
  223. if (preg_match('/\.xls$/i',$tmpfile)) { $mime='application/vnd.ms-excel'; $imgmime='xls.png'; }
  224. if (preg_match('/\.xls(b|m|x)$/i',$tmpfile)) { $mime='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; $imgmime='xls.png'; }
  225. if (preg_match('/\.pps(m|x)?$/i',$tmpfile)) { $mime='application/vnd.ms-powerpoint'; $imgmime='ppt.png'; }
  226. if (preg_match('/\.ppt(m|x)?$/i',$tmpfile)) { $mime='application/x-mspowerpoint'; $imgmime='ppt.png'; }
  227. // Other
  228. if (preg_match('/\.pdf$/i',$tmpfile)) { $mime='application/pdf'; $imgmime='pdf.png'; }
  229. // Scripts
  230. if (preg_match('/\.bat$/i',$tmpfile)) { $mime='text/x-bat'; $imgmime='script.png'; $srclang='dos'; }
  231. if (preg_match('/\.sh$/i',$tmpfile)) { $mime='text/x-sh'; $imgmime='script.png'; $srclang='bash'; }
  232. if (preg_match('/\.ksh$/i',$tmpfile)) { $mime='text/x-ksh'; $imgmime='script.png'; $srclang='bash'; }
  233. if (preg_match('/\.bash$/i',$tmpfile)) { $mime='text/x-bash'; $imgmime='script.png'; $srclang='bash'; }
  234. // Images
  235. if (preg_match('/\.ico$/i',$tmpfile)) { $mime='image/x-icon'; $imgmime='image.png'; }
  236. if (preg_match('/\.(jpg|jpeg)$/i',$tmpfile)) { $mime='image/jpeg'; $imgmime='image.png'; }
  237. if (preg_match('/\.png$/i',$tmpfile)) { $mime='image/png'; $imgmime='image.png'; }
  238. if (preg_match('/\.gif$/i',$tmpfile)) { $mime='image/gif'; $imgmime='image.png'; }
  239. if (preg_match('/\.bmp$/i',$tmpfile)) { $mime='image/bmp'; $imgmime='image.png'; }
  240. if (preg_match('/\.(tif|tiff)$/i',$tmpfile)) { $mime='image/tiff'; $imgmime='image.png'; }
  241. // Calendar
  242. if (preg_match('/\.vcs$/i',$tmpfile)) { $mime='text/calendar'; $imgmime='other.png'; }
  243. if (preg_match('/\.ics$/i',$tmpfile)) { $mime='text/calendar'; $imgmime='other.png'; }
  244. // Other
  245. if (preg_match('/\.torrent$/i',$tmpfile)) { $mime='application/x-bittorrent'; $imgmime='other.png'; }
  246. // Audio
  247. if (preg_match('/\.(mp3|ogg|au|wav|wma|mid)$/i',$tmpfile)) { $mime='audio'; $imgmime='audio.png'; }
  248. // Video
  249. if (preg_match('/\.ogv$/i',$tmpfile)) { $mime='video/ogg'; $imgmime='video.png'; }
  250. if (preg_match('/\.webm$/i',$tmpfile)) { $mime='video/webm'; $imgmime='video.png'; }
  251. if (preg_match('/\.avi$/i',$tmpfile)) { $mime='video/x-msvideo'; $imgmime='video.png'; }
  252. if (preg_match('/\.divx$/i',$tmpfile)) { $mime='video/divx'; $imgmime='video.png'; }
  253. if (preg_match('/\.xvid$/i',$tmpfile)) { $mime='video/xvid'; $imgmime='video.png'; }
  254. if (preg_match('/\.(wmv|mpg|mpeg)$/i',$tmpfile)) { $mime='video'; $imgmime='video.png'; }
  255. // Archive
  256. if (preg_match('/\.(zip|rar|gz|tgz|z|cab|bz2|7z|tar|lzh)$/i',$tmpfile)) { $mime='archive'; $imgmime='archive.png'; } // application/xxx where zzz is zip, ...
  257. // Exe
  258. if (preg_match('/\.(exe|com)$/i',$tmpfile)) { $mime='application/octet-stream'; $imgmime='other.png'; }
  259. // Lib
  260. if (preg_match('/\.(dll|lib|o|so|a)$/i',$tmpfile)) { $mime='library'; $imgmime='library.png'; }
  261. // Err
  262. if (preg_match('/\.err$/i',$tmpfile)) { $mime='error'; $imgmime='error.png'; }
  263. // Return string
  264. if ($mode == 1)
  265. {
  266. $tmp=explode('/',$mime);
  267. return (! empty($tmp[1])?$tmp[1]:$tmp[0]);
  268. }
  269. if ($mode == 2)
  270. {
  271. return $imgmime;
  272. }
  273. if ($mode == 3)
  274. {
  275. return $srclang;
  276. }
  277. return $mime;
  278. }
  279. /**
  280. * Test if filename is a directory
  281. *
  282. * @param string $folder Name of folder
  283. * @return boolean True if it's a directory, False if not found
  284. */
  285. function dol_is_dir($folder)
  286. {
  287. $newfolder=dol_osencode($folder);
  288. if (is_dir($newfolder)) return true;
  289. else return false;
  290. }
  291. /**
  292. * Return if path is a file
  293. *
  294. * @param string $pathoffile Path of file
  295. * @return boolean True or false
  296. */
  297. function dol_is_file($pathoffile)
  298. {
  299. $newpathoffile=dol_osencode($pathoffile);
  300. return is_file($newpathoffile);
  301. }
  302. /**
  303. * Return if path is an URL
  304. *
  305. * @param string $url Url
  306. * @return boolean True or false
  307. */
  308. function dol_is_url($url)
  309. {
  310. $tmpprot=array('file','http','https','ftp','zlib','data','ssh','ssh2','ogg','expect');
  311. foreach($tmpprot as $prot)
  312. {
  313. if (preg_match('/^'.$prot.':/i',$url)) return true;
  314. }
  315. return false;
  316. }
  317. /**
  318. * Test if a folder is empty
  319. *
  320. * @param string $folder Name of folder
  321. * @return boolean True if dir is empty or non-existing, False if it contains files
  322. */
  323. function dol_dir_is_emtpy($folder)
  324. {
  325. $newfolder=dol_osencode($folder);
  326. if (is_dir($newfolder))
  327. {
  328. $handle = opendir($newfolder);
  329. while ((gettype($name = readdir($handle)) != "boolean"))
  330. {
  331. $name_array[] = $name;
  332. }
  333. foreach($name_array as $temp) $folder_content .= $temp;
  334. if ($folder_content == "...") return true;
  335. else return false;
  336. closedir($handle);
  337. }
  338. else
  339. return true; // Dir does not exists
  340. }
  341. /**
  342. * Count number of lines in a file
  343. *
  344. * @param string $file Filename
  345. * @return int <0 if KO, Number of lines in files if OK
  346. */
  347. function dol_count_nb_of_line($file)
  348. {
  349. $nb=0;
  350. $newfile=dol_osencode($file);
  351. //print 'x'.$file;
  352. $fp=fopen($newfile,'r');
  353. if ($fp)
  354. {
  355. while (!feof($fp))
  356. {
  357. $line=fgets($fp);
  358. // 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.
  359. if (! $line === false) $nb++;
  360. }
  361. fclose($fp);
  362. }
  363. else
  364. {
  365. $nb=-1;
  366. }
  367. return $nb;
  368. }
  369. /**
  370. * Return size of a file
  371. *
  372. * @param tring $pathoffile Path of file
  373. * @return string File size
  374. */
  375. function dol_filesize($pathoffile)
  376. {
  377. $newpathoffile=dol_osencode($pathoffile);
  378. return filesize($newpathoffile);
  379. }
  380. /**
  381. * Return time of a file
  382. *
  383. * @param string $pathoffile Path of file
  384. * @return timestamp Time of file
  385. */
  386. function dol_filemtime($pathoffile)
  387. {
  388. $newpathoffile=dol_osencode($pathoffile);
  389. return date("c", @filemtime($newpathoffile)); // @Is to avoid errors if files does not exists
  390. }
  391. /**
  392. * Copy a file to another file.
  393. *
  394. * @param string $srcfile Source file (can't be a directory)
  395. * @param string $destfile Destination file (can't be a directory)
  396. * @param int $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK)
  397. * @param int $overwriteifexists Overwrite file if exists (1 by default)
  398. * @return int <0 if error, 0 if nothing done (dest file already exists and overwriteifexists=0), >0 if OK
  399. */
  400. function dol_copy($srcfile, $destfile, $newmask=0, $overwriteifexists=1)
  401. {
  402. global $conf;
  403. dol_syslog("files.lib.php::dol_copy srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." overwritifexists=".$overwriteifexists);
  404. $destexists=dol_is_file($destfile);
  405. if (! $overwriteifexists && $destexists) return 0;
  406. $newpathofsrcfile=dol_osencode($srcfile);
  407. $newpathofdestfile=dol_osencode($destfile);
  408. $newdirdestfile=dirname($newpathofdestfile);
  409. if ($destexists && ! is_writable($newpathofdestfile))
  410. {
  411. dol_syslog("files.lib.php::dol_copy failed Permission denied to overwrite target file", LOG_WARNING);
  412. return -1;
  413. }
  414. if (! is_writable($newdirdestfile))
  415. {
  416. dol_syslog("files.lib.php::dol_copy failed Permission denied to write into target directory ".$newdirdestfile, LOG_WARNING);
  417. return -2;
  418. }
  419. // Copy with overwriting if exists
  420. $result=@copy($newpathofsrcfile, $newpathofdestfile);
  421. //$result=copy($newpathofsrcfile, $newpathofdestfile); // To see errors, remove @
  422. if (! $result)
  423. {
  424. dol_syslog("files.lib.php::dol_copy failed to copy", LOG_WARNING);
  425. return -3;
  426. }
  427. if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $newmask=$conf->global->MAIN_UMASK;
  428. @chmod($newpathofdestfile, octdec($newmask));
  429. return 1;
  430. }
  431. /**
  432. * Move a file into another name.
  433. * This function differs from dol_move_uploaded_file, because it can be called in any context.
  434. *
  435. * @param string $srcfile Source file (can't be a directory)
  436. * @param string $destfile Destination file (can't be a directory)
  437. * @param string $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK)
  438. * @param int $overwriteifexists Overwrite file if exists (1 by default)
  439. * @return boolean True if OK, false if KO
  440. */
  441. function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1)
  442. {
  443. global $conf;
  444. $result=false;
  445. dol_syslog("files.lib.php::dol_move srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." overwritifexists=".$overwriteifexists);
  446. if ($overwriteifexists || ! dol_is_file($destfile))
  447. {
  448. $newpathofsrcfile=dol_osencode($srcfile);
  449. $newpathofdestfile=dol_osencode($destfile);
  450. $result=@rename($newpathofsrcfile, $newpathofdestfile); // To see errors, remove @
  451. if (! $result) dol_syslog("files.lib.php::dol_move failed", LOG_WARNING);
  452. if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $newmask=$conf->global->MAIN_UMASK;
  453. @chmod($newpathofsrcfile, octdec($newmask));
  454. }
  455. return $result;
  456. }
  457. /**
  458. * Unescape a file submitted by upload.
  459. * PHP escape char " (%22) or char ' (%27) into $FILES.
  460. *
  461. * @param string $filename Filename
  462. * @return string Filename sanitized
  463. */
  464. function dol_unescapefile($filename)
  465. {
  466. // Remove path information and dots around the filename, to prevent uploading
  467. // into different directories or replacing hidden system files.
  468. // Also remove control characters and spaces (\x00..\x20) around the filename:
  469. return trim(basename($filename), ".\x00..\x20");
  470. }
  471. /**
  472. * Make control on an uploaded file from an GUI page and move it to final destination.
  473. * If there is errors (virus found, antivir in error, bad filename), file is not moved.
  474. * Note: This function can be used only into a HTML page context. Use dol_move if you are outside.
  475. *
  476. * @param string $src_file Source full path filename ($_FILES['field']['tmp_name'])
  477. * @param string $dest_file Target full path filename ($_FILES['field']['name'])
  478. * @param int $allowoverwrite 1=Overwrite target file if it already exists
  479. * @param int $disablevirusscan 1=Disable virus scan
  480. * @param string $uploaderrorcode Value of PHP upload error code ($_FILES['field']['error'])
  481. * @param int $nohook Disable all hooks
  482. * @param string $varfiles _FILES var name
  483. * @return int >0 if OK, <0 or string if KO
  484. * @see dol_move
  485. */
  486. function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles='addedfile')
  487. {
  488. global $conf, $db, $user, $langs;
  489. global $object, $hookmanager;
  490. $error=0;
  491. $file_name = $dest_file;
  492. if (empty($nohook))
  493. {
  494. // If an upload error has been reported
  495. if ($uploaderrorcode)
  496. {
  497. switch($uploaderrorcode)
  498. {
  499. case UPLOAD_ERR_INI_SIZE: // 1
  500. return 'ErrorFileSizeTooLarge';
  501. break;
  502. case UPLOAD_ERR_FORM_SIZE: // 2
  503. return 'ErrorFileSizeTooLarge';
  504. break;
  505. case UPLOAD_ERR_PARTIAL: // 3
  506. return 'ErrorPartialFile';
  507. break;
  508. case UPLOAD_ERR_NO_TMP_DIR: //
  509. return 'ErrorNoTmpDir';
  510. break;
  511. case UPLOAD_ERR_CANT_WRITE:
  512. return 'ErrorFailedToWriteInDir';
  513. break;
  514. case UPLOAD_ERR_EXTENSION:
  515. return 'ErrorUploadBlockedByAddon';
  516. break;
  517. default:
  518. break;
  519. }
  520. }
  521. // If we need to make a virus scan
  522. if (empty($disablevirusscan) && file_exists($src_file) && ! empty($conf->global->MAIN_ANTIVIRUS_COMMAND))
  523. {
  524. if (! class_exists('AntiVir')) {
  525. require DOL_DOCUMENT_ROOT.'/core/class/antivir.class.php';
  526. }
  527. $antivir=new AntiVir($db);
  528. $result = $antivir->dol_avscan_file($src_file);
  529. if ($result < 0) // If virus or error, we stop here
  530. {
  531. $reterrors=$antivir->errors;
  532. dol_syslog('Files.lib::dol_move_uploaded_file File "'.$src_file.'" (target name "'.$dest_file.'") KO with antivirus: result='.$result.' errors='.join(',',$antivir->errors), LOG_WARNING);
  533. return 'ErrorFileIsInfectedWithAVirus: '.join(',',$reterrors);
  534. }
  535. }
  536. // Security:
  537. // Disallow file with some extensions. We renamed them.
  538. // Car si on a mis le rep documents dans un rep de la racine web (pas bien), cela permet d'executer du code a la demande.
  539. if (preg_match('/\.htm|\.html|\.php|\.pl|\.cgi$/i',$dest_file))
  540. {
  541. $file_name.= '.noexe';
  542. }
  543. // Security:
  544. // On interdit fichiers caches, remontees de repertoire ainsi que les pipes dans les noms de fichiers.
  545. if (preg_match('/^\./',$src_file) || preg_match('/\.\./',$src_file) || preg_match('/[<>|]/',$src_file))
  546. {
  547. dol_syslog("Refused to deliver file ".$src_file, LOG_WARNING);
  548. return -1;
  549. }
  550. // Security:
  551. // On interdit fichiers caches, remontees de repertoire ainsi que les pipe dans
  552. // les noms de fichiers.
  553. if (preg_match('/^\./',$dest_file) || preg_match('/\.\./',$dest_file) || preg_match('/[<>|]/',$dest_file))
  554. {
  555. dol_syslog("Refused to deliver file ".$dest_file, LOG_WARNING);
  556. return -2;
  557. }
  558. // Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
  559. $hookmanager->initHooks(array('fileslib'));
  560. $parameters=array('filename' => $file_name, 'varfiles' => $varfiles, 'allowoverwrite' => $allowoverwrite);
  561. $reshook=$hookmanager->executeHooks('moveUploadedFile', $parameters, $object);
  562. }
  563. if (empty($reshook))
  564. {
  565. // The file functions must be in OS filesystem encoding.
  566. $src_file_osencoded=dol_osencode($src_file);
  567. $file_name_osencoded=dol_osencode($file_name);
  568. // Check if destination dir is writable
  569. // TODO
  570. // Check if destination file already exists
  571. if (! $allowoverwrite)
  572. {
  573. if (file_exists($file_name_osencoded))
  574. {
  575. dol_syslog("Files.lib::dol_move_uploaded_file File ".$file_name." already exists. Return 'ErrorFileAlreadyExists'", LOG_WARNING);
  576. return 'ErrorFileAlreadyExists';
  577. }
  578. }
  579. // Move file
  580. $return=move_uploaded_file($src_file_osencoded, $file_name_osencoded);
  581. if ($return)
  582. {
  583. if (! empty($conf->global->MAIN_UMASK)) @chmod($file_name_osencoded, octdec($conf->global->MAIN_UMASK));
  584. dol_syslog("Files.lib::dol_move_uploaded_file Success to move ".$src_file." to ".$file_name." - Umask=".$conf->global->MAIN_UMASK, LOG_DEBUG);
  585. return 1; // Success
  586. }
  587. else
  588. {
  589. dol_syslog("Files.lib::dol_move_uploaded_file Failed to move ".$src_file." to ".$file_name, LOG_ERR);
  590. return -3; // Unknown error
  591. }
  592. }
  593. }
  594. /**
  595. * Remove a file or several files with a mask
  596. *
  597. * @param string $file File to delete or mask of file to delete
  598. * @param int $disableglob Disable usage of glob like *
  599. * @param int $nophperrors Disable all PHP output errors
  600. * @param int $nohook Disable all hooks
  601. * @param object $object Current object in use
  602. * @return boolean True if file is deleted, False if error
  603. */
  604. function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=null)
  605. {
  606. global $db, $conf, $user, $langs, $hookmanager;
  607. $langs->load("other");
  608. $langs->load("errors");
  609. if (empty($nohook))
  610. {
  611. // Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
  612. $hookmanager->initHooks(array('fileslib'));
  613. $parameters=array(
  614. 'GET' => $_GET,
  615. 'file' => $file,
  616. 'disableglob'=> $disableglob,
  617. 'nophperrors' => $nophperrors
  618. );
  619. $reshook=$hookmanager->executeHooks('deleteFile', $parameters, $object);
  620. }
  621. if (empty($nohook) && isset($reshook) && $reshook != '') // 0:not deleted, 1:deleted, null or '' for bypass
  622. {
  623. return $reshook;
  624. }
  625. else
  626. {
  627. $error=0;
  628. //print "x".$file." ".$disableglob;
  629. $ok=true;
  630. $file_osencoded=dol_osencode($file); // New filename encoded in OS filesystem encoding charset
  631. if (empty($disableglob) && ! empty($file_osencoded))
  632. {
  633. foreach (glob($file_osencoded) as $filename)
  634. {
  635. if ($nophperrors) $ok=@unlink($filename); // The unlink encapsulated by dolibarr
  636. else $ok=unlink($filename); // The unlink encapsulated by dolibarr
  637. if ($ok) dol_syslog("Removed file ".$filename, LOG_DEBUG);
  638. else dol_syslog("Failed to remove file ".$filename, LOG_WARNING);
  639. }
  640. }
  641. else
  642. {
  643. if ($nophperrors) $ok=@unlink($file_osencoded); // The unlink encapsulated by dolibarr
  644. else $ok=unlink($file_osencoded); // The unlink encapsulated by dolibarr
  645. if ($ok) dol_syslog("Removed file ".$file_osencoded, LOG_DEBUG);
  646. else dol_syslog("Failed to remove file ".$file_osencoded, LOG_WARNING);
  647. }
  648. return $ok;
  649. }
  650. }
  651. /**
  652. * Remove a directory (not recursive, so content must be empty).
  653. * If directory is not empty, return false
  654. *
  655. * @param string $dir Directory to delete
  656. * @param int $nophperrors Disable all PHP output errors
  657. * @return boolean True if success, false if error
  658. */
  659. function dol_delete_dir($dir,$nophperrors=0)
  660. {
  661. $dir_osencoded=dol_osencode($dir);
  662. return ($nophperrors?@rmdir($dir_osencoded):rmdir($dir_osencoded));
  663. }
  664. /**
  665. * Remove a directory $dir and its subdirectories
  666. *
  667. * @param string $dir Dir to delete
  668. * @param int $count Counter to count nb of deleted elements
  669. * @param int $nophperrors Disable all PHP output errors
  670. * @return int Number of files and directory removed
  671. */
  672. function dol_delete_dir_recursive($dir,$count=0,$nophperrors=0)
  673. {
  674. dol_syslog("functions.lib:dol_delete_dir_recursive ".$dir,LOG_DEBUG);
  675. if (dol_is_dir($dir))
  676. {
  677. $dir_osencoded=dol_osencode($dir);
  678. if ($handle = opendir("$dir_osencoded"))
  679. {
  680. while (false !== ($item = readdir($handle)))
  681. {
  682. if (! utf8_check($item)) $item=utf8_encode($item); // should be useless
  683. if ($item != "." && $item != "..")
  684. {
  685. if (is_dir(dol_osencode("$dir/$item")))
  686. {
  687. $count=dol_delete_dir_recursive("$dir/$item",$count,$nophperrors);
  688. }
  689. else
  690. {
  691. dol_delete_file("$dir/$item",1,$nophperrors);
  692. $count++;
  693. //echo " removing $dir/$item<br>\n";
  694. }
  695. }
  696. }
  697. closedir($handle);
  698. dol_delete_dir($dir,$nophperrors);
  699. $count++;
  700. //echo "removing $dir<br>\n";
  701. }
  702. }
  703. //echo "return=".$count;
  704. return $count;
  705. }
  706. /**
  707. * Delete all preview files linked to object instance
  708. *
  709. * @param Object $object Object to clean
  710. * @return int 0 if error, 1 if OK
  711. */
  712. function dol_delete_preview($object)
  713. {
  714. global $langs,$conf;
  715. // Define parent dir of elements
  716. $element = $object->element;
  717. if ($object->element == 'order_supplier') $dir = $conf->fournisseur->dir_output.'/commande';
  718. elseif ($object->element == 'invoice_supplier') $dir = $conf->fournisseur->dir_output.'/facture';
  719. elseif ($object->element == 'project') $dir = $conf->projet->dir_output;
  720. elseif ($object->element == 'shipping') $dir = $conf->expedition->dir_output.'/sending';
  721. elseif ($object->element == 'delivery') $dir = $conf->expedition->dir_output.'/receipt';
  722. elseif ($object->element == 'fichinter') $dir = $conf->ficheinter->dir_output;
  723. else $dir=empty($conf->$element->dir_output)?'':$conf->$element->dir_output;
  724. if (empty($dir)) return 'ErrorObjectNoSupportedByFunction';
  725. $refsan = dol_sanitizeFileName($object->ref);
  726. $dir = $dir . "/" . $refsan ;
  727. $file = $dir . "/" . $refsan . ".pdf.png";
  728. $multiple = $file . ".";
  729. if (file_exists($file) && is_writable($file))
  730. {
  731. if ( ! dol_delete_file($file,1) )
  732. {
  733. $this->error=$langs->trans("ErrorFailedToOpenFile",$file);
  734. return 0;
  735. }
  736. }
  737. else
  738. {
  739. for ($i = 0; $i < 20; $i++)
  740. {
  741. $preview = $multiple.$i;
  742. if (file_exists($preview) && is_writable($preview))
  743. {
  744. if ( ! dol_delete_file($preview,1) )
  745. {
  746. $this->error=$langs->trans("ErrorFailedToOpenFile",$preview);
  747. return 0;
  748. }
  749. }
  750. }
  751. }
  752. return 1;
  753. }
  754. /**
  755. * Create a meta file with document file into same directory.
  756. * This should allow "grep" search.
  757. * This feature is enabled only if option MAIN_DOC_CREATE_METAFILE is set.
  758. *
  759. * @param Object $object Object
  760. * @return int 0 if we did nothing, >0 success, <0 error
  761. */
  762. function dol_meta_create($object)
  763. {
  764. global $conf;
  765. if (empty($conf->global->MAIN_DOC_CREATE_METAFILE)) return 0; // By default, no metafile.
  766. // Define parent dir of elements
  767. $element=$object->element;
  768. if ($object->element == 'order_supplier') $dir = $conf->fournisseur->dir_output.'/commande';
  769. elseif ($object->element == 'invoice_supplier') $dir = $conf->fournisseur->dir_output.'/facture';
  770. elseif ($object->element == 'project') $dir = $conf->projet->dir_output;
  771. elseif ($object->element == 'shipping') $dir = $conf->expedition->dir_output.'/sending';
  772. elseif ($object->element == 'delivery') $dir = $conf->expedition->dir_output.'/receipt';
  773. elseif ($object->element == 'fichinter') $dir = $conf->ficheinter->dir_output;
  774. else $dir=empty($conf->$element->dir_output)?'':$conf->$element->dir_output;
  775. if ($dir)
  776. {
  777. $object->fetch_thirdparty();
  778. $facref = dol_sanitizeFileName($object->ref);
  779. $dir = $dir . "/" . $facref;
  780. $file = $dir . "/" . $facref . ".meta";
  781. if (! is_dir($dir))
  782. {
  783. dol_mkdir($dir);
  784. }
  785. if (is_dir($dir))
  786. {
  787. $nblignes = count($object->lines);
  788. $client = $object->client->nom . " " . $object->client->address . " " . $object->client->cp . " " . $object->client->ville;
  789. $meta = "REFERENCE=\"" . $object->ref . "\"
  790. DATE=\"" . dol_print_date($object->date,'') . "\"
  791. NB_ITEMS=\"" . $nblignes . "\"
  792. CLIENT=\"" . $client . "\"
  793. TOTAL_HT=\"" . $object->total_ht . "\"
  794. TOTAL_TTC=\"" . $object->total_ttc . "\"\n";
  795. for ($i = 0 ; $i < $nblignes ; $i++)
  796. {
  797. //Pour les articles
  798. $meta .= "ITEM_" . $i . "_QUANTITY=\"" . $object->lines[$i]->qty . "\"
  799. ITEM_" . $i . "_TOTAL_HT=\"" . $object->lines[$i]->total_ht . "\"
  800. ITEM_" . $i . "_TVA=\"" .$object->lines[$i]->tva_tx . "\"
  801. ITEM_" . $i . "_DESCRIPTION=\"" . str_replace("\r\n","",nl2br($object->lines[$i]->desc)) . "\"
  802. ";
  803. }
  804. }
  805. $fp = fopen($file,"w");
  806. fputs($fp,$meta);
  807. fclose($fp);
  808. if (! empty($conf->global->MAIN_UMASK))
  809. @chmod($file, octdec($conf->global->MAIN_UMASK));
  810. return 1;
  811. }
  812. return 0;
  813. }
  814. /**
  815. * Init $_SESSION with uploaded files
  816. *
  817. * @param string $pathtoscan Path to scan
  818. * @return void
  819. */
  820. function dol_init_file_process($pathtoscan='')
  821. {
  822. $listofpaths=array();
  823. $listofnames=array();
  824. $listofmimes=array();
  825. if ($pathtoscan)
  826. {
  827. $listoffiles=dol_dir_list($pathtoscan,'files');
  828. foreach($listoffiles as $key => $val)
  829. {
  830. $listofpaths[]=$val['fullname'];
  831. $listofnames[]=$val['name'];
  832. $listofmimes[]=dol_mimetype($val['name']);
  833. }
  834. }
  835. $_SESSION["listofpaths"]=join(';',$listofpaths);
  836. $_SESSION["listofnames"]=join(';',$listofnames);
  837. $_SESSION["listofmimes"]=join(';',$listofmimes);
  838. }
  839. /**
  840. * Get and save an upload file (for example after submitting a new file a mail form).
  841. * All information used are in db, conf, langs, user and _FILES.
  842. * Note: This function can be used only into a HTML page context.
  843. *
  844. * @param string $upload_dir Directory where to store uploaded file (note: also find in first part of dest_file)
  845. * @param int $allowoverwrite 1=Allow overwrite existing file
  846. * @param int $donotupdatesession 1=Do no edit _SESSION variable
  847. * @param string $varfiles _FILES var name
  848. * @return void
  849. */
  850. function dol_add_file_process($upload_dir,$allowoverwrite=0,$donotupdatesession=0,$varfiles='addedfile')
  851. {
  852. global $db,$user,$conf,$langs;
  853. if (! empty($_FILES[$varfiles])) // For view $_FILES[$varfiles]['error']
  854. {
  855. if (dol_mkdir($upload_dir) >= 0)
  856. {
  857. $resupload = dol_move_uploaded_file($_FILES[$varfiles]['tmp_name'], $upload_dir . "/" . $_FILES[$varfiles]['name'], $allowoverwrite, 0, $_FILES[$varfiles]['error'], 0, $varfiles);
  858. if (is_numeric($resupload) && $resupload > 0)
  859. {
  860. if (empty($donotupdatesession))
  861. {
  862. include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
  863. $formmail = new FormMail($db);
  864. $formmail->add_attached_files($upload_dir . "/" . $_FILES[$varfiles]['name'],$_FILES[$varfiles]['name'],$_FILES[$varfiles]['type']);
  865. }
  866. else if (image_format_supported($upload_dir . "/" . $_FILES[$varfiles]['name']) == 1)
  867. {
  868. // Create small thumbs for image (Ratio is near 16/9)
  869. // Used on logon for example
  870. $imgThumbSmall = vignette($upload_dir . "/" . $_FILES[$varfiles]['name'], 160, 120, '_small', 50, "thumbs");
  871. // Create mini thumbs for image (Ratio is near 16/9)
  872. // Used on menu or for setup page for example
  873. $imgThumbMini = vignette($upload_dir . "/" . $_FILES[$varfiles]['name'], 160, 120, '_mini', 50, "thumbs");
  874. }
  875. setEventMessage($langs->trans("FileTransferComplete"));
  876. }
  877. else
  878. {
  879. $langs->load("errors");
  880. if ($resupload < 0) // Unknown error
  881. {
  882. setEventMessage($langs->trans("ErrorFileNotUploaded"), 'errors');
  883. }
  884. else if (preg_match('/ErrorFileIsInfectedWithAVirus/',$resupload)) // Files infected by a virus
  885. {
  886. setEventMessage($langs->trans("ErrorFileIsInfectedWithAVirus"), 'errors');
  887. }
  888. else // Known error
  889. {
  890. setEventMessage($langs->trans($resupload), 'errors');
  891. }
  892. }
  893. }
  894. }
  895. else
  896. {
  897. $langs->load("errors");
  898. setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentities("File")), 'warnings');
  899. }
  900. }
  901. /**
  902. * Remove an uploaded file (for example after submitting a new file a mail form).
  903. * All information used are in db, conf, langs, user and _FILES.
  904. *
  905. * @param int $filenb File nb to delete
  906. * @param int $donotupdatesession 1=Do not edit _SESSION variable
  907. * @param int $donotdeletefile 1=Do not delete physically file
  908. * @return void
  909. */
  910. function dol_remove_file_process($filenb,$donotupdatesession=0,$donotdeletefile=0)
  911. {
  912. global $db,$user,$conf,$langs,$_FILES;
  913. $keytodelete=$filenb;
  914. $keytodelete--;
  915. $listofpaths=array();
  916. $listofnames=array();
  917. $listofmimes=array();
  918. if (! empty($_SESSION["listofpaths"])) $listofpaths=explode(';',$_SESSION["listofpaths"]);
  919. if (! empty($_SESSION["listofnames"])) $listofnames=explode(';',$_SESSION["listofnames"]);
  920. if (! empty($_SESSION["listofmimes"])) $listofmimes=explode(';',$_SESSION["listofmimes"]);
  921. if ($keytodelete >= 0)
  922. {
  923. $pathtodelete=$listofpaths[$keytodelete];
  924. $filetodelete=$listofnames[$keytodelete];
  925. if (empty($donotdeletefile)) $result = dol_delete_file($pathtodelete,1);
  926. else $result=0;
  927. if ($result >= 0)
  928. {
  929. if (empty($donotdeletefile))
  930. {
  931. $langs->load("other");
  932. setEventMessage($langs->trans("FileWasRemoved",$filetodelete));
  933. }
  934. if (empty($donotupdatesession))
  935. {
  936. include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
  937. $formmail = new FormMail($db);
  938. $formmail->remove_attached_files($keytodelete);
  939. }
  940. }
  941. }
  942. }
  943. /**
  944. * Convert an image file into antoher format.
  945. * This need Imagick php extension.
  946. *
  947. * @param string $file Input file name
  948. * @param string $ext Extension of target file
  949. * @return int <0 if KO, >0 if OK
  950. */
  951. function dol_convert_file($file,$ext='png')
  952. {
  953. global $langs;
  954. $image=new Imagick();
  955. $ret = $image->readImage($file);
  956. if ($ret)
  957. {
  958. $ret = $image->setImageFormat($ext);
  959. if ($ret)
  960. {
  961. $count = $image->getNumberImages();
  962. $ret = $image->writeImages($file . "." . $ext, true);
  963. if ($ret) return $count;
  964. else return -3;
  965. }
  966. else
  967. {
  968. return -2;
  969. }
  970. }
  971. else
  972. {
  973. return -1;
  974. }
  975. }
  976. /**
  977. * Compress a file
  978. *
  979. * @param string $inputfile Source file name
  980. * @param string $outputfile Target file name
  981. * @param string $mode 'gz' or 'bz' or 'zip'
  982. * @return int <0 if KO, >0 if OK
  983. */
  984. function dol_compress_file($inputfile, $outputfile, $mode="gz")
  985. {
  986. $foundhandler=0;
  987. try
  988. {
  989. $data = implode("", file(dol_osencode($inputfile)));
  990. if ($mode == 'gz') { $foundhandler=1; $compressdata = gzencode($data, 9); }
  991. elseif ($mode == 'bz') { $foundhandler=1; $compressdata = bzcompress($data, 9); }
  992. elseif ($mode == 'zip')
  993. {
  994. if (defined('ODTPHP_PATHTOPCLZIP'))
  995. {
  996. $foundhandler=1;
  997. include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
  998. $archive = new PclZip($outputfile);
  999. $archive->add($inputfile, PCLZIP_OPT_REMOVE_PATH, dirname($inputfile));
  1000. //$archive->add($inputfile);
  1001. return 1;
  1002. }
  1003. }
  1004. if ($foundhandler)
  1005. {
  1006. $fp = fopen($outputfile, "w");
  1007. fwrite($fp, $compressdata);
  1008. fclose($fp);
  1009. return 1;
  1010. }
  1011. else
  1012. {
  1013. dol_syslog("Try to zip with format ".$mode." with no handler for this format",LOG_ERR);
  1014. return -2;
  1015. }
  1016. }
  1017. catch (Exception $e)
  1018. {
  1019. global $langs, $errormsg;
  1020. $langs->load("errors");
  1021. dol_syslog("Failed to open file ".$outputfile,LOG_ERR);
  1022. $errormsg=$langs->trans("ErrorFailedToWriteInDir");
  1023. return -1;
  1024. }
  1025. }
  1026. /**
  1027. * Uncompress a file
  1028. *
  1029. * @param string $inputfile File to uncompress
  1030. * @param string $outputdir Target dir name
  1031. * @return array array('error'=>'Error code') or array() if no error
  1032. */
  1033. function dol_uncompress($inputfile,$outputdir)
  1034. {
  1035. global $conf;
  1036. if (defined('ODTPHP_PATHTOPCLZIP'))
  1037. {
  1038. include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
  1039. $archive = new PclZip($inputfile);
  1040. if ($archive->extract(PCLZIP_OPT_PATH, $outputdir) == 0) return array('error'=>$archive->errorInfo(true));
  1041. else return array();
  1042. }
  1043. if (class_exists('ZipArchive'))
  1044. {
  1045. $zip = new ZipArchive;
  1046. $res = $zip->open($inputfile);
  1047. if ($res === TRUE)
  1048. {
  1049. $zip->extractTo($outputdir.'/');
  1050. $zip->close();
  1051. return array();
  1052. }
  1053. else
  1054. {
  1055. return array('error'=>'ErrUnzipFails');
  1056. }
  1057. }
  1058. return array('error'=>'ErrNoZipEngine');
  1059. }
  1060. /**
  1061. * Return most recent file
  1062. *
  1063. * @param string $dir Directory to scan
  1064. * @param string $regexfilter Regexfilter
  1065. * @param string $excludefilter Array of Regex for exclude filter (example: array('\.meta$','^\.'))
  1066. * @return strnig Full path to most recent file
  1067. */
  1068. function dol_most_recent_file($dir,$regexfilter='',$excludefilter=array('\.meta$','^\.'))
  1069. {
  1070. $tmparray=dol_dir_list($dir,'files',0,$regexfilter,$excludefilter,'date',SORT_DESC);
  1071. return $tmparray[0];
  1072. }
  1073. ?>