PageRenderTime 26ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/scorm-1.2/import.php

https://github.com/atutor/scorm_packages
PHP | 490 lines | 393 code | 75 blank | 22 comment | 74 complexity | 145911a6f6ec0b44c995b4e4230b2395 MD5 | raw file
  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. define('AT_INCLUDE_PATH', '../../../include/');
  24. if (!isset ($_POST['type'])) {
  25. require(AT_INCLUDE_PATH.'vitals.inc.php');
  26. }
  27. @set_time_limit(0);
  28. $_SESSION['done'] = 1;
  29. require(AT_INCLUDE_PATH.'../mods/_core/file_manager/filemanager.inc.php');
  30. require(AT_INCLUDE_PATH.'classes/pclzip.lib.php');
  31. authenticate(AT_PRIV_PACKAGES);
  32. function chmodPackageDir ($path) {
  33. if (!is_dir($path)) return;
  34. else chmod ($path, 0755);
  35. $h = opendir($path);
  36. while ($f = readdir($h)) {
  37. if ($f == '.' || $f == '..') continue;
  38. $fpath = $path.'/'.$f;
  39. if (!is_dir($fpath)) {
  40. chmod ($fpath, 0644);
  41. } else {
  42. chmodPackageDir ($fpath);
  43. }
  44. }
  45. closedir ($h);
  46. }
  47. $package_base_path = '';
  48. $idx = ''; // the current item's index, 1, 1.1, 1.2, 2, 2.1 ...
  49. $idxs = array(); // array containing the idx for all items
  50. $orgid = 0; // index of current organization 1...
  51. $depth = 0; // depth in organization tree
  52. $itemid = array();
  53. $files = array();
  54. $orgitems = array();
  55. $idxs = array();
  56. $text;
  57. $res;
  58. $ress = array();
  59. $files = array();
  60. $finfo;
  61. $totalsize = 0;
  62. if (!isset($_POST['submit'])) {
  63. $msg->addFeedback('IMPORT_CANCELLED');
  64. header('Location: ../index.php');
  65. exit;
  66. }
  67. $cid = intval($_POST['cid']);
  68. if (isset($_POST['url']) && ($_POST['url'] != 'http://') ) {
  69. if ($content = @file_get_contents($_POST['url'])) {
  70. $filename = substr(time(), -6). '.zip';
  71. $full_filename = AT_CONTENT_DIR . $filename;
  72. if (!$fp = fopen($full_filename, 'w+b')) {
  73. echo "Cannot open file ($filename)";
  74. exit;
  75. }
  76. if (fwrite($fp, $content, strlen($content) ) === FALSE) {
  77. echo "Cannot write to file ($filename)";
  78. exit;
  79. }
  80. fclose($fp);
  81. }
  82. $_FILES['file']['name'] = $filename;
  83. $_FILES['file']['tmp_name'] = $full_filename;
  84. $_FILES['file']['size'] = strlen($content);
  85. unset($content);
  86. $url_parts = pathinfo($_POST['url']);
  87. $package_base_name_url = $url_parts['basename'];
  88. }
  89. $ext = pathinfo($_FILES['file']['name']);
  90. $ext = $ext['extension'];
  91. if ($_FILES['file']['error'] == 1) {
  92. require(AT_INCLUDE_PATH.'header.inc.php');
  93. $errors = array('FILE_MAX_SIZE', ini_get('upload_max_filesize'));
  94. $msg->printErrors($errors);
  95. require(AT_INCLUDE_PATH.'footer.inc.php');
  96. exit;
  97. }
  98. if (!$_FILES['file']['name']
  99. || (!is_uploaded_file($_FILES['file']['tmp_name']) && !$_POST['url'])
  100. || ($ext != 'zip')) {
  101. require(AT_INCLUDE_PATH.'header.inc.php');
  102. $msg->printErrors('FILE_NOT_SELECTED');
  103. require(AT_INCLUDE_PATH.'footer.inc.php');
  104. exit;
  105. }
  106. if ($_FILES['file']['size'] == 0) {
  107. require(AT_INCLUDE_PATH.'header.inc.php');
  108. $msg->printErrors('IMPORTFILE_EMPTY');
  109. require(AT_INCLUDE_PATH.'footer.inc.php');
  110. exit;
  111. }
  112. //$package_path = AT_INCLUDE_PATH . '../sco/';
  113. $package_path = AT_CONTENT_DIR.'/sco/';
  114. if (!is_dir($package_path)) {
  115. if (!@mkdir($package_path, 0755)) {
  116. require(AT_INCLUDE_PATH.'header.inc.php');
  117. $msg->printErrors('PACKAGE_DIR_FAILED'.AT_CONTENT_DIR);
  118. require(AT_INCLUDE_PATH.'footer.inc.php');
  119. exit;
  120. }
  121. chmod ($package_path, 0755);
  122. }
  123. $package_path .= $_SESSION['course_id'].'/';
  124. if (!is_dir($package_path)) {
  125. if (!@mkdir($package_path, 0755)) {
  126. require(AT_INCLUDE_PATH.'header.inc.php');
  127. $msg->printErrors('PACKAGE_DIR_FAILED');
  128. require(AT_INCLUDE_PATH.'footer.inc.php');
  129. exit;
  130. }
  131. chmod ($package_path, 0755);
  132. }
  133. $package_path .= 'tmp/';
  134. clr_dir($package_path);
  135. if (!is_dir($package_path)) {
  136. if (!@mkdir($package_path, 0755)) {
  137. require(AT_INCLUDE_PATH.'header.inc.php');
  138. $msg->printErrors('PACKAGE_DIR_FAILED');
  139. require(AT_INCLUDE_PATH.'footer.inc.php');
  140. exit;
  141. }
  142. chmod ($package_path, 0755);
  143. }
  144. $archive = new PclZip($_FILES['file']['tmp_name']);
  145. if ($archive->extract (PCLZIP_OPT_PATH, $package_path) == 0) {
  146. require(AT_INCLUDE_PATH.'header.inc.php');
  147. echo 'Error : '.$archive->errorInfo(true);
  148. require(AT_INCLUDE_PATH.'footer.inc.php');
  149. clr_dir($package_path);
  150. exit;
  151. }
  152. chmodPackageDir ($package_path);
  153. $sql = "SELECT max_quota
  154. FROM ".TABLE_PREFIX."courses
  155. WHERE course_id=$_SESSION[course_id]";
  156. $result = mysql_query($sql, $db);
  157. $q_row = mysql_fetch_assoc($result);
  158. if ($q_row['max_quota'] != AT_COURSESIZE_UNLIMITED) {
  159. if ($q_row['max_quota'] == AT_COURSESIZE_DEFAULT) {
  160. $q_row['max_quota'] = $MaxCourseSize;
  161. }
  162. $totalBytes = dirsize($import_path);
  163. $course_total = dirsize(AT_CONTENT_DIR . $_SESSION['course_id'].'/');
  164. $total_after = $q_row['max_quota'] - $course_total - $totalBytes + $MaxCourseFloat;
  165. if ($total_after < 0) {
  166. require(AT_INCLUDE_PATH.'header.inc.php');
  167. $errors = array('NO_CONTENT_SPACE', number_format(-1*($total_after/AT_KBYTE_SIZE), 2 ) );
  168. $msg->printErrors($errors);
  169. require(AT_INCLUDE_PATH.'footer.inc.php');
  170. clr_dir($import_path);
  171. exit;
  172. }
  173. }
  174. parseManifest ($package_path);
  175. doValidation();
  176. doImport();
  177. if (isset($_POST['url'])) {
  178. @unlink($full_filename);
  179. }
  180. $orgs = array();
  181. for ($i=1; $orgitems[$i]; $i++) {
  182. array_push ($orgs, $orgitems[$i]['title']);
  183. }
  184. $oc = sizeOf($orgs);
  185. if ($oc == 1) {
  186. $msg->addFeedback(array('PACKAGE_IMPORT_SUCCESS', $orgs[0]));
  187. } else {
  188. $l = '';
  189. for ($i=0; $i<$oc; $i++) {
  190. $l .= '<li>' . $orgs[$i] . '</li>';
  191. }
  192. $msg->addFeedback(array('PACKAGES_IMPORT_SUCCESS', $l));
  193. }
  194. header('Location: ./index.php');
  195. exit;
  196. function parseManifest ($import_path) {
  197. global $msg;
  198. $ims_manifest_xml = @file_get_contents($import_path.'imsmanifest.xml');
  199. if ($ims_manifest_xml === false) {
  200. require(AT_INCLUDE_PATH.'header.inc.php');
  201. $msg->addError('NO_IMSMANIFEST');
  202. $msg->printErrors();
  203. require(AT_INCLUDE_PATH.'footer.inc.php');
  204. clr_dir($import_path);
  205. exit;
  206. }
  207. $xml_parser = xml_parser_create();
  208. xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);
  209. xml_set_element_handler($xml_parser, 'startElement', 'endElement');
  210. xml_set_character_data_handler($xml_parser, 'characterData');
  211. if (!xml_parse($xml_parser, $ims_manifest_xml, true)) {
  212. die(sprintf("XML error: %s at line %d",
  213. xml_error_string(xml_get_error_code($xml_parser)),
  214. xml_get_current_line_number($xml_parser)));
  215. }
  216. xml_parser_free($xml_parser);
  217. }
  218. function scormType ($i) {
  219. global $idxs, $orgitems, $res;
  220. $r = $res[$orgitems[$idxs[$i]]['identifierref']]['adlcp:scormtype'];
  221. if ($r) return $r;
  222. $o = explode ('.', $idxs[$i]);
  223. if (sizeOf($o) > 1) return 'cluster';
  224. return 'organization';
  225. }
  226. function doValidation () {
  227. global $msg;
  228. global $orgitems;
  229. global $idxs;
  230. global $res;
  231. global $package_path;
  232. $ic = sizeOf ($idxs);
  233. $err = 0;
  234. $warn = 0;
  235. for ($i=0; $i<$ic; $i++) {
  236. $title = addslashes($orgitems[$idxs[$i]]['title']);
  237. $href = $res[$orgitems[$idxs[$i]]['identifierref']]['href'];
  238. $styp = $res[$orgitems[$idxs[$i]]['identifierref']]['adlcp:scormtype'];
  239. $pre = $orgitems[$idxs[$i]]['adlcp:prerequisites'];
  240. $max = $orgitems[$idxs[$i]]['adlcp:maxtimeallowed'];
  241. $act = $orgitems[$idxs[$i]]['adlcp:timelimitaction'];
  242. $lms = $orgitems[$idxs[$i]]['adlcp:datafromlms'];
  243. $mas = $orgitems[$idxs[$i]]['adlcp:masteryscore'];
  244. if ($idxs[$i].'.1' == $idxs[$i+1]) { // cluster
  245. if ($href != '' && ++$warn)
  246. $msg->addWarning ('SCORM_ITEM_CLUSTER_HAS_OBJECT');
  247. } else {
  248. if ($styp == '' && ++$err)
  249. $msg->addError ('SCORM_ITEM_SCORMTYPE_MISSING');
  250. if ($href == '' && ++$err)
  251. $msg->addError ('SCORM_ITEM_HREF_MISSING');
  252. }
  253. }
  254. if ($err) {
  255. header('Location: ./index.php');
  256. exit;
  257. }
  258. }
  259. function doImport () {
  260. global $db;
  261. global $msg;
  262. global $orgitems;
  263. global $idxs;
  264. global $res;
  265. global $package_path;
  266. $now = date('Y-m-d H:i:s');
  267. $file = $_FILES['file']['name'];
  268. $sql = "INSERT INTO ".TABLE_PREFIX."packages
  269. VALUES (
  270. NULL,
  271. '$file',
  272. '$now',
  273. $_SESSION[course_id],
  274. 'scorm-1.2'
  275. )";
  276. $result = mysql_query($sql, $db);
  277. if (!$result) {
  278. require(AT_INCLUDE_PATH.'header.inc.php');
  279. $msg->addError('DB_NOT_UPDATED');
  280. $msg->printAll();
  281. require(AT_INCLUDE_PATH.'footer.inc.php');
  282. exit;
  283. }
  284. $pkg = mysql_insert_id($db);
  285. rename ($package_path, dirname($package_path) . '/' . $pkg);
  286. $ic = sizeOf ($idxs);
  287. for ($i=0; $i<$ic; $i++) {
  288. $title = addslashes($orgitems[$idxs[$i]]['title']);
  289. $scormtype = scormType($i);
  290. switch ($scormtype) {
  291. case 'organization':
  292. $sql = "INSERT INTO ".TABLE_PREFIX."scorm_1_2_org (
  293. package_id, title
  294. ) VALUES ( $pkg, '$title')";
  295. $result = mysql_query($sql, $db);
  296. if (!$result) {
  297. require(AT_INCLUDE_PATH.'header.inc.php');
  298. $msg->addError('DB_NOT_UPDATED');
  299. $msg->printAll();
  300. require(AT_INCLUDE_PATH.'footer.inc.php');
  301. exit;
  302. }
  303. $orgid = mysql_insert_id($db);
  304. $sql = "INSERT INTO ".TABLE_PREFIX."scorm_1_2_item
  305. VALUES (
  306. 0,
  307. $orgid,
  308. '$idxs[$i]',
  309. '$title',
  310. '',
  311. '$scormtype',
  312. '', '', '', '', ''
  313. )";
  314. $result = mysql_query($sql, $db);
  315. break;
  316. case 'sco':
  317. if (!$orgitems[$idxs[$i]]['adlcp:timelimitaction'])
  318. $orgitems[$idxs[$i]]['adlcp:timelimitaction'] =
  319. 'continue, no message';
  320. case 'asset':
  321. case 'cluster':
  322. $href = $res[$orgitems[$idxs[$i]]['identifierref']]['href'];
  323. $pre = $orgitems[$idxs[$i]]['adlcp:prerequisites'];
  324. $max = $orgitems[$idxs[$i]]['adlcp:maxtimeallowed'];
  325. $act = $orgitems[$idxs[$i]]['adlcp:timelimitaction'];
  326. $lms = $orgitems[$idxs[$i]]['adlcp:datafromlms'];
  327. $mas = $orgitems[$idxs[$i]]['adlcp:masteryscore'];
  328. $sql = "INSERT INTO ".TABLE_PREFIX."scorm_1_2_item
  329. VALUES (
  330. 0,
  331. $orgid,
  332. '$idxs[$i]',
  333. '$title',
  334. '$href',
  335. '$scormtype',
  336. '$pre',
  337. '$max', '$act', '$lms', '$mas'
  338. )";
  339. $result = mysql_query($sql, $db);
  340. if (!$result) {
  341. require(AT_INCLUDE_PATH.'header.inc.php');
  342. $msg->addError('DB_NOT_UPDATED');
  343. $msg->printAll();
  344. require(AT_INCLUDE_PATH.'footer.inc.php');
  345. exit;
  346. }
  347. }
  348. }
  349. }
  350. function startElement($parser, $name, $h) {
  351. global $orgid, $itemid, $depth;
  352. global $orgitems, $idx, $idxs;
  353. global $res, $ress;
  354. global $files, $finfo, $totalsize;
  355. switch ($name) {
  356. case 'organization':
  357. $orgid++;
  358. case 'item':
  359. $itemid[$depth++]++;
  360. $idx = implode ('.', $itemid);
  361. array_push ($idxs, $idx);
  362. while (list($l, $r) = each($h)) {
  363. $orgitems[$idx][$l]=$r;
  364. }
  365. break;
  366. case 'title':
  367. break;
  368. case 'resource':
  369. array_push ($ress, $h['identifier']);
  370. while (list($l, $r) = each($h)) {
  371. $res[$h['identifier']][$l]=$r;
  372. }
  373. break;
  374. case 'dependency':
  375. break;
  376. case 'file':
  377. array_push ($files, $h['href']);
  378. $f=AT_CONTENT_DIR
  379. .'import/'.$_SESSION['course_id']
  380. .'/'.$h['href'];
  381. $finfo[$h['href']] = @stat($f);
  382. $totalsize += $finfo[$h['href']]['size'];
  383. break;
  384. }
  385. }
  386. function endElement($parser, $name) {
  387. global $orgid, $idx, $itemid, $depth, $text, $orgitems;
  388. switch ($name) {
  389. case 'organization':
  390. $depth=0;
  391. $itemid = array ($orgid);
  392. break;
  393. case 'item':
  394. while ($itemid[$depth]) {
  395. array_pop($itemid);
  396. }
  397. $depth--;
  398. break;
  399. case 'title':
  400. case 'adlcp:datafromlms':
  401. case 'adlcp:maxtimeallowed':
  402. case 'adlcp:timelimitaction':
  403. case 'adlcp:prerequisites':
  404. case 'adlcp:masteryscore':
  405. $orgitems[$idx][$name] = trim($text);
  406. break;
  407. case 'resource':
  408. }
  409. $text = '';
  410. }
  411. function characterData($parser, $data){
  412. global $text;
  413. $text .= $data;
  414. }
  415. ?>