| [ Index ] |
|
Code source de b2evolution 2.1.0-beta |
1 <?php 2 /** 3 * This file implements various File handling functions. 4 * 5 * This file is part of the evoCore framework - {@link http://evocore.net/} 6 * See also {@link http://sourceforge.net/projects/evocms/}. 7 * 8 * @copyright (c)2003-2007 by Francois PLANQUE - {@link http://fplanque.net/} 9 * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}. 10 * 11 * {@internal License choice 12 * - If you have received this file as part of a package, please find the license.txt file in 13 * the same folder or the closest folder above for complete license terms. 14 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/) 15 * then you must choose one of the following licenses before using the file: 16 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php 17 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php 18 * }} 19 * 20 * {@internal Open Source relicensing agreement: 21 * Daniel HAHLER grants Francois PLANQUE the right to license 22 * Daniel HAHLER's contributions to this file and the b2evolution project 23 * under any OSI approved OSS license (http://www.opensource.org/licenses/). 24 * }} 25 * 26 * @package evocore 27 * 28 * {@internal Below is a list of authors who have contributed to design/coding of this file: }} 29 * @author blueyed: Daniel HAHLER. 30 * @author fplanque: Francois PLANQUE. 31 * 32 * @version $Id: _file.funcs.php,v 1.3 2007/11/01 04:31:25 fplanque Exp $ 33 */ 34 if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' ); 35 36 37 /** 38 * Converts bytes to readable bytes/kb/mb/gb, like "12.45mb" 39 * 40 * @param integer bytes 41 * @return string bytes made readable 42 */ 43 function bytesreadable( $bytes ) 44 { 45 static $types = NULL; 46 47 if( empty($bytes) ) 48 { 49 return T_('Empty'); 50 } 51 52 if( !isset($types) ) 53 { // generate once: 54 $types = array( 55 0 => array( 'abbr' => /* TRANS: Abbr. for "Bytes" */ T_('B.'), 'text' => T_('Bytes') ), 56 1 => array( 'abbr' => /* TRANS: Abbr. for "Kilobytes" */ T_('KB'), 'text' => T_('Kilobytes') ), 57 2 => array( 'abbr' => /* TRANS: Abbr. for Megabytes */ T_('MB'), 'text' => T_('Megabytes') ), 58 3 => array( 'abbr' => /* TRANS: Abbr. for Gigabytes */ T_('GB'), 'text' => T_('Gigabytes') ), 59 4 => array( 'abbr' => /* TRANS: Abbr. for Terabytes */ T_('TB'), 'text' => T_('Terabytes') ) 60 ); 61 } 62 63 for( $i = 0; $bytes > 1024; $i++ ) 64 { 65 $bytes /= 1024; 66 } 67 68 // Format to maximum of 1 digit after . 69 $precision = max( 0, ( 1 -floor(log($bytes)/log(10))) ); 70 $r = sprintf( '%.'.$precision.'f', $bytes ); 71 72 $r .= ' <abbr title="'.$types[$i]['text'].'">'; 73 $r .= $types[$i]['abbr']; 74 $r .= '</abbr>'; 75 76 // $r .= ' '.$precision; 77 78 return $r; 79 } 80 81 82 /** 83 * Get an array of all directories (and optionally files) of a given 84 * directory, either flat (one-dimensional array) or multi-dimensional (then 85 * dirs are the keys and hold subdirs/files). 86 * 87 * Note: there is no ending slash on dir names returned. 88 * 89 * @param string the path to start 90 * @param boolean include files (not only directories) 91 * @param boolean include directories (not the directory itself!) 92 * @param boolean flat (return an one-dimension-array) 93 * @param boolean Recurse into subdirectories? 94 * @param boolean Get the basename only. 95 * @return false|array false if the first directory could not be accessed, 96 * array of entries otherwise 97 */ 98 function get_filenames( $path, $inc_files = true, $inc_dirs = true, $flat = true, $recurse = true, $basename = false ) 99 { 100 $r = array(); 101 102 $path = trailing_slash( $path ); 103 104 if( $dir = @opendir($path) ) 105 { 106 while( ( $file = readdir($dir) ) !== false ) 107 { 108 if( $file == '.' || $file == '..' ) 109 { 110 continue; 111 } 112 if( is_dir($path.$file) ) 113 { 114 if( $flat ) 115 { 116 if( $inc_dirs ) 117 { 118 $r[] = $basename ? $file : $path.$file; 119 } 120 if( $recurse ) 121 { 122 $rSub = get_filenames( $path.$file, $inc_files, $inc_dirs, $flat, $recurse, $basename ); 123 if( $rSub ) 124 { 125 $r = array_merge( $r, $rSub ); 126 } 127 } 128 } 129 else 130 { 131 $r[$file] = get_filenames( $path.$file, $inc_files, $inc_dirs, $flat, $recurse, $basename ); 132 } 133 } 134 elseif( $inc_files ) 135 { 136 $r[] = $basename ? $file : $path.$file; 137 } 138 } 139 closedir($dir); 140 } 141 else 142 { 143 return false; 144 } 145 146 return $r; 147 } 148 149 150 /** 151 * Get a list of available admin skins. 152 * 153 * This checks if there's a _adminUI.class.php in there. 154 * 155 * @return array List of directory names that hold admin skins or false, if the admin skins driectory does not exist. 156 */ 157 function get_admin_skins() 158 { 159 global $adminskins_path, $admin_subdir, $adminskins_subdir; 160 161 $dirs_in_adminskins_dir = get_filenames( $adminskins_path, false, true, true, false, true ); 162 163 if( $dirs_in_adminskins_dir === false ) 164 { 165 return false; 166 } 167 168 $r = array(); 169 if( $dirs_in_adminskins_dir ) 170 { 171 foreach( $dirs_in_adminskins_dir as $l_dir ) 172 { 173 if( !file_exists($adminskins_path.$l_dir.'/_adminUI.class.php') ) 174 { 175 continue; 176 } 177 $r[] = $l_dir; 178 } 179 } 180 return $r; 181 } 182 183 184 if( ! function_exists('fnmatch') ) 185 { 186 /** 187 * A replacement for fnmatch() which needs PHP 4.3 and a POSIX compliant system (Windows is not). 188 * 189 * @author jk at ricochetsolutions dot com {@link http://php.net/manual/function.fnmatch.php#71725} 190 */ 191 function fnmatch($pattern, $string) 192 { 193 return preg_match( '#^'.strtr(preg_quote($pattern, '#'), array('\*' => '.*', '\?' => '.')).'$#i', $string); 194 } 195 } 196 197 198 /** 199 * Get size of a directory, including anything (especially subdirs) in there. 200 * 201 * @param string the dir's full path 202 */ 203 function get_dirsize_recursive( $path ) 204 { 205 $files = get_filenames( $path, true, false ); 206 $total = 0; 207 208 foreach( $files as $lFile ) 209 { 210 $total += filesize($lFile); 211 } 212 213 return $total; 214 } 215 216 217 /** 218 * Deletes a dir recursively, wiping out all subdirectories!! 219 * 220 * @param string the dir 221 */ 222 function rmdir_r( $path ) 223 { 224 $path = trailing_slash( $path ); 225 // echo "<br>rmdir_r($path)"; 226 227 if( $dir = @opendir($path) ) 228 { 229 while( ( $file = readdir($dir) ) !== false ) 230 { 231 if( $file == '.' || $file == '..' ) 232 { 233 continue; 234 } 235 236 $adfp_filepath = $path.$file; 237 238 // echo "<br> - $os_filepath "; 239 240 if( is_dir( $adfp_filepath ) ) 241 { 242 // echo 'D'; 243 rmdir_r( $adfp_filepath ); 244 } 245 else 246 { 247 //echo 'F'; 248 @unlink( $adfp_filepath ); 249 } 250 } 251 closedir($dir); 252 253 @rmdir( $path ); 254 } 255 } 256 257 258 /** 259 * Get the size of an image file 260 * 261 * @param string absolute file path 262 * @param string what property/format to get: 'width', 'height', 'widthxheight', 263 * 'type', 'string' (as for img tags), else 'widthheight' (array) 264 * @return mixed false if no image, otherwise what was requested through $param 265 */ 266 function imgsize( $path, $param = 'widthheight' ) 267 { 268 /** 269 * Cache image sizes 270 */ 271 global $cache_imgsize; 272 273 if( isset($cache_imgsize[$path]) ) 274 { 275 $size = $cache_imgsize[$path]; 276 } 277 elseif( !($size = @getimagesize( $path )) ) 278 { 279 return false; 280 } 281 else 282 { 283 $cache_imgsize[$path] = $size; 284 } 285 286 if( $param == 'width' ) 287 { 288 return $size[0]; 289 } 290 elseif( $param == 'height' ) 291 { 292 return $size[1]; 293 } 294 elseif( $param == 'widthxheight' ) 295 { 296 return $size[0].'x'.$size[1]; 297 } 298 elseif( $param == 'type' ) 299 { 300 switch( $size[1] ) 301 { 302 case 1: return 'gif'; 303 case 2: return 'jpg'; 304 case 3: return 'png'; 305 case 4: return 'swf'; 306 default: return 'unknown'; 307 } 308 } 309 elseif( $param == 'string' ) 310 { 311 return $size[3]; 312 } 313 else 314 { // default: 'widthheight' 315 return array( $size[0], $size[1] ); 316 } 317 } 318 319 320 /** 321 * Add a trailing slash, if none present 322 * 323 * @param string the path/url 324 * @return string the path/url with trailing slash 325 */ 326 function trailing_slash( $path ) 327 { 328 if( empty($path) || substr( $path, -1 ) == '/' ) 329 { 330 return $path; 331 } 332 else 333 { 334 return $path.'/'; 335 } 336 } 337 338 339 /** 340 * Remove trailing slash, if present 341 * 342 * @param string the path/url 343 * @return string the path/url without trailing slash 344 */ 345 function no_trailing_slash( $path ) 346 { 347 if( substr( $path, -1 ) == '/' ) 348 { 349 return substr( $path, 0, strlen( $path ) ); 350 } 351 else 352 { 353 return $path; 354 } 355 } 356 357 358 /** 359 * Returns canonicalized pathname of a directory + ending slash 360 * 361 * @param string absolute path to be reduced ending with slash 362 * @return string absolute reduced path, slash terminated or NULL if the path doesn't exist 363 */ 364 function get_canonical_path( $ads_path ) 365 { 366 // Remove windows backslashes: 367 $ads_path = str_replace( '\\', '/', $ads_path ); 368 369 // Make sure there's a trailing slash 370 $ads_path = trailing_slash($ads_path); 371 372 $ads_path = str_replace( '//', '/', $ads_path ); 373 $ads_path = str_replace( '/./', '/', $ads_path ); 374 while( ($ads_realpath = preg_replace( '#(^|/)([^/^.]+)/\.\./#', '$1', $ads_path )) != $ads_path ) 375 { // While we find /../ back references to dereference... 376 // echo '*'; 377 $ads_path = $ads_realpath; 378 } 379 380 // pre_dump( 'get_canonical_path()', $ads_path, $ads_realpath ); 381 382 if( strpos( $ads_realpath, '..' ) !== false ) 383 { // Path malformed: 384 return NULL; 385 } 386 387 return $ads_realpath; 388 } 389 390 391 /** 392 * Returns canonicalized absolute pathname as with realpath(), except it will 393 * also translate paths that don't exist on the system. 394 * 395 * @deprecated overly complex 396 * @todo remove 397 * 398 * @param string the path to be translated 399 * @return array [0] = the translated path (with trailing slash); [1] = TRUE|FALSE (path exists?) 400 */ 401 function check_canonical_path( $path ) 402 { 403 $path = str_replace( '\\', '/', $path ); 404 $pwd = realpath( $path ); 405 406 if( !empty($pwd) ) 407 { // path exists 408 $pwd = str_replace( '\\', '/', $pwd); 409 if( substr( $pwd, -1 ) !== '/' ) 410 { 411 $pwd .= '/'; 412 } 413 return array( $pwd, true ); 414 } 415 else 416 { // no realpath 417 $pwd = ''; 418 $strArr = preg_split( '#/#', $path, -1, PREG_SPLIT_NO_EMPTY ); 419 $pwdArr = array(); 420 $j = 0; 421 for( $i = 0; $i < count($strArr); $i++ ) 422 { 423 if( $strArr[$i] != '..' ) 424 { 425 if( $strArr[$i] != '.' ) 426 { 427 $pwdArr[$j] = $strArr[$i]; 428 $j++; 429 } 430 } 431 else 432 { 433 array_pop( $pwdArr ); 434 $j--; 435 } 436 } 437 438 $r_path = implode('/', $pwdArr).'/'; 439 440 if( strpos( ltrim($path), '/' ) === 0 ) 441 { // There was at least one slash at the beginning 442 $r_path = '/'.$r_path; 443 } 444 return array( $r_path, false ); 445 } 446 } 447 448 449 /** 450 * Check for valid filename and extension of the filename (no path allowed). (MB) 451 * 452 * @uses $FiletypeCache, $settings or $force_regexp_filename form _advanced.php 453 * 454 * @param string filename to test 455 * @param boolean 456 * @return nothing if the filename is valid according to the regular expression and the extension too, error message if not 457 */ 458 function validate_filename( $filename, $allow_locked_filetypes = false ) 459 { 460 global $Settings, $force_regexp_filename; 461 462 // Check filename 463 if( $force_regexp_filename ) 464 { // Use the regexp from _advanced.php 465 if( !preg_match( ':'.str_replace( ':', '\:', $force_regexp_filename ).':', $filename ) ) 466 { // Invalid filename 467 return sprintf( T_('«%s» is not a valid filename.'), $filename ); 468 } 469 } 470 else 471 { // Use the regexp from SETTINGS 472 if( !preg_match( ':'.str_replace( ':', '\:', $Settings->get( 'regexp_filename' ) ).':', $filename ) ) 473 { // Invalid filename 474 return sprintf( T_('«%s» is not a valid filename.'), $filename ); 475 } 476 } 477 478 // Check extension filename 479 if( preg_match( '#\.([a-zA-Z0-9\-_]+)$#', $filename, $match ) ) 480 { // Filename has a valid extension 481 $FiletypeCache = & get_Cache( 'FiletypeCache' ); 482 if( $Filetype = & $FiletypeCache->get_by_extension( strtolower( $match[1] ) , false ) ) 483 { 484 if( $Filetype->allowed || $allow_locked_filetypes ) 485 { // Filename has an unlocked extension or we allow locked extensions 486 return; 487 } 488 else 489 { // Filename hasn't an allowed extension 490 return sprintf( T_('«%s» is a locked extension.'), htmlentities($match[1]) ); 491 } 492 } 493 else 494 { // Filename hasn't an allowed extension 495 return sprintf( T_('«%s» has an unrecognized extension.'), $filename ); 496 } 497 } 498 else 499 { // Filename hasn't a valid extension 500 return sprintf( T_('«%s» has not a valid extension.'), $filename ); 501 } 502 } 503 504 505 /** 506 * Check for valid dirname (no path allowed). ( MB ) 507 * 508 * @uses $Settings or $force_regexp_dirname form _advanced.php 509 * @param string dirname to test 510 * @return nothing if the dirname is valid according to the regular expression, error message if not 511 */ 512 function validate_dirname( $dirname ) 513 { 514 global $Settings, $force_regexp_dirname; 515 516 if( !empty( $force_regexp_dirname ) ) 517 { // Use the regexp from _advanced.php 518 if( preg_match( ':'.str_replace( ':', '\:', $force_regexp_dirname ).':', $dirname ) ) 519 { // Valid dirname 520 return; 521 } 522 else 523 { // Invalid filename 524 return sprintf( T_('«%s» is not a valid directory name.'), $dirname ); 525 } 526 } 527 else 528 { // Use the regexp from SETTINGS 529 if( preg_match( ':'.str_replace( ':', '\:', $Settings->get( 'regexp_dirname' ) ).':', $dirname ) ) 530 { // Valid dirname 531 return; 532 } 533 else 534 { // Invalid dirname 535 return sprintf( T_('«%s» is not a valid directory name.'), $dirname ); 536 } 537 } 538 } 539 540 541 /** 542 * Return the path without the leading {@link $basepath}, or if not 543 * below {@link $basepath}, just the basename of it. 544 * 545 * Do not use this for file handling. but "just" displaying! 546 * 547 * @param string Path 548 * @return string Relative path or even base name. 549 * NOTE: when $debug, the real path gets appended. 550 */ 551 function rel_path_to_base( $path ) 552 { 553 global $basepath, $debug; 554 555 // Remove basepath prefix: 556 if( preg_match( '~^('.preg_quote($basepath, '~').')(.+)$~', $path, $match ) ) 557 { 558 $r = $match[2]; 559 } 560 else 561 { 562 $r = basename($path).( is_dir($path) ? '/' : '' ); 563 } 564 565 if( $debug ) 566 { 567 $r .= ' [DEBUG: '.$path.']'; 568 } 569 570 return $r; 571 } 572 573 574 /** 575 * Get the directories of the supplied path as a radio button tree. 576 * 577 * @todo fp> Make a DirTree class (those static hacks suck) 578 * 579 * @param FileRoot A single root or NULL for all available. 580 * @param string the root path to use 581 * @param boolean add radio buttons ? 582 * @param string used by recursion 583 * @return string 584 */ 585 function get_directory_tree( $Root = NULL, $ads_full_path = NULL, $ads_selected_full_path = NULL, $radios = false, $rds_rel_path = NULL, $is_recursing = false ) 586 { 587 static $js_closeClickIDs; // clickopen IDs that should get closed 588 static $instance_ID = 0; 589 590 if( ! $is_recursing ) 591 { // This is not a recursive call (yet): 592 // Init: 593 $instance_ID++; 594 $js_closeClickIDs = array(); 595 $ret = '<ul class="clicktree">'; 596 } 597 else 598 { 599 $ret = ''; 600 } 601 602 // ________________________ Handle Roots ______________________ 603 if( $Root === NULL ) 604 { // We want to list all roots: 605 $FileRootCache = & get_Cache( 'FileRootCache' ); 606 $_roots = $FileRootCache->get_available_FileRoots(); 607 608 foreach( $_roots as $l_Root ) 609 { 610 $subR = get_directory_tree( $l_Root, $l_Root->ads_path, $ads_selected_full_path, $radios, '', true ); 611 if( !empty( $subR['string'] ) ) 612 { 613 $ret .= '<li>'.$subR['string'].'</li>'; 614 } 615 } 616 } 617 else 618 { 619 // We'll go through files in current dir: 620 $Nodelist = & new Filelist( $Root, trailing_slash($ads_full_path) ); 621 $Nodelist->load(); 622 $Nodelist->sort( 'name' ); 623 $has_sub_dirs = $Nodelist->count_dirs(); 624 625 $id_path = 'id_path_'.$instance_ID.md5( $ads_full_path ); 626 627 $r['string'] = '<span class="folder_in_tree">'; 628 629 // echo '<br />'. $rds_rel_path . ' - '.$ads_full_path; 630 if( $ads_full_path == $ads_selected_full_path ) 631 { // This is the current open path 632 $r['opened'] = true; 633 } 634 else 635 { 636 $r['opened'] = NULL; 637 } 638 639 640 if( $radios ) 641 { // Optional radio input to select this path: 642 $root_and_path = format_to_output( implode( '::', array($Root->ID, $rds_rel_path) ), 'formvalue' ); 643 644 $r['string'] .= '<input type="radio" name="root_and_path" value="'.$root_and_path.'" id="radio_'.$id_path.'"'; 645 646 if( $r['opened'] ) 647 { // This is the current open path 648 $r['string'] .= ' checked="checked"'; 649 } 650 651 //.( ! $has_sub_dirs ? ' style="margin-right:'.get_icon( 'collapse', 'size', array( 'size' => 'width' ) ).'px"' : '' ) 652 $r['string'] .= ' /> '; 653 } 654 655 // Folder Icon + Name: 656 $url = regenerate_url( 'root,path', 'root='.$Root->ID.'&path='.$rds_rel_path ); 657 $label = action_icon( T_('Open this directory in the file manager'), 'folder', $url ) 658 .'<a href="'.$url.'" 659 title="'.T_('Open this directory in the file manager').'">' 660 .( empty($rds_rel_path) ? $Root->name : basename( $ads_full_path ) ) 661 .'</a>'; 662 663 // Handle potential subdir: 664 if( ! $has_sub_dirs ) 665 { // No subirs 666 $r['string'] .= get_icon( 'expand', 'noimg', array( 'class'=>'' ) ).' '.$label.'</span>'; 667 } 668 else 669 { // Process subdirs 670 $r['string'] .= get_icon( 'collapse', 'imgtag', array( 'onclick' => 'toggle_clickopen(\''.$id_path.'\');', 671 'id' => 'clickimg_'.$id_path 672 ) ) 673 .' '.$label.'</span>' 674 .'<ul class="clicktree" id="clickdiv_'.$id_path.'">'."\n"; 675 676 while( $l_File = & $Nodelist->get_next( 'dir' ) ) 677 { 678 $rSub = get_directory_tree( $Root, $l_File->get_full_path(), $ads_selected_full_path, $radios, $l_File->get_rdfs_rel_path(), true ); 679 680 if( $rSub['opened'] ) 681 { // pass opened status on, if given 682 $r['opened'] = $rSub['opened']; 683 } 684 685 $r['string'] .= '<li>'.$rSub['string'].'</li>'; 686 } 687 688 if( !$r['opened'] ) 689 { 690 $js_closeClickIDs[] = $id_path; 691 } 692 $r['string'] .= '</ul>'; 693 } 694 695 if( $is_recursing ) 696 { 697 return $r; 698 } 699 else 700 { 701 $ret .= '<li>'.$r['string'].'</li>'; 702 } 703 } 704 705 if( ! $is_recursing ) 706 { 707 $ret .= '</ul>'; 708 709 if( ! empty($js_closeClickIDs) ) 710 { // there are IDs of checkboxes that we want to close 711 $ret .= "\n".'<script type="text/javascript">toggle_clickopen( \'' 712 .implode( "' );\ntoggle_clickopen( '", $js_closeClickIDs ) 713 ."' );\n</script>"; 714 } 715 } 716 717 return $ret; 718 } 719 720 721 /** 722 * Create a directory recursively. 723 * 724 * NOTE: this can be done with the "recursive" param in PHP5 725 * 726 * @todo dh> simpletests for this (especially for open_basedir) 727 * 728 * @param string directory name 729 * @param integer permissions 730 * @return boolean 731 */ 732 function mkdir_r( $dirName, $chmod = NULL ) 733 { 734 if( is_dir($dirName) ) 735 { // already exists: 736 return true; 737 } 738 739 if( $chmod === NULL ) 740 { 741 global $Settings; 742 $chmod = $Settings->get('fm_default_chmod_dir'); 743 } 744 745 /* 746 if( version_compare(PHP_VERSION, 5, '>=') ) 747 { 748 return mkdir( $dirName, $chmod, true ); 749 } 750 */ 751 752 $dirName = trailing_slash($dirName); 753 754 $parts = array_reverse( explode('/', $dirName) ); 755 $loop_dir = $dirName; 756 $create_dirs = array(); 757 foreach($parts as $part) 758 { 759 if( ! strlen($part) ) 760 { 761 continue; 762 } 763 // We want to create this dir: 764 array_unshift($create_dirs, $loop_dir); 765 $loop_dir = substr($loop_dir, 0, 0 - strlen($part)-1); 766 767 if( is_dir($loop_dir) ) 768 { // found existing dir: 769 foreach($create_dirs as $loop_dir ) 770 { 771 if( ! @mkdir($loop_dir, octdec($chmod)) ) 772 { 773 return false; 774 } 775 } 776 return true; 777 } 778 } 779 return true; 780 } 781 782 783 /* 784 * $Log: _file.funcs.php,v $ 785 * Revision 1.3 2007/11/01 04:31:25 fplanque 786 * Better root browsing (roots are groupes by type + only one root is shown at a time) 787 * 788 * Revision 1.2 2007/11/01 03:36:09 fplanque 789 * fixed file sorting in tree 790 * 791 * Revision 1.1 2007/06/25 10:59:54 fplanque 792 * MODULES (refactored MVC) 793 * 794 * Revision 1.53 2007/04/26 00:11:10 fplanque 795 * (c) 2007 796 * 797 * Revision 1.52 2007/03/20 07:43:44 fplanque 798 * .evocache cleanup triggers 799 * 800 * Revision 1.51 2007/03/04 05:24:52 fplanque 801 * some progress on the toolbar menu 802 * 803 * Revision 1.50 2007/01/25 03:37:14 fplanque 804 * made bytesreadable() really readable for average people. 805 * 806 * Revision 1.49 2007/01/24 13:44:56 fplanque 807 * cleaned up upload 808 * 809 * Revision 1.48 2007/01/24 12:18:25 blueyed 810 * Fixed PHP-fnmatch() implementation (for Windows) 811 * 812 * Revision 1.47 2007/01/24 06:31:09 fplanque 813 * doc 814 * 815 * Revision 1.46 2007/01/24 05:57:55 fplanque 816 * cleanup / settings 817 * 818 * Revision 1.45 2007/01/24 03:45:29 fplanque 819 * decrap / removed a lot of bloat... 820 * 821 * Revision 1.44 2007/01/23 22:30:14 fplanque 822 * empty icons cleanup 823 * 824 * Revision 1.43 2006/12/22 01:17:37 fplanque 825 * fix 826 * 827 * Revision 1.42 2006/12/22 01:09:30 fplanque 828 * cleanup 829 * 830 * Revision 1.41 2006/12/22 00:58:02 fplanque 831 * fix 832 * 833 * Revision 1.39 2006/12/22 00:50:33 fplanque 834 * improved path cleaning 835 * 836 * Revision 1.38 2006/12/22 00:17:05 fplanque 837 * got rid of dirty globals 838 * some refactoring 839 * 840 * Revision 1.36 2006/12/14 23:02:43 blueyed 841 * Fixed handling of "0" as directory 842 * 843 * Revision 1.35 2006/12/14 22:13:05 blueyed 844 * mkdir_r(): implemented suggestion from Francois, not tested with open_basedir yet 845 * 846 * Revision 1.34 2006/12/14 01:53:10 fplanque 847 * doc 848 * 849 * Revision 1.33 2006/12/14 00:58:17 blueyed 850 * mkdir_r(): fixed permissions with mkdir() call and handle open_basedir restrictions 851 * 852 * Revision 1.32 2006/12/14 00:42:04 fplanque 853 * A little bit of windows detection / normalization 854 * 855 * Revision 1.31 2006/12/14 00:07:43 blueyed 856 * Fixed mkdir_r 857 * 858 * Revision 1.30 2006/12/13 22:26:27 fplanque 859 * This has reached the point of a functional eternal cache. 860 * TODO: handle cache on delete, upload/overwrite, rename, move, copy. 861 * 862 * Revision 1.29 2006/12/13 21:23:56 fplanque 863 * .evocache folders / saving of thumbnails 864 * 865 * Revision 1.28 2006/12/07 20:03:32 fplanque 866 * Woohoo! File editing... means all skin editing. 867 * 868 * Revision 1.27 2006/12/07 15:23:42 fplanque 869 * filemanager enhanced, refactored, extended to skins directory 870 * 871 * Revision 1.26 2006/12/03 18:20:29 blueyed 872 * Added mkdir_r() 873 * 874 * Revision 1.25 2006/11/24 18:27:24 blueyed 875 * Fixed link to b2evo CVS browsing interface in file docblocks 876 */ 877 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Thu Nov 29 23:58:50 2007 | par Balluche grâce à PHPXref 0.7 |
|