tagging as ATutor 1.5.4-release
[atutor.git] / include / lib / file_storage.inc.php
1 <?php\r
2 /************************************************************************/\r
3 /* ATutor                                                                                                                               */\r
4 /************************************************************************/\r
5 /* Copyright (c) 2002-2006 by Greg Gay, Joel Kronenberg & Heidi Hazelton*/\r
6 /* Adaptive Technology Resource Centre / University of Toronto                  */\r
7 /* http://atutor.ca                                                                                                             */\r
8 /*                                                                                                                                              */\r
9 /* This program is free software. You can redistribute it and/or                */\r
10 /* modify it under the terms of the GNU General Public License                  */\r
11 /* as published by the Free Software Foundation.                                                */\r
12 /************************************************************************/\r
13 // $Id$\r
14 \r
15 /**\r
16  * Additional constants are found in /include/lib/constants.inc.php (for the work spaces)\r
17  *\r
18  * The File Storage was designed to allow for unlimited workspace, although only four right now.\r
19  *\r
20  * All the functions are namespaced with fs_ (for File Storage not File System).\r
21  *\r
22  * These two variables are used throughout.\r
23  * $owner_type is used to define the workspace type. Also appears as $ot in _GET.\r
24  * $owner_id is the ID of the particular workspace type. Also appears as $oid in _GET.\r
25  * \r
26  **/\r
27 \r
28 if (!defined('AT_INCLUDE_PATH')) { exit; }\r
29 \r
30 define('WORKSPACE_AUTH_NONE',  0);\r
31 define('WORKSPACE_AUTH_READ',  1);\r
32 define('WORKSPACE_AUTH_WRITE', 2); \r
33 define('WORKSPACE_AUTH_RW',    3); // to save time\r
34 \r
35 /**\r
36  * given an owner_type and owner_id\r
37  * returns false if user cannot read or write to this workspace\r
38  * returns WORKSPACE_AUTH_READ if the user can read\r
39  * returns WORKSPACE_AUTH_WRITE if the user can write\r
40  */\r
41 function fs_authenticate($owner_type, $owner_id) {\r
42         if (($owner_type == WORKSPACE_PERSONAL) && $_SESSION['member_id'] && ($owner_id == $_SESSION['member_id'])) {\r
43 \r
44                 return WORKSPACE_AUTH_RW;\r
45 \r
46         } else if ($owner_type == WORKSPACE_ASSIGNMENT && authenticate(AT_PRIV_ASSIGNMENTS, AT_PRIV_RETURN)) {\r
47                 // instructors have read only access to assignments\r
48 \r
49                 return WORKSPACE_AUTH_READ;\r
50         \r
51         } else if ($owner_type == WORKSPACE_GROUP) {\r
52                 if (isset($_SESSION['groups'][$owner_id])) {\r
53                         global $db;\r
54                         $sql = "SELECT * FROM ".TABLE_PREFIX."file_storage_groups WHERE group_id=$owner_id";\r
55                         $result = mysql_query($sql, $db);\r
56                         if (mysql_fetch_assoc($result)) {\r
57                                 return WORKSPACE_AUTH_RW;\r
58                         }\r
59                 }\r
60 \r
61         } else if ($owner_type == WORKSPACE_COURSE) {\r
62                 if (($owner_id == $_SESSION['course_id']) && authenticate(AT_PRIV_FILE_STORAGE, AT_PRIV_RETURN)) {\r
63                         return WORKSPACE_AUTH_RW;\r
64                 } else if ($owner_id == $_SESSION['course_id']) {\r
65                         return WORKSPACE_AUTH_READ;\r
66                 }\r
67         }\r
68         /* else if ($owner_type == WORKSPACE_SYSTEM) {\r
69                 if (admin_authenticate(AT_ADMIN_PRIV_FILE_STORAGE, TRUE)) {\r
70                         return WORKSPACE_AUTH_RW;\r
71                 } // else\r
72                 return WORKSPACE_AUTH_READ; // everyone can read the System File Space\r
73         } */\r
74 \r
75         return WORKSPACE_AUTH_NONE;\r
76 }\r
77 \r
78 /**\r
79  * returns the localised name of the specified workspace\r
80  */\r
81 function fs_get_workspace($owner_type, $owner_id) {\r
82         if ($owner_type == WORKSPACE_PERSONAL) {\r
83                 return _AT('my_files');\r
84 \r
85         } else if ($owner_type == WORKSPACE_COURSE) {\r
86                 return _AT('course_files');\r
87 \r
88         } else if ($owner_type == WORKSPACE_GROUP) {\r
89                 global $db;\r
90                 $sql = "SELECT title FROM ".TABLE_PREFIX."groups WHERE group_id=$owner_id";\r
91                 $result = mysql_query($sql, $db);\r
92                 $row    = mysql_fetch_assoc($result);\r
93                 return $row['title'];\r
94 \r
95         } else if ($owner_type == WORKSPACE_ASSIGNMENT) {\r
96                 $row    = fs_get_assignment($owner_id);\r
97                 return ($row ? $row['title'] : false);\r
98         } /*\r
99                 else if ($owner_type == WORKSPACE_SYSTEM) {\r
100                 return _AT('system_files');\r
101      }\r
102         */\r
103 }\r
104 \r
105 /**\r
106  * returns the assignment row specified by $assignment_id\r
107  * false if not found.\r
108  */\r
109 function fs_get_assignment($assignment_id) {\r
110         global $db;\r
111         $sql = "SELECT assignment_id, title, assign_to, date_due, date_cutoff, UNIX_TIMESTAMP(date_cutoff) AS u_date_cutoff, multi_submit FROM ".TABLE_PREFIX."assignments WHERE assignment_id=$assignment_id AND course_id=$_SESSION[course_id]";\r
112         $result = mysql_query($sql, $db);\r
113         $row    = mysql_fetch_assoc($result);\r
114         return $row;\r
115 }\r
116 \r
117 /**\r
118  * retrieve folder(s) specified by $folder_id\r
119  * $folder_id the ID of the single folder, or array of IDs\r
120  * if $folder_id is an array then returns an array of folder rows\r
121  * if $folder_id is an int then returns the single row array\r
122  *\r
123  * This function does not authenticate the $folder_id for the assignment.\r
124  *\r
125  * Note: This function checks if the $owner_type is an Assignment.\r
126  *\r
127  */\r
128 function fs_get_folder_by_id($folder_id, $owner_type, $owner_id) {\r
129         global $db;\r
130 \r
131         $rows = array();\r
132 \r
133         if ($owner_type == WORKSPACE_ASSIGNMENT) {\r
134                 // get the folder row from the assignments table\r
135 \r
136                 $sql = "SELECT assign_to FROM ".TABLE_PREFIX."assignments WHERE assignment_id=$owner_id AND course_id=$_SESSION[course_id]";\r
137                 $result = mysql_query($sql, $db);\r
138                 $row  = mysql_fetch_assoc($result);\r
139                 if ($row['assign_to']) {\r
140                         $sql = "SELECT title FROM ".TABLE_PREFIX."groups WHERE group_id=$folder_id";\r
141                         $result = mysql_query($sql, $db);\r
142                         $row = mysql_fetch_assoc($result);\r
143 \r
144                         $rows = array('title' => $row['title'], 'folder_id' => $folder_id);\r
145                 } else {\r
146                         $rows = array('title' => get_display_name($folder_id), 'folder_id' => $folder_id);\r
147                 }\r
148         } else {\r
149                 if (is_array($folder_id)) {\r
150                         $folder_id_list = implode(',', $folder_id);\r
151 \r
152                         $sql = "SELECT folder_id, title, parent_folder_id FROM ".TABLE_PREFIX."folders WHERE folder_id IN ($folder_id_list) AND owner_type=$owner_type AND owner_id=$owner_id ORDER BY title";\r
153                         $result = mysql_query($sql, $db);\r
154                         while ($row = mysql_fetch_assoc($result)) {\r
155                                 $rows[] = $row;\r
156                         }\r
157 \r
158                 } else {\r
159                         $sql = "SELECT folder_id, title, parent_folder_id FROM ".TABLE_PREFIX."folders WHERE folder_id=$folder_id AND owner_type=$owner_type AND owner_id=$owner_id";\r
160                         $result = mysql_query($sql, $db);\r
161                         $rows = mysql_fetch_assoc($result);\r
162                 }\r
163         }\r
164         return $rows;\r
165 }\r
166 \r
167 /**\r
168  * retrieve folder(s) specified by $parent_folder_id\r
169  *\r
170  * Note: This function checks if the $owner_type is an Assignment.\r
171  *\r
172  */\r
173 function fs_get_folder_by_pid($parent_folder_id, $owner_type, $owner_id) {\r
174         global $db;\r
175 \r
176         $rows = array();\r
177         if ($owner_type == WORKSPACE_ASSIGNMENT) {\r
178                 // get the folder row from the assignments table\r
179                 // does not currently support sub-folders for assignments\r
180                 if ($parent_folder_id == 0) {\r
181                         $sql = "SELECT assign_to FROM ".TABLE_PREFIX."assignments WHERE assignment_id=$owner_id AND course_id=$_SESSION[course_id]";\r
182                         $result = mysql_query($sql, $db);\r
183                         $row  = mysql_fetch_assoc($result);\r
184                         if ($row['assign_to']) {\r
185                                 $sql = "SELECT G.group_id AS folder_id, G.title FROM ".TABLE_PREFIX."groups G INNER JOIN ".TABLE_PREFIX."file_storage_groups FS USING (group_id) WHERE G.type_id=$row[assign_to] ORDER BY G.title";\r
186                         } else {\r
187                                 global $system_courses;\r
188 \r
189                                 $sql = "SELECT E.member_id AS folder_id, M.login AS title FROM ".TABLE_PREFIX."course_enrollment E INNER JOIN ".TABLE_PREFIX."members M USING (member_id) WHERE E.course_id=$_SESSION[course_id] AND E.approved='y' AND E.privileges & ".AT_PRIV_GROUPS." = 0 AND E.member_id<>{$system_courses[$_SESSION[course_id]][member_id]} ORDER BY M.login";\r
190                         }\r
191                         $result = mysql_query($sql, $db);\r
192 \r
193                         while ($row = mysql_fetch_assoc($result)) {\r
194                                 $rows[] = $row;\r
195                         }\r
196                 }\r
197         } else {\r
198                 $sql = "SELECT folder_id, title FROM ".TABLE_PREFIX."folders WHERE parent_folder_id=$parent_folder_id AND owner_type=$owner_type AND owner_id=$owner_id ORDER BY title";\r
199                 $result = mysql_query($sql, $db);\r
200                 while ($row = mysql_fetch_assoc($result)) {\r
201                         $rows[] = $row; \r
202                 }\r
203         }\r
204         return $rows;\r
205 }\r
206 \r
207 /**\r
208  * outputs the folders as a <ul> list.\r
209  *\r
210  * $current_folder_id the current folder id, used for pre-selecting the radio button\r
211  * $parent_folder_id the folder id to display children of\r
212  * $folders the array of folders returned from get_folders()\r
213  * $disable whether or not the radio button is available\r
214  */\r
215 function fs_print_folders($current_folder_id, $parent_folder_id, &$folders, $disable = FALSE) {\r
216         if (!isset($folders[$parent_folder_id])) {\r
217                 return;\r
218         }\r
219 \r
220         echo '<ul>';\r
221         foreach ($folders[$parent_folder_id] as $folder_id => $folder_info) {\r
222                 echo '<li class="folders">';\r
223                 \r
224                 echo '<input type="radio" name="new_folder" value="'.$folder_id.'" id="f'.$folder_id.'"';\r
225                 if ($_GET['folders'] && in_array($folder_id, $_GET['folders'])) {\r
226                         $disable = TRUE;\r
227                 }\r
228                 if ($folder_id == $current_folder_id) {\r
229                         echo ' checked="checked"';\r
230                 }\r
231                 if ($disable) {\r
232                         echo ' disabled="disabled"';\r
233                 }\r
234                 echo '/><label for="f'.$folder_id.'">'.htmlspecialchars($folder_info['title']);\r
235                 if ($folder_id == $current_folder_id) {\r
236                         echo ' '._AT('current_location');\r
237                 }\r
238                 echo '</label>';\r
239                 \r
240                 fs_print_folders($current_folder_id, $folder_id, $folders, $disable);\r
241                 if ($_GET['folders'] && in_array($folder_id, $_GET['folders'])) {\r
242                         $disable = FALSE;\r
243                 }\r
244                 echo '</li>';\r
245         }\r
246         echo '</ul>';\r
247 }\r
248 \r
249 /**\r
250  * returns an array of all the revisions for the given file_id\r
251  *\r
252  * $file_id ID of a file in a revision sequence. can be any revision, does not have to be the latest.\r
253  * This function is recursive and uses fs_get_revisions_down_recursive() and fs_get_revisions_recurisve() below.\r
254  */\r
255 function fs_get_revisions($file_id, $owner_type, $owner_id) {\r
256         global $db;\r
257 \r
258         $sql = "SELECT * FROM ".TABLE_PREFIX."files WHERE file_id=$file_id AND owner_type=$owner_type AND owner_id=$owner_id";\r
259         $result = mysql_query($sql, $db);\r
260         if ($row = mysql_fetch_assoc($result)) {\r
261                 return array_merge(array_reverse(fs_get_revisions_down_recursive($row['parent_file_id'])), array($row), fs_get_revisions_recursive($file_id));\r
262         }\r
263         return array();\r
264 }\r
265 \r
266 /**\r
267  * recursively retrieves all the revisions of the file.\r
268  * recurses DOWN the revisions path.\r
269  * PRIVATE! use fs_get_revisions() above.\r
270  */\r
271 function fs_get_revisions_down_recursive($file_id) {\r
272         global $db;\r
273 \r
274         if ($file_id == 0) {\r
275                 return array();\r
276         }\r
277 \r
278         $sql = "SELECT * FROM ".TABLE_PREFIX."files WHERE file_id=$file_id";\r
279         $result = mysql_query($sql, $db);\r
280         $row = mysql_fetch_assoc($result);\r
281 \r
282         if (!$row) {\r
283                 return array();\r
284         } else if (!$row['parent_file_id']) {\r
285                 return array($row);\r
286         }\r
287 \r
288         return array_merge(array($row), fs_get_revisions_down_recursive($row['parent_file_id']));\r
289 }\r
290 \r
291 /**\r
292  * recursively retrieves all the revisions of the file.\r
293  * recurses UP the revisions path.\r
294  * PRIVATE! use fs_get_revisions() above.\r
295  */\r
296 function fs_get_revisions_recursive($file_id) {\r
297         global $db;\r
298 \r
299         if ($file_id == 0) {\r
300                 return array();\r
301         }\r
302 \r
303         $sql = "SELECT * FROM ".TABLE_PREFIX."files WHERE parent_file_id=$file_id";\r
304         $result = mysql_query($sql, $db);\r
305         $row = mysql_fetch_assoc($result);\r
306 \r
307         if (!$row) {\r
308                 return array();\r
309         }\r
310 \r
311         return array_merge(array($row), fs_get_revisions_recursive($row['file_id']));\r
312 }\r
313 \r
314 /**\r
315  * returns the full path based on $file_id with trailing slash.\r
316  *\r
317  * Ex. if file_id is 2345 and WORKSPACE_PATH_DEPTH is set to 3 then\r
318  * the path returned will be WORKSPACE_FILE_PATH.'5/4/3/'\r
319  *\r
320  * If the path does not exist within the WORKSPACE_FILE_PATH then attempts\r
321  * to create it.\r
322  */\r
323 function fs_get_file_path($file_id) {\r
324         $end_part = substr($file_id, -WORKSPACE_PATH_DEPTH);\r
325         $path = WORKSPACE_FILE_PATH;\r
326         $dirs = max(-WORKSPACE_PATH_DEPTH, -strlen($file_id));\r
327         $id_threshold = pow(10,WORKSPACE_PATH_DEPTH); // only check for the dir before reaching this value.\r
328     for ($i = -1; $i >= $dirs; $i--) {\r
329                 $path .= substr($file_id, $i, 1) . DIRECTORY_SEPARATOR;\r
330                 if ($file_id <= $id_threshold) {\r
331                         if (!is_dir($path)) {\r
332                                 @mkdir($path);\r
333                         }\r
334                 }\r
335         }\r
336 \r
337         return $path;\r
338 }\r
339 \r
340 /**\r
341  * delete a given file, its revisions, and comments.\r
342  *\r
343  * $file_id the ID of the file to delete. can be any ID within a revision sequence.\r
344  */\r
345 function fs_delete_file($file_id, $owner_type, $owner_id) {\r
346         global $db;\r
347         $revisions = fs_get_revisions($file_id, $owner_type, $owner_id);\r
348         foreach ($revisions as $file) {\r
349                 $sql = "DELETE FROM ".TABLE_PREFIX."files WHERE file_id=$file[file_id] AND owner_type=$owner_type AND owner_id=$owner_id";\r
350                 mysql_query($sql, $db);\r
351 \r
352                 if (mysql_affected_rows($db) == 1) {\r
353                         $sql = "DELETE FROM ".TABLE_PREFIX."files_comments WHERE file_id=$file[file_id]";\r
354                         mysql_query($sql, $db);\r
355 \r
356                         $path = fs_get_file_path($file['file_id']);\r
357                         if (file_exists($path . $file['file_id'])) {\r
358                                 @unlink($path . $file['file_id']);\r
359                         }\r
360                 }\r
361         }\r
362 }\r
363 \r
364 /**\r
365  * returns only the extension part of the specified file name\r
366  *\r
367  * $file_name the full name of the file.\r
368  */\r
369 function fs_get_file_extension($file_name) {\r
370         $ext = pathinfo($file_name);\r
371         return $ext['extension'];\r
372 }\r
373 \r
374 /**\r
375  * returns the image name (w/o the ".gif" ending) of the icon to use\r
376  * for the given file name.\r
377  * if no icon is specified (by mime.inc.php) then returns "generic"\r
378  */\r
379 function fs_get_file_type_icon($file_name) {\r
380         global $mime;\r
381         if (!isset($mime)) {\r
382                 require(AT_INCLUDE_PATH.'lib/mime.inc.php');\r
383         }\r
384         $ext = fs_get_file_extension($file_name);\r
385 \r
386         if (isset($mime[$ext]) && $mime[$ext][1]) {\r
387                 return $mime[$ext][1];\r
388         }\r
389         return 'generic';\r
390 }\r
391 \r
392 /**\r
393  * deletes the folder, its sub-folders and associated files.\r
394  *\r
395  * $folder_id the ID of the folder to delete, recursively, with content.\r
396  */\r
397 function fs_delete_folder($folder_id, $owner_type, $owner_id) {\r
398         if (!$folder_id) { return; }\r
399 \r
400         global $db;\r
401 \r
402         $rows = fs_get_folder_by_pid($folder_id, $owner_type, $owner_id);\r
403         foreach ($rows as $row) {\r
404                 fs_delete_folder($row['folder_id'], $owner_type, $owner_id);\r
405         }\r
406 \r
407         $sql = "DELETE FROM ".TABLE_PREFIX."folders WHERE folder_id=$folder_id AND owner_type=$owner_type AND owner_id=$owner_id";\r
408         mysql_query($sql, $db);\r
409 \r
410         // delete this file's folders (we only select the latest versions because\r
411         // the delete_file() function takes care of the revisions for us\r
412         $sql = "SELECT file_id FROM ".TABLE_PREFIX."files WHERE folder_id=$folder_id AND parent_file_id=0 AND owner_type=$owner_type AND owner_id=$owner_id";\r
413         $result = mysql_query($sql, $db);\r
414         while ($row = mysql_fetch_assoc($result)) {\r
415                 fs_delete_file($row['file_id'], $owner_type, $owner_id);\r
416         }\r
417 }\r
418 \r
419 /**\r
420  * archives a folder into a specified zip handler.\r
421  *\r
422  * $folder_id the ID of the folder to archive recursively, with content.\r
423  * $zipfile reference to the zipFile object.\r
424  * $path the absolute path to the current folder.\r
425  */\r
426 function fs_download_folder($folder_id, &$zipfile, $owner_type, $owner_id, $path = '') {\r
427         global $db;\r
428 \r
429         $parent_row = fs_get_folder_by_id($folder_id, $owner_type, $owner_id);\r
430         //$sql = "SELECT title FROM ".TABLE_PREFIX."folders WHERE folder_id=$folder_id AND owner_type=$owner_type AND owner_id=$owner_id";\r
431         //$result = mysql_query($sql, $db);\r
432         if ($parent_row) {\r
433                 $zipfile->create_dir($path . $parent_row['title']);\r
434         }\r
435 \r
436         $sql = "SELECT file_id, file_name, UNIX_TIMESTAMP(date) AS date FROM ".TABLE_PREFIX."files WHERE folder_id=$folder_id AND parent_file_id=0 AND owner_type=$owner_type AND owner_id=$owner_id";\r
437         $result = mysql_query($sql, $db);\r
438         while ($row = mysql_fetch_assoc($result)) {\r
439                 $file_path = fs_get_file_path($row['file_id']) . $row['file_id'];\r
440 \r
441                 $zipfile->add_file(file_get_contents($file_path), $path . $parent_row['title'] .'/' . $row['file_name'], $row['date']);\r
442         }\r
443 \r
444         $rows = fs_get_folder_by_pid($folder_id, $owner_type, $owner_id);\r
445         foreach ($rows as $row) {\r
446                 fs_download_folder($row['folder_id'], $zipfile, $owner_type, $owner_id, $path . $parent_row['title'] . '/');\r
447         }\r
448 }\r
449 \r
450 /**\r
451  * returns the full path to the current folder\r
452  *\r
453  * $folder_id the current folder\r
454  * $workspace the owner_type of this folder\r
455  * $owner_id the ID of the owner.\r
456  */\r
457 function fs_get_folder_path($folder_id, $owner_type, $owner_id) {\r
458         $folder_path = fs_get_folder_path_recursive($folder_id, $owner_type, $owner_id);\r
459 \r
460         return array_reverse($folder_path);\r
461 }\r
462 \r
463 /**\r
464  * recursively return the path to the current folder\r
465  * PRIVATE! do not call directly, use get_folder_path() above.\r
466  */\r
467 function fs_get_folder_path_recursive($folder_id, $owner_type, $owner_id) {\r
468         global $db;\r
469 \r
470         if ($folder_id == 0) {\r
471                 return array();\r
472         }\r
473 \r
474         $row = fs_get_folder_by_id($folder_id, $owner_type, $owner_id);\r
475 \r
476         return array_merge(array($row), fs_get_folder_path_recursive($row['parent_folder_id'], $owner_type, $owner_id));\r
477 }\r
478 \r
479 /**\r
480  * deletes all the files, folders, comments, revisions, etc.. in the specified workspace.\r
481  */\r
482 function fs_delete_workspace($owner_type, $owner_id) {\r
483         global $db;\r
484 \r
485         $sql = "SELECT folder_id, owner_type, owner_id FROM ".TABLE_PREFIX."folders WHERE owner_type=$owner_type AND owner_id=$owner_id AND parent_folder_id=0";\r
486         $result = mysql_query($sql, $db);\r
487         while ($row = mysql_fetch_assoc($result)) {\r
488                 fs_delete_folder($row['folder_id'], $row['owner_type'], $row['owner_id']);\r
489         }\r
490 \r
491         $sql = "SELECT file_id, owner_type, owner_id FROM ".TABLE_PREFIX."files WHERE owner_type=$owner_type AND owner_id=$owner_id";\r
492         $result = mysql_query($sql, $db);\r
493         while ($row = mysql_fetch_assoc($result)) {\r
494                 fs_delete_file($row['file_id'], $row['owner_type'], $row['owner_id']);\r
495         }\r
496 }\r
497 \r
498 /**\r
499  * copies a file to another workspace.\r
500  * currently only used for submitting assignments.\r
501  **/\r
502 function fs_copy_file($file_id, $src_owner_type, $src_owner_id, $dest_owner_type, $dest_owner_id, $dest_folder_id) {\r
503         global $db;\r
504 \r
505         $sql = "SELECT file_name, file_size, description FROM ".TABLE_PREFIX."files WHERE file_id=$file_id AND owner_type=$src_owner_type AND owner_id=$src_owner_id";\r
506         $result = mysql_query($sql, $db);\r
507         if (!$row = mysql_fetch_assoc($result)) {\r
508                 return false;\r
509         }\r
510         $sql = "INSERT INTO ".TABLE_PREFIX."files VALUES (NULL, $dest_owner_type, $dest_owner_id, $_SESSION[member_id], $dest_folder_id, 0, NOW(), 0, 0, '$row[file_name]', '$row[file_size]', '$row[description]')";\r
511         $result = mysql_query($sql, $db);\r
512 \r
513         $id = mysql_insert_id($db);\r
514 \r
515         $src_file  = fs_get_file_path($file_id) . $file_id;\r
516         $dest_file = fs_get_file_path($id) . $id;\r
517         copy($src_file, $dest_file);\r
518 }\r
519 \r
520 /**\r
521  * used with usort() to sort the revisions array returned from fs_get_revisions()\r
522  * $col is a valid array key to sort by\r
523  * $order is either 'asc' or 'desc'\r
524  */\r
525 function fs_revisions_sort_compare($a, $b) {\r
526         global $col, $order;\r
527 \r
528         if ($order == 'asc') {\r
529                 return strcasecmp($a[$col], $b[$col]);\r
530         }\r
531         return strcasecmp($b[$col], $a[$col]);\r
532 }\r
533 \r
534 /**\r
535  * copies a directory to another workspace.\r
536  * not currently used anywhere.\r
537  */\r
538 /***\r
539 function fs_copy_folder($folder_id, $src_owner_type, $src_owner_id, $dest_owner_type, $dest_owner_id, $dest_parent_folder_id) {\r
540         global $db;\r
541 \r
542         $folder = fs_get_folder_by_id($folder_id, $src_owner_type, $src_owner_id);\r
543         if (!$folder) {\r
544                 return false;\r
545         }\r
546 \r
547         $sql = "INSERT INTO ".TABLE_PREFIX."folders VALUES (0, $dest_parent_folder_id, $dest_owner_type, $dest_owner_id, '$folder[title]')";\r
548         $result = mysql_query($sql, $db);\r
549         $id = mysql_insert_id($db);\r
550 \r
551         $sql = "SELECT file_id FROM ".TABLE_PREFIX."files WHERE folder_id=$folder_id AND owner_type=$src_owner_type AND owner_id=$src_owner_id";\r
552         $result = mysql_query($sql, $db);\r
553         while ($row = mysql_fetch_assoc($result)) {\r
554                 fs_copy_file($row['file_id'], $src_owner_type, $src_owner_id, $dest_owner_type, $dest_owner_id, $id);\r
555         }\r
556 \r
557         $folders = fs_get_folder_by_pid($folder_id, $src_owner_type, $src_owner_id);\r
558         foreach ($folders as $folder) {\r
559                 fs_copy_folder($folder['folder_id'], $src_owner_type, $src_owner_id, $dest_owner_type, $dest_owner_id, $id);\r
560         }\r
561 }\r
562 */\r
563 ?>