* @param - action (string) - action type require : 'delete' or 'update' * @param - old_path (string) - old path info stored to change * @param - new_path (string) - new path info to substitute * @desc Update the file or directory path in the document db document table * */ static function update_db_info($action, $old_path, $new_path = '') { $dbTable = Database::get_course_table(TABLE_DOCUMENT); $course_id = api_get_course_int_id(); /* DELETE */ if ($action == 'delete') { $old_path = Database::escape_string($old_path); $to_delete = "WHERE c_id = $course_id AND path LIKE BINARY '".$old_path."' OR path LIKE BINARY '".$old_path."/%'"; $query = "DELETE FROM $dbTable ".$to_delete; $result = Database::query("SELECT id FROM $dbTable ".$to_delete); if (Database::num_rows($result)) { require_once api_get_path(INCLUDE_PATH).'../metadata/md_funcs.php'; $mdStore = new mdstore(true); // create if needed $md_type = (substr($dbTable, -13) == 'scormdocument') ? 'Scorm' : 'Document'; while ($row = Database::fetch_array($result)) { $eid = $md_type.'.'.$row['id']; $mdStore->mds_delete($eid); $mdStore->mds_delete_offspring($eid); } } } /* UPDATE */ if ($action == 'update') { if ($new_path[0] == '.') { $new_path = substr($new_path, 1); } $new_path = str_replace('//', '/', $new_path); // Attempt to update - tested & working for root dir $new_path = Database::escape_string($new_path); $query = "UPDATE $dbTable SET path = CONCAT('".$new_path."', SUBSTRING(path, LENGTH('".$old_path."')+1) ) WHERE c_id = $course_id AND path LIKE BINARY '".$old_path."' OR path LIKE BINARY '".$old_path."/%'"; } Database::query($query); } /** * Cheks a file or a directory actually exist at this location * * @author - Hugues Peeters * @param - file_path (string) - path of the presume existing file or dir * @return - boolean TRUE if the file or the directory exists * boolean FALSE otherwise. */ static function check_name_exist($file_path) { clearstatcache(); $save_dir = getcwd(); if (!is_dir(dirname($file_path))) { return false; } chdir(dirname($file_path)); $file_name = basename($file_path); if (file_exists($file_name)) { chdir($save_dir); return true; } else { chdir($save_dir); return false; } } /** * Deletes a file or a directory * * @author - Hugues Peeters * @param - $file (String) - the path of file or directory to delete * @return - bolean - true if the delete succeed * bolean - false otherwise. * @see - delete() uses check_name_exist() and removeDir() functions */ static function my_delete($file) { if (self::check_name_exist($file)) { if (is_file($file)) { // FILE CASE unlink($file); return true; } elseif (is_dir($file)) { // DIRECTORY CASE self::removeDir($file); return true; } } else { return false; // no file or directory to delete } } /** * Removes a directory recursively * * @returns true if OK, otherwise false * * @author Amary (from Nexen.net) * @author Olivier Brouckaert * * @param string $dir directory to remove */ static function removeDir($dir) { if (!@$opendir = opendir($dir)) { return false; } while ($readdir = readdir($opendir)) { if ($readdir != '..' && $readdir != '.') { if (is_file($dir.'/'.$readdir)) { if (!@unlink($dir.'/'.$readdir)) { return false; } } elseif (is_dir($dir.'/'.$readdir)) { if (!self::removeDir($dir.'/'.$readdir)) { return false; } } } } closedir($opendir); if (!@rmdir($dir)) { return false; } return true; } /** * Return true if folder is empty * @author : hubert.borderiou@grenet.fr * @param string $in_folder : folder path on disk * @return 1 if folder is empty, 0 otherwise */ static function folder_is_empty($in_folder) { $tab_folder_content = scandir($in_folder); $folder_is_empty = 0; if ((count($tab_folder_content) == 2 && in_array(".", $tab_folder_content) && in_array( "..", $tab_folder_content )) || (count($tab_folder_content) < 2) ) { $folder_is_empty = 1; } return $folder_is_empty; } /** * Renames a file or a directory * * @author - Hugues Peeters * @param - $file_path (string) - complete path of the file or the directory * @param - $new_file_name (string) - new name for the file or the directory * @return - boolean - true if succeed * - boolean - false otherwise * @see - rename() uses the check_name_exist() and php2phps() functions */ static function my_rename($file_path, $new_file_name) { $save_dir = getcwd(); $path = dirname($file_path); $old_file_name = basename($file_path); $new_file_name = api_replace_dangerous_char($new_file_name); // If no extension, take the old one if ((strpos($new_file_name, '.') === false) && ($dotpos = strrpos($old_file_name, '.'))) { $new_file_name .= substr($old_file_name, $dotpos); } // Note: still possible: 'xx.yy' -rename-> '.yy' -rename-> 'zz' // This is useful for folder names, where otherwise '.' would be sticky // Extension PHP is not allowed, change to PHPS $new_file_name = self::php2phps($new_file_name); if ($new_file_name == $old_file_name) { return $old_file_name; } if (strtolower($new_file_name) != strtolower($old_file_name) && self::check_name_exist( $path.'/'.$new_file_name ) ) { return false; } // On a Windows server, it would be better not to do the above check // because it succeeds for some new names resembling the old name. // But on Unix/Linux the check must be done because rename overwrites. chdir($path); $res = rename($old_file_name, $new_file_name) ? $new_file_name : false; chdir($save_dir); return $res; } /** * Moves a file or a directory to an other area * * @author - Hugues Peeters * @param - $source (String) - the path of file or directory to move * @param - $target (String) - the path of the new area * @return - bolean - true if the move succeed * bolean - false otherwise. * @see - move() uses check_name_exist() and copyDirTo() functions */ static function move($source, $target) { if (self::check_name_exist($source)) { $file_name = basename($source); if (self::check_name_exist($target.'/'.$file_name)) { return false; } else { /* File case */ if (is_file($source)) { copy($source, $target.'/'.$file_name); unlink($source); return true; } elseif (is_dir($source)) { /* Directory case */ // Check to not copy the directory inside itself if (ereg('^'.$source.'/', $target.'/')) { // TODO: ereg() function is deprecated in PHP 5.3 return false; } else { self::copyDirTo($source, $target); return true; } } } } else { return false; } } /** * Moves a directory and its content to an other area * * @author - Hugues Peeters * @param - $orig_dir_path (string) - the path of the directory to move * @param - $destination (string) - the path of the new area * @return - no return */ static function copyDirTo($orig_dir_path, $destination, $move = true) { $save_dir = getcwd(); // Extract directory name - create it at destination - update destination trail $dir_name = basename($orig_dir_path); if (is_dir($orig_dir_path)) { mkdir($destination.'/'.$dir_name, api_get_permissions_for_new_directories()); $destination_trail = $destination.'/'.$dir_name; if (is_dir($destination)) { chdir($orig_dir_path); $handle = opendir($orig_dir_path); while ($element = readdir($handle)) { if ($element == '.' || $element == '..') { continue; // Skip the current and parent directories } elseif (is_file($element)) { copy($element, $destination_trail.'/'.$element); if ($move) { unlink($element); } } elseif (is_dir($element)) { $dir_to_copy[] = $orig_dir_path.'/'.$element; } } closedir($handle); if (sizeof($dir_to_copy) > 0) { foreach ($dir_to_copy as $this_dir) { self::copyDirTo($this_dir, $destination_trail, $move); // Recursivity } } if ($move) { rmdir($orig_dir_path); } chdir($save_dir); } } } /* NOTE: These functions batch is used to automatically build HTML forms * with a list of the directories contained on the course Directory. * * From a thechnical point of view, form_dir_lists calls sort_dir wich calls index_dir */ /** * Gets all the directories and subdirectories * contented in a given directory * * @author - Hugues Peeters * @param - path (string) - directory path of the one to index * @return - an array containing the path of all the subdirectories */ static function index_dir($path) { $dir_array = array(); $save_dir = getcwd(); if (is_dir($path)) { chdir($path); $handle = opendir($path); // Reads directory content end record subdirectoies names in $dir_array if ($handle !== false) { while ($element = readdir($handle)) { if ($element == '.' || $element == '..') { continue; } // Skip the current and parent directories if (is_dir($element)) { $dir_array[] = $path.'/'.$element; } } closedir($handle); } // Recursive operation if subdirectories exist $dir_number = sizeof($dir_array); if ($dir_number > 0) { for ($i = 0; $i < $dir_number; $i++) { $sub_dir_array = self::index_dir($dir_array[$i]); // Function recursivity $dir_array = array_merge((array)$dir_array, (array)$sub_dir_array); // Data merge } } } chdir($save_dir); return $dir_array; } /** * Indexes all the directories and subdirectories * contented in a given directory, and sort them alphabetically * * @author - Hugues Peeters * @param - path (string) - directory path of the one to index * @return - an array containing the path of all the subdirectories sorted * false, if there is no directory * @see - index_and_sort_dir uses the index_dir() function */ static function index_and_sort_dir($path) { $dir_list = self::index_dir($path); if ($dir_list) { natsort($dir_list); return $dir_list; } return false; } /** * Extracting extention of a filename * * @returns array * @param string $filename filename */ static function getextension($filename) { $bouts = explode('.', $filename); return array(array_pop($bouts), implode('.', $bouts)); } /** * Calculation size of a directory * * @returns integer size * @param string $path path to size * @param boolean $recursive if true , include subdir in total */ static function dirsize($root, $recursive = true) { $dir = @opendir($root); $size = 0; while ($file = @readdir($dir)) { if (!in_array($file, array('.', '..'))) { if (is_dir($root.'/'.$file)) { $size += $recursive ? dirsize($root.'/'.$file) : 0; } else { $size += @filesize($root.'/'.$file); } } } @closedir($dir); return $size; } /** Returns a list of all directories, except the base dir, of the current course. This function uses recursion. Convention: the parameter $path does not end with a slash. @author Roan Embrechts @version 1.0.1 */ static function list_all_directories($path) { $result_array = array(); if (is_dir($path)) { $save_dir = getcwd(); chdir($path); $handle = opendir($path); while ($element = readdir($handle)) { if ($element == '.' || $element == '..') { continue; } // Skip the current and parent directories if (is_dir($element)) { $dir_array[] = $path.'/'.$element; } } closedir($handle); // Recursive operation if subdirectories exist $dir_number = sizeof($dir_array); if ($dir_number > 0) { for ($i = 0; $i < $dir_number; $i++) { $sub_dir_array = self::list_all_directories($dir_array[$i]); // Function recursivity if (is_array($dir_array) && is_array($sub_dir_array)) { $dir_array = array_merge($dir_array, $sub_dir_array); // Data merge } } } $result_array = $dir_array; chdir($save_dir); } return $result_array; } /** This function receives a list of directories. It returns a list of all files in these directories @author Roan Embrechts @version 1.0 */ function list_all_files($dir_array) { $element_array = array(); if (is_dir($dir_array)) { $save_dir = getcwd(); foreach ($dir_array as $directory) { chdir($directory); $handle = opendir($directory); while ($element = readdir($handle)) { if ($element == '.' || $element == '..' || $element == '.htaccess') { continue; } // Skip the current and parent directories if (!is_dir($element)) { $element_array[] = $directory.'/'.$element; } } closedir($handle); chdir('..'); chdir($save_dir); } } return $element_array; } /** Loads contents of file $filename into memory and returns them as a string. Function kept for compatibility with older PHP versions. Function is binary safe (is needed on Windows) */ static function compat_load_file($file_name) { $buffer = ''; if (file_exists($file_name)) { $fp = fopen($file_name, 'rb'); $buffer = fread($fp, filesize($file_name)); fclose($fp); } return $buffer; } static function choose_image($file_name) { static $type, $image; /* TABLES INITIALISATION */ if (!$type || !$image) { $type['word'] = array('doc', 'dot', 'rtf', 'mcw', 'wps', 'psw', 'docm', 'docx', 'dotm', 'dotx'); $type['web'] = array('htm', 'html', 'htx', 'xml', 'xsl', 'php', 'xhtml'); $type['image'] = array('gif', 'jpg', 'png', 'bmp', 'jpeg', 'tif', 'tiff'); $type['image_vect'] = array('svg', 'svgz'); $type['audio'] = array('wav', 'mid', 'mp2', 'mp3', 'midi', 'sib', 'amr', 'kar', 'oga', 'au', 'wma'); $type['video'] = array( 'mp4', 'mov', 'rm', 'pls', 'mpg', 'mpeg', 'm2v', 'm4v', 'flv', 'f4v', 'avi', 'wmv', 'asf', '3gp', 'ogv', 'ogg', 'ogx', 'webm' ); $type['excel'] = array('xls', 'xlt', 'xls', 'xlt', 'pxl', 'xlsx', 'xlsm', 'xlam', 'xlsb', 'xltm', 'xltx'); $type['compressed'] = array('zip', 'tar', 'rar', 'gz'); $type['code'] = array('js', 'cpp', 'c', 'java', 'phps', 'jsp', 'asp', 'aspx', 'cfm'); $type['acrobat'] = array('pdf'); $type['powerpoint'] = array('ppt', 'pps', 'pptm', 'pptx', 'potm', 'potx', 'ppam', 'ppsm', 'ppsx'); $type['flash'] = array('fla', 'swf'); $type['text'] = array('txt', 'log'); $type['oo_writer'] = array('odt', 'ott', 'sxw', 'stw'); $type['oo_calc'] = array('ods', 'ots', 'sxc', 'stc'); $type['oo_impress'] = array('odp', 'otp', 'sxi', 'sti'); $type['oo_draw'] = array('odg', 'otg', 'sxd', 'std'); $type['epub'] = array('epub'); $type['java'] = array('class', 'jar'); $type['freemind'] = array('mm'); $image['word'] = 'word.gif'; $image['web'] = 'file_html.gif'; $image['image'] = 'file_image.gif'; $image['image_vect'] = 'file_svg.png'; $image['audio'] = 'file_sound.gif'; $image['video'] = 'film.gif'; $image['excel'] = 'excel.gif'; $image['compressed'] = 'file_zip.gif'; $image['code'] = 'icons/22/mime_code.png'; $image['acrobat'] = 'file_pdf.gif'; $image['powerpoint'] = 'powerpoint.gif'; $image['flash'] = 'file_flash.gif'; $image['text'] = 'icons/22/mime_text.png'; $image['oo_writer'] = 'file_oo_writer.gif'; $image['oo_calc'] = 'file_oo_calc.gif'; $image['oo_impress'] = 'file_oo_impress.gif'; $image['oo_draw'] = 'file_oo_draw.gif'; $image['epub'] = 'file_epub.gif'; $image['java'] = 'file_java.png'; $image['freemind'] = 'file_freemind.png'; } /* FUNCTION CORE */ $extension = array(); if (!is_array($file_name)) { if (preg_match('/\.([[:alnum:]]+)(\?|$)/', $file_name, $extension)) { $extension[1] = strtolower($extension[1]); foreach ($type as $generic_type => $extension_list) { if (in_array($extension[1], $extension_list)) { return $image[$generic_type]; } } } } return 'defaut.gif'; } /** * Transform the file path to a URL. * * @param - $file_path (string) - Relative local path of the file on the hard disk * @return - Relative url */ static function format_url($file_path) { $path_component = explode('/', $file_path); $path_component = array_map('rawurlencode', $path_component); return implode('/', $path_component); } /** * Calculates the total size of a directory by adding the sizes (that * are stored in the database) of all files & folders in this directory. * * @param string $path * @param boolean $can_see_invisible * @return Total size */ static function get_total_folder_size($path, $can_see_invisible = false) { $table_itemproperty = Database::get_course_table(TABLE_ITEM_PROPERTY); $table_document = Database::get_course_table(TABLE_DOCUMENT); $tool_document = TOOL_DOCUMENT; $course_id = api_get_course_int_id(); $session_id = api_get_session_id(); $session_condition = api_get_session_condition($session_id, true, true, 'props.id_session'); $visibility_rule = ' props.visibility '.($can_see_invisible ? '<> 2' : '= 1'); $sql = "SELECT SUM(table1.size) FROM ( SELECT size FROM $table_itemproperty AS props, $table_document AS docs WHERE docs.c_id = $course_id AND docs.id = props.ref AND docs.path LIKE '$path/%' AND props.c_id = $course_id AND props.tool = '$tool_document' AND $visibility_rule $session_condition GROUP BY ref ) as table1"; $result = Database::query($sql); if ($result && Database::num_rows($result) != 0) { $row = Database::fetch_row($result); return $row[0] == null ? 0 : $row[0]; } else { return 0; } } /** * Changes the file name extension from .php to .phps * Useful for securing a site. * * @author - Hugues Peeters * @param - file_name (string) name of a file * * @return string the filename phps'ized */ static function php2phps($file_name) { return preg_replace('/\.(php.?|phtml.?)(\.){0,1}.*$/i', '.phps', $file_name); } /** * Renames .htaccess & .HTACCESS to htaccess.txt * * @param string $filename * @return string */ static function htaccess2txt($filename) { return str_replace(array('.htaccess', '.HTACCESS'), array('htaccess.txt', 'htaccess.txt'), $filename); } /** * This function executes our safety precautions * more functions can be added * * @param string $filename * @return string * @see FileManager::php2phps() * @see htaccess2txt() */ static function disable_dangerous_file($filename) { return self::htaccess2txt(self::php2phps($filename)); } /** * This function generates a unique name for a file on a given location. Filenames are changed to name_#.ext * * @param string $path * @param string $name * @return new unique name */ static function unique_name($path, $name) { $ext = substr(strrchr($name, '.'), 0); $name_no_ext = substr($name, 0, strlen($name) - strlen(strstr($name, $ext))); $n = 0; $unique = ''; while (file_exists($path.$name_no_ext.$unique.$ext)) { $unique = '_'.++$n; } return $name_no_ext.$unique.$ext; } /** * Returns the name without extension, used for the title * * @param string $name * @return name without the extension */ static function get_document_title($name) { // If they upload .htaccess... $name = self::disable_dangerous_file($name); $ext = substr(strrchr($name, '.'), 0); return addslashes(substr($name, 0, strlen($name) - strlen(strstr($name, $ext)))); } /** * This function checks if the upload succeeded * * @param array $uploaded_file ($_FILES) * @param bool $show_output * * @return true if upload succeeded */ static function process_uploaded_file($uploaded_file, $show_output = true) { // Checking the error code sent with the file upload. switch ($uploaded_file['error']) { case 1: // The uploaded file exceeds the upload_max_filesize directive in php.ini. if ($show_output) { Display::display_error_message( get_lang('UplExceedMaxServerUpload').ini_get('upload_max_filesize') ); } return false; case 2: // The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form. // Not used at the moment, but could be handy if we want to limit the size of an upload (e.g. image upload in html editor). $max_file_size = intval($_POST['MAX_FILE_SIZE']); if ($show_output) { Display::display_error_message(get_lang('UplExceedMaxPostSize').Text::format_file_size($max_file_size)); } return false; case 3: // The uploaded file was only partially uploaded. if ($show_output) { Display::display_error_message(get_lang('UplPartialUpload').' '.get_lang('PleaseTryAgain')); } return false; case 4: // No file was uploaded. if ($show_output) { Display::display_error_message(get_lang('UplNoFileUploaded').' '.get_lang('UplSelectFileFirst')); } return false; } if (!file_exists($uploaded_file['tmp_name'])) { // No file was uploaded. if ($show_output) { Display::display_error_message(get_lang('UplUploadFailed')); } return false; } if (file_exists($uploaded_file['tmp_name'])) { $filesize = filesize($uploaded_file['tmp_name']); if (empty($filesize)) { // No file was uploaded. if ($show_output) { Display::display_error_message(get_lang('UplUploadFailedSizeIsZero')); } return false; } } $course_id = api_get_course_id(); //Checking course quota if we are in a course if (!empty($course_id)) { $max_filled_space = DocumentManager::get_course_quota(); // Check if there is enough space to save the file if (!DocumentManager::enough_space($uploaded_file['size'], $max_filled_space)) { if ($show_output) { Display::display_error_message(get_lang('UplNotEnoughSpace')); } return false; } } // case 0: default: We assume there is no error, the file uploaded with success. return true; } /** * This function does the save-work for the documents. * It handles the uploaded file and adds the properties to the database * If unzip=1 and the file is a zipfile, it is extracted * If we decide to save ALL kinds of documents in one database, * we could extend this with a $type='document', 'scormdocument',... * * @param array $_course * @param array $uploaded_file ($_FILES) * @param string $base_work_dir * @param string $upload_path * @param int $user_id * @param int $to_group_id, 0 for everybody * @param int $to_user_id, NULL for everybody * @param int $unzip 1/0 * @param string $what_if_file_exists overwrite, rename or warn if exists (default) * @param boolean Optional output parameter. So far only use for unzip_uploaded_document function. If no output wanted on success, set to false. * @return path of the saved file */ static function handle_uploaded_document( $_course, $uploaded_file, $base_work_dir, $upload_path, $user_id, $to_group_id = 0, $to_user_id = null, $unzip = 0, $what_if_file_exists = '', $output = true ) { if (!$user_id) { die('Not a valid user.'); } // Strip slashes $uploaded_file['name'] = stripslashes($uploaded_file['name']); // Add extension to files without one (if possible) $uploaded_file['name'] = self::add_ext_on_mime($uploaded_file['name'], $uploaded_file['type']); $current_session_id = api_get_session_id(); //Just in case process_uploaded_file is not called $max_filled_space = DocumentManager::get_course_quota(); // Check if there is enough space to save the file if (!DocumentManager::enough_space($uploaded_file['size'], $max_filled_space)) { if ($output) { Display::display_error_message(get_lang('UplNotEnoughSpace')); } return false; } // If the want to unzip, check if the file has a .zip (or ZIP,Zip,ZiP,...) extension if ($unzip == 1 && preg_match('/.zip$/', strtolower($uploaded_file['name']))) { return self::unzip_uploaded_document( $uploaded_file, $upload_path, $base_work_dir, $max_filled_space, $output, $to_group_id ); //display_message('Unzipping file'); } elseif ($unzip == 1 && !preg_match( '/.zip$/', strtolower($uploaded_file['name']) ) ) { // We can only unzip ZIP files (no gz, tar,...) if ($output) { Display::display_error_message(get_lang('UplNotAZip')." ".get_lang('PleaseTryAgain')); } return false; } else { // Clean up the name, only ASCII characters should stay. (and strict) $clean_name = api_replace_dangerous_char($uploaded_file['name'], 'strict'); // No "dangerous" files $clean_name = self::disable_dangerous_file($clean_name); if (!self::filter_extension($clean_name)) { if ($output) { Display::display_error_message(get_lang('UplUnableToSaveFileFilteredExtension')); } return false; } else { // Extension is good //echo '
clean name = '.$clean_name; //echo '
upload_path = '.$upload_path; // If the upload path differs from / (= root) it will need a slash at the end if ($upload_path != '/') { $upload_path = $upload_path.'/'; } //echo '
upload_path = '.$upload_path; $file_path = $upload_path.$clean_name; //echo '
file path = '.$file_path; // Full path to where we want to store the file with trailing slash $where_to_save = $base_work_dir.$upload_path; // At least if the directory doesn't exist, tell so if (!is_dir($where_to_save)) { if ($output) { Display::display_error_message(get_lang('DestDirectoryDoesntExist').' ('.$upload_path.')'); } return false; } //echo '
where to save = '.$where_to_save; // Full path of the destination $store_path = $where_to_save.$clean_name; //echo '
store path = '.$store_path; // Name of the document without the extension (for the title) $document_name = self::get_document_title($uploaded_file['name']); // Size of the uploaded file (in bytes) $file_size = $uploaded_file['size']; $files_perm = api_get_permissions_for_new_files(); // What to do if the target file exists switch ($what_if_file_exists) { // Overwrite the file if it exists case 'overwrite': // Check if the target file exists, so we can give another message $file_exists = file_exists($store_path); if (@move_uploaded_file($uploaded_file['tmp_name'], $store_path)) { chmod($store_path, $files_perm); if ($file_exists) { // UPDATE DATABASE $document_id = DocumentManager::get_document_id($_course, $file_path); if (is_numeric($document_id)) { // Update filesize self::update_existing_document($_course, $document_id, $uploaded_file['size']); // Update document item_property api_item_property_update( $_course, TOOL_DOCUMENT, $document_id, 'DocumentUpdated', $user_id, $to_group_id, $to_user_id, null, null, $current_session_id ); //Redo visibility api_set_default_visibility($_course, TOOL_DOCUMENT, $document_id); } // If the file is in a folder, we need to update all parent folders self::item_property_update_on_folder($_course, $upload_path, $user_id); // Display success message with extra info to user if ($output) { Display::display_confirmation_message( get_lang('UplUploadSucceeded').'
'.$file_path.' '.get_lang( 'UplFileOverwritten' ), false ); } return $file_path; } else { // Put the document data in the database $document_id = self::add_document( $_course, $file_path, 'file', $file_size, $document_name, null, 0, true ); if ($document_id) { // Put the document in item_property update api_item_property_update( $_course, TOOL_DOCUMENT, $document_id, 'DocumentAdded', $user_id, $to_group_id, $to_user_id, null, null, $current_session_id ); } // If the file is in a folder, we need to update all parent folders self::item_property_update_on_folder($_course, $upload_path, $user_id); // Display success message to user if ($output) { Display::display_confirmation_message( get_lang('UplUploadSucceeded').'
'.$file_path, false ); } return $file_path; } } else { if ($output) { Display::display_error_message(get_lang('UplUnableToSaveFile')); } return false; } break; // Rename the file if it exists case 'rename': $new_name = unique_name($where_to_save, $clean_name); $store_path = $where_to_save.$new_name; $new_file_path = $upload_path.$new_name; if (@move_uploaded_file($uploaded_file['tmp_name'], $store_path)) { chmod($store_path, $files_perm); // Put the document data in the database $document_id = self::add_document( $_course, $new_file_path, 'file', $file_size, $document_name, null, 0, true ); if ($document_id) { // Update document item_property api_item_property_update( $_course, TOOL_DOCUMENT, $document_id, 'DocumentAdded', $user_id, $to_group_id, $to_user_id, null, null, $current_session_id ); } // If the file is in a folder, we need to update all parent folders self::item_property_update_on_folder($_course, $upload_path, $user_id); // Display success message to user if ($output) { Display::display_confirmation_message( get_lang('UplUploadSucceeded').'
'.get_lang('UplFileSavedAs').$new_file_path, false ); } return $new_file_path; } else { if ($output) { Display::display_error_message(get_lang('UplUnableToSaveFile')); } return false; } break; // Only save the file if it doesn't exist or warn user if it does exist default: if (file_exists($store_path)) { if ($output) { Display::display_error_message($clean_name.' '.get_lang('UplAlreadyExists')); } } else { if (@move_uploaded_file($uploaded_file['tmp_name'], $store_path)) { chmod($store_path, $files_perm); // Put the document data in the database $document_id = self::add_document( $_course, $file_path, 'file', $file_size, $document_name, null, 0, true ); if ($document_id) { // Update document item_property api_item_property_update( $_course, TOOL_DOCUMENT, $document_id, 'DocumentAdded', $user_id, $to_group_id, $to_user_id, null, null, $current_session_id ); } // If the file is in a folder, we need to update all parent folders self::item_property_update_on_folder($_course, $upload_path, $user_id); // Display success message to user if ($output) { Display::display_confirmation_message( get_lang('UplUploadSucceeded').'
'.$file_path, false ); } return $file_path; } else { if ($output) { Display::display_error_message(get_lang('UplUnableToSaveFile')); } return false; } } break; } } } } /** * Checks if there is enough place to add a file on a directory * on the base of a maximum directory size allowed * deprecated: use enough_space instead! * @author - Hugues Peeters * @param - file_size (int) - size of the file in byte * @param - dir (string) - Path of the directory * whe the file should be added * @param - max_dir_space (int) - maximum size of the diretory in byte * @return - boolean true if there is enough space, * boolean false otherwise * * @see - enough_size() uses dir_total_space() function */ static function enough_size($file_size, $dir, $max_dir_space) { if ($max_dir_space) { $already_filled_space = self::dir_total_space($dir); if (($file_size + $already_filled_space) > $max_dir_space) { return false; } } return true; } /** * Computes the size already occupied by a directory and is subdirectories * * @param string dir_path (string) - size of the file in byte * @return int - return the directory size in bytes */ static function dir_total_space($dir_path) { $fs = new Filesystem(); if (!empty($dir_path) && $fs->exists($dir_path)) { $finder = new Finder(); $finder->files()->in($dir_path); $sumSize = 0; foreach ($finder as $file) { // Print the absolute path //var_dump($file->getRelativePathname()); $sumSize += $file->getSize(); } return $sumSize; } return 0; /* // author - Hugues Peeters $save_dir = getcwd(); chdir($dir_path); $handle = opendir($dir_path); $sumSize = 0; $dirList = array(); while ($element = readdir($handle)) { if ($element == '.' || $element == '..') { continue; // Skip the current and parent directories } if (is_file($element)) { $sumSize += filesize($element); } if (is_dir($element)) { $dirList[] = $dir_path.'/'.$element; } } closedir($handle); if (sizeof($dirList) > 0) { foreach ($dirList as $j) { $sizeDir = self::dir_total_space($j, 0); // Recursivity $sumSize += $sizeDir; } } chdir($save_dir); // Return to initial position return $sumSize;*/ } /** * Tries to add an extension to files without extension * Some applications on Macintosh computers don't add an extension to the files. * This subroutine try to fix this on the basis of the MIME type sent * by the browser. * * Note : some browsers don't send the MIME Type (e.g. Netscape 4). * We don't have solution for this kind of situation * * @author - Hugues Peeters * @author - Bert Vanderkimpen * @param - file_name (string) - Name of the file * @param - file_type (string) - Type of the file * @return - file_name (string) */ static function add_ext_on_mime($file_name, $file_type) { // Check whether the file has an extension AND whether the browser has sent a MIME Type if (!preg_match('/^.*\.[a-zA-Z_0-9]+$/', $file_name) && $file_type) { // Build a "MIME-types / extensions" connection table static $mime_type = array(); $mime_type[] = 'application/msword'; $extension[] = '.doc'; $mime_type[] = 'application/rtf'; $extension[] = '.rtf'; $mime_type[] = 'application/vnd.ms-powerpoint'; $extension[] = '.ppt'; $mime_type[] = 'application/vnd.ms-excel'; $extension[] = '.xls'; $mime_type[] = 'application/pdf'; $extension[] = '.pdf'; $mime_type[] = 'application/postscript'; $extension[] = '.ps'; $mime_type[] = 'application/mac-binhex40'; $extension[] = '.hqx'; $mime_type[] = 'application/x-gzip'; $extension[] = 'tar.gz'; $mime_type[] = 'application/x-shockwave-flash'; $extension[] = '.swf'; $mime_type[] = 'application/x-stuffit'; $extension[] = '.sit'; $mime_type[] = 'application/x-tar'; $extension[] = '.tar'; $mime_type[] = 'application/zip'; $extension[] = '.zip'; $mime_type[] = 'application/x-tar'; $extension[] = '.tar'; $mime_type[] = 'text/html'; $extension[] = '.html'; $mime_type[] = 'text/plain'; $extension[] = '.txt'; $mime_type[] = 'text/rtf'; $extension[] = '.rtf'; $mime_type[] = 'img/gif'; $extension[] = '.gif'; $mime_type[] = 'img/jpeg'; $extension[] = '.jpg'; $mime_type[] = 'img/png'; $extension[] = '.png'; $mime_type[] = 'audio/midi'; $extension[] = '.mid'; $mime_type[] = 'audio/mpeg'; $extension[] = '.mp3'; $mime_type[] = 'audio/x-aiff'; $extension[] = '.aif'; $mime_type[] = 'audio/x-pn-realaudio'; $extension[] = '.rm'; $mime_type[] = 'audio/x-pn-realaudio-plugin'; $extension[] = '.rpm'; $mime_type[] = 'audio/x-wav'; $extension[] = '.wav'; $mime_type[] = 'video/mpeg'; $extension[] = '.mpg'; $mime_type[] = 'video/mpeg4-generic'; $extension[] = '.mp4'; $mime_type[] = 'video/quicktime'; $extension[] = '.mov'; $mime_type[] = 'video/x-msvideo'; $extension[] = '.avi'; $mime_type[] = 'video/x-ms-wmv'; $extension[] = '.wmv'; $mime_type[] = 'video/x-flv'; $extension[] = '.flv'; $mime_type[] = 'image/svg+xml'; $extension[] = '.svg'; $mime_type[] = 'image/svg+xml'; $extension[] = '.svgz'; $mime_type[] = 'video/ogg'; $extension[] = '.ogv'; $mime_type[] = 'audio/ogg'; $extension[] = '.oga'; $mime_type[] = 'application/ogg'; $extension[] = '.ogg'; $mime_type[] = 'application/ogg'; $extension[] = '.ogx'; $mime_type[] = 'application/x-freemind'; $extension[] = '.mm'; $mime_type[] = 'application/vnd.ms-word.document.macroEnabled.12'; $extension[] = '.docm'; $mime_type[] = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; $extension[] = '.docx'; $mime_type[] = 'application/vnd.ms-word.template.macroEnabled.12'; $extension[] = '.dotm'; $mime_type[] = 'application/vnd.openxmlformats-officedocument.wordprocessingml.template'; $extension[] = '.dotx'; $mime_type[] = 'application/vnd.ms-powerpoint.template.macroEnabled.12'; $extension[] = '.potm'; $mime_type[] = 'application/vnd.openxmlformats-officedocument.presentationml.template'; $extension[] = '.potx'; $mime_type[] = 'application/vnd.ms-powerpoint.addin.macroEnabled.12'; $extension[] = '.ppam'; $mime_type[] = 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12'; $extension[] = '.ppsm'; $mime_type[] = 'application/vnd.openxmlformats-officedocument.presentationml.slideshow'; $extension[] = '.ppsx'; $mime_type[] = 'application/vnd.ms-powerpoint.presentation.macroEnabled.12'; $extension[] = '.pptm'; $mime_type[] = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'; $extension[] = '.pptx'; $mime_type[] = 'application/vnd.ms-excel.addin.macroEnabled.12'; $extension[] = '.xlam'; $mime_type[] = 'application/vnd.ms-excel.sheet.binary.macroEnabled.12'; $extension[] = '.xlsb'; $mime_type[] = 'application/vnd.ms-excel.sheet.macroEnabled.12'; $extension[] = '.xlsm'; $mime_type[] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; $extension[] = '.xlsx'; $mime_type[] = 'application/vnd.ms-excel.template.macroEnabled.12'; $extension[] = '.xltm'; $mime_type[] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.template'; $extension[] = '.xltx'; // Test on PC (files with no extension get application/octet-stream) //$mime_type[] = 'application/octet-stream'; $extension[] = '.ext'; // Check whether the MIME type sent by the browser is within the table foreach ($mime_type as $key => & $type) { if ($type == $file_type) { $file_name .= $extension[$key]; break; } } unset($mime_type, $extension, $type, $key); // Delete to eschew possible collisions } return $file_name; } /** * Manages all the unzipping process of an uploaded document * This uses the item_property table for properties of documents * * @author Hugues Peeters * @author Bert Vanderkimpen * * @param array $uploaded_file - follows the $_FILES Structure * @param string $upload_path - destination of the upload. * This path is to append to $base_work_dir * @param string $base_work_dir - base working directory of the module * @param int $max_filled_space - amount of bytes to not exceed in the base * working directory * @param boolean Output switch. Optional. If no output not wanted on success, set to false. * * @return boolean true if it succeeds false otherwise */ static function unzip_uploaded_document( $uploaded_file, $upload_path, $base_work_dir, $max_filled_space, $output = true, $to_group_id = 0 ) { $_course = api_get_course_info(); global $_user; global $to_user_id; global $to_group_id; $zip_file = new PclZip($uploaded_file['tmp_name']); // Check the zip content (real size and file extension) $zip_content_array = (array)$zip_file->listContent(); $real_filesize = 0; foreach ($zip_content_array as & $this_content) { $real_filesize += $this_content['size']; } if (!DocumentManager::enough_space($real_filesize, $max_filled_space)) { Display::display_error_message(get_lang('UplNotEnoughSpace')); return false; } // It happens on Linux that $upload_path sometimes doesn't start with '/' if ($upload_path[0] != '/') { $upload_path = '/'.$upload_path; } /* Uncompressing phase */ // Get into the right directory $save_dir = getcwd(); chdir($base_work_dir.$upload_path); // We extract using a callback function that "cleans" the path //@todo check if this works $unzipping_state = $zip_file->extract( PCLZIP_CB_PRE_EXTRACT, 'FileManager::clean_up_files_in_zip', PCLZIP_OPT_REPLACE_NEWER ); // Add all documents in the unzipped folder to the database self::add_all_documents_in_folder_to_database( $_course, $_user['user_id'], $base_work_dir, $upload_path == '/' ? '' : $upload_path, $to_group_id ); //Display::display_normal_message(get_lang('UplZipExtractSuccess')); return true; } /** * This function is a callback function that is used while extracting a zipfile * http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_cb_pre_extract * * @param $p_event * @param $p_header * @return 1 (If the function returns 1, then the extraction is resumed) */ function clean_up_files_in_zip($p_event, &$p_header) { $res = self::clean_up_path($p_header['filename']); return $res; } /** * This function cleans up a given path * by eliminating dangerous file names and cleaning them * * @param string $path * @return $path * @see FileManager::disable_dangerous_file() * @see replace_dangerous_char() */ static function clean_up_path(&$path) { // Split the path in folders and files $path_array = explode('/', $path); // Clean up every foler and filename in the path foreach ($path_array as $key => & $val) { // We don't want to lose the dots in ././folder/file (cfr. zipfile) if ($val != '.') { $val = self::disable_dangerous_file(api_replace_dangerous_char($val)); } } // Join the "cleaned" path (modified in-place as passed by reference) $path = implode('/', $path_array); $res = self::filter_extension($path); return $res; } /** * Checks if the file is dangerous, based on extension and/or mimetype. * The list of extensions accepted/rejected can be found from * api_get_setting('upload_extensions_exclude') and api_get_setting('upload_extensions_include') * @param string filename passed by reference. The filename will be modified if filter rules say so! (you can include path but the filename should look like 'abc.html') * @return int 0 to skip file, 1 to keep file */ static function filter_extension(&$filename) { if (substr($filename, -1) == '/') { return 1; // Authorize directories } $blacklist = api_get_setting('upload_extensions_list_type'); if ($blacklist != 'whitelist') { // if = blacklist $extensions = explode(';', strtolower(api_get_setting('upload_extensions_blacklist'))); $skip = api_get_setting('upload_extensions_skip'); $ext = strrchr($filename, '.'); $ext = substr($ext, 1); if (empty($ext)) { return 1; // We're in blacklist mode, so accept empty extensions } if (in_array(strtolower($ext), $extensions)) { if ($skip == 'true') { return 0; } else { $new_ext = api_get_setting('upload_extensions_replace_by'); $filename = str_replace('.'.$ext, '.'.$new_ext, $filename); return 1; } } else { return 1; } } else { $extensions = split(';', strtolower(api_get_setting('upload_extensions_whitelist'))); $skip = api_get_setting('upload_extensions_skip'); $ext = strrchr($filename, '.'); $ext = substr($ext, 1); if (empty($ext)) { return 1; // Accept empty extensions } if (!in_array(strtolower($ext), $extensions)) { if ($skip == 'true') { return 0; } else { $new_ext = api_get_setting('upload_extensions_replace_by'); $filename = str_replace('.'.$ext, '.'.$new_ext, $filename); return 1; } } else { return 1; } } } /** * Adds a new document to the database * * @param array $_course * @param string $path * @param string $filetype * @param int $filesize * @param string $title * * @return id if inserted document */ static function add_document( $_course, $path, $filetype, $filesize, $title, $comment = null, $readonly = 0, $save_visibility = true, $group_id = null ) { $session_id = api_get_session_id(); $readonly = intval($readonly); $comment = Database::escape_string($comment); $path = Database::escape_string($path); $filetype = Database::escape_string($filetype); $filesize = intval($filesize); $title = Database::escape_string(htmlspecialchars($title)); $c_id = $_course['real_id']; $table_document = Database::get_course_table(TABLE_DOCUMENT); $sql = "INSERT INTO $table_document (c_id, path, filetype, size, title, comment, readonly, session_id) VALUES ($c_id, '$path','$filetype','$filesize','$title', '$comment', $readonly, $session_id)"; if (Database::query($sql)) { $document_id = Database::insert_id(); if ($document_id) { if ($save_visibility) { api_set_default_visibility($_course, $document_id, TOOL_DOCUMENT, $group_id); } } return $document_id; } else { return false; } } /** * Updates an existing document in the database * as the file exists, we only need to change the size * * @param array $_course * @param int $document_id * @param int $filesize * @param int $readonly * * @return boolean true /false */ static function update_existing_document($_course, $document_id, $filesize, $readonly = 0) { $document_table = Database::get_course_table(TABLE_DOCUMENT); $document_id = intval($document_id); $filesize = intval($filesize); $readonly = intval($readonly); $course_id = $_course['real_id']; $sql = "UPDATE $document_table SET size = '$filesize' , readonly = '$readonly' WHERE c_id = $course_id AND id = $document_id"; if (Database::query($sql)) { return true; } else { return false; } } /** * This function updates the last_edit_date, last edit user id on all folders in a given path * * @param array $_course * @param string $path * @param int $user_id */ static function item_property_update_on_folder($_course, $path, $user_id) { //display_message("Start update_lastedit_on_folder"); // If we are in the root, just return... no need to update anything if ($path == '/') { return; } $user_id = intval($user_id); // If the given path ends with a / we remove it $endchar = substr($path, strlen($path) - 1, 1); if ($endchar == '/') { $path = substr($path, 0, strlen($path) - 1); } $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY); // Get the time $time = date('Y-m-d H:i:s', time()); // Det all paths in the given path // /folder/subfolder/subsubfolder/file // if file is updated, subsubfolder, subfolder and folder are updated $exploded_path = explode('/', $path); $course_id = api_get_course_int_id(); foreach ($exploded_path as $key => & $value) { // We don't want a slash before our first slash if ($key != 0) { $newpath .= '/'.$value; //echo 'path= '.$newpath.'
'; // Select ID of given folder $folder_id = DocumentManager::get_document_id($_course, $newpath); if ($folder_id) { $sql = "UPDATE $TABLE_ITEMPROPERTY SET lastedit_date='$time',lastedit_type='DocumentInFolderUpdated', lastedit_user_id='$user_id' WHERE c_id = $course_id AND tool='".TOOL_DOCUMENT."' AND ref='$folder_id'"; Database::query($sql); } } } } /** * Returns the directory depth of the file. * * @author Olivier Cauberghe * @param path+filename eg: /main/document/document.php * @return The directory depth */ static function get_levels($filename) { $levels = explode('/', $filename); if (empty($levels[count($levels) - 1])) { unset($levels[count($levels) - 1]); } return count($levels); } /** * Retrieves the image path list in a html file * * @author Hugues Peeters * @param string $html_file * @return array - images path list */ static function search_img_from_html($html_file) { $img_path_list = array(); if (!$fp = fopen($html_file, 'r')) { return; } // Aearch and store occurences of the tag in an array $size_file = (filesize($html_file) === 0) ? 1 : filesize($html_file); if (isset($fp) && $fp !== false) { $buffer = fread($fp, $size_file); if (strlen($buffer) >= 0 && $buffer !== false) { // } else { die('
Can not read file.
'); } } else { die('
Can not read file.
'); } $matches = array(); if (preg_match_all('~<[[:space:]]*img[^>]*>~i', $buffer, $matches)) { $img_tag_list = $matches[0]; } fclose($fp); unset($buffer); // Search the image file path from all the tag detected if (sizeof($img_tag_list) > 0) { foreach ($img_tag_list as & $this_img_tag) { if (preg_match('~src[[:space:]]*=[[:space:]]*[\"]{1}([^\"]+)[\"]{1}~i', $this_img_tag, $matches)) { $img_path_list[] = $matches[1]; } } $img_path_list = array_unique($img_path_list); // Remove duplicate entries } return $img_path_list; } /** * Creates a new directory trying to find a directory name * that doesn't already exist * (we could use unique_name() here...) * * @author Hugues Peeters * @author Bert Vanderkimpen * @param array $_course current course information * @param int $user_id current user id * @param string $desiredDirName complete path of the desired name * @param string The visible name of the directory * @param int Visibility (0 for invisible, 1 for visible, 2 for deleted) * @return string actual directory name if it succeeds, * boolean false otherwise */ static function create_unexisting_directory( $_course, $user_id, $session_id, $to_group_id, $to_user_id, $base_work_dir, $desired_dir_name, $title = null, $visibility = '' ) { $nb = ''; // add numerical suffix to directory if another one of the same number already exists while (file_exists($base_work_dir.$desired_dir_name.$nb)) { $nb += 1; } if ($title == null) { $title = basename($desired_dir_name); } $course_id = $_course['real_id']; if (mkdir($base_work_dir.$desired_dir_name.$nb, api_get_permissions_for_new_directories(), true)) { // Check if pathname already exists inside document table $tbl_document = Database::get_course_table(TABLE_DOCUMENT); $sql = "SELECT path FROM $tbl_document WHERE c_id = $course_id AND path='".$desired_dir_name.$nb."'"; $rs = Database::query($sql); if (Database::num_rows($rs) == 0) { $document_id = self::add_document( $_course, $desired_dir_name.$nb, 'folder', 0, $title, null, 0, true, $to_group_id ); if ($document_id) { // Update document item_property if ($visibility !== '') { $visibilities = array(0 => 'invisible', 1 => 'visible', 2 => 'delete'); api_item_property_update( $_course, TOOL_DOCUMENT, $document_id, $visibilities[$visibility], $user_id, $to_group_id, $to_user_id, null, null, $session_id ); } else { api_item_property_update( $_course, TOOL_DOCUMENT, $document_id, 'FolderCreated', $user_id, $to_group_id, $to_user_id, null, null, $session_id ); } return $desired_dir_name.$nb; } } else { //This means the folder NOT exist in the filesystem (now this was created) but there is a record in the Database return $desired_dir_name.$nb; } } else { return false; } } /** * Handles uploaded missing images * * @author Hugues Peeters * @author Bert Vanderkimpen * @param array $_course * @param array $uploaded_file_collection - follows the $_FILES Structure * @param string $base_work_dir * @param string $missing_files_dir * @param int $user_id * @param int $max_filled_space */ static function move_uploaded_file_collection_into_directory( $_course, $uploaded_file_collection, $base_work_dir, $missing_files_dir, $user_id, $to_group_id, $to_user_id, $max_filled_space ) { $number_of_uploaded_images = count($uploaded_file_collection['name']); for ($i = 0; $i < $number_of_uploaded_images; $i++) { $missing_file['name'] = $uploaded_file_collection['name'][$i]; $missing_file['type'] = $uploaded_file_collection['type'][$i]; $missing_file['tmp_name'] = $uploaded_file_collection['tmp_name'][$i]; $missing_file['error'] = $uploaded_file_collection['error'][$i]; $missing_file['size'] = $uploaded_file_collection['size'][$i]; $upload_ok = self::process_uploaded_file($missing_file); if ($upload_ok) { $new_file_list[] = self::handle_uploaded_document( $_course, $missing_file, $base_work_dir, $missing_files_dir, $user_id, $to_group_id, $to_user_id, $max_filled_space, 0, 'overwrite' ); } unset($missing_file); } return $new_file_list; } /** * Opens the old html file and replace the src path into the img tag * This also works for files in subdirectories. * @param $original_img_path is an array * @param $new_img_path is an array */ static function replace_img_path_in_html_file($original_img_path, $new_img_path, $html_file) { // Open the file $fp = fopen($html_file, 'r'); $buffer = fread($fp, filesize($html_file)); $new_html_content = null; // Fix the image tags for ($i = 0, $fileNb = count($original_img_path); $i < $fileNb; $i++) { $replace_what = $original_img_path[$i]; // We only need the directory and the filename /path/to/file_html_files/missing_file.gif -> file_html_files/missing_file.gif $exploded_file_path = explode('/', $new_img_path[$i]); $replace_by = $exploded_file_path[count($exploded_file_path) - 2].'/'.$exploded_file_path[count( $exploded_file_path ) - 1]; $buffer = str_replace($replace_what, $replace_by, $buffer); } $new_html_content .= $buffer; @fclose($fp); // Write the resulted new file if (!$fp = fopen($html_file, 'w')) { return; } if (!fwrite($fp, $new_html_content)) { return; } } /** * Checks the extension of a file, if it's .htm or .html * we use search_img_from_html to get all image paths in the file * * @param string $file * @return array paths * @see check_for_missing_files() uses search_img_from_html() */ static function check_for_missing_files($file) { if (strrchr($file, '.') == '.htm' || strrchr($file, '.') == '.html') { $img_file_path = self::search_img_from_html($file); return $img_file_path; } return false; } /** * This function builds a form that asks for the missing images in a html file * maybe we should do this another way? * * @param array $missing_files * @param string $upload_path * @param string $file_name * @return string the form */ static function build_missing_files_form($missing_files, $upload_path, $file_name) { // Do we need a / or not? $added_slash = ($upload_path == '/') ? '' : '/'; $folder_id = DocumentManager::get_document_id(api_get_course_info(), $upload_path); // Build the form $form = "

".get_lang('MissingImagesDetected')."

" ."
" // Related_file is the path to the file that has missing images ."" ."" ."" .""; foreach ($missing_files as & $this_img_file_path) { $form .= "" ."" ."" .""; } $form .= "
".basename($this_img_file_path)." : " ."" ."" ."
" ."" ."" ."
"; return $form; } /** * This recursive function can be used during the upgrade process form older versions of Chamilo * It crawls the given directory, checks if the file is in the DB and adds it if it's not * * @param string $base_work_dir * @param string $current_path, needed for recursivity */ static function add_all_documents_in_folder_to_database( $_course, $user_id, $base_work_dir, $current_path = '', $to_group_id = 0 ) { $current_session_id = api_get_session_id(); $path = $base_work_dir.$current_path; // Open dir $handle = opendir($path); if (is_dir($path)) { // Run trough while ($file = readdir($handle)) { if ($file == '.' || $file == '..') { continue; } $completepath = "$path/$file"; // Directory? if (is_dir($completepath)) { $title = self::get_document_title($file); $safe_file = api_replace_dangerous_char($file); @rename($path.'/'.$file, $path.'/'.$safe_file); // If we can't find the file, add it if (!DocumentManager::get_document_id($_course, $current_path.'/'.$safe_file)) { $document_id = self::add_document($_course, $current_path.'/'.$safe_file, 'folder', 0, $title); api_item_property_update( $_course, TOOL_DOCUMENT, $document_id, 'DocumentAdded', $user_id, $to_group_id, null, null, null, $current_session_id ); //echo $current_path.'/'.$safe_file.' added!
'; } // Recursive self::add_all_documents_in_folder_to_database( $_course, $user_id, $base_work_dir, $current_path.'/'.$safe_file, $to_group_id ); } else { //Rename $safe_file = self::disable_dangerous_file(api_replace_dangerous_char($file, 'strict')); @rename($base_work_dir.$current_path.'/'.$file, $base_work_dir.$current_path.'/'.$safe_file); $document_id = DocumentManager::get_document_id($_course, $current_path.'/'.$safe_file); if (!$document_id) { $title = self::get_document_title($file); $size = filesize($base_work_dir.$current_path.'/'.$safe_file); $document_id = self::add_document( $_course, $current_path.'/'.$safe_file, 'file', $size, $title ); api_item_property_update( $_course, TOOL_DOCUMENT, $document_id, 'DocumentAdded', $user_id, $to_group_id, null, null, null, $current_session_id ); //echo $current_path.'/'.$safe_file.' added!
'; } else { api_item_property_update( $_course, TOOL_DOCUMENT, $document_id, 'DocumentUpdated', $user_id, $to_group_id, null, null, null, $current_session_id ); } } } } } }