PageRenderTime 43ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/cms/utils/file_utils.php

http://kancms.googlecode.com/
PHP | 373 lines | 267 code | 61 blank | 45 comment | 73 complexity | b369581f4d0a957596dbfe082f6d6e40 MD5 | raw file
Possible License(s): BSD-2-Clause, GPL-2.0, LGPL-2.1
  1. <?php
  2. if( !defined("SITE_ID") ) {
  3. require_once('../accesscheck.php');
  4. }
  5. $fileUtils = new FileUtils();
  6. if( isset($_POST['action']) && $_POST['action'] == "save_file" && isset($_POST['FilePath']) ) {
  7. $fileUtils->saveFileContent( kan_fix_path($_POST['FilePath']), $_POST['EditorContent'] );
  8. }
  9. if( isset($_POST['action']) && $_POST['action'] == "show_file" && $_POST['FilePath'] ) {
  10. $content = file_get_contents( kan_fix_path($_POST['FilePath']) );
  11. $mimeType = isset($_POST['mimeType']) ? $_POST['mimeType'] : 'text/php';
  12. $content = htmlentities($content);
  13. $fileUtils->getEditorForContent($content, $mimeType);
  14. }
  15. if( isset($_POST['action']) && $_POST['action'] == "delete_file" && isset($_POST['FilePath']) ) {
  16. // check if the file can found without redirection
  17. if( file_exists($_POST['FilePath']) ) {
  18. $fileUtils->deleteFile( $_POST['FilePath'] );
  19. // redirect outside the utils folder, especially when running via ajax
  20. } else if( file_exists( kan_fix_path($_POST['FilePath']) ) ) {
  21. $fileUtils->deleteFile( kan_fix_path($_POST['FilePath']) );
  22. }
  23. }
  24. class FileUtils {
  25. public $mimeTypes = array(
  26. "js" => "text/javascript",
  27. "css" => "text/css",
  28. "php" => "text/php",
  29. "html" => "text/html",
  30. "htm" => "text/html",
  31. "xml" => "text/xml",
  32. "json" => "text/javascript"
  33. );
  34. public $webExtensions = array(
  35. "js" => "javascript",
  36. "css" => "css",
  37. "php" => "php",
  38. "html" => "html",
  39. "htm" => "html",
  40. "xml" => "xml",
  41. "gif" => "gif",
  42. "jpg" => "jpg",
  43. "png" => "png",
  44. "swf" => "swf",
  45. "json" => "json"
  46. );
  47. public function printScripts() { ?>
  48. <link type="text/css" href="../cms/utils/file_utils.css" rel="stylesheet" />
  49. <script type="text/javascript" src="../cms/utils/file_utils.js"></script>
  50. <script type="text/javascript" src="../cms/scripts/code_mirror/js/codemirror.js"></script>
  51. <?php
  52. }
  53. public function getFileEditInfo($filePath, $mimeType = 'text/php') {
  54. $file_type = is_dir($filePath) ? "Folder" : "File";
  55. if( is_writable($filePath) ) {
  56. echo "<span class='cms-file-writable'>$file_type Is Writable</span>";
  57. if( !is_dir($filePath) ) {
  58. echo " | <a href=\"javascript:file_utils.showOverlayedEditor('$filePath', '$mimeType');\">Edit File</a>";
  59. }
  60. } else {
  61. echo "<span class='cms-file-readonly'>File Is Readonly</span>";
  62. }
  63. }
  64. public function saveFileContent($filePath, $contentData) {
  65. if( is_writable($filePath) ) {
  66. $data = stripslashes($contentData); // remove possible escaped characters
  67. $data = htmlentities($data); // encode the data as HTML
  68. file_put_contents( $filePath, "" . html_entity_decode($data) . "" );
  69. }
  70. }
  71. public function generateFolderTree($folder) {
  72. if( $folder == '' || $folder == NULL ) {
  73. return;
  74. }
  75. $dirname = basename($folder);
  76. echo "<div id='dir_tree' class='dir_tree'>\n";
  77. echo "<ul class='dir_group'><li class='dir_name'>"
  78. . "<div >"
  79. . " <div class='name_col'><span>$dirname</span></div>"
  80. . " <!--<div class='options_col'><a href='#'>Add</a> | <a href='#'>Delete</a></div>--> "
  81. . "</div>";
  82. $this->traverseDirTree($folder, FALSE);
  83. echo "</li></ul>\n";
  84. echo "</div>\n"; ?>
  85. <script type="text/javascript">
  86. pageManager.addLoadEvent( file_utils.attachFolderHandlers );
  87. </script><?php
  88. }
  89. public function traverseDirTree($path = '.', $isSub = TRUE) {
  90. $handle = opendir($path);
  91. if ( $handle ) {
  92. $collapsed = ($isSub == TRUE) ? "collapsed" : "expanded";
  93. echo "<ul class='dir_group $collapsed'>";
  94. $queuedir = array();
  95. $queuefile = array();
  96. while (false !== ($file = readdir($handle))) {
  97. if (is_dir($path.$file) && $file != '.' && $file !='..')
  98. $queuedir[] = $file;
  99. else if ($file != '.' && $file !='..')
  100. $queuefile[] = $file;
  101. }
  102. sort($queuedir);
  103. sort($queuefile);
  104. $this->printSubDir($queuedir, $path);
  105. $this->printQueue($queuefile, $path);
  106. echo "</ul>";
  107. }
  108. }
  109. private function printSubDir($queue, $path) {
  110. foreach ($queue as $dir) {
  111. echo "<li class='dir_name'>"
  112. . "<div >"
  113. . " <div class='name_col'><span>$dir</span></div>"
  114. . " <!--<div class='options_col'>Add | Delete</div>-->"
  115. . "</div>";
  116. $this->traverseDirTree($path.$dir."/");
  117. echo "</li>";
  118. }
  119. }
  120. private function printQueue($queue, $path) {
  121. foreach ($queue as $file) {
  122. $filePath = $path.$file;
  123. $extension = substr($file, strrpos($file,".") + 1);
  124. // if file is writable and file type is editable
  125. if( is_writable($filePath) && array_key_exists($extension, $this->mimeTypes) ) {
  126. $mimeType = $this->mimeTypes[$extension];
  127. echo "<li class='file_name'>"
  128. . "<div class='name_col'>"
  129. . " <a href=\"javascript:file_utils.showOverlayedEditor('$filePath', '$mimeType'); \">$file</a>"
  130. . "</div>"
  131. . "<div class='options_col'>"
  132. . " <a href=\"javascript:file_utils.showOverlayedEditor('$filePath', '$mimeType'); \">Edit</a> | "
  133. . " <a href=\"#\" onclick=\"file_utils.deleteFile('$filePath', this); return false;\">Delete</a> "
  134. . "</div>"
  135. . "</li>";
  136. // if is web related document
  137. } else if( array_key_exists($extension, $this->webExtensions) ) {
  138. echo "<li class='file_name'>$file</li>";
  139. } else {
  140. //echo "<li class='file_name'>$file</li>";
  141. }
  142. }
  143. }
  144. public function deleteFile($filePath, $canRemoveDir = false) {
  145. if( file_exists($filePath) ) {
  146. if( is_dir($filePath) && $canRemoveDirr ) {
  147. $this->rmdirr($filePath);
  148. } else {
  149. unlink($filePath);
  150. }
  151. }
  152. }
  153. public function rmdirr($dirname) {
  154. // Sanity check
  155. if (!file_exists($dirname)) {
  156. return false;
  157. }
  158. // Simple delete for a file
  159. if (is_file($dirname)) {
  160. return unlink($dirname);
  161. }
  162. // Loop through the folder
  163. $dir = dir($dirname);
  164. while (false !== $entry = $dir->read()) {
  165. // Skip pointers
  166. if ($entry == '.' || $entry == '..') {
  167. continue;
  168. }
  169. // Recurse
  170. $this->rmdirr("$dirname/$entry");
  171. }
  172. // Clean up
  173. $dir->close();
  174. return rmdir($dirname);
  175. }
  176. public function getEditorForContent($content = '', $mimeType = 'text/php') {
  177. if( $content == '' ) {
  178. $content .= "<?php \n";
  179. $content .= " //TODO: your PHP code goes here\n";
  180. $content .= "?>";
  181. } ?>
  182. <div style="height: 520px; position: relative; overflow: hidden;">
  183. <textarea cols="10" rows="3" id='EditorContent' name='EditorContent' style="width: 100%; height: 100%;"><?php echo $content; ?></textarea>
  184. <script type="text/javascript">
  185. pageManager.addLoadEvent( function() {
  186. file_utils.codeEditor = CodeMirror.fromTextArea('EditorContent', {
  187. parserfile: ["parsexml.js", "parsecss.js", "tokenizejavascript.js", "parsejavascript.js", "parsehtmlmixed.js",
  188. "../contrib/php/js/tokenizephp.js", "../contrib/php/js/parsephp.js",
  189. "../contrib/php/js/parsephphtmlmixed.js"],
  190. stylesheet: ["../cms/scripts/code_mirror/css/xmlcolors.css",
  191. "../cms/scripts/code_mirror/css/jscolors.css",
  192. "../cms/scripts/code_mirror/css/csscolors.css",
  193. "../cms/scripts/code_mirror/contrib/php/css/phpcolors.css"],
  194. path: "../cms/scripts/code_mirror/js/",
  195. continuousScanning: 500,
  196. textWrapping: false
  197. });
  198. });
  199. </script>
  200. </div><?php
  201. }
  202. public function extractZipArchive($filePath, $destFolder = '') {
  203. // create object
  204. $zip = new ZipArchive() ;
  205. // open archive
  206. if ($zip->open( $destZipFile ) !== TRUE) {
  207. die ('Could not open archive');
  208. }
  209. // if the destFolder is not supplied, then we'll need to extract the file to
  210. // same directory.
  211. if( $destFolder == '') {
  212. $destFolder = dirname($filePath);
  213. }
  214. // extract contents to destination directory
  215. $zip->extractTo($destFolder);
  216. // close archive
  217. $zip->close();
  218. }
  219. /**
  220. * Copy file or folder from source to destination, it can do
  221. * recursive copy as well and is very smart
  222. * It recursively creates the dest file or directory path if there weren't exists
  223. * Situtaions :
  224. * - Src:/home/test/file.txt ,Dst:/home/test/b ,Result:/home/test/b -> If source was file copy file.txt name with b as name to destination
  225. * - Src:/home/test/file.txt ,Dst:/home/test/b/ ,Result:/home/test/b/file.txt -> If source was file Creates b directory if does not exsits and copy file.txt into it
  226. * - Src:/home/test ,Dst:/home/ ,Result:/home/test/** -> If source was directory copy test directory and all of its content into dest
  227. * - Src:/home/test/ ,Dst:/home/ ,Result:/home/**-> if source was direcotry copy its content to dest
  228. * - Src:/home/test ,Dst:/home/test2 ,Result:/home/test2/** -> if source was directoy copy it and its content to dest with test2 as name
  229. * - Src:/home/test/ ,Dst:/home/test2 ,Result:->/home/test2/** if source was directoy copy it and its content to dest with test2 as name
  230. * @todo
  231. * - Should have rollback technique so it can undo the copy when it wasn't successful
  232. * - Auto destination technique should be possible to turn off
  233. * - Supporting callback function
  234. * - May prevent some issues on shared enviroments : http://us3.php.net/umask
  235. * @param $source //file or folder
  236. * @param $dest ///file or folder
  237. * @param $options //folderPermission,filePermission
  238. * @return boolean
  239. */
  240. public function smartCopy($source, $dest, $options=array('folderPermission'=>0755,'filePermission'=>0755))
  241. {
  242. $result=false;
  243. if (is_file($source)) {
  244. if ($dest[strlen($dest)-1]=='/') {
  245. if (!file_exists($dest)) {
  246. cmfcDirectory::makeAll($dest,$options['folderPermission'],true);
  247. }
  248. $__dest=$dest."/".basename($source);
  249. } else {
  250. $__dest=$dest;
  251. }
  252. $result=copy($source, $__dest);
  253. chmod($__dest,$options['filePermission']);
  254. } elseif(is_dir($source)) {
  255. if ($dest[strlen($dest)-1]=='/') {
  256. if ($source[strlen($source)-1]=='/') {
  257. //Copy only contents
  258. } else {
  259. //Change parent itself and its contents
  260. $dest=$dest.basename($source);
  261. @mkdir($dest);
  262. chmod($dest,$options['filePermission']);
  263. }
  264. } else {
  265. if ($source[strlen($source)-1]=='/') {
  266. //Copy parent directory with new name and all its content
  267. @mkdir($dest,$options['folderPermission']);
  268. chmod($dest,$options['filePermission']);
  269. } else {
  270. //Copy parent directory with new name and all its content
  271. @mkdir($dest,$options['folderPermission']);
  272. chmod($dest,$options['filePermission']);
  273. }
  274. }
  275. $dirHandle=opendir($source);
  276. while($file=readdir($dirHandle))
  277. {
  278. if($file!="." && $file!="..")
  279. {
  280. if(!is_dir($source."/".$file)) {
  281. $__dest=$dest."/".$file;
  282. } else {
  283. $__dest=$dest."/".$file;
  284. }
  285. //echo "$source/$file ||| $__dest<br />";
  286. $result = $this->smartCopy($source."/".$file, $__dest, $options);
  287. }
  288. }
  289. closedir($dirHandle);
  290. } else {
  291. $result=false;
  292. }
  293. return $result;
  294. }
  295. public function encodeUrlParam ( $string ) {
  296. $string = trim($string);
  297. if ( ctype_digit($string) ) {
  298. return $string;
  299. } else {
  300. // replace accented chars
  301. $accents = '/&([A-Za-z]{1,2})(grave|acute|circ|cedil|uml|lig);/';
  302. $string_encoded = htmlentities($string,ENT_NOQUOTES,'UTF-8');
  303. $string = preg_replace($accents,'$1',$string_encoded);
  304. // clean out the rest
  305. $replace = array('([\40])','([^a-zA-Z0-9-])','(-{2,})');
  306. $with = array('-','','-');
  307. $string = preg_replace($replace,$with,$string);
  308. }
  309. return strtolower($string);
  310. }
  311. }
  312. ?>