2 /************************************************************************/
4 /************************************************************************/
5 /* Copyright (c) 2002-2008 by Greg Gay, Harris Wong */
6 /* Adaptive Technology Resource Centre / University of Toronto */
9 /* This program is free software. You can redistribute it and/or */
10 /* modify it under the terms of the GNU General Public License */
11 /* as published by the Free Software Foundation. */
12 /************************************************************************/
15 define('AT_INCLUDE_PATH', '../../include/');
16 require(AT_INCLUDE_PATH.'vitals.inc.php');
17 require(AT_INCLUDE_PATH.'lib/filemanager.inc.php'); /* for clr_dir() and preImportCallBack and dirsize() */
18 require(AT_INCLUDE_PATH.'lib/qti.inc.php');
19 require(AT_INCLUDE_PATH.'classes/pclzip.lib.php');
20 //require(AT_INCLUDE_PATH.'classes/QTI/QTIParser.class.php');
21 require(AT_INCLUDE_PATH.'classes/QTI/QTIImport.class.php');
23 /* to avoid timing out on large files */
25 $_SESSION['done'] = 1;
27 $element_path = array();
33 if (isset($_POST['submit_yes'])){
35 } elseif (isset($_POST['submit_no'])){
36 $msg->addFeedback('IMPORT_CANCELLED');
37 header('Location: question_db.php');
42 /* called at the start of en element */
43 /* builds the $path array which is the path from the root to the current element */
44 function startElement($parser, $name, $attrs) {
45 global $attributes, $element_path, $resource_num;
49 $attributes[$name.$resource_num]['identifier'] = $attrs['identifier'];
50 $attributes[$name.$resource_num]['href'] = $attrs['href'];
51 $attributes[$name.$resource_num]['type'] = $attrs['type'];
55 if(in_array('resource', $element_path)){
56 $attributes['resource'.($resource_num-1)]['file'][] = $attrs['href'];
60 if(in_array('resource', $element_path)){
61 $attributes['resource'.($resource_num-1)]['dependency'][] = $attrs['identifierref'];
66 array_push($element_path, $name);
69 /* called when an element ends */
70 /* removed the current element from the $path */
71 function endElement($parser, $name) {
73 array_pop($element_path);
76 /* called when there is character data within elements */
77 /* constructs the $items array using the last entry in $path as the parent element */
78 function characterData($parser, $data){
79 global $character_data;
81 $character_data .= preg_replace('/[\t\0\x0B]*/', '', $data);
85 //If overwrite hasn't been set to true, then the file has not been exported and still in the cache.
86 //otherwise, the zip file is extracted but has not been deleted (due to the confirmation).
88 if (!isset($_POST['submit_import'])) {
89 /* just a catch all */
91 $errors = array('FILE_MAX_SIZE', ini_get('post_max_size'));
92 $msg->addError($errors);
94 header('Location: ./question_db.php');
101 if (isset($_POST['url']) && ($_POST['url'] != 'http://') ) {
102 if ($content = @file_get_contents($_POST['url'])) {
104 // save file to /content/
105 $filename = substr(time(), -6). '.zip';
106 $full_filename = AT_CONTENT_DIR . $filename;
108 if (!$fp = fopen($full_filename, 'w+b')) {
109 echo "Cannot open file ($filename)";
113 if (fwrite($fp, $content, strlen($content) ) === FALSE) {
114 echo "Cannot write to file ($filename)";
119 $_FILES['file']['name'] = $filename;
120 $_FILES['file']['tmp_name'] = $full_filename;
121 $_FILES['file']['size'] = strlen($content);
123 $url_parts = pathinfo($_POST['url']);
124 $package_base_name_url = $url_parts['basename'];
127 $ext = pathinfo($_FILES['file']['name']);
128 $ext = $ext['extension'];
131 $msg->addError('IMPORTDIR_IMS_NOTVALID');
132 } else if ($_FILES['file']['error'] == 1) {
133 $errors = array('FILE_MAX_SIZE', ini_get('upload_max_filesize'));
134 $msg->addError($errors);
135 } else if ( !$_FILES['file']['name'] || (!is_uploaded_file($_FILES['file']['tmp_name']) && !$_POST['url'])) {
136 $msg->addError('FILE_NOT_SELECTED');
137 } else if ($_FILES['file']['size'] == 0) {
138 $msg->addError('IMPORTFILE_EMPTY');
142 if ($msg->containsErrors()) {
143 if (isset($_GET['tile'])) {
144 header('Location: '.$_base_path.'tools/tile/index.php');
146 header('Location: question_db.php');
151 /* check if ../content/import/ exists */
152 $import_path = AT_CONTENT_DIR . 'import/';
153 $content_path = AT_CONTENT_DIR;
155 if (!is_dir($import_path)) {
156 if (!@mkdir($import_path, 0700)) {
157 $msg->addError('IMPORTDIR_FAILED');
161 $import_path .= $_SESSION['course_id'].'/';
163 if (is_dir($import_path)) {
164 clr_dir($import_path);
167 if (!@mkdir($import_path, 0700)) {
168 $msg->addError('IMPORTDIR_FAILED');
171 /* extract the entire archive into AT_COURSE_CONTENT . import/$course using the call back function to filter out php files */
173 $archive = new PclZip($_FILES['file']['tmp_name']);
174 if ($archive->extract( PCLZIP_OPT_PATH, $import_path,
175 PCLZIP_CB_PRE_EXTRACT, 'preImportCallBack') == 0) {
176 $msg->addError('IMPORT_FAILED');
177 echo 'Error : '.$archive->errorInfo(true);
178 clr_dir($import_path);
179 header('Location: questin_db.php');
182 error_reporting(AT_ERROR_REPORTING);
185 /* get the course's max_quota */
186 $sql = "SELECT max_quota FROM ".TABLE_PREFIX."courses WHERE course_id=$_SESSION[course_id]";
187 $result = mysql_query($sql, $db);
188 $q_row = mysql_fetch_assoc($result);
190 if ($q_row['max_quota'] != AT_COURSESIZE_UNLIMITED) {
192 if ($q_row['max_quota'] == AT_COURSESIZE_DEFAULT) {
193 $q_row['max_quota'] = $MaxCourseSize;
195 $totalBytes = dirsize($import_path);
196 $course_total = dirsize(AT_CONTENT_DIR . $_SESSION['course_id'].'/');
197 $total_after = $q_row['max_quota'] - $course_total - $totalBytes + $MaxCourseFloat;
199 if ($total_after < 0) {
200 /* remove the content dir, since there's no space for it */
201 $errors = array('NO_CONTENT_SPACE', number_format(-1*($total_after/AT_KBYTE_SIZE), 2 ) );
202 $msg->addError($errors);
204 clr_dir($import_path);
206 if (isset($_GET['tile'])) {
207 header('Location: '.$_base_path.'tools/tile/index.php');
209 header('Location: question_db.php');
215 $ims_manifest_xml = @file_get_contents($import_path.'imsmanifest.xml');
217 if ($ims_manifest_xml === false) {
218 $msg->addError('NO_IMSMANIFEST');
220 if (file_exists($import_path . 'atutor_backup_version')) {
221 $msg->addError('NO_IMS_BACKUP');
224 clr_dir($import_path);
226 if (isset($_GET['tile'])) {
227 header('Location: '.$_base_path.'tools/tile/index.php');
229 header('Location: question_db.php');
234 $xml_parser = xml_parser_create();
236 xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */
237 xml_set_element_handler($xml_parser, 'startElement', 'endElement');
238 xml_set_character_data_handler($xml_parser, 'characterData');
240 if (!xml_parse($xml_parser, $ims_manifest_xml, true)) {
241 die(sprintf("XML error: %s at line %d",
242 xml_error_string(xml_get_error_code($xml_parser)),
243 xml_get_current_line_number($xml_parser)));
246 xml_parser_free($xml_parser);
248 //assign folder names
249 //if (!$package_base_name){
250 // $package_base_name = substr($_FILES['file']['name'], 0, -4);
253 //$package_base_name = strtolower($package_base_name);
254 //$package_base_name = str_replace(array('\'', '"', ' ', '|', '\\', '/', '<', '>', ':'), '_' , $package_base_name);
255 //$package_base_name = preg_replace("/[^A-Za-z0-9._\-]/", '', $package_base_name);
257 //if (is_dir(AT_CONTENT_DIR . $_SESSION['course_id'].'/'.$package_base_name)) {
258 // echo 'Already exist: Quitting. (Need better msg here)';
260 // $package_base_name .= '_'.date('ymdHis');
263 if ($package_base_path) {
264 $package_base_path = implode('/', $package_base_path);
267 //Dependency handling
268 //$media_items = array();
269 $xml_items = array();
270 //foreach($attributes as $resource=>$attrs){
271 // if ($attrs['type'] != 'webcontent'){
272 // $media_items[$attrs['identifier']] = $attrs['file'];
276 //Check if the files exist, if so, warn the user.
277 $existing_files = isQTIFileExist($attributes);
278 //debug($existing_files);
279 if (!$overwrite && !empty($existing_files)){
280 $existing_files = implode('<br/>', $existing_files);
281 require(AT_INCLUDE_PATH.'header.inc.php');
282 // $msg->addConfirm(array('MEDIA_FILE_EXISTED', $existing_files));
283 // $msg->printConfirm();
284 echo '<form action="" method="POST">';
285 echo '<div class="input-form">';
286 echo '<div class="row">';
287 $msg->printInfos(array('MEDIA_FILE_EXISTED', $existing_files));
289 echo '<div class="row buttons">';
290 echo '<input type="submit" class="" name="submit_yes" value="'._AT('yes').'"/>';
291 echo '<input type="submit" class="" name="submit_no" value="'._AT('no').'"/>';
292 echo '<input type="hidden" name="submit_import" value="submit_import" />';
293 ECHO '<input type="hidden" name="url" value="'.$_POST['url'].'" />';
296 require (AT_INCLUDE_PATH.'footer.inc.php');
302 //Get the XML file out and start importing them into our database.
303 //TODO: import_test.php shares approx. the same code as below, just that import_test.php has
304 // an extra line of code that uses a stack to remember the question #. Might want to
305 // create a function for this.
306 $qti_import = new QTIImport($import_path);
307 $qti_import->importQuestions($attributes);
310 clr_dir(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id']);
311 if (!$msg->containsErrors()) {
312 $msg->addFeedback('IMPORT_SUCCEEDED');
315 header('Location: question_db.php');