Completed
Branch develop (0fc56d)
by
unknown
26:25
created

files.lib.php ➔ dol_delete_dir_recursive()   C

Complexity

Conditions 11
Paths 5

Size

Total Lines 39
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 20
nc 5
nop 5
dl 0
loc 39
rs 5.2653
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* Copyright (C) 2008-2012  Laurent Destailleur <[email protected]>
3
 * Copyright (C) 2012-2015  Regis Houssin       <[email protected]>
4
 * Copyright (C) 2012-2016  Juanjo Menent       <[email protected]>
5
 * Copyright (C) 2015       Marcos García       <[email protected]>
6
 * Copyright (C) 2016       Raphaël Doursenaud  <[email protected]>
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
23
/**
24
 *  \file		htdocs/core/lib/files.lib.php
25
 *  \brief		Library for file managing functions
26
 */
27
28
/**
29
 * Make a basename working with all page code (default PHP basenamed fails with cyrillic).
30
 * We supose dir separator for input is '/'.
31
 *
32
 * @param	string	$pathfile	String to find basename.
33
 * @return	string				Basename of input
34
 */
35
function dol_basename($pathfile)
36
{
37
    return preg_replace('/^.*\/([^\/]+)$/','$1',rtrim($pathfile,'/'));
38
}
39
40
/**
41
 *  Scan a directory and return a list of files/directories.
42
 *  Content for string is UTF8 and dir separator is "/".
43
 *
44
 *  @param	string		$path        	Starting path from which to search. This is a full path.
45
 *  @param	string		$types        	Can be "directories", "files", or "all"
46
 *  @param	int			$recursive		Determines whether subdirectories are searched
47
 *  @param	string		$filter        	Regex filter to restrict list. This regex value must be escaped for '/' by doing preg_quote($var,'/'), since this char is used for preg_match function,
48
 *                                      but must not contains the start and end '/'. Filter is checked into basename only.
49
 *  @param	array		$excludefilter  Array of Regex for exclude filter (example: array('(\.meta|_preview.*\.png)$','^\.')). Exclude is checked into fullpath.
50
 *  @param	string		$sortcriteria	Sort criteria ("","fullname","name","date","size")
51
 *  @param	string		$sortorder		Sort order (SORT_ASC, SORT_DESC)
52
 *	@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
53
 *  @param	int			$nohook			Disable all hooks
54
 *  @return	array						Array of array('name'=>'xxx','fullname'=>'/abc/xxx','date'=>'yyy','size'=>99,'type'=>'dir|file',...)
55
 *  @see dol_dir_list_indatabase
56
 */
57
function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter="", $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0)
58
{
59
	global $db, $hookmanager;
60
	global $object;
61
62
	dol_syslog("files.lib.php::dol_dir_list path=".$path." types=".$types." recursive=".$recursive." filter=".$filter." excludefilter=".json_encode($excludefilter));
63
	//print 'xxx'."files.lib.php::dol_dir_list path=".$path." types=".$types." recursive=".$recursive." filter=".$filter." excludefilter=".json_encode($excludefilter);
64
65
	$loaddate=($mode==1||$mode==2)?true:false;
66
	$loadsize=($mode==1||$mode==3)?true:false;
67
68
	// Clean parameters
69
	$path=preg_replace('/([\\/]+)$/i','',$path);
70
	$newpath=dol_osencode($path);
71
72
	$reshook = 0;
73
	$file_list = array();
74
75
	if (is_object($hookmanager) && ! $nohook)
76
	{
77
	    $hookmanager->resArray=array();
78
79
	    $hookmanager->initHooks(array('fileslib'));
80
81
		$parameters=array(
82
				'path' => $newpath,
83
				'types'=> $types,
84
				'recursive' => $recursive,
85
				'filter' => $filter,
86
				'excludefilter' => $excludefilter,
87
				'sortcriteria' => $sortcriteria,
88
				'sortorder' => $sortorder,
89
				'loaddate' => $loaddate,
90
				'loadsize' => $loadsize,
91
				'mode' => $mode
92
		);
93
		$reshook=$hookmanager->executeHooks('getDirList', $parameters, $object);
94
	}
95
96
	// $hookmanager->resArray may contain array stacked by other modules
97
	if (empty($reshook))
98
	{
99
		if (! is_dir($newpath)) return array();
100
101
		if ($dir = opendir($newpath))
102
		{
103
			$filedate='';
104
			$filesize='';
105
106
			while (false !== ($file = readdir($dir)))        // $file is always a basename (into directory $newpath)
107
			{
108
				if (! utf8_check($file)) $file=utf8_encode($file);	// To be sure data is stored in utf8 in memory
109
110
				$qualified=1;
111
112
				// Define excludefilterarray
113
				$excludefilterarray=array('^\.');
114
				if (is_array($excludefilter))
115
				{
116
					$excludefilterarray=array_merge($excludefilterarray,$excludefilter);
117
				}
118
				else if ($excludefilter) $excludefilterarray[]=$excludefilter;
119
				// Check if file is qualified
120
				foreach($excludefilterarray as $filt)
121
				{
122
					if (preg_match('/'.$filt.'/i',$file)) {
123
						$qualified=0; break;
124
					}
125
				}
126
127
				if ($qualified)
128
				{
129
					$isdir=is_dir(dol_osencode($path."/".$file));
130
					// Check whether this is a file or directory and whether we're interested in that type
131
					if ($isdir && (($types=="directories") || ($types=="all") || $recursive))
132
					{
133
						// Add entry into file_list array
134
						if (($types=="directories") || ($types=="all"))
135
						{
136
							if ($loaddate || $sortcriteria == 'date') $filedate=dol_filemtime($path."/".$file);
137
							if ($loadsize || $sortcriteria == 'size') $filesize=dol_filesize($path."/".$file);
138
139
							if (! $filter || preg_match('/'.$filter.'/i',$file))	// We do not search key $filter into all $path, only into $file part
140
							{
141
								preg_match('/([^\/]+)\/[^\/]+$/',$path.'/'.$file,$reg);
142
								$level1name=(isset($reg[1])?$reg[1]:'');
143
								$file_list[] = array(
144
										"name" => $file,
145
										"path" => $path,
146
										"level1name" => $level1name,
147
										"fullname" => $path.'/'.$file,
148
										"date" => $filedate,
149
										"size" => $filesize,
150
										"type" => 'dir'
151
								);
152
							}
153
						}
154
155
						// if we're in a directory and we want recursive behavior, call this function again
156
						if ($recursive)
157
						{
158
							$file_list = array_merge($file_list,dol_dir_list($path."/".$file, $types, $recursive, $filter, $excludefilter, $sortcriteria, $sortorder, $mode, $nohook));
159
						}
160
					}
161
					else if (! $isdir && (($types == "files") || ($types == "all")))
162
					{
163
						// Add file into file_list array
164
						if ($loaddate || $sortcriteria == 'date') $filedate=dol_filemtime($path."/".$file);
165
						if ($loadsize || $sortcriteria == 'size') $filesize=dol_filesize($path."/".$file);
166
167
						if (! $filter || preg_match('/'.$filter.'/i',$file))	// We do not search key $filter into $path, only into $file
168
						{
169
							preg_match('/([^\/]+)\/[^\/]+$/',$path.'/'.$file,$reg);
170
							$level1name=(isset($reg[1])?$reg[1]:'');
171
							$file_list[] = array(
172
									"name" => $file,
173
									"path" => $path,
174
									"level1name" => $level1name,
175
									"fullname" => $path.'/'.$file,
176
									"date" => $filedate,
177
									"size" => $filesize,
178
									"type" => 'file'
179
							);
180
						}
181
					}
182
				}
183
			}
184
			closedir($dir);
185
186
			// Obtain a list of columns
187
			if (! empty($sortcriteria))
188
			{
189
				$myarray=array();
190
				foreach ($file_list as $key => $row)
191
				{
192
					$myarray[$key] = (isset($row[$sortcriteria])?$row[$sortcriteria]:'');
193
				}
194
				// Sort the data
195
				if ($sortorder) array_multisort($myarray, $sortorder, $file_list);
196
			}
197
		}
198
	}
199
200
	if (is_object($hookmanager) && is_array($hookmanager->resArray)) $file_list = array_merge($file_list, $hookmanager->resArray);
201
202
	return $file_list;
203
}
204
205
206
/**
207
 *  Scan a directory and return a list of files/directories.
208
 *  Content for string is UTF8 and dir separator is "/".
209
 *
210
 *  @param	string		$path        	Starting path from which to search. Example: 'produit/MYPROD'
211
 *  @param	string		$filter        	Regex filter to restrict list. This regex value must be escaped for '/', since this char is used for preg_match function
212
 *  @param	array|null	$excludefilter  Array of Regex for exclude filter (example: array('(\.meta|_preview.*\.png)$','^\.'))
213
 *  @param	string		$sortcriteria	Sort criteria ("","fullname","name","date","size")
214
 *  @param	string		$sortorder		Sort order (SORT_ASC, SORT_DESC)
215
 *	@param	int			$mode			0=Return array minimum keys loaded (faster), 1=Force all keys like description
216
 *  @return	array						Array of array('name'=>'xxx','fullname'=>'/abc/xxx','type'=>'dir|file',...)
217
 *  @see dol_dir_list
218
 */
219
function dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0)
220
{
221
    global $conf, $db;
222
223
    $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, acl, position";
224
    if ($mode) $sql.=", description";
225
    $sql.=" FROM ".MAIN_DB_PREFIX."ecm_files";
226
    $sql.=" WHERE filepath = '".$db->escape($path)."'";
227
    $sql.=" AND entity = ".$conf->entity;
228
229
    $resql = $db->query($sql);
230
    if ($resql)
231
    {
232
        $file_list=array();
233
        $num = $db->num_rows($resql);
234
        $i = 0;
235
        while ($i < $num)
236
        {
237
            $obj = $db->fetch_object($resql);
238
            if ($obj)
239
            {
240
                preg_match('/([^\/]+)\/[^\/]+$/',DOL_DATA_ROOT.'/'.$obj->filepath.'/'.$obj->filename,$reg);
241
                $level1name=(isset($reg[1])?$reg[1]:'');
242
                $file_list[] = array(
243
                    "rowid" => $obj->rowid,
244
                    "label" => $obj->label,         // md5
245
    				"name" => $obj->filename,
246
    				"path" => DOL_DATA_ROOT.'/'.$obj->filepath,
247
                    "level1name" => $level1name,
248
    				"fullname" => DOL_DATA_ROOT.'/'.$obj->filepath.'/'.$obj->filename,
249
    				"fullpath_orig" => $obj->fullpath_orig,
250
                    "date_c" => $db->jdate($obj->date_c),
251
                    "date_m" => $db->jdate($obj->date_m),
252
    				"type" => 'file',
253
                    "keywords" => $obj->keywords,
254
                    "cover" => $obj->cover,
255
                    "position" => (int) $obj->position,
256
                    "acl" => $obj->acl
257
                );
258
            }
259
            $i++;
260
        }
261
262
        // Obtain a list of columns
263
        if (! empty($sortcriteria))
264
        {
265
            $myarray=array();
266
            foreach ($file_list as $key => $row)
267
            {
268
                $myarray[$key] = (isset($row[$sortcriteria])?$row[$sortcriteria]:'');
269
            }
270
            // Sort the data
271
            if ($sortorder) array_multisort($myarray, $sortorder, $file_list);
272
        }
273
274
        return $file_list;
275
    }
276
    else
277
    {
278
        dol_print_error($db);
279
        return array();
280
    }
281
}
282
283
284
/**
285
 * Fast compare of 2 files identified by their properties ->name, ->date and ->size
286
 *
287
 * @param	string 	$a		File 1
288
 * @param 	string	$b		File 2
289
 * @return 	int				1, 0, 1
290
 */
291
function dol_compare_file($a, $b)
292
{
293
	global $sortorder;
294
	global $sortfield;
295
296
	$sortorder=strtoupper($sortorder);
297
298
	if ($sortorder == 'ASC') { $retup=-1; $retdown=1; }
299
	else { $retup=1; $retdown=-1; }
300
301
	if ($sortfield == 'name')
302
	{
303
		if ($a->name == $b->name) return 0;
304
		return ($a->name < $b->name) ? $retup : $retdown;
305
	}
306
	if ($sortfield == 'date')
307
	{
308
		if ($a->date == $b->date) return 0;
309
		return ($a->date < $b->date) ? $retup : $retdown;
310
	}
311
	if ($sortfield == 'size')
312
	{
313
		if ($a->size == $b->size) return 0;
314
		return ($a->size < $b->size) ? $retup : $retdown;
315
	}
316
}
317
318
319
/**
320
 * Test if filename is a directory
321
 *
322
 * @param	string		$folder     Name of folder
323
 * @return	boolean     			True if it's a directory, False if not found
324
 */
325
function dol_is_dir($folder)
326
{
327
    $newfolder=dol_osencode($folder);
328
    if (is_dir($newfolder)) return true;
329
    else return false;
330
}
331
332
/**
333
 * Return if path is a file
334
 *
335
 * @param   string		$pathoffile		Path of file
336
 * @return  boolean     			    True or false
337
 */
338
function dol_is_file($pathoffile)
339
{
340
    $newpathoffile=dol_osencode($pathoffile);
341
    return is_file($newpathoffile);
342
}
343
344
/**
345
 * Return if path is an URL
346
 *
347
 * @param   string		$url	Url
348
 * @return  boolean      	   	True or false
349
 */
350
function dol_is_url($url)
351
{
352
    $tmpprot=array('file','http','https','ftp','zlib','data','ssh','ssh2','ogg','expect');
353
    foreach($tmpprot as $prot)
354
    {
355
        if (preg_match('/^'.$prot.':/i',$url)) return true;
356
    }
357
    return false;
358
}
359
360
/**
361
 * 	Test if a folder is empty
362
 *
363
 * 	@param	string	$folder		Name of folder
364
 * 	@return boolean				True if dir is empty or non-existing, False if it contains files
365
 */
