Putting SCORM into maintree CVS, to make it easier to test.
authormoodler <moodler>
Thu, 20 May 2004 17:06:19 +0000 (17:06 +0000)
committermoodler <moodler>
Thu, 20 May 2004 17:06:19 +0000 (17:06 +0000)
It's getting pretty useful now!

27 files changed:
mod/scorm/README.txt [new file with mode: 0644]
mod/scorm/api1_2.php [new file with mode: 0644]
mod/scorm/cmi.php [new file with mode: 0755]
mod/scorm/coursefiles.php [new file with mode: 0755]
mod/scorm/db/mysql.php [new file with mode: 0755]
mod/scorm/db/mysql.sql [new file with mode: 0755]
mod/scorm/db/postgres7.php [new file with mode: 0755]
mod/scorm/db/postgres7.sql [new file with mode: 0755]
mod/scorm/details.php [new file with mode: 0755]
mod/scorm/icon.gif [new file with mode: 0755]
mod/scorm/index.php [new file with mode: 0755]
mod/scorm/lib.php [new file with mode: 0755]
mod/scorm/mod.html [new file with mode: 0755]
mod/scorm/pix/browsed.gif [new file with mode: 0755]
mod/scorm/pix/completed.gif [new file with mode: 0755]
mod/scorm/pix/failed.gif [new file with mode: 0755]
mod/scorm/pix/incomplete.gif [new file with mode: 0755]
mod/scorm/pix/minus.gif [new file with mode: 0755]
mod/scorm/pix/notattempted.gif [new file with mode: 0755]
mod/scorm/pix/passed.gif [new file with mode: 0755]
mod/scorm/pix/plus.gif [new file with mode: 0755]
mod/scorm/pix/spacer.gif [new file with mode: 0755]
mod/scorm/playscorm.php [new file with mode: 0755]
mod/scorm/report.php [new file with mode: 0755]
mod/scorm/scormAPI.php [new file with mode: 0755]
mod/scorm/version.php [new file with mode: 0755]
mod/scorm/view.php [new file with mode: 0755]

