made a copy
[atutor.git] / tools / ims / ims_import.php
1 <?php
2 /****************************************************************/
3 /* ATutor                                                                                                               */
4 /****************************************************************/
5 /* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
6 /* Adaptive Technology Resource Centre / University of Toronto  */
7 /* http://atutor.ca                                                                                             */
8 /*                                                              */
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 /****************************************************************/
13 // $Id$
14 define('AT_INCLUDE_PATH', '../../include/');
15 require(AT_INCLUDE_PATH.'vitals.inc.php');
16
17 require(AT_INCLUDE_PATH.'lib/filemanager.inc.php'); /* for clr_dir() and preImportCallBack and dirsize() */
18 require(AT_INCLUDE_PATH.'classes/pclzip.lib.php');
19 require(AT_INCLUDE_PATH.'lib/qti.inc.php'); 
20 //require(AT_INCLUDE_PATH.'classes/QTI/QTIParser.class.php');   
21 require(AT_INCLUDE_PATH.'classes/QTI/QTIImport.class.php');
22 require(AT_INCLUDE_PATH.'classes/A4a/A4aImport.class.php');
23
24 /* make sure we own this course that we're exporting */
25 authenticate(AT_PRIV_CONTENT);
26
27 /* to avoid timing out on large files */
28 @set_time_limit(0);
29 $_SESSION['done'] = 1;
30
31 $html_head_tags = array("style", "script");
32
33 $package_base_path = '';
34 $xml_base_path = '';
35 $element_path = array();
36 $imported_glossary = array();
37 $test_attributes = array();
38 $character_data = '';
39 $test_message = '';
40
41         /* called at the start of en element */
42         /* builds the $path array which is the path from the root to the current element */
43         function startElement($parser, $name, $attrs) {
44                 global $items, $path, $package_base_path;
45                 global $element_path;
46                 global $xml_base_path, $test_message;
47                 global $current_identifier;
48
49                 if ($name == 'manifest' && isset($attrs['xml:base']) && $attrs['xml:base']) {
50                         $xml_base_path = $attrs['xml:base'];
51                 } else if ($name == 'file') {
52
53                         // special case for webCT content packages that don't specify the `href` attribute 
54                         // with the `<resource>` element.
55                         // we take the `href` from the first `<file>` element.
56
57                         if (isset($items[$current_identifier]) && ($items[$current_identifier]['href'] == '')) {
58                                 $attrs['href'] = urldecode($attrs['href']);
59
60                                 $items[$current_identifier]['href'] = $attrs['href'];
61
62                                 $items[$current_identifier]['href'] = $attrs['href'];
63
64                                 $temp_path = pathinfo($attrs['href']);
65                                 $temp_path = explode('/', $temp_path['dirname']);
66
67                                 if ($package_base_path == '') {
68                                         $package_base_path = $temp_path;
69                                 } 
70 //                              else {
71 //                                      $package_base_path = array_intersect($package_base_path, $temp_path);
72 //                              }
73
74                                 $items[$current_identifier]['new_path'] = implode('/', $temp_path);
75                         } 
76
77                         if (    isset($_POST['allow_test_import']) && isset($items[$current_identifier]) 
78                                                 && preg_match('/((.*)\/)*tests\_[0-9]+\.xml$/', $attrs['href'])) {
79                                 $items[$current_identifier]['tests'][] = $attrs['href'];
80                         } 
81                         if (    isset($_POST['allow_a4a_import']) && isset($items[$current_identifier])) {
82                                 $items[$current_identifier]['a4a_import_enabled'] = true;
83                         }
84                 } else if (($name == 'item') && ($attrs['identifierref'] != '')) {
85                         $path[] = $attrs['identifierref'];
86                 } else if (($name == 'item') && ($attrs['identifier'])) {
87                         $path[] = $attrs['identifier'];
88                 } else if (($name == 'resource') && is_array($items[$attrs['identifier']]))  {
89                         $current_identifier = $attrs['identifier'];
90
91                         if ($attrs['href']) {
92                                 $attrs['href'] = urldecode($attrs['href']);
93
94                                 $items[$attrs['identifier']]['href'] = $attrs['href'];
95
96                                 // href points to a remote url
97                                 if (preg_match('/^http.*:\/\//', trim($attrs['href'])))
98                                         $items[$attrs['identifier']]['new_path'] = '';
99                                 else // href points to local file
100                                 {
101                                         $temp_path = pathinfo($attrs['href']);
102                                         $temp_path = explode('/', $temp_path['dirname']);
103                                         if (!$package_base_path) {
104                                                 $package_base_path = $temp_path;
105                                         } else {
106                                                 $package_base_path = array_intersect($package_base_path, $temp_path);
107                                         }
108         
109                                         $items[$attrs['identifier']]['new_path'] = implode('/', $temp_path);
110                                 }
111                         }
112
113                         //if test custom message has not been saved
114 //                      if (!isset($items[$current_identifier]['test_message'])){
115 //                              $items[$current_identifier]['test_message'] = $test_message;
116 //                      }
117                 } 
118                 if (($name == 'item') && ($attrs['parameters'] != '')) {
119                         $items[$attrs['identifierref']]['test_message'] = $attrs['parameters'];
120                 }
121                 if ($name=='file'){
122                         if (file_exists(AT_CONTENT_DIR .'import/'.$_SESSION['course_id'].'/'.$attrs['href'])){
123                                 $items[$current_identifier]['file'][] = $attrs['href'];
124                         }
125                 }
126         array_push($element_path, $name);
127 }
128
129         /* called when an element ends */
130         /* removed the current element from the $path */
131         function endElement($parser, $name) {
132                 global $path, $element_path, $my_data, $items;
133                 global $current_identifier;
134                 global $msg;
135                 static $resource_num = 0;
136                 
137                 if ($name == 'item') {
138                         array_pop($path);
139                 } 
140
141                 //check if this is a test import
142                 if ($name == 'schema'){
143                         if (trim($my_data)=='IMS Question and Test Interoperability'){                  
144                                 $msg->addError('IMPORT_FAILED');
145                         }
146                 }
147
148                 //Handles A4a
149                 if ($current_identifier != ''){
150                         $my_data = trim($my_data);
151                         $last_file_name = $items[$current_identifier]['file'][(sizeof($items[$current_identifier]['file']))-1];
152
153                         if ($name=='originalAccessMode'){
154                                 if (in_array('accessModeStatement', $element_path)){
155                                         $items[$current_identifier]['a4a'][$last_file_name][$resource_num]['access_stmt_originalAccessMode'][] = $my_data;
156                                 } elseif (in_array('adaptationStatement', $element_path)){
157                                         $items[$current_identifier]['a4a'][$last_file_name][$resource_num]['adapt_stmt_originalAccessMode'][] = $my_data;
158                                 }                       
159                         } elseif (($name=='language') && in_array('accessModeStatement', $element_path)){
160                                 $items[$current_identifier]['a4a'][$last_file_name][$resource_num]['language'][] = $my_data;
161                         } elseif ($name=='hasAdaptation') {
162                                 $items[$current_identifier]['a4a'][$last_file_name][$resource_num]['hasAdaptation'][] = $my_data;
163                         } elseif ($name=='isAdaptationOf'){
164                                 $items[$current_identifier]['a4a'][$last_file_name][$resource_num]['isAdaptationOf'][] = $my_data;
165                         } elseif ($name=='accessForAllResource'){
166                                 $resource_num++;
167                         } elseif($name=='file'){
168                                 $resource_num = 0;      //reset resournce number to 0 when the file tags ends
169                         }
170                 }
171
172                 if ($element_path === array('manifest', 'metadata', 'imsmd:lom', 'imsmd:general', 'imsmd:title', 'imsmd:langstring')) {
173                         global $package_base_name;
174                         $package_base_name = trim($my_data);
175                 }
176
177                 array_pop($element_path);
178                 $my_data = '';
179         }
180
181         /* called when there is character data within elements */
182         /* constructs the $items array using the last entry in $path as the parent element */
183         function characterData($parser, $data){
184                 global $path, $items, $order, $my_data, $element_path;
185
186                 $str_trimmed_data = trim($data);
187                                 
188                 if (!empty($str_trimmed_data)) {
189                         $size = count($path);
190                         if ($size > 0) {
191                                 $current_item_id = $path[$size-1];
192                                 if ($size > 1) {
193                                         $parent_item_id = $path[$size-2];
194                                 } else {
195                                         $parent_item_id = 0;
196                                 }
197
198                                 if (isset($items[$current_item_id]['parent_content_id']) && is_array($items[$current_item_id])) {
199
200                                         /* this item already exists, append the title           */
201                                         /* this fixes {\n, \t, `, &} characters in elements */
202
203                                         /* horible kludge to fix the <ns2:objectiveDesc xmlns:ns2="http://www.utoronto.ca/atrc/tile/xsd/tile_objective"> */
204                                         /* from TILE */
205                                         if (in_array('accessForAllResource', $element_path)){
206                                                 //skip this tag
207                                         } elseif ($element_path[count($element_path)-1] != 'ns1:objectiveDesc') {
208                                                 $items[$current_item_id]['title'] .= $data;
209                                         }
210         
211                                 } else {
212                                         $order[$parent_item_id] ++;
213
214                                         $item_tmpl = array(     'title'                 => $data,
215                                                                                 'parent_content_id' => $parent_item_id,
216                                                                                 'ordering'                      => $order[$parent_item_id]-1);
217
218                                         //append other array values if it exists
219                                         if (is_array($items[$current_item_id])){
220                                                 $items[$current_item_id] = array_merge($items[$current_item_id], $item_tmpl);
221                                         } else {
222                                                 $items[$current_item_id] = $item_tmpl;
223                                         }
224                                 }
225                         }
226                 }
227
228                 $my_data .= $data;
229         }
230
231         /* glossary parser: */
232         function glossaryStartElement($parser, $name, $attrs) {
233                 global $element_path;
234
235                 array_push($element_path, $name);
236         }
237
238         /* called when an element ends */
239         /* removed the current element from the $path */
240         function glossaryEndElement($parser, $name) {
241                 global $element_path, $my_data, $imported_glossary;
242                 static $current_term;
243
244                 if ($element_path === array('glossary', 'item', 'term')) {
245                         $current_term = $my_data;
246
247                 } else if ($element_path === array('glossary', 'item', 'definition')) {
248                         $imported_glossary[trim($current_term)] = trim($my_data);
249                 }
250
251                 array_pop($element_path);
252                 $my_data = '';
253         }
254
255         function glossaryCharacterData($parser, $data){
256                 global $my_data;
257
258                 $my_data .= $data;
259         }
260
261 if (!isset($_POST['submit']) && !isset($_POST['cancel'])) {
262         /* just a catch all */
263         
264         $errors = array('FILE_MAX_SIZE', ini_get('post_max_size'));
265         $msg->addError($errors);
266
267         header('Location: ./index.php');
268         exit;
269 } else if (isset($_POST['cancel'])) {
270         $msg->addFeedback('IMPORT_CANCELLED');
271
272         header('Location: ./index.php');
273         exit;
274 }
275
276 $cid = intval($_POST['cid']);
277
278 if (isset($_POST['url']) && ($_POST['url'] != 'http://') ) {
279         if ($content = @file_get_contents($_POST['url'])) {
280
281                 // save file to /content/
282                 $filename = substr(time(), -6). '.zip';
283                 $full_filename = AT_CONTENT_DIR . $filename;
284
285                 if (!$fp = fopen($full_filename, 'w+b')) {
286                         echo "Cannot open file ($filename)";
287                         exit;
288                 }
289
290                 if (fwrite($fp, $content, strlen($content) ) === FALSE) {
291                         echo "Cannot write to file ($filename)";
292                         exit;
293                 }
294                 fclose($fp);
295         }       
296         $_FILES['file']['name']     = $filename;
297         $_FILES['file']['tmp_name'] = $full_filename;
298         $_FILES['file']['size']     = strlen($content);
299         unset($content);
300         $url_parts = pathinfo($_POST['url']);
301         $package_base_name_url = $url_parts['basename'];
302 }
303 $ext = pathinfo($_FILES['file']['name']);
304 $ext = $ext['extension'];
305
306 if ($ext != 'zip') {
307         $msg->addError('IMPORTDIR_IMS_NOTVALID');
308 } else if ($_FILES['file']['error'] == 1) {
309         $errors = array('FILE_MAX_SIZE', ini_get('upload_max_filesize'));
310         $msg->addError($errors);
311 } else if ( !$_FILES['file']['name'] || (!is_uploaded_file($_FILES['file']['tmp_name']) && !$_POST['url'])) {
312         $msg->addError('FILE_NOT_SELECTED');
313 } else if ($_FILES['file']['size'] == 0) {
314         $msg->addError('IMPORTFILE_EMPTY');
315
316
317 if ($msg->containsErrors()) {
318         if (isset($_GET['tile'])) {
319                 header('Location: '.$_base_path.'tools/tile/index.php');
320         } else {
321                 header('Location: index.php');
322         }
323         exit;
324 }
325
326 /* check if ../content/import/ exists */
327 $import_path = AT_CONTENT_DIR . 'import/';
328 $content_path = AT_CONTENT_DIR;
329
330 if (!is_dir($import_path)) {
331         if (!@mkdir($import_path, 0700)) {
332                 $msg->addError('IMPORTDIR_FAILED');
333         }
334 }
335
336 $import_path .= $_SESSION['course_id'].'/';
337 if (is_dir($import_path)) {
338         clr_dir($import_path);
339 }
340
341 if (!@mkdir($import_path, 0700)) {
342         $msg->addError('IMPORTDIR_FAILED');
343 }
344
345 if ($msg->containsErrors()) {
346         if (isset($_GET['tile'])) {
347                 header('Location: '.$_base_path.'tools/tile/index.php');
348         } else {
349                 header('Location: index.php');
350         }
351         exit;
352 }
353
354 /* extract the entire archive into AT_COURSE_CONTENT . import/$course using the call back function to filter out php files */
355 error_reporting(0);
356 $archive = new PclZip($_FILES['file']['tmp_name']);
357 if ($archive->extract(  PCLZIP_OPT_PATH,        $import_path,
358                                                 PCLZIP_CB_PRE_EXTRACT,  'preImportCallBack') == 0) {
359         $msg->addError('IMPORT_FAILED');
360         echo 'Error : '.$archive->errorInfo(true);
361         clr_dir($import_path);
362         header('Location: index.php');
363         exit;
364 }
365 error_reporting(AT_ERROR_REPORTING);
366
367 /* get the course's max_quota */
368 $sql    = "SELECT max_quota FROM ".TABLE_PREFIX."courses WHERE course_id=$_SESSION[course_id]";
369 $result = mysql_query($sql, $db);
370 $q_row  = mysql_fetch_assoc($result);
371
372 if ($q_row['max_quota'] != AT_COURSESIZE_UNLIMITED) {
373
374         if ($q_row['max_quota'] == AT_COURSESIZE_DEFAULT) {
375                 $q_row['max_quota'] = $MaxCourseSize;
376         }
377         $totalBytes   = dirsize($import_path);
378         $course_total = dirsize(AT_CONTENT_DIR . $_SESSION['course_id'].'/');
379         $total_after  = $q_row['max_quota'] - $course_total - $totalBytes + $MaxCourseFloat;
380
381         if ($total_after < 0) {
382                 /* remove the content dir, since there's no space for it */
383                 $errors = array('NO_CONTENT_SPACE', number_format(-1*($total_after/AT_KBYTE_SIZE), 2 ) );
384                 $msg->addError($errors);
385                 
386                 clr_dir($import_path);
387
388                 if (isset($_GET['tile'])) {
389                         header('Location: '.$_base_path.'tools/tile/index.php');
390                 } else {
391                         header('Location: index.php');
392                 }
393                 exit;
394         }
395 }
396
397
398 $items = array(); /* all the content pages */
399 $order = array(); /* keeps track of the ordering for each content page */
400 $path  = array();  /* the hierarchy path taken in the menu to get to the current item in the manifest */
401
402 /*
403 $items[content_id/resource_id] = array(
404                                                                         'title'
405                                                                         'real_content_id' // calculated after being inserted
406                                                                         'parent_content_id'
407                                                                         'href'
408                                                                         'ordering'
409                                                                         );
410 */
411
412 $ims_manifest_xml = @file_get_contents($import_path.'imsmanifest.xml');
413
414 if ($ims_manifest_xml === false) {
415         $msg->addError('NO_IMSMANIFEST');
416
417         if (file_exists($import_path . 'atutor_backup_version')) {
418                 $msg->addError('NO_IMS_BACKUP');
419         }
420
421         clr_dir($import_path);
422
423         if (isset($_GET['tile'])) {
424                 header('Location: '.$_base_path.'tools/tile/index.php');
425         } else {
426                 header('Location: index.php');
427         }
428         exit;
429 }
430
431 $xml_parser = xml_parser_create();
432
433 xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */
434 xml_set_element_handler($xml_parser, 'startElement', 'endElement');
435 xml_set_character_data_handler($xml_parser, 'characterData');
436
437 if (!xml_parse($xml_parser, $ims_manifest_xml, true)) {
438         die(sprintf("XML error: %s at line %d",
439                                 xml_error_string(xml_get_error_code($xml_parser)),
440                                 xml_get_current_line_number($xml_parser)));
441 }
442
443 xml_parser_free($xml_parser);
444
445
446 /* check if the glossary terms exist */
447 if (file_exists($import_path . 'glossary.xml')){
448         $glossary_xml = @file_get_contents($import_path.'glossary.xml');
449         $element_path = array();
450
451         $xml_parser = xml_parser_create();
452
453         /* insert the glossary terms into the database (if they're not in there already) */
454         /* parse the glossary.xml file and insert the terms */
455         xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */
456         xml_set_element_handler($xml_parser, 'glossaryStartElement', 'glossaryEndElement');
457         xml_set_character_data_handler($xml_parser, 'glossaryCharacterData');
458
459         if (!xml_parse($xml_parser, $glossary_xml, true)) {
460                 die(sprintf("XML error: %s at line %d",
461                                         xml_error_string(xml_get_error_code($xml_parser)),
462                                         xml_get_current_line_number($xml_parser)));
463         }
464         xml_parser_free($xml_parser);
465         $contains_glossary_terms = true;
466         foreach ($imported_glossary as $term => $defn) {
467                 if (!$glossary[urlencode($term)]) {
468                         $sql = "INSERT INTO ".TABLE_PREFIX."glossary VALUES (NULL, $_SESSION[course_id], '$term', '$defn', 0)";
469                         mysql_query($sql, $db); 
470                 }
471         }
472 }
473
474 // Check if there are any errors during parsing.
475 if ($msg->containsErrors()) {
476         if (isset($_GET['tile'])) {
477                 header('Location: '.$_base_path.'tools/tile/index.php');
478         } else {
479                 header('Location: index.php');
480         }
481         exit;
482 }
483
484 /* generate a unique new package base path based on the package file name and date as needed. */
485 /* the package name will be the dir where the content for this package will be put, as a result */
486 /* the 'content_path' field in the content table will be set to this path. */
487 /* $package_base_name_url comes from the URL file name (NOT the file name of the actual file we open)*/
488 if (!$package_base_name && $package_base_name_url) {
489         $package_base_name = substr($package_base_name_url, 0, -4);
490 } else if (!$package_base_name) {
491         $package_base_name = substr($_FILES['file']['name'], 0, -4);
492 }
493
494 $package_base_name = strtolower($package_base_name);
495 $package_base_name = str_replace(array('\'', '"', ' ', '|', '\\', '/', '<', '>', ':'), '_' , $package_base_name);
496 $package_base_name = preg_replace("/[^A-Za-z0-9._\-]/", '', $package_base_name);
497
498 if (is_dir(AT_CONTENT_DIR . $_SESSION['course_id'].'/'.$package_base_name)) {
499         $package_base_name .= '_'.date('ymdHis');
500 }
501
502 if ($package_base_path) {
503         $package_base_path = implode('/', $package_base_path);
504 } elseif (empty($package_base_path)){
505         $package_base_path = '';
506 }
507
508 if ($xml_base_path) {
509         $package_base_path = $xml_base_path . $package_base_path;
510
511         mkdir(AT_CONTENT_DIR .$_SESSION['course_id'].'/'.$xml_base_path);
512         $package_base_name = $xml_base_path . $package_base_name;
513 }
514 reset($items);
515
516 /* get the top level content ordering offset */
517 $sql    = "SELECT MAX(ordering) AS ordering FROM ".TABLE_PREFIX."content WHERE course_id=$_SESSION[course_id] AND content_parent_id=$cid";
518 $result = mysql_query($sql, $db);
519 $row    = mysql_fetch_assoc($result);
520 $order_offset = intval($row['ordering']); /* it's nice to have a real number to deal with */
521
522 foreach ($items as $item_id => $content_info) 
523 {
524         // remote href
525         if (preg_match('/^http.*:\/\//', trim($content_info['href'])) )
526         {
527                 $content = '<a href="'.$content_info['href'].'" target="_blank">'.$content_info['title'].'</a>';
528         }
529         else
530         {
531                 if (isset($content_info['href'], $xml_base_path)) {
532                         $content_info['href'] = $xml_base_path . $content_info['href'];
533                 }
534                 if (!isset($content_info['href'])) {
535                         // this item doesn't have an identifierref. so create an empty page.
536                         $content = '';
537                         $ext = '';
538                         $last_modified = date('Y-m-d H:i:s');
539                 } else {
540                         $file_info = @stat(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/'.$content_info['href']);
541                         if ($file_info === false) {
542                                 continue;
543                         }
544                 
545                         $path_parts = pathinfo(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/'.$content_info['href']);
546                         $ext = strtolower($path_parts['extension']);
547
548                         $last_modified = date('Y-m-d H:i:s', $file_info['mtime']);
549                 }
550                 if (in_array($ext, array('gif', 'jpg', 'bmp', 'png', 'jpeg'))) {
551                         /* this is an image */
552                         $content = '<img src="'.$content_info['href'].'" alt="'.$content_info['title'].'" />';
553                 } else if ($ext == 'swf') {
554                         /* this is flash */
555             /* Using default size of 550 x 400 */
556
557                         $content = '<object type="application/x-shockwave-flash" data="' . $content_info['href'] . '" width="550" height="400"><param name="movie" value="'. $content_info['href'] .'" /></object>';
558
559                 } else if ($ext == 'mov') {
560                         /* this is a quicktime movie  */
561             /* Using default size of 550 x 400 */
562
563                         $content = '<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="550" height="400" codebase="http://www.apple.com/qtactivex/qtplugin.cab"><param name="src" value="'. $content_info['href'] . '" /><param name="autoplay" value="true" /><param name="controller" value="true" /><embed src="' . $content_info['href'] .'" width="550" height="400" controller="true" pluginspage="http://www.apple.com/quicktime/download/"></embed></object>';
564                 } else if ($ext == 'mp3') {
565                         $content = '<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="200" height="15" codebase="http://www.apple.com/qtactivex/qtplugin.cab"><param name="src" value="'. $content_info['href'] . '" /><param name="autoplay" value="false" /><embed src="' . $content_info['href'] .'" width="200" height="15" autoplay="false" pluginspage="http://www.apple.com/quicktime/download/"></embed></object>';
566                 } else if (in_array($ext, array('wav', 'au'))) {
567                         $content = '<embed SRC="'.$content_info['href'].'" autostart="false" width="145" height="60"><noembed><bgsound src="'.$content_info['href'].'"></noembed></embed>';
568
569                 } else if (in_array($ext, array('txt', 'css', 'html', 'htm', 'csv', 'asc', 'tsv', 'xml', 'xsl'))) {
570                         /* this is a plain text file */
571                         $content = file_get_contents(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/'.$content_info['href']);
572                         if ($content === false) {
573                                 /* if we can't stat() it then we're unlikely to be able to read it */
574                                 /* so we'll never get here. */
575                                 continue;
576                         }
577
578                         // get the contents of the 'head' element
579                         $head = get_html_head_by_tag($content, $html_head_tags);
580                         
581                         // Specifically handle eXe package
582                         // NOTE: THIS NEEDS WORK! TO FIND A WAY APPLY EXE .CSS FILES ONLY ON COURSE CONTENT PART.
583                         // NOW USE OUR OWN .CSS CREATED SOLELY FOR EXE
584                         $isExeContent = false;
585
586                         // check xml file in eXe package
587                         if (preg_match("/<organization[ ]*identifier=\"eXe*>*/", $ims_manifest_xml))
588                         {
589                                 $isExeContent = true;
590                         }
591
592                         // use ATutor's eXe style sheet as the ones from eXe conflicts with ATutor's style sheets
593                         if ($isExeContent)
594                         {
595                                 $head = preg_replace ('/(<style.*>)(.*)(<\/style>)/ms', '\\1@import url(/docs/exestyles.css);\\3', $head);
596                         }
597
598                         // end of specifically handle eXe package
599
600                         $content = get_html_body($content);
601                         if ($contains_glossary_terms) 
602                         {
603                                 // replace glossary content package links to real glossary mark-up using [?] [/?]
604                                 // refer to bug 3641, edited by Harris
605                                 $content = preg_replace('/<a href="([.\w\d\s]+[^"]+)" target="body" class="at-term">([.\w\d\s&;"]+|.*)<\/a>/i', '[?]\\2[/?]', $content);
606                         }
607
608                         /* potential security risk? */
609                         if ( strpos($content_info['href'], '..') === false && !preg_match('/((.*)\/)*tests\_[0-9]+\.xml$/', $content_info['href'])) {
610                                 @unlink(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/'.$content_info['href']);
611                         }
612                 } else if ($ext) {
613                         /* non text file, and can't embed (example: PDF files) */
614                         $content = '<a href="'.$content_info['href'].'">'.$content_info['title'].'</a>';
615                 }
616         }
617
618         $content_parent_id = $cid;
619         if ($content_info['parent_content_id'] !== 0) {
620                 $content_parent_id = $items[$content_info['parent_content_id']]['real_content_id'];
621         }
622
623         $my_offset = 0;
624         if ($content_parent_id == $cid) {
625                 $my_offset = $order_offset;
626         }
627
628         /* replace the old path greatest common denomiator with the new package path. */
629         /* we don't use str_replace, b/c there's no knowing what the paths may be         */
630         /* we only want to replace the first part of the path.                                            */
631         if ($package_base_path != '') {
632                 $content_info['new_path']       = $package_base_name . substr($content_info['new_path'], strlen($package_base_path));
633         } else {
634                 $content_info['new_path'] = $package_base_name;
635         }
636         
637         $head = addslashes($head);
638         $content_info['title'] = addslashes($content_info['title']);
639         $content_info['test_message'] = addslashes($content_info['test_message']);
640
641         //if this file is a test_xml, create a blank page instead, for imscc.
642         if (preg_match('/((.*)\/)*tests\_[0-9]+\.xml$/', $content_info['href'])){
643                 $content = '';
644         } else {
645                 $content = addslashes($content);
646         }
647
648         $sql= 'INSERT INTO '.TABLE_PREFIX.'content'
649               . '(course_id, 
650                   content_parent_id, 
651                   ordering,
652                   last_modified, 
653                   revision, 
654                   formatting, 
655                   release_date,
656                   head,
657                   use_customized_head,
658                   keywords, 
659                   content_path, 
660                   title, 
661                   text,
662                           test_message) 
663                VALUES 
664                              ('.$_SESSION['course_id'].','                                                                                                                      
665                              .intval($content_parent_id).','            
666                              .($content_info['ordering'] + $my_offset + 1).','
667                              .'"'.$last_modified.'",                                                                                                    
668                               0,
669                               1,
670                               NOW(),"'
671                              . $head .'",
672                              1,
673                               "",'
674                              .'"'.$content_info['new_path'].'",'
675                              .'"'.$content_info['title'].'",'
676                              .'"'.$content.'",'
677                                  .'"'.$content_info['test_message'].'")';
678
679         $result = mysql_query($sql, $db) or die(mysql_error());
680
681         /* get the content id and update $items */
682         $items[$item_id]['real_content_id'] = mysql_insert_id($db);
683
684         /* get the tests associated with this content */
685         if (!empty($items[$item_id]['tests'])){
686                 $qti_import =& new QTIImport($import_path);
687
688                 foreach ($items[$item_id]['tests'] as $array_id => $test_xml_file){
689                         $tests_xml = $import_path.$test_xml_file;
690                         
691                         //Mimic the array for now.
692                         $test_attributes['resource']['href'] = $test_xml_file;
693                         $test_attributes['resource']['type'] = 'imsqti_xmlv1p1';
694                         $test_attributes['resource']['file'] = $items[$item_id]['file'];
695 //                      $test_attributes['resource']['file'] = array($test_xml_file);
696
697
698                         //Get the XML file out and start importing them into our database.
699                         //TODO: See question_import.php 287-289.
700                         $qids = $qti_import->importQuestions($test_attributes);
701
702                         //import test
703                         $tid = $qti_import->importTest();
704
705                         //associate question and tests
706                         foreach ($qids as $order=>$qid){
707                                 if (isset($qti_import->weights[$order])){
708                                         $weight = round($qti_import->weights[$order]);
709                                 } else {
710                                         $weight = 0;
711                                 }
712                                 $new_order = $order + 1;
713                                 $sql = "INSERT INTO " . TABLE_PREFIX . "tests_questions_assoc" . 
714                                                 "(test_id, question_id, weight, ordering, required) " .
715                                                 "VALUES ($tid, $qid, $weight, $new_order, 0)";
716                                 $result = mysql_query($sql, $db);
717                         }
718
719                         //associate content and test
720                         $sql =  'INSERT INTO ' . TABLE_PREFIX . 'content_tests_assoc' . 
721                                         '(content_id, test_id) ' .
722                                         'VALUES (' . $items[$item_id]['real_content_id'] . ", $tid)";
723                         $result = mysql_query($sql, $db);
724                 
725                         if (!$msg->containsErrors()) {
726                                 $msg->addFeedback('IMPORT_SUCCEEDED');
727                         }
728                 }
729         }
730
731         /* get the a4a related xml */
732         if (isset($items[$item_id]['a4a_import_enabled']) && isset($items[$item_id]['a4a']) && !empty($items[$item_id]['a4a'])) {
733                 $a4a_import = new A4aImport($items[$item_id]['real_content_id']);
734                 $a4a_import->setRelativePath($items[$item_id]['new_path']);
735                 $a4a_import->importA4a($items[$item_id]['a4a']);
736         }
737 }
738
739 if ($package_base_path == '.') {
740         $package_base_path = '';
741 }
742
743 // loop through the files outside the package folder, and copy them to its relative path
744 if (is_dir(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/resources')) {
745         $handler = opendir(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/resources');
746         while ($file = readdir($handler)){
747                 $filename = AT_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/resources/'.$file;
748                 if(is_file($filename)){
749                         @rename($filename, AT_CONTENT_DIR .$_SESSION['course_id'].'/'.$package_base_name.'/'.$file);
750                 }
751         }
752         closedir($handler);
753 }
754 if (rename(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id'].'/'.$package_base_path, AT_CONTENT_DIR .$_SESSION['course_id'].'/'.$package_base_name) === false) {
755         if (!$msg->containsErrors()) {
756                 $msg->addError('IMPORT_FAILED');
757         }
758 }
759 clr_dir(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id']);
760
761 if (isset($_POST['url'])) {
762         @unlink($full_filename);
763 }
764
765
766 if ($_POST['s_cid']){
767         if (!$msg->containsErrors()) {
768                 $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
769         }
770         header('Location: ../../editor/edit_content.php?cid='.intval($_POST['cid']));
771         exit;
772 } else {
773         if (!$msg->containsErrors()) {
774                 $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
775         }
776         if ($_GET['tile']) {
777                 header('Location: '.AT_BASE_HREF.'tools/tile/index.php');
778         } else {
779                 header('Location: ./index.php?cid='.intval($_POST['cid']));
780         }
781         exit;
782 }
783
784 ?>