366
function dol_dir_is_emtpy($folder)
367
{
368
	$newfolder=dol_osencode($folder);
369
	if (is_dir($newfolder))
370
	{
371
		$handle = opendir($newfolder);
372
        $folder_content = '';
373
		while ((gettype($name = readdir($handle)) != "boolean"))
374
		{
375
			$name_array[] = $name;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$name_array was never initialized. Although not strictly required by PHP, it is generally a good practice to add $name_array = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
376
		}
377
		foreach($name_array as $temp) $folder_content .= $temp;
0 ignored issues
show
Bug introduced by
The variable $name_array does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
378
379
        closedir($handle);
380
381
		if ($folder_content == "...") return true;
382
		else return false;
383
	}
384
	else
385
	return true; // Dir does not exists
386
}
387
388
/**
389
 * 	Count number of lines in a file
390
 *
391
 * 	@param	string	$file		Filename
392
 * 	@return int					<0 if KO, Number of lines in files if OK
393
 */
394
function dol_count_nb_of_line($file)
395
{
396
	$nb=0;
397
398
	$newfile=dol_osencode($file);
399
	//print 'x'.$file;
400
	$fp=fopen($newfile,'r');
401
	if ($fp)
402
	{
403
		while (!feof($fp))
404
		{
405
			$line=fgets($fp);
406
            // 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.
407
			if (! $line === false) $nb++;
408
		}
409
		fclose($fp);
410
	}
411
	else
412
	{
413
		$nb=-1;
414
	}
415
416
	return $nb;
417
}
418
419
420
/**
421
 * Return size of a file
422
 *
423
 * @param 	string		$pathoffile		Path of file
424
 * @return 	integer						File size
425
 */
426
function dol_filesize($pathoffile)
427
{
428
	$newpathoffile=dol_osencode($pathoffile);
429
	return filesize($newpathoffile);
430
}
431
432
/**
433
 * Return time of a file
434
 *
435
 * @param 	string		$pathoffile		Path of file
436
 * @return 	int					Time of file
437
 */
438
function dol_filemtime($pathoffile)
439
{
440
	$newpathoffile=dol_osencode($pathoffile);
441
	return @filemtime($newpathoffile); // @Is to avoid errors if files does not exists
442
}
443
444
/**
445
 * Make replacement of strings into a file.
446
 *
447
 * @param	string	$srcfile			Source file (can't be a directory)
448
 * @param	array	$arrayreplacement	Array with strings to replace
449
 * @param	string	$destfile			Destination file (can't be a directory). If empty, will be same than source file.
450
 * @param	int		$newmask			Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666'
451
 * @param	int		$indexdatabase		Index new file into database.
452
 * @return	int							<0 if error, 0 if nothing done (dest file already exists), >0 if OK
453
 * @see		dolCopyr
454
 */
455
function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, $indexdatabase=0)
456
{
457
    global $conf;
458
459
    dol_syslog("files.lib.php::dolReplaceInFile srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." indexdatabase=".$indexdatabase);
460
461
    if (empty($srcfile)) return -1;
462
    if (empty($destfile)) $destfile=$srcfile;
463
464
    $destexists=dol_is_file($destfile);
465
    if (($destfile != $srcfile) && $destexists) return 0;
466
467
    $tmpdestfile=$destfile.'.tmp';
468
469
    $newpathofsrcfile=dol_osencode($srcfile);
470
    $newpathoftmpdestfile=dol_osencode($tmpdestfile);
471
    $newpathofdestfile=dol_osencode($destfile);
472
    $newdirdestfile=dirname($newpathofdestfile);
473
474
    if ($destexists && ! is_writable($newpathofdestfile))
475
    {
476
        dol_syslog("files.lib.php::dolReplaceInFile failed Permission denied to overwrite target file", LOG_WARNING);
477
        return -1;
478
    }
479
    if (! is_writable($newdirdestfile))
480
    {
481
        dol_syslog("files.lib.php::dolReplaceInFile failed Permission denied to write into target directory ".$newdirdestfile, LOG_WARNING);
482
        return -2;
483
    }
484
485
    dol_delete_file($tmpdestfile);
486
487
    // Create $newpathoftmpdestfile from $newpathofsrcfile
488
    $content=file_get_contents($newpathofsrcfile, 'r');
489
490
    $content = make_substitutions($content, $arrayreplacement, null);
491
492
    file_put_contents($newpathoftmpdestfile, $content);
493
    @chmod($newpathoftmpdestfile, octdec($newmask));
494
495
    // Rename
496
    $result=dol_move($newpathoftmpdestfile, $newpathofdestfile, $newmask, (($destfile == $srcfile)?1:0), 0, $indexdatabase);
497
    if (! $result)
498
    {
499
        dol_syslog("files.lib.php::dolReplaceInFile failed to move tmp file to final dest", LOG_WARNING);
500
        return -3;
501
    }
502
    if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $newmask=$conf->global->MAIN_UMASK;
503
    if (empty($newmask))	// This should no happen
504
    {
505
        dol_syslog("Warning: dolReplaceInFile called with empty value for newmask and no default value defined", LOG_WARNING);
506
        $newmask='0664';
507
    }
508
509
    @chmod($newpathofdestfile, octdec($newmask));
510
511
    return 1;
512
}
513
514
/**
515
 * Copy a file to another file.
516
 *
517
 * @param	string	$srcfile			Source file (can't be a directory)
518
 * @param	string	$destfile			Destination file (can't be a directory)
519
 * @param	int		$newmask			Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666'
520
 * @param 	int		$overwriteifexists	Overwrite file if exists (1 by default)
521
 * @return	int							<0 if error, 0 if nothing done (dest file already exists and overwriteifexists=0), >0 if OK
522
 * @see		dolCopyr
523
 */
524
function dol_copy($srcfile, $destfile, $newmask=0, $overwriteifexists=1)
525
{
526
	global $conf;
527
528
	dol_syslog("files.lib.php::dol_copy srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." overwriteifexists=".$overwriteifexists);
529
530
	if (empty($srcfile) || empty($destfile)) return -1;
531
532
	$destexists=dol_is_file($destfile);
533
	if (! $overwriteifexists && $destexists) return 0;
534
535
	$newpathofsrcfile=dol_osencode($srcfile);
536
    $newpathofdestfile=dol_osencode($destfile);
537
    $newdirdestfile=dirname($newpathofdestfile);
538
539
    if ($destexists && ! is_writable($newpathofdestfile))
540
    {
541
        dol_syslog("files.lib.php::dol_copy failed Permission denied to overwrite target file", LOG_WARNING);
542
        return -1;
543
    }
544
    if (! is_writable($newdirdestfile))
545
    {
546
        dol_syslog("files.lib.php::dol_copy failed Permission denied to write into target directory ".$newdirdestfile, LOG_WARNING);
547
        return -2;
548
    }
549
    // Copy with overwriting if exists
550
    $result=@copy($newpathofsrcfile, $newpathofdestfile);
551
	//$result=copy($newpathofsrcfile, $newpathofdestfile);	// To see errors, remove @
552
	if (! $result)
553
	{
554
	    dol_syslog("files.lib.php::dol_copy failed to copy", LOG_WARNING);
555
	    return -3;
556
	}
557
	if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $newmask=$conf->global->MAIN_UMASK;
558
	if (empty($newmask))	// This should no happen
559
	{
560
		dol_syslog("Warning: dol_copy called with empty value for newmask and no default value defined", LOG_WARNING);
561
		$newmask='0664';
562
	}
563
564
	@chmod($newpathofdestfile, octdec($newmask));
565
566
	return 1;
567
}
568
569
/**
570
 * Copy a dir to another dir.
571
 *
572
 * @param	string	$srcfile			Source file (a directory)
573
 * @param	string	$destfile			Destination file (a directory)
574
 * @param	int		$newmask			Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666'
575
 * @param 	int		$overwriteifexists	Overwrite file if exists (1 by default)
576
 * @param	array	$arrayreplacement	Array to use to replace filenames with another one during the copy (works only on file names, not on directory names).
577
 * @return	int							<0 if error, 0 if nothing done (all files already exists and overwriteifexists=0), >0 if OK
578
 * @see		dol_copy
579
 */
580
function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayreplacement=null)
581
{
582
	global $conf;
583
584
	$result=0;
585
586
	dol_syslog("files.lib.php::dolCopyDir srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." overwriteifexists=".$overwriteifexists);
587
588
	if (empty($srcfile) || empty($destfile)) return -1;
589
590
	$destexists=dol_is_dir($destfile);
591
	//if (! $overwriteifexists && $destexists) return 0;	// The overwriteifexists is for files only, so propagated to dol_copy only.
592
593
    if (! $destexists)
594
    {
595
        // We must set mask just before creating dir, becaause it can be set differently by dol_copy
596
        umask(0);
597
        $dirmaskdec=octdec($newmask);
598
        if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $dirmaskdec=octdec($conf->global->MAIN_UMASK);
599
        $dirmaskdec |= octdec('0200');  // Set w bit required to be able to create content for recursive subdirs files
600
        dol_mkdir($destfile, '', decoct($dirmaskdec));
601
    }
602
603
	$ossrcfile=dol_osencode($srcfile);
604
	$osdestfile=dol_osencode($destfile);
605
606
    // Recursive function to copy all subdirectories and contents:
607
	if (is_dir($ossrcfile))
608
	{
609
        $dir_handle=opendir($ossrcfile);
610
        while ($file=readdir($dir_handle))
611
        {
612
            if ($file!="." && $file!="..")
613
            {
614
                if (is_dir($ossrcfile."/".$file))
615
                {
616
                    //var_dump("xxx dolCopyDir $srcfile/$file, $destfile/$file, $newmask, $overwriteifexists");
617
                    $tmpresult=dolCopyDir($srcfile."/".$file, $destfile."/".$file, $newmask, $overwriteifexists, $arrayreplacement);
618
                }
619
                else
620
				{
621
					$newfile = $file;
622
					// Replace destination filename with a new one
623
					if (is_array($arrayreplacement))
624
					{
625
						foreach($arrayreplacement as $key => $val)
626
						{
627
							$newfile = str_replace($key, $val, $newfile);
628
						}
629
					}
630
                    $tmpresult=dol_copy($srcfile."/".$file, $destfile."/".$newfile, $newmask, $overwriteifexists);
631
                }
632
                // Set result
633
                if ($result > 0 && $tmpresult >= 0)
634
                {
635
                    // Do nothing, so we don't set result to 0 if tmpresult is 0 and result was success in a previous pass
636
                }
637
                else
638
                {
639
                    $result=$tmpresult;
640
                }
641
                if ($result < 0) break;
642
643
            }
644
        }
645
        closedir($dir_handle);
646
    }
647
    else
648
	{
649
		// Source directory does not exists
650
        $result = -2;
651
    }
652
653
    return $result;
654
}
655
656
657
/**
658
 * Move a file into another name.
659
 * Note:
660
 *  - This function differs from dol_move_uploaded_file, because it can be called in any context.
661
 *  - Database of files is updated.
662
 *  - Test on antivirus is done only if param testvirus is provided and an antivirus was set.
663
 *
664
 * @param	string  $srcfile            Source file (can't be a directory. use native php @rename() to move a directory)
665
 * @param   string	$destfile           Destination file (can't be a directory. use native php @rename() to move a directory)
666
 * @param   integer	$newmask            Mask in octal string for new file (0 by default means $conf->global->MAIN_UMASK)
667
 * @param   int		$overwriteifexists  Overwrite file if exists (1 by default)
668
 * @param   int     $testvirus          Do an antivirus test. Move is canceled if a virus is found.
669
 * @param	int		$indexdatabase		Index new file into database.
670
 * @return  boolean 		            True if OK, false if KO
671
 * @see dol_move_uploaded_file
672
 */
673
function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvirus=0, $indexdatabase=1)
674
{
675
    global $user, $db, $conf;
676
    $result=false;
677
678
    dol_syslog("files.lib.php::dol_move srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." overwritifexists=".$overwriteifexists);
679
    $srcexists=dol_is_file($srcfile);
680
    $destexists=dol_is_file($destfile);
681
682
    if (! $srcexists)
683
    {
684
        dol_syslog("files.lib.php::dol_move srcfile does not exists. we ignore the move request.");
685
        return false;
686
    }
687
688
    if ($overwriteifexists || ! $destexists)
689
    {
690
        $newpathofsrcfile=dol_osencode($srcfile);
691
        $newpathofdestfile=dol_osencode($destfile);
692
693
        // Check virus
694
        $testvirusarray=array();
695
        if ($testvirus)
696
        {
697
            $testvirusarray=dolCheckVirus($newpathofsrcfile);
698
            if (count($testvirusarray))
699
            {
700
                dol_syslog("files.lib.php::dol_move canceled because a virus was found into source file. we ignore the move request.", LOG_WARNING);
701
                return false;
702
            }
703
        }
704
705
        $result=@rename($newpathofsrcfile, $newpathofdestfile); // To see errors, remove @
706
        if (! $result)
707
        {
708
        	if ($destexists)
709
        	{
710
        		dol_syslog("files.lib.php::dol_move Failed. We try to delete target first and move after.", LOG_WARNING);
711
        		// We force delete and try again. Rename function sometimes fails to replace dest file with some windows NTFS partitions.
712
        		dol_delete_file($destfile);
713
        		$result=@rename($newpathofsrcfile, $newpathofdestfile); // To see errors, remove @
714
        	}
715
        	else dol_syslog("files.lib.php::dol_move Failed.", LOG_WARNING);
716
        }
717
718
        // Move ok
719
        if ($result && $indexdatabase)
720
        {
721
            // Rename entry into ecm database
722
            $rel_filetorenamebefore = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $srcfile);
723
            $rel_filetorenameafter = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $destfile);
724
            if (! preg_match('/(\/temp\/|\/thumbs|\.meta$)/', $rel_filetorenameafter))     // If not a tmp file
725
            {
726
                $rel_filetorenamebefore = preg_replace('/^[\\/]/', '', $rel_filetorenamebefore);
727
                $rel_filetorenameafter = preg_replace('/^[\\/]/', '', $rel_filetorenameafter);
728
                //var_dump($rel_filetorenamebefore.' - '.$rel_filetorenameafter);
729
730
                dol_syslog("Try to rename also entries in database for full relative path before = ".$rel_filetorenamebefore." after = ".$rel_filetorenameafter, LOG_DEBUG);
731
                include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
732
733
                $ecmfiletarget=new EcmFiles($db);
734
                $resultecmtarget = $ecmfiletarget->fetch(0, '', $rel_filetorenameafter);
735
                if ($resultecmtarget > 0)   // An entry for target name already exists for target, we delete it, a new one will be created.
736
                {
737
                    $ecmfiletarget->delete($user);
738
                }
739
740
                $ecmfile=new EcmFiles($db);
741
                $resultecm = $ecmfile->fetch(0, '', $rel_filetorenamebefore);
742
                if ($resultecm > 0)   // If an entry was found for src file, we use it to move entry
743
                {
744
                    $filename = basename($rel_filetorenameafter);
745
                    $rel_dir = dirname($rel_filetorenameafter);
746
                    $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
747
                    $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
748
749
                    $ecmfile->filepath = $rel_dir;
750
                    $ecmfile->filename = $filename;
751
                    $resultecm = $ecmfile->update($user);
752
                }
753
                elseif ($resultecm == 0)   // If no entry were found for src files, create/update target file
754
                {
755
                    $filename = basename($rel_filetorenameafter);
756
                    $rel_dir = dirname($rel_filetorenameafter);
757
                    $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
758
                    $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
759
760
                    $ecmfile->filepath = $rel_dir;
761
                    $ecmfile->filename = $filename;
762
                    $ecmfile->label = md5_file(dol_osencode($destfile));        // $destfile is a full path to file
763
                    $ecmfile->fullpath_orig = $srcfile;
764
                    $ecmfile->gen_or_uploaded = 'unknown';
765
                    $ecmfile->description = '';    // indexed content
766
                    $ecmfile->keyword = '';        // keyword content
767
                    $resultecm = $ecmfile->create($user);
768
                    if ($resultecm < 0)
769
                    {
770
                        setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
771
                    }
772
                }
773
                elseif ($resultecm < 0)
774
                {
775
                    setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
776
                }
777
778
                if ($resultecm > 0) $result=true;
779
                else $result = false;
780
            }
781
        }
782
783
        if (empty($newmask)) $newmask=empty($conf->global->MAIN_UMASK)?'0755':$conf->global->MAIN_UMASK;
784
        $newmaskdec=octdec($newmask);
785
        // Currently method is restricted to files (dol_delete_files previously used is for files, and mask usage if for files too)
786
        // to allow mask usage for dir, we shoul introduce a new param "isdir" to 1 to complete newmask like this
787
        // if ($isdir) $newmaskdec |= octdec('0111');  // Set x bit required for directories
788
        @chmod($newpathofdestfile, $newmaskdec);
789
    }
790
791
    return $result;
792
}
793
794
/**
795
 *	Unescape a file submitted by upload.
796
 *  PHP escape char " (%22) or char ' (%27) into $FILES.
797
 *
798
 *	@param	string	$filename		Filename
799
 *	@return	string					Filename sanitized
800
 */
