fileUpload.lib.php 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943
  1. <?php
  2. /*
  3. ==============================================================================
  4. Dokeos - elearning and course management software
  5. Copyright (c) 2004 Dokeos S.A.
  6. Copyright (c) 2003 Ghent University (UGent)
  7. Copyright (c) 2001 Universite catholique de Louvain (UCL)
  8. Copyright (c) various contributors
  9. For a full list of contributors, see "credits.txt".
  10. The full license can be read in "license.txt".
  11. This program is free software; you can redistribute it and/or
  12. modify it under the terms of the GNU General Public License
  13. as published by the Free Software Foundation; either version 2
  14. of the License, or (at your option) any later version.
  15. See the GNU General Public License for more details.
  16. Contact: Dokeos, 181 rue Royale, B-1000 Brussels, Belgium, info@dokeos.com
  17. ==============================================================================
  18. */
  19. /**
  20. ==============================================================================
  21. FILE UPLOAD LIBRARY
  22. * This is the file upload library for Dokeos.
  23. * Include/require it in your code to use its functionality.
  24. *
  25. * @package dokeos.library
  26. * @todo test and reorganise
  27. ==============================================================================
  28. */
  29. /*
  30. ==============================================================================
  31. List of functions
  32. function php2phps ($fileName)
  33. function htaccess2txt($filename)
  34. function disable_dangerous_file($filename)
  35. function unique_name($path,$name)
  36. function get_document_title($name)
  37. function process_uploaded_file($uploaded_file)
  38. function handle_uploaded_document($_course,$uploaded_file,$base_work_dir,$upload_path,$user_id,$to_group_id,$to_user_id,$maxFilledSpace,$unzip=0,$what_if_file_exists='')
  39. function enough_size($fileSize, $dir, $maxDirSpace) //depreciated
  40. function enough_space($file_size, $max_dir_space)
  41. function dir_total_space($dirPath) //depreciated
  42. function documents_total_space()
  43. function add_ext_on_mime($fileName,$fileType)
  44. function treat_uploaded_file($uploadedFile, $baseWorkDir, $uploadPath, $maxFilledSpace, $uncompress= '') //depreciated
  45. function unzip_uploaded_file($uploaded_file, $upload_path, $base_work_dir, $max_filled_space)
  46. function clean_up_files_in_zip($p_event, &$p_header)
  47. function clean_up_path(&$path)
  48. function add_document($_course,$path,$filetype,$filesize,$title)
  49. function update_existing_document($_course,$document_id,$filesize)
  50. function item_property_update_on_folder($_course,$path,$user_id)
  51. function get_levels($filename)
  52. function set_default_settings($upload_path,$filename,$filetype="file")
  53. function search_img_from_html($htmlFile)
  54. function create_unexisting_directory($_course,$user_id,$base_work_dir,$desired_dir_name)
  55. function move_uploaded_file_collection_into_directory($_course, $uploaded_file_collection, $base_work_dir, $missing_files_dir,$user_id,$max_filled_space)
  56. function replace_img_path_in_html_file($originalImgPath, $newImgPath, $htmlFile)
  57. function create_link_file($filePath, $url)
  58. function api_replace_links_in_html($upload_path, $full_file_name)
  59. function api_replace_links_in_string($upload_path, $buffer)
  60. function check_for_missing_files($file)
  61. function build_missing_files_form($missing_files,$upload_path,$file_name)
  62. Still experimental:
  63. function api_replace_parameter($upload_path, $buffer, $param_name="src")
  64. ==============================================================================
  65. */
  66. //------------------------------------------------------------------------------
  67. /**
  68. * change the file name extension from .php to .phps
  69. * Useful to secure a site !!
  70. *
  71. * @author - Hugues Peeters <peeters@ipm.ucl.ac.be>
  72. * @param - fileName (string) name of a file
  73. * @return - the filenam phps'ized
  74. */
  75. function php2phps ($fileName)
  76. {
  77. $fileName = preg_replace('/\.(php.?|phtml.?)(\.){0,1}.*$/i', '.phps', $fileName);
  78. return $fileName;
  79. }
  80. //------------------------------------------------------------------------------
  81. /**
  82. * Renames .htaccess & .HTACCESS tot htaccess.txt
  83. *
  84. * @param string $filename
  85. * @return string
  86. */
  87. function htaccess2txt($filename)
  88. {
  89. $filename = str_replace('.htaccess', 'htaccess.txt', $filename);
  90. $filename = str_replace('.HTACCESS', 'htaccess.txt', $filename);
  91. return $filename;
  92. }
  93. //------------------------------------------------------------------------------
  94. /**
  95. * this function executes our safety precautions
  96. * more functions can be added
  97. *
  98. * @param string $filename
  99. * @return string
  100. * @see php2phps()
  101. * @see htaccess2txt()
  102. */
  103. function disable_dangerous_file($filename)
  104. {
  105. $filename = php2phps($filename);
  106. $filename = htaccess2txt($filename);
  107. return $filename;
  108. }
  109. //------------------------------------------------------------------------------
  110. /**
  111. * this function generates a unique name for a file on a given location
  112. * filenames are changed to name_#.ext
  113. *
  114. * @param string $path
  115. * @param string $name
  116. * @return new unique name
  117. */
  118. function unique_name($path,$name)
  119. {
  120. $ext = substr(strrchr($name, "."), 0);
  121. $name_no_ext = substr($name, 0, strlen($name) - strlen(strstr($name,$ext)));
  122. $n = 0;
  123. $unique = '';
  124. while(file_exists($path . $name_no_ext . $unique . $ext))
  125. {
  126. $unique = '_' . ++$n;
  127. }
  128. return $name_no_ext . $unique . $ext;
  129. }
  130. //------------------------------------------------------------------------------
  131. /**
  132. * Returns the name without extension, used for the title
  133. *
  134. * @param string $name
  135. * @return name without the extension
  136. */
  137. function get_document_title($name)
  138. {
  139. //if they upload .htaccess...
  140. $name = disable_dangerous_file($name);
  141. $ext = substr(strrchr($name, "."), 0);
  142. $name_no_ext = substr($name, 0, strlen($name) - strlen(strstr($name,$ext)));
  143. $filename = addslashes($name_no_ext);
  144. return $filename;
  145. }
  146. //------------------------------------------------------------------------------
  147. /**
  148. * This function checks if the upload succeeded
  149. *
  150. * @param array $uploaded_file ($_FILES)
  151. * @return true if upload succeeded
  152. */
  153. function process_uploaded_file($uploaded_file) {
  154. // Checking the error code sent with the file upload.
  155. switch ($uploaded_file['error']) {
  156. case 1:
  157. // The uploaded file exceeds the upload_max_filesize directive in php.ini.
  158. Display::display_error_message(get_lang('UplExceedMaxServerUpload'). ini_get('upload_max_filesize'));
  159. return false;
  160. case 2:
  161. // The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.
  162. // Not used at the moment, but could be handy if we want to limit the size of an upload (e.g. image upload in html editor).
  163. Display::display_error_message(get_lang('UplExceedMaxPostSize'). round($_POST['MAX_FILE_SIZE']/1024) ." KB");
  164. return false;
  165. case 3:
  166. // The uploaded file was only partially uploaded.
  167. Display::display_error_message(get_lang('$UplPartialUpload')." ".get_lang('PleaseTryAgain'));
  168. return false;
  169. case 4:
  170. // No file was uploaded.
  171. Display::display_error_message(get_lang('UplNoFileUploaded')." ". get_lang('UplSelectFileFirst'));
  172. return false;
  173. }
  174. // case 0: default: We assume there is no error, the file uploaded with success.
  175. return true;
  176. }
  177. //------------------------------------------------------------------------------
  178. /**
  179. * this function does the save-work for the documents.
  180. * it handles the uploaded file and adds the properties to the database
  181. * if unzip=1 and the file is a zipfile, it is extracted
  182. * if we decide to save ALL kinds of documents in one database,
  183. * we could extend this with a $type='document', 'scormdocument',...
  184. *
  185. * @param array $_course
  186. * @param array $uploaded_file ($_FILES)
  187. * @param string $base_work_dir
  188. * @param string $upload_path
  189. * @param int $user_id
  190. * @param int $to_group_id, 0 for everybody
  191. * @param int $to_user_id, NULL for everybody
  192. * @param int $maxFilledSpace
  193. * @param int $unzip 1/0
  194. * @param string $what_if_file_exists overwrite, rename or warn if exists (default)
  195. * @param boolean Optional output parameter. So far only use for unzip_uploaded_document function. If no output wanted on success, set to false.
  196. * @return path of the saved file
  197. */
  198. function handle_uploaded_document($_course,$uploaded_file,$base_work_dir,$upload_path,$user_id,$to_group_id=0,$to_user_id=NULL,$maxFilledSpace='',$unzip=0,$what_if_file_exists='',$output=true)
  199. {
  200. if(!$user_id) die("Not a valid user.");
  201. //strip slashes
  202. $uploaded_file['name']=stripslashes($uploaded_file['name']);
  203. //add extension to files without one (if possible)
  204. $uploaded_file['name']=add_ext_on_mime($uploaded_file['name'],$uploaded_file['type']);
  205. $current_session_id = api_get_session_id();
  206. //check if there is enough space to save the file
  207. if (!enough_space($uploaded_file['size'], $maxFilledSpace))
  208. {
  209. Display::display_error_message(get_lang('UplNotEnoughSpace'));
  210. return false;
  211. }
  212. //if the want to unzip, check if the file has a .zip (or ZIP,Zip,ZiP,...) extension
  213. if ($unzip == 1 && preg_match("/.zip$/", strtolower($uploaded_file['name'])) )
  214. {
  215. return unzip_uploaded_document($uploaded_file, $upload_path, $base_work_dir, $maxFilledSpace, $output, $to_group_id);
  216. //display_message("Unzipping file");
  217. }
  218. //we can only unzip ZIP files (no gz, tar,...)
  219. elseif ($unzip == 1 && !preg_match("/.zip$/", strtolower($uploaded_file['name'])) )
  220. {
  221. Display::display_error_message(get_lang('UplNotAZip')." ".get_lang('PleaseTryAgain'));
  222. return false;
  223. }
  224. else
  225. {
  226. //clean up the name, only ASCII characters should stay. (and strict)
  227. $clean_name = replace_dangerous_char($uploaded_file['name'], 'strict');
  228. //no "dangerous" files
  229. $clean_name = disable_dangerous_file($clean_name);
  230. if(!filter_extension($clean_name))
  231. {
  232. Display::display_error_message(get_lang('UplUnableToSaveFileFilteredExtension'));
  233. return false;
  234. }
  235. else
  236. {
  237. //extension is good
  238. //echo "<br/>clean name = ".$clean_name;
  239. //echo "<br/>upload_path = ".$upload_path;
  240. //if the upload path differs from / (= root) it will need a slash at the end
  241. if ($upload_path!='/') {
  242. $upload_path = $upload_path.'/';
  243. }
  244. //echo "<br/>upload_path = ".$upload_path;
  245. $file_path = $upload_path.$clean_name;
  246. //echo "<br/>file path = ".$file_path;
  247. //full path to where we want to store the file with trailing slash
  248. $where_to_save = $base_work_dir.$upload_path;
  249. //at least if the directory doesn't exist, tell so
  250. if(!is_dir($where_to_save)){
  251. Display::display_error_message(get_lang('DestDirectoryDoesntExist').' ('.$upload_path.')');
  252. return false;
  253. }
  254. //echo "<br/>where to save = ".$where_to_save;
  255. // full path of the destination
  256. $store_path = $where_to_save.$clean_name;
  257. //echo "<br/>store path = ".$store_path;
  258. //name of the document without the extension (for the title)
  259. $document_name = get_document_title($uploaded_file['name']);
  260. //size of the uploaded file (in bytes)
  261. $file_size = $uploaded_file['size'];
  262. $files_perm = api_get_permissions_for_new_files();
  263. //what to do if the target file exists
  264. switch ($what_if_file_exists)
  265. {
  266. //overwrite the file if it exists
  267. case 'overwrite':
  268. //check if the target file exists, so we can give another message
  269. if (file_exists($store_path))
  270. {
  271. $file_exists = true;
  272. }
  273. else
  274. {
  275. $file_exists = false;
  276. }
  277. if (@move_uploaded_file($uploaded_file['tmp_name'], $store_path))
  278. {
  279. chmod($store_path,$files_perm);
  280. if($file_exists)
  281. {
  282. //UPDATE DATABASE!
  283. $document_id = DocumentManager::get_document_id($_course,$file_path);
  284. if ($document_id)
  285. {
  286. //update filesize
  287. update_existing_document($_course,$document_id,$uploaded_file['size']);
  288. //update document item_property
  289. api_item_property_update($_course,TOOL_DOCUMENT,$document_id,'DocumentUpdated',$user_id,$to_group_id,$to_user_id,null,null,$current_session_id);
  290. }
  291. //if the file is in a folder, we need to update all parent folders
  292. item_property_update_on_folder($_course,$upload_path,$user_id);
  293. //display success message with extra info to user
  294. if($output){
  295. Display::display_confirmation_message(get_lang('UplUploadSucceeded')."<br/>".$file_path .' '. get_lang('UplFileOverwritten'),false);
  296. }
  297. return $file_path;
  298. }
  299. else
  300. {
  301. //put the document data in the database
  302. $document_id = add_document($_course,$file_path,'file',$file_size,$document_name);
  303. if ($document_id)
  304. {
  305. //put the document in item_property update
  306. api_item_property_update($_course,TOOL_DOCUMENT,$document_id,'DocumentAdded',$user_id,$to_group_id,$to_user_id,null,null,$current_session_id);
  307. }
  308. //if the file is in a folder, we need to update all parent folders
  309. item_property_update_on_folder($_course,$upload_path,$user_id);
  310. //display success message to user
  311. Display::display_confirmation_message(get_lang('UplUploadSucceeded')."<br/>".$file_path,false);
  312. return $file_path;
  313. }
  314. }
  315. else
  316. {
  317. Display::display_error_message(get_lang('UplUnableToSaveFile'));
  318. return false;
  319. }
  320. break;
  321. //rename the file if it exists
  322. case 'rename':
  323. $new_name = unique_name($where_to_save, $clean_name);
  324. $store_path = $where_to_save.$new_name;
  325. $new_file_path = $upload_path.$new_name;
  326. if (@move_uploaded_file($uploaded_file['tmp_name'], $store_path))
  327. {
  328. chmod($store_path,$files_perm);
  329. //put the document data in the database
  330. $document_id = add_document($_course,$new_file_path,'file',$file_size,$document_name);
  331. if ($document_id)
  332. {
  333. //update document item_property
  334. api_item_property_update($_course,TOOL_DOCUMENT,$document_id,'DocumentAdded',$user_id,$to_group_id,$to_user_id,null,null,$current_session_id);
  335. }
  336. //if the file is in a folder, we need to update all parent folders
  337. item_property_update_on_folder($_course,$upload_path,$user_id);
  338. //display success message to user
  339. if($output){
  340. Display::display_confirmation_message(get_lang('UplUploadSucceeded'). "<br>" .get_lang('UplFileSavedAs') . $new_file_path,false);
  341. }
  342. return $new_file_path;
  343. }
  344. else
  345. {
  346. Display::display_error_message(get_lang('UplUnableToSaveFile'));
  347. return false;
  348. }
  349. break;
  350. //only save the file if it doesn't exist or warn user if it does exist
  351. default:
  352. if (file_exists($store_path))
  353. {
  354. Display::display_error_message($clean_name.' '.get_lang('UplAlreadyExists'));
  355. }
  356. else
  357. {
  358. if (@move_uploaded_file($uploaded_file['tmp_name'], $store_path))
  359. {
  360. chmod($store_path,$files_perm);
  361. //put the document data in the database
  362. $document_id = add_document($_course,$file_path,'file',$file_size,$document_name);
  363. if ($document_id)
  364. {
  365. //update document item_property
  366. api_item_property_update($_course,TOOL_DOCUMENT,$document_id,'DocumentAdded',$user_id,$to_group_id,$to_user_id,null,null,$current_session_id);
  367. }
  368. //if the file is in a folder, we need to update all parent folders
  369. item_property_update_on_folder($_course,$upload_path,$user_id);
  370. //display success message to user
  371. if($output){
  372. Display::display_confirmation_message(get_lang('UplUploadSucceeded')."<br/>".$file_path,false);
  373. }
  374. return $file_path;
  375. }
  376. else
  377. {
  378. Display::display_error_message(get_lang('UplUnableToSaveFile'));
  379. return false;
  380. }
  381. }
  382. break;
  383. }
  384. }
  385. }
  386. }
  387. //------------------------------------------------------------------------------
  388. /**
  389. * Check if there is enough place to add a file on a directory
  390. * on the base of a maximum directory size allowed
  391. * @deprecated use enough_space instead!
  392. * @author - Hugues Peeters <peeters@ipm.ucl.ac.be>
  393. * @param - fileSize (int) - size of the file in byte
  394. * @param - dir (string) - Path of the directory
  395. * whe the file should be added
  396. * @param - maxDirSpace (int) - maximum size of the diretory in byte
  397. * @return - boolean true if there is enough space,
  398. * boolean false otherwise
  399. *
  400. * @see - enough_size() uses dir_total_space() function
  401. */
  402. function enough_size($fileSize, $dir, $maxDirSpace)
  403. {
  404. if ($maxDirSpace)
  405. {
  406. $alreadyFilledSpace = dir_total_space($dir);
  407. if ( ($fileSize + $alreadyFilledSpace) > $maxDirSpace)
  408. {
  409. return false;
  410. }
  411. }
  412. return true;
  413. }
  414. //------------------------------------------------------------------------------
  415. /**
  416. * Check if there is enough place to add a file on a directory
  417. * on the base of a maximum directory size allowed
  418. *
  419. * @author Bert Vanderkimpen
  420. * @param int file_size size of the file in byte
  421. * @param array $_course
  422. * @param int max_dir_space maximum size
  423. * @return boolean true if there is enough space, false otherwise
  424. *
  425. * @see enough_space() uses documents_total_space() function
  426. */
  427. function enough_space($file_size, $max_dir_space)
  428. {
  429. if ($max_dir_space)
  430. {
  431. $already_filled_space = documents_total_space();
  432. if ( ($file_size + $already_filled_space) > $max_dir_space)
  433. {
  434. return false;
  435. }
  436. }
  437. return true;
  438. }
  439. //------------------------------------------------------------------------------
  440. /**
  441. * Compute the size already occupied by a directory and is subdirectories
  442. *
  443. * @author - Hugues Peeters <peeters@ipm.ucl.ac.be>
  444. * @param - dirPath (string) - size of the file in byte
  445. * @return - int - return the directory size in bytes
  446. */
  447. function dir_total_space($dirPath)
  448. {
  449. $save_dir = getcwd();
  450. chdir ($dirPath) ;
  451. $handle = opendir($dirPath);
  452. while ($element = readdir($handle) )
  453. {
  454. if ( $element == "." || $element == "..")
  455. {
  456. continue; // skip the current and parent directories
  457. }
  458. if ( is_file($element) )
  459. {
  460. $sumSize += filesize($element);
  461. }
  462. if ( is_dir($element) )
  463. {
  464. $dirList[] = $dirPath."/".$element;
  465. }
  466. }
  467. closedir($handle) ;
  468. if ( sizeof($dirList) > 0)
  469. {
  470. foreach($dirList as $j)
  471. {
  472. $sizeDir = dir_total_space($j); // recursivity
  473. $sumSize += $sizeDir;
  474. }
  475. }
  476. chdir($save_dir);//return to initial position
  477. return $sumSize;
  478. }
  479. //------------------------------------------------------------------------------
  480. /**
  481. * Calculate the total size of all documents in a course
  482. *
  483. * @author Bert vanderkimpen
  484. * @param int $to_group_id (to calculate group document space)
  485. * @return int total size
  486. */
  487. function documents_total_space($to_group_id='0')
  488. {
  489. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  490. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  491. $sql = "SELECT SUM(size)
  492. FROM ".$TABLE_ITEMPROPERTY." AS props, ".$TABLE_DOCUMENT." AS docs
  493. WHERE docs.id = props.ref
  494. AND props.tool = '".TOOL_DOCUMENT."'
  495. AND props.to_group_id='".$to_group_id."'
  496. AND props.visibility <> 2";
  497. $result = Database::query($sql,__FILE__,__LINE__);
  498. if($result && Database::num_rows($result)!=0)
  499. {
  500. $row = Database::fetch_row($result);
  501. return $row[0];
  502. }
  503. else
  504. {
  505. return 0;
  506. }
  507. }
  508. //------------------------------------------------------------------------------
  509. /**
  510. * Try to add an extension to files without extension
  511. * Some applications on Macintosh computers don't add an extension to the files.
  512. * This subroutine try to fix this on the basis of the MIME type sent
  513. * by the browser.
  514. *
  515. * Note : some browsers don't send the MIME Type (e.g. Netscape 4).
  516. * We don't have solution for this kind of situation
  517. *
  518. * @author - Hugues Peeters <peeters@ipm.ucl.ac.be>
  519. * @author - Bert Vanderkimpen
  520. * @param - fileName (string) - Name of the file
  521. * @param - fileType (string) - Type of the file
  522. * @return - fileName (string)
  523. *
  524. */
  525. function add_ext_on_mime($fileName,$fileType)
  526. {
  527. /*
  528. * Check if the file has an extension AND if the browser has sent a MIME Type
  529. */
  530. //if(!ereg("([[:alnum:]]|[[[:punct:]])+\.[[:alnum:]]+$", $fileName) // TODO: This fails sometimes on non-ASCII encoded file names. To be removed.
  531. // && $fileType)
  532. if(!preg_match('/^.*\.[a-zA-Z_0-9]+$/', $fileName) && $fileType)
  533. {
  534. /*
  535. * Build a "MIME-types / extensions" connection table
  536. */
  537. static $mimeType = array();
  538. $mimeType[] = "application/msword"; $extension[] =".doc";
  539. $mimeType[] = "application/rtf"; $extension[] =".rtf";
  540. $mimeType[] = "application/vnd.ms-powerpoint"; $extension[] =".ppt";
  541. $mimeType[] = "application/vnd.ms-excel"; $extension[] =".xls";
  542. $mimeType[] = "application/pdf"; $extension[] =".pdf";
  543. $mimeType[] = "application/postscript"; $extension[] =".ps";
  544. $mimeType[] = "application/mac-binhex40"; $extension[] =".hqx";
  545. $mimeType[] = "application/x-gzip"; $extension[] ="tar.gz";
  546. $mimeType[] = "application/x-shockwave-flash"; $extension[] =".swf";
  547. $mimeType[] = "application/x-stuffit"; $extension[] =".sit";
  548. $mimeType[] = "application/x-tar"; $extension[] =".tar";
  549. $mimeType[] = "application/zip"; $extension[] =".zip";
  550. $mimeType[] = "application/x-tar"; $extension[] =".tar";
  551. $mimeType[] = "text/html"; $extension[] =".html";
  552. $mimeType[] = "text/plain"; $extension[] =".txt";
  553. $mimeType[] = "text/rtf"; $extension[] =".rtf";
  554. $mimeType[] = "img/gif"; $extension[] =".gif";
  555. $mimeType[] = "img/jpeg"; $extension[] =".jpg";
  556. $mimeType[] = "img/png"; $extension[] =".png";
  557. $mimeType[] = "audio/midi"; $extension[] =".mid";
  558. $mimeType[] = "audio/mpeg"; $extension[] =".mp3";
  559. $mimeType[] = "audio/x-aiff"; $extension[] =".aif";
  560. $mimeType[] = "audio/x-pn-realaudio"; $extension[] =".rm";
  561. $mimeType[] = "audio/x-pn-realaudio-plugin"; $extension[] =".rpm";
  562. $mimeType[] = "audio/x-wav"; $extension[] =".wav";
  563. $mimeType[] = "video/mpeg"; $extension[] =".mpg";
  564. $mimeType[] = "video/mpeg4-generic"; $extension[] =".mp4";
  565. $mimeType[] = "video/quicktime"; $extension[] =".mov";
  566. $mimeType[] = "video/x-msvideo"; $extension[] =".avi";
  567. $mimeType[] = "video/x-ms-wmv"; $extension[] =".wmv";
  568. $mimeType[] = "video/x-flv"; $extension[] =".flv";
  569. $mimeType[] = "application/vnd.ms-word.document.macroEnabled.12"; $extension[] =".docm";
  570. $mimeType[] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; $extension[] =".docx";
  571. $mimeType[] = "application/vnd.ms-word.template.macroEnabled.12"; $extension[] =".dotm";
  572. $mimeType[] = "application/vnd.openxmlformats-officedocument.wordprocessingml.template"; $extension[] =".dotx";
  573. $mimeType[] = "application/vnd.ms-powerpoint.template.macroEnabled.12"; $extension[] =".potm";
  574. $mimeType[] = "application/vnd.openxmlformats-officedocument.presentationml.template"; $extension[] =".potx";
  575. $mimeType[] = "application/vnd.ms-powerpoint.addin.macroEnabled.12"; $extension[] =".ppam";
  576. $mimeType[] = "application/vnd.ms-powerpoint.slideshow.macroEnabled.12"; $extension[] =".ppsm";
  577. $mimeType[] = "application/vnd.openxmlformats-officedocument.presentationml.slideshow"; $extension[] =".ppsx";
  578. $mimeType[] = "application/vnd.ms-powerpoint.presentation.macroEnabled.12"; $extension[] =".pptm";
  579. $mimeType[] = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; $extension[] =".pptx";
  580. $mimeType[] = "application/vnd.ms-excel.addin.macroEnabled.12"; $extension[] =".xlam";
  581. $mimeType[] = "application/vnd.ms-excel.sheet.binary.macroEnabled.12"; $extension[] =".xlsb";
  582. $mimeType[] = "application/vnd.ms-excel.sheet.macroEnabled.12"; $extension[] =".xlsm";
  583. $mimeType[] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; $extension[] =".xlsx";
  584. $mimeType[] = "application/vnd.ms-excel.template.macroEnabled.12"; $extension[] =".xltm";
  585. $mimeType[] = "application/vnd.openxmlformats-officedocument.spreadsheetml.template"; $extension[] =".xltx";
  586. //test on PC (files with no extension get application/octet-stream)
  587. //$mimeType[] = "application/octet-stream"; $extension[] =".ext";
  588. /*
  589. * Check if the MIME type sent by the browser is in the table
  590. */
  591. foreach($mimeType as $key=>$type)
  592. {
  593. if ($type == $fileType)
  594. {
  595. $fileName .= $extension[$key];
  596. break;
  597. }
  598. }
  599. unset($mimeType, $extension, $type, $key); // Delete to eschew possible collisions
  600. }
  601. return $fileName;
  602. }
  603. //------------------------------------------------------------------------------
  604. /**
  605. *
  606. * @author Hugues Peeters <hugues.peeters@claroline.net>
  607. *
  608. * @param array $uploadedFile - follows the $_FILES Structure
  609. * @param string $baseWorkDir - base working directory of the module
  610. * @param string $uploadPath - destination of the upload.
  611. * This path is to append to $baseWorkDir
  612. * @param int $maxFilledSpace - amount of bytes to not exceed in the base
  613. * working directory
  614. *
  615. * @return boolean true if it succeds, false otherwise
  616. */
  617. function treat_uploaded_file($uploadedFile, $baseWorkDir, $uploadPath, $maxFilledSpace, $uncompress= '')
  618. {
  619. $uploadedFile['name']=stripslashes($uploadedFile['name']);
  620. if (!enough_size($uploadedFile['size'], $baseWorkDir, $maxFilledSpace))
  621. {
  622. return api_failure::set_failure('not_enough_space');
  623. }
  624. if ($uncompress == 'unzip' && preg_match("/.zip$/", strtolower($uploadedFile['name'])) )
  625. {
  626. return unzip_uploaded_file($uploadedFile, $uploadPath, $baseWorkDir, $maxFilledSpace);
  627. }
  628. else
  629. {
  630. $fileName = trim($uploadedFile['name']);
  631. // CHECK FOR NO DESIRED CHARACTERS
  632. $fileName = replace_dangerous_char($fileName, 'strict');
  633. // TRY TO ADD AN EXTENSION TO FILES WITOUT EXTENSION
  634. $fileName = add_ext_on_mime($fileName,$uploadedFile['type']);
  635. // HANDLE PHP FILES
  636. $fileName = ($fileName);
  637. // COPY THE FILE TO THE DESIRED DESTINATION
  638. if(move_uploaded_file($uploadedFile['tmp_name'], $baseWorkDir.$uploadPath."/".$fileName))
  639. set_default_settings($uploadPath,$fileName);
  640. return true;
  641. }
  642. }
  643. /**
  644. * Manages all the unzipping process of an uploaded file
  645. *
  646. * @author Hugues Peeters <hugues.peeters@claroline.net>
  647. *
  648. * @param array $uploadedFile - follows the $_FILES Structure
  649. * @param string $uploadPath - destination of the upload.
  650. * This path is to append to $baseWorkDir
  651. * @param string $baseWorkDir - base working directory of the module
  652. * @param int $maxFilledSpace - amount of bytes to not exceed in the base
  653. * working directory
  654. *
  655. * @return boolean true if it succeeds false otherwise
  656. */
  657. function unzip_uploaded_file($uploadedFile, $uploadPath, $baseWorkDir, $maxFilledSpace)
  658. {
  659. $zipFile = new pclZip($uploadedFile['tmp_name']);
  660. // Check the zip content (real size and file extension)
  661. if(file_exists($uploadedFile)) {
  662. $zipContentArray = $zipFile->listContent();
  663. $okScorm=false;
  664. foreach($zipContentArray as $thisContent)
  665. {
  666. if ( preg_match('~.(php.*|phtml)$~i', $thisContent['filename']) )
  667. {
  668. return api_failure::set_failure('php_file_in_zip_file');
  669. }
  670. elseif(stristr($thisContent['filename'],'imsmanifest.xml'))
  671. {
  672. $okScorm=true;
  673. }
  674. elseif(stristr($thisContent['filename'],'LMS'))
  675. {
  676. $okPlantynScorm1=true;
  677. }
  678. elseif(stristr($thisContent['filename'],'REF'))
  679. {
  680. $okPlantynScorm2=true;
  681. }
  682. elseif(stristr($thisContent['filename'],'SCO'))
  683. {
  684. $okPlantynScorm3=true;
  685. }
  686. elseif(stristr($thisContent['filename'],'AICC'))
  687. {
  688. $okAiccScorm=true;
  689. }
  690. $realFileSize += $thisContent['size'];
  691. }
  692. if ((($okPlantynScorm1==true) and ($okPlantynScorm2==true) and ($okPlantynScorm3==true)) or ($okAiccScorm==true))
  693. {
  694. $okScorm=true;
  695. }
  696. if(!$okScorm && defined('CHECK_FOR_SCORM') && CHECK_FOR_SCORM)
  697. {
  698. return api_failure::set_failure('not_scorm_content');
  699. }
  700. if (! enough_size($realFileSize, $baseWorkDir, $maxFilledSpace) )
  701. {
  702. return api_failure::set_failure('not_enough_space');
  703. }
  704. // it happens on Linux that $uploadPath sometimes doesn't start with '/'
  705. if($uploadPath[0] != '/')
  706. {
  707. $uploadPath='/'.$uploadPath;
  708. }
  709. if($uploadPath[strlen($uploadPath)-1] == '/')
  710. {
  711. $uploadPath=substr($uploadPath,0,-1);
  712. }
  713. /*
  714. --------------------------------------
  715. Uncompressing phase
  716. --------------------------------------
  717. */
  718. /*
  719. The first version, using OS unzip, is not used anymore
  720. because it does not return enough information.
  721. We need to process each individual file in the zip archive to
  722. - add it to the database
  723. - parse & change relative html links
  724. */
  725. if (PHP_OS == 'Linux' && ! get_cfg_var('safe_mode') && false) // *** UGent, changed by OC ***
  726. {
  727. // Shell Method - if this is possible, it gains some speed
  728. exec("unzip -d \"".$baseWorkDir.$uploadPath."/\"".$uploadedFile['name']." "
  729. .$uploadedFile['tmp_name']);
  730. }
  731. else
  732. {
  733. // PHP method - slower...
  734. $save_dir = getcwd();
  735. chdir($baseWorkDir.$uploadPath);
  736. $unzippingState = $zipFile->extract();
  737. for($j=0;$j<count($unzippingState);$j++)
  738. {
  739. $state=$unzippingState[$j];
  740. //fix relative links in html files
  741. $extension = strrchr($state["stored_filename"], ".");
  742. }
  743. if($dir=@opendir($baseWorkDir.$uploadPath))
  744. {
  745. while($file=readdir($dir))
  746. {
  747. if($file != '.' && $file != '..')
  748. {
  749. $filetype="file";
  750. if(is_dir($baseWorkDir.$uploadPath.'/'.$file)) $filetype="folder";
  751. $safe_file=replace_dangerous_char($file,'strict');
  752. @rename($baseWorkDir.$uploadPath.'/'.$file,$baseWorkDir.$uploadPath.'/'.$safe_file);
  753. set_default_settings($uploadPath,$safe_file,$filetype);
  754. }
  755. }
  756. closedir($dir);
  757. }
  758. chdir($save_dir); //back to previous dir position
  759. }
  760. }
  761. return true;
  762. }
  763. //------------------------------------------------------------------------------
  764. /**
  765. * Manages all the unzipping process of an uploaded document
  766. * This uses the item_property table for properties of documents
  767. *
  768. * @author Hugues Peeters <hugues.peeters@claroline.net>
  769. * @author Bert Vanderkimpen
  770. *
  771. * @param array $uploadedFile - follows the $_FILES Structure
  772. * @param string $uploadPath - destination of the upload.
  773. * This path is to append to $baseWorkDir
  774. * @param string $baseWorkDir - base working directory of the module
  775. * @param int $maxFilledSpace - amount of bytes to not exceed in the base
  776. * working directory
  777. * @param boolean Output switch. Optional. If no output not wanted on success, set to false.
  778. *
  779. * @return boolean true if it succeeds false otherwise
  780. */
  781. function unzip_uploaded_document($uploaded_file, $upload_path, $base_work_dir, $max_filled_space, $output = true, $to_group_id=0)
  782. {
  783. global $_course;
  784. global $_user;
  785. global $to_user_id;
  786. global $to_group_id;
  787. $zip_file = new pclZip($uploaded_file['tmp_name']);
  788. // Check the zip content (real size and file extension)
  789. $zip_content_array = $zip_file->listContent();
  790. foreach((array) $zip_content_array as $this_content)
  791. {
  792. $real_filesize += $this_content['size'];
  793. }
  794. if (! enough_space($real_filesize, $max_filled_space) )
  795. {
  796. Display::display_error_message(get_lang('UplNotEnoughSpace'));
  797. return false;
  798. }
  799. // it happens on Linux that $uploadPath sometimes doesn't start with '/'
  800. if($upload_path[0] != '/')
  801. {
  802. $upload_path='/'.$upload_path;
  803. }
  804. /*
  805. --------------------------------------
  806. Uncompressing phase
  807. --------------------------------------
  808. */
  809. //get into the right directory
  810. $save_dir = getcwd();
  811. chdir($base_work_dir.$upload_path);
  812. //we extract using a callback function that "cleans" the path
  813. $unzipping_state = $zip_file->extract(PCLZIP_CB_PRE_EXTRACT, 'clean_up_files_in_zip');
  814. // Add all documents in the unzipped folder to the database
  815. add_all_documents_in_folder_to_database($_course,$_user['user_id'],$base_work_dir,$upload_path == '/' ? '' : $upload_path, $to_group_id);
  816. //Display::display_normal_message(get_lang('UplZipExtractSuccess'));
  817. return true;
  818. /*
  819. if ($upload_path != '/')
  820. $upload_path = $upload_path.'/';
  821. if($unzipping_state!=0)
  822. {
  823. for($j=0;$j<count($unzipping_state);$j++)
  824. {
  825. $state=$unzipping_state[$j];
  826. $filename = $state['stored_filename'];
  827. //echo("<br>filename = ".$filename."<br>");
  828. $filename2 = $state['filename'];
  829. //echo("<br>filename2 = ".$filename2."<br>");
  830. $filetype="file";
  831. //if(is_dir($filename))
  832. if($state['folder']==1)
  833. {
  834. $filetype="folder";
  835. $endchar=substr($filename,strlen($filename)-1,1);
  836. if($endchar=="\\" || $endchar=="/")
  837. $filename=substr($filename,0,strlen($filename)-1);
  838. }
  839. //store document in database
  840. if($state['status']=="ok" || $state['status']=="already_a_directory")
  841. {
  842. //echo $base_work_dir.$upload_path.clean_up_path($state["stored_filename"])." (".$filetype.")<br/>";
  843. $cleaned_up_filename = clean_up_path($filename);
  844. $file_path = $upload_path.$cleaned_up_filename;
  845. echo("file path = ".$file_path."<br>");
  846. //this is a quick fix for zipfiles that have files in folders but the folder is not stored in the zipfile
  847. //if the path has folders, check if they already are in the database
  848. if(dirname('/'.$cleaned_up_filename)!='/' AND dirname('/'.$cleaned_up_filename)!='\\')
  849. {
  850. $folder_id=DocumentManager::get_document_id($_course,$upload_path.dirname($cleaned_up_filename));
  851. if(!$folder_id)
  852. {
  853. echo($upload_path.dirname($cleaned_up_filename).' not found in database!<br>');
  854. $folder_id = add_document($_course,$upload_path.dirname($cleaned_up_filename),'folder',0,basename(dirname($cleaned_up_filename)));
  855. if($folder_id)
  856. {
  857. api_item_property_update($_course,TOOL_DOCUMENT,$folder_id,'FolderAdded',$_user['user_id'],$to_group_id,$to_user_id);
  858. //echo('folder '.$upload_path.dirname($cleaned_up_filename)." added<br>\n");
  859. }
  860. }
  861. }
  862. $store_path = $base_work_dir.$file_path;
  863. //echo("store path = ".$store_path."<br>");
  864. $document_name = get_document_title(basename($filename));
  865. //echo("document_name = ".$document_name."<br><br>");
  866. //put the document data in the database
  867. //if the file/dir does not exist, just add it
  868. //if(!file_exists($store_path)) <- not working, as the file is already extracted
  869. //so we check if the document is already in the database
  870. $document_id = DocumentManager::get_document_id($_course,$file_path);
  871. if(!$document_id)
  872. {
  873. $document_id = add_document($_course,$file_path,$filetype,$state['size'],$document_name);
  874. if ($document_id)
  875. {
  876. $lastedit_type = ($filetype=='folder')?'FolderAdded':'DocumentAdded';
  877. //update item property for document
  878. api_item_property_update($_course,TOOL_DOCUMENT,$document_id,$lastedit_type,$_user['user_id'],$to_group_id,$to_user_id);
  879. }
  880. }
  881. //file/dir exists -> update
  882. else
  883. {
  884. $lastedit_type = ($filetype=='folder')?'FolderUpdated':'DocumentUpdated';
  885. //update the document in item_property
  886. api_item_property_update($_course,TOOL_DOCUMENT,$document_id,$lastedit_type,$_user['user_id'],$to_group_id,$to_user_id);
  887. }
  888. }
  889. }
  890. //print_r_pre($zip_content_array);
  891. //if the file is in a folder, we need to update all parent folders
  892. item_property_update_on_folder($_course,$upload_path,$_user['user_id']);
  893. //display success message to user
  894. chdir($save_dir); //return to previous dir position
  895. if($output){
  896. Display::display_normal_message(get_lang('UplZipExtractSuccess'));
  897. }
  898. return true;
  899. }
  900. else {
  901. //zip file could not be extracted -> corrupt file
  902. Display::display_error_message(get_lang('UplZipCorrupt'));
  903. return false;
  904. }
  905. */
  906. }
  907. //------------------------------------------------------------------------------
  908. /**
  909. * this function is a callback function that is used while extracting a zipfile
  910. * http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_cb_pre_extract
  911. *
  912. * @param $p_event
  913. * @param $p_header
  914. * @return 1 (If the function returns 1, then the extraction is resumed)
  915. */
  916. function clean_up_files_in_zip($p_event, &$p_header)
  917. {
  918. $res = clean_up_path($p_header['filename']);
  919. return $res;
  920. }
  921. //------------------------------------------------------------------------------
  922. /**
  923. * this function cleans up a given path
  924. * by eliminating dangerous file names and cleaning them
  925. *
  926. * @param string $path
  927. * @return $path
  928. * @see disable_dangerous_file()
  929. * @see replace_dangerous_char()
  930. */
  931. function clean_up_path(&$path)
  932. {
  933. //split the path in folders and files
  934. $path_array = explode('/',$path);
  935. //clean up every foler and filename in the path
  936. $val = '';
  937. foreach($path_array as $key => $val)
  938. {
  939. //we don't want to lose the dots in ././folder/file (cfr. zipfile)
  940. if($path_array[$key]!='.')
  941. $path_array[$key] = disable_dangerous_file( replace_dangerous_char($val) );
  942. }
  943. //join the "cleaned" path (modified in-place as passed by reference)
  944. $path = implode('/',$path_array);
  945. $res = filter_extension($path);
  946. return $res;
  947. }
  948. /**
  949. * Check if the file is dangerous, based on extension and/or mimetype.
  950. * The list of extensions accepted/rejected can be found from
  951. * api_get_setting('upload_extensions_exclude') and api_get_setting('upload_extensions_include')
  952. * @param string filename passed by reference. The filename will be modified if filter rules say so! (you can include path but the filename should look like 'abc.html')
  953. * @return int 0 to skip file, 1 to keep file
  954. */
  955. function filter_extension(&$filename)
  956. {
  957. if(substr($filename,-1)=='/'){return 1;} //authorize directories
  958. $blacklist = api_get_setting('upload_extensions_list_type');
  959. if($blacklist!='whitelist')//if = blacklist
  960. {
  961. $extensions = split(';',strtolower(api_get_setting('upload_extensions_blacklist')));
  962. $skip = api_get_setting('upload_extensions_skip');
  963. $ext = strrchr($filename, ".");
  964. $ext = substr($ext,1);
  965. if(empty($ext)){return 1;}//we're in blacklist mode, so accept empty extensions
  966. if(in_array(strtolower($ext),$extensions))
  967. {
  968. if($skip=='true')
  969. {
  970. return 0;
  971. }
  972. else
  973. {
  974. $new_ext = api_get_setting('upload_extensions_replace_by');
  975. $filename = str_replace(".".$ext,".".$new_ext,$filename);
  976. return 1;
  977. }
  978. }
  979. else
  980. {
  981. return 1;
  982. }
  983. }
  984. else
  985. {
  986. $extensions = split(';',strtolower(api_get_setting('upload_extensions_whitelist')));
  987. $skip = api_get_setting('upload_extensions_skip');
  988. $ext = strrchr($filename, ".");
  989. $ext = substr($ext,1);
  990. if(empty($ext)){return 1;}//accept empty extensions
  991. if(!in_array(strtolower($ext),$extensions))
  992. {
  993. if($skip=='true')
  994. {
  995. return 0;
  996. }
  997. else
  998. {
  999. $new_ext = api_get_setting('upload_extensions_replace_by');
  1000. $filename = str_replace(".".$ext,".".$new_ext,$filename);
  1001. return 1;
  1002. }
  1003. }
  1004. else
  1005. {
  1006. return 1;
  1007. }
  1008. }
  1009. }
  1010. //------------------------------------------------------------------------------
  1011. /**
  1012. * Adds a new document to the database
  1013. *
  1014. * @param array $_course
  1015. * @param string $path
  1016. * @param string $filetype
  1017. * @param int $filesize
  1018. * @param string $title
  1019. * @return id if inserted document
  1020. */
  1021. function add_document($_course,$path,$filetype,$filesize,$title,$comment=NULL, $readonly=0)
  1022. {
  1023. global $charset;
  1024. $session_id = api_get_session_id();
  1025. $table_document = Database::get_course_table(TABLE_DOCUMENT,$_course['dbName']);
  1026. $sql="INSERT INTO $table_document
  1027. (`path`, `filetype`, `size`, `title`, `comment`, `readonly`, `session_id`)
  1028. VALUES ('$path','$filetype','$filesize','".
  1029. Database::escape_string(htmlspecialchars($title, ENT_QUOTES, $charset))."', '$comment', $readonly, $session_id)";
  1030. if(Database::query($sql,__FILE__,__LINE__))
  1031. {
  1032. //display_message("Added to database (id ".Database::insert_id().")!");
  1033. return Database::insert_id();
  1034. }
  1035. else
  1036. {
  1037. //display_error("The uploaded file could not be added to the database (".mysql_error().")!");
  1038. return false;
  1039. }
  1040. }
  1041. //------------------------------------------------------------------------------
  1042. /*
  1043. function get_document_id() moved to document.lib.php
  1044. */
  1045. //------------------------------------------------------------------------------
  1046. /**
  1047. * Update an existing document in the database
  1048. * as the file exists, we only need to change the size
  1049. *
  1050. * @param array $_course
  1051. * @param int $document_id
  1052. * @param int $filesize
  1053. * @param int $readonly
  1054. * @return boolean true /false
  1055. */
  1056. function update_existing_document($_course,$document_id,$filesize,$readonly=0)
  1057. {
  1058. $document_table = Database::get_course_table(TABLE_DOCUMENT,$_course['dbName']);
  1059. $sql="UPDATE $document_table SET size = '$filesize' , readonly = '$readonly' WHERE id='$document_id'";
  1060. if(Database::query($sql,__FILE__,__LINE__))
  1061. {
  1062. return true;
  1063. }
  1064. else
  1065. {
  1066. return false;
  1067. }
  1068. }
  1069. /**
  1070. * this function updates the last_edit_date, last edit user id on all folders in a given path
  1071. *
  1072. * @param array $_course
  1073. * @param string $path
  1074. * @param int $user_id
  1075. */
  1076. function item_property_update_on_folder($_course,$path,$user_id)
  1077. {
  1078. //display_message("Start update_lastedit_on_folder");
  1079. //if we are in the root, just return... no need to update anything
  1080. if ($path=='/')
  1081. return;
  1082. //if the given path ends with a / we remove it
  1083. $endchar=substr($path,strlen($path)-1,1);
  1084. if($endchar=='/')
  1085. $path=substr($path,0,strlen($path)-1);
  1086. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY,$_course['dbName']);
  1087. //get the time
  1088. $time = date("Y-m-d H:i:s", time());
  1089. //get all paths in the given path
  1090. // /folder/subfolder/subsubfolder/file
  1091. // if file is updated, subsubfolder, subfolder and folder are updated
  1092. $exploded_path = explode('/',$path);
  1093. foreach ($exploded_path as $key => $value) {
  1094. //we don't want a slash before our first slash
  1095. if($key!=0){
  1096. $newpath .= "/".$value;
  1097. //echo "path= ".$newpath."<br>";
  1098. //select ID of given folder
  1099. $folder_id = DocumentManager::get_document_id($_course,$newpath);
  1100. if($folder_id)
  1101. {
  1102. $sql = "UPDATE $TABLE_ITEMPROPERTY SET `lastedit_date`='$time',`lastedit_type`='DocumentInFolderUpdated', `lastedit_user_id`='$user_id' WHERE tool='".TOOL_DOCUMENT."' AND ref='$folder_id'";
  1103. Database::query($sql,__FILE__,__LINE__);
  1104. }
  1105. }
  1106. }
  1107. }
  1108. //------------------------------------------------------------------------------
  1109. /**
  1110. * Returns the directory depth of the file.
  1111. *
  1112. * @author Olivier Cauberghe <olivier.cauberghe@ugent.be>
  1113. * @param path+filename eg: /main/document/document.php
  1114. * @return The directory depth
  1115. */
  1116. function get_levels($filename)
  1117. {
  1118. $levels=explode("/",$filename);
  1119. if(empty($levels[count($levels)-1])) unset($levels[count($levels)-1]);
  1120. return count($levels);
  1121. }
  1122. /*
  1123. function file_set_default_settings
  1124. moved to fileManage.lib.php,
  1125. class FileManager
  1126. */
  1127. //------------------------------------------------------------------------------
  1128. /**
  1129. * Adds file to document table in database
  1130. * @deprecated, use file_set_default_settings instead
  1131. *
  1132. * @author Olivier Cauberghe <olivier.cauberghe@ugent.be>
  1133. * @param path,filename
  1134. * @action Adds an entry to the document table with the default settings.
  1135. */
  1136. function set_default_settings($upload_path,$filename,$filetype="file")
  1137. {
  1138. global $dbTable,$_configuration;
  1139. global $default_visibility;
  1140. if (!$default_visibility)
  1141. $default_visibility="v";
  1142. $upload_path=str_replace('\\','/',$upload_path);
  1143. $upload_path=str_replace("//","/",$upload_path);
  1144. if($upload_path == '/')
  1145. {
  1146. $upload_path='';
  1147. }
  1148. elseif(!empty($upload_path) && $upload_path[0] != '/')
  1149. {
  1150. $upload_path="/$upload_path";
  1151. }
  1152. $endchar=substr($filename,strlen($filename)-1,1);
  1153. if($endchar == '/')
  1154. {
  1155. $filename=substr($filename,0,-1);
  1156. }
  1157. //$dbTable already has `backticks`!
  1158. //$query="select count(*) as bestaat from `$dbTable` where path='$upload_path/$filename'";
  1159. $query="select count(*) as bestaat from $dbTable where path='$upload_path/$filename'";
  1160. $result=Database::query($query,__FILE__,__LINE__);
  1161. $row=Database::fetch_array($result);
  1162. if($row["bestaat"]>0)
  1163. //$query="update `$dbTable` set path='$upload_path/$filename',visibility='$default_visibility', filetype='$filetype' where path='$upload_path/$filename'";
  1164. $query="update $dbTable set path='$upload_path/$filename',visibility='$default_visibility', filetype='$filetype' where path='$upload_path/$filename'";
  1165. else //$query="INSERT INTO `$dbTable` (path,visibility,filetype) VALUES('$upload_path/$filename','$default_visibility','$filetype')";
  1166. $query="INSERT INTO $dbTable (path,visibility,filetype) VALUES('$upload_path/$filename','$default_visibility','$filetype')";
  1167. Database::query($query,__FILE__,__LINE__);
  1168. }
  1169. //------------------------------------------------------------------------------
  1170. /**
  1171. * retrieve the image path list in a html file
  1172. *
  1173. * @author Hugues Peeters <hugues.peeters@claroline.net>
  1174. * @param string $htmlFile
  1175. * @return array - images path list
  1176. */
  1177. function search_img_from_html($htmlFile)
  1178. {
  1179. $imgFilePath = array();
  1180. if(!$fp = fopen($htmlFile, "r")){ //or die('<center>can not open file</center>');
  1181. return ;
  1182. }
  1183. // search and store occurences of the <IMG> tag in an array
  1184. $size_file=(filesize($htmlFile)===0) ? 1 : filesize($htmlFile);
  1185. if (isset($fp) && !($fp===false)) {
  1186. $buffer = fread( $fp, $size_file );
  1187. if (strlen($buffer)>=0 && !($buffer===false)) {
  1188. //
  1189. } else {
  1190. die('<center>Can not read file.</center>');
  1191. }
  1192. } else {
  1193. die('<center>Can not read file.</center>');
  1194. }
  1195. $matches = array();
  1196. if ( preg_match_all('~<[[:space:]]*img[^>]*>~i', $buffer, $matches) )
  1197. {
  1198. $imgTagList = $matches[0];
  1199. }
  1200. fclose ($fp); unset($buffer);
  1201. // Search the image file path from all the <IMG> tag detected
  1202. if ( sizeof($imgTagList) > 0)
  1203. {
  1204. foreach($imgTagList as $thisImgTag)
  1205. {
  1206. if ( preg_match('~src[[:space:]]*=[[:space:]]*[\"]{1}([^\"]+)[\"]{1}~i',
  1207. $thisImgTag, $matches) )
  1208. {
  1209. $imgPathList[] = $matches[1];
  1210. }
  1211. }
  1212. $imgPathList = array_unique($imgPathList); // remove duplicate entries
  1213. }
  1214. return $imgPathList;
  1215. }
  1216. //------------------------------------------------------------------------------
  1217. /**
  1218. * creates a new directory trying to find a directory name
  1219. * that doesn't already exist
  1220. * (we could use unique_name() here...)
  1221. *
  1222. * @author Hugues Peeters <hugues.peeters@claroline.net>
  1223. * @author Bert Vanderkimpen
  1224. * @param array $_course current course information
  1225. * @param int $user_id current user id
  1226. * @param string $desiredDirName complete path of the desired name
  1227. * @return string actual directory name if it succeeds,
  1228. * boolean false otherwise
  1229. */
  1230. function create_unexisting_directory($_course,$user_id,$to_group_id,$to_user_id,$base_work_dir,$desired_dir_name, $title = null, $visibility = '')
  1231. {
  1232. $nb = '';
  1233. while ( file_exists($base_work_dir.$desired_dir_name.$nb) )
  1234. {
  1235. $nb += 1;
  1236. }
  1237. if( $title == null)
  1238. {
  1239. $title = basename($desired_dir_name);
  1240. }
  1241. if (mkdir($base_work_dir.$desired_dir_name.$nb, api_get_permissions_for_new_directories(), true))
  1242. {
  1243. $document_id = add_document($_course, $desired_dir_name.$nb,'folder',0,$title);
  1244. if ($document_id)
  1245. {
  1246. //update document item_property
  1247. $current_session_id = api_get_session_id();
  1248. if ($visibility !== '') {
  1249. $visibilities = array(0 => 'invisible', 1 => 'visible', 2 => 'delete');
  1250. api_item_property_update($_course,TOOL_DOCUMENT,$document_id,$visibilities[$visibility],$user_id,$to_group_id,$to_user_id,null,null,$current_session_id);
  1251. } else {
  1252. api_item_property_update($_course,TOOL_DOCUMENT,$document_id,'FolderCreated',$user_id,$to_group_id,$to_user_id,null,null,$current_session_id);
  1253. }
  1254. return $desired_dir_name.$nb;
  1255. }
  1256. }
  1257. else
  1258. {
  1259. return false;
  1260. }
  1261. }
  1262. //------------------------------------------------------------------------------
  1263. /**
  1264. * Handles uploaded missing images
  1265. *
  1266. * @author Hugues Peeters <hugues.peeters@claroline.net>
  1267. * @author Bert Vanderkimpen
  1268. * @param array $_course
  1269. * @param array $uploaded_file_collection - follows the $_FILES Structure
  1270. * @param string $base_work_dir
  1271. * @param string $missing_files_dir
  1272. * @param int $user_id
  1273. * @param int $max_filled_space
  1274. */
  1275. function move_uploaded_file_collection_into_directory($_course, $uploaded_file_collection, $base_work_dir, $missing_files_dir,$user_id,$to_group_id,$to_user_id,$max_filled_space)
  1276. {
  1277. $number_of_uploaded_images = count($uploaded_file_collection['name']);
  1278. for ($i=0; $i < $number_of_uploaded_images; $i++)
  1279. {
  1280. $missing_file['name'] = $uploaded_file_collection['name'][$i];
  1281. $missing_file['type'] = $uploaded_file_collection['type'][$i];
  1282. $missing_file['tmp_name'] = $uploaded_file_collection['tmp_name'][$i];
  1283. $missing_file['error'] = $uploaded_file_collection['error'][$i];
  1284. $missing_file['size'] = $uploaded_file_collection['size'][$i];
  1285. $upload_ok = process_uploaded_file($missing_file);
  1286. if($upload_ok)
  1287. {
  1288. $new_file_list[] = handle_uploaded_document($_course,$missing_file,$base_work_dir,$missing_files_dir,$user_id,$to_group_id,$to_user_id,$max_filled_space,0,'overwrite');
  1289. }
  1290. unset($missing_file);
  1291. }
  1292. return $new_file_list;
  1293. }
  1294. //------------------------------------------------------------------------------
  1295. //------------------------------------------------------------------------------
  1296. /*
  1297. * Open the old html file and replace the src path into the img tag
  1298. * This also works for files in subdirectories.
  1299. * @param $originalImgPath is an array
  1300. * @param $newImgPath is an array
  1301. */
  1302. function replace_img_path_in_html_file($originalImgPath, $newImgPath, $htmlFile)
  1303. {
  1304. global $_course;
  1305. /*
  1306. * Open the file
  1307. */
  1308. $fp = fopen($htmlFile, "r");
  1309. $buffer = fread ($fp, filesize ($htmlFile));
  1310. /*
  1311. * Fix the image tags
  1312. */
  1313. for ($i = 0, $fileNb = count($originalImgPath); $i < $fileNb ; $i++)
  1314. {
  1315. $replace_what = $originalImgPath[$i];
  1316. /*
  1317. we only need the directory and the filename
  1318. /path/to/file_html_files/missing_file.gif -> file_html_files/missing_file.gif
  1319. */
  1320. $exploded_file_path = explode('/',$newImgPath[$i]);
  1321. $replace_by = $exploded_file_path[count($exploded_file_path)-2].'/'.$exploded_file_path[count($exploded_file_path)-1];
  1322. //$message .= "Element [$i] <b>" . $replace_what . "</b> replaced by <b>" . $replace_by . "</b><br>"; //debug
  1323. //api_display_debug_info($message);
  1324. $buffer = str_replace( $replace_what, $replace_by, $buffer);
  1325. }
  1326. $new_html_content .= $buffer;
  1327. fclose ($fp) or die ('<center>cannot close file</center>');;
  1328. /*
  1329. * Write the resulted new file
  1330. */
  1331. if (!$fp = fopen($htmlFile, 'w')){ //or die('<center>cannot open file</center>');
  1332. return;
  1333. }
  1334. if (!fwrite($fp, $new_html_content)){ // or die('<center>cannot write in file</center>');
  1335. return;
  1336. }
  1337. }
  1338. //------------------------------------------------------------------------------
  1339. /**
  1340. * Creates a file containing an html redirection to a given url
  1341. *
  1342. * @author Hugues Peeters <hugues.peeters@claroline.net>
  1343. * @param string $filePath
  1344. * @param string $url
  1345. * @return void
  1346. */
  1347. function create_link_file($filePath, $url)
  1348. {
  1349. $fileContent = '<html>'
  1350. .'<head>'
  1351. .'<meta http-equiv="refresh" content="1;url='.$url.'">'
  1352. .'</head>'
  1353. .'<body>'
  1354. .'</body>'
  1355. .'</html>';
  1356. if(file_exists($filePath)){
  1357. if (!($fp = fopen ($filePath, 'w'))) {
  1358. return false;
  1359. }
  1360. return fwrite($fp, $fileContent);
  1361. }
  1362. }
  1363. //------------------------------------------------------------------------------
  1364. /**
  1365. Open html file $full_file_name;
  1366. Parse the hyperlinks; and
  1367. Write the result back in the html file.
  1368. @author Roan Embrechts
  1369. @version 0.1
  1370. */
  1371. function api_replace_links_in_html($upload_path, $full_file_name)
  1372. {
  1373. //Open the file
  1374. if(file_exists($full_file_name)){
  1375. $fp = fopen($full_file_name, "r");
  1376. $buffer = fread ($fp, filesize ($full_file_name));
  1377. //Parse the contents
  1378. $new_html_content = api_replace_links_in_string($upload_path, $buffer);
  1379. //Write the result
  1380. $fp = fopen($full_file_name, "w");
  1381. fwrite($fp, $new_html_content);
  1382. }
  1383. }
  1384. //------------------------------------------------------------------------------
  1385. /**
  1386. @deprecated, use api_replace_parameter instead
  1387. Parse the buffer string provided as parameter
  1388. Replace the a href tags so they are displayed correctly.
  1389. - works for files in root and subdirectories
  1390. - replace relative hyperlinks to use showinframes.php?file= ...
  1391. - add target="_self" to all absolute hyperlinks
  1392. - leave local anchors untouched (e.g. #CHAPTER1)
  1393. - leave links with download.php and showinframes.php untouched
  1394. @author Roan Embrechts
  1395. @version 0.6
  1396. */
  1397. function api_replace_links_in_string($upload_path, $buffer)
  1398. {
  1399. // Search for hyperlinks
  1400. $matches = array();
  1401. if ( preg_match_all("/<a[\s]*href[^<]*>/i", $buffer, $matches) )
  1402. {
  1403. $tag_list = $matches[0];
  1404. }
  1405. // Search the filepath of all detected <a href> tags
  1406. if (sizeof($tag_list) > 0)
  1407. {
  1408. $file_path_list=array();
  1409. $href_list=array();
  1410. foreach($tag_list as $this_tag)
  1411. {
  1412. /* Match case insensitive, the stuff between the two ~ :
  1413. a href = <exactly one quote><one or more non-quotes><exactly one ">
  1414. e.g. a href="www.google.be", A HREF = "info.html"
  1415. to match ["] escape the " or else PHP interprets it
  1416. [\"]{1} --> matches exactly one "
  1417. + 1 or more (like * is 0 or more)
  1418. [\s]* matches whitespace
  1419. $matches contains captured subpatterns
  1420. the only one here is ([^\"]+) --> matches[1]
  1421. */
  1422. if ( preg_match("~a href[\s]*=[\s]*[\"]{1}([^\"]+)[\"]{1}~i",
  1423. $this_tag, $matches) )
  1424. {
  1425. $file_path_list[] = $matches[1];//older
  1426. $href_list[] = $matches[0];//to also add target="_self"
  1427. }
  1428. }
  1429. }
  1430. // replace the original hyperlinks
  1431. // by the correct ones
  1432. for ($count = 0; $count < sizeof($href_list); $count++)
  1433. {
  1434. $replaceWhat[$count] = $href_list[$count];
  1435. $is_absolute_hyperlink = strpos($replaceWhat[$count], "http");
  1436. $is_local_anchor = strpos($replaceWhat[$count], "#");
  1437. if ($is_absolute_hyperlink == false && $is_local_anchor == false )
  1438. {
  1439. //this is a relative hyperlink
  1440. if (
  1441. (strpos($replaceWhat[$count], "showinframes.php") == false) &&
  1442. (strpos($replaceWhat[$count], "download.php") == false)
  1443. )
  1444. {
  1445. //fix the link to use showinframes.php
  1446. $replaceBy[$count] = "a href = \"showinframes.php?file=" . $upload_path."/".$file_path_list[$count]."\" target=\"_self\"";
  1447. }
  1448. else
  1449. {
  1450. //url already fixed, leave as is
  1451. $replaceBy[$count] = $replaceWhat[$count];
  1452. }
  1453. }
  1454. else if ($is_absolute_hyperlink)
  1455. {
  1456. $replaceBy[$count] = "a href=\"" . $file_path_list[$count] . "\" target =\"_self\"";
  1457. }
  1458. else
  1459. {
  1460. //don't change anything
  1461. $replaceBy[$count] = $replaceWhat[$count];
  1462. }
  1463. //Display::display_normal_message("link replaced by " . $replaceBy[$count]); //debug
  1464. }
  1465. $buffer = str_replace($replaceWhat, $replaceBy, $buffer);
  1466. return $buffer;
  1467. }
  1468. //------------------------------------------------------------------------------
  1469. /**
  1470. EXPERIMENTAL - function seems to work, needs more testing
  1471. @param $upload_path is the path where the document is stored, like "/archive/"
  1472. if it is the root level, the function expects "/"
  1473. otherwise "/path/"
  1474. This function parses all tags with $param_name parameters.
  1475. so the tags are displayed correctly.
  1476. --------------
  1477. Algorithm v1.0
  1478. --------------
  1479. given a string and a parameter,
  1480. * OK find all tags in that string with the specified parameter (like href or src)
  1481. * OK for every one of these tags, find the src|href|... part to edit it
  1482. * OK change the src|href|... part to use download.php (or showinframes.php)
  1483. * OK do some special stuff for hyperlinks
  1484. Exceptions
  1485. * OK if download.php or showinframes.php is already in the tag, leave it alone
  1486. * OK if mailto is in the tag, leave it alone
  1487. * OK if the src|href param contains http://, it's absolute --> leave it alone
  1488. Special for hyperlinks (a href...)
  1489. * OK add target="_self"
  1490. * OK use showinframes.php instead of download.php
  1491. @author Roan Embrechts
  1492. @version 1.1
  1493. */
  1494. function api_replace_parameter($upload_path, $buffer, $param_name="src")
  1495. {
  1496. /*
  1497. * Search for tags with $param_name as a parameter
  1498. */
  1499. /*
  1500. // [\s]* matches whitespace
  1501. // [\"=a-z] matches ", = and a-z
  1502. // ([\s]*[a-z]*)* matches all whitespace and normal alphabet
  1503. // characters a-z combinations but seems too slow
  1504. // perhaps ([\s]*[a-z]*) a maximum number of times ?
  1505. // [\s]*[a-z]*[\s]* matches many tags
  1506. // the ending "i" means to match case insensitive (a matches a and A)
  1507. */
  1508. $matches = array();
  1509. if ( preg_match_all("/<[a-z]+[^<]*".$param_name."[^<]*>/i", $buffer, $matches) )
  1510. {
  1511. $tag_list = $matches[0];
  1512. }
  1513. /*
  1514. * Search the filepath of parameter $param_name in all detected tags
  1515. */
  1516. if (sizeof($tag_list) > 0)
  1517. {
  1518. $file_path_list=array();
  1519. $href_list=array();
  1520. foreach($tag_list as $this_tag)
  1521. {
  1522. //Display::display_normal_message(htmlentities($this_tag)); //debug
  1523. if ( preg_match("~".$param_name."[\s]*=[\s]*[\"]{1}([^\"]+)[\"]{1}~i",
  1524. $this_tag, $matches) )
  1525. {
  1526. $file_path_list[] = $matches[1];//older
  1527. $href_list[] = $matches[0];//to also add target="_self"
  1528. }
  1529. }
  1530. }
  1531. /*
  1532. * Replace the original tags by the correct ones
  1533. */
  1534. for ($count = 0; $count < sizeof($href_list); $count++)
  1535. {
  1536. $replaceWhat[$count] = $href_list[$count];
  1537. $is_absolute_hyperlink = strpos($replaceWhat[$count], 'http');
  1538. $is_local_anchor = strpos($replaceWhat[$count], '#');
  1539. if ($is_absolute_hyperlink == false && $is_local_anchor == false )
  1540. {
  1541. if (
  1542. (strpos($replaceWhat[$count], 'showinframes.php') == false) &&
  1543. (strpos($replaceWhat[$count], 'download.php') == false) &&
  1544. (strpos($replaceWhat[$count], 'mailto') == false)
  1545. )
  1546. {
  1547. //fix the link to use download.php or showinframes.php
  1548. if ( preg_match("/<a([\s]*[\"\/:'=a-z0-9]*){5}href[^<]*>/i", $tag_list[$count]) )
  1549. {
  1550. $replaceBy[$count] = " $param_name =\"showinframes.php?file=" . $upload_path.$file_path_list[$count]."\" target=\"_self\" ";
  1551. }
  1552. else
  1553. {
  1554. $replaceBy[$count] = " $param_name =\"download.php?doc_url=" . $upload_path.$file_path_list[$count]."\" ";
  1555. }
  1556. }
  1557. else
  1558. {
  1559. //"mailto" or url already fixed, leave as is
  1560. //$message .= "Already fixed or contains mailto: ";
  1561. $replaceBy[$count] = $replaceWhat[$count];
  1562. }
  1563. }
  1564. else if ($is_absolute_hyperlink)
  1565. {
  1566. //$message .= "Absolute hyperlink, don't change, add target=_self: ";
  1567. $replaceBy[$count] = " $param_name=\"" . $file_path_list[$count] . "\" target =\"_self\"";
  1568. }
  1569. else
  1570. {
  1571. //don't change anything
  1572. //$message .= "Local anchor, don't change: ";
  1573. $replaceBy[$count] = $replaceWhat[$count];
  1574. }
  1575. //$message .= "In tag $count, <b>" . htmlentities($tag_list[$count])
  1576. // . "</b>, parameter <b>" . $replaceWhat[$count] . "</b> replaced by <b>" . $replaceBy[$count] . "</b><br>"; //debug
  1577. }
  1578. //if (isset($message) && $message == true) api_display_debug_info($message); //debug
  1579. $buffer = str_replace($replaceWhat, $replaceBy, $buffer);
  1580. return $buffer;
  1581. }
  1582. //------------------------------------------------------------------------------
  1583. /**
  1584. * Checks the extension of a file, if it's .htm or .html
  1585. * we use search_img_from_html to get all image paths in the file
  1586. *
  1587. * @param string $file
  1588. * @return array paths
  1589. * @see check_for_missing_files() uses search_img_from_html()
  1590. */
  1591. function check_for_missing_files($file)
  1592. {
  1593. if (strrchr($file, '.') == '.htm' || strrchr($file, '.') == '.html')
  1594. {
  1595. $img_file_path = search_img_from_html($file);
  1596. return $img_file_path;
  1597. }
  1598. return false;
  1599. }
  1600. //------------------------------------------------------------------------------
  1601. /**
  1602. * This builds a form that asks for the missing images in a html file
  1603. * maybe we should do this another way?
  1604. *
  1605. * @param array $missing_files
  1606. * @param string $upload_path
  1607. * @param string $file_name
  1608. * @return string the form
  1609. */
  1610. function build_missing_files_form($missing_files,$upload_path,$file_name)
  1611. {
  1612. //do we need a / or not?
  1613. $added_slash = ($upload_path=='/')?'':'/';
  1614. //build the form
  1615. $form .= "<p><strong>".get_lang('MissingImagesDetected')."</strong></p>\n"
  1616. ."<form method=\"post\" action=\"".api_get_self()."\" enctype=\"multipart/form-data\">\n"
  1617. //related_file is the path to the file that has missing images
  1618. ."<input type=\"hidden\" name=\"related_file\" value=\"".$upload_path.$added_slash.$file_name."\" />\n"
  1619. ."<input type=\"hidden\" name=\"upload_path\" value=\"".$upload_path."\" />\n"
  1620. ."<table border=\"0\">\n";
  1621. foreach($missing_files as $this_img_file_path )
  1622. {
  1623. $form .= "<tr>\n"
  1624. ."<td>".basename($this_img_file_path)." : </td>\n"
  1625. ."<td>"
  1626. ."<input type=\"file\" name=\"img_file[]\"/>"
  1627. ."<input type=\"hidden\" name=\"img_file_path[]\" value=\"".$this_img_file_path."\" />"
  1628. ."</td>\n"
  1629. ."</tr>\n";
  1630. }
  1631. $form .= "</table>\n"
  1632. ."<button type='submit' name=\"cancel_submit_image\" value=\"".get_lang('Cancel')."\" class=\"cancel\">".get_lang('Cancel')."</button>"
  1633. ."<button type='submit' name=\"submit_image\" value=\"".get_lang('Ok')."\" class=\"save\">".get_lang('Ok')."</button>"
  1634. ."</form>\n";
  1635. return $form;
  1636. }
  1637. //------------------------------------------------------------------------------
  1638. /**
  1639. * This recursive function can be used during the upgrade process form older versions of Dokeos
  1640. * It crawls the given directory, checks if the file is in the DB and adds it if it's not
  1641. *
  1642. * @param string $base_work_dir
  1643. * @param string $current_path, needed for recursivity
  1644. */
  1645. function add_all_documents_in_folder_to_database($_course,$user_id,$base_work_dir,$current_path='',$to_group_id=0)
  1646. {
  1647. $current_session_id = api_get_session_id();
  1648. $path = $base_work_dir.$current_path;
  1649. //open dir
  1650. $handle=opendir($path);
  1651. if(is_dir($path)){
  1652. //run trough
  1653. while($file=readdir($handle))
  1654. {
  1655. if ($file=='.' || $file=='..') continue;
  1656. $completepath="$path/$file";
  1657. //directory?
  1658. if (is_dir($completepath))
  1659. {
  1660. $title=get_document_title($file);
  1661. $safe_file=replace_dangerous_char($file);
  1662. @rename($path.'/'.$file, $path.'/'.$safe_file);
  1663. //if we can't find the file, add it
  1664. if(!DocumentManager::get_document_id($_course, $current_path.'/'.$safe_file))
  1665. {
  1666. $document_id=add_document($_course,$current_path.'/'.$safe_file,'folder',0,$title);
  1667. api_item_property_update($_course,TOOL_DOCUMENT,$document_id,'DocumentAdded',$user_id, $to_group_id,null,null,null,$current_session_id);
  1668. //echo $current_path.'/'.$safe_file." added!<br/>";
  1669. }
  1670. //recursive
  1671. add_all_documents_in_folder_to_database($_course,$user_id,$base_work_dir,$current_path.'/'.$safe_file, $to_group_id);
  1672. }
  1673. //file!
  1674. else
  1675. {
  1676. //rename
  1677. $safe_file=disable_dangerous_file(replace_dangerous_char($file, 'strict'));
  1678. @rename($base_work_dir.$current_path.'/'.$file,$base_work_dir.$current_path.'/'.$safe_file);
  1679. if(!DocumentManager::get_document_id($_course, $current_path.'/'.$safe_file))
  1680. {
  1681. $title=get_document_title($file);
  1682. $size = filesize($base_work_dir.$current_path.'/'.$safe_file);
  1683. $document_id = add_document($_course,$current_path.'/'.$safe_file,'file',$size,$title);
  1684. api_item_property_update($_course,TOOL_DOCUMENT,$document_id,'DocumentAdded',$user_id,$to_group_id,null,null,null,$current_session_id);
  1685. //echo $current_path.'/'.$safe_file." added!<br/>";
  1686. }
  1687. }
  1688. }
  1689. }
  1690. }
  1691. /*
  1692. ==============================================================================
  1693. DEPRECATED FUNCTIONS
  1694. ==============================================================================
  1695. */
  1696. /**
  1697. * @deprecated Use transliteration instead, it is applicable for all languages.
  1698. *
  1699. * Replaces all accentuated characters by non-accentuated characters for filenames, as
  1700. * well as special HTML characters by their HTML entity's first letter.
  1701. *
  1702. * Although this method is not absolute, it gives good results in general. It first
  1703. * transforms the string to HTML entities (&ocirc;, @oslash;, etc) then removes the
  1704. * HTML character part to result in simple characters (o, o, etc).
  1705. * In the case of special characters (out of alphabetical value) like &nbsp; and &lt;,
  1706. * it will still replace them by the first letter of the HTML entity (n, l, ...) but it
  1707. * is still an acceptable method, knowing we're filtering filenames here...
  1708. * @param string The accentuated string
  1709. * @return string The escaped string, not absolutely correct but satisfying
  1710. */
  1711. function replace_accents($string, $encoding = null) {
  1712. /*
  1713. global $charset;
  1714. $string = api_htmlentities($string,ENT_QUOTES,$charset);
  1715. $res = preg_replace("/&([a-z])[a-z]+;/i","$1",$string);
  1716. return $res;
  1717. */
  1718. return api_transliterate($string, 'x', $encoding);
  1719. }
  1720. /**
  1721. * @deprecated Use transliteration instead, it is applicable for all languages.
  1722. */
  1723. function remove_accents($string, $encoding = null) {
  1724. /*
  1725. $string = strtr ( $string, "�����������������������������������������������������", "AAAAAAaaaaaaOOOOOOooooooEEEEeeeeCcIIIIiiiiUUUUuuuuyNn");
  1726. return $string;
  1727. */
  1728. return api_transliterate($string, 'x', $encoding);
  1729. }