Trying to fix the LP scorm import/export still doesn't work for all cases (working on it) see #4706

skala
Julio Montoya 14 years ago
parent a763ae04b1
commit 78ee79ded6
  1. 59
      main/newscorm/download.php
  2. 65
      main/newscorm/learnpath.class.php
  3. 38
      main/newscorm/learnpathItem.class.php
  4. 8
      main/newscorm/lp_list.php
  5. 15
      main/newscorm/scorm.class.php

@ -0,0 +1,59 @@
<?php
/* For licensing terms, see /license.txt */
/**
* This file is responsible for passing requested documents to the browser.
*
* @package chamilo.document
*/
/**
* Code
* Many functions updated and moved to lib/document.lib.php
*/
session_cache_limiter('none');
require_once '../inc/global.inc.php';
$this_section = SECTION_COURSES;
// Protection
api_protect_course_script();
if (!isset($_course)) {
api_not_allowed(true);
}
$doc_url = $_GET['doc_url'];
// Change the '&' that got rewritten to '///' by mod_rewrite back to '&'
$doc_url = str_replace('///', '&', $doc_url);
// Still a space present? it must be a '+' (that got replaced by mod_rewrite)
$doc_url = str_replace(' ', '+', $doc_url);
$doc_url = str_replace(array('../', '\\..', '\\0', '..\\'), array('', '', '', ''), $doc_url); //echo $doc_url;
if (strpos($doc_url,'../') OR strpos($doc_url,'/..')) {
$doc_url = '';
}
$sys_course_path = api_get_path(SYS_COURSE_PATH).$_course['path'].'/scorm';
$user_id = api_get_user_id();
if ($_SESSION['oLP']) {
$lp_id = $_SESSION['oLP']->get_id();
$lp_item_id = $_SESSION['oLP']->current;
$lp_item_info = new learnpathItem($lp_item_id);
if (!empty($lp_item_info)) {
//if (basename($lp_item_info->path) == basename($doc_url)) {
$visible = $_SESSION['oLP']->is_lp_visible_for_student($lp_id, $user_id);
if ($visible) {
event_download($doc_url);
if (Security::check_abs_path($sys_course_path.$doc_url, $sys_course_path.'/')) {
$full_file_name = $sys_course_path.$doc_url;
DocumentManager::file_send_for_download($full_file_name);
exit;
}
}
//}
}
}
Display::display_error_message(get_lang('ProtectedDocument'));//api_not_allowed backbutton won't work.
exit;