801
function dol_unescapefile($filename)
802
{
803
	// Remove path information and dots around the filename, to prevent uploading
804
	// into different directories or replacing hidden system files.
805
	// Also remove control characters and spaces (\x00..\x20) around the filename:
806
	return trim(basename($filename), ".\x00..\x20");
807
}
808
809
810
/**
811
 * Check virus into a file
812
 *
813
 * @param   string      $src_file       Source file to check
814
 * @return  array                       Array of errors or empty array if not virus found
815
 */
816
function dolCheckVirus($src_file)
817
{
818
    global $conf;
819
820
    if (! empty($conf->global->MAIN_ANTIVIRUS_COMMAND))
821
    {
822
        if (! class_exists('AntiVir')) {
823
            require_once DOL_DOCUMENT_ROOT.'/core/class/antivir.class.php';
824
        }
825
        $antivir=new AntiVir($db);
0 ignored issues
show
Bug introduced by
The variable $db does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
826
        $result = $antivir->dol_avscan_file($src_file);
827
        if ($result < 0)	// If virus or error, we stop here
828
        {
829
            $reterrors=$antivir->errors;
830
            return $reterrors;
831
        }
832
    }
833
    return array();
834
}
835
836
837
/**
838
 *	Make control on an uploaded file from an GUI page and move it to final destination.
839
 * 	If there is errors (virus found, antivir in error, bad filename), file is not moved.
840
 *  Note:
841
 *  - This function can be used only into a HTML page context. Use dol_move if you are outside.
842
 *  - Test on antivirus is always done (if antivirus set).
843
 *  - Database of files is NOT updated.
844
 *
845
 *	@param	string	$src_file			Source full path filename ($_FILES['field']['tmp_name'])
846
 *	@param	string	$dest_file			Target full path filename  ($_FILES['field']['name'])
847
 * 	@param	int		$allowoverwrite		1=Overwrite target file if it already exists
848
 * 	@param	int		$disablevirusscan	1=Disable virus scan
849
 * 	@param	integer	$uploaderrorcode	Value of PHP upload error code ($_FILES['field']['error'])
850
 * 	@param	int		$nohook				Disable all hooks
851
 * 	@param	string	$varfiles			_FILES var name
852
 *	@return int       			  		>0 if OK, <0 or string if KO
853
 *  @see    dol_move
854
 */
855
function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles='addedfile')
856
{
857
	global $conf, $db, $user, $langs;
858
	global $object, $hookmanager;
859
860
	$reshook=0;
861
	$file_name = $dest_file;
862
863
	if (empty($nohook))
864
	{
865
		$reshook=$hookmanager->initHooks(array('fileslib'));
866
867
		$parameters=array('dest_file' => $dest_file, 'src_file' => $src_file, 'file_name' => $file_name, 'varfiles' => $varfiles, 'allowoverwrite' => $allowoverwrite);
868
		$reshook=$hookmanager->executeHooks('moveUploadedFile', $parameters, $object);
869
	}
870
871
	if (empty($reshook))
872
	{
873
    	// If an upload error has been reported
874
    	if ($uploaderrorcode)
875
    	{
876
    	    switch($uploaderrorcode)
877
    	    {
878
    	        case UPLOAD_ERR_INI_SIZE:	// 1
879
    	            return 'ErrorFileSizeTooLarge';
880
    	            break;
881
    	        case UPLOAD_ERR_FORM_SIZE:	// 2
882
    	            return 'ErrorFileSizeTooLarge';
883
    	            break;
884
    	        case UPLOAD_ERR_PARTIAL:	// 3
885
    	            return 'ErrorPartialFile';
886
    	            break;
887
    	        case UPLOAD_ERR_NO_TMP_DIR:	//
888
    	            return 'ErrorNoTmpDir';
889
    	            break;
890
    	        case UPLOAD_ERR_CANT_WRITE:
891
    	            return 'ErrorFailedToWriteInDir';
892
    	            break;
893
    	        case UPLOAD_ERR_EXTENSION:
894
    	            return 'ErrorUploadBlockedByAddon';
895
    	            break;
896
    	        default:
897
    	            break;
898
    	    }
899
    	}
900
901
    	// If we need to make a virus scan
902
    	if (empty($disablevirusscan) && file_exists($src_file))
903
    	{
904
    	    $checkvirusarray=dolCheckVirus($src_file);
905
    	    if (count($checkvirusarray))
906
    	    {
907
    	       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);
0 ignored issues
show
Bug introduced by
The variable $result does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
908
    	       return 'ErrorFileIsInfectedWithAVirus: '.join(',',$checkvirusarray);
909
    	    }
910
    	}
911
912
    	// Security:
913
    	// Disallow file with some extensions. We rename them.
914
    	// Because if we put the documents directory into a directory inside web root (very bad), this allows to execute on demand arbitrary code.
915
    	if (preg_match('/\.htm|\.html|\.php|\.pl|\.cgi$/i',$dest_file) && empty($conf->global->MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED))
916
    	{
917
    	    $file_name.= '.noexe';
918
    	}
919
920
    	// Security:
921
    	// We refuse cache files/dirs, upload using .. and pipes into filenames.
922
    	if (preg_match('/^\./',$src_file) || preg_match('/\.\./',$src_file) || preg_match('/[<>|]/',$src_file))
923
    	{
924
    	    dol_syslog("Refused to deliver file ".$src_file, LOG_WARNING);
925
    	    return -1;
926
    	}
927
928
    	// Security:
929
    	// On interdit fichiers caches, remontees de repertoire ainsi que les pipe dans les noms de fichiers.
930
    	if (preg_match('/^\./',$dest_file) || preg_match('/\.\./',$dest_file) || preg_match('/[<>|]/',$dest_file))
931
    	{
932
    	    dol_syslog("Refused to deliver file ".$dest_file, LOG_WARNING);
933
    	    return -2;
934
    	}
935
	}
936
937
	if ($reshook < 0)	// At least one blocking error returned by one hook
938
	{
939
		$errmsg = join(',', $hookmanager->errors);
940
		if (empty($errmsg)) $errmsg = 'ErrorReturnedBySomeHooks';	// Should not occurs. Added if hook is bugged and does not set ->errors when there is error.
941
		return $errmsg;
942
	}
943
	elseif (empty($reshook))
944
	{
945
		// The file functions must be in OS filesystem encoding.
946
		$src_file_osencoded=dol_osencode($src_file);
947
		$file_name_osencoded=dol_osencode($file_name);
948
949
		// Check if destination dir is writable
950
		// TODO
951
952
		// Check if destination file already exists
953
		if (! $allowoverwrite)
954
		{
955
			if (file_exists($file_name_osencoded))
956
			{
957
				dol_syslog("Files.lib::dol_move_uploaded_file File ".$file_name." already exists. Return 'ErrorFileAlreadyExists'", LOG_WARNING);
958
				return 'ErrorFileAlreadyExists';
959
			}
960
		}
961
962
		// Move file
963
		$return=move_uploaded_file($src_file_osencoded, $file_name_osencoded);
964
		if ($return)
965
		{
966
			if (! empty($conf->global->MAIN_UMASK)) @chmod($file_name_osencoded, octdec($conf->global->MAIN_UMASK));
967
			dol_syslog("Files.lib::dol_move_uploaded_file Success to move ".$src_file." to ".$file_name." - Umask=".$conf->global->MAIN_UMASK, LOG_DEBUG);
968
			return 1;	// Success
969
		}
970
		else
971
		{
972
			dol_syslog("Files.lib::dol_move_uploaded_file Failed to move ".$src_file." to ".$file_name, LOG_ERR);
973
			return -3;	// Unknown error
974
		}
975
	}
976
977
	return 1;	// Success
978
}
979
980
/**
981
 *  Remove a file or several files with a mask
982
 *
983
 *  @param	string	$file           File to delete or mask of files to delete
984
 *  @param  int		$disableglob    Disable usage of glob like * so function is an exact delete function that will return error if no file found
985
 *  @param  int		$nophperrors    Disable all PHP output errors
986
 *  @param	int		$nohook			Disable all hooks
987
 *  @param	object	$object			Current object in use
988
 *  @return boolean         		True if no error (file is deleted or if glob is used and there's nothing to delete), False if error
989
 *  @see dol_delete_dir
990
 */
