2 /************************************************************************/
\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
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
16 * Additional constants are found in /include/lib/constants.inc.php (for the work spaces)
\r
18 * The File Storage was designed to allow for unlimited workspace, although only four right now.
\r
20 * All the functions are namespaced with fs_ (for File Storage not File System).
\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
28 if (!defined('AT_INCLUDE_PATH')) { exit; }
\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
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
41 function fs_authenticate($owner_type, $owner_id) {
\r
42 if (($owner_type == WORKSPACE_PERSONAL) && $_SESSION['member_id'] && ($owner_id == $_SESSION['member_id'])) {
\r
44 return WORKSPACE_AUTH_RW;
\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
49 return WORKSPACE_AUTH_READ;
\r
51 } else if ($owner_type == WORKSPACE_GROUP) {
\r
52 if (isset($_SESSION['groups'][$owner_id])) {
\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
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
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
72 return WORKSPACE_AUTH_READ; // everyone can read the System File Space
\r
75 return WORKSPACE_AUTH_NONE;
\r
79 * returns the localised name of the specified workspace
\r
81 function fs_get_workspace($owner_type, $owner_id) {
\r
82 if ($owner_type == WORKSPACE_PERSONAL) {
\r
83 return _AT('my_files');
\r
85 } else if ($owner_type == WORKSPACE_COURSE) {
\r
86 return _AT('course_files');
\r
88 } else if ($owner_type == WORKSPACE_GROUP) {
\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
95 } else if ($owner_type == WORKSPACE_ASSIGNMENT) {
\r
96 $row = fs_get_assignment($owner_id);
\r
97 return ($row ? $row['title'] : false);
\r
99 else if ($owner_type == WORKSPACE_SYSTEM) {
\r
100 return _AT('system_files');
\r
106 * returns the assignment row specified by $assignment_id
\r
107 * false if not found.
\r
109 function fs_get_assignment($assignment_id) {
\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
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
123 * This function does not authenticate the $folder_id for the assignment.
\r
125 * Note: This function checks if the $owner_type is an Assignment.
\r
128 function fs_get_folder_by_id($folder_id, $owner_type, $owner_id) {
\r
133 if ($owner_type == WORKSPACE_ASSIGNMENT) {
\r
134 // get the folder row from the assignments table
\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
144 $rows = array('title' => $row['title'], 'folder_id' => $folder_id);
\r
146 $rows = array('title' => get_display_name($folder_id), 'folder_id' => $folder_id);
\r
149 if (is_array($folder_id)) {
\r
150 $folder_id_list = implode(',', $folder_id);
\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
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
168 * retrieve folder(s) specified by $parent_folder_id
\r
170 * Note: This function checks if the $owner_type is an Assignment.
\r
173 function fs_get_folder_by_pid($parent_folder_id, $owner_type, $owner_id) {
\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
187 global $system_courses;
\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
191 $result = mysql_query($sql, $db);
\r
193 while ($row = mysql_fetch_assoc($result)) {
\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
208 * outputs the folders as a <ul> list.
\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
215 function fs_print_folders($current_folder_id, $parent_folder_id, &$folders, $disable = FALSE) {
\r
216 if (!isset($folders[$parent_folder_id])) {
\r
221 foreach ($folders[$parent_folder_id] as $folder_id => $folder_info) {
\r
222 echo '<li class="folders">';
\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
228 if ($folder_id == $current_folder_id) {
\r
229 echo ' checked="checked"';
\r
232 echo ' disabled="disabled"';
\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
240 fs_print_folders($current_folder_id, $folder_id, $folders, $disable);
\r
241 if ($_GET['folders'] && in_array($folder_id, $_GET['folders'])) {
\r
250 * returns an array of all the revisions for the given file_id
\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
255 function fs_get_revisions($file_id, $owner_type, $owner_id) {
\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
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
271 function fs_get_revisions_down_recursive($file_id) {
\r
274 if ($file_id == 0) {
\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
284 } else if (!$row['parent_file_id']) {
\r
285 return array($row);
\r
288 return array_merge(array($row), fs_get_revisions_down_recursive($row['parent_file_id']));
\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
296 function fs_get_revisions_recursive($file_id) {
\r
299 if ($file_id == 0) {
\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
311 return array_merge(array($row), fs_get_revisions_recursive($row['file_id']));
\r
315 * returns the full path based on $file_id with trailing slash.
\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
320 * If the path does not exist within the WORKSPACE_FILE_PATH then attempts
\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
341 * delete a given file, its revisions, and comments.
\r
343 * $file_id the ID of the file to delete. can be any ID within a revision sequence.
\r
345 function fs_delete_file($file_id, $owner_type, $owner_id) {
\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
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
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
365 * returns only the extension part of the specified file name
\r
367 * $file_name the full name of the file.
\r
369 function fs_get_file_extension($file_name) {
\r
370 $ext = pathinfo($file_name);
\r
371 return $ext['extension'];
\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
379 function fs_get_file_type_icon($file_name) {
\r
381 if (!isset($mime)) {
\r
382 require(AT_INCLUDE_PATH.'lib/mime.inc.php');
\r
384 $ext = fs_get_file_extension($file_name);
\r
386 if (isset($mime[$ext]) && $mime[$ext][1]) {
\r
387 return $mime[$ext][1];
\r
393 * deletes the folder, its sub-folders and associated files.
\r
395 * $folder_id the ID of the folder to delete, recursively, with content.
\r
397 function fs_delete_folder($folder_id, $owner_type, $owner_id) {
\r
398 if (!$folder_id) { return; }
\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
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
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
420 * archives a folder into a specified zip handler.
\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
426 function fs_download_folder($folder_id, &$zipfile, $owner_type, $owner_id, $path = '') {
\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
433 $zipfile->create_dir($path . $parent_row['title']);
\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
441 $zipfile->add_file(file_get_contents($file_path), $path . $parent_row['title'] .'/' . $row['file_name'], $row['date']);
\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
451 * returns the full path to the current folder
\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
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
460 return array_reverse($folder_path);
\r
464 * recursively return the path to the current folder
\r
465 * PRIVATE! do not call directly, use get_folder_path() above.
\r
467 function fs_get_folder_path_recursive($folder_id, $owner_type, $owner_id) {
\r
470 if ($folder_id == 0) {
\r
474 $row = fs_get_folder_by_id($folder_id, $owner_type, $owner_id);
\r
476 return array_merge(array($row), fs_get_folder_path_recursive($row['parent_folder_id'], $owner_type, $owner_id));
\r
480 * deletes all the files, folders, comments, revisions, etc.. in the specified workspace.
\r
482 function fs_delete_workspace($owner_type, $owner_id) {
\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
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
499 * copies a file to another workspace.
\r
500 * currently only used for submitting assignments.
\r
502 function fs_copy_file($file_id, $src_owner_type, $src_owner_id, $dest_owner_type, $dest_owner_id, $dest_folder_id) {
\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
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
513 $id = mysql_insert_id($db);
\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
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
525 function fs_revisions_sort_compare($a, $b) {
\r
526 global $col, $order;
\r
528 if ($order == 'asc') {
\r
529 return strcasecmp($a[$col], $b[$col]);
\r
531 return strcasecmp($b[$col], $a[$col]);
\r
535 * copies a directory to another workspace.
\r
536 * not currently used anywhere.
\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
542 $folder = fs_get_folder_by_id($folder_id, $src_owner_type, $src_owner_id);
\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
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
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