changed git call from https to git readonly
[atutor.git] / mods / scorm_packages / scorm-1.2 / import.php
1 <?php
2 /*
3  * mods/scorm_packages/scorm-1.2/import.php
4  *
5  * This file is part of ATutor, see http://www.atutor.ca
6  * 
7  * Copyright (C) 2005  Matthai Kurian 
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; either version 2
12  * of the License, or (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  */
23
24 define('AT_INCLUDE_PATH', '../../../include/');
25 if (!isset ($_POST['type'])) {
26         require(AT_INCLUDE_PATH.'vitals.inc.php');
27
28
29 @set_time_limit(0);
30 $_SESSION['done'] = 1;
31
32 require(AT_INCLUDE_PATH.'../mods/_core/file_manager/filemanager.inc.php');
33 require(AT_INCLUDE_PATH.'classes/pclzip.lib.php');
34
35 authenticate(AT_PRIV_PACKAGES);
36
37
38 function chmodPackageDir ($path) {
39
40         if (!is_dir($path)) return;
41         else chmod ($path, 0755);
42
43         $h = opendir($path);
44         while ($f = readdir($h)) {
45                 if ($f == '.' || $f == '..') continue;
46                 $fpath = $path.'/'.$f;
47                 if (!is_dir($fpath)) {
48                         chmod ($fpath, 0644);
49                 } else {
50                         chmodPackageDir ($fpath);
51                 }
52         }
53         closedir ($h);
54 }
55
56 $package_base_path = '';
57
58 $idx      = '';         // the current item's index, 1, 1.1, 1.2, 2, 2.1 ...
59 $idxs     = array();    // array containing the idx for all items
60 $orgid    = 0;          // index of current organization 1...
61 $depth    = 0;          // depth in organization tree
62 $itemid   = array();    
63 $files    = array();
64 $orgitems = array();
65 $idxs     = array();
66 $text;
67 $res;
68 $ress     = array();
69 $files    = array();
70 $finfo;
71 $totalsize = 0;
72
73 if (!isset($_POST['submit'])) {
74         $msg->addFeedback('IMPORT_CANCELLED');
75         header('Location: ../index.php');
76         exit;
77 }
78
79 $cid = intval($_POST['cid']);
80
81
82 if (isset($_POST['url']) && ($_POST['url'] != 'http://') ) {
83         if ($content = @file_get_contents($_POST['url'])) {
84                 $filename = substr(time(), -6). '.zip';
85                 $full_filename = AT_CONTENT_DIR . $filename;
86
87                 if (!$fp = fopen($full_filename, 'w+b')) {
88                         echo "Cannot open file ($filename)";
89                         exit;
90                 }
91
92                 if (fwrite($fp, $content, strlen($content) ) === FALSE) {
93                         echo "Cannot write to file ($filename)";
94                         exit;
95                 }
96                 fclose($fp);
97         }       
98         $_FILES['file']['name']     = $filename;
99         $_FILES['file']['tmp_name'] = $full_filename;
100         $_FILES['file']['size']     = strlen($content);
101         unset($content);
102         $url_parts = pathinfo($_POST['url']);
103         $package_base_name_url = $url_parts['basename'];
104 }
105 $ext = pathinfo($_FILES['file']['name']);
106 $ext = $ext['extension'];
107
108 if ($_FILES['file']['error'] == 1) {
109         require(AT_INCLUDE_PATH.'header.inc.php');
110         $errors = array('FILE_MAX_SIZE', ini_get('upload_max_filesize'));
111         $msg->printErrors($errors);
112         require(AT_INCLUDE_PATH.'footer.inc.php');
113         exit;
114 }
115
116 if (!$_FILES['file']['name'] 
117         || (!is_uploaded_file($_FILES['file']['tmp_name']) && !$_POST['url']) 
118         || ($ext != 'zip')) {
119                 require(AT_INCLUDE_PATH.'header.inc.php');
120                 $msg->printErrors('FILE_NOT_SELECTED');
121                 require(AT_INCLUDE_PATH.'footer.inc.php');
122                 exit;
123         }
124
125         if ($_FILES['file']['size'] == 0) {
126                 require(AT_INCLUDE_PATH.'header.inc.php');
127                 $msg->printErrors('IMPORTFILE_EMPTY');
128                 require(AT_INCLUDE_PATH.'footer.inc.php');
129                 exit;
130         }
131                         
132         $package_path = AT_INCLUDE_PATH . '../sco/';
133
134         if (!is_dir($package_path)) {
135                 if (!@mkdir($package_path, 0755)) {
136                         require(AT_INCLUDE_PATH.'header.inc.php');
137                         $msg->printErrors('PACKAGE_DIR_FAILED');
138                         require(AT_INCLUDE_PATH.'footer.inc.php');
139                         exit;
140                 }
141                 chmod ($package_path, 0755);
142         }
143
144         $package_path .= $_SESSION['course_id'].'/';
145         if (!is_dir($package_path)) {
146                 if (!@mkdir($package_path, 0755)) {
147                         require(AT_INCLUDE_PATH.'header.inc.php');
148                         $msg->printErrors('PACKAGE_DIR_FAILED');
149                         require(AT_INCLUDE_PATH.'footer.inc.php');
150                         exit;
151                 }
152                 chmod ($package_path, 0755);
153         }
154
155         $package_path .= 'tmp/';
156         clr_dir($package_path);
157         if (!is_dir($package_path)) {
158                 if (!@mkdir($package_path, 0755)) {
159                         require(AT_INCLUDE_PATH.'header.inc.php');
160                         $msg->printErrors('PACKAGE_DIR_FAILED');
161                         require(AT_INCLUDE_PATH.'footer.inc.php');
162                         exit;
163                 }
164                 chmod ($package_path, 0755);
165         }
166
167         $archive = new PclZip($_FILES['file']['tmp_name']);
168         if ($archive->extract (PCLZIP_OPT_PATH, $package_path) == 0) {
169
170                 require(AT_INCLUDE_PATH.'header.inc.php');
171                 echo 'Error : '.$archive->errorInfo(true);
172                 require(AT_INCLUDE_PATH.'footer.inc.php');
173                 clr_dir($package_path);
174                 exit;
175         }
176
177         chmodPackageDir ($package_path);
178
179         $sql    = "SELECT max_quota
180                    FROM ".TABLE_PREFIX."courses
181                    WHERE  course_id=$_SESSION[course_id]";
182
183         $result = mysql_query($sql, $db);
184         $q_row  = mysql_fetch_assoc($result);
185
186         if ($q_row['max_quota'] != AT_COURSESIZE_UNLIMITED) {
187
188                 if ($q_row['max_quota'] == AT_COURSESIZE_DEFAULT) {
189                         $q_row['max_quota'] = $MaxCourseSize;
190                 }
191                 $totalBytes   = dirsize($import_path);
192                 $course_total = dirsize(AT_CONTENT_DIR . $_SESSION['course_id'].'/');
193                 $total_after  = $q_row['max_quota'] - $course_total - $totalBytes + $MaxCourseFloat;
194
195                 if ($total_after < 0) {
196                         require(AT_INCLUDE_PATH.'header.inc.php');
197                         $errors = array('NO_CONTENT_SPACE', number_format(-1*($total_after/AT_KBYTE_SIZE), 2 ) );
198                         $msg->printErrors($errors);
199                         
200                         require(AT_INCLUDE_PATH.'footer.inc.php');
201                         clr_dir($import_path);
202                         exit;
203                 }
204         }
205
206
207 parseManifest ($package_path);
208 doValidation();
209 doImport();
210
211
212 if (isset($_POST['url'])) {
213       @unlink($full_filename);
214 }
215 $orgs = array();
216 for ($i=1; $orgitems[$i]; $i++) {
217         array_push ($orgs, $orgitems[$i]['title']);
218 }
219 $oc = sizeOf($orgs);
220 if ($oc == 1)  {
221         $msg->addFeedback(array('PACKAGE_IMPORT_SUCCESS', $orgs[0]));
222 } else {
223         $l = '';
224         for ($i=0; $i<$oc; $i++) {
225                 $l .= '<li>' . $orgs[$i] . '</li>';
226         }
227         $msg->addFeedback(array('PACKAGES_IMPORT_SUCCESS', $l));
228 }
229
230 header('Location: ./index.php');
231 exit;
232
233
234 function parseManifest ($import_path) {
235         global $msg;
236
237         $ims_manifest_xml = @file_get_contents($import_path.'imsmanifest.xml');
238
239         if ($ims_manifest_xml === false) {
240                 require(AT_INCLUDE_PATH.'header.inc.php');
241                 $msg->addError('NO_IMSMANIFEST');
242                 $msg->printErrors();
243                 require(AT_INCLUDE_PATH.'footer.inc.php');
244                 clr_dir($import_path);
245                 exit;
246         }
247
248         $xml_parser = xml_parser_create();
249
250         xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);
251         xml_set_element_handler($xml_parser, 'startElement', 'endElement');
252         xml_set_character_data_handler($xml_parser, 'characterData');
253         
254         if (!xml_parse($xml_parser, $ims_manifest_xml, true)) {
255                 die(sprintf("XML error: %s at line %d",
256                 xml_error_string(xml_get_error_code($xml_parser)),
257                 xml_get_current_line_number($xml_parser)));
258         }
259         
260         xml_parser_free($xml_parser);
261 }
262
263 function scormType ($i) {
264         global $idxs, $orgitems, $res;
265         $r = $res[$orgitems[$idxs[$i]]['identifierref']]['adlcp:scormtype'];
266         if ($r) return $r;
267         $o = explode ('.', $idxs[$i]);
268         if (sizeOf($o) > 1) return 'cluster';
269         return 'organization';  
270 }  
271
272 function doValidation () {
273         global $msg;
274         global $orgitems;
275         global $idxs;
276         global $res;
277         global $package_path;
278
279         $ic = sizeOf ($idxs);
280
281         $err  = 0;
282         $warn = 0;
283
284         for ($i=0; $i<$ic; $i++) {
285                 $title = addslashes($orgitems[$idxs[$i]]['title']);
286
287                 $href = $res[$orgitems[$idxs[$i]]['identifierref']]['href'];
288                 $styp = $res[$orgitems[$idxs[$i]]['identifierref']]['adlcp:scormtype'];
289                 $pre  = $orgitems[$idxs[$i]]['adlcp:prerequisites'];
290                 $max  = $orgitems[$idxs[$i]]['adlcp:maxtimeallowed'];
291                 $act  = $orgitems[$idxs[$i]]['adlcp:timelimitaction'];
292                 $lms  = $orgitems[$idxs[$i]]['adlcp:datafromlms'];
293                 $mas  = $orgitems[$idxs[$i]]['adlcp:masteryscore'];
294
295                 if ($idxs[$i].'.1' == $idxs[$i+1]) { // cluster
296                         if ($href != '' && ++$warn)
297                             $msg->addWarning ('SCORM_ITEM_CLUSTER_HAS_OBJECT');
298                 } else { 
299                         if ($styp == '' && ++$err)
300                             $msg->addError ('SCORM_ITEM_SCORMTYPE_MISSING');
301                         if ($href == '' && ++$err)
302                             $msg->addError ('SCORM_ITEM_HREF_MISSING');
303                 }
304
305         }
306         if ($err) {
307                 header('Location: ./index.php');
308                 exit;
309         }
310
311 }
312
313
314 function doImport () {
315         global $db;
316         global $msg;
317         global $orgitems;
318         global $idxs;
319         global $res;
320         global $package_path;
321
322         $now = date('Y-m-d H:i:s');
323         $file = $_FILES['file']['name'];
324         $sql = "INSERT INTO ".TABLE_PREFIX."packages
325                 VALUES (
326                         NULL,
327                         '$file',
328                         '$now',
329                         $_SESSION[course_id],
330                         'scorm-1.2'
331                 )";
332
333         $result = mysql_query($sql, $db);
334         if (!$result) {
335                 require(AT_INCLUDE_PATH.'header.inc.php');
336                 $msg->addError('DB_NOT_UPDATED');
337                 $msg->printAll();
338                 require(AT_INCLUDE_PATH.'footer.inc.php');
339                 exit;
340         } 
341
342         $pkg = mysql_insert_id($db);
343         rename ($package_path, dirname($package_path) . '/' . $pkg);
344
345         $ic = sizeOf ($idxs);
346
347         for ($i=0; $i<$ic; $i++) {
348                 $title = addslashes($orgitems[$idxs[$i]]['title']);
349                 $scormtype = scormType($i);
350
351                 switch ($scormtype) {
352                 case 'organization':
353                         $sql = "INSERT INTO ".TABLE_PREFIX."scorm_1_2_org (
354                                         package_id, title
355                                 ) VALUES ( $pkg, '$title')";
356
357                         $result = mysql_query($sql, $db);
358                         if (!$result) {
359                                 require(AT_INCLUDE_PATH.'header.inc.php');
360                                 $msg->addError('DB_NOT_UPDATED');
361                                 $msg->printAll();
362                                 require(AT_INCLUDE_PATH.'footer.inc.php');
363                                 exit;
364                         }
365                         $orgid = mysql_insert_id($db);
366                         $sql = "INSERT INTO ".TABLE_PREFIX."scorm_1_2_item
367                                 VALUES (
368                                         0,
369                                         $orgid,
370                                         '$idxs[$i]',
371                                         '$title',
372                                         '',
373                                         '$scormtype',
374                                         '', '', '', '', ''
375                                 )";
376                         $result = mysql_query($sql, $db);
377                         break;
378
379                 case 'sco':
380                         if (!$orgitems[$idxs[$i]]['adlcp:timelimitaction'])
381                                 $orgitems[$idxs[$i]]['adlcp:timelimitaction'] =
382                                         'continue, no message';
383                 case 'asset':
384                 case 'cluster':
385                         $href = $res[$orgitems[$idxs[$i]]['identifierref']]['href'];
386                         $pre  = $orgitems[$idxs[$i]]['adlcp:prerequisites'];
387                         $max  = $orgitems[$idxs[$i]]['adlcp:maxtimeallowed'];
388                         $act  = $orgitems[$idxs[$i]]['adlcp:timelimitaction'];
389                         $lms  = $orgitems[$idxs[$i]]['adlcp:datafromlms'];
390                         $mas  = $orgitems[$idxs[$i]]['adlcp:masteryscore'];
391                         $sql = "INSERT INTO ".TABLE_PREFIX."scorm_1_2_item
392                                 VALUES (
393                                         0,
394                                         $orgid,
395                                         '$idxs[$i]',
396                                         '$title',
397                                         '$href',
398                                         '$scormtype',
399                                         '$pre',
400                                         '$max', '$act', '$lms', '$mas'
401                                 )";
402                         $result = mysql_query($sql, $db);
403                         if (!$result) {
404                                 require(AT_INCLUDE_PATH.'header.inc.php');
405                                 $msg->addError('DB_NOT_UPDATED');
406                                 $msg->printAll();
407                                 require(AT_INCLUDE_PATH.'footer.inc.php');
408                                 exit;
409                         }
410                 }
411         }
412 }
413
414
415 function startElement($parser, $name, $h) {
416
417         global $orgid, $itemid,  $depth;
418         global $orgitems, $idx, $idxs;
419         global $res, $ress;
420         global $files, $finfo, $totalsize;
421
422         switch ($name) {
423                 case 'organization':
424                                 $orgid++;
425                 case 'item':
426                                 $itemid[$depth++]++;
427                                 $idx = implode ('.', $itemid);
428                                 array_push ($idxs, $idx);
429                                 while (list($l, $r) = each($h)) {
430                                         $orgitems[$idx][$l]=$r;
431                                 }
432                                 break;
433                 case 'title':
434                                 break;
435
436                 case 'resource':
437                                 array_push ($ress, $h['identifier']);
438                                 while (list($l, $r) = each($h)) {
439                                         $res[$h['identifier']][$l]=$r;
440                                 }
441                                 break;
442                 case 'dependency':
443                                 break;
444                 case 'file':
445                                 array_push ($files, $h['href']);
446                                 $f=AT_CONTENT_DIR
447                                         .'import/'.$_SESSION['course_id']
448                                         .'/'.$h['href'];
449                                 $finfo[$h['href']] = @stat($f);
450                                 $totalsize +=  $finfo[$h['href']]['size'];
451                                 break;
452         }
453 }
454
455 function endElement($parser, $name) {
456         global $orgid, $idx, $itemid, $depth, $text, $orgitems;
457
458         switch ($name) {
459                 case 'organization':
460                                 $depth=0;
461                                 $itemid = array ($orgid);
462                                 break;
463                 case 'item':    
464                                 while ($itemid[$depth]) {
465                                         array_pop($itemid);
466                                 }
467                                 $depth--;
468                                 break;
469                 case 'title':
470                 case 'adlcp:datafromlms':
471                 case 'adlcp:maxtimeallowed':
472                 case 'adlcp:timelimitaction':
473                 case 'adlcp:prerequisites':
474                 case 'adlcp:masteryscore':
475                                 $orgitems[$idx][$name] = trim($text);
476                                 break;
477                 case 'resource':
478
479         }
480         $text = '';
481 }
482
483 function characterData($parser, $data){
484         global $text;
485
486         $text .= $data;
487 }
488
489 ?>