remove old readme
[atutor.git] / mods / _core / file_manager / filemanager.inc.php
1 <?php
2 /****************************************************************/
3 /* ATutor                                                                                                               */
4 /****************************************************************/
5 /* Copyright (c) 2002-2010                                      */
6 /* Inclusive Design Institute                                   */
7 /* http://atutor.ca                                                                                             */
8 /*                                                              */
9 /* This program is free software. You can redistribute it and/or*/
10 /* modify it under the terms of the GNU General Public License  */
11 /* as published by the Free Software Foundation.                                */
12 /****************************************************************/
13 if (!defined('AT_INCLUDE_PATH')) { exit; }
14
15 /**
16 * Allows the copying of entire directories.
17 * @access  public
18 * @param   string $source               the source directory
19 * @param   string $dest                 the destination directory
20 * @return  boolean                              whether the copy was successful or not
21 * @link    http://www.php.net/copy
22 * @author  www at w8c dot com
23 */
24
25 function copys($source,$dest)
26 {
27         if (!is_dir($source)) {
28                 return false;
29         }
30         if (!is_dir($dest))     {
31                 mkdir($dest);
32         }
33         
34         $h=@dir($source);
35         while (@($entry=$h->read()) !== false) {
36                 if (($entry == '.') || ($entry == '..')) {
37                         continue;
38                 }
39
40                 if (is_dir("$source/$entry") && $dest!=="$source/$entry") {
41                         copys("$source/$entry", "$dest/$entry");
42                 } else {
43                         @copy("$source/$entry", "$dest/$entry");
44                 }
45         }
46         $h->close();
47         return true;
48
49
50 /**
51 * Enables deletion of directory if not empty
52 * @access  public
53 * @param   string $dir          the directory to delete
54 * @return  boolean                      whether the deletion was successful
55 * @author  Joel Kronenberg
56 */
57 function clr_dir($dir) {
58         if(!$opendir = @opendir($dir)) {
59                 return false;
60         }
61         
62         while(($readdir=readdir($opendir)) !== false) {
63                 if (($readdir !== '..') && ($readdir !== '.')) {
64                         $readdir = trim($readdir);
65
66                         clearstatcache(); /* especially needed for Windows machines: */
67
68                         if (is_file($dir.'/'.$readdir)) {
69                                 if(!@unlink($dir.'/'.$readdir)) {
70                                         return false;
71                                 }
72                         } else if (is_dir($dir.'/'.$readdir)) {
73                                 /* calls itself to clear subdirectories */
74                                 if(!clr_dir($dir.'/'.$readdir)) {
75                                         return false;
76                                 }
77                         }
78                 }
79         } /* end while */
80
81         @closedir($opendir);
82         
83         if(!@rmdir($dir)) {
84                 return false;
85         }
86         return true;
87 }
88
89 /**
90 * Calculate the size in Bytes of a directory recursively.
91 * @access  public
92 * @param   string $dir          the directory to traverse
93 * @return  int                          the total size in Bytes of the directory
94 * @author  Joel Kronenberg
95 */
96 function dirsize($dir) {
97         if (is_dir($dir)) {
98                 $dh = @opendir($dir);
99         }
100         if (!$dh) {
101                 return -1;
102         }
103         $size = 0;
104         while (($file = readdir($dh)) !== false) {
105     
106                 if ($file != '.' && $file != '..') {
107                         $path = $dir.$file;
108                         if (is_dir($path)) {
109                                 $size += dirsize($path.'/');
110                         } elseif (is_file($path)) {
111                                 $size += filesize($path);
112                         }
113                 }
114                  
115         }
116         closedir($dh);
117         //       echo 'something';
118     //  exit;
119         return $size;
120  // exit;
121 }
122
123 /**
124 * This function gets used by PclZip when extracting a zip archive.
125 * @access  private
126 * @return  int                          whether or not to include the file
127 * @author  Joel Kronenberg
128 */
129         function preExtractCallBack($p_event, &$p_header) {
130                 global $translated_file_names;
131
132                 if ($p_header['folder'] == 1) {
133                         return 1;
134                 }
135
136                 if ($translated_file_names[$p_header['index']] == '') {
137                         return 0;
138                 }
139
140                 if ($translated_file_names[$p_header['index']]) {
141                         $p_header['filename'] = substr($p_header['filename'], 0, -strlen($p_header['stored_filename']));
142                         $p_header['filename'] .= $translated_file_names[$p_header['index']];
143                 }
144                 return 1;
145         }
146
147 /**
148 * This function gets used by PclZip when creating a zip archive.
149 * @access  private
150 * @return  int                          whether or not to include the file
151 * @author  Joel Kronenberg
152 */
153         function preImportCallBack($p_event, &$p_header) {
154                 global $IllegalExtentions;
155
156                 if ($p_header['folder'] == 1) {
157                         return 1;
158                 }
159
160                 $path_parts = pathinfo($p_header['filename']);
161                 $ext = $path_parts['extension'];
162
163                 if (in_array($ext, $IllegalExtentions)) {
164                         return 0;
165                 }
166
167                 return 1;
168         }
169
170
171 /* prints the <options> out of $cats which is an array of course categories where */
172 /* $cats[parent_cat_id][] = $row */
173 function print_course_cats($parent_cat_id, &$cats, $cat_row, $depth=0) {
174         $my_cats = $cats[$parent_cat_id];
175         if (!is_array($my_cats)) {
176                 return;
177         }
178         foreach ($my_cats as $cat) {
179
180                 echo '<option value="'.$cat['cat_id'].'"';
181                 if($cat['cat_id'] == $cat_row){
182                         echo  ' selected="selected"';
183                 }
184                 echo '>';
185                 echo str_pad('', $depth, '-');
186                 echo $cat['cat_name'].'</option>'."\n";
187
188                 print_course_cats($cat['cat_id'], $cats,  $cat_row, $depth+1);
189         }
190 }
191
192 // returns the most appropriate representation of Bytes in MB, KB, or B
193 function get_human_size($num_bytes) {
194         $abs_num_bytes = abs($num_bytes);
195
196         if ($abs_num_bytes >= AT_KBYTE_SIZE * AT_KBYTE_SIZE) {
197                 return round(bytes_to_megabytes($num_bytes), 2) .' '. _AT('mb');
198         } else if ($abs_num_bytes >= AT_KBYTE_SIZE) {
199                 return round(bytes_to_kilobytes($num_bytes), 2) .' '._AT('kb') ;
200         }
201         // else:
202
203         return $num_bytes . ' '._AT('bt');
204 }
205
206 /**
207 * Returns the MB representation of inputed bytes
208 * @access  public
209 * @param   int $num_bytes       the input bytes to convert
210 * @return  int                          MB representation of $num_bytes
211 * @author  Heidi Hazelton
212 */
213 function bytes_to_megabytes($num_bytes) {
214         return $num_bytes/AT_KBYTE_SIZE/AT_KBYTE_SIZE;
215 }
216
217 /**
218 * Returns the Byte representation of inputed MB
219 * @access  public
220 * @param   int $num_bytes       the input MB to convert
221 * @return  int                          the Bytes representation of $num_bytes
222 * @author  Heidi Hazelton
223 */
224 function megabytes_to_bytes($num_bytes) {
225         return $num_bytes*AT_KBYTE_SIZE*AT_KBYTE_SIZE;
226 }
227
228 /**
229 * Returns the KB representation of inputed Bytes
230 * @access  public
231 * @param   int $num_bytes       the input Bytes to convert
232 * @return  int                          the KB representation of $num_bytes
233 * @author  Heidi Hazelton
234 */
235 function bytes_to_kilobytes($num_bytes) {
236         return $num_bytes/AT_KBYTE_SIZE;
237 }
238
239 /**
240 * Returns the Bytes representation of inputed KBytes
241 * @access  public
242 * @param   int $num_bytes       the input KBytes to convert
243 * @return  int                          the KBytes representation of $num_bytes
244 * @author  Heidi Hazelton
245 */
246 function kilobytes_to_bytes($num_bytes) {
247         return $num_bytes*AT_KBYTE_SIZE;
248 }
249
250 /**
251 * Outputs the directories associated with a course in the form of <option> elements.
252 * @access public
253 * @param  string $cur_dir  the current directory to include in the options.
254 * @author Norma Thompson
255 */
256 function output_dirs($current_path,$cur_dir,$indent) {
257         // open the cur_dir
258         if ($dir = opendir($current_path.$cur_dir)) {
259
260                 // recursively call output_dirs() for all directories in this directory
261                 while (false !== ($file = readdir($dir)) ) {
262
263                         //if the name is not a directory 
264                         if( ($file == '.') || ($file == '..') ) {
265                                 continue;
266                         }
267
268                         // if it is a directory call function
269                         if(is_dir($current_path.$cur_dir.$file)) {
270                                 $ldir = explode('/',$cur_dir.$file);
271                                 $count = count($ldir);
272                                 $label = $ldir[$count-1];
273                                 
274                                 $dir_option .= '<option value="'.$cur_dir.$file.'/" >'.$indent.$label.'</option>';
275
276                                 $dir_option .= output_dirs($current_path,$cur_dir.$file.'/',$indent.'--');
277                         }
278                         
279                 } // end while  
280                 
281                 closedir($dir); 
282         }
283         return $dir_option;
284 }
285
286 function display_tree($current_path, $cur_dir, $pathext, $ignore_children = false) {
287         // open the cur_dir
288         static $list_array;
289         if (!isset($list_array)) {
290                 $list_array = explode(',', $_GET['list']);
291         }
292         if ($dir = opendir($current_path . $cur_dir)) {
293
294                 // recursively call output_dirs() for all directories in this directory
295                 while (false !== ($file = readdir($dir)) ) {
296
297                         //if the name is not a directory 
298                         if( ($file == '.') || ($file == '..') ) {
299                                 continue;
300                         }
301
302                         // if it is a directory call function
303                         if (is_dir($current_path . $cur_dir . $file)) {
304
305                                 //$ldir = explode('/',$cur_dir.$file);
306                                 //$count = count($ldir);
307                                 //$label = $ldir[$count-1];
308
309                                 $check = '';
310                                 $here  = '';
311                                 if ($cur_dir . $file == substr($pathext, 0, -1)) {
312                                         $check = 'checked="checked"';
313                                         $here = ' ' . _AT('current_location');
314                                 } else if (($cur_dir == $pathext) && in_array($file, $list_array)) {
315                                         $ignore_children = true;
316                                 }
317
318                                 if ($ignore_children) {
319                                         $check = 'disabled="disabled"';
320                                         $class = ' disabled';
321                                 }
322
323                                 $dir_option .= '<ul><li class="folders'.$class.'">';
324                                 $dir_option .= '<label><input type="radio" name="dir_name" value="'.$cur_dir.$file.'" '.$check. '/>'. $file . $here. '</label>';
325                                 $dir_option .= ''.display_tree($current_path,$cur_dir.$file.'/', $pathext, $ignore_children).'';
326                                 $dir_option .= '</li></ul>';
327
328                                 if (($cur_dir == $pathext) && in_array($file, $list_array)) {
329                                         $ignore_children = false;
330                                         $class = '';
331                                 }
332                         }
333
334                         
335                 } // end while  
336                 
337                 closedir($dir); 
338         }
339         return $dir_option;
340 }
341
342 function course_realpath($file) {
343         if (!$_SESSION['course_id']) {
344                 return FALSE;
345         }
346         
347         $course_path = AT_CONTENT_DIR . $_SESSION['course_id'];
348         
349         $path_parts = pathinfo($file);
350         
351         $dir_name   = $path_parts['dirname'];
352         $file_name  = $path_parts['basename'];
353         $ext_name   = $path_parts['extension'];
354
355         //1. determine the real path of the file/directory
356         if (is_dir($dir_name.DIRECTORY_SEPARATOR.$file_name) && $ext_name == '') {
357                 //if directory ws passed through (moving file to diff directory)
358                 $real = realpath($dir_name . DIRECTORY_SEPARATOR . $file_name);
359         } else {
360                 //if file was passed through or no existant direcotry was passed through (rename/creating dir)
361                 $real = realpath($dir_name);
362         }
363
364         //2. and whether its in the course content directory
365         if (substr($real, 0, strlen($course_path)) != $course_path) {
366                 return FALSE;
367         }
368
369         //3. check if extensions are legal
370
371         //4. Otherwise return the real path of the file
372         return $real;
373 }
374
375 /**
376 * Returns canonicalized absolute pathname to a file/directory in the content directory
377 * @access public
378 * @param  string $file the relative path to the file or directory
379 * @return  string       the full path to the file or directory, FALSE if it does not exist in our content directory.
380 */
381 function course_realpath_NEW_VERSION($file) {
382         if (!$_SESSION['course_id']) {
383                 return FALSE;
384         }
385         
386         $course_path = AT_CONTENT_DIR . $_SESSION['course_id'];
387
388         // determine the real path of the file/directory
389         $real = realpath($course_path . DIRECTORY_SEPARATOR . $file);
390         
391         if (!file_exists($real)) {
392                 // the file or directory does not exist
393                 return FALSE;
394
395         } else if (substr($real, 0, strlen($course_path)) != $course_path) {
396                 // the file or directory is not in the content path
397                 return FALSE;
398
399         } else {
400                 // Otherwise return the real path of the file
401                 return $real;
402         }
403 }
404
405 /**
406 * Returns the name of the readme file in the given directory
407 * @access public
408 * @param  string $dir_name the name of the directory
409 * @return  string       the name of the readme file
410 */
411 function get_readme($dir)
412 {
413         if (!is_dir($dir)) return '';
414         
415         $dh = opendir($dir);
416         
417         while (($file = readdir($dh)) !== false) {
418                 if (stristr($file, 'readme') && substr($file, -4) <> '.php')
419                         return $file;
420         }
421         
422         closedir($dh);
423         return '';
424 }
425
426
427 /**
428  * This function is mainly used to download big zip files that are created by ATutor.
429  * For example, download common cartridge, content package, backup.
430  * Note that the file is only in binary, as fopen($filename, "rb"). 
431  * Don't use it to read open text/html files
432  * 
433  * When downloading large files exceeding 1M, instead of use readfile() to read
434  * the whole file into memory once at a time, push down 1M at a time. This way can
435  * download whatever size of the file regardless of php memory limit.
436  */  
437 function readfile_in_chunks($filename) {
438         $filesize = intval(sprintf("%u", filesize($filename)));
439         $chunk_size = 1024 * 1024;
440         
441         if ($filesize > $chunk_size) {
442                 $fp = fopen($filename, "rb");
443                 while (!feof($fp))
444                 {
445                         echo fread($fp, $chunk_size);
446                         ob_flush();
447                         flush();
448                 }
449                 fclose($fp);
450         } else {
451                 readfile($filename);
452         }
453 }
454
455 /**
456  * This function handles ajax request and return an array of errors encoded in JSON
457  * @param   int     HTTP Status code, so far, handle 200 and 500.
458  */
459 function handleAjaxUpload($statusCode) {
460     if ($_POST['type'] === 'ajax') {
461         if ($statusCode === 500) {
462 //            $msg->printErrors();
463             header("HTTP/1.1 500 Internal Server Error", TRUE, 500);
464         } elseif ($statusCode === 200) {
465 //            $msg->printFeedbacks();
466             header("HTTP/1.1 200 Ok", TRUE, 200);
467         }
468         exit;
469     }
470 }
471  
472 ?>