991
function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=null)
0 ignored issues
show
Coding Style introduced by
dol_delete_file uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
992
{
993
	global $db, $conf, $user, $langs;
994
	global $hookmanager;
995
996
	$langs->load("other");
997
	$langs->load("errors");
998
999
	dol_syslog("dol_delete_file file=".$file." disableglob=".$disableglob." nophperrors=".$nophperrors." nohook=".$nohook);
1000
1001
	// Security:
1002
	// We refuse transversal using .. and pipes into filenames.
1003
	if (preg_match('/\.\./',$file) || preg_match('/[<>|]/',$file))
1004
	{
1005
        dol_syslog("Refused to delete file ".$file, LOG_WARNING);
1006
	    return False;
1007
	}
1008
1009
	if (empty($nohook))
1010
	{
1011
		$hookmanager->initHooks(array('fileslib'));
1012
1013
		$parameters=array(
1014
				'GET' => $_GET,
1015
				'file' => $file,
1016
				'disableglob'=> $disableglob,
1017
				'nophperrors' => $nophperrors
1018
		);
1019
		$reshook=$hookmanager->executeHooks('deleteFile', $parameters, $object);
1020
	}
1021
1022
	if (empty($nohook) && $reshook != 0) // reshook = 0 to do standard actions, 1 = ok, -1 = ko
1023
	{
1024
		if ($reshook < 0) return false;
0 ignored issues
show
Bug introduced by
The variable $reshook does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1025
		return true;
1026
	}
1027
	else
1028
	{
1029
		$error=0;
1030
1031
		//print "x".$file." ".$disableglob;exit;
1032
		$file_osencoded=dol_osencode($file);    // New filename encoded in OS filesystem encoding charset
1033
		if (empty($disableglob) && ! empty($file_osencoded))
1034
		{
1035
			$ok=true;
1036
			$globencoded=str_replace('[','\[',$file_osencoded);
1037
			$globencoded=str_replace(']','\]',$globencoded);
1038
			$listofdir=glob($globencoded);
1039
			if (! empty($listofdir) && is_array($listofdir))
1040
			{
1041
				foreach ($listofdir as $filename)
1042
				{
1043
					if ($nophperrors) $ok=@unlink($filename);
1044
					else $ok=unlink($filename);
1045
					if ($ok)
1046
					{
1047
					    dol_syslog("Removed file ".$filename, LOG_DEBUG);
1048
1049
	                    // Delete entry into ecm database
1050
    				    $rel_filetodelete = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $filename);
1051
    				    if (! preg_match('/(\/temp\/|\/thumbs\/|\.meta$)/', $rel_filetodelete))     // If not a tmp file
1052
    				    {
1053
    				        $rel_filetodelete = preg_replace('/^[\\/]/', '', $rel_filetodelete);
1054
1055
    				        dol_syslog("Try to remove also entries in database for full relative path = ".$rel_filetodelete, LOG_DEBUG);
1056
        				    include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
1057
        				    $ecmfile=new EcmFiles($db);
1058
        				    $result = $ecmfile->fetch(0, '', $rel_filetodelete);
1059
        				    if ($result >= 0 && $ecmfile->id > 0)
1060
        				    {
1061
        				        $result = $ecmfile->delete($user);
1062
        				    }
1063
        				    if ($result < 0)
1064
        				    {
1065
        				        setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
1066
        				    }
1067
    				    }
1068
					}
1069
					else dol_syslog("Failed to remove file ".$filename, LOG_WARNING);
1070
					// TODO Failure to remove can be because file was already removed or because of permission
1071
					// If error because of not exists, we must should return true and we should return false if this is a permission problem
1072
				}
1073
			}
1074
			else dol_syslog("No files to delete found", LOG_DEBUG);
1075
		}
1076
		else
1077
		{
1078
			$ok=false;
1079
			if ($nophperrors) $ok=@unlink($file_osencoded);
1080
			else $ok=unlink($file_osencoded);
1081
			if ($ok) dol_syslog("Removed file ".$file_osencoded, LOG_DEBUG);
1082
			else dol_syslog("Failed to remove file ".$file_osencoded, LOG_WARNING);
1083
		}
1084
1085
		return $ok;
1086
	}
1087
}
1088
1089
/**
1090
 *  Remove a directory (not recursive, so content must be empty).
1091
 *  If directory is not empty, return false
1092
 *
1093
 *  @param	string	$dir            Directory to delete
1094
 *  @param  int		$nophperrors    Disable all PHP output errors
1095
 *  @return boolean         		True if success, false if error
1096
 *  @see dol_delete_file
1097
 */
1098
function dol_delete_dir($dir,$nophperrors=0)
1099
{
1100
	// Security:
1101
	// We refuse transversal using .. and pipes into filenames.
1102
	if (preg_match('/\.\./',$dir) || preg_match('/[<>|]/',$dir))
1103
	{
1104
        dol_syslog("Refused to delete dir ".$dir, LOG_WARNING);
1105
	    return False;
1106
	}
1107
1108
    $dir_osencoded=dol_osencode($dir);
1109
    return ($nophperrors?@rmdir($dir_osencoded):rmdir($dir_osencoded));
1110
}
1111
1112
/**
1113
 *  Remove a directory $dir and its subdirectories (or only files and subdirectories)
1114
 *
1115
 *  @param	string	$dir            Dir to delete
1116
 *  @param  int		$count          Counter to count nb of elements found to delete
1117
 *  @param  int		$nophperrors    Disable all PHP output errors
1118
 *  @param	int		$onlysub		Delete only files and subdir, not main directory
1119
 *  @param  int		$countdeleted   Counter to count nb of elements found really deleted
1120
 *  @return int             		Number of files and directory we try to remove. NB really removed is returned into $countdeleted.
1121
 */
1122
function dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0)
1123
{
1124
    dol_syslog("functions.lib:dol_delete_dir_recursive ".$dir,LOG_DEBUG);
1125
    if (dol_is_dir($dir))
1126
    {
1127
        $dir_osencoded=dol_osencode($dir);
1128
        if ($handle = opendir("$dir_osencoded"))
1129
        {
1130
            while (false !== ($item = readdir($handle)))
1131
            {
1132
                if (! utf8_check($item)) $item=utf8_encode($item);  // should be useless
1133
1134
                if ($item != "." && $item != "..")
1135
                {
1136
                    if (is_dir(dol_osencode("$dir/$item")))
1137
                    {
1138
                        $count=dol_delete_dir_recursive("$dir/$item", $count, $nophperrors, 0, $countdeleted);
1139
                    }
1140
                    else
1141
                    {
1142
                        $result=dol_delete_file("$dir/$item", 1, $nophperrors);
1143
                        $count++;
1144
                        if ($result) $countdeleted++;
1145
                    }
1146
                }
1147
            }
1148
            closedir($handle);
1149
1150
            if (empty($onlysub))
1151
            {
1152
	            $result=dol_delete_dir($dir, $nophperrors);
1153
	            $count++;
1154
    	        if ($result) $countdeleted++;
1155
            }
1156
        }
1157
    }
1158
1159
    return $count;
1160
}
1161
1162
1163
/**
1164
 *  Delete all preview files linked to object instance
1165
 *
1166
 *  @param	object	$object		Object to clean
1167
 *  @return	int					0 if error, 1 if OK
1168
 */
1169
function dol_delete_preview($object)
1170
{
1171
	global $langs,$conf;
1172
1173
	// Define parent dir of elements
1174
	$element = $object->element;
1175
1176
    if ($object->element == 'order_supplier')		$dir = $conf->fournisseur->dir_output.'/commande';
1177
    elseif ($object->element == 'invoice_supplier')	$dir = $conf->fournisseur->dir_output.'/facture';
1178
    elseif ($object->element == 'project')			$dir = $conf->projet->dir_output;
1179
    elseif ($object->element == 'shipping')			$dir = $conf->expedition->dir_output.'/sending';
1180
    elseif ($object->element == 'delivery')			$dir = $conf->expedition->dir_output.'/receipt';
1181
    elseif ($object->element == 'fichinter')		$dir = $conf->ficheinter->dir_output;
1182
    else $dir=empty($conf->$element->dir_output)?'':$conf->$element->dir_output;
1183
1184
    if (empty($dir)) return 'ErrorObjectNoSupportedByFunction';
1185
1186
	$refsan = dol_sanitizeFileName($object->ref);
1187
	$dir = $dir . "/" . $refsan ;
1188
	$file = $dir . "/" . $refsan . ".pdf.png";
1189
	$multiple = $file . ".";
1190
1191
	if (file_exists($file) && is_writable($file))
1192
	{
1193
		if (! dol_delete_file($file,1))
1194
		{
1195
			$object->error=$langs->trans("ErrorFailedToDeleteFile",$file);
1196
			return 0;
1197
		}
1198
	}
1199
	else
1200
	{
1201
		for ($i = 0; $i < 20; $i++)
1202
		{
1203
			$preview = $multiple.$i;
1204
1205
			if (file_exists($preview) && is_writable($preview))
1206
			{
1207
				if ( ! dol_delete_file($preview,1) )
1208
				{
1209
					$object->error=$langs->trans("ErrorFailedToOpenFile",$preview);
1210
					return 0;
1211
				}
1212
			}
1213
		}
1214
	}
1215
1216
	return 1;
1217
}
1218
1219
/**
1220
 *	Create a meta file with document file into same directory.
1221
 *	This should allow "grep" search.
1222
 *  This feature is enabled only if option MAIN_DOC_CREATE_METAFILE is set.
1223
 *
1224
 *	@param	CommonObject	$object		Object
1225
 *	@return	int					0 if we did nothing, >0 success, <0 error
1226
 */
1227
function dol_meta_create($object)
1228
{
1229
	global $conf;
1230
1231
	if (empty($conf->global->MAIN_DOC_CREATE_METAFILE)) return 0;	// By default, no metafile.
1232
1233
	// Define parent dir of elements
1234
	$element=$object->element;
1235
1236
	if ($object->element == 'order_supplier')		$dir = $conf->fournisseur->dir_output.'/commande';
1237
	elseif ($object->element == 'invoice_supplier')	$dir = $conf->fournisseur->dir_output.'/facture';
1238
	elseif ($object->element == 'project')			$dir = $conf->projet->dir_output;
1239
	elseif ($object->element == 'shipping')			$dir = $conf->expedition->dir_output.'/sending';
1240
	elseif ($object->element == 'delivery')			$dir = $conf->expedition->dir_output.'/receipt';
1241
	elseif ($object->element == 'fichinter')		$dir = $conf->ficheinter->dir_output;
1242
	else $dir=empty($conf->$element->dir_output)?'':$conf->$element->dir_output;
1243
1244
	if ($dir)
1245
	{
1246
		$object->fetch_thirdparty();
1247
1248
		$facref = dol_sanitizeFileName($object->ref);
1249
		$dir = $dir . "/" . $facref;
1250
		$file = $dir . "/" . $facref . ".meta";
1251
1252
		if (! is_dir($dir))
1253
		{
1254
			dol_mkdir($dir);
1255
		}
1256
1257
		if (is_dir($dir))
1258
		{
1259
			$nblignes = count($object->lines);
1260
			$client = $object->thirdparty->name . " " . $object->thirdparty->address . " " . $object->thirdparty->zip . " " . $object->thirdparty->town;
1261
			$meta = "REFERENCE=\"" . $object->ref . "\"
1262
			DATE=\"" . dol_print_date($object->date,'') . "\"
1263
			NB_ITEMS=\"" . $nblignes . "\"
1264
			CLIENT=\"" . $client . "\"
1265
			TOTAL_HT=\"" . $object->total_ht . "\"
1266
			TOTAL_TTC=\"" . $object->total_ttc . "\"\n";
1267
1268
			for ($i = 0 ; $i < $nblignes ; $i++)
1269
			{
1270
				//Pour les articles
1271
				$meta .= "ITEM_" . $i . "_QUANTITY=\"" . $object->lines[$i]->qty . "\"
1272
				ITEM_" . $i . "_TOTAL_HT=\"" . $object->lines[$i]->total_ht . "\"
1273
				ITEM_" . $i . "_TVA=\"" .$object->lines[$i]->tva_tx . "\"
1274
				ITEM_" . $i . "_DESCRIPTION=\"" . str_replace("\r\n","",nl2br($object->lines[$i]->desc)) . "\"
1275
				";
1276
			}
1277
		}
1278
1279
		$fp = fopen($file,"w");
1280
		fputs($fp,$meta);
0 ignored issues
show
Bug introduced by
The variable $meta does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1281
		fclose($fp);
1282
		if (! empty($conf->global->MAIN_UMASK))
1283
		@chmod($file, octdec($conf->global->MAIN_UMASK));
1284
1285
		return 1;
1286
	}
1287
1288
	return 0;
1289
}
1290
1291
1292
1293
/**
1294
 * Scan a directory and init $_SESSION to manage uploaded files with list of all found files.
1295
 * Note: Only email module seems to use this. Other feature initialize the $_SESSION doing $formmail->clear_attached_files(); $formmail->add_attached_files()
1296
 *
1297
 * @param	string	$pathtoscan				Path to scan
1298
 * @param   string  $trackid                Track id (used to prefix name of session vars to avoid conflict)
1299
 * @return	void
1300
 */
1301
function dol_init_file_process($pathtoscan='', $trackid='')
1302
{
1303
	$listofpaths=array();
1304
	$listofnames=array();
1305
	$listofmimes=array();
1306
1307
	if ($pathtoscan)
1308
	{
1309
		$listoffiles=dol_dir_list($pathtoscan,'files');
1310
		foreach($listoffiles as $key => $val)
1311
		{
1312
			$listofpaths[]=$val['fullname'];
1313
			$listofnames[]=$val['name'];
1314
			$listofmimes[]=dol_mimetype($val['name']);
1315
		}
1316
	}
1317
    $keytoavoidconflict = empty($trackid)?'':'-'.$trackid;
1318
	$_SESSION["listofpaths".$keytoavoidconflict]=join(';',$listofpaths);
1319
	$_SESSION["listofnames".$keytoavoidconflict]=join(';',$listofnames);
1320
	$_SESSION["listofmimes".$keytoavoidconflict]=join(';',$listofmimes);
1321
}
1322
1323
1324
/**
1325
 * Get and save an upload file (for example after submitting a new file a mail form).
1326
 * All information used are in db, conf, langs, user and _FILES.
1327
 * Note: This function can be used only into a HTML page context.
1328
 *
1329
 * @param	string	$upload_dir				Directory where to store uploaded file (note: used to forge $destpath = $upload_dir + filename)
1330
 * @param	int		$allowoverwrite			1=Allow overwrite existing file
1331
 * @param	int		$donotupdatesession		1=Do no edit _SESSION variable
1332
 * @param	string	$varfiles				_FILES var name
1333
 * @param	string	$savingdocmask			Mask to use to define output filename. For example 'XXXXX-__YYYYMMDD__-__file__'
1334
 * @param	string	$link					Link to add (to add a link instead of a file)
1335
 * @param   string  $trackid                Track id (used to prefix name of session vars to avoid conflict)
1336
 * @return	int                             <=0 if KO, >0 if OK
1337
 */
