hotpotatoes.lib.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Code library for HotPotatoes integration.
  5. * @package chamilo.exercise
  6. * @author Istvan Mandak (original author)
  7. */
  8. $dbTable = Database::get_course_table(TABLE_DOCUMENT); // TODO: This is a global variable with too simple name, conflicts are possible. Better eliminate it. Correct the test unit too.
  9. /**
  10. * Creates a hotpotato directory.
  11. *
  12. * If a directory of that name already exists, don't create any. If a file of that name exists, remove it and create a directory.
  13. * @param string Wanted path
  14. * @return boolean Always true so far
  15. */
  16. function hotpotatoes_init($base_work_dir) {
  17. $document_path = $base_work_dir.'/';
  18. if (!is_dir($document_path)) {
  19. if (is_file($document_path)) {
  20. @unlink($document_path);
  21. }
  22. @mkdir($document_path, api_get_permissions_for_new_directories());
  23. return true;
  24. } else {
  25. return false;
  26. }
  27. //why create a .htaccess here?
  28. //if (!is_file($document_path.".htacces"))
  29. //{
  30. // if (!($fp = fopen($document_path.".htaccess", "w"))) {
  31. // }
  32. // $str = "order deny,allow\nallow from all";
  33. // if (!fwrite($fp,$str)) { }
  34. //}
  35. }
  36. /**
  37. * Gets the title of the quizz file given as parameter.
  38. * @param string File name
  39. * @param string File path
  40. * @return string The exercise title
  41. */
  42. function GetQuizName($fname, $fpath) {
  43. $title = GetComment($fname);
  44. if (trim($title) == '') {
  45. if (file_exists($fpath.$fname)) {
  46. if (!($fp = @fopen($fpath.$fname, 'r'))) {
  47. //die('Could not open Quiz input.');
  48. return basename($fname);
  49. }
  50. $contents = @fread($fp, filesize($fpath.$fname));
  51. @fclose($fp);
  52. $title = Text::api_get_title_html($contents);
  53. }
  54. }
  55. if ($title == '') {
  56. $title = basename($fname);
  57. }
  58. return (string)$title;
  59. }
  60. /**
  61. * Gets the comment about a file from the corresponding database record.
  62. * @param string File path
  63. * @return string Comment from the database record
  64. * Added conditional to the table if is empty.
  65. */
  66. function GetComment($path, $course_code = '') {
  67. global $dbTable;
  68. $course_info = api_get_course_info($course_code);
  69. $path = Database::escape_string($path);
  70. if (!empty($course_info) && !empty($path)) {
  71. $query = "SELECT comment FROM $dbTable WHERE c_id = {$course_info['real_id']} AND path='$path'";
  72. $result = Database::query($query);
  73. while ($row = Database::fetch_array($result)) {
  74. return $row[0];
  75. }
  76. }
  77. return null;
  78. }
  79. /**
  80. * Sets the comment in the database for a particular path.
  81. * @param string File path
  82. * @param string Comment to set
  83. * @return string Result of the database operation (Database::query will output some message directly on error anyway)
  84. */
  85. function SetComment($path, $comment) {
  86. global $dbTable;
  87. $path = Database::escape_string($path);
  88. $comment = Database::escape_string($comment);
  89. $course_id = api_get_course_int_id();
  90. $query = "UPDATE $dbTable SET comment='$comment' WHERE $course_id AND path='$path'";
  91. $result = Database::query($query);
  92. return $result;
  93. }
  94. /**
  95. * Reads the file contents into a string.
  96. * @param string Urlencoded path
  97. * @return string The file contents or false on security error
  98. */
  99. function ReadFileCont($full_file_path) {
  100. if (empty($full_file_path)) {
  101. return false;
  102. }
  103. if (Security::check_abs_path(dirname($full_file_path).'/', api_get_path(SYS_COURSE_PATH))) {
  104. if (is_file($full_file_path)) {
  105. if (!($fp = fopen(urldecode($full_file_path), 'r'))) {
  106. return '';
  107. }
  108. $contents = fread($fp, filesize($full_file_path));
  109. fclose($fp);
  110. return $contents;
  111. }
  112. }
  113. return false;
  114. }
  115. /**
  116. * Writes the file contents into the given filepath.
  117. * @param string Urlencoded path
  118. * @param string The file contents
  119. * @return boolean True on success, false on security error
  120. */
  121. function WriteFileCont($full_file_path, $content) {
  122. // Check if this is not an attack, trying to get into other directories or something like that.
  123. $_course = api_get_course_info();
  124. if (Security::check_abs_path(dirname($full_file_path).'/', api_get_path(SYS_COURSE_PATH).$_course['path'].'/')) {
  125. // Check if this is not an attack, trying to upload a php file or something like that.
  126. if (basename($full_file_path) != Security::filter_filename(basename($full_file_path))) { return false; }
  127. if (!($fp = fopen(urldecode($full_file_path), 'w'))) {
  128. //die('Could not open Quiz input.');
  129. }
  130. fwrite($fp, $content);
  131. fclose($fp);
  132. return true;
  133. }
  134. return false;
  135. }
  136. /**
  137. * Gets the name of an img whose path is given (without directories or extensions).
  138. * @param string An image tag (<img src="...." ...>)
  139. * @return string The image file name or an empty string
  140. */
  141. function GetImgName($imgtag) {
  142. // Select src tag from img tag.
  143. $match = array();
  144. //preg_match('/(src=(["\'])1.*(["\'])1)/i', $imgtag, $match); //src
  145. preg_match('/src(\s)*=(\s)*[\'"]([^\'"]*)[\'"]/i', $imgtag, $match); //get the img src as contained between " or '
  146. //list($key, $srctag) = each($match);
  147. $src = $match[3];
  148. //$src = substr($srctag, 5, (strlen($srctag) - 7));
  149. if (stristr($src, 'http') === false) {
  150. // Valid or invalid image name.
  151. if ($src == '') {
  152. return '';
  153. } else {
  154. $tmp_src = basename($src) ;
  155. if ($tmp_src == '') {
  156. return $src;
  157. } else {
  158. return $tmp_src;
  159. }
  160. }
  161. } else {
  162. // The img tag contained "http", which means it is probably external. Ignore it.
  163. return '';
  164. }
  165. }
  166. /**
  167. * Gets the source path of an image tag.
  168. * @param string An image tag
  169. * @return string The image source or ""
  170. */
  171. function GetSrcName($imgtag) {
  172. // Select src tag from img tag.
  173. $match = array();
  174. preg_match("|(src=\".*\" )|U", $imgtag, $match); //src
  175. list($key, $srctag) = each($match);
  176. $src = substr($srctag, 5, (strlen($srctag) - 7));
  177. if (stristr($src, 'http') === false) {
  178. // valid or invalid image name
  179. return $src;
  180. } else {
  181. return '';
  182. }
  183. }
  184. /**
  185. * Gets the image parameters from an image path.
  186. * @param string File name
  187. * @param string File path
  188. * @param reference Reference to a list of image parameters (emptied, then used to return results)
  189. * @param reference Reference to a counter of images (emptied, then used to return results)
  190. */
  191. function GetImgParams($fname, $fpath, &$imgparams, &$imgcount) {
  192. // Select img tags from context.
  193. $imgparams = array();
  194. //phpinfo();
  195. $contents = ReadFileCont("$fpath"."$fname");
  196. $matches = array();
  197. preg_match_all('(<img .*>)', $contents, $matches);
  198. $imgcount = 0;
  199. while (list($int, $match) = each($matches)) {
  200. // Each match consists of a key and a value.
  201. while (list($key, $imgtag) = each($match)) {
  202. $imgname = GetImgName($imgtag);
  203. if ($imgname != '' && !in_array($imgname, $imgparams)) {
  204. array_push($imgparams, $imgname); // name (+ type) of the images in the html test
  205. $imgcount = $imgcount + 1; // number of images in the html test
  206. }
  207. }
  208. }
  209. }
  210. /**
  211. * Generates a list of hidden fields with the image params given as parameter to this function.
  212. * @param array List of image parameters
  213. * @return string String containing the hidden parameters built from the list given
  214. */
  215. function GenerateHiddenList($imgparams) {
  216. $list = '';
  217. if (is_array($imgparams)) {
  218. while (list($int, $string) = each($imgparams)) {
  219. $list .= "<input type=\"hidden\" name=\"imgparams[]\" value=\"$string\" />\n";
  220. }
  221. }
  222. return $list;
  223. }
  224. /**
  225. * Searches for a node in the given array.
  226. * @param reference Reference to the array to search
  227. * @param string Node we are looking for in the array
  228. * @return mixed Node name or false if not found
  229. */
  230. function myarraysearch(&$array, $node) {
  231. $match = false;
  232. $tmp_array = array();
  233. for ($i = 0; $i < count($array); $i++) {
  234. if (!strcmp($array[$i], $node)) {
  235. $match = $node;
  236. } else {
  237. array_push($tmp_array, $array[$i]);
  238. }
  239. }
  240. $array = $tmp_array;
  241. return $match;
  242. }
  243. /**
  244. * Searches an image name into an array.
  245. * @param reference Reference to an array to search
  246. * @param string String to look for
  247. * @return mixed String given if found, false otherwise
  248. * @uses myarraysearch This function is just an additional layer on the myarraysearch() function
  249. */
  250. function CheckImageName(&$imgparams, $string) {
  251. $checked = myarraysearch($imgparams, $string);
  252. return $checked;
  253. }
  254. /**
  255. * Replaces an image tag by ???
  256. * @param string The content to replace
  257. * @return string The modified content
  258. */
  259. function ReplaceImgTag($content) {
  260. $newcontent = $content;
  261. $matches = array();
  262. preg_match_all('(<img .*>)', $content, $matches);
  263. $imgcount = 0;
  264. while (list($int, $match) = each($matches)) {
  265. while (list($key, $imgtag) = each($match)) {
  266. $imgname = GetSrcName($imgtag);
  267. if ($imgname == '') {} // Valid or invalid image name.
  268. else {
  269. $prehref = $imgname;
  270. $posthref = basename($imgname);
  271. $newcontent = str_replace($prehref, $posthref, $newcontent);
  272. }
  273. }
  274. }
  275. return $newcontent;
  276. }
  277. /**
  278. * Fills the folder name up to a certain length with "0".
  279. * @param string Original folder name
  280. * @param integer Length to reach
  281. * @return string Modified folder name
  282. */
  283. function FillFolderName($name, $nsize) {
  284. $str = '';
  285. for ($i = 0; $i < $nsize - strlen($name); $i++) {
  286. $str .= '0';
  287. }
  288. $str .= $name;
  289. return $str;
  290. }
  291. /**
  292. * Generates the HotPotato folder tree.
  293. * @param string Folder path
  294. * @return string Folder name (modified)
  295. */
  296. function GenerateHpFolder($folder) {
  297. $filelist = array();
  298. if ($dir = @opendir($folder)) {
  299. while (($file = readdir($dir)) !== false) {
  300. if ($file != '.') {
  301. if ($file != '..') {
  302. $full_name = $folder.'/'.$file;
  303. if (is_dir($full_name)) {
  304. $filelist[] = $file;
  305. }
  306. }
  307. }
  308. }
  309. }
  310. $w = 0;
  311. do {
  312. $name = FillFolderName(mt_rand(1, 99999), 6);
  313. $checked = myarraysearch($filelist, $name);
  314. // As long as we find the name in the array, continue looping. As soon as we have a new element, quit.
  315. if ($checked) { $w = 1; }
  316. else { $w = 0; }
  317. } while ($w == 1);
  318. return $name;
  319. }
  320. /**
  321. * Gets the folder name (strips down path).
  322. * @param string Path
  323. * @return string Folder name stripped down
  324. */
  325. function GetFolderName($fname) {
  326. $name = explode('/', $fname);
  327. $name = $name[sizeof($name) - 2];
  328. return $name;
  329. }
  330. /**
  331. * Gets the folder path (withouth the name of the folder itself) ?
  332. * @param string Path
  333. * @return string Path stripped down
  334. */
  335. function GetFolderPath($fname) {
  336. $str = '';
  337. $name = explode('/', $fname);
  338. for ($i = 0; $i < sizeof($name) - 1; $i++) {
  339. $str = $str.$name[$i].'/';
  340. }
  341. return $str;
  342. }
  343. /**
  344. * Checks if there are subfolders.
  345. * @param string Path
  346. * @return integer 1 if a subfolder was found, 0 otherwise
  347. */
  348. function CheckSubFolder($path) {
  349. $folder = GetFolderPath($path);
  350. $dflag = 0;
  351. if ($dir = @opendir($folder)) {
  352. while (($file = readdir($dir)) !== false) {
  353. if ($file != '.') {
  354. if ($file != '..') {
  355. $full_name = $folder.'/'.$file;
  356. if (is_dir($full_name)) {
  357. $dflag = 1; // first directory
  358. }
  359. }
  360. }
  361. }
  362. }
  363. return $dflag;
  364. }
  365. /**
  366. * Hotpotato Garbage Collector
  367. * @param string Path
  368. * @param integer Flag
  369. * @param integer User id
  370. * @return void No return value, but echoes results
  371. */
  372. function HotPotGCt($folder, $flag, $user_id) {
  373. // Garbage Collector
  374. $filelist = array();
  375. if ($dir = @opendir($folder)) {
  376. while (($file = readdir($dir)) !== false) {
  377. if ($file != '.') {
  378. if ($file != '..') {
  379. $full_name = $folder.'/'.$file;
  380. if (is_dir($full_name)) {
  381. HotPotGCt($folder.'/'.$file, $flag, $user_id);
  382. } else {
  383. $filelist[] = $file;
  384. }
  385. }
  386. }
  387. }
  388. closedir($dir);
  389. }
  390. while (list($key, $val) = each($filelist)) {
  391. if (stristr($val, $user_id.'.t.html')) {
  392. if ($flag == 1) {
  393. FileManager::my_delete($folder.'/'.$val);
  394. } else {
  395. echo $folder.'/'.$val.'<br />';
  396. }
  397. }
  398. }
  399. }