PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/admin/upload.php

https://gitlab.com/tutaalexandr/bot_local
PHP | 460 lines | 371 code | 10 blank | 79 comment | 34 complexity | bbdc3248e027d1f9018b643e940fa908 MD5 | raw file
  1. <?php
  2. /***************************************
  3. * http://www.program-o.com
  4. * PROGRAM O
  5. * Version: 2.4.8
  6. * FILE: upload.php
  7. * AUTHOR: Elizabeth Perreau and Dave Morton
  8. * DATE: FEB 01 2016
  9. * DETAILS: Provides functionality to upload AIML files to a chatbot's database
  10. ***************************************/
  11. ini_set('memory_limit', '128M');
  12. ini_set('max_execution_time', '0');
  13. ini_set('display_errors', false);
  14. ini_set('log_errors', true);
  15. libxml_use_internal_errors(true);
  16. $bot_id = ($bot_id == 'new') ? 0 : $bot_id;
  17. $msg = (array_key_exists('aimlfile', $_FILES)) ? processUpload() : '';
  18. $upperScripts = <<<endScript
  19. <script type="text/javascript">
  20. <!--
  21. function showMe() {
  22. var sh = document.getElementById('showHelp');
  23. var tf = document.getElementById('uploadForm');
  24. sh.style.display = 'block';
  25. tf.style.display = 'none';
  26. }
  27. function hideMe() {
  28. var sh = document.getElementById('showHelp');
  29. var tf = document.getElementById('uploadForm');
  30. sh.style.display = 'none';
  31. tf.style.display = 'block';
  32. }
  33. function showHide() {
  34. var display = document.getElementById('showHelp').style.display;
  35. switch (display) {
  36. case '':
  37. case 'none':
  38. return showMe();
  39. break;
  40. case 'block':
  41. return hideMe();
  42. break;
  43. default:
  44. alert('display = ' + display);
  45. }
  46. }
  47. function checkSize(){
  48. var file_upload = document.getElementById('aimlfile');
  49. if (!file_upload.files) return false;
  50. var fileSize = file_upload.files[0].size;//.fileSize;
  51. var fileName = file_upload.files[0].name;//.fileSize;
  52. if (fileSize > 2000000){
  53. showError("The file " + fileName + " exceeds the file size limit of 2MB. Please choose a different file.")
  54. file_upload.value = null;
  55. }
  56. var fileType = file_upload.files[0].type;//.fileSize;
  57. //showError('The file type is ' + file_upload.files[0].type);
  58. if (fileType != 'text/aiml' && fileType != 'application/x-zip-compressed') {
  59. //showError("The file " + fileName + " is neither an AIML file, nor a zip archive. Please select another file.")
  60. //file_upload.value = null;
  61. }
  62. }
  63. function showError(msg){
  64. var errorDiv = document.getElementById("errMsg");
  65. var closeButton = '<div class="closeButton" id="closeButton" onclick="closeStatus(\'errMsg\')" title="Click to hide">&nbsp;</div>';
  66. errorDiv.innerHTML = closeButton + msg;
  67. errorDiv.style.display = 'block';
  68. }
  69. //-->
  70. </script>
  71. endScript;
  72. $post_vars = filter_input_array(INPUT_POST);
  73. $XmlEntities = array('&amp;' => '&', '&lt;' => '<', '&gt;' => '>', '&apos;' => '\'', '&quot;' => '"',);
  74. $g_tagName = null;
  75. $aiml_sql = "";
  76. $pattern_sql = "";
  77. $that_sql = "";
  78. $template_sql = "";
  79. $insert_sql = "";
  80. $file = "";
  81. $full_path = "";
  82. $cat_counter = 0;
  83. $AIML_List = getAIML_List();
  84. $all_bots = getBotList();
  85. $uploadContent = $template->getSection('UploadAIMLForm');
  86. $showHelp = $template->getSection('UploadShowHelp');
  87. $topNav = $template->getSection('TopNav');
  88. $leftNav = $template->getSection('LeftNav');
  89. $main = $template->getSection('Main');
  90. $navHeader = $template->getSection('NavHeader');
  91. $FooterInfo = getFooter();
  92. $errMsgClass = (!empty ($msg)) ? "ShowError" : "HideError";
  93. $errMsgStyle = $template->getSection($errMsgClass);
  94. $noLeftNav = '';
  95. $noTopNav = '';
  96. $noRightNav = $template->getSection('NoRightNav');
  97. $headerTitle = 'Actions:';
  98. $pageTitle = 'My-Program O - Upload AIML';
  99. $mainContent = $template->getSection('UploadMain');
  100. $mainTitle = "Upload AIML to use for the bot named $bot_name [helpLink]";
  101. #$msg = (empty($msg)) ? 'Test' : $msg;
  102. $mainContent = str_replace('[bot_name]', $bot_name, $mainContent);
  103. $mainContent = str_replace('[mainTitle]', $mainTitle, $mainContent);
  104. $mainContent = str_replace('[upload_content]', $uploadContent, $mainContent);
  105. $mainContent = str_replace('[showHelp]', $showHelp, $mainContent);
  106. $mainContent = str_replace('[AIML_List]', $AIML_List, $mainContent);
  107. $mainContent = str_replace('[all_bots]', $all_bots, $mainContent);
  108. $mainTitle = str_replace('[helpLink]', $template->getSection('HelpLink'), $mainTitle);
  109. $mainTitle = str_replace('[errMsg]', $msg, $mainTitle);
  110. /**
  111. * Function parseAIML
  112. *
  113. * * @param $fn
  114. * @param $aimlContent
  115. * @param bool $from_zip
  116. * @return string
  117. */
  118. function parseAIML($fn, $aimlContent, $from_zip = false)
  119. {
  120. global $dbConn, $post_vars;
  121. if (empty ($aimlContent))
  122. return "File $fn was empty!";
  123. global $dbConn, $debugmode, $bot_id, $charset;
  124. $fileName = basename($fn);
  125. $success = false;
  126. $topic = '';
  127. #Clear the database of the old entries
  128. $sql = "DELETE FROM `aiml` WHERE `filename` = :filename AND bot_id = :bot_id";
  129. if (isset ($post_vars['clearDB']))
  130. {
  131. $params = array(':filename' => $fileName, ':bot_id' => $bot_id);
  132. $affectedRows = db_write($sql, $params, false, __FILE__, __FUNCTION__, __LINE__);
  133. }
  134. $myBot_id = (isset ($post_vars['bot_id'])) ? $post_vars['bot_id'] : $bot_id;
  135. # Read new file into the XML parser
  136. $sql = 'insert into `aiml` (`id`, `bot_id`, `aiml`, `pattern`, `thatpattern`, `template`, `topic`, `filename`) values
  137. (NULL, :bot_id, :aiml, :pattern, :that, :template, :topic, :fileName);';
  138. # Validate the incoming document
  139. /*******************************************************/
  140. /* Set up for validation from a common DTD */
  141. /* This will involve removing the XML and */
  142. /* AIML tags from the beginning of the file */
  143. /* and replacing them with our own tags */
  144. /*******************************************************/
  145. $validAIMLHeader = '<?xml version="1.0" encoding="[charset]"?>
  146. <!DOCTYPE aiml PUBLIC "-//W3C//DTD Specification Version 1.0//EN" "http://www.program-o.com/xml/aiml.dtd">
  147. <aiml version="1.0.1" xmlns="http://alicebot.org/2001/AIML-1.0.1">';
  148. $validAIMLHeader = str_replace('[charset]', $charset, $validAIMLHeader);
  149. $aimlTagStart = stripos($aimlContent, '<aiml', 0);
  150. $aimlTagEnd = strpos($aimlContent, '>', $aimlTagStart) + 1;
  151. $aimlFile = $validAIMLHeader . substr($aimlContent, $aimlTagEnd);
  152. $tmpDir = _UPLOAD_PATH_ . 'tmp' . DIRECTORY_SEPARATOR;
  153. if (!file_exists($tmpDir)) mkdir($tmpDir, 0755);
  154. save_file(_UPLOAD_PATH_ . 'tmp/' . $fileName, $aimlFile);
  155. try
  156. {
  157. libxml_use_internal_errors(true);
  158. $xml = new DOMDocument();
  159. $xml->loadXML($aimlFile);
  160. $aiml = new SimpleXMLElement($xml->saveXML());
  161. $rowCount = 0;
  162. $_SESSION['failCount'] = 0;
  163. $params = array();
  164. if (!empty ($aiml->topic))
  165. {
  166. foreach ($aiml->topic as $topicXML)
  167. {
  168. # handle any topic tag(s) in the file
  169. $topicAttributes = $topicXML->attributes();
  170. $topic = $topicAttributes['name'];
  171. foreach ($topicXML->category as $category)
  172. {
  173. $fullCategory = $category->asXML();
  174. $pattern = trim($category->pattern);
  175. $pattern = str_replace("'", ' ', $pattern);
  176. $pattern = (IS_MB_ENABLED) ? mb_strtoupper($pattern) : strtoupper($pattern);
  177. $that = $category->that;
  178. $that = (IS_MB_ENABLED) ? mb_strtoupper($that) : strtoupper($that);
  179. $template = $category->template->asXML();
  180. $template = str_replace('<template>', '', $template);
  181. $template = str_replace('</template>', '', $template);
  182. $template = trim($template);
  183. # Strip CRLF and LF from category (Windows/mac/*nix)
  184. $aiml_add = str_replace(array("\r\n", "\n"), '', $fullCategory);
  185. $params[] = array(
  186. ':bot_id' => $bot_id,
  187. ':aiml' => $aiml_add,
  188. ':pattern' => $pattern,
  189. ':that' => $that,
  190. ':template' => $template,
  191. ':topic' => $topic,
  192. ':fileName' => $fileName
  193. );
  194. }
  195. }
  196. }
  197. if (!empty ($aiml->category))
  198. {
  199. foreach ($aiml->category as $category)
  200. {
  201. $fullCategory = $category->asXML();
  202. $pattern = trim($category->pattern);
  203. $pattern = str_replace("'", ' ', $pattern);
  204. $pattern = (IS_MB_ENABLED) ? mb_strtoupper($pattern) : strtoupper($pattern);
  205. $that = $category->that;
  206. $template = $category->template->asXML();
  207. //strip out the <template> tags, as they aren't needed
  208. $template = substr($template, 10);
  209. $tLen = strlen($template);
  210. $template = substr($template, 0, $tLen - 11);
  211. $template = trim($template);
  212. # Strip CRLF and LF from category (Windows/mac/*nix)
  213. $aiml_add = str_replace(array("\r\n", "\n"), '', $fullCategory);
  214. $params[] = array(
  215. ':bot_id' => $bot_id,
  216. ':aiml' => $aiml_add,
  217. ':pattern' => $pattern,
  218. ':that' => $that,
  219. ':template' => $template,
  220. ':topic' => '',
  221. ':fileName' => $fileName
  222. );
  223. }
  224. }
  225. if (!empty($params))
  226. {
  227. $rowCount = db_write($sql, $params, true, __FILE__, __FUNCTION__, __LINE__);
  228. $success = ($rowCount !== false) ? true : false;
  229. }
  230. $msg = ($from_zip === true) ? '' : "Successfully added $fileName to the database.<br />\n";
  231. }
  232. catch (Exception $e)
  233. {
  234. //$trace = print_r($e->getTrace(), true);
  235. //exit($e->getMessage() . ' at line ' . $e->getLine());
  236. $msg = $e->getMessage() . ' at line ' . $e->getLine() . "<br>\n";
  237. //trigger_error("Trace:\n$trace");
  238. //file_put_contents(_LOG_PATH_ . 'error.trace.log', $trace . "\nEnd Trace\n\n", FILE_APPEND);
  239. $success = false;
  240. $_SESSION['failCount']++;
  241. $errMsg = "There was a problem adding file $fileName to the database. Please refer to the message below to correct the problem and try again.<br>\n" . $e->getMessage();
  242. $msg .= upload_libxml_display_errors($errMsg);
  243. }
  244. return $msg;
  245. }
  246. /**
  247. * Function processUpload
  248. *
  249. *
  250. * @return string
  251. */
  252. function processUpload()
  253. {
  254. global $msg;
  255. // Validate the uploaded file
  256. if ($_FILES['aimlfile']['size'] === 0 or empty ($_FILES['aimlfile']['tmp_name']))
  257. {
  258. $msg = 'No file was selected.';
  259. }
  260. elseif ($_FILES['aimlfile']['size'] > 2000000)
  261. {
  262. $msg = 'The file was too large.';
  263. }
  264. else
  265. if ($_FILES['aimlfile']['error'] !== UPLOAD_ERR_OK)
  266. {
  267. // There was a PHP error
  268. $msg = 'There was an error uploading.';
  269. }
  270. else
  271. {
  272. // Create uploads directory if necessary
  273. if (!file_exists('uploads'))
  274. mkdir('uploads');
  275. // Move the file
  276. $file = './uploads/' . $_FILES['aimlfile']['name'];
  277. if (move_uploaded_file($_FILES['aimlfile']['tmp_name'], $file))
  278. {
  279. #file_put_contents(_LOG_PATH_ . 'upload.type.txt', 'Type = ' . $_FILES['aimlfile']['type']);
  280. if ($_FILES['aimlfile']['type'] == 'application/zip' or $_FILES['aimlfile']['type'] == 'application/x-zip-compressed')
  281. return processZip($file);
  282. else
  283. return parseAIML($file, file_get_contents($file));
  284. }
  285. else
  286. {
  287. $msg = 'There was an error moving the file.';
  288. }
  289. }
  290. $_SESSION['errorMessage'] = $msg;
  291. return $msg;
  292. }
  293. /**
  294. * Function getAIML_List
  295. *
  296. *
  297. * @return string
  298. */
  299. function getAIML_List()
  300. {
  301. global $dbConn, $dbn, $bot_id;
  302. $out = " <!-- Start List of Currently Stored AIML files -->\n";
  303. $sql = "SELECT DISTINCT filename FROM `aiml` where `bot_id` = $bot_id order by `filename`;";
  304. $result = db_fetchAll($sql, null, __FILE__, __FUNCTION__, __LINE__);
  305. foreach ($result as $row)
  306. {
  307. if (empty ($row['filename']))
  308. {
  309. $curOption = " No Filename entry<br />\n";
  310. }
  311. else
  312. $out .= $row['filename'] . "<br />\n";
  313. }
  314. $out .= " <!-- End List of Currently Stored AIML files -->\n";
  315. return $out;
  316. }
  317. /**
  318. * Function getBotList
  319. *
  320. *
  321. * @return string
  322. */
  323. function getBotList()
  324. {
  325. global $dbConn, $dbn, $bot_id;
  326. $botOptions = '';
  327. $sql = 'SELECT `bot_name`, `bot_id` FROM `bots` order by `bot_id`;';
  328. $result = db_fetchAll($sql, null, __FILE__, __FUNCTION__, __LINE__);
  329. foreach ($result as $row)
  330. {
  331. $bn = $row['bot_name'];
  332. $bi = $row['bot_id'];
  333. $sel = ($bot_id == $bi) ? ' selected="selected"' : '';
  334. $botOptions .= " <option$sel value=\"$bi\">$bn</option>\n";
  335. }
  336. return $botOptions;
  337. }
  338. /**
  339. * Function upload_libxml_display_errors
  340. *
  341. * * @param $msg
  342. * @return string
  343. */
  344. function upload_libxml_display_errors($msg)
  345. {
  346. $out = '';
  347. $errors = libxml_get_errors();
  348. foreach ($errors as $error)
  349. {
  350. $out .= upload_libxml_display_error($error) . "<br />\n";
  351. }
  352. libxml_clear_errors();
  353. return $msg . $out;
  354. }
  355. /**
  356. * Function upload_libxml_display_error
  357. *
  358. * * @param $error
  359. * @return string
  360. */
  361. function upload_libxml_display_error($error)
  362. {
  363. $out = "<br/>\n";
  364. switch ($error->level)
  365. {
  366. case LIBXML_ERR_WARNING :
  367. $out .= "<b>Warning {$error->code}</b>: ";
  368. break;
  369. case LIBXML_ERR_ERROR :
  370. $out .= "<b>Error {$error->code}</b>: ";
  371. break;
  372. case LIBXML_ERR_FATAL :
  373. $out .= "<b>Fatal Error {$error->code}</b>: ";
  374. break;
  375. }
  376. $out .= trim($error->message);
  377. if ($error->file)
  378. {
  379. $out .= " in <b>{$error->file}</b><br>\n";
  380. }
  381. $out .= " on line <b>{$error->line}</b><br>\n";
  382. return "$out<br>\n";
  383. }
  384. /**
  385. * Function processZip
  386. *
  387. * * @param $fileName
  388. * @return string
  389. */
  390. function processZip($fileName)
  391. {
  392. $out = '';
  393. $_SESSION['failCount'] = 0;
  394. $zipName = basename($fileName);
  395. $zip = new ZipArchive;
  396. $res = $zip->open($fileName);
  397. if ($res === TRUE)
  398. {
  399. $numFiles = $zip->numFiles;
  400. for ($loop = 0; $loop < $numFiles; $loop++)
  401. {
  402. $curName = $zip->getNameIndex($loop);
  403. if (strstr($curName, '/') !== false)
  404. {
  405. $endPos = strrpos($curName, '/') + 1;
  406. $curName = substr($curName, $endPos);
  407. }
  408. if (empty ($curName))
  409. continue;
  410. $fp = $zip->getStream($zip->getNameIndex($loop));
  411. if (!$fp)
  412. {
  413. $out .= "Processing for $curName failed.<br />\n";
  414. $bad_aiml_files = (!isset ($bad_aiml_files)) ? array() : $bad_aiml_files;
  415. $bad_aiml_files[] = $curName;
  416. $_SESSION['bad_aiml_files'] = $curName;
  417. }
  418. else
  419. {
  420. $curText = '';
  421. while (!feof($fp))
  422. {
  423. $curText .= fread($fp, 8192);
  424. }
  425. fclose($fp);
  426. if (!stristr($curName, '.aiml'))
  427. continue;
  428. $out .= parseAIML($curName, $curText, true);
  429. }
  430. }
  431. $zip->close();
  432. $failCount = $_SESSION['failCount'];
  433. $out .= "<br />\nUpload complete. $numFiles files were processed, and $failCount files encountered errors.<br />\n";
  434. if (isset ($_SESSION['bad_aiml_files']))
  435. {
  436. $out .= "<br />\nThe following AIML files encountered errors:<br />\n";
  437. foreach ($_SESSION['bad_aiml_files'] as $fn)
  438. {
  439. $out .= "$fn, ";
  440. }
  441. $out = rtrim($out, ', ') . "<br .>\nPlease test each of these files independently, to locate the errors within.";
  442. unset ($_SESSION['bad_aiml_files']);
  443. }
  444. }
  445. else
  446. {
  447. $out = "Upload failed. $fileName was either corrupted, or not a zip file.";
  448. }
  449. return $out;
  450. }