1338
function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesession=0, $varfiles='addedfile', $savingdocmask='', $link=null, $trackid='')
0 ignored issues
show
Coding Style introduced by
dol_add_file_process uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
1339
{
1340
	global $db,$user,$conf,$langs;
1341
1342
	$res = 0;
1343
1344
	if (! empty($_FILES[$varfiles])) // For view $_FILES[$varfiles]['error']
1345
	{
1346
		dol_syslog('dol_add_file_process upload_dir='.$upload_dir.' allowoverwrite='.$allowoverwrite.' donotupdatesession='.$donotupdatesession.' savingdocmask='.$savingdocmask, LOG_DEBUG);
1347
		if (dol_mkdir($upload_dir) >= 0)
1348
		{
1349
			$TFile = $_FILES[$varfiles];
1350
			if (!is_array($TFile['name']))
1351
			{
1352
				foreach ($TFile as $key => &$val)
1353
				{
1354
					$val = array($val);
1355
				}
1356
			}
1357
1358
			$nbfile = count($TFile['name']);
1359
1360
			for ($i = 0; $i < $nbfile; $i++)
1361
			{
1362
				// Define $destfull (path to file including filename) and $destfile (only filename)
1363
				$destfull=$upload_dir . "/" . $TFile['name'][$i];
1364
				$destfile=$TFile['name'][$i];
1365
1366
				$savingdocmask = dol_sanitizeFileName($savingdocmask);
1367
1368
				if ($savingdocmask)
1369
				{
1370
					$destfull=$upload_dir . "/" . preg_replace('/__file__/',$TFile['name'][$i],$savingdocmask);
1371
					$destfile=preg_replace('/__file__/',$TFile['name'][$i],$savingdocmask);
1372
				}
1373
1374
				// lowercase extension
1375
				$info = pathinfo($destfull);
1376
				$destfull = $info['dirname'].'/'.$info['filename'].'.'.strtolower($info['extension']);
1377
				$info = pathinfo($destfile);
1378
				$destfile = $info['filename'].'.'.strtolower($info['extension']);
1379
1380
				$resupload = dol_move_uploaded_file($TFile['tmp_name'][$i], $destfull, $allowoverwrite, 0, $TFile['error'][$i], 0, $varfiles);
1381
1382
				if (is_numeric($resupload) && $resupload > 0)   // $resupload can be 'ErrorFileAlreadyExists'
1383
				{
1384
					global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini;
1385
1386
					include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
1387
1388
					// Generate thumbs.
1389
					if (image_format_supported($destfull) == 1)
1390
					{
1391
					    // Create thumbs
1392
					    // We can't use $object->addThumbs here because there is no $object known
1393
1394
					    // Used on logon for example
1395
					    $imgThumbSmall = vignette($destfull, $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs");
1396
					    // Create mini thumbs for image (Ratio is near 16/9)
1397
					    // Used on menu or for setup page for example
1398
					    $imgThumbMini = vignette($destfull, $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs");
1399
					}
1400
1401
					// Update session
1402
					if (empty($donotupdatesession))
1403
					{
1404
						include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
1405
						$formmail = new FormMail($db);
1406
						$formmail->trackid = $trackid;
1407
						$formmail->add_attached_files($destfull, $destfile, $TFile['type'][$i]);
1408
					}
1409
1410
					// Update table of files
1411
					if ($donotupdatesession)
1412
					{
1413
					    $rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $upload_dir);
1414
1415
					    if (! preg_match('/[\\/]temp[\\/]/', $rel_dir))     // If not a tmp dir
1416
					    {
1417
					        $filename = basename($destfile);
1418
					        $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
1419
					        $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
1420
1421
    					    include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
1422
    					    $ecmfile=new EcmFiles($db);
1423
    					    $ecmfile->filepath = $rel_dir;
1424
    					    $ecmfile->filename = $filename;
1425
    					    $ecmfile->label = md5_file(dol_osencode($destfull));
1426
    					    $ecmfile->fullpath_orig = $TFile['name'][$i];
1427
    					    $ecmfile->gen_or_uploaded = 'uploaded';
1428
    					    $ecmfile->description = '';    // indexed content
1429
    					    $ecmfile->keyword = '';        // keyword content
1430
    					    $result = $ecmfile->create($user);
1431
                            if ($result < 0)
1432
                            {
1433
                                setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
1434
                            }
1435
					    }
1436
					}
1437
1438
					$res = 1;
1439
					setEventMessages($langs->trans("FileTransferComplete"), null, 'mesgs');
1440
				}
1441
				else
1442
				{
1443
					$langs->load("errors");
1444
					if ($resupload < 0)	// Unknown error
1445
					{
1446
						setEventMessages($langs->trans("ErrorFileNotUploaded"), null, 'errors');
1447
					}
1448
					else if (preg_match('/ErrorFileIsInfectedWithAVirus/',$resupload))	// Files infected by a virus
1449
					{
1450
						setEventMessages($langs->trans("ErrorFileIsInfectedWithAVirus"), null, 'errors');
1451
					}
1452
					else	// Known error
1453
					{
1454
						setEventMessages($langs->trans($resupload), null, 'errors');
1455
					}
1456
				}
1457
			}
1458
1459
		}
1460
	} elseif ($link) {
1461
		require_once DOL_DOCUMENT_ROOT . '/core/class/link.class.php';
1462
		$linkObject = new Link($db);
1463
		$linkObject->entity = $conf->entity;
1464
		$linkObject->url = $link;
1465
		$linkObject->objecttype = GETPOST('objecttype', 'alpha');
1466
		$linkObject->objectid = GETPOST('objectid', 'int');
1467
		$linkObject->label = GETPOST('label', 'alpha');
1468
		$res = $linkObject->create($user);
1469
		$langs->load('link');
1470
		if ($res > 0) {
1471
			setEventMessages($langs->trans("LinkComplete"), null, 'mesgs');
1472
		} else {
1473
			setEventMessages($langs->trans("ErrorFileNotLinked"), null, 'errors');
1474
		}
1475
	}
1476
	else
1477
	{
1478
		$langs->load("errors");
1479
		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("File")), null, 'errors');
1480
	}
1481
1482
	return $res;
1483
}
1484
1485
1486
/**
1487
 * Remove an uploaded file (for example after submitting a new file a mail form).
1488
 * All information used are in db, conf, langs, user and _FILES.
1489
 *
1490
 * @param	int		$filenb					File nb to delete
1491
 * @param	int		$donotupdatesession		1=Do not edit _SESSION variable
1492
 * @param   int		$donotdeletefile        1=Do not delete physically file
1493
 * @param   string  $trackid                Track id (used to prefix name of session vars to avoid conflict)
1494
 * @return	void
1495
 */
1496
function dol_remove_file_process($filenb,$donotupdatesession=0,$donotdeletefile=1,$trackid='')
0 ignored issues
show
Coding Style introduced by
dol_remove_file_process uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
1497
{
1498
	global $db,$user,$conf,$langs,$_FILES;
1499
1500
	$keytodelete=$filenb;
1501
	$keytodelete--;
1502
1503
	$listofpaths=array();
1504
	$listofnames=array();
1505
	$listofmimes=array();
1506
    $keytoavoidconflict = empty($trackid)?'':'-'.$trackid;
1507
	if (! empty($_SESSION["listofpaths".$keytoavoidconflict])) $listofpaths=explode(';',$_SESSION["listofpaths".$keytoavoidconflict]);
1508
	if (! empty($_SESSION["listofnames".$keytoavoidconflict])) $listofnames=explode(';',$_SESSION["listofnames".$keytoavoidconflict]);
1509
	if (! empty($_SESSION["listofmimes".$keytoavoidconflict])) $listofmimes=explode(';',$_SESSION["listofmimes".$keytoavoidconflict]);
1510
1511
	if ($keytodelete >= 0)
1512
	{
1513
		$pathtodelete=$listofpaths[$keytodelete];
1514
		$filetodelete=$listofnames[$keytodelete];
1515
		if (empty($donotdeletefile)) $result = dol_delete_file($pathtodelete,1);  // The delete of ecm database is inside the function dol_delete_file
1516
		else $result=0;
1517
		if ($result >= 0)
1518
		{
1519
			if (empty($donotdeletefile))
1520
			{
1521
				$langs->load("other");
1522
				setEventMessages($langs->trans("FileWasRemoved",$filetodelete), null, 'mesgs');
1523
			}
1524
			if (empty($donotupdatesession))
1525
			{
1526
				include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
1527
				$formmail = new FormMail($db);
1528
				$formmail->trackid = $trackid;
1529
				$formmail->remove_attached_files($keytodelete);
1530
			}
1531
		}
1532
	}
1533
}
1534
1535
/**
1536
 * 	Convert an image file into anoher format.
1537
 *  This need Imagick php extension.
1538
 *
1539
 *  @param	string	$fileinput  Input file name
1540
 *  @param  string	$ext        Format of target file (It is also extension added to file if fileoutput is not provided).
1541
 *  @param	string	$fileoutput	Output filename
1542
 *  @return	int					<0 if KO, >0 if OK
1543
 */
1544
function dol_convert_file($fileinput,$ext='png',$fileoutput='')
1545
{
1546
	global $langs;
1547
1548
	$image=new Imagick();
1549
	$ret = $image->readImage($fileinput);
1550
	if ($ret)
1551
	{
1552
		$ret = $image->setImageFormat($ext);
1553
		if ($ret)
1554
		{
1555
			if (empty($fileoutput)) $fileoutput=$fileinput.".".$ext;
1556
1557
			$count = $image->getNumberImages();
1558
			$ret = $image->writeImages($fileoutput, true);
1559
			if ($ret) return $count;
1560
			else return -3;
1561
		}
1562
		else
1563
		{
1564
			return -2;
1565
		}
1566
	}
1567
	else
1568
	{
1569
		return -1;
1570
	}
1571
}
1572
1573
1574
/**
1575
 * Compress a file
1576
 *
1577
 * @param 	string	$inputfile		Source file name
1578
 * @param 	string	$outputfile		Target file name
1579
 * @param 	string	$mode			'gz' or 'bz' or 'zip'
1580
 * @return	int						<0 if KO, >0 if OK
1581
 */
1582
function dol_compress_file($inputfile, $outputfile, $mode="gz")
1583
{
1584
    $foundhandler=0;
1585
1586
    try
1587
    {
1588
        $data = implode("", file(dol_osencode($inputfile)));
1589
        if ($mode == 'gz')     { $foundhandler=1; $compressdata = gzencode($data, 9); }
1590
        elseif ($mode == 'bz') { $foundhandler=1; $compressdata = bzcompress($data, 9); }
1591
        elseif ($mode == 'zip')
1592
        {
1593
            if (defined('ODTPHP_PATHTOPCLZIP'))
1594
            {
1595
                $foundhandler=1;
1596
1597
                include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
1598
                $archive = new PclZip($outputfile);
1599
                $archive->add($inputfile, PCLZIP_OPT_REMOVE_PATH, dirname($inputfile));
1600
                //$archive->add($inputfile);
1601
                return 1;
1602
            }
1603
        }
1604
1605
        if ($foundhandler)
1606
        {
1607
            $fp = fopen($outputfile, "w");
1608
            fwrite($fp, $compressdata);
0 ignored issues
show
Bug introduced by
The variable $compressdata does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1609
            fclose($fp);
1610
            return 1;
1611
        }
1612
        else
1613
        {
1614
            dol_syslog("Try to zip with format ".$mode." with no handler for this format",LOG_ERR);
1615
            return -2;
1616
        }
1617
    }
1618
    catch (Exception $e)
1619
    {
1620
        global $langs, $errormsg;
1621
        $langs->load("errors");
1622
        dol_syslog("Failed to open file ".$outputfile,LOG_ERR);
1623
        $errormsg=$langs->trans("ErrorFailedToWriteInDir");
1624
        return -1;
1625
    }
1626
}
1627
1628
/**
1629
 * Uncompress a file
1630
 *
1631
 * @param 	string 	$inputfile		File to uncompress
1632
 * @param 	string	$outputdir		Target dir name
1633
 * @return 	array					array('error'=>'Error code') or array() if no error
1634
 */
1635
function dol_uncompress($inputfile,$outputdir)
1636
{
1637
    global $langs;
1638
1639
    if (defined('ODTPHP_PATHTOPCLZIP'))
1640
    {
1641
    	dol_syslog("Constant ODTPHP_PATHTOPCLZIP for pclzip library is set to ".ODTPHP_PATHTOPCLZIP.", so we use Pclzip to unzip into ".$outputdir);
1642
        include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
1643
        $archive = new PclZip($inputfile);
1644
        $result=$archive->extract(PCLZIP_OPT_PATH, $outputdir);
1645
        //var_dump($result);
1646
        if (! is_array($result) && $result <= 0) return array('error'=>$archive->errorInfo(true));
1647
        else
1648
		{
1649
			$ok=1; $errmsg='';
1650
			// Loop on each file to check result for unzipping file
1651
			foreach($result as $key => $val)
1652
			{
1653
				if ($val['status'] == 'path_creation_fail')
1654
				{
1655
					$langs->load("errors");
1656
					$ok=0;
1657
					$errmsg=$langs->trans("ErrorFailToCreateDir", $val['filename']);
1658
					break;
1659
				}
1660
			}
1661
1662
			if ($ok) return array();
1663
			else return array('error'=>$errmsg);
1664
		}
1665
    }
1666
1667
    if (class_exists('ZipArchive'))
1668
    {
1669
    	dol_syslog("Class ZipArchive is set so we unzip using ZipArchive to unzip into ".$outputdir);
1670
    	$zip = new ZipArchive;
1671
        $res = $zip->open($inputfile);
1672
        if ($res === TRUE)
1673
        {
1674
            $zip->extractTo($outputdir.'/');
1675
            $zip->close();
1676
            return array();
1677
        }
1678
        else
1679
        {
1680
            return array('error'=>'ErrUnzipFails');
1681
        }
1682
    }
1683
1684
    return array('error'=>'ErrNoZipEngine');
1685
}
1686
1687
1688
/**
1689
 * Compress a directory and subdirectories into a package file.
1690
 *
1691
 * @param 	string	$inputdir		Source dir name
1692
 * @param 	string	$outputfile		Target file name
1693
 * @param 	string	$mode			'zip'
1694
 * @return	int						<0 if KO, >0 if OK
1695
 */
