1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Function expands all relative parts of supplied path string thus
19 * removing things like ../../ or ./../.
20 *
21 * @param string $path
22 * @param string $dirsep Character that represents directory separator should be
23 *                       specified here. Default is DIRECTORY_SEPARATOR.
24 * @return string
25 */
26function fullPath($path,$dirsep=DIRECTORY_SEPARATOR) {
27    $token = '$IMS-CC-FILEBASE$';
28    $path = str_replace($token,'',$path);
29    if ( is_string($path) && ($path != '') ) {
30        $sep   = $dirsep;
31        $dotDir= '.';
32        $upDir = '..';
33        $length= strlen($path);
34        $rtemp= trim($path);
35        $start = strrpos($path, $sep);
36        $canContinue = ($start !== false);
37        $result= $canContinue ? '': $path;
38        $rcount=0;
39        while ($canContinue) {
40            $dirPart = ($start !== false) ? substr($rtemp,$start+1,$length-$start) : $rtemp;
41            $canContinue = ($dirPart !== false);
42            if ($canContinue) {
43                if ($dirPart != $dotDir) {
44                    if ($dirPart == $upDir) {
45                        $rcount++;
46                    } else {
47                        if ($rcount > 0) {
48                            $rcount--;
49                        } else {
50                            $result = ($result == '') ? $dirPart : $dirPart.$sep.$result;
51                        }
52                    }
53                }
54                $rtemp = substr($path,0,$start);
55                $start = strrpos($rtemp, $sep);
56                $canContinue = (($start !== false) || (strlen($rtemp) > 0));
57            }
58        } //end while
59    }
60    return $result;
61}
62
63
64
65/**
66 * Function strips url part from css link
67 *
68 * @param string $path
69 * @param string $rootDir
70 * @return string
71 */
72function stripUrl($path, $rootDir='') {
73    $result = $path;
74    if ( is_string($path) && ($path != '') ) {
75        $start=strpos($path,'(')+1;
76        $length=strpos($path,')')-$start;
77        $rut = $rootDir.substr($path,$start,$length);
78        $result=fullPath($rut,'/');
79    }
80    return $result;
81}
82
83/**
84 * Converts direcotry separator in given path to / to validate in CC
85 * Value is passed byref hence variable itself is changed
86 *
87 * @param string $path
88 */
89function toNativePath(&$path) {
90    for ($count = 0 ; $count < strlen($path); ++$count) {
91        $chr = $path[$count];
92        if (($chr == '\\') || ($chr == '/')) {
93            $path[$count] = '/';
94        }
95    }
96}
97
98
99/**
100 * Converts direcotry separator in given path to the one on the server platform
101 * Value is passed byref hence variable itself is changed
102 *
103 * @param string $path
104 */
105function toNativePath2(&$path) {
106    for ($count = 0 ; $count < strlen($path); ++$count) {
107        $chr = $path[$count];
108        if (($chr == '\\') || ($chr == '/')) {
109            $path[$count] = DIRECTORY_SEPARATOR;
110        }
111    }
112}
113
114/**
115 * Converts \ Directory separator to the / more suitable for URL
116 *
117 * @param string $path
118 */
119function toUrlPath(&$path) {
120    for ($count = 0 ; $count < strlen($path); ++$count) {
121        $chr = $path[$count];
122        if (($chr == '\\')) {
123            $path[$count] = '/';
124        }
125    }
126}
127
128/**
129 * Returns relative path from two directories with full path
130 *
131 * @param string $path1
132 * @param string $path2
133 * @return string
134 */
135function pathDiff($path1, $path2) {
136    toUrlPath($path1);
137    toUrlPath($path2);
138    $result = "";
139    $bl2 = strlen($path2);
140    $a = strpos($path1,$path2);
141    if ($a !== false) {
142        $result = trim(substr($path1,$bl2+$a),'/');
143    }
144    return $result;
145}
146
147 /**
148  * Copy a file, or recursively copy a folder and its contents
149  *
150  * @author      Aidan Lister <aidan@php.net>
151  * @version     1.0.1
152  * @link        http://aidanlister.com/repos/v/function.copyr.php
153  * @param       string   $source    Source path
154  * @param       string   $dest      Destination path
155  * @return      bool     Returns TRUE on success, FALSE on failure
156  */
157 function copyr($source, $dest)
158 {
159     global $CFG;
160     // Simple copy for a file
161     if (is_file($source)) {
162         return copy($source, $dest);
163     }
164
165     // Make destination directory
166     if (!is_dir($dest)) {
167         mkdir($dest, $CFG->directorypermissions, true);
168     }
169
170     // Loop through the folder
171     $dir = dir($source);
172     while (false !== $entry = $dir->read()) {
173         // Skip pointers
174         if ($entry == '.' || $entry == '..') {
175             continue;
176         }
177
178         // Deep copy directories
179         if ($dest !== "$source/$entry") {
180             copyr("$source/$entry", "$dest/$entry");
181         }
182     }
183
184     // Clean up
185     $dir->close();
186     return true;
187 }
188
189/**
190 * Function returns array with directories contained in folder (only first level)
191 *
192 * @param  string $rootDir  directory to look into
193 * @param  string $contains which string to look for
194 * @param  array  $excludeitems array of names to be excluded
195 * @param  bool   $startswith should the $contains value be searched only from
196 *                             beginning
197 * @return array  Returns array of sub-directories. In case $rootDir path is
198 *                invalid it returns FALSE.
199 */
200function getDirectories($rootDir, $contains, $excludeitems = null, $startswith = true) {
201    $result = is_dir($rootDir);
202    if ($result) {
203        $dirlist = dir($rootDir);
204        $entry = null;
205        $result = array();
206        while(false !== ($entry = $dirlist->read())) {
207            $currdir = $rootDir.$entry;
208            if (is_dir($currdir)) {
209                $bret = strpos($entry,$contains);
210                if (($bret !== false)) {
211                    if (($startswith && ($bret == 0)) || !$startswith) {
212                        if (!( is_array($excludeitems) && in_array($entry,$excludeitems) )) {
213                            $result[] = $entry;
214                        }
215                    }
216                }
217            }
218        }
219    }
220    return $result;
221}
222
223function getFilesOnly($rootDir, $contains, $excludeitems = null, $startswith = true,$extension=null) {
224    $result = is_dir($rootDir);
225    if ($result) {
226        $filelist = dir($rootDir);
227        $entry = null;
228        $result = array();
229        while(false !== ($entry = $filelist->read())) {
230            $curritem = $rootDir.$entry;
231            $pinfo = pathinfo($entry);
232            $ext = array_key_exists('extension',$pinfo) ? $pinfo['extension'] : null;
233            if (is_file($curritem) && (is_null($extension) || ($ext == $extension) )) {
234                $bret = strpos($entry,$contains);
235                if (($bret !== false)) {
236                    if (($startswith && ($bret == 0)) || !$startswith) {
237                        if (!( is_array($excludeitems) && in_array($entry,$excludeitems) )) {
238                            $result[] = $entry;
239                        }
240                    }
241                }
242            }
243        }
244    }
245    natcasesort($result);
246    return $result;
247}
248
249
250
251/**
252 * Search an identifier in array
253 *
254 * @param array $array
255 * @param string $name
256 *
257 */
258
259function search_ident_by_name($array,$name){
260    if (empty($array)){
261        throw new Exception('The array given is null');
262    }
263    $ident = null;
264    foreach ($array as $k => $v){
265        ($k);
266        if ($v[1] == $name){
267            $ident = $v[0];
268            break;
269        }
270    }
271    return $ident;
272}
273
274
275
276
277
278/**
279 * Function returns files recursivly with appeneded relative path
280 *
281 * @param string $startDir
282 * @param string $rootDir
283 * @param array $excludedirs
284 * @param array $excludefileext
285 * @return array
286 */
287function getRawFiles($startDir, &$fhandle, $rootDir='', $excludedirs = null, $excludefileext = null) {
288    $result = is_dir($startDir);
289    if ($result) {
290        $dirlist = dir($startDir);
291        $entry = null;
292        while(false !== ($entry = $dirlist->read())) {
293            $curritem = $startDir.$entry;
294            if (($entry=='.') || ($entry =='..')) {
295                continue;
296            }
297            if (is_dir($curritem)) {
298                if (!( is_array($excludedirs) && in_array($entry,$excludedirs) )) {
299                    getRawFiles($startDir.$entry."/",$fhandle,$rootDir.$entry."/",$excludedirs,$excludefileext);
300                }
301                continue;
302            }
303            if (is_file($curritem)){
304                $pinfo = pathinfo($entry);
305                $ext = array_key_exists('extension',$pinfo) ? $pinfo['extension'] : '';
306                if (!is_array($excludefileext) ||
307                (is_array($excludefileext) && !in_array($ext,$excludefileext))) {
308                    fwrite($fhandle,$rootDir.$entry."\n");
309                }
310            }
311        }
312    }
313    return $result;
314}
315
316
317function getRawFiles2($startDir,&$arr, $rootDir='', $excludedirs = null, $excludefileext = null) {
318
319    $result = is_dir($startDir);
320    if ($result) {
321        $dirlist = dir($startDir);
322        $entry = null;
323        while(false !== ($entry = $dirlist->read())) {
324            $curritem = $startDir.$entry;
325            if (($entry=='.') || ($entry =='..')) {
326                continue;
327            }
328            if (is_dir($curritem)) {
329                if (!( is_array($excludedirs) && in_array($entry,$excludedirs) )) {
330                    getRawFiles2($startDir.$entry."/",$arr,$rootDir.$entry."/",$excludedirs,$excludefileext);
331                }
332                continue;
333            }
334            if (is_file($curritem)){
335                $pinfo = pathinfo($entry);
336                $ext = array_key_exists('extension',$pinfo) ? $pinfo['extension'] : '';
337                if (!is_array($excludefileext) ||
338                (is_array($excludefileext) && !in_array($ext,$excludefileext))) {
339                    array_push($arr,$rootDir.$entry);
340                   // fwrite($fhandle,$rootDir.$entry."\n");
341                }
342            }
343        }
344    }
345    return $result;
346}
347
348
349function GetFiles($startDir, $outfile, $rootDir='', $excludedirs = null, $excludefileext = null) {
350    $fh = @fopen($outfile,"w+");
351    if ($fh !== FALSE) {
352        getRawFiles($startDir,$fh,$rootDir,$excludedirs,$excludefileext);
353        @fclose($fh);
354        @chmod($outfile,0777);
355    }
356}
357
358
359/**
360 * Function to get an array with all files in a directory and subdirectories
361 *
362 * @param string $startDir
363 * @param string $rootDir
364 * @param string $excludedirs
365 * @param string $excludefileext
366 * @return array
367 */
368
369function GetFilesArray($startDir, $rootDir='', $excludedirs = null, $excludefileext = null) {
370    $arr = array();
371    getRawFiles2($startDir,$arr,$rootDir,$excludedirs,$excludefileext);
372    return $arr;
373}
374
375
376
377/**
378 * Function returns array with directories contained in folder (only first level)
379 * simmilar to getDirectories but returned items are naturally sorted.
380 *
381 * @param string $rootDir
382 * @param string $contains
383 * @param array $excludeitems
384 * @param bool $startswith
385 * @return array
386 */
387function getCourseDirs ($rootDir, $contains, $excludeitems=null, $startswith=true) {
388    $result = getDirectories($rootDir,$contains,$excludeitems,$startswith);
389    if ($result !== false) {
390        natcasesort($result);
391        $result = array_values($result);
392    }
393    return $result;
394}
395
396
397/**
398 * Delete a directory recursive with files inside
399 *
400 * @param string $dirname
401 * @return bool
402 */
403function rmdirr($dirname)
404{
405    if (!file_exists($dirname)) {
406        return false;
407    }
408    if (is_file($dirname) || is_link($dirname)) {
409        return unlink($dirname);
410    }
411    $dir = dir($dirname);
412    while (false !== $entry = $dir->read()) {
413        if ($entry == '.' || $entry == '..') {
414            continue;
415        }
416        rmdirr($dirname . DIRECTORY_SEPARATOR . $entry);
417    }
418    $dir->close();
419    return rmdir($dirname);
420}
421