@ -6676,7 +6676,12 @@ class learnpath {
if (!empty($item_path)) {
$extension = pathinfo($item_path, PATHINFO_EXTENSION);
}
if (($item_type == 'asset' || $item_type == 'sco') && ($extension == 'html' || $extension == 'htm')) {
//assets can't be modified
//$item_type == 'asset' ||
if (( $item_type == 'sco') && ($extension == 'html' || $extension == 'htm')) {
if ($item_type == 'sco') {
$form->addElement('html', '<script type="text/javascript">alert("' . get_lang('WarningWhenEditingScorm') . '")</script>');
}
@ -8128,12 +8133,12 @@ class learnpath {
$link_updates = array();
foreach ($this->items as $index => $item) {
if (!in_array($item->type, array(TOOL_QUIZ, TOOL_FORUM, TOOL_THREAD, TOOL_LINK, TOOL_STUDENTPUBLICATION))) {
// Get included documents from this item.
// Get included documents from this item
if ($item->type == 'sco')
$inc_docs = $item->get_resources_from_source(null, api_get_path(SYS_COURSE_PATH).api_get_course_path().'/'.'scorm/'.$this->path.'/'.$item->get_path());
else
$inc_docs = $item->get_resources_from_source();
// Give a child element <item> to the <organization> element.
$my_item_id = $item->get_id();
$my_item = $xmldoc->createElement('item');
@ -8179,7 +8184,6 @@ class learnpath {
$my_xml_file_path = str_replace($path_to_remove, $path_to_replace, $my_file_path);
}
$my_sub_dir = dirname($my_file_path);
$my_sub_dir = str_replace('\\', '/', $my_sub_dir);
//$my_xml_sub_dir = api_htmlentities(api_utf8_encode($my_sub_dir), ENT_QUOTES, 'UTF-8');
@ -8206,23 +8210,27 @@ class learnpath {
// Dependency to other files - not yet supported.
$i = 1;
foreach ($inc_docs as $doc_info) {
if (count($doc_info) < 1 || empty($doc_info[0])) { continue; }
$my_dep = $xmldoc->createElement('resource');
$res_id = 'RESOURCE_'.$item->get_id().'_'.$i;
$my_dep->setAttribute('identifier', $res_id);
$my_dep->setAttribute('type', 'webcontent');
$my_dep->setAttribute('adlcp:scormtype', 'asset');
$my_dep_file = $xmldoc->createElement('file');
// Check type of URL.
//error_log(__LINE__.'Now dealing with '.$doc_info[0].' of type '.$doc_info[1].'-'.$doc_info[2], 0);
if ($doc_info[1] == 'remote') {
// Remote file. Save url as is.
$my_dep_file->setAttribute('href', $doc_info[0]);
$my_dep->setAttribute('xml:base', '');
} elseif ($doc_info[1] == 'local') {
} elseif ($doc_info[1] == 'local') {
switch ($doc_info[2]) {
case 'url': // Local URL - save path as url for now, don't zip file.
$abs_path = api_get_path(SYS_PATH).str_replace(api_get_path(WEB_PATH), '', $doc_info[0]);
$current_dir = dirname($abs_path);
@ -8278,6 +8286,7 @@ class learnpath {
// Prepare the current directory path (until just under 'document') with a trailing slash.
$cur_path = substr($current_course_path, -1) == '/' ? $current_course_path : $current_course_path.'/';
// Check if the current document is in that path.
if (strstr($file_path, $cur_path) !== false) {
// The document is in that path, now get the relative path
// to the containing document.
@ -8285,14 +8294,21 @@ class learnpath {
$orig_file_path = str_replace('\\', '/', $orig_file_path);
$relative_path = '';
if (strstr($file_path, $cur_path) !== false) {
$relative_path = substr($file_path, strlen($orig_file_path));
$file_path = substr($file_path, strlen($cur_path));
if (strpos($orig_file_path, $file_path) == false) {
//no need to do something
$file_path = $relative_path = substr($file_path, strlen($cur_path));
} else {
$relative_path = substr($file_path, strlen($orig_file_path));
$file_path = substr($file_path, strlen($cur_path));
}
} else {
// This case is still a problem as it's difficult to calculate a relative path easily
// might still generate wrong links.
//$file_path = substr($file_path,strlen($cur_path));
// Calculate the directory path to the current file (without trailing slash).
$my_relative_path = dirname($file_path);
$my_relative_path = str_replace('\\', '/', $my_relative_path);
$my_relative_file = basename($file_path);
// Calculate the directory path to the containing file (without trailing slash).
@ -8310,11 +8326,13 @@ class learnpath {
}
$relative_path = $dotdot.$subdir.$my_relative_file;
}
// Put the current document in the zip (this array is the array
// that will manage documents already in the course folder - relative).
$zip_files[] = $file_path;
// Update the links to the current document in the containing document (make them relative).
$link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => $relative_path);
$my_dep_file->setAttribute('href', $file_path);
$my_dep->setAttribute('xml:base', '');
} elseif (strstr($file_path,$main_path) !== false) {
@ -8343,13 +8361,16 @@ class learnpath {
}
}
break;
case 'rel': // Path relative to the current document. Save xml:base as current document's directory and save file in zip as subdir.file_path
case 'rel': // Path relative to the current document. Save xml:base as current document's directory and save file in zip as subdir.file_path
if (substr($doc_info[0], 0, 2) == '..') {
// Relative path going up.
$current_dir = dirname($current_course_path.'/'.$item->get_file_path()).'/';
$current_dir = str_replace('\\', '/', $current_dir);
$file_path = realpath($current_dir.$doc_info[0]);
$file_path = str_replace('\\', '/', $file_path);
//error_log($file_path.' <-> '.$main_path,0);
if (strstr($file_path, $main_path) !== false) {
// The calculated real path is really inside Chamilo's root path.
@ -8361,7 +8382,7 @@ class learnpath {
$my_dep_file->setAttribute('href', 'document/'.$file_path);
$my_dep->setAttribute('xml:base', '');
}
} else {
} else {
$zip_files[] = $my_sub_dir.'/'.$doc_info[0];
$my_dep_file->setAttribute('href', $doc_info[0]);
$my_dep->setAttribute('xml:base', $my_xml_sub_dir);
@ -8575,7 +8596,7 @@ class learnpath {
$zip_files[] = $my_sub_dir.'/'.$file_path;
$link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => 'document/'.$file_path);
$my_dep_file->setAttribute('href', 'document/'.$file_path);
$my_dep->setAttribute('xml:base', '');
$my_dep->setAttribute('xml:base', '');
}
}
break;
@ -8609,7 +8630,7 @@ class learnpath {
$zip_files[] = $my_sub_dir.'/'.$file_path;
$link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => $file_path);
$my_dep_file->setAttribute('href', 'document/'.$file_path);
$my_dep->setAttribute('xml:base', '');
$my_dep->setAttribute('xml:base', '');
}
}
break;
@ -8704,7 +8725,8 @@ class learnpath {
// http://www.reload.ac.uk/scormplayer.html - once done, don't forget to close FS#138
//error_log(print_r($zip_files,true), 0);
$root = api_get_path(SYS_PATH);
foreach ($zip_files as $file_path) {
if (empty($file_path)) { continue; }
@ -8718,12 +8740,13 @@ class learnpath {
$this->create_path($dest_file);
//error_log('copy '.api_get_path(SYS_COURSE_PATH).$_course['path'].'/'.$file_path.' to '.api_get_path(SYS_ARCHIVE_PATH).$temp_dir_short.'/'.$file_path,0);
//echo $main_path.$file_path.'<br />';
@copy($sys_course_path.$_course['path'].'/'.$file_path, $dest_file);
// Check if the file needs a link update
if (in_array($file_path, array_keys($link_updates))) {
$string = file_get_contents($dest_file);
unlink($dest_file);
unlink($dest_file);
foreach ($link_updates[$file_path] as $old_new) {
//error_log('Replacing '.$old_new['orig'].' by '.$old_new['dest'].' in '.$file_path, 0);
// This is an ugly hack that allows .flv files to be found by the flv player that
@ -8732,11 +8755,18 @@ class learnpath {
// ../../.. to return from inc/lib/flv_player to the document/main path.
if (substr($old_new['dest'], -3) == 'flv' && substr($old_new['dest'], 0, 5) == 'main/') {
$old_new['dest'] = str_replace('main/', '../../../', $old_new['dest']);
}
elseif (substr($old_new['dest'], -3) == 'flv' && substr($old_new['dest'], 0, 6) == 'video/') {
} elseif (substr($old_new['dest'], -3) == 'flv' && substr($old_new['dest'], 0, 6) == 'video/') {
$old_new['dest'] = str_replace('video/', '../../../../video/', $old_new['dest']);
}
$string = str_replace($old_new['orig'], $old_new['dest'], $string);
//Add files inside the HTMLs
$new_path = str_replace('/courses/', '', $old_new['orig']);
/*var_dump($sys_course_path.$new_path);
var_dump($archive_path.$temp_dir_short.'/document/'.$old_new['dest']);
echo '---';*/
copy($sys_course_path.$new_path, $archive_path.$temp_dir_short.'/document/'.$old_new['dest']);
}
file_put_contents($dest_file, $string);
}
@ -9073,9 +9103,6 @@ EOD;
$course_restorer->set_tool_copy_settings(array('learnpaths' => array('reset_dates' => true)));
$course_restorer->restore(api_get_course_id(), api_get_session_id(), false, false);
}
}
if (!function_exists('trim_value')) {

@ -725,6 +725,7 @@ class learnpathItem {
//error_log(str_repeat(' ',$recursivity).'Analyse file '.$abs_path, 0);
$files_list = array();
$type = $this->get_type();
switch ($type) {
case TOOL_DOCUMENT :
case TOOL_QUIZ:
@ -734,8 +735,10 @@ class learnpathItem {
if (is_file($abs_path)) {
// for now, read the whole file in one go (that's gonna be a problem when the file is too big).
$info = pathinfo($abs_path);
$ext = $info['extension'];
switch(strtolower($ext)) {
switch (strtolower($ext)) {
case 'html':
case 'htm':
case 'shtml':
@ -745,12 +748,13 @@ class learnpathItem {
$file_content = file_get_contents($abs_path);
// Get an array of attributes from the HTML source.
$attributes = DocumentManager::parse_HTML_attributes($file_content, $wanted_attributes);
// Look at 'src' attributes in this file.
// Look at 'src' attributes in this file
foreach ($wanted_attributes as $attr) {
if (isset($attributes[$attr])) {
// Find which kind of path these are (local or remote).
$sources = $attributes[$attr];
foreach ($sources as $source) {
// Skip what is obviously not a resource.
if (strpos($source, "+this.")) continue; // javascript code - will still work unaltered.
@ -759,15 +763,15 @@ class learnpathItem {
if (strpos($source, ';') && !strpos($source, '&amp;')) continue; // Avoid code - that should help.
if ($attr == 'value') {
if (strpos($source , 'mp3file')) {
if (strpos($source , 'mp3file')) {
$files_list[] = array(substr($source, 0, strpos($source , '.swf') + 4), 'local', 'abs');
$mp3file = substr($source , strpos($source , 'mp3file=') + 8);
if (substr($mp3file, 0, 1) == '/')
$files_list[] = array($mp3file, 'local', 'abs');
else
$files_list[] = array($mp3file, 'local', 'rel');
}
elseif (strpos($source, 'flv=') === 0) {
} elseif (strpos($source, 'flv=') === 0) {
$source = substr($source, 4);
if (strpos($source, '&') > 0) {
$source = substr($source, 0, strpos($source, '&'));
@ -786,6 +790,7 @@ class learnpathItem {
continue; // Skipping anything else to avoid two entries (while the others can have sub-files in their url, flv's can't).
}
}
if (strpos($source, '://') > 0) {
// Cut at '?' in a URL with params.
@ -808,8 +813,7 @@ class learnpathItem {
// We didn't find any trace of current portal.
$files_list[] = array($second_part, 'remote', 'url');
}
}
elseif(strpos($second_part, '=') > 0) {
} elseif(strpos($second_part, '=') > 0) {
if (substr($second_part, 0, 1) === '/') {
// Link starts with a /, making it absolute (relative to DocumentRoot).
$files_list[] = array($second_part, 'local', 'abs');
@ -817,8 +821,7 @@ class learnpathItem {
if (count($in_files_list) > 0) {
$files_list = array_merge($files_list, $in_files_list);
}
}
elseif(strstr($second_part, '..') === 0) {
} elseif(strstr($second_part, '..') === 0) {
// Link is relative but going back in the hierarchy.
$files_list[] = array($second_part, 'local', 'rel');
$dir = dirname($abs_path);
@ -889,6 +892,7 @@ class learnpathItem {
}
}
}
// Found some protocol there.
if (strpos($source, api_get_path(WEB_PATH)) !== false) {
// We found the current portal url.
@ -903,15 +907,14 @@ class learnpathItem {
}
} else {
// No protocol found, make link local.
if (substr($source, 0, 1) === '/') {
if (substr($source, 0, 1) === '/') {
// Link starts with a /, making it absolute (relative to DocumentRoot).
$files_list[] = array($source, 'local', 'abs');
$in_files_list[] = learnpathItem::get_resources_from_source(TOOL_DOCUMENT, $source, $recursivity + 1);
if (count($in_files_list) > 0) {
$files_list = array_merge($files_list, $in_files_list);
}
}
elseif (strstr($source, '..') === 0) {
} elseif (strstr($source, '..') === 0) {
// Link is relative but going back in the hierarchy.
$files_list[] = array($source, 'local', 'rel');
$dir = dirname($abs_path);
@ -921,10 +924,15 @@ class learnpathItem {
$files_list = array_merge($files_list, $in_files_list);
}
} else {
// No starting '/', making it relative to current document's path.
if (strpos($source, 'width=') || strpos($source, 'autostart=')) {
continue;
}
if (substr($source, 0, 2) == './') {
$source = substr($source, 2);
}
}
$files_list[] = array($source, 'local', 'rel');
$dir = dirname($abs_path);
$new_abs_path = realpath($dir.'/'.$source);
@ -961,7 +969,7 @@ class learnpathItem {
$checked_array_list[] = $files_list[$idx];
}
}
}
}
return $checked_array_list;
}

@ -412,16 +412,16 @@ if (!empty($flat_list)) {
/* Export */
if ($details['lp_type'] == 1) {
$dsp_disk = Display::url(Display::return_icon('export_scorm.png', get_lang('Export'), array(), ICON_SIZE_SMALL), api_get_self()."?".api_get_cidreq()."&action=export&lp_id=$id");
$dsp_disk = Display::url(Display::return_icon('cd.gif', get_lang('Export'), array(), ICON_SIZE_SMALL), api_get_self()."?".api_get_cidreq()."&action=export&lp_id=$id");
} elseif ($details['lp_type'] == 2) {
$dsp_disk = Display::url(Display::return_icon('export_scorm.png', get_lang('Export'), array(), ICON_SIZE_SMALL), api_get_self()."?".api_get_cidreq()."&action=export&lp_id=$id&export_name=".replace_dangerous_char($name, 'strict').".zip");
$dsp_disk = Display::url(Display::return_icon('cd.gif', get_lang('Export'), array(), ICON_SIZE_SMALL), api_get_self()."?".api_get_cidreq()."&action=export&lp_id=$id&export_name=".replace_dangerous_char($name, 'strict').".zip");
} else {
$dsp_disk = Display::return_icon('export_scorm_na.png', get_lang('Export'), array(), ICON_SIZE_SMALL);
$dsp_disk = Display::return_icon('cd_gray.gif', get_lang('Export'), array(), ICON_SIZE_SMALL);
}
//Copy
$copy = Display::url(Display::return_icon('cd.gif', get_lang('Copy'), array(), ICON_SIZE_SMALL), api_get_self()."?".api_get_cidreq()."&action=copy&lp_id=$id");
$copy = Display::url(Display::return_icon('cd_copy.png', get_lang('Copy'), array(), ICON_SIZE_SMALL), api_get_self()."?".api_get_cidreq()."&action=copy&lp_id=$id");
/* Auto Lunch LP code*/
$lp_auto_lunch_icon = '';

@ -271,6 +271,7 @@ class scorm extends learnpath {
$new_lp = Database::get_course_table(TABLE_LP_MAIN);
$new_lp_item = Database::get_course_table(TABLE_LP_ITEM);
$use_max_score = intval($use_max_score);
foreach ($this->organizations as $id => $dummy) {
$is_session = api_get_session_id();
$is_session != 0 ? $session_id = $is_session : $session_id = 0;
@ -297,6 +298,7 @@ class scorm extends learnpath {
$res = Database::query($sql);
$lp_id = Database::insert_id();
$this->lp_id = $lp_id;
// Insert into item_property.
api_item_property_update(api_get_course_info($course_code), TOOL_LEARNPATH, $this->lp_id, 'LearnpathAdded', api_get_user_id());
api_item_property_update(api_get_course_info($course_code), TOOL_LEARNPATH, $this->lp_id, 'visible', api_get_user_id());
@ -308,6 +310,7 @@ class scorm extends learnpath {
$parent = 0;
$previous = 0;
$level = 0;
foreach ($list as $item) {
if ($item['level'] > $level) {
// Push something into the parents array.
@ -363,6 +366,7 @@ class scorm extends learnpath {
$identifier = Database::escape_string($item['identifier']);
$prereq = Database::escape_string($item['prerequisites']);
$sql_item = "INSERT INTO $new_lp_item (c_id, lp_id,item_type,ref,title, path,min_score,max_score, $field_add parent_item_id,previous_item_id,next_item_id, prerequisite,display_order,launch_data, parameters) VALUES " .
"($course_id, $lp_id, '$type','".$identifier."','".$title."'," .
"'$path',0,$max_score, $value_add" .
@ -461,6 +465,7 @@ class scorm extends learnpath {
$zip_file_path = $zip_file_info['tmp_name'];
$zip_file_name = $zip_file_info['name'];
if ($this->debug > 1) { error_log('New LP - import_package() - zip file path = '.$zip_file_path.', zip file name = '.$zip_file_name, 0); }
$course_rel_dir = api_get_course_path().'/scorm'; // scorm dir web path starting from /courses
$course_sys_dir = api_get_path(SYS_COURSE_PATH).$course_rel_dir; // Absolute system path for this course.
@ -493,7 +498,8 @@ class scorm extends learnpath {
$manifest_list = array();
// The following loop should be stopped as soon as we found the right imsmanifest.xml (how to recognize it?).
foreach ($zipContentArray as $thisContent) {
foreach ($zipContentArray as $thisContent) {
$thisContent['filename'];
//error_log('Looking at '.$thisContent['filename'], 0);
if (preg_match('~.(php.*|phtml)$~i', $thisContent['filename'])) {
$this->set_error_msg("File $file contains a PHP script");
@ -514,6 +520,7 @@ class scorm extends learnpath {
}
$realFileSize += $thisContent['size'];
}
// Now get the shortest path (basically, the imsmanifest that is the closest to the root).
$shortest_path = $manifest_list[0];
$slash_count = substr_count($shortest_path, '/');
@ -565,6 +572,7 @@ class scorm extends learnpath {
$saved_dir = getcwd();
chdir($course_sys_dir.$new_dir);
$unzippingState = $zipFile->extract();
for ($j = 0; $j < count($unzippingState); $j++) {
$state = $unzippingState[$j];
@ -596,10 +604,11 @@ class scorm extends learnpath {
if ($this->debug >= 1) { error_log('Comparing: '.$safe_file, 0); }
if ($this->debug >= 1) { error_log('and: '.$file, 0); }
if ($safe_file != $file) {
//@rename($course_sys_dir.$new_dir, $course_sys_dir.'/'.$safe_file);
$mydir = dirname($course_sys_dir.$new_dir.$safe_file);
if (!is_dir($mydir)) {
$mysubdirs = split('/', $mydir);
$mybasedir = '/';
@ -746,7 +755,7 @@ class scorm extends learnpath {
require_once api_get_path(LIBRARY_PATH).'fileUpload.lib.php';
require_once api_get_path(LIBRARY_PATH).'fileManage.lib.php';
require_once api_get_path(LIBRARY_PATH).'document.lib.php';
require_once api_get_path(LIBRARY_PATH).'pclzip/pclzip.lib.php';
require_once 'learnpath_functions.inc.php';
$course_id = api_get_course_int_id();
$tbl_lp = Database::get_course_table(TABLE_LP_MAIN);

Loading…
Cancel
Save