1696
function dol_compress_dir($inputdir, $outputfile, $mode="zip")
1697
{
1698
    $foundhandler=0;
1699
1700
    dol_syslog("Try to zip dir ".$inputdir." into ".$outputdir." mode=".$mode);
0 ignored issues
show
Bug introduced by
The variable $outputdir does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1701
    try
1702
    {
1703
        if ($mode == 'gz')     { $foundhandler=0; }
1704
        elseif ($mode == 'bz') { $foundhandler=0; }
1705
        elseif ($mode == 'zip')
1706
        {
1707
            /*if (defined('ODTPHP_PATHTOPCLZIP'))
1708
            {
1709
                $foundhandler=0;        // TODO implement this
1710
1711
                include_once ODTPHP_PATHTOPCLZIP.'/pclzip.lib.php';
1712
                $archive = new PclZip($outputfile);
1713
                $archive->add($inputfile, PCLZIP_OPT_REMOVE_PATH, dirname($inputfile));
1714
                //$archive->add($inputfile);
1715
                return 1;
1716
            }
1717
            else*/
1718
            if (class_exists('ZipArchive'))
1719
            {
1720
                $foundhandler=1;
1721
1722
                // Initialize archive object
1723
                $zip = new ZipArchive();
1724
                $zip->open($outputfile, ZipArchive::CREATE | ZipArchive::OVERWRITE);
1725
1726
                // Create recursive directory iterator
1727
                /** @var SplFileInfo[] $files */
1728
                $files = new RecursiveIteratorIterator(
1729
                    new RecursiveDirectoryIterator($inputdir),
1730
                    RecursiveIteratorIterator::LEAVES_ONLY
1731
                    );
1732
1733
                foreach ($files as $name => $file)
1734
                {
1735
                    // Skip directories (they would be added automatically)
1736
                    if (!$file->isDir())
1737
                    {
1738
                        // Get real and relative path for current file
1739
                        $filePath = $file->getRealPath();
1740
                        $relativePath = substr($filePath, strlen($inputdir) + 1);
1741
1742
                        // Add current file to archive
1743
                        $zip->addFile($filePath, $relativePath);
1744
                    }
1745
                }
1746
1747
                // Zip archive will be created only after closing object
1748
                $zip->close();
1749
1750
                return 1;
1751
            }
1752
        }
1753
1754
        if (! $foundhandler)
1755
        {
1756
            dol_syslog("Try to zip with format ".$mode." with no handler for this format",LOG_ERR);
1757
            return -2;
1758
        }
1759
    }
1760
    catch (Exception $e)
1761
    {
1762
        global $langs, $errormsg;
1763
        $langs->load("errors");
1764
        dol_syslog("Failed to open file ".$outputfile, LOG_ERR);
1765
        dol_syslog($e->getMessage(), LOG_ERR);
1766
        $errormsg=$langs->trans("ErrorFailedToWriteInDir",$outputfile);
1767
        return -1;
1768
    }
1769
}
1770
1771
1772
1773
/**
1774
 * Return file(s) into a directory (by default most recent)
1775
 *
1776
 * @param 	string		$dir			Directory to scan
1777
 * @param	string		$regexfilter	Regex filter to restrict list. This regex value must be escaped for '/', since this char is used for preg_match function
1778
 * @param	array		$excludefilter  Array of Regex for exclude filter (example: array('(\.meta|_preview.*\.png)$','^\.')). This regex value must be escaped for '/', since this char is used for preg_match function
1779
 * @param	int			$nohook			Disable all hooks
1780
 * @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
1781
 * @return	string						Full path to most recent file
1782
 */
1783
function dol_most_recent_file($dir,$regexfilter='',$excludefilter=array('(\.meta|_preview.*\.png)$','^\.'),$nohook=false,$mode='')
1784
{
1785
    $tmparray=dol_dir_list($dir,'files',0,$regexfilter,$excludefilter,'date',SORT_DESC,$mode,$nohook);
0 ignored issues
show
Bug introduced by
It seems like $nohook defined by parameter $nohook on line 1783 can also be of type false; however, dol_dir_list() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
1786
    return $tmparray[0];
1787
}
1788
1789
/**
1790
 * Security check when accessing to a document (used by document.php, viewimage.php and webservices)
1791
 *
1792
 * @param	string	$modulepart			Module of document ('module', 'module_user_temp', 'module_user' or 'module_temp')
1793
 * @param	string	$original_file		Relative path with filename, relative to modulepart.
1794
 * @param	string	$entity				Restrict onto entity (0=no restriction)
1795
 * @param  	User	$fuser				User object (forced)
1796
 * @param	string	$refname			Ref of object to check permission for external users (autodetect if not provided)
1797
 * @param   string  $mode               Check permission for 'read' or 'write'
1798
 * @return	mixed						Array with access information : 'accessallowed' & 'sqlprotectagainstexternals' & 'original_file' (as a full path name)
1799
 * @see restrictedArea
1800
 */
