From 9fb4257162426ea14b35cd89bf76f233a7e7950b Mon Sep 17 00:00:00 2001 From: Julio Montoya Date: Fri, 4 Mar 2011 19:31:03 +0100 Subject: [PATCH] Adding jquery multiple uploader script for documents see #2784 (need to be more preatty) the pbar.ani.gif is also very big 250kb need to be replaced --- main/document/upload.php | 339 ++-------- main/inc/ajax/document.ajax.php | 16 + main/inc/lib/document.lib.php | 274 ++++++++ main/inc/lib/fileUpload.lib.php | 32 +- .../lib/javascript/jquery-upload/README.txt | 61 ++ .../jquery-upload/jquery.fileupload-ui.css | 74 +++ .../jquery-upload/jquery.fileupload-ui.js | 308 +++++++++ .../jquery-upload/jquery.fileupload.js | 629 ++++++++++++++++++ .../lib/javascript/jquery-upload/pbar-ani.gif | Bin 0 -> 304064 bytes main/inc/lib/main_api.lib.php | 10 +- 10 files changed, 1451 insertions(+), 292 deletions(-) create mode 100644 main/inc/ajax/document.ajax.php create mode 100644 main/inc/lib/javascript/jquery-upload/README.txt create mode 100644 main/inc/lib/javascript/jquery-upload/jquery.fileupload-ui.css create mode 100644 main/inc/lib/javascript/jquery-upload/jquery.fileupload-ui.js create mode 100644 main/inc/lib/javascript/jquery-upload/jquery.fileupload.js create mode 100644 main/inc/lib/javascript/jquery-upload/pbar-ani.gif diff --git a/main/document/upload.php b/main/document/upload.php index e85c99eb67..f57cdb450a 100755 --- a/main/document/upload.php +++ b/main/document/upload.php @@ -40,14 +40,13 @@ $language_file = array('document','gradebook'); require_once '../inc/global.inc.php'; // Including additional libraries -require_once api_get_path(LIBRARY_PATH).'fileUpload.lib.php'; require_once api_get_path(LIBRARY_PATH).'document.lib.php'; require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php'; require_once api_get_path(LIBRARY_PATH).'formvalidator/FormValidator.class.php'; require_once 'document.inc.php'; // Adding extra javascript to the form -$htmlHeadXtra[] = ''; +$htmlHeadXtra[] = api_get_jquery_libraries_js(array('jquery-ui', 'jquery-upload')); $htmlHeadXtra[] = ''; -/** - * Obtains the text inside the file with the right parser - */ -function get_text_content($doc_path, $doc_mime) { - // TODO: review w$ compatibility - - // Use usual exec output lines array to store stdout instead of a temp file - // because we need to store it at RAM anyway before index on DokeosIndexer object - $ret_val = null; - switch ($doc_mime) { - case 'text/plain': - $handle = fopen($doc_path, 'r'); - $output = array(fread($handle, filesize($doc_path))); - fclose($handle); - break; - case 'application/pdf': - exec("pdftotext $doc_path -", $output, $ret_val); - break; - case 'application/postscript': - $temp_file = tempnam(sys_get_temp_dir(), 'chamilo'); - exec("ps2pdf $doc_path $temp_file", $output, $ret_val); - if ($ret_val !== 0) { // shell fail, probably 127 (command not found) - return false; - } - exec("pdftotext $temp_file -", $output, $ret_val); - unlink($temp_file); - //var_dump($output); - break; - case 'application/msword': - exec("catdoc $doc_path", $output, $ret_val); - //var_dump($output); - break; - case 'text/html': - exec("html2text $doc_path", $output, $ret_val); - break; - case 'text/rtf': - // Note: correct handling of code pages in unrtf - // on debian lenny unrtf v0.19.2 can not, but unrtf v0.20.5 can - exec("unrtf --text $doc_path", $output, $ret_val); - if ($ret_val == 127) { // command not found - return false; - } - // Avoid index unrtf comments - if (is_array($output) && count($output) > 1) { - $parsed_output = array(); - foreach ($output as & $line) { - if (!preg_match('/^###/', $line, $matches)) { - if (!empty($line)) { - $parsed_output[] = $line; - } - } - } - $output = $parsed_output; - } - break; - case 'application/vnd.ms-powerpoint': - exec("catppt $doc_path", $output, $ret_val); - break; - case 'application/vnd.ms-excel': - exec("xls2csv -c\" \" $doc_path", $output, $ret_val); - break; - } - - $content = ''; - if (!is_null($ret_val)) { - if ($ret_val !== 0) { // shell fail, probably 127 (command not found) - return false; - } - } - if (isset($output)) { - foreach ($output as & $line) { - $content .= $line."\n"; - } - return $content; - } - else { - return false; - } -} +$htmlHeadXtra[] = " +"; // Variables @@ -184,17 +124,17 @@ if (!DocumentManager::get_document_id($_course, $path)) { } // This needs cleaning! -if (isset($_SESSION['_gid']) && $_SESSION['_gid'] != '') { // If the group id is set, check if the user has the right to be here +if (api_get_group_id()) { // If the group id is set, check if the user has the right to be here // Needed for group related stuff require_once api_get_path(LIBRARY_PATH).'groupmanager.lib.php'; // Get group info - $group_properties = GroupManager::get_group_properties($_SESSION['_gid']); + $group_properties = GroupManager::get_group_properties(api_get_group_id()); $noPHP_SELF = true; - if ($is_allowed_to_edit || GroupManager::is_user_in_group($_user['user_id'], $_SESSION['_gid'])) { // Only courseadmin or group members allowed - $to_group_id = $_SESSION['_gid']; - $req_gid = '&gidReq='.$_SESSION['_gid']; - $interbreadcrumb[] = array('url' => '../group/group_space.php?gidReq='.$_SESSION['_gid'], 'name' => get_lang('GroupSpace')); + if ($is_allowed_to_edit || GroupManager::is_user_in_group($_user['user_id'], api_get_group_id())) { // Only courseadmin or group members allowed + $to_group_id = api_get_group_id(); + $req_gid = '&gidReq='.api_get_group_id(); + $interbreadcrumb[] = array('url' => '../group/group_space.php?gidReq='.api_get_group_id(), 'name' => get_lang('GroupSpace')); } else { api_not_allowed(true); } @@ -218,13 +158,8 @@ if ($is_certificate_array[0] == 'certificates') { $is_certificate_mode = true; } -// If we want to unzip a file, we need the library -if (isset($_POST['unzip']) && $_POST['unzip'] == 1) { - require_once api_get_path(LIBRARY_PATH).'pclzip/pclzip.lib.php'; -} - // Variables -$max_filled_space = DocumentManager::get_course_quota(); +//$max_filled_space = DocumentManager::get_course_quota(); // Title of the tool if ($to_group_id != 0) { // Add group name after for group documents @@ -243,6 +178,7 @@ if ($is_certificate_mode) { $interbreadcrumb[] = array('url' => './document.php?curdirpath='.urlencode($path).$req_gid, 'name'=> get_lang('Documents')); } + $this_section = SECTION_COURSES; // Display the header @@ -251,182 +187,12 @@ Display::display_header($nameTools, 'Doc'); /* Here we do all the work */ // User has submitted a file -if (isset($_FILES['user_upload'])) { - //echo('
');
-	//print_r($_FILES['user_upload']);
-	//echo('
'); - - $upload_ok = process_uploaded_file($_FILES['user_upload']); - if ($upload_ok) { - // File got on the server without problems, now process it - $new_path = handle_uploaded_document($_course, $_FILES['user_upload'], $base_work_dir, $_POST['curdirpath'], $_user['user_id'], $to_group_id, $to_user_id, $max_filled_space, $_POST['unzip'], $_POST['if_exists']); - - $new_comment = isset($_POST['comment']) ? trim($_POST['comment']) : ''; - $new_title = isset($_POST['title']) ? trim($_POST['title']) : ''; - - if ($new_path && ($new_comment || $new_title)) { - if (($docid = DocumentManager::get_document_id($_course, $new_path))) { - $table_document = Database::get_course_table(TABLE_DOCUMENT); - $ct = ''; - if ($new_comment) $ct .= ", comment='$new_comment'"; - if ($new_title) $ct .= ", title='$new_title'"; - Database::query("UPDATE $table_document SET".substr($ct, 1)." WHERE id = '$docid'"); - } - } - // Showing message when sending zip files - if ($new_path === true && $_POST['unzip'] == 1) { - Display::display_confirmation_message(get_lang('UplUploadSucceeded').'
', false); - } - - if ((api_get_setting('search_enabled') == 'true') && ($docid = DocumentManager::get_document_id($_course, $new_path))) { - $table_document = Database::get_course_table(TABLE_DOCUMENT); - $result = Database::query("SELECT * FROM $table_document WHERE id = '$docid' LIMIT 1"); - if (Database::num_rows($result) == 1) { - $row = Database::fetch_array($result); - $doc_path = api_get_path(SYS_COURSE_PATH).$courseDir.$row['path']; - //TODO: mime_content_type is deprecated, fileinfo php extension is enabled by default as of PHP 5.3.0 - // now versions of PHP on Debian testing(5.2.6-5) and Ubuntu(5.2.6-2ubuntu) are lower, so wait for a while - $doc_mime = mime_content_type($doc_path); - //echo $doc_mime; - //TODO: more mime types - $allowed_mime_types = array('text/plain', 'application/pdf', 'application/postscript', 'application/msword', 'text/html', 'text/rtf', 'application/vnd.ms-powerpoint', 'application/vnd.ms-excel'); - - // mime_content_type does not detect correctly some formats that are going to be supported for index, so an extensions array is used by the moment - if (empty($doc_mime)) { - $allowed_extensions = array('ppt', 'pps', 'xls'); - $extensions = preg_split("/[\/\\.]/", $doc_path) ; - $doc_ext = strtolower($extensions[count($extensions) - 1]); - if (in_array($doc_ext, $allowed_extensions)) { - switch ($doc_ext) { - case 'ppt': - case 'pps': - $doc_mime = 'application/vnd.ms-powerpoint'; - break; - case 'xls': - $doc_mime = 'application/vnd.ms-excel'; - break; - } - } - } - - if (in_array($doc_mime, $allowed_mime_types) && isset($_POST['index_document']) && $_POST['index_document']) { - $file_title = $row['title']; - $file_content = get_text_content($doc_path, $doc_mime); - $courseid = api_get_course_id(); - $lang = isset($_POST['language']) ? Database::escape_string($_POST['language']) : 'english'; - - require_once api_get_path(LIBRARY_PATH).'search/DokeosIndexer.class.php'; - require_once api_get_path(LIBRARY_PATH).'search/IndexableChunk.class.php'; - - $ic_slide = new IndexableChunk(); - $ic_slide->addValue('title', $file_title); - $ic_slide->addCourseId($courseid); - $ic_slide->addToolId(TOOL_DOCUMENT); - $xapian_data = array( - SE_COURSE_ID => $courseid, - SE_TOOL_ID => TOOL_DOCUMENT, - SE_DATA => array('doc_id' => (int)$docid), - SE_USER => (int)api_get_user_id(), - ); - $ic_slide->xapian_data = serialize($xapian_data); - $di = new DokeosIndexer(); - $di->connectDb(null, null, $lang); - - $specific_fields = get_specific_field_list(); - - // process different depending on what to do if file exists - /** - * FIXME: Find a way to really verify if the file had been - * overwriten. Now all work is done at - * handle_uploaded_document() and it's difficult to verify it - */ - if (!empty($_POST['if_exists']) && $_POST['if_exists'] == 'overwrite') { - // overwrite the file on search engine - // actually, it consists on delete terms from db, insert new ones, create a new search engine document, and remove the old one - - // Get search_did - $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF); - $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1'; - $sql = sprintf($sql, $tbl_se_ref, $courseid, TOOL_DOCUMENT, $docid); - $res = Database::query($sql); - - if (Database::num_rows($res) > 0) { - $se_ref = Database::fetch_array($res); - $di->remove_document((int)$se_ref['search_did']); - $all_specific_terms = ''; - foreach ($specific_fields as $specific_field) { - delete_all_specific_field_value($courseid, $specific_field['id'], TOOL_DOCUMENT, $docid); - // Update search engine - $sterms = trim($_REQUEST[$specific_field['code']]); - $all_specific_terms .= ' '. $sterms; - $sterms = explode(',', $sterms); - foreach ($sterms as $sterm) { - $sterm = trim($sterm); - if (!empty($sterm)) { - $ic_slide->addTerm($sterm, $specific_field['code']); - add_specific_field_value($specific_field['id'], $courseid, TOOL_DOCUMENT, $docid, $value); - } - } - } - // Add terms also to content to make terms findable by probabilistic search - $file_content = $all_specific_terms .' '. $file_content; - $ic_slide->addValue('content', $file_content); - $di->addChunk($ic_slide); - // Index and return a new search engine document id - $did = $di->index(); - if ($did) { - // update the search_did on db - $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF); - $sql = 'UPDATE %s SET search_did=%d WHERE id=%d LIMIT 1'; - $sql = sprintf($sql, $tbl_se_ref, (int)$did, (int)$se_ref['id']); - Database::query($sql); - } - - } - } else { - // Add all terms - $all_specific_terms = ''; - foreach ($specific_fields as $specific_field) { - if (isset($_REQUEST[$specific_field['code']])) { - $sterms = trim($_REQUEST[$specific_field['code']]); - $all_specific_terms .= ' '. $sterms; - if (!empty($sterms)) { - $sterms = explode(',', $sterms); - foreach ($sterms as $sterm) { - $ic_slide->addTerm(trim($sterm), $specific_field['code']); - add_specific_field_value($specific_field['id'], $courseid, TOOL_DOCUMENT, $docid, $sterm); - } - } - } - } - // Add terms also to content to make terms findable by probabilistic search - $file_content = $all_specific_terms .' '. $file_content; - $ic_slide->addValue('content', $file_content); - $di->addChunk($ic_slide); - // Index and return search engine document id - $did = $di->index(); - if ($did) { - // Save it to db - $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF); - $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, search_did) - VALUES (NULL , \'%s\', \'%s\', %s, %s)'; - $sql = sprintf($sql, $tbl_se_ref, $courseid, TOOL_DOCUMENT, $docid, $did); - Database::query($sql); - } - } - } - } - } - - // Check for missing images in html files - $missing_files = check_for_missing_files($base_work_dir.$new_path); - if ($missing_files) { - // Show a form to upload the missing files - Display::display_normal_message(build_missing_files_form($missing_files, $_POST['curdirpath'], $_FILES['user_upload']['name']), false); - } - } +if (!empty($_FILES)) { + DocumentManager::upload_document($_FILES, $_POST['curdirpath'], $_POST['title'], $_POST['comment'], $_POST['unzip'], $_POST['if_exists'], $_POST['index_document'], true); } +// @todo remove this submit_image ??? +/* // Missing images are submitted if (isset($_POST['submit_image'])) { $number_of_uploaded_images = count($_FILES['img_file']['name']); @@ -444,7 +210,9 @@ if (isset($_POST['submit_image'])) { item_property_update_on_folder($_course, $_POST['curdirpath'], $_user['user_id']); } } - +*/ +//@todo keep it simple this page should only upload files! +/* // They want to create a directory if (isset($_POST['create_dir']) && $_POST['dirname'] != '') { $added_slash = ($path=='/') ? '' : '/'; @@ -456,13 +224,13 @@ if (isset($_POST['create_dir']) && $_POST['dirname'] != '') { } else { display_error(get_lang('CannotCreateDir')); } -} +}*/ // Tracking not needed here? //event_access_tool(TOOL_DOCUMENT); /* They want to create a new directory */ - +/* if (isset($_GET['createdir'])) { // create the form that asks for the directory name $new_folder_text = '
'; @@ -475,7 +243,7 @@ if (isset($_GET['createdir'])) { //Display::display_normal_message($new_folder_text, false); echo create_dir_form(); -} +}*/ // Actions echo '
'; @@ -488,9 +256,10 @@ if ($is_certificate_mode) { } // Link to create a folder +/* if (!isset($_GET['createdir']) && !is_my_shared_folder($_user['user_id'], $path, api_get_session_id()) && !$is_certificate_mode) { echo ''.Display::return_icon('new_folder.png', get_lang('CreateDir'),'','32').''; -} +}*/ echo '
'; // Form to select directory @@ -501,9 +270,8 @@ if (!$is_certificate_mode) { $form = new FormValidator('upload', 'POST', api_get_self(), '', 'enctype="multipart/form-data"'); $form->addElement('hidden', 'curdirpath', $path); -$form->addElement('file', 'user_upload', get_lang('File'), 'id="user_upload" size="45"'); +$form->addElement('file', 'file', get_lang('File'), 'id="user_upload" size="45"'); $form->addElement('html', '
 
'.get_lang('MaxFileSize').': '.ini_get('upload_max_filesize').'
'.get_lang('DocumentQuota').': '.(round(DocumentManager::get_course_quota()/1000000)-round(documents_total_space($_course)/1000000)).' M
'); - if (api_get_setting('use_document_title') == 'true') { $form->addElement('text', 'title', get_lang('Title'), array('size' => '20', 'style' => 'width:300px', 'id' => 'title_file')); $form->addElement('textarea', 'comment', get_lang('Comment'), 'wrap="virtual" style="width:300px;"'); @@ -542,6 +310,7 @@ $form->addElement('radio', 'if_exists', '', get_lang('UplRenameLong'), 'rename') // Close the java script and avoid the footer up $form -> addElement('html', ''); + // Button send document $form->addElement('style_submit_button', 'submitDocument', get_lang('SendDocument'), 'class="upload"'); $form->add_real_progress_bar('DocumentUpload', 'user_upload'); @@ -550,7 +319,19 @@ $defaults = array('index_document' => 'checked="checked"'); $form->setDefaults($defaults); -$form->display(); - +$simple_form = $form->return_form(); + +// Multiple uploads +$url = api_get_path(WEB_AJAX_PATH).'document.ajax.php'; +$multiple_form = get_lang('ClickToSelectOrDragAndDropMultipleFilesOnTheUploadField').'
'; +$multiple_form .= ' + + + +
'.get_lang('UploadFiles').'
+
'; +$multiple_form .='
'; +$headers = array(get_lang('Simple') , get_lang('Multiple')); +echo Display::tabs($headers, array($simple_form, $multiple_form ),'tabs'); // Footer -Display::display_footer(); +Display::display_footer(); \ No newline at end of file diff --git a/main/inc/ajax/document.ajax.php b/main/inc/ajax/document.ajax.php new file mode 100644 index 0000000000..fdcd208286 --- /dev/null +++ b/main/inc/ajax/document.ajax.php @@ -0,0 +1,16 @@ +html_to_pdf($file_path, $document_data['title'], $course_code); } + + public function upload_document($files, $path, $title = '', $comment = '', $unzip = 0, $if_exists = '', $index_document = false, $show_output = false) { + require_once api_get_path(LIBRARY_PATH).'fileUpload.lib.php'; + //If we want to unzip a file, we need the library + if (isset($unzip) && $unzip == 1) { + require_once api_get_path(LIBRARY_PATH).'pclzip/pclzip.lib.php'; + } + + $max_filled_space = self::get_course_quota(); + $course_info = api_get_course_info(); + + $courseDir = $course_info['path'].'/document'; + $sys_course_path = api_get_path(SYS_COURSE_PATH); + $base_work_dir = $sys_course_path.$courseDir; + + if (isset($files['file'])) { + //echo('
');
+        
+            //echo('
'); + + $upload_ok = process_uploaded_file($files['file']); + if ($upload_ok) { + // File got on the server without problems, now process it + $new_path = handle_uploaded_document($course_info, $files['file'], $base_work_dir, $path, api_get_user_id(), api_get_group_id(), null, $max_filled_space, $unzip, $if_exists, $show_output); + + $new_comment = isset($title) ? trim($comment) : ''; + $new_title = isset($title) ? trim($title) : ''; + + if ($new_path && ($new_comment || $new_title)) { + if (($docid = DocumentManager::get_document_id($course_info, $new_path))) { + $table_document = Database::get_course_table(TABLE_DOCUMENT); + $ct = ''; + if ($new_comment) $ct .= ", comment='$new_comment'"; + if ($new_title) $ct .= ", title='$new_title'"; + Database::query("UPDATE $table_document SET ".substr($ct, 1)." WHERE id = $docid"); + } + } + // Showing message when sending zip files + if ($new_path === true && $unzip == 1) { + //Display::display_confirmation_message(get_lang('UplUploadSucceeded').'
', false); + } + + if ((api_get_setting('search_enabled') == 'true') && ($docid = DocumentManager::get_document_id($course_info, $new_path))) { + $table_document = Database::get_course_table(TABLE_DOCUMENT); + $result = Database::query("SELECT * FROM $table_document WHERE id = '$docid' LIMIT 1"); + if (Database::num_rows($result) == 1) { + $row = Database::fetch_array($result); + $doc_path = api_get_path(SYS_COURSE_PATH).$courseDir.$row['path']; + //TODO: mime_content_type is deprecated, fileinfo php extension is enabled by default as of PHP 5.3.0 + // now versions of PHP on Debian testing(5.2.6-5) and Ubuntu(5.2.6-2ubuntu) are lower, so wait for a while + $doc_mime = mime_content_type($doc_path); + //echo $doc_mime; + //TODO: more mime types + $allowed_mime_types = array('text/plain', 'application/pdf', 'application/postscript', 'application/msword', 'text/html', 'text/rtf', 'application/vnd.ms-powerpoint', 'application/vnd.ms-excel'); + + // mime_content_type does not detect correctly some formats that are going to be supported for index, so an extensions array is used by the moment + if (empty($doc_mime)) { + $allowed_extensions = array('ppt', 'pps', 'xls'); + $extensions = preg_split("/[\/\\.]/", $doc_path) ; + $doc_ext = strtolower($extensions[count($extensions) - 1]); + if (in_array($doc_ext, $allowed_extensions)) { + switch ($doc_ext) { + case 'ppt': + case 'pps': + $doc_mime = 'application/vnd.ms-powerpoint'; + break; + case 'xls': + $doc_mime = 'application/vnd.ms-excel'; + break; + } + } + } + + //@todo move this nightmare in a search controller or something like that!!! J.M + + if (in_array($doc_mime, $allowed_mime_types) && isset($index_document) && $index_document) { + $file_title = $row['title']; + $file_content = self::get_text_content($doc_path, $doc_mime); + $courseid = api_get_course_id(); + $lang = isset($_POST['language']) ? Database::escape_string($_POST['language']) : 'english'; + + require_once api_get_path(LIBRARY_PATH).'search/DokeosIndexer.class.php'; + require_once api_get_path(LIBRARY_PATH).'search/IndexableChunk.class.php'; + + $ic_slide = new IndexableChunk(); + $ic_slide->addValue('title', $file_title); + $ic_slide->addCourseId($courseid); + $ic_slide->addToolId(TOOL_DOCUMENT); + $xapian_data = array( + SE_COURSE_ID => $courseid, + SE_TOOL_ID => TOOL_DOCUMENT, + SE_DATA => array('doc_id' => (int)$docid), + SE_USER => (int)api_get_user_id(), + ); + $ic_slide->xapian_data = serialize($xapian_data); + $di = new DokeosIndexer(); + $di->connectDb(null, null, $lang); + + $specific_fields = get_specific_field_list(); + + // process different depending on what to do if file exists + /** + * FIXME: Find a way to really verify if the file had been + * overwriten. Now all work is done at + * handle_uploaded_document() and it's difficult to verify it + */ + if (!empty($if_exists) && $if_exists == 'overwrite') { + // overwrite the file on search engine + // actually, it consists on delete terms from db, insert new ones, create a new search engine document, and remove the old one + + // Get search_did + $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF); + $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1'; + $sql = sprintf($sql, $tbl_se_ref, $courseid, TOOL_DOCUMENT, $docid); + $res = Database::query($sql); + + if (Database::num_rows($res) > 0) { + $se_ref = Database::fetch_array($res); + $di->remove_document((int)$se_ref['search_did']); + $all_specific_terms = ''; + foreach ($specific_fields as $specific_field) { + delete_all_specific_field_value($courseid, $specific_field['id'], TOOL_DOCUMENT, $docid); + // Update search engine + $sterms = trim($_REQUEST[$specific_field['code']]); + $all_specific_terms .= ' '. $sterms; + $sterms = explode(',', $sterms); + foreach ($sterms as $sterm) { + $sterm = trim($sterm); + if (!empty($sterm)) { + $ic_slide->addTerm($sterm, $specific_field['code']); + add_specific_field_value($specific_field['id'], $courseid, TOOL_DOCUMENT, $docid, $value); + } + } + } + // Add terms also to content to make terms findable by probabilistic search + $file_content = $all_specific_terms .' '. $file_content; + $ic_slide->addValue('content', $file_content); + $di->addChunk($ic_slide); + // Index and return a new search engine document id + $did = $di->index(); + if ($did) { + // update the search_did on db + $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF); + $sql = 'UPDATE %s SET search_did=%d WHERE id=%d LIMIT 1'; + $sql = sprintf($sql, $tbl_se_ref, (int)$did, (int)$se_ref['id']); + Database::query($sql); + } + + } + } else { + // Add all terms + $all_specific_terms = ''; + foreach ($specific_fields as $specific_field) { + if (isset($_REQUEST[$specific_field['code']])) { + $sterms = trim($_REQUEST[$specific_field['code']]); + $all_specific_terms .= ' '. $sterms; + if (!empty($sterms)) { + $sterms = explode(',', $sterms); + foreach ($sterms as $sterm) { + $ic_slide->addTerm(trim($sterm), $specific_field['code']); + add_specific_field_value($specific_field['id'], $courseid, TOOL_DOCUMENT, $docid, $sterm); + } + } + } + } + // Add terms also to content to make terms findable by probabilistic search + $file_content = $all_specific_terms .' '. $file_content; + $ic_slide->addValue('content', $file_content); + $di->addChunk($ic_slide); + // Index and return search engine document id + $did = $di->index(); + if ($did) { + // Save it to db + $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF); + $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, search_did) + VALUES (NULL , \'%s\', \'%s\', %s, %s)'; + $sql = sprintf($sql, $tbl_se_ref, $courseid, TOOL_DOCUMENT, $docid, $did); + Database::query($sql); + } + } + } + } + } + + // Check for missing images in html files + $missing_files = check_for_missing_files($base_work_dir.$new_path); + if ($missing_files) { + // Show a form to upload the missing files + //Display::display_normal_message(build_missing_files_form($missing_files, $path, $files['file']['name']), false); + } + } + } + } + + /** + * Obtains the text inside the file with the right parser + + */ + function get_text_content($doc_path, $doc_mime) { + // TODO: review w$ compatibility + + // Use usual exec output lines array to store stdout instead of a temp file + // because we need to store it at RAM anyway before index on DokeosIndexer object + $ret_val = null; + switch ($doc_mime) { + case 'text/plain': + $handle = fopen($doc_path, 'r'); + $output = array(fread($handle, filesize($doc_path))); + fclose($handle); + break; + case 'application/pdf': + exec("pdftotext $doc_path -", $output, $ret_val); + break; + case 'application/postscript': + $temp_file = tempnam(sys_get_temp_dir(), 'chamilo'); + exec("ps2pdf $doc_path $temp_file", $output, $ret_val); + if ($ret_val !== 0) { // shell fail, probably 127 (command not found) + return false; + } + exec("pdftotext $temp_file -", $output, $ret_val); + unlink($temp_file); + //var_dump($output); + break; + case 'application/msword': + exec("catdoc $doc_path", $output, $ret_val); + //var_dump($output); + break; + case 'text/html': + exec("html2text $doc_path", $output, $ret_val); + break; + case 'text/rtf': + // Note: correct handling of code pages in unrtf + // on debian lenny unrtf v0.19.2 can not, but unrtf v0.20.5 can + exec("unrtf --text $doc_path", $output, $ret_val); + if ($ret_val == 127) { // command not found + return false; + } + // Avoid index unrtf comments + if (is_array($output) && count($output) > 1) { + $parsed_output = array(); + foreach ($output as & $line) { + if (!preg_match('/^###/', $line, $matches)) { + if (!empty($line)) { + $parsed_output[] = $line; + } + } + } + $output = $parsed_output; + } + break; + case 'application/vnd.ms-powerpoint': + exec("catppt $doc_path", $output, $ret_val); + break; + case 'application/vnd.ms-excel': + exec("xls2csv -c\" \" $doc_path", $output, $ret_val); + break; + } + + $content = ''; + if (!is_null($ret_val)) { + if ($ret_val !== 0) { // shell fail, probably 127 (command not found) + return false; + } + } + if (isset($output)) { + foreach ($output as & $line) { + $content .= $line."\n"; + } + return $content; + } + else { + return false; + } + } } //end class DocumentManager \ No newline at end of file diff --git a/main/inc/lib/fileUpload.lib.php b/main/inc/lib/fileUpload.lib.php index 21d312bd10..366ce423a8 100755 --- a/main/inc/lib/fileUpload.lib.php +++ b/main/inc/lib/fileUpload.lib.php @@ -139,7 +139,9 @@ function handle_uploaded_document($_course, $uploaded_file, $base_work_dir, $upl $current_session_id = api_get_session_id(); // Check if there is enough space to save the file if (!enough_space($uploaded_file['size'], $maxFilledSpace)) { - Display::display_error_message(get_lang('UplNotEnoughSpace')); + if ($output){ + Display::display_error_message(get_lang('UplNotEnoughSpace')); + } return false; } @@ -150,7 +152,9 @@ function handle_uploaded_document($_course, $uploaded_file, $base_work_dir, $upl } // We can only unzip ZIP files (no gz, tar,...) elseif ($unzip == 1 && !preg_match('/.zip$/', strtolower($uploaded_file['name']))) { - Display::display_error_message(get_lang('UplNotAZip')." ".get_lang('PleaseTryAgain')); + 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) @@ -158,7 +162,9 @@ function handle_uploaded_document($_course, $uploaded_file, $base_work_dir, $upl // No "dangerous" files $clean_name = disable_dangerous_file($clean_name); if (!filter_extension($clean_name)) { - Display::display_error_message(get_lang('UplUnableToSaveFileFilteredExtension')); + if ($output){ + Display::display_error_message(get_lang('UplUnableToSaveFileFilteredExtension')); + } return false; } else { // Extension is good @@ -175,7 +181,9 @@ function handle_uploaded_document($_course, $uploaded_file, $base_work_dir, $upl $where_to_save = $base_work_dir.$upload_path; // At least if the directory doesn't exist, tell so if (!is_dir($where_to_save)) { - Display::display_error_message(get_lang('DestDirectoryDoesntExist').' ('.$upload_path.')'); + if ($output){ + Display::display_error_message(get_lang('DestDirectoryDoesntExist').' ('.$upload_path.')'); + } return false; } //echo '
where to save = '.$where_to_save; @@ -223,11 +231,15 @@ function handle_uploaded_document($_course, $uploaded_file, $base_work_dir, $upl // If the file is in a folder, we need to update all parent folders item_property_update_on_folder($_course, $upload_path, $user_id); // Display success message to user - Display::display_confirmation_message(get_lang('UplUploadSucceeded').'
'.$file_path, false); + if ($output){ + Display::display_confirmation_message(get_lang('UplUploadSucceeded').'
'.$file_path, false); + } return $file_path; } } else { - Display::display_error_message(get_lang('UplUnableToSaveFile')); + if ($output){ + Display::display_error_message(get_lang('UplUnableToSaveFile')); + } return false; } break; @@ -264,7 +276,9 @@ function handle_uploaded_document($_course, $uploaded_file, $base_work_dir, $upl // Only save the file if it doesn't exist or warn user if it does exist default: if (file_exists($store_path)) { - Display::display_error_message($clean_name.' '.get_lang('UplAlreadyExists')); + 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); @@ -283,7 +297,9 @@ function handle_uploaded_document($_course, $uploaded_file, $base_work_dir, $upl } return $file_path; } else { - Display::display_error_message(get_lang('UplUnableToSaveFile')); + if ($output){ + Display::display_error_message(get_lang('UplUnableToSaveFile')); + } return false; } } diff --git a/main/inc/lib/javascript/jquery-upload/README.txt b/main/inc/lib/javascript/jquery-upload/README.txt new file mode 100644 index 0000000000..64eeeed84f --- /dev/null +++ b/main/inc/lib/javascript/jquery-upload/README.txt @@ -0,0 +1,61 @@ +jQuery File Upload Plugin +========================= + +Demo +---- +http://aquantum-demo.appspot.com/file-upload + +Features +-------- + - Multiple file upload: + Allows to select multiple files at once and upload them simultaneously. + - Drag & Drop support: + Allows to upload files by dragging them from your desktop or filemanager and dropping them on your browser window. + - Upload progress bar: + Shows a progress bar indicating the upload progress for individual files. + - Cancelable uploads: + Individual file uploads can be canceled to stop the upload progress. + - No browser plugins (e.g. Adobe Flash) required: + The implementation is based on open standards like HTML5 and JavaScript and requires no additional browser plugins. + - Graceful fallback for legacy browsers: + Uploads files via XMLHttpRequests if supported and uses iframes as fallback for legacy browsers. + - HTML file upload form fallback: + Shows a standard HTML file upload form if JavaScript is disabled. + - Cross-site file uploads: + Supports uploading files to a different domain with Cross-site XMLHttpRequests. + - Multiple plugin instances: + Allows to use multiple plugin instances on the same webpage. + - Customizable and extensible: + Provides an API to set individual options and define callBack methods for various upload events. + - Multipart and file contents stream uploads: + Files can be uploaded as standard "multipart/form-data" or file contents stream (HTTP PUT file upload). + - Compatible with any server-side application platform: + Works with Google App Engine (Python, Java), Ruby on Rails, PHP and any other platform that supports HTTP file uploads. + +Requirements +------------ + - jQuery v. 1.4+ + - jQuery UI v. 1.8+ (optional) + +Browser Support (tested versions) +--------------------------------- + - Google Chrome - 7.0, 8.0, 9.0 + - Apple Safari - 5.0 ¹ + - Mozilla Firefox - 3.6 + - Opera - 10.60 ², 11.00 ² + - Microsoft Internet Explorer 6.0 ², 7.0 ², 8.0 ², 9.0 ² +¹ Drag & Drop is not supported on the Windows version of Safari. +² MSIE and Opera have no support for Drag & Drop, multiple file selection or upload progress indication. + +License +------- +Released under the MIT license: +http://creativecommons.org/licenses/MIT/ + +Source Code & Download +---------------------- +https://github.com/blueimp/jQuery-File-Upload + +Documentation +------------- +https://github.com/blueimp/jQuery-File-Upload/wiki diff --git a/main/inc/lib/javascript/jquery-upload/jquery.fileupload-ui.css b/main/inc/lib/javascript/jquery-upload/jquery.fileupload-ui.css new file mode 100644 index 0000000000..dd4a9379e0 --- /dev/null +++ b/main/inc/lib/javascript/jquery-upload/jquery.fileupload-ui.css @@ -0,0 +1,74 @@ +.file_upload { + position: relative; + overflow: hidden; + direction: ltr; + cursor: pointer; + text-align: center; + color: #333; + font-weight: bold; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + border-radius: 10px; + width: 200px; + height: 30px; + line-height: 30px; + background: palegreen; + border: 1px solid limegreen; +} + +.file_upload_small { + width: 200px; + height: 30px; + line-height: 30px; + font-size: auto; + background: palegreen; + border: 1px solid limegreen; +} + +.file_upload_large { + width: 100%; + height: 150px; + line-height: 150px; + font-size: 20px; + background: palegreen; + border: 1px solid limegreen; +} + +.file_upload_highlight { + background: lawngreen; +} + +.file_upload input { + position: absolute; + top: 0; + right: 0; + margin: 0; + border: 300px solid transparent; + opacity: 0; + -ms-filter: 'alpha(opacity=0)'; + filter: alpha(opacity=0); + -o-transform: translate(-300px, -300px) scale(10); + -moz-transform: translate(-800px, 0) scale(10); + cursor: pointer; +} + +.file_upload iframe, .file_upload button { + display: none; +} + +.file_upload_preview img { + width: 80px; +} + +.file_upload_progress .ui-progressbar-value { + background: url(pbar-ani.gif); +} + +.file_upload_progress div { + width: 150px; + height: 15px; +} + +.file_upload_cancel button { + cursor: pointer; +} \ No newline at end of file diff --git a/main/inc/lib/javascript/jquery-upload/jquery.fileupload-ui.js b/main/inc/lib/javascript/jquery-upload/jquery.fileupload-ui.js new file mode 100644 index 0000000000..4223be04f7 --- /dev/null +++ b/main/inc/lib/javascript/jquery-upload/jquery.fileupload-ui.js @@ -0,0 +1,308 @@ +/* + * jQuery File Upload User Interface Plugin 3.6 + * + * Copyright 2010, Sebastian Tschan, AQUANTUM + * Licensed under the MIT license: + * http://creativecommons.org/licenses/MIT/ + * + * https://blueimp.net + * http://www.aquantum.de + */ + +/*jslint browser: true */ +/*global jQuery, FileReader, URL */ + +(function ($) { + + var undef = 'undefined', + func = 'function', + UploadHandler, + methods, + + LocalImage = function (file, imageTypes) { + var img, + fileReader; + if (!imageTypes.test(file.type)) { + return null; + } + img = document.createElement('img'); + if (typeof URL !== undef && typeof URL.createObjectURL === func) { + img.src = URL.createObjectURL(file); + img.onload = function () { + URL.revokeObjectURL(this.src); + }; + return img; + } + if (typeof FileReader !== undef) { + fileReader = new FileReader(); + if (typeof fileReader.readAsDataURL === func) { + fileReader.onload = function (e) { + img.src = e.target.result; + }; + fileReader.readAsDataURL(file); + return img; + } + } + return null; + }; + + UploadHandler = function (container, options) { + var uploadHandler = this, + dragOverTimeout, + isDropZoneEnlarged; + + this.dropZone = container; + this.imageTypes = /^image\/(gif|jpeg|png)$/; + this.previewSelector = '.file_upload_preview'; + this.progressSelector = '.file_upload_progress div'; + this.cancelSelector = '.file_upload_cancel button'; + this.cssClassSmall = 'file_upload_small'; + this.cssClassLarge = 'file_upload_large'; + this.cssClassHighlight = 'file_upload_highlight'; + this.dropEffect = 'highlight'; + this.uploadTable = this.downloadTable = null; + + this.buildUploadRow = this.buildDownloadRow = function () { + return null; + }; + + this.addNode = function (parentNode, node, callBack) { + if (node) { + node.css('display', 'none').appendTo(parentNode).fadeIn(function () { + if (typeof callBack === func) { + try { + callBack(); + } catch (e) { + // Fix endless exception loop: + $(this).stop(); + throw e; + } + } + }); + } else if (typeof callBack === func) { + callBack(); + } + }; + + this.removeNode = function (node, callBack) { + if (node) { + node.fadeOut(function () { + $(this).remove(); + if (typeof callBack === func) { + try { + callBack(); + } catch (e) { + // Fix endless exception loop: + $(this).stop(); + throw e; + } + } + }); + } else if (typeof callBack === func) { + callBack(); + } + }; + + this.onAbort = function (event, files, index, xhr, handler) { + handler.removeNode(handler.uploadRow); + }; + + this.cancelUpload = function (event, files, index, xhr, handler) { + var readyState = xhr.readyState; + xhr.abort(); + // If readyState is below 2, abort() has no effect: + if (isNaN(readyState) || readyState < 2) { + handler.onAbort(event, files, index, xhr, handler); + } + }; + + this.initProgressBar = function (node, value) { + if (typeof node.progressbar === func) { + return node.progressbar({ + value: value + }); + } else { + var progressbar = $('').appendTo(node); + progressbar.progressbar = function (key, value) { + progressbar.attr('value', value); + }; + return progressbar; + } + }; + + this.initUploadRow = function (event, files, index, xhr, handler, callBack) { + var uploadRow = handler.uploadRow = handler.buildUploadRow(files, index, handler); + if (uploadRow) { + handler.progressbar = handler.initProgressBar( + uploadRow.find(handler.progressSelector), + (xhr.upload ? 0 : 100) + ); + uploadRow.find(handler.cancelSelector).click(function (e) { + handler.cancelUpload(e, files, index, xhr, handler); + }); + uploadRow.find(handler.previewSelector).each(function () { + $(this).append(new LocalImage(files[index], handler.imageTypes)); + }); + } + handler.addNode( + (typeof handler.uploadTable === func ? handler.uploadTable(handler) : handler.uploadTable), + uploadRow, + callBack + ); + }; + + this.initUpload = function (event, files, index, xhr, handler, callBack) { + handler.initUploadRow(event, files, index, xhr, handler, function () { + if (typeof handler.beforeSend === func) { + handler.beforeSend(event, files, index, xhr, handler, callBack); + } else { + callBack(); + } + }); + }; + + this.onProgress = function (event, files, index, xhr, handler) { + if (handler.progressbar) { + handler.progressbar.progressbar( + 'value', + parseInt(event.loaded / event.total * 100, 10) + ); + } + }; + + this.parseResponse = function (xhr) { + if (typeof xhr.responseText !== undef) { + return $.parseJSON(xhr.responseText); + } else { + // Instead of an XHR object, an iframe is used for legacy browsers: + return $.parseJSON(xhr.contents().text()); + } + }; + + this.initDownloadRow = function (event, files, index, xhr, handler, callBack) { + var json, downloadRow; + try { + json = handler.response = handler.parseResponse(xhr); + downloadRow = handler.downloadRow = handler.buildDownloadRow(json, handler); + handler.addNode( + (typeof handler.downloadTable === func ? handler.downloadTable(handler) : handler.downloadTable), + downloadRow, + callBack + ); + } catch (e) { + if (typeof handler.onError === func) { + handler.originalEvent = event; + handler.onError(e, files, index, xhr, handler); + } else { + throw e; + } + } + }; + + this.onLoad = function (event, files, index, xhr, handler) { + handler.removeNode(handler.uploadRow, function () { + handler.initDownloadRow(event, files, index, xhr, handler, function () { + if (typeof handler.onComplete === func) { + handler.onComplete(event, files, index, xhr, handler); + } + }); + }); + }; + + this.dropZoneEnlarge = function () { + if (!isDropZoneEnlarged) { + if (typeof uploadHandler.dropZone.switchClass === func) { + uploadHandler.dropZone.switchClass( + uploadHandler.cssClassSmall, + uploadHandler.cssClassLarge + ); + } else { + uploadHandler.dropZone.addClass(uploadHandler.cssClassLarge); + uploadHandler.dropZone.removeClass(uploadHandler.cssClassSmall); + } + isDropZoneEnlarged = true; + } + }; + + this.dropZoneReduce = function () { + if (typeof uploadHandler.dropZone.switchClass === func) { + uploadHandler.dropZone.switchClass( + uploadHandler.cssClassLarge, + uploadHandler.cssClassSmall + ); + } else { + uploadHandler.dropZone.addClass(uploadHandler.cssClassSmall); + uploadHandler.dropZone.removeClass(uploadHandler.cssClassLarge); + } + isDropZoneEnlarged = false; + }; + + this.onDocumentDragEnter = function (event) { + uploadHandler.dropZoneEnlarge(); + }; + + this.onDocumentDragOver = function (event) { + if (dragOverTimeout) { + clearTimeout(dragOverTimeout); + } + dragOverTimeout = setTimeout(function () { + uploadHandler.dropZoneReduce(); + }, 200); + }; + + this.onDragEnter = this.onDragLeave = function (event) { + uploadHandler.dropZone.toggleClass(uploadHandler.cssClassHighlight); + }; + + this.onDrop = function (event) { + if (dragOverTimeout) { + clearTimeout(dragOverTimeout); + } + if (uploadHandler.dropEffect && typeof uploadHandler.dropZone.effect === func) { + uploadHandler.dropZone.effect(uploadHandler.dropEffect, function () { + uploadHandler.dropZone.removeClass(uploadHandler.cssClassHighlight); + uploadHandler.dropZoneReduce(); + }); + } else { + uploadHandler.dropZone.removeClass(uploadHandler.cssClassHighlight); + uploadHandler.dropZoneReduce(); + } + }; + + $.extend(this, options); + }; + + methods = { + init : function (options) { + return this.each(function () { + $(this).fileUpload(new UploadHandler($(this), options)); + }); + }, + + option: function (option, value, namespace) { + if (typeof option === undef || (typeof option === 'string' && typeof value === undef)) { + return $(this).fileUpload('option', option, value, namespace); + } + return this.each(function () { + $(this).fileUpload('option', option, value, namespace); + }); + }, + + destroy : function (namespace) { + return this.each(function () { + $(this).fileUpload('destroy', namespace); + }); + } + }; + + $.fn.fileUploadUI = function (method) { + if (methods[method]) { + return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); + } else if (typeof method === 'object' || !method) { + return methods.init.apply(this, arguments); + } else { + $.error('Method ' + method + ' does not exist on jQuery.fileUploadUI'); + } + }; + +}(jQuery)); \ No newline at end of file diff --git a/main/inc/lib/javascript/jquery-upload/jquery.fileupload.js b/main/inc/lib/javascript/jquery-upload/jquery.fileupload.js new file mode 100644 index 0000000000..6a5c39de7e --- /dev/null +++ b/main/inc/lib/javascript/jquery-upload/jquery.fileupload.js @@ -0,0 +1,629 @@ +/* + * jQuery File Upload Plugin 3.7.1 + * + * Copyright 2010, Sebastian Tschan, AQUANTUM + * Licensed under the MIT license: + * http://creativecommons.org/licenses/MIT/ + * + * https://blueimp.net + * http://www.aquantum.de + */ + +/*jslint browser: true */ +/*global File, FileReader, FormData, unescape, jQuery */ + +(function ($) { + + var defaultNamespace = 'file_upload', + undef = 'undefined', + func = 'function', + num = 'number', + FileUpload, + methods, + + MultiLoader = function (callBack, numberComplete) { + var loaded = 0; + this.complete = function () { + loaded += 1; + if (loaded === numberComplete) { + callBack(); + } + }; + }; + + FileUpload = function (container) { + var fileUpload = this, + uploadForm, + fileInput, + settings = { + namespace: defaultNamespace, + uploadFormFilter: function (index) { + return true; + }, + fileInputFilter: function (index) { + return true; + }, + cssClass: defaultNamespace, + dragDropSupport: true, + dropZone: container, + url: function (form) { + return form.attr('action'); + }, + method: function (form) { + return form.attr('method'); + }, + fieldName: function (input) { + return input.attr('name'); + }, + formData: function (form) { + return form.serializeArray(); + }, + multipart: true, + multiFileRequest: false, + withCredentials: false, + forceIframeUpload: false + }, + documentListeners = {}, + dropZoneListeners = {}, + protocolRegExp = /^http(s)?:\/\//, + optionsReference, + + isXHRUploadCapable = function () { + return typeof XMLHttpRequest !== undef && typeof File !== undef && ( + !settings.multipart || typeof FormData !== undef || typeof FileReader !== undef + ); + }, + + initEventHandlers = function () { + if (settings.dragDropSupport) { + if (typeof settings.onDocumentDragEnter === func) { + documentListeners['dragenter.' + settings.namespace] = function (e) { + settings.onDocumentDragEnter(e); + }; + } + if (typeof settings.onDocumentDragLeave === func) { + documentListeners['dragleave.' + settings.namespace] = function (e) { + settings.onDocumentDragLeave(e); + }; + } + documentListeners['dragover.' + settings.namespace] = fileUpload.onDocumentDragOver; + documentListeners['drop.' + settings.namespace] = fileUpload.onDocumentDrop; + $(document).bind(documentListeners); + if (typeof settings.onDragEnter === func) { + dropZoneListeners['dragenter.' + settings.namespace] = function (e) { + settings.onDragEnter(e); + }; + } + if (typeof settings.onDragLeave === func) { + dropZoneListeners['dragleave.' + settings.namespace] = function (e) { + settings.onDragLeave(e); + }; + } + dropZoneListeners['dragover.' + settings.namespace] = fileUpload.onDragOver; + dropZoneListeners['drop.' + settings.namespace] = fileUpload.onDrop; + settings.dropZone.bind(dropZoneListeners); + } + fileInput.bind('change.' + settings.namespace, fileUpload.onChange); + }, + + removeEventHandlers = function () { + $.each(documentListeners, function (key, value) { + $(document).unbind(key, value); + }); + $.each(dropZoneListeners, function (key, value) { + settings.dropZone.unbind(key, value); + }); + fileInput.unbind('change.' + settings.namespace); + }, + + initUploadEventHandlers = function (files, index, xhr, settings) { + if (typeof settings.onProgress === func) { + xhr.upload.onprogress = function (e) { + settings.onProgress(e, files, index, xhr, settings); + }; + } + if (typeof settings.onLoad === func) { + xhr.onload = function (e) { + settings.onLoad(e, files, index, xhr, settings); + }; + } + if (typeof settings.onAbort === func) { + xhr.onabort = function (e) { + settings.onAbort(e, files, index, xhr, settings); + }; + } + if (typeof settings.onError === func) { + xhr.onerror = function (e) { + settings.onError(e, files, index, xhr, settings); + }; + } + }, + + getUrl = function (settings) { + if (typeof settings.url === func) { + return settings.url(settings.uploadForm || uploadForm); + } + return settings.url; + }, + + getMethod = function (settings) { + if (typeof settings.method === func) { + return settings.method(settings.uploadForm || uploadForm); + } + return settings.method; + }, + + getFieldName = function (settings) { + if (typeof settings.fieldName === func) { + return settings.fieldName(settings.fileInput || fileInput); + } + return settings.fieldName; + }, + + getFormData = function (settings) { + var formData; + if (typeof settings.formData === func) { + return settings.formData(settings.uploadForm || uploadForm); + } else if ($.isArray(settings.formData)) { + return settings.formData; + } else if (settings.formData) { + formData = []; + $.each(settings.formData, function (name, value) { + formData.push({name: name, value: value}); + }); + return formData; + } + return []; + }, + + isSameDomain = function (url) { + if (protocolRegExp.test(url)) { + var host = location.host, + indexStart = location.protocol.length + 2, + index = url.indexOf(host, indexStart), + pathIndex = index + host.length; + if ((index === indexStart || index === url.indexOf('@', indexStart) + 1) && + (url.length === pathIndex || $.inArray(url.charAt(pathIndex), ['/', '?', '#']) !== -1)) { + return true; + } + return false; + } + return true; + }, + + nonMultipartUpload = function (file, xhr, sameDomain) { + if (sameDomain) { + xhr.setRequestHeader('X-File-Name', unescape(encodeURIComponent(file.name))); + } + xhr.setRequestHeader('Content-Type', file.type); + xhr.send(file); + }, + + formDataUpload = function (files, xhr, settings) { + var formData = new FormData(), + i; + $.each(getFormData(settings), function (index, field) { + formData.append(field.name, field.value); + }); + for (i = 0; i < files.length; i += 1) { + formData.append(getFieldName(settings), files[i]); + } + xhr.send(formData); + }, + + loadFileContent = function (file, callBack) { + var fileReader = new FileReader(); + fileReader.onload = function (e) { + file.content = e.target.result; + callBack(); + }; + fileReader.readAsBinaryString(file); + }, + + buildMultiPartFormData = function (boundary, files, filesFieldName, fields) { + var doubleDash = '--', + crlf = '\r\n', + formData = ''; + $.each(fields, function (index, field) { + formData += doubleDash + boundary + crlf + + 'Content-Disposition: form-data; name="' + + unescape(encodeURIComponent(field.name)) + + '"' + crlf + crlf + + unescape(encodeURIComponent(field.value)) + crlf; + }); + $.each(files, function (index, file) { + formData += doubleDash + boundary + crlf + + 'Content-Disposition: form-data; name="' + + unescape(encodeURIComponent(filesFieldName)) + + '"; filename="' + unescape(encodeURIComponent(file.name)) + '"' + crlf + + 'Content-Type: ' + file.type + crlf + crlf + + file.content + crlf; + }); + formData += doubleDash + boundary + doubleDash + crlf; + return formData; + }, + + fileReaderUpload = function (files, xhr, settings) { + var boundary = '----MultiPartFormBoundary' + (new Date()).getTime(), + loader, + i; + xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary); + loader = new MultiLoader(function () { + xhr.sendAsBinary(buildMultiPartFormData( + boundary, + files, + getFieldName(settings), + getFormData(settings) + )); + }, files.length); + for (i = 0; i < files.length; i += 1) { + loadFileContent(files[i], loader.complete); + } + }, + + upload = function (files, index, xhr, settings) { + var url = getUrl(settings), + sameDomain = isSameDomain(url), + filesToUpload; + initUploadEventHandlers(files, index, xhr, settings); + xhr.open(getMethod(settings), url, true); + if (sameDomain) { + xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + } else if (settings.withCredentials) { + xhr.withCredentials = true; + } + if (!settings.multipart) { + nonMultipartUpload(files[index], xhr, sameDomain); + } else { + if (typeof index === num) { + filesToUpload = [files[index]]; + } else { + filesToUpload = files; + } + if (typeof FormData !== undef) { + formDataUpload(filesToUpload, xhr, settings); + } else if (typeof FileReader !== undef) { + fileReaderUpload(filesToUpload, xhr, settings); + } else { + $.error('Browser does neither support FormData nor FileReader interface'); + } + } + }, + + handleUpload = function (event, files, input, form, index) { + var xhr = new XMLHttpRequest(), + uploadSettings = $.extend({}, settings); + uploadSettings.fileInput = input; + uploadSettings.uploadForm = form; + if (typeof uploadSettings.initUpload === func) { + uploadSettings.initUpload( + event, + files, + index, + xhr, + uploadSettings, + function () { + upload(files, index, xhr, uploadSettings); + } + ); + } else { + upload(files, index, xhr, uploadSettings); + } + }, + + handleFiles = function (event, files, input, form) { + var i; + if (settings.multiFileRequest) { + handleUpload(event, files, input, form); + } else { + for (i = 0; i < files.length; i += 1) { + handleUpload(event, files, input, form, i); + } + } + }, + + legacyUploadFormDataInit = function (input, form, settings) { + var formData = getFormData(settings); + form.find(':input').not(':disabled') + .attr('disabled', true) + .addClass(settings.namespace + '_disabled'); + $.each(formData, function (index, field) { + $('') + .attr('name', field.name) + .val(field.value) + .addClass(settings.namespace + '_form_data') + .appendTo(form); + }); + input + .attr('name', getFieldName(settings)) + .appendTo(form); + }, + + legacyUploadFormDataReset = function (input, form, settings) { + input.detach(); + form.find('.' + settings.namespace + '_disabled') + .removeAttr('disabled') + .removeClass(settings.namespace + '_disabled'); + form.find('.' + settings.namespace + '_form_data').remove(); + }, + + legacyUpload = function (input, form, iframe, settings) { + var originalAction = form.attr('action'), + originalMethod = form.attr('method'), + originalTarget = form.attr('target'); + iframe + .unbind('abort') + .bind('abort', function (e) { + iframe.readyState = 0; + // javascript:false as iframe src prevents warning popups on HTTPS in IE6 + // concat is used here to prevent the "Script URL" JSLint error: + iframe.unbind('load').attr('src', 'javascript'.concat(':false;')); + if (typeof settings.onAbort === func) { + settings.onAbort(e, [{name: input.val(), type: null, size: null}], 0, iframe, settings); + } + }) + .unbind('load') + .bind('load', function (e) { + iframe.readyState = 4; + if (typeof settings.onLoad === func) { + settings.onLoad(e, [{name: input.val(), type: null, size: null}], 0, iframe, settings); + } + // Fix for IE endless progress bar activity bug (happens on form submits to iframe targets): + $('').appendTo(form).remove(); + }); + form + .attr('action', getUrl(settings)) + .attr('method', getMethod(settings)) + .attr('target', iframe.attr('name')); + legacyUploadFormDataInit(input, form, settings); + iframe.readyState = 2; + form.get(0).submit(); + legacyUploadFormDataReset(input, form, settings); + form + .attr('action', originalAction) + .attr('method', originalMethod) + .attr('target', originalTarget); + }, + + handleLegacyUpload = function (event, input, form) { + // javascript:false as iframe src prevents warning popups on HTTPS in IE6: + var iframe = $(''), + uploadSettings = $.extend({}, settings); + uploadSettings.fileInput = input; + uploadSettings.uploadForm = form; + iframe.readyState = 0; + iframe.abort = function () { + iframe.trigger('abort'); + }; + iframe.bind('load', function () { + iframe.unbind('load'); + if (typeof uploadSettings.initUpload === func) { + uploadSettings.initUpload( + event, + [{name: input.val(), type: null, size: null}], + 0, + iframe, + uploadSettings, + function () { + legacyUpload(input, form, iframe, uploadSettings); + } + ); + } else { + legacyUpload(input, form, iframe, uploadSettings); + } + }).appendTo(form); + }, + + initUploadForm = function () { + uploadForm = (container.is('form') ? container : container.find('form')) + .filter(settings.uploadFormFilter); + }, + + initFileInput = function () { + fileInput = uploadForm.find('input:file') + .filter(settings.fileInputFilter); + }, + + replaceFileInput = function (input) { + var inputClone = input.clone(true); + $('
').append(inputClone).get(0).reset(); + input.after(inputClone).detach(); + initFileInput(); + }; + + this.onDocumentDragOver = function (e) { + if (typeof settings.onDocumentDragOver === func && + settings.onDocumentDragOver(e) === false) { + return false; + } + e.preventDefault(); + }; + + this.onDocumentDrop = function (e) { + if (typeof settings.onDocumentDrop === func && + settings.onDocumentDrop(e) === false) { + return false; + } + e.preventDefault(); + }; + + this.onDragOver = function (e) { + if (typeof settings.onDragOver === func && + settings.onDragOver(e) === false) { + return false; + } + var dataTransfer = e.originalEvent.dataTransfer; + if (dataTransfer) { + dataTransfer.dropEffect = dataTransfer.effectAllowed = 'copy'; + } + e.preventDefault(); + }; + + this.onDrop = function (e) { + if (typeof settings.onDrop === func && + settings.onDrop(e) === false) { + return false; + } + var dataTransfer = e.originalEvent.dataTransfer; + if (dataTransfer && dataTransfer.files && isXHRUploadCapable()) { + handleFiles(e, dataTransfer.files); + } + e.preventDefault(); + }; + + this.onChange = function (e) { + if (typeof settings.onChange === func && + settings.onChange(e) === false) { + return false; + } + var input = $(e.target), + form = $(e.target.form); + if (form.length === 1) { + input.data(defaultNamespace + '_form', form); + replaceFileInput(input); + } else { + form = input.data(defaultNamespace + '_form'); + } + if (!settings.forceIframeUpload && e.target.files && isXHRUploadCapable()) { + handleFiles(e, e.target.files, input, form); + } else { + handleLegacyUpload(e, input, form); + } + }; + + this.init = function (options) { + if (options) { + $.extend(settings, options); + optionsReference = options; + } + initUploadForm(); + initFileInput(); + if (container.data(settings.namespace)) { + $.error('FileUpload with namespace "' + settings.namespace + '" already assigned to this element'); + return; + } + container + .data(settings.namespace, fileUpload) + .addClass(settings.cssClass); + settings.dropZone.not(container).addClass(settings.cssClass); + initEventHandlers(); + }; + + this.options = function (options) { + var oldCssClass, + oldDropZone, + uploadFormFilterUpdate, + fileInputFilterUpdate; + if (typeof options === undef) { + return $.extend({}, settings); + } + if (optionsReference) { + $.extend(optionsReference, options); + } + removeEventHandlers(); + $.each(options, function (name, value) { + switch (name) { + case 'namespace': + $.error('The FileUpload namespace cannot be updated.'); + return; + case 'uploadFormFilter': + uploadFormFilterUpdate = true; + fileInputFilterUpdate = true; + break; + case 'fileInputFilter': + fileInputFilterUpdate = true; + break; + case 'cssClass': + oldCssClass = settings.cssClass; + break; + case 'dropZone': + oldDropZone = settings.dropZone; + break; + } + settings[name] = value; + }); + if (uploadFormFilterUpdate) { + initUploadForm(); + } + if (fileInputFilterUpdate) { + initFileInput(); + } + if (typeof oldCssClass !== undef) { + container + .removeClass(oldCssClass) + .addClass(settings.cssClass); + (oldDropZone ? oldDropZone : settings.dropZone).not(container) + .removeClass(oldCssClass); + settings.dropZone.not(container).addClass(settings.cssClass); + } else if (oldDropZone) { + oldDropZone.not(container).removeClass(settings.cssClass); + settings.dropZone.not(container).addClass(settings.cssClass); + } + initEventHandlers(); + }; + + this.option = function (name, value) { + var options; + if (typeof value === undef) { + return settings[name]; + } + options = {}; + options[name] = value; + fileUpload.options(options); + }; + + this.destroy = function () { + removeEventHandlers(); + container + .removeData(settings.namespace) + .removeClass(settings.cssClass); + settings.dropZone.not(container).removeClass(settings.cssClass); + }; + }; + + methods = { + init : function (options) { + return this.each(function () { + (new FileUpload($(this))).init(options); + }); + }, + + option: function (option, value, namespace) { + namespace = namespace ? namespace : defaultNamespace; + var fileUpload = $(this).data(namespace); + if (fileUpload) { + if (typeof option === 'string') { + return fileUpload.option(option, value); + } + return fileUpload.options(option); + } else { + $.error('No FileUpload with namespace "' + namespace + '" assigned to this element'); + } + }, + + destroy : function (namespace) { + namespace = namespace ? namespace : defaultNamespace; + return this.each(function () { + var fileUpload = $(this).data(namespace); + if (fileUpload) { + fileUpload.destroy(); + } else { + $.error('No FileUpload with namespace "' + namespace + '" assigned to this element'); + } + }); + + } + }; + + $.fn.fileUpload = function (method) { + if (methods[method]) { + return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); + } else if (typeof method === 'object' || !method) { + return methods.init.apply(this, arguments); + } else { + $.error('Method ' + method + ' does not exist on jQuery.fileUpload'); + } + }; + +}(jQuery)); \ No newline at end of file diff --git a/main/inc/lib/javascript/jquery-upload/pbar-ani.gif b/main/inc/lib/javascript/jquery-upload/pbar-ani.gif new file mode 100644 index 0000000000000000000000000000000000000000..0dfd45b885a2dd69a4c16febc5e886300cdb08e0 GIT binary patch literal 304064 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'; $js .= ''; } - - - - if (in_array('jquery-ui',$libraries)) { + + if (in_array('jquery-upload',$libraries)) { //Adding default CSS changes of the jquery-ui themes for Chamilo in order to preserve the original jquery-ui css - $js .= ''; + $js .= ''; + $js .= ''; + $js .= ''; } return $js; }