diff --git a/mod/scorm/README.txt b/mod/scorm/README.txt
new file mode 100644 (file)
index 0000000..585c253
--- /dev/null
@@ -0,0 +1,24 @@
+SCORM Module by Roberto "Bobo" Pinna
+
+The current module version seem to work fine but I tried it only with 3/4 SCORM courses (Marine Navigation distribuited with ADL RTE 1.2 and some courses developed by our course team). 
+
+I try to explain how SCORM module works:
+SCORM packages come in .zip or .pif (is a zip file with another extension);
+Like any other file we must upload the package using the files page.
+
+    * Create an activity:
+      When we create a new activity, we can choose from a popup menu the right package.
+      After that, on continue, the package is checked and validated (the current version check only if the package contains a imsmanifest.xml file; future versions will check if this file is well formed and other);
+      This operation creates a record in the scorm table and a directory containing the unpacked SCORM course.
+    * View an activity:
+      The first time someone try to view a SCORM activity the module parse the imsmanifest file and insert a record for every manifest item in the scorm_scoes table.
+      Then the module show the course summary with two buttons of three, browse and review or enter the course.
+      When we click one of them will load an new page that will show the first SCO or the last viewed not completed SCO.
+    * Activity report:
+      I develop also a begining report page that show the status of every SCO in the SCORM and the time spent in each SCO.
+
+If anyone what to help me to design and develop this module is welcome.
+
+Sorry for my poor English.
+
+Bobo
diff --git a/mod/scorm/api1_2.php b/mod/scorm/api1_2.php
new file mode 100644 (file)
index 0000000..25231d1
--- /dev/null
@@ -0,0 +1,304 @@
+//
+// CMI Initialization SCORM 1.2
+//
+       var cmi= new Object();
+       
+       cmi.core = new Object();
+       cmi.core._children = "student_id,student_name,lesson_location,credit,lesson_status,exit,entry,session_time,total_time,lesson_mode,score,suspend_data,launch_data";
+       cmi.core.student_id = "<?php echo $USER->username ?>";
+       cmi.core.student_name = "<?php echo $USER->firstname." ".$USER->lastname ?>";
+       cmi.core.lesson_location = "<?php echo $sco_user->cmi_core_lesson_location ?>";
+       cmi.core.credit = "credit";
+       cmi.core.lesson_status = "<?php echo $sco_user->cmi_core_lesson_status ?>";
+       cmi.core.exit = "<?php echo $sco_user->cmi_core_exit ?>";
+       cmi.core.entry = "<?php if ($sco_user->cmi_core_lesson_status=="not attempted") 
+                                   echo 'ab-initio'; 
+                               else 
+                                   if ($sco_user->cmi_core_lesson_status!="completed") 
+                                       echo 'resume'; 
+                                   else 
+                                       echo '';?>";
+       cmi.core.session_time = "<?php echo $sco_user->cmi_core_session_time ?>";
+       cmi.core.total_time = "<?php echo $sco_user->cmi_core_total_time ?>";
+       cmi.core.lesson_mode = "<?php echo $_GET["mode"] ?>";
+       
+       cmi.core.score = new Object();
+       cmi.core.score._children = "raw";
+       cmi.core.score.raw = "<?php echo $sco_user->cmi_core_score_raw ?>";
+       cmi.suspend_data = "<?php echo $sco_user->cmi_suspend_data ?>";
+       cmi.launch_data = "<?php echo $sco_user->cmi_launch_data ?>";
+/*     cmi.interactions = new Object();
+       cmi.interactions._children = "id,objectives,time,type,correct_responses,weighting,student_response,result,latency";
+       cmi.interactions._count = 0;
+*/
+       var errorCode = 0;
+
+//
+// end CMI Initialization
+//
+
+
+// 
+// SCORM API 1.2 Implementation
+//
+function SCORMapi() {
+    var Initialized = false;
+
+    function LMSInitialize (param) {
+       if (param != "") {
+           errorCode = 201;
+           return "false";
+       }
+       if (!Initialized) {
+           Initialized = true;
+           errorCode = 0;
+           return "true";
+       } else {
+           errorCode = 101;
+           return "false";
+       }
+    }
+    
+    function LMSGetValue (param) {
+       if (Initialized) {
+           //top.status="GET "+param;
+           switch (param) {
+               case "cmi.core._children":
+               case "cmi.core.student_id":
+               case "cmi.core.student_name":
+               case "cmi.core.lesson_location":
+               case "cmi.core.credit":
+               case "cmi.core.lesson_status":
+               case "cmi.core.entry":
+               case "cmi.core.total_time":
+               case "cmi.core.lesson_mode":
+               case "cmi.core.score._children":
+               case "cmi.core.score.raw":
+               case "cmi.launch_data":
+               case "cmi.suspend_data":
+                   errorCode = 0;
+                   return eval(param);
+               break;
+               case "cmi.core.exit":
+               case "cmi.core.session_time":
+                   errorCode = 404;
+                   return "";
+               break;
+               default:
+                   errorCode = 401;
+                   return "";
+               break;
+           }
+       } else {
+           errorCode = 301;
+           return "";
+       }
+    }
+    
+    function LMSSetValue (param,value) {
+       if (Initialized) {
+           //top.status="SET "+param+" = "+value;
+           switch (param) {
+               case "cmi.core.session_time":
+                   cmi.core.total_time = AddTime(cmi.core.total_time, value);
+                   //top.status="SET cmi.core.total_time = "+cmi.core.total_time;
+                   eval(param+'="'+value+'";');
+                   errorCode = 0;
+                   return "true";
+               break;
+               case "cmi.core.lesson_status":
+                   if ((value!="passed")&&(value!="completed")&&(value!="failed")&&(value!="incomplete")&&(value!="browsed")) {
+                       errorCode = 405;
+                       return "false";
+                   }
+                   eval(param+'="'+value+'";');
+                   errorCode = 0;
+                   return "true";
+               break;
+               case "cmi.core.score.raw":
+                   if ((parseFloat(value,10)).toString() != value) {
+                       errorCode = 405;
+                       return "false";
+                   }
+                   eval(param+'="'+value+'";');
+                   errorCode = 0;
+                   return "true";
+               break;
+               case "cmi.core.exit":
+                   if ((value!="time-out")&&(value!="suspend")&&(value!="logout")&&(value!="")) {
+                       errorCode = 405;
+                       return "false";
+                   }
+                   eval(param+'="'+value+'";');
+                   errorCode = 0;
+                   return "true";
+               break;
+               case "cmi.core.lesson_location":
+               case "cmi.suspend_data":
+                   eval(param+'="'+value+'";');
+                   errorCode = 0;
+                   return "true";
+               break;
+               case "cmi.core._children":
+               case "cmi.core.score._children":
+                   errorCode = 402;
+                   return "false";
+               break;
+               case "cmi.core.student_id":
+               case "cmi.core.student_name":
+               case "cmi.core.credit":
+               case "cmi.core.entry":
+               case "cmi.core.total_time":
+               case "cmi.core.lesson_mode":
+               case "cmi.launch_data":
+                   errorCode = 403;
+                   return "false";
+               break;
+               default:
+                   //errorCode = 401;  This is more correct but may have problem with some SCOes
+                   errorCode = 0; // With this disable any possible SCO errors alert
+                   return "false";
+               break;
+           }
+       } else {
+           errorCode = 301;
+           return "false";
+       }
+    }
+
+    function LMSCommit (param) {
+       if (param != "") {
+           errorCode = 201;
+           return "false";
+       }
+       if (Initialized) {
+           if (top.nav.cmi.document.theform) {
+               cmiform = top.nav.cmi.document.forms[0];
+               cmiform.scoid.value = "<?php echo  $sco->id ?>";
+               cmiform.cmi_core_lesson_location.value = cmi.core.lesson_location;
+               cmiform.cmi_core_lesson_status.value = cmi.core.lesson_status;
+               cmiform.cmi_core_exit.value = cmi.core.exit;
+               cmiform.cmi_core_session_time.value = cmi.core.session_time;
+               cmiform.cmi_core_total_time.value = cmi.core.total_time;
+               cmiform.cmi_core_score_raw.value = cmi.core.score.raw;
+               cmiform.cmi_suspend_data.value = cmi.suspend_data;
+               cmiform.submit();
+           }
+           errorCode = 0;
+           return "true";
+       } else {
+           errorCode = 301;
+           return "false";
+       }
+    }
+    
+    function LMSFinish (param) {
+       if (param != "") {
+           errorCode = 201;
+           return "false";
+       }
+       if (!Initialized) {
+           errorCode = 301;
+           return "false";
+       } else {
+           Initialized = false;
+           errorCode = 0;
+            <?php
+                if ($scorm->auto) {
+                    if ($sco != $last) {
+                        print "setTimeout('top.nav.document.navform.next.click();',500);\n";
+                    } else {
+                        print "exitloc = '".$CFG->wwwroot."/mod/scorm/view.php?id=$cm->id';\n";
+                        print "setTimeout('top.location = exitloc;',500);\n";
+                    }
+               } 
+           ?>
+           return "true";
+       }    
+    }
+    
+    function LMSGetLastError () {
+       return errorCode;
+    }
+    
+    function LMSGetErrorString (param) {
+       var errorString = new Array();
+       errorString["0"] = "No error";
+       errorString["101"] = "General exception";
+       errorString["201"] = "Invalid argument error";
+       errorString["202"] = "Element cannot have children";
+       errorString["203"] = "Element not an array - cannot have count";
+       errorString["301"] = "Not initializated";
+       errorString["401"] = "Not implemented error";
+       errorString["402"] = "Invalid set value, element is a keyword";
+       errorString["403"] = "Element is read only";
+       errorString["404"] = "Element is write only";
+       errorString["405"] = "Incorrect data type";
+       return errorString[param];
+    }
+    
+    function LMSGetDiagnostic (param) {
+       return param;
+    }
+       
+    function AddTime (first, second) {
+       var sFirst = first.split(":");
+       var sSecond = second.split(":");
+       var change = 0;
+       
+       var secs = (Math.round((parseFloat(sFirst[2],10)+parseFloat(sSecond[2],10))*100))/100;  //Seconds
+       if (secs > 60) {
+           secs = secs - 60;
+           change = 1;
+       } else {
+           change = 0;
+       }
+       if (Math.floor(secs) < 10) secs = "0" + secs.toString();
+       
+       mins = parseInt(sFirst[1],10)+parseInt(sSecond[1],10)+change;   //Minutes
+       if (mins > 60) 
+           change = 1;
+       else
+           change = 0;
+       if (mins < 10) mins = "0" + mins.toString();
+           
+       hours = parseInt(sFirst[0],10)+parseInt(sSecond[0],10)+change;  //Hours
+       if (hours < 10) hours = "0" + hours.toString();
+       
+       return hours + ":" + mins + ":" + secs;
+    }
+    this.LMSInitialize = LMSInitialize;
+    this.LMSGetValue = LMSGetValue;
+    this.LMSSetValue = LMSSetValue;
+    this.LMSCommit = LMSCommit;
+    this.LMSFinish = LMSFinish;
+    this.LMSGetLastError = LMSGetLastError;
+    this.LMSGetErrorString = LMSGetErrorString;
+    this.LMSGetDiagnostic = LMSGetDiagnostic;
+}
+
+var API = new SCORMapi();
+
+function SCOInitialize() { 
+<?php
+    if ( $sco->previous || $first) {
+       print "\ttop.nav.document.navform.prev.disabled = true;\n";
+       print "\ttop.nav.document.navform.prev.style.display = 'none';\n";
+    }
+    if ( $sco->next || $last) {
+       print "\ttop.nav.document.navform.next.disabled = true;\n";
+       print "\ttop.nav.document.navform.next.style.display = 'none';\n";
+    }
+?>
+       top.main.location="<?php echo $result ?>";
+} 
+
+function changeSco(direction) {
+       if (direction == "prev")
+           top.nav.document.navform.scoid.value="<?php echo $prevsco ?>";
+       else
+           top.nav.document.navform.scoid.value="<?php echo $nextsco ?>";
+           
+       //alert ("Prev: <?php echo $prevsco ?>\nNext: <?php echo $nextsco ?>\nNew SCO: "+top.nav.document.navform.scoid.value);
+       top.nav.document.navform.submit();
+}
diff --git a/mod/scorm/cmi.php b/mod/scorm/cmi.php
new file mode 100755 (executable)
index 0000000..32f08de
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+    require_once("../../config.php");
+    require_once("lib.php");
+    
+    optional_variable($id);    // Course Module ID, or
+    optional_variable($a);     // scorm ID
+
+    if ($id) {
+        if (! $cm = get_record("course_modules", "id", $id)) {
+            error("Course Module ID was incorrect");
+        }
+    
+        if (! $course = get_record("course", "id", $cm->course)) {
+            error("Course is misconfigured");
+        }
+    
+        if (! $scorm = get_record("scorm", "id", $cm->instance)) {
+            error("Course module is incorrect");
+        }
+
+    } else {
+        if (! $scorm = get_record("scorm", "id", $a)) {
+            error("Course module is incorrect");
+        }
+        if (! $course = get_record("course", "id", $scorm->course)) {
+            error("Course is misconfigured");
+        }
+        if (! $cm = get_coursemodule_from_instance("scorm", $scorm->id, $course->id)) {
+            error("Course Module ID was incorrect");
+        }
+    }
+
+    require_login($course->id);
+    
+    if ($_POST["scoid"]) {
+       set_field("scorm_sco_users","cmi_core_lesson_location",$_POST["cmi_core_lesson_location"],"scoid",$_POST["scoid"],"userid",$USER->id);
+        set_field("scorm_sco_users","cmi_core_lesson_status",$_POST["cmi_core_lesson_status"],"scoid",$_POST["scoid"],"userid",$USER->id);
+        set_field("scorm_sco_users","cmi_core_exit",$_POST["cmi_core_exit"],"scoid",$_POST["scoid"],"userid",$USER->id);
+        set_field("scorm_sco_users","cmi_core_session_time",$_POST["cmi_core_session_time"],"scoid",$_POST["scoid"],"userid",$USER->id);
+        set_field("scorm_sco_users","cmi_core_total_time",$_POST["cmi_core_total_time"],"scoid",$_POST["scoid"],"userid",$USER->id);
+        set_field("scorm_sco_users","cmi_core_score_raw",$_POST["cmi_core_score_raw"],"scoid",$_POST["scoid"],"userid",$USER->id);
+        set_field("scorm_sco_users","cmi_suspend_data",$_POST["cmi_suspend_data"],"scoid",$_POST["scoid"],"userid",$USER->id);
+    /*    if ($scorm->auto)
+            $result="<script language=\"Javascript\">\n\ttop.nav.document.navform.next.click();\n    </script>\n"; */
+    }
+?>
+<html>
+<head>
+   <title>cmi</title>
+</head>
+<body>
+   <form name="theform" method="POST" action="<?php echo $_SERVER["PHP_SELF"] ?>?id=<?php echo $cm->id ?>"> 
+       <input type="hidden" name="scoid" />
+       <input type="hidden" name="cmi_core_lesson_location" />
+       <input type="hidden" name="cmi_core_lesson_status" />
+       <input type="hidden" name="cmi_core_exit" />
+       <input type="hidden" name="cmi_core_session_time" />
+       <input type="hidden" name="cmi_core_total_time" />
+       <input type="hidden" name="cmi_core_score_raw" />
+       <input type="hidden" name="cmi_suspend_data" />
+   </form>
+   <?php echo $result?>
+</body>
+</html>
diff --git a/mod/scorm/coursefiles.php b/mod/scorm/coursefiles.php
new file mode 100755 (executable)
index 0000000..0414315
--- /dev/null
@@ -0,0 +1,855 @@
+<?PHP // $Id$
+
+//  Manage ONLY ZIP & PIF uploaded files in a course file area
+
+//  This file is a hack to files/index.php that removes
+//  the headers and adds some controls so that images
+//  can be selected within the Richtext editor.  
+
+//  All the Moodle-specific stuff is in this top section
+//  Configuration and access control occurs here.
+//  Must define:  USER, basedir, baseweb, html_header and html_footer
+//  USER is a persistent variable using sessions
+
+    require("../../config.php");
+    require("../../files/mimetypes.php");
+
+    require_variable($id);
+    optional_variable($file, "");
+    optional_variable($wdir, "");
+    optional_variable($action, "");
+
+    if (! $course = get_record("course", "id", $id) ) {
+        error("That's an invalid course id");
+    }
+
+    require_login($course->id);
+
+    if (! isteacher($course->id) ) {
+        error("Only teachers can edit files");
+    }
+
+    function html_footer() {
+        echo "</td></tr></table></body></html>";
+    }
+    
+    function html_header($course, $wdir, $formfield=""){
+
+        global $CFG,$THEME;
+
+        if (! $site = get_site()) {
+            error("Invalid site!");
+        }
+
+        if ($course->id == $site->id) {
+            $strfiles = get_string("sitefiles");
+        } else {
+            $strfiles = get_string("files");
+        }
+    
+        if ($wdir == "/") {
+            $fullnav = "$strfiles";
+        } else {
+            $dirs = explode("/", $wdir);
+            $numdirs = count($dirs);
+            $link = "";
+            $navigation = "";
+            for ($i=1; $i<$numdirs; $i++) {
+               $navigation .= " -> ";
+               $link .= "/".urlencode($dirs[$i]);
+               $navigation .= "<a href=\"".$_SERVER['PHP_SELF']."?id=$course->id&wdir=$link\">".$dirs[$i]."</a>";
+            }
+            $fullnav = "<a href=\"".$_SERVER['PHP_SELF']."?id=$course->id&wdir=/\">$strfiles</a> $navigation";
+        }
+
+        print_header();
+        ?>
+           <script language="javascript" type="text/javascript">
+           <!--
+           function set_value(txt) {
+                   opener.document.forms['form'].reference.value = txt;
+                   window.close();
+           }
+        -->
+           </script>
+        <?php
+
+        echo '<table border="0" cellpadding="3" cellspacing="0" width="100%">';
+        echo '<tr>';
+        echo '<td bgcolor="'.$THEME->cellheading.'" class="navbar">';
+        echo '<font size="2"><b>'."$course->shortname -> $fullnav".'</b></font>';
+        echo '</td>';
+        echo '</tr>';
+        echo '</table>';
+
+        if ($course->id == $site->id) {
+            print_heading(get_string("publicsitefileswarning"), "center", 2);
+        }
+
+        echo "<table border=0 align=center cellspacing=3 cellpadding=3 width=640>";
+        echo "<tr>";
+        echo "<td colspan=\"2\">";
+    }
+
+    if (! $basedir = make_upload_directory("$course->id")) {
+        error("The site administrator needs to fix the file permissions");
+    }
+
+    $baseweb = $CFG->wwwroot;
+
+//  End of configuration and access control
+
+
+    $regexp="\\.\\.";
+    if (ereg( $regexp, $file, $regs )| ereg( $regexp, $wdir,$regs )) {           
+        $message = "Error: Directories can not contain \"..\"";
+        $wdir = "/";
+        $action = "";
+    }    
+
+    if (!$wdir) {
+        $wdir="/";
+    }
+
+
+    switch ($action) {
+
+        case "upload":
+            html_header($course, $wdir);
+
+            if (!empty($_FILES['userfile'])) {
+                $userfile = $_FILES['userfile'];
+            } else {
+                $save = false;
+            }
+            if (!empty($save)) {
+                if (!is_uploaded_file($userfile['tmp_name']) or $userfile['size'] == 0) {
+                    notify(get_string("uploadnofilefound"));
+                } else {
+                    $userfile_name = clean_filename($userfile['name']);
+                    if ($userfile_name) {
+                        $newfile = "$basedir$wdir/$userfile_name";
+                        if (move_uploaded_file($userfile['tmp_name'], $newfile)) {
+                            chmod($newfile, 0666);
+                            $a = NULL;
+                            $a->file = "$userfile_name (".$userfile['type'].")";
+                            $a->directory = $wdir;
+                            print_string("uploadedfileto", "", $a);
+                        } else {
+                            notify(get_string("uploadproblem", "", $userfile_name));
+                        }
+                    }
+                }
+                displaydir($wdir);
+                    
+            } else {
+                $upload_max_filesize = get_max_upload_file_size($CFG->maxbytes);
+                $filesize = display_size($upload_max_filesize);
+
+                $struploadafile = get_string("uploadafile");
+                $struploadthisfile = get_string("uploadthisfile");
+                $strmaxsize = get_string("maxsize", "", $filesize);
+                $strcancel = get_string("cancel");
+
+                echo "<P>$struploadafile ($strmaxsize) --> <B>$wdir</B>";
+                echo "<TABLE><TR><TD COLSPAN=2>";
+                echo "<FORM ENCTYPE=\"multipart/form-data\" METHOD=\"post\" ACTION=\"".$_SERVER['PHP_SELF']."\">";
+                echo " <INPUT TYPE=hidden NAME=MAX_FILE_SIZE value=\"$upload_max_filesize\">";
+                echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+                echo " <INPUT TYPE=hidden NAME=wdir VALUE=$wdir>";
+                echo " <INPUT TYPE=hidden NAME=action VALUE=upload>";
+                echo " <INPUT NAME=\"userfile\" TYPE=\"file\" size=\"60\">";
+                echo " </TD><TR><TD WIDTH=10>";
+                echo " <INPUT TYPE=submit NAME=save VALUE=\"$struploadthisfile\">";
+                echo "</FORM>";
+                echo "</TD><TD WIDTH=100%>";
+                echo "<FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=\"get\">";
+                echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+                echo " <INPUT TYPE=hidden NAME=wdir VALUE=$wdir>";
+                echo " <INPUT TYPE=hidden NAME=action VALUE=cancel>";
+                echo " <INPUT TYPE=submit VALUE=\"$strcancel\">";
+                echo "</FORM>";
+                echo "</TD></TR></TABLE>";
+            }
+            html_footer();
+            break;
+
+        case "delete":
+            if (!empty($confirm)) {
+                html_header($course, $wdir);
+                foreach ($USER->filelist as $file) {
+                    $fullfile = $basedir.$file;
+                    if (! fulldelete($fullfile)) {
+                        echo "<BR>Error: Could not delete: $fullfile";
+                    }
+                }
+                clearfilelist();
+                displaydir($wdir);
+                html_footer();
+
+            } else {
+                html_header($course, $wdir);
+                if (setfilelist($_POST)) {
+                    echo "<p align=center>".get_string("deletecheckwarning").":</p>";
+                    print_simple_box_start("center");
+                    printfilelist($USER->filelist);
+                    print_simple_box_end();
+                    echo "<br />";
+                    notice_yesno (get_string("deletecheckfiles"), 
+                                "".basename($_SERVER['PHP_SELF'])."?id=$id&wdir=$wdir&action=delete&confirm=1",
+                                "".basename($_SERVER['PHP_SELF'])."?id=$id&wdir=$wdir&action=cancel");
+                } else {
+                    displaydir($wdir);
+                }
+                html_footer();
+            }
+            break;
+
+        case "move":
+            html_header($course, $wdir);
+            if ($count = setfilelist($_POST)) {
+                $USER->fileop     = $action;
+                $USER->filesource = $wdir;
+                echo "<p align=center>";
+                print_string("selectednowmove", "moodle", $count);
+                echo "</p>";
+            }
+            displaydir($wdir);
+            html_footer();
+            break;
+
+        case "paste":
+            html_header($course, $wdir);
+            if (isset($USER->fileop) and $USER->fileop == "move") {
+                foreach ($USER->filelist as $file) {
+                    $shortfile = basename($file);
+                    $oldfile = $basedir.$file;
+                    $newfile = $basedir.$wdir."/".$shortfile;
+                    if (!rename($oldfile, $newfile)) {
+                        echo "<P>Error: $shortfile not moved";
+                    }
+                }
+            }
+            clearfilelist();
+            displaydir($wdir);
+            html_footer();
+            break;
+
+        case "rename":
+            if (!empty($name)) {
+                html_header($course, $wdir);
+                $name = clean_filename($name);
+                if (file_exists($basedir.$wdir."/".$name)) {
+                    echo "Error: $name already exists!";
+                } else if (!rename($basedir.$wdir."/".$oldname, $basedir.$wdir."/".$name)) {
+                    echo "Error: could not rename $oldname to $name";
+                }
+                displaydir($wdir);
+                    
+            } else {
+                $strrename = get_string("rename");
+                $strcancel = get_string("cancel");
+                $strrenamefileto = get_string("renamefileto", "moodle", $file);
+                html_header($course, $wdir, "form.name");
+                echo "<P>$strrenamefileto:";
+                echo "<TABLE><TR><TD>";
+                echo "<FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=\"post\" NAME=\"form\">";
+                echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+                echo " <INPUT TYPE=hidden NAME=wdir VALUE=$wdir>";
+                echo " <INPUT TYPE=hidden NAME=action VALUE=rename>";
+                echo " <INPUT TYPE=hidden NAME=oldname VALUE=\"$file\">";
+                echo " <INPUT TYPE=text NAME=name SIZE=35 VALUE=\"$file\">";
+                echo " <INPUT TYPE=submit VALUE=\"$strrename\">";
+                echo "</FORM>";
+                echo "</TD><TD>";
+                echo "<FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=get>";
+                echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+                echo " <INPUT TYPE=hidden NAME=wdir VALUE=$wdir>";
+                echo " <INPUT TYPE=hidden NAME=action VALUE=cancel>";
+                echo " <INPUT TYPE=submit VALUE=\"$strcancel\">";
+                echo "</FORM>";
+                echo "</TD></TR></TABLE>";
+            }
+            html_footer();
+            break;
+
+        case "mkdir":
+            if (!empty($name)) {
+                html_header($course, $wdir);
+                $name = clean_filename($name);
+                if (file_exists("$basedir$wdir/$name")) {
+                    echo "Error: $name already exists!";
+                } else if (! make_upload_directory("$course->id/$wdir/$name")) {
+                    echo "Error: could not create $name";
+                }
+                displaydir($wdir);
+                    
+            } else {
+                $strcreate = get_string("create");
+                $strcancel = get_string("cancel");
+                $strcreatefolder = get_string("createfolder", "moodle", $wdir);
+                html_header($course, $wdir, "form.name");
+                echo "<P>$strcreatefolder:";
+                echo "<TABLE><TR><TD>";
+                echo "<FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=post NAME=form>";
+                echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+                echo " <INPUT TYPE=hidden NAME=wdir VALUE=$wdir>";
+                echo " <INPUT TYPE=hidden NAME=action VALUE=mkdir>";
+                echo " <INPUT TYPE=text NAME=name SIZE=35>";
+                echo " <INPUT TYPE=submit VALUE=\"$strcreate\">";
+                echo "</FORM>";
+                echo "</TD><TD>";
+                echo "<FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=get>";
+                echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+                echo " <INPUT TYPE=hidden NAME=wdir VALUE=$wdir>";
+                echo " <INPUT TYPE=hidden NAME=action VALUE=cancel>";
+                echo " <INPUT TYPE=submit VALUE=\"$strcancel\">";
+                echo "</FORM>";
+                echo "</TD></TR></TABLE>";
+            }
+            html_footer();
+            break;
+
+        case "edit":
+            html_header($course, $wdir);
+            if (isset($text)) {
+                $fileptr = fopen($basedir.$file,"w");
+                fputs($fileptr, stripslashes($text));
+                fclose($fileptr);
+                displaydir($wdir);
+                    
+            } else {
+                $streditfile = get_string("edit", "", "<B>$file</B>");
+                $fileptr  = fopen($basedir.$file, "r");
+                $contents = fread($fileptr, filesize($basedir.$file));
+                fclose($fileptr);
+
+                if (mimeinfo("type", $file) == "text/html") {
+                    if ($usehtmleditor = can_use_richtext_editor()) {
+                        $onsubmit = "onsubmit=\"copyrichtext(document.form.text);\"";
+                    } else {
+                        $onsubmit = "";
+                    }
+                } else {
+                    $usehtmleditor = false;
+                    $onsubmit = "";
+                }
+
+                print_heading("$streditfile");
+
+                echo "<TABLE><TR><TD COLSPAN=2>";
+                echo "<FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=\"post\" NAME=\"form\" $onsubmit>";
+                echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+                echo " <INPUT TYPE=hidden NAME=wdir VALUE=\"$wdir\">";
+                echo " <INPUT TYPE=hidden NAME=file VALUE=\"$file\">";
+                echo " <INPUT TYPE=hidden NAME=action VALUE=edit>";
+                print_textarea($usehtmleditor, 25, 80, 680, 400, "text", $contents);
+                echo "</TD></TR><TR><TD>";
+                echo " <INPUT TYPE=submit VALUE=\"".get_string("savechanges")."\">";
+                echo "</FORM>";
+                echo "</TD><TD>";
+                echo "<FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=get>";
+                echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+                echo " <INPUT TYPE=hidden NAME=wdir VALUE=$wdir>";
+                echo " <INPUT TYPE=hidden NAME=action VALUE=cancel>";
+                echo " <INPUT TYPE=submit VALUE=\"".get_string("cancel")."\">";
+                echo "</FORM>";
+                echo "</TD></TR></TABLE>";
+
+                if ($usehtmleditor) { 
+                    print_richedit_javascript("form", "text", "yes");
+                }
+
+
+            }
+            html_footer();
+            break;
+
+        case "zip":
+            if (!empty($name)) {
+                html_header($course, $wdir);
+                $name = clean_filename($name);
+                if (empty($CFG->zip)) {    // Use built-in php-based zip function
+                    $files = array();
+                    foreach ($USER->filelist as $file) {
+                        $files[] = "$basedir/$file";
+                    }
+                    include_once($CFG->libdir.'/pclzip/pclzip.lib.php');
+                    $archive = new PclZip("$basedir/$wdir/$name");
+                    if (($list = $archive->create($files,'',"$basedir/$wdir/")) == 0) {
+                        error($archive->errorInfo(true));
+                    }
+                } else {                   // Use external zip program
+                    $files = "";
+                    foreach ($USER->filelist as $file) {
+                        $files .= basename($file);
+                        $files .= " ";
+                    }
+                    $command = "cd $basedir/$wdir ; $CFG->zip -r $name $files";
+                    Exec($command);
+                }
+                clearfilelist();
+                displaydir($wdir);
+                    
+            } else {
+                html_header($course, $wdir, "form.name");
+
+                if (setfilelist($_POST)) {
+                    echo "<P ALIGN=CENTER>".get_string("youareabouttocreatezip").":</P>";
+                    print_simple_box_start("center");
+                    printfilelist($USER->filelist);
+                    print_simple_box_end();
+                    echo "<BR>";
+                    echo "<P ALIGN=CENTER>".get_string("whattocallzip");
+                    echo "<TABLE><TR><TD>";
+                    echo "<FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=post NAME=form>";
+                    echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+                    echo " <INPUT TYPE=hidden NAME=wdir VALUE=\"$wdir\">";
+                    echo " <INPUT TYPE=hidden NAME=action VALUE=zip>";
+                    echo " <INPUT TYPE=text NAME=name SIZE=35 VALUE=\"new.zip\">";
+                    echo " <INPUT TYPE=submit VALUE=\"".get_string("createziparchive")."\">";
+                    echo "</FORM>";
+                    echo "</TD><TD>";
+                    echo "<FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=get>";
+                    echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+                    echo " <INPUT TYPE=hidden NAME=wdir VALUE=$wdir>";
+                    echo " <INPUT TYPE=hidden NAME=action VALUE=cancel>";
+                    echo " <INPUT TYPE=submit VALUE=\"".get_string("cancel")."\">";
+                    echo "</FORM>";
+                    echo "</TD></TR></TABLE>";
+                } else {
+                    displaydir($wdir);
+                    clearfilelist();
+                }
+            }
+            html_footer();
+            break;
+
+        case "unzip":
+            html_header($course, $wdir);
+            if (!empty($file)) {
+                $strname = get_string("name");
+                $strsize = get_string("size");
+                $strmodified = get_string("modified");
+                $strstatus = get_string("status");
+                $strok = get_string("ok");
+                $strunpacking = get_string("unpacking", "", $file);
+
+                echo "<P ALIGN=CENTER>$strunpacking:</P>";
+
+                $file = basename($file);
+
+                if (empty($CFG->unzip)) {    // Use built-in php-based unzip function
+                    include_once($CFG->libdir.'/pclzip/pclzip.lib.php');
+                    $archive = new PclZip("$basedir/$wdir/$file");
+                    if (!$list = $archive->extract("$basedir/$wdir")) {
+                        error($archive->errorInfo(true));
+                    } else {  // print some output
+                        echo "<table cellpadding=\"4\" cellspacing=\"2\" border=\"0\" width=640>";
+                        echo "<tr><th align=left>$strname</th>";
+                        echo "<th align=right>$strsize</th>";
+                        echo "<th align=right>$strmodified</th>";
+                        echo "<th align=right>$strstatus</th></tr>";
+                        foreach ($list as $item) {
+                            echo "<tr>";
+                            $item['filename'] = str_replace("$basedir/$wdir/", "", $item['filename']);
+                            print_cell("left", $item['filename']);
+                            if (! $item['folder']) {
+                                print_cell("right", display_size($item['size']));
+                            } else {
+                                echo "<td>&nbsp;</td>";
+                            }
+                            $filedate  = userdate($item['mtime'], get_string("strftimedatetime"));
+                            print_cell("right", $filedate);
+                            print_cell("right", $item['status']);
+                            echo "</tr>";
+                        }
+                        echo "</table>";
+                    }
+                    
+                } else {                     // Use external unzip program
+                    print_simple_box_start("center");
+                    echo "<PRE>";
+                    $command = "cd $basedir/$wdir ; $CFG->unzip -o $file 2>&1";
+                    passthru($command);
+                    echo "</PRE>";
+                    print_simple_box_end();
+                }
+
+                echo "<CENTER><FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=get>";
+                echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+                echo " <INPUT TYPE=hidden NAME=wdir VALUE=$wdir>";
+                echo " <INPUT TYPE=hidden NAME=action VALUE=cancel>";
+                echo " <INPUT TYPE=submit VALUE=\"$strok\">";
+                echo "</FORM>";
+                echo "</CENTER>";
+            } else {
+                displaydir($wdir);
+            }
+            html_footer();
+            break;
+
+        case "listzip":
+            html_header($course, $wdir);
+            if (!empty($file)) {
+                $strname = get_string("name");
+                $strsize = get_string("size");
+                $strmodified = get_string("modified");
+                $strok = get_string("ok");
+                $strlistfiles = get_string("listfiles", "", $file);
+
+                echo "<P ALIGN=CENTER>$strlistfiles:</P>";
+                $file = basename($file);
+
+                include_once($CFG->libdir.'/pclzip/pclzip.lib.php');
+                $archive = new PclZip("$basedir/$wdir/$file");
+                if (!$list = $archive->listContent("$basedir/$wdir")) {
+                    notify($archive->errorInfo(true));
+
+                } else {
+                    echo "<table cellpadding=\"4\" cellspacing=\"2\" border=\"0\" width=640>";
+                    echo "<tr><th align=left>$strname</th><th align=right>$strsize</th><th align=right>$strmodified</th></tr>";
+                    foreach ($list as $item) {
+                        echo "<tr>";
+                        print_cell("left", $item['filename']);
+                        if (! $item['folder']) {
+                            print_cell("right", display_size($item['size']));
+                        } else {
+                            echo "<td>&nbsp;</td>";
+                        }
+                        $filedate  = userdate($item['mtime'], get_string("strftimedatetime"));
+                        print_cell("right", $filedate);
+                        echo "</tr>";
+                    }
+                    echo "</table>";
+                }
+                echo "<br><center><form action=\"".$_SERVER['PHP_SELF']."\" method=get>";
+                echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+                echo " <INPUT TYPE=hidden NAME=wdir VALUE=$wdir>";
+                echo " <INPUT TYPE=hidden NAME=action VALUE=cancel>";
+                echo " <INPUT TYPE=submit VALUE=\"$strok\">";
+                echo "</FORM>";
+                echo "</CENTER>";
+            } else {
+                displaydir($wdir);
+            }
+            html_footer();
+            break;
+
+        case "torte":
+               if($_POST)
+               {
+                       while(list($key, $val) = each($_POST))
+                       {
+                               if(ereg("file([0-9]+)", $key, $regs))
+                               {
+                                       $file = $val;
+                               }
+                       }
+                       if(@filetype($CFG->dataroot ."/". $course->id . $file) == "file")
+                       {
+                               if(mimeinfo("icon", $file) == "image.gif")
+                               {
+                                       $url = $CFG->wwwroot ."/file.php?file=/" .$course->id . $file;
+                                       runjavascript($url);
+                               }
+                               else
+                               {
+                                       print "File is not a image!";
+                               }
+                       }
+                       else
+                       {
+                               print "You cannot insert FOLDER into richtext editor!!!";
+                       }
+               }
+               break;
+        case "cancel";
+            clearfilelist();
+
+        default:
+            html_header($course, $wdir);
+            displaydir($wdir);
+            html_footer();
+            break;
+}
+
+
+/// FILE FUNCTIONS ///////////////////////////////////////////////////////////
+
+
+function fulldelete($location) { 
+    if (is_dir($location)) {
+        $currdir = opendir($location);
+        while ($file = readdir($currdir)) { 
+            if ($file <> ".." && $file <> ".") {
+                $fullfile = $location."/".$file;
+                if (is_dir($fullfile)) { 
+                    if (!fulldelete($fullfile)) {
+                        return false;
+                    }
+                } else {
+                    if (!unlink($fullfile)) {
+                        return false;
+                    }
+                } 
+            }
+        } 
+        closedir($currdir);
+        if (! rmdir($location)) {
+            return false;
+        }
+
+    } else {
+        if (!unlink($location)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+
+
+function setfilelist($VARS) {
+    global $USER;
+
+    $USER->filelist = array ();
+    $USER->fileop = "";
+
+    $count = 0;
+    foreach ($VARS as $key => $val) {
+        if (substr($key,0,4) == "file") {
+            $count++;
+            $USER->filelist[] = rawurldecode($val);
+        }
+    }
+    return $count;
+}
+
+function clearfilelist() {
+    global $USER;
+
+    $USER->filelist = array ();
+    $USER->fileop = "";
+}
+
+
+function printfilelist($filelist) {
+    global $basedir, $CFG;
+
+    foreach ($filelist as $file) {
+        if (is_dir($basedir.$file)) {
+            echo "<img src=\"$CFG->pixpath/f/folder.gif\" height=16 width=16> $file<br>";
+            $subfilelist = array();
+            $currdir = opendir($basedir.$file);
+            while ($subfile = readdir($currdir)) { 
+                if ($subfile <> ".." && $subfile <> ".") {
+                    $subfilelist[] = $file."/".$subfile;
+                }
+            }
+            printfilelist($subfilelist);
+
+        } else { 
+            $icon = mimeinfo("icon", $file);
+            echo "<img src=\"$CFG->pixpath/f/$icon\"  height=16 width=16> $file<br>";
+        }
+    }
+}
+
+
+function print_cell($alignment="center", $text="&nbsp;") {
+    echo "<TD ALIGN=\"$alignment\" NOWRAP>";
+    echo "<FONT SIZE=\"-1\" FACE=\"Arial, Helvetica\">";
+    echo "$text";
+    echo "</FONT>";
+    echo "</TD>\n";
+}
+
+function displaydir ($wdir) {
+//  $wdir == / or /a or /a/b/c/d  etc
+
+    global $basedir;
+    global $id;
+    global $USER, $CFG;
+
+    $fullpath = $basedir.$wdir;
+
+    $directory = opendir($fullpath);             // Find all files
+    while ($file = readdir($directory)) {
+        if ($file == "." || $file == "..") {
+            continue;
+        }
+        
+        if (is_dir($fullpath."/".$file)) {
+            $dirlist[] = $file;
+        } else {
+            if ((basename(strtolower($file),".zip") != basename(strtolower($file))) || (basename(strtolower($file),".pif") != basename(strtolower($file))))
+               $filelist[] = $file;
+        }
+    }
+    closedir($directory);
+
+    $strname = get_string("name");
+    $strsize = get_string("size");
+    $strmodified = get_string("modified");
+    $straction = get_string("action");
+    $strmakeafolder = get_string("makeafolder");
+    $struploadafile = get_string("uploadafile");
+    $strwithchosenfiles = get_string("withchosenfiles");
+    $strmovetoanotherfolder = get_string("movetoanotherfolder");
+    $strmovefilestohere = get_string("movefilestohere");
+    $strdeletecompletely = get_string("deletecompletely");
+    $strcreateziparchive = get_string("createziparchive");
+    $strrename = get_string("rename");
+    $stredit   = get_string("edit");
+    $strunzip  = get_string("unzip");
+    $strlist   = get_string("list");
+    $strchoose   = get_string("choose");
+
+
+    echo "<FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=post NAME=dirform>";
+    echo "<TABLE BORDER=0 cellspacing=2 cellpadding=2 width=640>";    
+    echo "<TR>";
+    echo "<TH WIDTH=5></TH>";
+    echo "<TH ALIGN=left>$strname</TH>";
+    echo "<TH ALIGN=right>$strsize</TH>";
+    echo "<TH ALIGN=right>$strmodified</TH>";
+    echo "<TH ALIGN=right>$straction</TH>";
+    echo "</TR>\n";
+
+    if ($wdir == "/") {
+        $wdir = "";
+    }
+
+    $count = 0;
+
+    if (!empty($dirlist)) {
+        asort($dirlist);
+        foreach ($dirlist as $dir) {
+
+            $count++;
+
+            $filename = $fullpath."/".$dir;
+            $fileurl  = rawurlencode($wdir."/".$dir);
+            $filesafe = rawurlencode($dir);
+            $filedate = userdate(filectime($filename), "%d %b %Y, %I:%M %p");
+    
+            echo "<TR>";
+
+            print_cell("center", "<INPUT TYPE=checkbox NAME=\"file$count\" VALUE=\"$fileurl\">");
+            print_cell("left", "<A HREF=\"".basename($_SERVER['PHP_SELF'])."?id=$id&wdir=$fileurl\"><IMG SRC=\"$CFG->pixpath/f/folder.gif\" HEIGHT=16 WIDTH=16 BORDER=0 ALT=\"Folder\"></A> <A HREF=\"".basename($_SERVER['PHP_SELF'])."?id=$id&wdir=$fileurl\">".htmlspecialchars($dir)."</A>");
+            print_cell("right", "-");
+            print_cell("right", $filedate);
+            print_cell("right", "<A HREF=\"".basename($_SERVER['PHP_SELF'])."?id=$id&wdir=$wdir&file=$filesafe&action=rename\">$strrename</A>");
+    
+            echo "</TR>";
+        }
+    }
+
+
+    if (!empty($filelist)) {
+        asort($filelist);
+        foreach ($filelist as $file) {
+
+            $icon = mimeinfo("icon", $file);
+
+            $count++;
+            $filename    = "$fullpath/$file";
+            $fileurl     = "$wdir/$file";
+            $filesafe    = rawurlencode($file);
+            $fileurlsafe = rawurlencode($fileurl);
+            $filedate    = userdate(filectime($filename), "%d %b %Y, %I:%M %p");
+
+            if (substr($fileurl,0,1) == '/') {
+                $selectfile = substr($fileurl,1);
+            } else {
+                $selectfile = $fileurl;
+            }
+            if ($CFG->slasharguments) {
+                $ffurl = "/file.php/$id$fileurl";
+            } else {
+                $ffurl = "/file.php?file=/$id$fileurl";
+            }
+
+            echo "<tr>";
+
+            print_cell("center", "<input type=\"checkbox\" name=\"file$count\" value=\"$fileurl\">");
+
+            echo "<td align=left nowrap>";
+            link_to_popup_window ($ffurl, "display", 
+                                  "<img src=\"$CFG->pixpath/f/$icon\" height=16 width=16 border=0 alt=\"file\">", 
+                                  480, 640);
+            echo "<font size=\"-1\" face=\"Arial, Helvetica\">";
+            link_to_popup_window ($ffurl, "display", htmlspecialchars($file), 480, 640);
+            echo "</font></td>";
+
+            $file_size = filesize($filename);
+            print_cell("right", display_size($file_size));
+            print_cell("right", $filedate);
+
+            $edittext = "<b><a onMouseDown=\"return set_value('$selectfile')\" href=\"\">$strchoose</a></b>&nbsp;";
+
+            if ($icon == "text.gif" || $icon == "html.gif") {
+                $edittext .= "<a href=\"".basename($_SERVER['PHP_SELF'])."?id=$id&wdir=$wdir&file=$fileurl&action=edit\">$stredit</a>";
+            } else if ($icon == "zip.gif") {
+                $edittext .= "<a href=\"".basename($_SERVER['PHP_SELF'])."?id=$id&wdir=$wdir&file=$fileurl&action=unzip\">$strunzip</a>&nbsp;";
+                $edittext .= "<a href=\"".basename($_SERVER['PHP_SELF'])."?id=$id&wdir=$wdir&file=$fileurl&action=listzip\">$strlist</a> ";
+            }
+
+            print_cell("right", "$edittext <A HREF=\"".basename($_SERVER['PHP_SELF'])."?id=$id&wdir=$wdir&file=$filesafe&action=rename\">$strrename</A>");
+    
+            echo "</tr>";
+        }
+    }
+    echo "</table>";
+    echo "<hr width=640 align=center noshade size=1>";
+
+    if (empty($wdir)) {
+        $wdir = "/";
+    }
+
+    echo "<TABLE BORDER=0 cellspacing=2 cellpadding=2 width=640>";    
+    echo "<TR><TD>";
+    echo "<INPUT TYPE=hidden NAME=id VALUE=\"$id\">";
+    echo "<INPUT TYPE=hidden NAME=wdir VALUE=\"$wdir\"> ";
+    $options = array (
+                   "move" => "$strmovetoanotherfolder",
+                   "delete" => "$strdeletecompletely",
+                   "zip" => "$strcreateziparchive"
+               );
+    if (!empty($count)) {
+        choose_from_menu ($options, "action", "", "$strwithchosenfiles...", "javascript:document.dirform.submit()");
+    }
+
+    echo "</FORM>";
+    echo "<TD ALIGN=center>";
+    if (!empty($USER->fileop) and ($USER->fileop == "move") and ($USER->filesource <> $wdir)) {
+        echo "<FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=get>";
+        echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+        echo " <INPUT TYPE=hidden NAME=wdir VALUE=\"$wdir\">";
+        echo " <INPUT TYPE=hidden NAME=action VALUE=paste>";
+        echo " <INPUT TYPE=submit VALUE=\"$strmovefilestohere\">";
+        echo "</FORM>";
+    }
+    echo "<TD ALIGN=right>";
+        echo "<FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=get>";
+        echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+        echo " <INPUT TYPE=hidden NAME=wdir VALUE=\"$wdir\">";
+        echo " <INPUT TYPE=hidden NAME=action VALUE=mkdir>";
+        echo " <INPUT TYPE=submit VALUE=\"$strmakeafolder\">";
+        echo "</FORM>";
+    echo "</TD>";
+    echo "<TD ALIGN=right>";
+        echo "<FORM ACTION=\"".$_SERVER['PHP_SELF']."\" METHOD=get>";
+        echo " <INPUT TYPE=hidden NAME=id VALUE=$id>";
+        echo " <INPUT TYPE=hidden NAME=wdir VALUE=\"$wdir\">";
+        echo " <INPUT TYPE=hidden NAME=action VALUE=upload>";
+        echo " <INPUT TYPE=submit VALUE=\"$struploadafile\">";
+        echo "</FORM>";
+    echo "</TD></TR>";
+    echo "</TABLE>";
+    echo "<HR WIDTH=640 ALIGN=CENTER NOSHADE SIZE=1>";
+
+}
+
+?>
diff --git a/mod/scorm/db/mysql.php b/mod/scorm/db/mysql.php
new file mode 100755 (executable)
index 0000000..d9ae381
--- /dev/null
@@ -0,0 +1,18 @@
+<?PHP // $Id$
+
+function scorm_upgrade($oldversion) {
+/// This function does anything necessary to upgrade
+/// older versions to match current functionality
+    global $CFG;
+    if ($oldversion < 2004033000) {
+       execute_sql(" ALTER TABLE `{$CFG->prefix}scorm` ADD `auto` TINYINT( 1 ) UNSIGNED DEFAULT '0' NOT NULL AFTER `summary`"); 
+    }
+    if ($oldversion < 2004040900) {
+       execute_sql(" ALTER TABLE `{$CFG->prefix}scorm_sco_users` ADD `cmi_core_score_raw` FLOAT( 3 ) DEFAULT '0' NOT NULL AFTER `cmi_core_session_time`"); 
+    }
+    return true;
+}
+
+
+?>
+
diff --git a/mod/scorm/db/mysql.sql b/mod/scorm/db/mysql.sql
new file mode 100755 (executable)
index 0000000..58b2046
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# Table structure for table `scorm`
+#
+CREATE TABLE prefix_scorm (
+  id int(10) unsigned NOT NULL auto_increment,
+  course int(10) unsigned NOT NULL default '0',
+  name varchar(255) NOT NULL default '',
+  reference varchar(255) default NULL,
+  datadir varchar(255) NOT NULL default '',
+  launch int(10) unsigned NOT NULL default 0,
+  summary text NOT NULL,
+  auto tinyint(1) unsigned NOT NULL default '0',
+  timemodified int(10) unsigned NOT NULL default '0',
+  PRIMARY KEY  (id),
+  UNIQUE KEY id (id)
+) TYPE=MyISAM;
+
+CREATE TABLE prefix_scorm_scoes (
+  id int(10) unsigned NOT NULL auto_increment,
+  scorm int(10) unsigned NOT NULL default '0',
+  parent varchar(255) NOT NULL default '',
+  identifier varchar(255) NOT NULL default '',
+  launch varchar(255) NOT NULL default '',
+  type varchar(5) NOT NULL default '',
+  title varchar(255) NOT NULL default '',
+  next tinyint(1) unsigned NOT NULL default '0',
+  previous tinyint(1) unsigned NOT NULL default '0',
+  PRIMARY KEY (id),
+  UNIQUE KEY id (id)
+) TYPE=MyISAM;
+
+CREATE TABLE prefix_scorm_sco_users (
+  id int(10) unsigned NOT NULL auto_increment,
+  userid int(10) unsigned NOT NULL default '0',
+  scormid int(10) NOT NULL default '0',
+  scoid int(10) unsigned NOT NULL default '0',
+  cmi_core_lesson_location varchar(255) NOT NULL default '',
+  cmi_core_lesson_status varchar(30) NOT NULL default '',
+  cmi_core_exit varchar(30) NOT NULL default '',
+  cmi_core_total_time varchar(13) NOT NULL default '00:00:00',
+  cmi_core_session_time varchar(13) NOT NULL default '00:00:00',
+  cmi_core_score_raw float(3) NOT NULL default '0',
+  cmi_suspend_data longtext,
+  cmi_launch_data longtext,
+  PRIMARY KEY  (id)
+) TYPE=MyISAM;
+
+#
+# Dumping data for table log_display
+#
+
+INSERT INTO prefix_log_display VALUES ('scorm', 'view', 'scorm', 'name');
+INSERT INTO prefix_log_display VALUES ('scorm', 'update', 'scorm', 'name');
+INSERT INTO prefix_log_display VALUES ('scorm', 'add', 'scorm', 'name');
\ No newline at end of file
diff --git a/mod/scorm/db/postgres7.php b/mod/scorm/db/postgres7.php
new file mode 100755 (executable)
index 0000000..0183ddd
--- /dev/null
@@ -0,0 +1,12 @@
+<?PHP // $Id$
+
+function resource_upgrade($oldversion) {
+// This function does anything necessary to upgrade
+// older versions to match current functionality
+
+    return true;
+}
+
+
+?>
+
diff --git a/mod/scorm/db/postgres7.sql b/mod/scorm/db/postgres7.sql
new file mode 100755 (executable)
index 0000000..930b7a7
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# Table structure for table `scorm`
+#
+
+CREATE TABLE prefix_scorm (
+  id SERIAL PRIMARY KEY,
+  course integer NOT NULL default '0',
+  name varchar(255) NOT NULL default '',
+  reference varchar(255) default NULL,
+  datadir varchar(255) NOT NULL default '',
+  launch integer NOT NULL default '0',
+  summary text NOT NULL default '',
+  auto integer NOT NULL default '0',
+  timemodified integer NOT NULL default '0'
+);
+
+CREATE TABLE prefix_scorm_scoes (
+  id SERIAL PRIMARY KEY,
+  scorm integer NOT NULL default '0',
+  parent varchar(255) NOT NULL default '',
+  identifier varchar(255) NOT NULL default '',
+  launch varchar(255) NOT NULL default '',
+  type varchar(5) NOT NULL default '',
+  title varchar(255) NOT NULL default '',
+  next integer NOT NULL default '0',
+  previous integer NOT NULL default '0'
+);
+
+CREATE TABLE prefix_scorm_sco_users (
+  id iSERIAL PRIMARY KEY,
+  userid integer NOT NULL default '0',
+  scormid integer NOT NULL default '0',
+  scoid integer NOT NULL default '0',
+  cmi_core_lesson_location varchar(255) NOT NULL default '',
+  cmi_core_lesson_status varchar(30) NOT NULL default '',
+  cmi_core_exit varchar(30) NOT NULL default '',
+  cmi_core_total_time varchar(13) NOT NULL default '00:00:00',,
+  cmi_core_session_time varchar(13) NOT NULL default '00:00:00',
+  cmi_core_score_raw real NOT NULL default '0',
+  cmi_suspend_data text NOT NULL default '',
+  cmi_launch_data text NOT NULL default ''
+);
+
+#
+# Dumping data for table `log_display`
+#
+
+INSERT INTO prefix_log_display VALUES ('resource', 'view', 'resource', 'name');
+INSERT INTO prefix_log_display VALUES ('resource', 'update', 'resource', 'name');
+INSERT INTO prefix_log_display VALUES ('resource', 'add', 'resource', 'name');
diff --git a/mod/scorm/details.php b/mod/scorm/details.php
new file mode 100755 (executable)
index 0000000..d9547d2
--- /dev/null
@@ -0,0 +1,118 @@
+<?PHP // $Id$
+
+    require_once("../../config.php");
+    require_once("lib.php");
+
+    require_login();
+    if ($form = data_submitted($destination)) { 
+
+        if (! $course = get_record("course", "id", $form->course)) {
+            error("This course doesn't exist");
+        }
+
+        require_login($course->id);
+
+        if (!isteacher($course->id)) {
+            error("You can't modify this course!");
+        }
+
+        $strediting = get_string("validateascorm", "scorm");
+        $strname = get_string("name");
+
+        print_header("$course->shortname: $strediting", "$course->shortname: $strediting",
+                      "<A HREF=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</A> -> $strediting");
+
+        if (!$form->name or !$form->reference or !$form->summary) {
+            error(get_string("filloutallfields"), $_SERVER["HTTP_REFERER"]);
+        }
+       
+       //
+       // Create a temporary directory to unzip package and validate imsmanifest
+       //
+       $basedir = $CFG->dataroot."/".$course->id;
+       $scormdir = "/moddata/scorm";   
+       if (scorm_mkdirs($basedir.$scormdir)) {
+           if ($tempdir = scorm_datadir($basedir.$scormdir, $form->datadir)) {
+               copy ($basedir."/".$form->reference, $tempdir."/".basename($form->reference));
+               if (empty($CFG->unzip)) {    // Use built-in php-based unzip function
+                   include_once($CFG->dirroot.'/lib/pclzip/pclzip.lib.php');
+                   $archive = new PclZip($tempdir."/".basename($form->reference));
+                   if (!$list = $archive->extract($tempdir)) {
+                       error($archive->errorInfo(true));
+                   }
+               } else {
+                   $command = "cd $tempdir; $CFG->unzip -o ".basename($form->reference)." 2>&1";
+                   exec($command);
+               }
+               $result = scorm_validate($tempdir."/imsmanifest.xml");
+           } else {
+               $result = "packagedir";
+           }
+       } else {
+           $result = "datadir";
+       }
+       
+       if ($result != "regular") {
+           //
+           // Delete files and temporary directory
+           //
+           if (is_dir($tempdir))
+               scorm_delete_files($tempdir);
+       } else {
+           //
+           // Delete package file
+           //
+           unlink ($tempdir."/".basename($form->reference));
+           if ($form->mode == "update") {
+               $fp = fopen($basedir."/".$form->reference,"r");
+               $fstat = fstat($fp);
+               fclose($fp);
+               if (get_field("scorm","timemodified","id",$form->instance) < $fstat["mtime"])
+                   $form->launch = 0;
+           }
+       }
+       //
+       // Print validation result
+       //
+       print_simple_box_start("center", "", "$THEME->cellheading");
+       echo "<table cellpadding=\"5\" align=\"center\">\n";
+       echo "    <tr><td align=\"right\" nowrap><p><b>$strname:</b></p></td><td><p>$form->name</p></a></td></tr>\n";
+       echo "    <tr><td align=\"right\" nowrap><p><b>".get_string("validation","scorm").":</b></p></td><td><p>".get_string($result,"scorm")."</p></a></td></tr>\n";
+       if (($form->mode == "update") && ($form->launch == 0) && (get_records("scorm_sco_user","scormid",$form->instance)))
+           echo "    <tr><td align=\"center\" colspan=\"2\" nowrap><p><b>".get_string("trackingloose","scorm")."</b></p></td></tr>\n";
+       echo "</table>\n";
+       if ($result == "regular") {
+           echo "<form name=\"theform\" method=\"post\" $onsubmit action=\"$form->destination\">\n";
+?>
+        <input type="hidden" name="reference"  value="<?php p($form->reference) ?>">
+        <input type="hidden" name="datadir"    value="<?php p(substr($tempdir,strlen($basedir)+strlen($scormdir))) ?>">
+        <input type="hidden" name="summary"    value="<?php p($form->summary) ?>">
+        <input type="hidden" name="auto"       value="<?php p($form->auto) ?>">
+        <input type="hidden" name="name"       value="<?php p($form->name) ?>">
+       <input type="hidden" name="launch"      value="<?php p($form->launch) ?>">
+        <input type="hidden" name="course"     value="<?php p($form->course) ?>">
+        <input type="hidden" name="coursemodule"       value="<?php p($form->coursemodule) ?>">
+        <input type="hidden" name="section"    value="<?php p($form->section) ?>">
+        <input type="hidden" name="module"     value="<?php p($form->module) ?>">
+        <input type="hidden" name="modulename" value="<?php p($form->modulename) ?>">
+        <input type="hidden" name="instance"   value="<?php p($form->instance) ?>">
+        <input type="hidden" name="mode"       value="<?php p($form->mode) ?>">
+       <center>
+           <input type="submit" value="<?php print_string("savechanges") ?>">
+           <input type="submit" name=cancel value="<?php print_string("cancel") ?>">
+       </center>
+        </form>
+<?
+       } else {
+?>
+       <center>
+           <input type="button" value="<?php print_string("continue") ?>" onClick="document.location='<?php echo $CFG->wwwroot ?>/course/view.php?id=<?php echo $course->id ?>';">
+        </center>
+<?
+       }
+       print_simple_box_end();
+        print_footer($course);
+    } else {
+           error("This script was called incorrectly");
+    }
+?>
diff --git a/mod/scorm/icon.gif b/mod/scorm/icon.gif
new file mode 100755 (executable)
index 0000000..2729187
Binary files /dev/null and b/mod/scorm/icon.gif differ
diff --git a/mod/scorm/index.php b/mod/scorm/index.php
new file mode 100755 (executable)
index 0000000..1505879
--- /dev/null
@@ -0,0 +1,80 @@
+<?PHP // $Id$
+
+    require_once("../../config.php");
+
+    require_variable($id);   // course
+
+    if (! $course = get_record("course", "id", $id)) {
+        error("Course ID is incorrect");
+    }
+
+    if ($course->category) {
+        require_login($course->id);
+        $navigation = "<A HREF=\"../../course/view.php?id=$course->id\">$course->shortname</A> ->";
+    }
+
+    add_to_log($course->id, "scorm", "view all", "index.php?id=$course->id", "");
+
+    $strscorm = get_string("modulename", "scorm");
+    $strscorms = get_string("modulenameplural", "scorm");
+    $strweek = get_string("week");
+    $strtopic = get_string("topic");
+    $strname = get_string("name");
+    $strsummary = get_string("summary");
+    $strlastmodified = get_string("lastmodified");
+
+    print_header("$course->shortname: $strscorms", "$course->fullname", "$navigation $strscorms", 
+                 "", "", true, "", navmenu($course));
+
+    if ($course->format == "weeks" or $course->format == "topics") {
+        $sortorder = "cw.section ASC";
+    } else {
+        $sortorder = "m.timemodified DESC";
+    }
+
+    if (! $scorms = get_all_instances_in_course("scorm", $course)) {
+        notice("There are no scorms", "../../course/view.php?id=$course->id");
+        exit;
+    }
+
+    if ($course->format == "weeks") {
+        $table->head  = array ($strweek, $strname, $strsummary);
+        $table->align = array ("CENTER", "LEFT", "LEFT");
+    } else if ($course->format == "topics") {
+        $table->head  = array ($strtopic, $strname, $strsummary);
+        $table->align = array ("CENTER", "LEFT", "LEFT");
+    } else {
+        $table->head  = array ($strlastmodified, $strname, $strsummary);
+        $table->align = array ("LEFT", "LEFT", "LEFT");
+    }
+
+    foreach ($scorms as $scorm) {
+
+        $tt = "";
+        if ($course->format == "weeks" or $course->format == "topics") {
+            if ($scorm->section) {
+                $tt = "$scorm->section";
+            }
+        } else {
+            $tt = "<FONT SIZE=1>".userdate($scorm->timemodified);
+        }
+        if (!$scorm->visible) {
+           //Show dimmed if the mod is hidden
+           $table->data[] = array ($tt, "<A class=\"dimmed\" HREF=\"view.php?id=$scorm->coursemodule\">$scorm->name</A>",
+                                   text_to_html($scorm->summary) );
+        } else {
+           //Show normal if the mod is visible
+           $table->data[] = array ($tt, "<A HREF=\"view.php?id=$scorm->coursemodule\">$scorm->name</A>",
+                                   text_to_html($scorm->summary) );
+        }
+    }
+
+    echo "<BR>";
+
+    print_table($table);
+
+    print_footer($course);
+
+?>
+
diff --git a/mod/scorm/lib.php b/mod/scorm/lib.php
new file mode 100755 (executable)
index 0000000..142326b
--- /dev/null
@@ -0,0 +1,364 @@
+<?PHP  // $Id$
+
+/// Library of functions and constants for module scorm
+/// (replace scorm with the name of your module and delete this line)
+
+
+$scorm_CONSTANT = 7;     /// for example
+$SCORM_TOP_FRAME_SIZE = 120;
+$SCORM_LEFT_FRAME_SIZE = 210;
+
+function scorm_add_instance($scorm) {
+/// Given an object containing all the necessary data, 
+/// (defined by the form in mod.html) this function 
+/// will create a new instance and return the id number 
+/// of the new instance.
+
+    $scorm->timemodified = time();
+
+    # May have to add extra stuff in here #
+    
+    return insert_record("scorm", $scorm);
+}
+
+
+function scorm_update_instance($scorm) {
+/// Given an object containing all the necessary data, 
+/// (defined by the form in mod.html) this function 
+/// will update an existing instance with new data.
+
+    $scorm->timemodified = time();
+    $scorm->id = $scorm->instance;
+
+    # May have to add extra stuff in here #
+
+    return update_record("scorm", $scorm);
+}
+
+
+function scorm_delete_instance($id) {
+/// Given an ID of an instance of this module, 
+/// this function will permanently delete the instance 
+/// and any data that depends on it.  
+       
+    require('../config.php');
+
+    if (! $scorm = get_record("scorm", "id", "$id")) {
+        return false;
+    }
+
+    $result = true;
+
+    # Delete any dependent files #
+    scorm_delete_files($CFG->dataroot."/".$scorm->course."/moddata/scorm".$scorm->datadir);
+
+    # Delete any dependent records here #
+    if (! delete_records("scorm_sco_users", "scormid", "$scorm->id")) {
+        $result = false;
+    }
+    if (! delete_records("scorm_scoes", "scorm", "$scorm->id")) {
+        $result = false;
+    }
+    if (! delete_records("scorm", "id", "$scorm->id")) {
+        $result = false;
+    }
+    
+
+    return $result;
+}
+
+function scorm_user_outline($course, $user, $mod, $scorm) {
+/// Return a small object with summary information about what a 
+/// user has done with a given particular instance of this module
+/// Used for user activity reports.
+/// $return->time = the time they did it
+/// $return->info = a short text description
+
+    return $return;
+}
+
+function scorm_user_complete($course, $user, $mod, $scorm) {
+/// Print a detailed representation of what a  user has done with 
+/// a given particular instance of this module, for user activity reports.
+
+    return true;
+}
+
+function scorm_print_recent_activity(&$logs, $isteacher=false) {
+/// Given a list of logs, assumed to be those since the last login 
+/// this function prints a short list of changes related to this module
+/// If isteacher is true then perhaps additional information is printed.
+/// This function is called from course/lib.php: print_recent_activity()
+
+    global $CFG, $COURSE_TEACHER_COLOR;
+
+    return $content;  // True if anything was printed, otherwise false
+}
+
+function scorm_cron () {
+/// Function to be run periodically according to the moodle cron
+/// This function searches for things that need to be done, such 
+/// as sending out mail, toggling flags etc ... 
+
+    global $CFG;
+
+    return true;
+}
+
+function scorm_grades($scormid) {
+/// Must return an array of grades for a given instance of this module, 
+/// indexed by user.  It also returns a maximum allowed grade.
+
+       global $CFG;
+       
+    $return->grades = NULL;
+    if ($sco_users=get_records_select("scorm_sco_users", "scormid='$scormid' GROUP BY userid")) {
+        foreach ($sco_users as $sco_user) {
+               $user_data=get_records_select("scorm_sco_users","scormid='$scormid' AND userid='$sco_user->userid'");
+               $scores->completed=0;
+               $scores->browsed=0;
+               $scores->incomplete=0;
+               $scores->failed=0;
+               $scores->notattempted=0;
+               $result="";
+               $data = current($user_data);
+               foreach ($user_data as $data) {
+                       if ($data->cmi_core_lesson_status=="passed")
+                               $scores->completed++;
+                       else
+                               $scores->{scorm_remove_spaces($data->cmi_core_lesson_status)}++;
+                       
+               }
+               if ($scores->completed)
+                       $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/completed.gif\" alt=\"".get_string("completed","scorm")."\" title=\"".get_string("completed","scorm")."\"> $scores->completed ";
+               if ($scores->incomplete)
+                       $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/incomplete.gif\" alt=\"".get_string("incomplete","scorm")."\" title=\"".get_string("incomplete","scorm")."\"> $scores->incomplete ";
+               if ($scores->failed)
+                       $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/failed.gif\" alt=\"".get_string("failed","scorm")."\" title=\"".get_string("failed","scorm")."\"> $scores->failed ";
+               if ($scores->browsed)
+                       $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/browsed.gif\" alt=\"".get_string("browsed","scorm")."\" title=\"".get_string("browsed","scorm")."\"> $scores->browsed ";
+                       if ($scores->notattempted)
+                       $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/notattempted.gif\" alt=\"".get_string("notattempted","scorm")."\" title=\"".get_string("notattempted","scorm")."\"> $scores->notattempted ";
+               
+               $return->grades[$sco_user->userid]=$result;
+        }
+        
+    }
+    
+    $return->maxgrade = count_records_select("scorm_scoes","scorm='$scormid' AND launch<>''");
+
+    return $return;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+/// Any other scorm functions go here.  Each of them must have a name that 
+/// starts with scorm_
+
+
+function scorm_randstring($len = "8")
+{
+        $rstring = NULL;
+        for($i=0; $i<$len; $i++) {
+                $char = chr(rand(48,122));
+                while (!ereg("[a-zA-Z0-9]", $char)){
+                        if($char == $lchar) continue;
+                        $char = chr(rand(48,90));
+                }
+                $rstring .= $char;
+                $lchar = $char;
+        }
+        return $rstring;
+}
+
+function scorm_mkdirs($strPath)
+{
+ if (is_dir($strPath))
+       return true;
+ $pStrPath = dirname($strPath);
+ if (!scorm_mkdirs($pStrPath)) 
+       return false;
+ return mkdir($strPath);
+}
+function scorm_datadir($strPath, $existingdir="", $prefix = "SCORM")
+{
+       if (($existingdir!="") && (is_dir($strPath.$existingdir)))
+               return $strPath.$existingdir;
+               
+       if (is_dir($strPath)) {
+               do {
+                       $datadir="/".$prefix.scorm_randstring();
+               } while (file_exists($strPath.$datadir));
+               mkdir($strPath.$datadir);
+               return $strPath.$datadir;
+       } else {
+               return false;
+       }
+} 
+
+function scorm_validate($manifest)
+{
+    if (is_file ($manifest)) {
+       if (file_exists($manifest))
+       {
+               return "regular";
+       }
+    } else {
+           return "nomanifest";
+    }
+}
+
+function scorm_delete_files($directory)
+{
+    if (is_dir($directory))
+    {
+        $handle=opendir($directory);
+        while (($file = readdir($handle)) != '')
+        {
+            if ($file != "." && $file != "..")
+           {
+               if (!is_dir($directory."/".$file))
+                    unlink($directory."/".$file);
+               else
+                   scorm_delete_files($directory."/".$file);
+           }
+        }
+        rmdir($directory);
+    }
+}
+
+function scorm_startElement($parser, $name, $attrs) {
+    global $manifest,$i,$resources,$parent,$level;
+    if ($name == "ITEM") {
+               $i++;
+               $manifest[$i]["identifier"] = $attrs["IDENTIFIER"];
+               $manifest[$i]["identifierref"] = $attrs["IDENTIFIERREF"];
+               $manifest[$i]["isvisible"] = $attrs["ISVISIBLE"];
+               $manifest[$i]["parent"] = $parent[$level];
+               $level++;
+               $parent[$level] = $attrs["IDENTIFIER"];
+    }
+    if ($name == "RESOURCE") {
+               $resources[$attrs["IDENTIFIER"]]["href"]=$attrs["HREF"];
+               $resources[$attrs["IDENTIFIER"]]["type"]=$attrs["ADLCP:SCORMTYPE"];
+    }
+}
+
+function scorm_endElement($parser, $name) {
+    global $manifest,$i,$level,$datacontent,$navigation;
+    if ($name == "ITEM") {
+        $level--;
+    }
+    if ($name == "TITLE" && $level>0)
+               $manifest[$i]["title"] = $datacontent;
+       if ($name == "ADLCP:HIDERTSUI")
+               $manifest[$i][$datacontent] = 1;
+}
+
+function scorm_characterData($parser, $data) {
+    global $datacontent;
+    $datacontent = $data;
+}
+
+function scorm_parse($basedir,$file,$scorm_id) {
+    global $manifest,$i,$resources,$parent,$level;
+    $datacontent = "";
+    $manifest[][] = "";
+    $resources[] = "";
+    $i = 0;
+    $level = 0;
+    $parent[$level] = "/";
+
+    $xml_parser = xml_parser_create();
+    // use case-folding so we are sure to find the tag in $map_array
+    xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
+    xml_set_element_handler($xml_parser, "scorm_startElement", "scorm_endElement");
+    xml_set_character_data_handler($xml_parser, "scorm_characterData");
+    if (!($fp = fopen($basedir.$file, "r"))) {
+       die("could not open XML input");
+    }
+
+    while ($data = fread($fp, 4096)) {
+       if (!xml_parse($xml_parser, $data, feof($fp))) {
+            die(sprintf("XML error: %s at line %d",
+                    xml_error_string(xml_get_error_code($xml_parser)),
+                    xml_get_current_line_number($xml_parser)));
+        }
+    }
+    xml_parser_free($xml_parser);
+    $launch = 0;
+
+    $sco->scorm = $scorm_id;
+    delete_records("scorm_scoes","scorm",$scorm_id);
+    delete_records("scorm_sco_users","scormid",$scorm_id);
+    for ($j=1; $j<=$i; $j++) {
+        $sco->identifier = $manifest[$j]["identifier"];
+        $sco->parent = $manifest[$j]["parent"];
+        $sco->title = $manifest[$j]["title"];
+        $sco->launch = $resources[$manifest[$j]["identifierref"]]["href"];
+               $sco->type = $resources[$manifest[$j]["identifierref"]]["type"];
+               $sco->previous = $manifest[$j]["previous"];
+               $sco->next = $manifest[$j]["continue"];
+               if (scorm_remove_spaces($manifest[$j]["isvisible"]) != "false")
+                       $id = insert_record("scorm_scoes",$sco);
+               if ($launch==0 && $sco->launch)
+                       $launch = $id;  
+    }
+    return $launch;
+}
+
+function scorm_get_scoes_records($sco_user) {
+/// Gets all info required to display the table of scorm results
+/// for report.php
+    global $CFG;
+
+    return get_records_sql("SELECT su.*, u.firstname, u.lastname, u.picture 
+                            FROM {$CFG->prefix}scorm_sco_users su, 
+                                 {$CFG->prefix}user u
+                            WHERE su.scormid = '$sco_user->scormid'
+                              AND su.userid = u.id
+                              AND su.userid = $sco_user->userid
+                              ORDER BY scoid");
+}
+
+function scorm_remove_spaces($sourcestr) {
+// Remove blank space from a string
+    $newstr="";
+       for( $i=0; $i<strlen($sourcestr); $i++) {
+               if ($sourcestr[$i]!=' ')
+                       $newstr .=$sourcestr[$i];
+       }
+       return $newstr;
+}
+
+function scorm_string_round($stringa) {
+// Crop a string to $len character and set an anchor title to the full string
+    $len=11;
+    if ( strlen($stringa)>$len ) {
+       return "<A name=\"\" title=\"$stringa\">".substr($stringa,0,$len-4)."...".substr($stringa,strlen($stringa)-1,1)."</A>";
+    } else
+       return $stringa;
+}
+
+function scorm_external_link($link) {
+// check if a link is external
+    $result = false;
+    $link = strtolower($link);
+    if (substr($link,0,7) == "http://")
+       $result = true;
+    else if (substr($link,0,8) == "https://")
+       $result = true;
+    else if (substr($link,0,4) == "www.")
+       $result = true;
+    else if (substr($link,0,7) == "rstp://")
+       $result = true;
+    else if (substr($link,0,6) == "rtp://")
+       $result = true;
+    else if (substr($link,0,6) == "ftp://")
+       $result = true;
+    else if (substr($link,0,9) == "gopher://")
+       $result = true;
+    return $result;
+}    
+?>
diff --git a/mod/scorm/mod.html b/mod/scorm/mod.html
new file mode 100755 (executable)
index 0000000..521a97b
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+    if (empty($form->name)) {
+       $form->name = "";
+    }
+    if (empty($form->summary)) {
+       $form->summary = "";
+    }
+    if (empty($form->alltext)) {
+       $form->alltext = "";
+    }
+?>
+
+
+<form name="form" method="post" action="<?php echo $CFG->wwwroot ?>/mod/scorm/details.php">
+    <table cellpadding=5>
+       <tr valign=top>
+           <td align=right><p><b><?php print_string("name") ?>:</b></p></td>
+           <td>
+               <input type="text" name="name" size=50 value="<?php p($form->name) ?>">
+           </td>
+       </tr>
+<?php 
+    $strfilename = get_string("coursepacket", "scorm");
+    $strchooseafile = get_string("chooseapacket", "scorm");
+?>
+       <tr valign="top">
+           <td align="right" nowrap>
+               <p><b><?php echo $strfilename?>:</b></p>
+           </td>
+           <td>
+               <?php
+                   echo "<input name=\"reference\" size=\"50\" value=\"$form->reference\">&nbsp;";
+                   button_to_popup_window ("/mod/scorm/coursefiles.php?id=$course->id", 
+                                           "coursefiles", $strchooseafile, 500, 750, $strchooseafile);
+               ?>
+           </td>
+       </tr>
+       <tr valign=top>
+           <td align=right><p><b><?php print_string("summary") ?>:</b></p>
+               <font size="1">
+               <?php
+                   helpbutton("summary", get_string("summary"), "scorm", true, true);
+                   echo "<br \>";
+                   helpbutton("writing", get_string("helpwriting"), "moodle", true, true);
+                   echo "<br \>";
+                   helpbutton("text", get_string("helptext"), "moodle", true, true);
+               ?>
+                  <br />
+               </font>
+           </td>
+           <td>
+               <textarea name="summary" rows=5 cols=50 wrap="virtual"><?php p($form->summary) ?></textarea>
+           </td>
+       </tr>
+       <tr valign=top>
+           <td align=right><p><b><?php print_string("autocontinue","scorm") ?>:</b></p></td>
+           <td>
+           <?php
+               $options[]=get_string("no");
+               $options[]=get_string("yes");
+               choose_from_menu ($options, "auto", $form->auto);
+           ?>
+           </td>
+       </tr>
+    </table>
+    <input type="hidden" name=course   value="<?php p($form->course) ?>">
+    <input type="hidden" name=coursemodule     value="<?php p($form->coursemodule) ?>">
+    <input type="hidden" name=datadir  value="<?php p($form->datadir) ?>">
+    <input type="hidden" name=launch   value="<?php p($form->launch) ?>">
+    <input type="hidden" name=section  value="<?php p($form->section) ?>">
+    <input type="hidden" name=module   value="<?php p($form->module) ?>">
+    <input type="hidden" name=modulename       value="<?php p($form->modulename) ?>">
+    <input type="hidden" name=instance value="<?php p($form->instance) ?>">
+    <input type="hidden" name=mode             value="<?php p($form->mode) ?>">
+    <input type="hidden" name=destination      value="<?php echo $ME ?>">
+    <center>
+       <input type="submit" value="<?php print_string("continue") ?>">
+    </center>
+</form>
\ No newline at end of file
diff --git a/mod/scorm/pix/browsed.gif b/mod/scorm/pix/browsed.gif
new file mode 100755 (executable)
index 0000000..f0607e8
Binary files /dev/null and b/mod/scorm/pix/browsed.gif differ
diff --git a/mod/scorm/pix/completed.gif b/mod/scorm/pix/completed.gif
new file mode 100755 (executable)
index 0000000..7c60c3f
Binary files /dev/null and b/mod/scorm/pix/completed.gif differ
diff --git a/mod/scorm/pix/failed.gif b/mod/scorm/pix/failed.gif
new file mode 100755 (executable)
index 0000000..aea7ded
Binary files /dev/null and b/mod/scorm/pix/failed.gif differ
diff --git a/mod/scorm/pix/incomplete.gif b/mod/scorm/pix/incomplete.gif
new file mode 100755 (executable)
index 0000000..1f4661e
Binary files /dev/null and b/mod/scorm/pix/incomplete.gif differ
diff --git a/mod/scorm/pix/minus.gif b/mod/scorm/pix/minus.gif
new file mode 100755 (executable)
index 0000000..e37cf32
Binary files /dev/null and b/mod/scorm/pix/minus.gif differ
diff --git a/mod/scorm/pix/notattempted.gif b/mod/scorm/pix/notattempted.gif
new file mode 100755 (executable)
index 0000000..eb5e517
Binary files /dev/null and b/mod/scorm/pix/notattempted.gif differ
diff --git a/mod/scorm/pix/passed.gif b/mod/scorm/pix/passed.gif
new file mode 100755 (executable)
index 0000000..7c60c3f
Binary files /dev/null and b/mod/scorm/pix/passed.gif differ
diff --git a/mod/scorm/pix/plus.gif b/mod/scorm/pix/plus.gif
new file mode 100755 (executable)
index 0000000..bb5f262
Binary files /dev/null and b/mod/scorm/pix/plus.gif differ
diff --git a/mod/scorm/pix/spacer.gif b/mod/scorm/pix/spacer.gif
new file mode 100755 (executable)
index 0000000..61c8ba4
Binary files /dev/null and b/mod/scorm/pix/spacer.gif differ
diff --git a/mod/scorm/playscorm.php b/mod/scorm/playscorm.php
new file mode 100755 (executable)
index 0000000..4d5edec
--- /dev/null
@@ -0,0 +1,203 @@
+<?PHP  // $Id$
+
+/// This page prints a particular instance of scorm
+/// (Replace scorm with the name of your module)
+
+    require_once("../../config.php");
+    require_once("lib.php");
+
+    optional_variable($id);    // Course Module ID, or
+    optional_variable($a);     // scorm ID
+
+    if ($id) {
+        if (! $cm = get_record("course_modules", "id", $id)) {
+            error("Course Module ID was incorrect");
+        }
+    
+        if (! $course = get_record("course", "id", $cm->course)) {
+            error("Course is misconfigured");
+        }
+    
+        if (! $scorm = get_record("scorm", "id", $cm->instance)) {
+            error("Course module is incorrect");
+        }
+
+    } else {
+        if (! $scorm = get_record("scorm", "id", $a)) {
+            error("Course module is incorrect");
+        }
+        if (! $course = get_record("course", "id", $scorm->course)) {
+            error("Course is misconfigured");
+        }
+        if (! $cm = get_coursemodule_from_instance("scorm", $scorm->id, $course->id)) {
+            error("Course Module ID was incorrect");
+        }
+    }
+
+    require_login($course->id);
+
+    
+    $strscorms = get_string("modulenameplural", "scorm");
+    $strscorm  = get_string("modulename", "scorm");
+       
+    if ($course->category) {
+        $navigation = "<a target=\"{$CFG->framename}\" href=\"../../course/view.php?id=$course->id\">$course->shortname</a> ->
+                       <a target=\"{$CFG->framename}\" href=\"index.php?id=$course->id\">$strscorms</a> ->";
+    } else {
+        $navigation = "<a target=\"{$CFG->framename}\" href=\"index.php?id=$course->id\">$strscorms</a> ->";
+    }
+
+    $pagetitle = strip_tags("$course->shortname: $scorm->name");
+
+    if (!$cm->visible and !isteacher($course->id)) {
+        print_header($pagetitle, "$course->fullname", "$navigation $scorm->name", "", "", true, 
+                     update_module_button($cm->id, $course->id, $strscorm), navmenu($course, $cm));
+        notice(get_string("activityiscurrentlyhidden"));
+    }
+    switch ($frameset) {
+        case "top":
+           add_to_log($course->id, "scorm", "view", "playscorm.php?id=$cm->id", "$scorm->id");
+           //
+           // Print the page header
+           //
+           print_header($pagetitle, "$course->fullname",
+               "$navigation <a target=\"{$CFG->framename}\" href=\"view.php?id=$cm->id\" title=\"$scorm->summary\">$scorm->name</a>",
+               "", "", true, update_module_button($cm->id, $course->id, $strscorm), navmenu($course, $cm));
+       
+           echo "<table width=\"100%\"><tr><td align=\"center\">".text_to_html($scorm->summary, true, false)."</td></tr></table>\n";
+           echo "</body>\n</html>\n";
+       break;
+       case "left":
+           //
+           // Print SCORM Nav button
+           //
+           if (file_exists("$CFG->dirroot/theme/$CFG->theme/styles.php")) {
+               $styles = $CFG->stylesheet;
+               require_once("$CFG->dirroot/theme/$CFG->theme/config.php");
+           } else {
+               $styles = "$CFG->wwwroot/theme/standard/styles.php";
+               require_once("$CFG->dirroot/theme/standard/config.php");
+           }
+           if ( get_string("thisdirection") == "rtl" ) {
+               $direction = " dir=\"rtl\"";
+           } else {
+               $direction = " dir=\"ltr\"";
+           }
+           $meta = "<meta http-equiv=\"content-type\" content=\"text/html; charset=$encoding\" />\n$meta\n";
+           echo "<html $direction>\n<head>\n";
+           echo $meta;
+           echo "<title>Navigator</title>\n";
+           echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"".$styles."\" />\n";
+           //echo "<script language=\"JavaScript\" type=\"text/javascript\" src=\"scormAPI.php?id=$cm->id&mode=".$_GET["mode"].$scoid."\"></script>\n";
+           echo "</head>\n<body bgcolor=\"".$THEME->body."\" leftmargin=\"0\">\n";
+           echo "<table width=\"100%\">\n";
+           if ($_GET["mode"] == "browse")
+               echo "    <tr><td align=\"center\"><b>".get_string("browsemode","scorm")."</b></td></tr>";
+           echo "   <tr><td align=\"center\" width=\"20%\" nowrap>
+                    <iframe name=\"cmi\" width=\"1\" height=\"1\" src=\"cmi.php?id=$cm->id\" style=\"visibility: hidden;\"></iframe>
+                    <form name=\"navform\" method=\"POST\" action=\"playscorm.php?id=$cm->id\" target=\"_top\">
+                       <input name=\"scoid\" type=\"hidden\" />
+                       <input name=\"mode\" type=\"hidden\" value=\"".$_GET["mode"]."\" />
+                       <input name=\"prev\" type=\"button\" value=\"".get_string("prev","scorm")."\" onClick=\"top.changeSco('prev');\" />&nbsp;
+                       <input name=\"next\" type=\"button\" value=\"".get_string("next","scorm")."\" onClick=\"top.changeSco('next')\" />
+                    </form>
+               </td></tr>\n";
+           echo "</table>\n";
+           echo "<style type=\"text/css\">.scormlist { list-style-type:none;font-size:small; }</style>\n";
+           echo "<ul class=\"scormlist\">\n";
+           if ($scoes = get_records_select("scorm_scoes","scorm='$scorm->id' order by id ASC")){
+               $level=0;
+               $sublist=0;                     
+               $parents[$level]="/";
+               $incomplete=false;
+               foreach ($scoes as $sco) {
+                   if ($parents[$level]!=$sco->parent) {
+                       if ($level>0 && $parents[$level-1]==$sco->parent) {
+                           echo "  </ul>\n";
+                           $level--;
+                       } else {
+                           echo "  <ul id='".$sublist."' class=\"scormlist\">\n";
+                           $level++;
+                           $parents[$level]=$sco->parent;
+                       }
+                   }
+                   echo "    <li>";
+                   $nextsco = next($scoes);
+                   if (($nextsco !== false) && ($sco->parent != $nextsco->parent) && ($nextsco->parent != $parents[$level-1])) {
+                       $sublist++;
+                       echo "<img src=\"pix/minus.gif\" onClick='expandCollide(this,".$sublist.");'/>";
+                   } else
+                       echo "<img src=\"pix/spacer.gif\" />";
+                   if ($sco->launch) {
+                       if ($sco_user=get_record("scorm_sco_users","scoid",$sco->id,"userid",$USER->id)) {
+                           if ( $sco_user->cmi_core_lesson_status == "")
+                               $sco_user->cmi_core_lesson_status = "not attempted";
+                           echo "<img src=\"pix/".scorm_remove_spaces($sco_user->cmi_core_lesson_status).".gif\" alt=\"".get_string(scorm_remove_spaces($sco_user->cmi_core_lesson_status),"scorm")."\" title=\"".get_string(scorm_remove_spaces($sco_user->cmi_core_lesson_status),"scorm")."\" />";
+                           switch ($sco_user->cmi_core_lesson_status) {
+                               case "not attempted":
+                               case "incomplete":
+                               case "browsed":
+                                   $incomplete = true;
+                           }
+                       } else {
+                           echo "<img src=\"pix/notattempted.gif\" alt=\"".get_string("notattempted","scorm")."\" />";
+                           $incomplete = true;
+                       }
+                       echo "&nbsp;<a href=\"javascript:playSCO(".$sco->id.")\">$sco->title</a></li>\n";
+                   } else {
+                       echo "&nbsp;$sco->title</li>\n";
+                   }
+               }
+               
+               for ($i=0;$i<$level;$i++){
+                    echo "  </ul>\n";
+               }
+           }
+           echo "</ul></p>\n";
+           echo "<script language=\"javascript\">
+<!--
+    function playSCO(scoid,status) {
+       document.navform.scoid.value = scoid;
+       document.navform.submit();
+    }
+    
+    function expandCollide(which,list) {
+       var nn=document.ids?true:false
+       var w3c=document.getElementById?true:false
+       var beg=nn?\"document.ids.\":w3c?\"document.getElementById(\":\"document.all.\";
+       var mid=w3c?\").style\":\".style\";
+       
+       if (eval(beg+list+mid+\".display\") != \"none\") {
+           which.src = \"pix/plus.gif\";
+           eval(beg+list+mid+\".display='none';\");
+       } else {
+           which.src = \"pix/minus.gif\";
+           eval(beg+list+mid+\".display='block';\");
+       }
+       
+    }  
+    
+-->
+</script>\n";
+           echo "</body>\n</html>\n";
+       break;
+       default:
+           // 
+           // Frameset
+           //
+           if ($_POST["scoid"])
+               $scoid = "&scoid=".$_POST["scoid"];
+           echo "<html>\n";
+            echo "<head><title>$course->shortname: $scorm->name</title></head>\n";
+            echo "<script id=\"scormAPI\" language=\"JavaScript\" type=\"text/javascript\" src=\"scormAPI.php?id=$cm->id&mode=".$_GET["mode"].$scoid."\"></script>\n";
+            echo "<frameset rows=\"$SCORM_TOP_FRAME_SIZE,*\">\n";
+            echo "         <frame name=\"upper\" src=\"playscorm.php?id=$cm->id&mode=".$_POST["mode"]."&frameset=top\">\n";
+            echo "         <frameset cols=\"$SCORM_LEFT_FRAME_SIZE,*\" onload=\"SCOInitialize();\">\n";
+            echo "               <frame name=\"nav\" src=\"playscorm.php?id=$cm->id&mode=".$_POST["mode"]."&frameset=left\">\n";
+            echo "               <frame name=\"main\" src=\"\">\n";
+            echo "      </frameset>\n";
+            echo "</frameset>\n";
+           echo "</html>\n";
+       break;
+    }
+?>
diff --git a/mod/scorm/report.php b/mod/scorm/report.php
new file mode 100755 (executable)
index 0000000..c757c40
--- /dev/null
@@ -0,0 +1,110 @@
+<?PHP  // $Id$
+
+// This script uses installed report plugins to print quiz reports
+
+    require_once("../../config.php");
+    require_once("lib.php");
+
+    optional_variable($id);    // Course Module ID, or
+
+    if ($id) {
+        if (! $cm = get_record("course_modules", "id", $id)) {
+            error("Course Module ID was incorrect");
+        }
+    
+        if (! $course = get_record("course", "id", $cm->course)) {
+            error("Course is misconfigured");
+        }
+    
+        if (! $scorm = get_record("scorm", "id", $cm->instance)) {
+            error("Course module is incorrect");
+        }
+
+    } else {
+        if (! $scorm = get_record("scorm", "id", $q)) {
+            error("Course module is incorrect");
+        }
+        if (! $course = get_record("course", "id", $scorm->course)) {
+            error("Course is misconfigured");
+        }
+        if (! $cm = get_coursemodule_from_instance("scorm", $scorm->id, $course->id)) {
+            error("Course Module ID was incorrect");
+        }
+    }
+
+    require_login($course->id);
+
+    if (!isteacher($course->id)) {
+        error("You are not allowed to use this script");
+    }
+
+    add_to_log($course->id, "scorm", "report", "report.php?id=$cm->id", "$scorm->id");
+
+/// Print the page header
+    if (empty($noheader)) {
+
+        if ($course->category) {
+            $navigation = "<a href=\"../../course/view.php?id=$course->id\">$course->shortname</a> ->";
+        }
+    
+        $strscorms = get_string("modulenameplural", "scorm");
+        $strscorm  = get_string("modulename", "scorm");
+        $strreport  = get_string("report", "scorm");
+    
+        print_header("$course->shortname: $scorm->name", "$course->fullname",
+                     "$navigation <A HREF=index.php?id=$course->id>$strscorms</A> 
+                      -> <a href=\"view.php?id=$cm->id\">$scorm->name</a> -> $strreport", 
+                     "", "", true);
+    
+        print_heading($scorm->name);
+    }
+    if ($scoes =get_records_select("scorm_scoes","scorm='$scorm->id' ORDER BY id")) {
+       if ($sco_users=get_records_select("scorm_sco_users", "scormid='$scorm->id' GROUP BY userid")) {
+                       
+               $strname  = get_string("name");
+
+               $table->head = array("&nbsp;", $strname);
+               $table->align = array("center", "left");
+               $table->wrap = array("nowrap", "nowrap");
+               $table->width = "100%";
+               $table->size = array(10, "*");
+               foreach ($scoes as $sco) {
+                       if ($sco->launch!="") {
+                           $table->head[]=scorm_string_round($sco->title);
+                           $table->align[] = "center";
+                               $table->wrap[] = "nowrap";
+                               $table->size[] = "*";
+                       }
+               }
+
+               foreach ($sco_users as $sco_user) {
+                       $user_data=scorm_get_scoes_records($sco_user);
+               $picture = print_user_picture($sco_user->userid, $course->id, $user_data->picture, false, true);
+               $row="";
+                       $row[] = $picture;
+                       if (is_array($user_data)) {
+                               $data = current($user_data);
+                               $row[] = "<a href=\"$CFG->wwwroot/user/view.php?id=$data->userid&course=$course->id\">".
+                                        "$data->firstname $data->lastname</a>";
+                               foreach ($user_data as $data) {
+                               $row[]="<img src=\"pix/".scorm_remove_spaces($data->cmi_core_lesson_status).".gif\" 
+                                                  alt=\"".get_string(scorm_remove_spaces($data->cmi_core_lesson_status),"scorm")."\"
+                                                  title=\"".get_string(scorm_remove_spaces($data->cmi_core_lesson_status),"scorm")."\">&nbsp;"
+                                                  .$data->cmi_core_total_time;
+                               }
+                       }
+               $table->data[] = $row; 
+               }
+    
+               print_table($table);
+        
+       } else {
+               notice("No users to report");
+       }
+    }
+    if (empty($noheader)) {
+        print_footer($course);
+    }
+
+
+?>
diff --git a/mod/scorm/scormAPI.php b/mod/scorm/scormAPI.php
new file mode 100755 (executable)
index 0000000..2681c22
--- /dev/null
@@ -0,0 +1,110 @@
+<?php
+    require_once("../../config.php");
+    require_once("lib.php");
+
+    optional_variable($id);    // Course Module ID, or
+    optional_variable($a);     // scorm ID
+
+    if ($id) {
+       if (! $cm = get_record("course_modules", "id", $id)) {
+           error("Course Module ID was incorrect");
+       }
+
+       if (! $course = get_record("course", "id", $cm->course)) {
+           error("Course is misconfigured");
+       }
+
+       if (! $scorm = get_record("scorm", "id", $cm->instance)) {
+           error("Course module is incorrect");
+       }
+
+    } else {
+       if (! $scorm = get_record("scorm", "id", $a)) {
+           error("Course module is incorrect");
+       }
+       if (! $course = get_record("course", "id", $scorm->course)) {
+           error("Course is misconfigured");
+       }
+       if (! $cm = get_coursemodule_from_instance("scorm", $scorm->id, $course->id)) {
+           error("Course Module ID was incorrect");
+       }
+    }
+
+    require_login($course->id);
+
+    if ( $scoes_user = get_records_select("scorm_sco_users","userid = ".$USER->id." AND scormid = ".$scorm->id,"scoid ASC") ) {
+       if ($_GET["scoid"]) {
+           $sco = get_record("scorm_scoes","id",$_GET["scoid"]);
+       } else {
+           foreach ( $scoes_user as $sco_user ) {
+               if (($sco_user->cmi_core_lesson_status != "completed") && ($sco_user->cmi_core_lesson_status != "passed") && ($sco_user->cmi_core_lesson_status != "failed")) {
+                   $sco = get_record("scorm_scoes","id",$sco_user->scoid);
+                   break;
+               } else {
+                   if ($_GET["mode"] == "review") {
+                       $sco = get_record("scorm_scoes","id",$sco_user->scoid);
+                       break;
+                   }
+               }
+           }
+       }
+       if (!$sco)
+           $sco = get_record_select("scorm_scoes","scorm=".$scorm->id." AND launch<>'' order by id ASC");
+    } else {   
+       if ($scoes = get_records("scorm_scoes","scorm",$scorm->id,"id ASC")) {
+           foreach ($scoes as $sco) {
+               if ($sco->launch != "") {
+                   if (!$first)
+                       $first = $sco;
+                   $sco_user->userid = $USER->id;
+                   $sco_user->scoid = $sco->id;
+                   $sco_user->scormid = $scorm->id;
+                   $element = "cmi_core_lesson_status";
+                   if ($sco->type == "sco") 
+                       $sco_user->$element = "not attempted";
+                   else if ($sco->type == "sca")
+                       $sco_user->$element = "completed";
+                   $ident = insert_record("scorm_sco_users",$sco_user);
+       }
+           }
+           $sco = $first;
+           if ($_GET["scoid"])
+               $sco = get_record("scorm_scoes","id",$_GET["scoid"]);
+       }
+    }
+    //
+    // Get first, last, prev and next scoes
+    //
+    $scoes = get_records("scorm_scoes","scorm",$scorm->id,"id ASC");
+    foreach ($scoes as $fsco) {
+       if ($fsco->launch != "") {
+           if (!$min || ($min > $fsco->id))
+               $min = $fsco->id;
+           if (!$max || ($max < $fsco->id))
+               $max = $fsco->id;
+           if ((!$prevsco) || ($sco->id > $fsco->id)) {
+               $prevsco = $fsco->id;
+           }
+           if ((!$nextsco) && ($sco->id < $fsco->id)) {
+               $nextsco = $fsco->id;
+           }
+       }
+    }
+    if ($sco->id == $min)
+       $first = $sco;
+    if ($sco->id == $max)
+       $last = $sco;
+
+    // Get User data
+    $sco_user = get_record("scorm_sco_users","userid",$USER->id,"scoid",$sco->id);
+    if (scorm_external_link($sco->launch)) {
+       $result = $sco->launch;
+    } else {
+       if ($CFG->slasharguments) {
+           $result = "$CFG->wwwroot/file.php/$scorm->course/moddata/scorm$scorm->datadir/$sco->launch";
+       } else {
+           $result = "$CFG->wwwroot/file.php?file=/$scorm->course/moddata/scorm$scorm->datadir/$sco->launch";
+       }
+    }
+    include("api1_2.php");
+?>
diff --git a/mod/scorm/version.php b/mod/scorm/version.php
new file mode 100755 (executable)
index 0000000..e3ee06f
--- /dev/null
@@ -0,0 +1,11 @@
+<?PHP // $Id$
+
+/////////////////////////////////////////////////////////////////////////////////
+///  Code fragment to define the version of scorm
+///  This fragment is called by moodle_needs_upgrading() and /admin/index.php
+/////////////////////////////////////////////////////////////////////////////////
+
+$module->version  = 2004040900;   // The (date) version of this module
+$module->cron     = 0;            // How often should cron check this module (seconds)?
+
+?>
diff --git a/mod/scorm/view.php b/mod/scorm/view.php
new file mode 100755 (executable)
index 0000000..c1cca74
--- /dev/null
@@ -0,0 +1,184 @@
+<?PHP  // $Id$
+
+/// This page prints a particular instance of scorm
+/// (Replace scorm with the name of your module)
+
+    require_once("../../config.php");
+    require_once("lib.php");
+
+    optional_variable($id);    // Course Module ID, or
+    optional_variable($a);     // scorm ID
+
+    if ($id) {
+        if (! $cm = get_record("course_modules", "id", $id)) {
+            error("Course Module ID was incorrect");
+        }
+    
+        if (! $course = get_record("course", "id", $cm->course)) {
+            error("Course is misconfigured");
+        }
+    
+        if (! $scorm = get_record("scorm", "id", $cm->instance)) {
+            error("Course module is incorrect");
+        }
+
+    } else {
+        if (! $scorm = get_record("scorm", "id", $a)) {
+            error("Course module is incorrect");
+        }
+        if (! $course = get_record("course", "id", $scorm->course)) {
+            error("Course is misconfigured");
+        }
+        if (! $cm = get_coursemodule_from_instance("scorm", $scorm->id, $course->id)) {
+            error("Course Module ID was incorrect");
+        }
+    }
+
+    require_login($course->id);
+
+    
+    $strscorms = get_string("modulenameplural", "scorm");
+    $strscorm  = get_string("modulename", "scorm");
+       
+    if ($course->category) {
+        $navigation = "<a target=\"{$CFG->framename}\" href=\"../../course/view.php?id=$course->id\">$course->shortname</a> ->
+                       <a target=\"{$CFG->framename}\" href=\"index.php?id=$course->id\">$strscorms</a> ->";
+    } else {
+        $navigation = "<a target=\"{$CFG->framename}\" href=\"index.php?id=$course->id\">$strscorms</a> ->";
+    }
+
+    $pagetitle = strip_tags("$course->shortname: $scorm->name");
+    
+    add_to_log($course->id, "scorm", "pre-view", "view.php?id=$cm->id", "$scorm->id");
+    //
+    // Checking if parsed scorm manifest
+    //
+    if ($scorm->launch == 0) {
+       $basedir = $CFG->dataroot."/".$course->id;
+               $scormdir = "/moddata/scorm";
+       $scorm->launch = scorm_parse($basedir,$scormdir.$scorm->datadir."/imsmanifest.xml",$scorm->id);
+       set_field("scorm","launch",$scorm->launch,"id",$scorm->id);
+    }
+    //
+    // Print the page header
+    //
+    if (!$cm->visible and !isteacher($course->id)) {
+        print_header($pagetitle, "$course->fullname", "$navigation $scorm->name", "", "", true, 
+                     update_module_button($cm->id, $course->id, $strscorm), navmenu($course, $cm));
+        notice(get_string("activityiscurrentlyhidden"));
+    } else {
+       print_header($pagetitle, "$course->fullname","$navigation <a target=\"{$CFG->framename}\" href=\"$ME?id=$cm->id\" title=\"$scorm->summary\">$scorm->name</a>",
+                        "", "", true, update_module_button($cm->id, $course->id, $strscorm), navmenu($course, $cm));
+        
+       if (isteacher($course->id)) {
+           if ($sco_users = get_records_select("scorm_sco_users", "scormid='$scorm->id' GROUP BY userid")) {
+               echo "<p align=right><a target=\"{$CFG->framename}\" href=\"report.php?id=$cm->id\">".get_string("viewallreports","scorm",count($sco_users))."</a></p>";
+            } else {
+               echo "<p align=right>".get_string("noreports","scorm")."</p>";
+            }
+       }
+       // Print the main part of the page
+
+       print_heading($scorm->name);
+
+       print_simple_box(text_to_html($scorm->summary), "CENTER");
+
+       if (isguest()) {
+            print_heading(get_string("guestsno", "scorm"));
+            print_footer($course);
+            exit;
+       }
+        echo "<br />";
+        print_simple_box_start("CENTER");
+       echo "<table>\n";
+       echo "  <tr><th>".get_string("coursestruct","scorm")."</th></tr>\n";
+       echo "  <tr><td nowrap>\n<ul compact style='list-style-type:none'>\n";
+       if ($scoes = get_records_select("scorm_scoes","scorm='$scorm->id' order by id ASC")){
+           $level=0;
+           $sublist=0;
+           $parents[$level]="/";
+           $incomplete=false;
+           foreach ($scoes as $sco) {
+               if ($parents[$level]!=$sco->parent) {
+                   if ($level>0 && $parents[$level-1]==$sco->parent) {
+                       echo "  </ul>\n";
+                       $level--;
+                   } else {
+                       echo "  <ul id='".$sublist."'compact style='list-style-type:none;'>\n";
+                       $level++;
+                       $parents[$level]=$sco->parent;
+                   }
+               }
+               echo "    <li>\n";
+               $nextsco = next($scoes);
+               if (($nextsco !== false) && ($sco->parent != $nextsco->parent) && ($nextsco->parent != $parents[$level-1])) {
+                   $sublist++;
+                   echo "      <img src=\"pix/minus.gif\" onClick='expandCollide(this,".$sublist.");'/>\n";
+               } else
+                   echo "      <img src=\"pix/spacer.gif\" />\n";
+               if ($sco->launch) {
+                   if ($sco_user=get_record("scorm_sco_users","scoid",$sco->id,"userid",$USER->id)) {
+                       if ( $sco_user->cmi_core_lesson_status == "")
+                           $sco_user->cmi_core_lesson_status = "not attempted";
+                       echo "      <img src=\"pix/".scorm_remove_spaces($sco_user->cmi_core_lesson_status).".gif\" alt=\"".get_string(scorm_remove_spaces($sco_user->cmi_core_lesson_status),"scorm")."\" title=\"".get_string(scorm_remove_spaces($sco_user->cmi_core_lesson_status),"scorm")."\" />\n";
+                       switch ($sco_user->cmi_core_lesson_status) {
+                               case "not attempted":
+                               case "incomplete":
+                               case "browsed":
+                                   $incomplete = true;
+                       }
+                   } else {
+                       echo "      <img src=\"pix/notattempted.gif\" alt=\"".get_string("notattempted","scorm")."\" />";
+                       $incomplete = true;
+                   }
+                   echo "      &nbsp;<a href=\"javascript:playSCO(".$sco->id.")\">$sco->title</a>\n    </li>\n";
+               } else {
+                   echo "      &nbsp;$sco->title\n    </li>\n";
+               }
+           }
+       }
+       echo "</ul>\n</td></tr>\n";
+       echo "</table>\n";
+       print_simple_box_end();
+       echo "<form name=\"theform\" method=\"POST\" action=\"playscorm.php?id=$cm->id\">\n";
+       echo "<table align=\"CENTER\">\n<tr>\n<td align=\"center\">";
+       print_string("mode","scorm");
+        echo ": <input type=\"radio\" id=\"b\" name=\"mode\" value=\"browse\" /><label for=\"b\">".get_string("browse","scorm")."</label>\n";
+        if ($incomplete) {
+            echo "<input type=\"radio\" id=\"n\" name=\"mode\" value=\"normal\" checked /><label for=\"n\">".get_string("normal","scorm")."</label>\n";
+        } else {
+            echo "<input type=\"radio\" id=\"r\" name=\"mode\" value=\"review\" checked /><label for=\"r\">".get_string("review","scorm")."</label>\n";
+       }
+       echo "</td>\n</tr>\n<tr><td align=\"center\">";
+       echo '<input type="hidden" name="scoid" />
+       <input type="submit" value="'.get_string("entercourse","scorm").'" />';
+        echo "\n</td>\n</tr>\n</table>\n</form><br />";
+?>
+<script language="javascript">
+<!--
+    function playSCO(scoid,status) {
+       document.theform.scoid.value = scoid;
+       document.theform.submit();
+    }
+    
+    function expandCollide(which,list) {
+       var nn=document.ids?true:false
+       var w3c=document.getElementById?true:false
+       var beg=nn?"document.ids.":w3c?"document.getElementById(":"document.all.";
+       var mid=w3c?").style":".style";
+       
+       if (eval(beg+list+mid+".display") != "none") {
+           which.src = "pix/plus.gif";
+           eval(beg+list+mid+".display='none';");
+       } else {
+           which.src = "pix/minus.gif";
+           eval(beg+list+mid+".display='block';");
+       }
+       
+    }
+-->
+</script>
+<?php
+       print_footer($course);
+    }
+?>