1801
function dol_check_secure_access_document($modulepart, $original_file, $entity, $fuser='', $refname='', $mode='read')
1802
{
1803
	global $user, $conf, $db;
1804
	global $dolibarr_main_data_root;
1805
1806
	if (! is_object($fuser)) $fuser=$user;
1807
1808
	if (empty($modulepart)) return 'ErrorBadParameter';
1809
	if (empty($entity)) $entity=0;
1810
	dol_syslog('modulepart='.$modulepart.' original_file='.$original_file);
1811
	// We define $accessallowed and $sqlprotectagainstexternals
1812
	$accessallowed=0;
1813
	$sqlprotectagainstexternals='';
1814
	$ret=array();
1815
1816
    // Find the subdirectory name as the reference. For exemple original_file='10/myfile.pdf' -> refname='10'
1817
	if (empty($refname)) $refname=basename(dirname($original_file)."/");
1818
1819
	$relative_original_file = $original_file;
1820
1821
	// Define possible keys to use for permission check
1822
	$lire='lire'; $read='read'; $download='download';
1823
	if ($mode == 'write')
1824
	{
1825
	    $lire='creer'; $read='write'; $download='upload';
1826
	}
1827
1828
	// Wrapping for miscellaneous medias files
1829
	if ($modulepart == 'medias' && !empty($dolibarr_main_data_root))
1830
	{
1831
	    $accessallowed=1;
1832
	    $original_file=$dolibarr_main_data_root.'/medias/'.$original_file;
1833
	}
1834
	// Wrapping for *.log files, like when used with url http://.../document.php?modulepart=logs&file=dolibarr.log
1835
	elseif ($modulepart == 'logs' && !empty($dolibarr_main_data_root))
1836
	{
1837
	    $accessallowed=($user->admin && basename($original_file) == $original_file && preg_match('/^dolibarr.*\.log$/', basename($original_file)));
1838
	    $original_file=$dolibarr_main_data_root.'/'.$original_file;
1839
	}
1840
	// Wrapping for some images
1841
	elseif (($modulepart == 'mycompany' || $modulepart == 'companylogo') && !empty($conf->mycompany->dir_output))
1842
	{
1843
		$accessallowed=1;
1844
		$original_file=$conf->mycompany->dir_output.'/logos/'.$original_file;
1845
	}
1846
	// Wrapping for users photos
1847
	elseif ($modulepart == 'userphoto' && !empty($conf->user->dir_output))
1848
	{
1849
		$accessallowed=1;
1850
		$original_file=$conf->user->dir_output.'/'.$original_file;
1851
	}
1852
	// Wrapping for members photos
1853
	elseif ($modulepart == 'memberphoto' && !empty($conf->adherent->dir_output))
1854
	{
1855
		$accessallowed=1;
1856
		$original_file=$conf->adherent->dir_output.'/'.$original_file;
1857
	}
1858
	// Wrapping pour les apercu factures
1859
	elseif ($modulepart == 'apercufacture' && !empty($conf->facture->dir_output))
1860
	{
1861
		if ($fuser->rights->facture->{$lire}) $accessallowed=1;
1862
		$original_file=$conf->facture->dir_output.'/'.$original_file;
1863
	}
1864
	// Wrapping pour les apercu propal
1865
	elseif ($modulepart == 'apercupropal' && !empty($conf->propal->dir_output))
1866
	{
1867
		if ($fuser->rights->propale->{$lire}) $accessallowed=1;
1868
		$original_file=$conf->propal->dir_output.'/'.$original_file;
1869
	}
1870
	// Wrapping pour les apercu commande
1871
	elseif ($modulepart == 'apercucommande' && !empty($conf->commande->dir_output))
1872
	{
1873
		if ($fuser->rights->commande->{$lire}) $accessallowed=1;
1874
		$original_file=$conf->commande->dir_output.'/'.$original_file;
1875
	}
1876
	// Wrapping pour les apercu intervention
1877
	elseif (($modulepart == 'apercufichinter' || $modulepart == 'apercuficheinter') && !empty($conf->ficheinter->dir_output))
1878
	{
1879
	    if ($fuser->rights->ficheinter->{$lire}) $accessallowed=1;
1880
	    $original_file=$conf->ficheinter->dir_output.'/'.$original_file;
1881
	}
1882
	// Wrapping pour les apercu conat
1883
	elseif (($modulepart == 'apercucontract') && !empty($conf->contrat->dir_output))
1884
	{
1885
	    if ($fuser->rights->contrat->{$lire}) $accessallowed=1;
1886
	    $original_file=$conf->contrat->dir_output.'/'.$original_file;
1887
	}
1888
	// Wrapping pour les apercu supplier proposal
1889
	elseif (($modulepart == 'apercusupplier_proposal' || $modulepart == 'apercusupplier_proposal') && !empty($conf->supplier_proposal->dir_output))
1890
	{
1891
	    if ($fuser->rights->supplier_proposal->{$lire}) $accessallowed=1;
1892
	    $original_file=$conf->supplier_proposal->dir_output.'/'.$original_file;
1893
	}
1894
	// Wrapping pour les apercu supplier order
1895
	elseif (($modulepart == 'apercusupplier_order' || $modulepart == 'apercusupplier_order') && !empty($conf->fournisseur->commande->dir_output))
1896
	{
1897
	    if ($fuser->rights->fournisseur->commande->{$lire}) $accessallowed=1;
1898
	    $original_file=$conf->fournisseur->commande->dir_output.'/'.$original_file;
1899
	}
1900
	// Wrapping pour les apercu supplier invoice
1901
	elseif (($modulepart == 'apercusupplier_invoice' || $modulepart == 'apercusupplier_invoice') && !empty($conf->fournisseur->facture->dir_output))
1902
	{
1903
	    if ($fuser->rights->fournisseur->facture->{$lire}) $accessallowed=1;
1904
	    $original_file=$conf->fournisseur->facture->dir_output.'/'.$original_file;
1905
	}
1906
	// Wrapping pour les apercu supplier invoice
1907
	elseif (($modulepart == 'apercuexpensereport') && !empty($conf->expensereport->dir_output))
1908
	{
1909
	    if ($fuser->rights->expensereport->{$lire}) $accessallowed=1;
1910
	    $original_file=$conf->expensereport->dir_output.'/'.$original_file;
1911
	}
1912
	// Wrapping pour les images des stats propales
1913
	elseif ($modulepart == 'propalstats' && !empty($conf->propal->dir_temp))
1914
	{
1915
		if ($fuser->rights->propale->{$lire}) $accessallowed=1;
1916
		$original_file=$conf->propal->dir_temp.'/'.$original_file;
1917
	}
1918
	// Wrapping pour les images des stats commandes
1919
	elseif ($modulepart == 'orderstats' && !empty($conf->commande->dir_temp))
1920
	{
1921
		if ($fuser->rights->commande->{$lire}) $accessallowed=1;
1922
		$original_file=$conf->commande->dir_temp.'/'.$original_file;
1923
	}
1924
	elseif ($modulepart == 'orderstatssupplier' && !empty($conf->fournisseur->dir_output))
1925
	{
1926
		if ($fuser->rights->fournisseur->commande->{$lire}) $accessallowed=1;
1927
		$original_file=$conf->fournisseur->commande->dir_temp.'/'.$original_file;
1928
	}
1929
	// Wrapping pour les images des stats factures
1930
	elseif ($modulepart == 'billstats' && !empty($conf->facture->dir_temp))
1931
	{
1932
		if ($fuser->rights->facture->{$lire}) $accessallowed=1;
1933
		$original_file=$conf->facture->dir_temp.'/'.$original_file;
1934
	}
1935
	elseif ($modulepart == 'billstatssupplier' && !empty($conf->fournisseur->dir_output))
1936
	{
1937
		if ($fuser->rights->fournisseur->facture->{$lire}) $accessallowed=1;
1938
		$original_file=$conf->fournisseur->dir_output.'/facture/temp/'.$original_file;
1939
	}
1940
	// Wrapping pour les images des stats expeditions
1941
	elseif ($modulepart == 'expeditionstats' && !empty($conf->expedition->dir_temp))
1942
	{
1943
		if ($fuser->rights->expedition->{$lire}) $accessallowed=1;
1944
		$original_file=$conf->expedition->dir_temp.'/'.$original_file;
1945
	}
1946
	// Wrapping pour les images des stats expeditions
1947
	elseif ($modulepart == 'tripsexpensesstats' && !empty($conf->deplacement->dir_temp))
1948
	{
1949
		if ($fuser->rights->deplacement->{$lire}) $accessallowed=1;
1950
		$original_file=$conf->deplacement->dir_temp.'/'.$original_file;
1951
	}
1952
	// Wrapping pour les images des stats expeditions
1953
	elseif ($modulepart == 'memberstats' && !empty($conf->adherent->dir_temp))
1954
	{
1955
		if ($fuser->rights->adherent->{$lire}) $accessallowed=1;
1956
		$original_file=$conf->adherent->dir_temp.'/'.$original_file;
1957
	}
1958
	// Wrapping pour les images des stats produits
1959
	elseif (preg_match('/^productstats_/i',$modulepart) && !empty($conf->product->dir_temp))
1960
	{
1961
		if ($fuser->rights->produit->{$lire} || $fuser->rights->service->{$lire}) $accessallowed=1;
1962
		$original_file=(!empty($conf->product->multidir_temp[$entity])?$conf->product->multidir_temp[$entity]:$conf->service->multidir_temp[$entity]).'/'.$original_file;
1963
	}
1964
	// Wrapping for taxes
1965
	elseif ($modulepart == 'tax' && !empty($conf->tax->dir_output))
1966
	{
1967
		if ($fuser->rights->tax->charges->{$lire}) $accessallowed=1;
1968
		$original_file=$conf->tax->dir_output.'/'.$original_file;
1969
	}
1970
	// Wrapping for events
1971
	elseif ($modulepart == 'actions' && !empty($conf->agenda->dir_output))
1972
	{
1973
		if ($fuser->rights->agenda->myactions->{$read}) $accessallowed=1;
1974
		$original_file=$conf->agenda->dir_output.'/'.$original_file;
1975
	}
1976
	// Wrapping for categories
1977
	elseif ($modulepart == 'category' && !empty($conf->categorie->dir_output))
1978
	{
1979
		if ($fuser->rights->categorie->{$lire}) $accessallowed=1;
1980
		$original_file=$conf->categorie->multidir_output[$entity].'/'.$original_file;
1981
	}
1982
	// Wrapping pour les prelevements
1983
	elseif ($modulepart == 'prelevement' && !empty($conf->prelevement->dir_output))
1984
	{
1985
		if ($fuser->rights->prelevement->bons->{$lire} || preg_match('/^specimen/i',$original_file)) $accessallowed=1;
1986
		$original_file=$conf->prelevement->dir_output.'/'.$original_file;
1987
	}
1988
	// Wrapping pour les graph energie
1989
	elseif ($modulepart == 'graph_stock' && !empty($conf->stock->dir_temp))
1990
	{
1991
		$accessallowed=1;
1992
		$original_file=$conf->stock->dir_temp.'/'.$original_file;
1993
	}
1994
	// Wrapping pour les graph fournisseurs
1995
	elseif ($modulepart == 'graph_fourn' && !empty($conf->fournisseur->dir_temp))
1996
	{
1997
		$accessallowed=1;
1998
		$original_file=$conf->fournisseur->dir_temp.'/'.$original_file;
1999
	}
2000
	// Wrapping pour les graph des produits
2001
	elseif ($modulepart == 'graph_product' && !empty($conf->product->dir_temp))
2002
	{
2003
		$accessallowed=1;
2004
		$original_file=$conf->product->multidir_temp[$entity].'/'.$original_file;
2005
	}
2006
	// Wrapping pour les code barre
2007
	elseif ($modulepart == 'barcode')
2008
	{
2009
		$accessallowed=1;
2010
		// If viewimage is called for barcode, we try to output an image on the fly, with no build of file on disk.
2011
		//$original_file=$conf->barcode->dir_temp.'/'.$original_file;
2012
		$original_file='';
2013
	}
2014
	// Wrapping pour les icones de background des mailings
2015
	elseif ($modulepart == 'iconmailing' && !empty($conf->mailing->dir_temp))
2016
	{
2017
		$accessallowed=1;
2018
		$original_file=$conf->mailing->dir_temp.'/'.$original_file;
2019
	}
2020
	// Wrapping pour le scanner
2021
	elseif ($modulepart == 'scanner_user_temp' && !empty($conf->scanner->dir_temp))
2022
	{
2023
		$accessallowed=1;
2024
		$original_file=$conf->scanner->dir_temp.'/'.$fuser->id.'/'.$original_file;
2025
	}
2026
	// Wrapping pour les images fckeditor
2027
	elseif ($modulepart == 'fckeditor' && !empty($conf->fckeditor->dir_output))
2028
	{
2029
		$accessallowed=1;
2030
		$original_file=$conf->fckeditor->dir_output.'/'.$original_file;
2031
	}
2032
2033
	// Wrapping for users
2034
	else if ($modulepart == 'user' && !empty($conf->user->dir_output))
2035
	{
2036
        $canreaduser=(! empty($fuser->admin) || $fuser->rights->user->user->{$lire});
2037
        if ($fuser->id == (int) $refname) { $canreaduser=1; } // A user can always read its own card
2038
        if ($canreaduser || preg_match('/^specimen/i',$original_file))
2039
	    {
2040
	        $accessallowed=1;
2041
	    }
2042
	    $original_file=$conf->user->dir_output.'/'.$original_file;
2043
	}
2044
2045
	// Wrapping for third parties
2046
	else if (($modulepart == 'company' || $modulepart == 'societe') && !empty($conf->societe->dir_output))
2047
	{
2048
		if ($fuser->rights->societe->{$lire} || preg_match('/^specimen/i',$original_file))
2049
		{
2050
			$accessallowed=1;
2051
		}
2052
		$original_file=$conf->societe->multidir_output[$entity].'/'.$original_file;
2053
		$sqlprotectagainstexternals = "SELECT rowid as fk_soc FROM ".MAIN_DB_PREFIX."societe WHERE rowid='".$db->escape($refname)."' AND entity IN (".getEntity('societe').")";
2054
	}
2055
2056
	// Wrapping for contact
2057
	else if ($modulepart == 'contact' && !empty($conf->societe->dir_output))
2058
	{
2059
		if ($fuser->rights->societe->{$lire})
2060
		{
2061
			$accessallowed=1;
2062
		}
2063
		$original_file=$conf->societe->multidir_output[$entity].'/contact/'.$original_file;
2064
	}
2065
2066
	// Wrapping for invoices
2067
	else if (($modulepart == 'facture' || $modulepart == 'invoice') && !empty($conf->facture->dir_output))
2068
	{
2069
		if ($fuser->rights->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2070
		{
2071
			$accessallowed=1;
2072
		}
2073
		$original_file=$conf->facture->dir_output.'/'.$original_file;
2074
		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2075
	}
2076
	// Wrapping for mass actions
2077
	else if ($modulepart == 'massfilesarea_proposals' && !empty($conf->propal->dir_output))
2078
	{
2079
	    if ($fuser->rights->propal->{$lire} || preg_match('/^specimen/i',$original_file))
2080
	    {
2081
	        $accessallowed=1;
2082
	    }
2083
	    $original_file=$conf->propal->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2084
	}
2085
	else if ($modulepart == 'massfilesarea_orders')
2086
	{
2087
	    if ($fuser->rights->commande->{$lire} || preg_match('/^specimen/i',$original_file))
2088
	    {
2089
	        $accessallowed=1;
2090
	    }
2091
	    $original_file=$conf->commande->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2092
	}
2093
	else if ($modulepart == 'massfilesarea_invoices')
2094
	{
2095
	    if ($fuser->rights->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2096
	    {
2097
	        $accessallowed=1;
2098
	    }
2099
	    $original_file=$conf->facture->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2100
	}
2101
	else if ($modulepart == 'massfilesarea_expensereport')
2102
	{
2103
	    if ($fuser->rights->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2104
	    {
2105
	        $accessallowed=1;
2106
	    }
2107
	    $original_file=$conf->expensereport->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2108
	}
2109
	else if ($modulepart == 'massfilesarea_interventions')
2110
	{
2111
	    if ($fuser->rights->ficheinter->{$lire} || preg_match('/^specimen/i',$original_file))
2112
	    {
2113
	        $accessallowed=1;
2114
	    }
2115
	    $original_file=$conf->ficheinter->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2116
	}
2117
	else if ($modulepart == 'massfilesarea_supplier_proposal' && !empty($conf->propal->dir_output))
2118
	{
2119
	    if ($fuser->rights->supplier_proposal->{$lire} || preg_match('/^specimen/i',$original_file))
2120
	    {
2121
	        $accessallowed=1;
2122
	    }
2123
	    $original_file=$conf->supplier_proposal->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2124
	}
2125
	else if ($modulepart == 'massfilesarea_supplier_order')
2126
	{
2127
	    if ($fuser->rights->fournisseur->commande->{$lire} || preg_match('/^specimen/i',$original_file))
2128
	    {
2129
	        $accessallowed=1;
2130
	    }
2131
	    $original_file=$conf->fournisseur->commande->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2132
	}
2133
	else if ($modulepart == 'massfilesarea_supplier_invoice')
2134
	{
2135
	    if ($fuser->rights->fournisseur->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2136
	    {
2137
	        $accessallowed=1;
2138
	    }
2139
	    $original_file=$conf->fournisseur->facture->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
2140
	}
2141
2142
	// Wrapping for interventions
2143
	else if (($modulepart == 'fichinter' || $modulepart == 'ficheinter') && !empty($conf->ficheinter->dir_output))
2144
	{
2145
		if ($fuser->rights->ficheinter->{$lire} || preg_match('/^specimen/i',$original_file))
2146
		{
2147
			$accessallowed=1;
2148
		}
2149
		$original_file=$conf->ficheinter->dir_output.'/'.$original_file;
2150
		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2151
	}
2152
2153
	// Wrapping pour les deplacements et notes de frais
2154
	else if ($modulepart == 'deplacement' && !empty($conf->deplacement->dir_output))
2155
	{
2156
		if ($fuser->rights->deplacement->{$lire} || preg_match('/^specimen/i',$original_file))
2157
		{
2158
			$accessallowed=1;
2159
		}
2160
		$original_file=$conf->deplacement->dir_output.'/'.$original_file;
2161
		//$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2162
	}
2163
	// Wrapping pour les propales
2164
	else if ($modulepart == 'propal' && !empty($conf->propal->dir_output))
2165
	{
2166
		if ($fuser->rights->propale->{$lire} || preg_match('/^specimen/i',$original_file))
2167
		{
2168
			$accessallowed=1;
2169
		}
2170
2171
		$original_file=$conf->propal->dir_output.'/'.$original_file;
2172
		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."propal WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2173
	}
2174
2175
	// Wrapping pour les commandes
2176
	else if (($modulepart == 'commande' || $modulepart == 'order') && !empty($conf->commande->dir_output))
2177
	{
2178
		if ($fuser->rights->commande->{$lire} || preg_match('/^specimen/i',$original_file))
2179
		{
2180
			$accessallowed=1;
2181
		}
2182
		$original_file=$conf->commande->dir_output.'/'.$original_file;
2183
		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2184
	}
2185
2186
	// Wrapping pour les projets
2187
	else if ($modulepart == 'project' && !empty($conf->projet->dir_output))
2188
	{
2189
		if ($fuser->rights->projet->{$lire} || preg_match('/^specimen/i',$original_file))
2190
		{
2191
			$accessallowed=1;
2192
		}
2193
		$original_file=$conf->projet->dir_output.'/'.$original_file;
2194
		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project').")";
2195
	}
2196
	else if ($modulepart == 'project_task' && !empty($conf->projet->dir_output))
2197
	{
2198
		if ($fuser->rights->projet->{$lire} || preg_match('/^specimen/i',$original_file))
2199
		{
2200
			$accessallowed=1;
2201
		}
2202
		$original_file=$conf->projet->dir_output.'/'.$original_file;
2203
		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project').")";
2204
	}
2205
2206
	// Wrapping pour les commandes fournisseurs
2207
	else if (($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') && !empty($conf->fournisseur->commande->dir_output))
2208
	{
2209
		if ($fuser->rights->fournisseur->commande->{$lire} || preg_match('/^specimen/i',$original_file))
2210
		{
2211
			$accessallowed=1;
2212
		}
2213
		$original_file=$conf->fournisseur->commande->dir_output.'/'.$original_file;
2214
		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande_fournisseur WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2215
	}
2216
2217
	// Wrapping pour les factures fournisseurs
2218
	else if (($modulepart == 'facture_fournisseur' || $modulepart == 'invoice_supplier') && !empty($conf->fournisseur->facture->dir_output))
2219
	{
2220
		if ($fuser->rights->fournisseur->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2221
		{
2222
			$accessallowed=1;
2223
		}
2224
		$original_file=$conf->fournisseur->facture->dir_output.'/'.$original_file;
2225
		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture_fourn WHERE facnumber='".$db->escape($refname)."' AND entity=".$conf->entity;
2226
	}
2227
	// Wrapping pour les rapport de paiements
2228
	else if ($modulepart == 'supplier_payment')
2229
	{
2230
		if ($fuser->rights->fournisseur->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2231
		{
2232
			$accessallowed=1;
2233
		}
2234
		$original_file=$conf->fournisseur->payment->dir_output.'/'.$original_file;
2235
		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."paiementfournisseur WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2236
	}
2237
2238
	// Wrapping pour les rapport de paiements
2239
	else if ($modulepart == 'facture_paiement' && !empty($conf->facture->dir_output))
2240
	{
2241
		if ($fuser->rights->facture->{$lire} || preg_match('/^specimen/i',$original_file))
2242
		{
2243
			$accessallowed=1;
2244
		}
2245
		if ($fuser->societe_id > 0) $original_file=$conf->facture->dir_output.'/payments/private/'.$fuser->id.'/'.$original_file;
2246
		else $original_file=$conf->facture->dir_output.'/payments/'.$original_file;
2247
	}
2248
2249
	// Wrapping for accounting exports
2250
	else if ($modulepart == 'export_compta' && !empty($conf->accounting->dir_output))
2251
	{
2252
		if ($fuser->rights->accounting->bind->write || preg_match('/^specimen/i',$original_file))
2253
		{
2254
			$accessallowed=1;
2255
		}
2256
		$original_file=$conf->accounting->dir_output.'/'.$original_file;
2257
	}
2258
2259
	// Wrapping pour les expedition
2260
	else if ($modulepart == 'expedition' && !empty($conf->expedition->dir_output))
2261
	{
2262
		if ($fuser->rights->expedition->{$lire} || preg_match('/^specimen/i',$original_file))
2263
		{
2264
			$accessallowed=1;
2265
		}
2266
		$original_file=$conf->expedition->dir_output."/sending/".$original_file;
2267
	}
2268
	// Wrapping pour les bons de livraison
2269
	else if ($modulepart == 'livraison' && !empty($conf->expedition->dir_output))
2270
	{
2271
		if ($fuser->rights->expedition->livraison->{$lire} || preg_match('/^specimen/i',$original_file))
2272
		{
2273
			$accessallowed=1;
2274
		}
2275
		$original_file=$conf->expedition->dir_output."/receipt/".$original_file;
2276
	}
2277
2278
	// Wrapping pour les actions
2279
	else if ($modulepart == 'actions' && !empty($conf->agenda->dir_output))
2280
	{
2281
		if ($fuser->rights->agenda->myactions->{$read} || preg_match('/^specimen/i',$original_file))
2282
		{
2283
			$accessallowed=1;
2284
		}
2285
		$original_file=$conf->agenda->dir_output.'/'.$original_file;
2286
	}
2287
2288
	// Wrapping pour les actions
2289
	else if ($modulepart == 'actionsreport' && !empty($conf->agenda->dir_temp))
2290
	{
2291
		if ($fuser->rights->agenda->allactions->{$read} || preg_match('/^specimen/i',$original_file))
2292
		{
2293
			$accessallowed=1;
2294
		}
2295
		$original_file = $conf->agenda->dir_temp."/".$original_file;
2296
	}
2297
2298
	// Wrapping pour les produits et services
2299
	else if ($modulepart == 'product' || $modulepart == 'produit' || $modulepart == 'service' || $modulepart == 'produit|service')
2300
	{
2301
		if (($fuser->rights->produit->{$lire} || $fuser->rights->service->{$lire}) || preg_match('/^specimen/i',$original_file))
2302
		{
2303
			$accessallowed=1;
2304
		}
2305
		if (! empty($conf->product->enabled)) $original_file=$conf->product->multidir_output[$entity].'/'.$original_file;
2306
		elseif (! empty($conf->service->enabled)) $original_file=$conf->service->multidir_output[$entity].'/'.$original_file;
2307
	}
2308
2309
	// Wrapping pour les contrats
2310
	else if ($modulepart == 'contract' && !empty($conf->contrat->dir_output))
2311
	{
2312
		if ($fuser->rights->contrat->{$lire} || preg_match('/^specimen/i',$original_file))
2313
		{
2314
			$accessallowed=1;
2315
		}
2316
		$original_file=$conf->contrat->dir_output.'/'.$original_file;
2317
		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."contrat WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('contract').")";
2318
	}
2319
2320
	// Wrapping pour les dons
2321
	else if ($modulepart == 'donation' && !empty($conf->don->dir_output))
2322
	{
2323
		if ($fuser->rights->don->{$lire} || preg_match('/^specimen/i',$original_file))
2324
		{
2325
			$accessallowed=1;
2326
		}
2327
		$original_file=$conf->don->dir_output.'/'.$original_file;
2328
	}
2329
2330
	// Wrapping pour les dons
2331
	else if ($modulepart == 'dolresource' && !empty($conf->resource->dir_output))
2332
	{
2333
		if ($fuser->rights->resource->{$read} || preg_match('/^specimen/i',$original_file))
2334
		{
2335
			$accessallowed=1;
2336
		}
2337
		$original_file=$conf->resource->dir_output.'/'.$original_file;
2338
	}
2339
2340
	// Wrapping pour les remises de cheques
2341
	else if ($modulepart == 'remisecheque' && !empty($conf->banque->dir_output))
2342
	{
2343
		if ($fuser->rights->banque->{$lire} || preg_match('/^specimen/i',$original_file))
2344
		{
2345
			$accessallowed=1;
2346
		}
2347
2348
		$original_file=$conf->bank->dir_output.'/checkdeposits/'.$original_file;		// original_file should contains relative path so include the get_exdir result
2349
	}
2350
2351
	// Wrapping for bank
2352
	else if ($modulepart == 'bank' && !empty($conf->bank->dir_output))
2353
	{
2354
		if ($fuser->rights->banque->{$lire})
2355
		{
2356
			$accessallowed=1;
2357
		}
2358
		$original_file=$conf->bank->dir_output.'/'.$original_file;
2359
	}
2360
2361
	// Wrapping for export module
2362
	else if ($modulepart == 'export' && !empty($conf->export->dir_temp))
2363
	{
2364
		// Aucun test necessaire car on force le rep de download sur
2365
		// le rep export qui est propre a l'utilisateur
2366
		$accessallowed=1;
2367
		$original_file=$conf->export->dir_temp.'/'.$fuser->id.'/'.$original_file;
2368
	}
2369
2370
	// Wrapping for import module
2371
	else if ($modulepart == 'import' && !empty($conf->import->dir_temp))
2372
	{
2373
		$accessallowed=1;
2374
		$original_file=$conf->import->dir_temp.'/'.$original_file;
2375
	}
2376
2377
	// Wrapping pour l'editeur wysiwyg
2378
	else if ($modulepart == 'editor' && !empty($conf->fckeditor->dir_output))
2379
	{
2380
		$accessallowed=1;
2381
		$original_file=$conf->fckeditor->dir_output.'/'.$original_file;
2382
	}
2383
2384
	// Wrapping for backups
2385
	else if ($modulepart == 'systemtools' && !empty($conf->admin->dir_output))
2386
	{
2387
		if ($fuser->admin) $accessallowed=1;
2388
		$original_file=$conf->admin->dir_output.'/'.$original_file;
2389
	}
2390
2391
	// Wrapping for upload file test
2392
	else if ($modulepart == 'admin_temp' && !empty($conf->admin->dir_temp))
2393
	{
2394
		if ($fuser->admin) $accessallowed=1;
2395
		$original_file=$conf->admin->dir_temp.'/'.$original_file;
2396
	}
2397
2398
	// Wrapping pour BitTorrent
2399
	else if ($modulepart == 'bittorrent' && !empty($conf->bittorrent->dir_output))
2400
	{
2401
		$accessallowed=1;
2402
		$dir='files';
2403
		if (dol_mimetype($original_file) == 'application/x-bittorrent') $dir='torrents';
2404
		$original_file=$conf->bittorrent->dir_output.'/'.$dir.'/'.$original_file;
2405
	}
2406
2407
	// Wrapping pour Foundation module
2408
	else if ($modulepart == 'member' && !empty($conf->adherent->dir_output))
2409
	{
2410
		if ($fuser->rights->adherent->{$lire} || preg_match('/^specimen/i',$original_file))
2411
		{
2412
			$accessallowed=1;
2413
		}
2414
		$original_file=$conf->adherent->dir_output.'/'.$original_file;
2415
	}
2416
2417
	// Wrapping for Scanner
2418
	else if ($modulepart == 'scanner_user_temp' && !empty($conf->scanner->dir_temp))
2419
	{
2420
		$accessallowed=1;
2421
		$original_file=$conf->scanner->dir_temp.'/'.$fuser->id.'/'.$original_file;
2422
	}
2423
2424
    // GENERIC Wrapping
2425
    // If modulepart=module_user_temp	Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/temp/iduser
2426
    // If modulepart=module_temp		Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/temp
2427
    // If modulepart=module_user		Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart/iduser
2428
    // If modulepart=module				Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart
2429
    else
2430
	{
2431
	    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.
2432
	    if ($fuser->admin) $accessallowed=1;    // If user is admin
2433
2434
		// Define $accessallowed
2435
		if (preg_match('/^([a-z]+)_user_temp$/i',$modulepart,$reg))
2436
		{
2437
			if (empty($conf->{$reg[1]}->dir_temp))	// modulepart not supported
2438
			{
2439
				dol_print_error('','Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')');
2440
				exit;
2441
			}
2442
		    if ($fuser->rights->{$reg[1]}->{$lire} || $fuser->rights->{$reg[1]}->{$read} || ($fuser->rights->{$reg[1]}->{$download})) $accessallowed=1;
2443
			$original_file=$conf->{$reg[1]}->dir_temp.'/'.$fuser->id.'/'.$original_file;
2444
		}
2445
		else if (preg_match('/^([a-z]+)_temp$/i',$modulepart,$reg))
2446
		{
2447
			if (empty($conf->{$reg[1]}->dir_temp))	// modulepart not supported
2448
			{
2449
				dol_print_error('','Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')');
2450
				exit;
2451
			}
2452
		    if ($fuser->rights->{$reg[1]}->{$lire} || $fuser->rights->{$reg[1]}->{$read} || ($fuser->rights->{$reg[1]}->{$download})) $accessallowed=1;
2453
			$original_file=$conf->{$reg[1]}->dir_temp.'/'.$original_file;
2454
		}
2455
		else if (preg_match('/^([a-z]+)_user$/i',$modulepart,$reg))
2456
		{
2457
			if (empty($conf->{$reg[1]}->dir_output))	// modulepart not supported
2458
			{
2459
				dol_print_error('','Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')');
2460
				exit;
2461
			}
2462
		    if ($fuser->rights->{$reg[1]}->{$lire} || $fuser->rights->{$reg[1]}->{$read} || ($fuser->rights->{$reg[1]}->{$download})) $accessallowed=1;
2463
			$original_file=$conf->{$reg[1]}->dir_output.'/'.$fuser->id.'/'.$original_file;
2464
		}
2465
		else
2466
		{
2467
			if (empty($conf->$modulepart->dir_output))	// modulepart not supported
2468
			{
2469
				dol_print_error('','Error call dol_check_secure_access_document with not supported value for modulepart parameter ('.$modulepart.')');
2470
				exit;
2471
			}
2472
2473
			$perm=GETPOST('perm');
2474
			$subperm=GETPOST('subperm');
2475
			if ($perm || $subperm)
2476
			{
2477
				if (($perm && ! $subperm && $fuser->rights->$modulepart->$perm) || ($perm && $subperm && $fuser->rights->$modulepart->$perm->$subperm)) $accessallowed=1;
2478
				$original_file=$conf->$modulepart->dir_output.'/'.$original_file;
2479
			}
2480
			else
2481
			{
2482
				if ($fuser->rights->$modulepart->{$lire} || $fuser->rights->$modulepart->{$read}) $accessallowed=1;
2483
				$original_file=$conf->$modulepart->dir_output.'/'.$original_file;
2484
			}
2485
		}
2486
2487
		// For modules who wants to manage different levels of permissions for documents
2488
		$subPermCategoryConstName = strtoupper($modulepart).'_SUBPERMCATEGORY_FOR_DOCUMENTS';
2489
		if (! empty($conf->global->$subPermCategoryConstName))
2490
		{
2491
			$subPermCategory = $conf->global->$subPermCategoryConstName;
2492
			if (! empty($subPermCategory) && (($fuser->rights->$modulepart->$subPermCategory->{$lire}) || ($fuser->rights->$modulepart->$subPermCategory->{$read}) || ($fuser->rights->$modulepart->$subPermCategory->{$download})))
2493
			{
2494
				$accessallowed=1;
2495
			}
2496
		}
2497
2498
		// Define $sqlprotectagainstexternals for modules who want to protect access using a SQL query.
2499
		$sqlProtectConstName = strtoupper($modulepart).'_SQLPROTECTAGAINSTEXTERNALS_FOR_DOCUMENTS';
2500
		if (! empty($conf->global->$sqlProtectConstName))	// If module want to define its own $sqlprotectagainstexternals
2501
		{
2502
			// Example: mymodule__SQLPROTECTAGAINSTEXTERNALS_FOR_DOCUMENTS = "SELECT fk_soc FROM ".MAIN_DB_PREFIX.$modulepart." WHERE ref='".$db->escape($refname)."' AND entity=".$conf->entity;
2503
			eval('$sqlprotectagainstexternals = "'.$conf->global->$sqlProtectConstName.'";');
0 ignored issues
show
Coding Style introduced by
The function dol_check_secure_access_document() contains an eval expression.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
2504
		}
2505
	}
2506
2507
	$ret = array(
2508
		'accessallowed' => $accessallowed,
2509
		'sqlprotectagainstexternals'=>$sqlprotectagainstexternals,
2510
		'original_file'=>$original_file
2511
	);
2512
2513
	return $ret;
2514
}
2515
2516
/**
2517
 * Store object in file.
2518
 *
2519
 * @param string $directory Directory of cache
2520
 * @param string $filename Name of filecache
2521
 * @param mixed $object Object to store in cachefile
2522
 * @return void
2523
 */
2524
function dol_filecache($directory, $filename, $object)
2525
{
2526
    if (! dol_is_dir($directory)) dol_mkdir($directory);
2527
    $cachefile = $directory . $filename;
2528
    file_put_contents($cachefile, serialize($object), LOCK_EX);
2529
    @chmod($cachefile, 0644);
2530
}
2531
2532
/**
2533
 * Test if Refresh needed.
2534
 *
2535
 * @param string $directory Directory of cache
2536
 * @param string $filename Name of filecache
2537
 * @param int $cachetime Cachetime delay
2538
 * @return boolean 0 no refresh 1 if refresh needed
2539
 */
2540
function dol_cache_refresh($directory, $filename, $cachetime)
2541
{
2542
    $now = dol_now();
2543
    $cachefile = $directory . $filename;
2544
    $refresh = !file_exists($cachefile) || ($now-$cachetime) > dol_filemtime($cachefile);
2545
    return $refresh;
2546
}
2547
2548
/**
2549
 * Read object from cachefile.
2550
 *
2551
 * @param string $directory Directory of cache
2552
 * @param string $filename Name of filecache
2553
 * @return mixed Unserialise from file
2554
 */
2555
function dol_readcachefile($directory, $filename)
2556
{
2557
    $cachefile = $directory . $filename;
2558
    $object = unserialize(file_get_contents($cachefile));
2559
    return $object;
2560
}
2561