[ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
1 <?php 2 /**************************************************************************\ 3 * eGroupWare API - VFS base class * 4 * This file written by Jason Wies (Zone) <zone@phpgroupware.org> * 5 * This class handles file/dir access for eGroupWare * 6 * Copyright (C) 2001 Jason Wies * 7 * -------------------------------------------------------------------------* 8 * This library is part of the eGroupWare API * 9 * http://www.egroupware.org/api * 10 * ------------------------------------------------------------------------ * 11 * This library is free software; you can redistribute it and/or modify it * 12 * under the terms of the GNU Lesser General Public License as published by * 13 * the Free Software Foundation; either version 2.1 of the License, * 14 * or any later version. * 15 * This library is distributed in the hope that it will be useful, but * 16 * WITHOUT ANY WARRANTY; without even the implied warranty of * 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 18 * See the GNU Lesser General Public License for more details. * 19 * You should have received a copy of the GNU Lesser General Public License * 20 * along with this library; if not, write to the Free Software Foundation, * 21 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 22 \**************************************************************************/ 23 24 /* $Id: class.vfs.inc.php 20295 2006-02-15 12:31:25Z $ */ 25 26 if (empty ($GLOBALS['egw_info']['server']['file_repository'])) 27 { 28 $GLOBALS['egw_info']['server']['file_repository'] = 'sql'; 29 } 30 31 /* Relative defines. Used mainly by getabsolutepath () */ 32 define ('RELATIVE_ROOT', 1); 33 define ('RELATIVE_USER', 2); 34 define ('RELATIVE_CURR_USER', 4); 35 define ('RELATIVE_USER_APP', 8); 36 define ('RELATIVE_PATH', 16); 37 define ('RELATIVE_NONE', 32); 38 define ('RELATIVE_CURRENT', 64); 39 define ('VFS_REAL', 1024); 40 define ('RELATIVE_ALL', RELATIVE_PATH); 41 42 /* These are used in calls to add_journal (), and allow journal messages to be more standard */ 43 define ('VFS_OPERATION_CREATED', 1); 44 define ('VFS_OPERATION_EDITED', 2); 45 define ('VFS_OPERATION_EDITED_COMMENT', 4); 46 define ('VFS_OPERATION_COPIED', 8); 47 define ('VFS_OPERATION_MOVED', 16); 48 define ('VFS_OPERATION_DELETED', 32); 49 50 /** 51 * * helper class for path_parts 52 * * 53 */ 54 class path_class 55 { 56 var $mask; 57 var $outside; 58 var $fake_full_path; 59 var $fake_leading_dirs; 60 var $fake_extra_path; 61 var $fake_name; 62 var $real_full_path; 63 var $real_leading_dirs; 64 var $real_extra_path; 65 var $real_name; 66 var $fake_full_path_clean; 67 var $fake_leading_dirs_clean; 68 var $fake_extra_path_clean; 69 var $fake_name_clean; 70 var $real_full_path_clean; 71 var $real_leading_dirs_clean; 72 var $real_extra_path_clean; 73 var $real_name_clean; 74 } 75 76 /** 77 * * Base class for Virtual File System classes 78 * * 79 * * @author Zone 80 */ 81 class vfs_shared 82 { 83 /* 84 * All VFS classes must have some form of 'linked directories'. 85 * Linked directories allow an otherwise disparate "real" directory 86 * to be linked into the "virtual" filesystem. See make_link(). 87 */ 88 var $linked_dirs = array (); 89 90 /* 91 * All VFS classes need to support the access control in some form 92 * (see acl_check()). There are times when applications will need 93 * to explictly disable access checking, for example when creating a 94 * user's home directory for the first time or when the admin is 95 * performing maintanence. When override_acl is set, any access 96 * checks must return True. 97 */ 98 var $override_acl = 0; 99 100 /* 101 * The current relativity. See set_relative() and get_relative(). 102 */ 103 var $relative; 104 105 /* 106 * Implementation dependant 'base real directory'. It is not required 107 * that derived classes use $basedir, but some of the shared functions 108 * below rely on it, so those functions will need to be overload if 109 * basedir isn't appropriate for a particular backend. 110 */ 111 var $basedir; 112 113 /* 114 * Fake base directory. Only the administrator should change this. 115 */ 116 var $fakebase = '/home'; 117 118 /* 119 * All derived classes must store certain information about each 120 * location. The attributes in the 'attributes' array represent 121 * the minimum attributes that must be stored. Derived classes 122 * should add to this array any custom attributes. 123 * 124 * Not all of the attributes below are appropriate for all backends. 125 * Those that don't apply can be replaced by dummy values, ie. '' or 0. 126 */ 127 var $attributes = array( 128 'file_id', /* Integer. Unique to each location */ 129 'owner_id', /* phpGW account_id of owner */ 130 'createdby_id', /* phpGW account_id of creator */ 131 'modifiedby_id',/* phpGW account_id of who last modified */ 132 'created', /* Datetime created, in SQL format */ 133 'modified', /* Datetime last modified, in SQL format */ 134 'size', /* Size in bytes */ 135 'mime_type', /* Mime type. 'Directory' for directories */ 136 'comment', /* User-supplied comment. Can be empty */ 137 'app', /* Name of phpGW application responsible for location */ 138 'directory', /* Directory location is in */ 139 'name', /* Name of file/directory */ 140 'link_directory', /* Directory location is linked to, if any */ 141 'link_name', /* Name location is linked to, if any */ 142 'version', /* Version of file. May be 0 */ 143 ); 144 145 /** 146 * * constructor 147 * * 148 * * All derived classes should call this function in their 149 * constructor ($this->vfs_shared()) 150 */ 151 function vfs_shared () 152 { 153 } 154 155 /* 156 * Definitions for functions that every derived 157 * class must have, and suggestions for private functions 158 * to completement the public ones. The prototypes for 159 * the public functions need to be uniform for all 160 * classes. Of course, each derived class should overload these 161 * functions with their own version. 162 */ 163 164 /* 165 * Journal functions. 166 * 167 * See also: VFS_OPERATION_* defines 168 * 169 * Overview: 170 * Each action performed on a location 171 * should be recorded, in both machine and human 172 * readable format. 173 * 174 * PRIVATE functions (suggested examples only, not mandatory): 175 * 176 * add_journal - Add journal entry 177 * flush_journal - Clear all journal entries for a location 178 * 179 * PUBLIC functions (mandatory): 180 * 181 * get_journal - Get journal entries for a location 182 */ 183 184 /* Private, suggestions only */ 185 function add_journal ($data) {} 186 function flush_journal ($data) {} 187 188 /** 189 * * Get journal entries for a location 190 * * 191 * * string Path to location 192 * * relatives Relativity array (default: RELATIVE_CURRENT) 193 * * type [0|1|2] 194 * 0 = any journal entries 195 * 1 = current journal entries 196 * 2 = deleted journal entries 197 * * @return Array of arrays of journal entries 198 * The keys will vary depending on the implementation, 199 * with most attributes in this->attributes being valid, 200 * and these keys being mandatory: 201 * created - Datetime in SQL format that journal entry 202 * was entered 203 * comment - Human readable comment describing the action 204 * version - May be 0 if the derived class does not support 205 * versioning 206 */ 207 function get_journal ($data) { return array(array()); } 208 209 /* 210 * Access checking functions. 211 * 212 * Overview: 213 * Each derived class should have some kind of 214 * user and group access control. This will 215 * usually be based directly on the ACL class. 216 * 217 * If $this->override_acl is set, acl_check() 218 * must always return True. 219 * 220 * PUBLIC functions (mandatory): 221 * 222 * acl_check() - Check access for a user to a given 223 */ 224 225 /** 226 * * Check access for a user to a given location 227 * * 228 * * If $this->override_acl is set, always return True 229 * * string Path to location 230 * * relatives Relativity array (default: RELATIVE_CURRENT) 231 * * operation Operation to check access for. Any combination 232 * of the EGW_ACL_* defines, for example: 233 * EGW_ACL_READ 234 * EGW_ACL_READ|EGW_ACL_WRITE 235 * * owner_id phpGW ID to check access for. 236 * * Default: $GLOBALS['egw_info']['user']['account_id'] 237 * * must_exist If set, string must exist, and acl_check() must 238 * return False if it doesn't. If must_exist isn't 239 * passed, and string doesn't exist, check the owner_id's 240 * access to the parent directory, if it exists. 241 * * @return Boolean. True if access is ok, False otherwise. 242 */ 243 function acl_check ($data) { return True; } 244 245 /* 246 * Operations functions. 247 * 248 * Overview: 249 * These functions perform basic file operations. 250 * 251 * PUBLIC functions (mandatory): 252 * 253 * read - Retreive file contents 254 * 255 * write - Store file contents 256 * 257 * touch - Create a file if it doesn't exist. 258 * Optionally, update the modified time and 259 * modified user if the file exists. 260 * 261 * cp - Copy location 262 * 263 * mv - Move location 264 * 265 * rm - Delete location 266 * 267 * mkdir - Create directory 268 */ 269 270 /** 271 * * Retreive file contents 272 * * 273 * * string Path to location 274 * * relatives Relativity array (default: RELATIVE_CURRENT) 275 * * @return String. Contents of 'string', or False on error. 276 */ 277 function read ($data) { return False; } 278 279 /** 280 * Views the specified file (does not return!) 281 * 282 * @param string filename 283 * @param relatives Relativity array 284 * @return None (doesnt return) 285 * By default this function just reads the file and 286 * outputs it too the browser, after setting the content-type header 287 * appropriately. For some other VFS implementations though, there 288 * may be some more sensible way of viewing the file. 289 */ 290 function view($data) 291 { 292 293 $default_values = array 294 ( 295 'relatives' => array (RELATIVE_CURRENT) 296 ); 297 $data = array_merge ($this->default_values ($data, $default_values), $data); 298 299 $GLOBALS['egw_info']['flags']['noheader'] = true; 300 $GLOBALS['egw_info']['flags']['nonavbar'] = true; 301 $GLOBALS['egw_info']['flags']['noappheader'] = true; 302 $GLOBALS['egw_info']['flags']['noappfooter'] = true; 303 $ls_array = $this->ls (array ( 304 'string' => $data['string'], 305 'relatives' => $data['relatives'], 306 'checksubdirs' => False, 307 'nofiles' => True 308 ) 309 ); 310 311 if ($ls_array[0]['mime_type']) 312 { 313 $mime_type = $ls_array[0]['mime_type']; 314 } 315 elseif ($GLOBALS['settings']['viewtextplain']) 316 { 317 $mime_type = 'text/plain'; 318 } 319 320 header('Content-type: ' . $mime_type); 321 echo $this->read (array ( 322 'string' => $data['string'], 323 'relatives' => $data['relatives'], 324 ) 325 ); 326 exit(); 327 } 328 329 /** 330 * * Store file contents 331 * * 332 * * string Path to location 333 * * relatives Relativity array (default: RELATIVE_CURRENT) 334 * * @return Boolean. True on success, False otherwise. 335 */ 336 function write ($data) { return False; } 337 338 /** 339 * * Create a file if it doesn't exist. 340 * * 341 * Optionally, update the modified time and 342 * modified user if the file exists. 343 * * string Path to location 344 * * relatives Relativity array (default: RELATIVE_CURRENT) 345 * * @return Boolean. True on success, False otherwise. 346 */ 347 function touch ($data) { return False; } 348 349 /** 350 * * Copy location 351 * * 352 * * from Path to location to copy from 353 * * to Path to location to copy to 354 * * relatives Relativity array (default: RELATIVE_CURRENT, RELATIVE_CURRENT) 355 * * @return Boolean. True on success, False otherwise. 356 */ 357 function cp ($data) { return False; } 358 359 /** 360 * * Move location 361 * * 362 * * from Path to location to move from 363 * * to Path to location to move to 364 * * relatives Relativity array (default: RELATIVE_CURRENT, RELATIVE_CURRENT) 365 * * @return Boolean. True on success, False otherwise. 366 */ 367 function mv ($data) { return False; } 368 369 /** 370 * * Delete location 371 * * 372 * * string Path to location 373 * * relatives Relativity array (default: RELATIVE_CURRENT) 374 * * @return Boolean. True on success, False otherwise. 375 */ 376 function rm ($data) { return False; } 377 378 /** 379 * * Create directory 380 * * 381 * * string Path to location 382 * * relatives Relativity array (default: RELATIVE_CURRENT) 383 * * @return Boolean. True on success, False otherwise. 384 */ 385 function mkdir ($data) { return False; } 386 387 /* 388 * Information functions. 389 * 390 * Overview: 391 * These functions set or return information about locations. 392 * 393 * PUBLIC functions (mandatory): 394 * 395 * set_attributes - Set attributes for a location 396 * 397 * file_exists - Check if a location (file or directory) exists 398 * 399 * get_size - Determine size of location 400 * 401 * ls - Return detailed information for location(s) 402 */ 403 404 /** 405 * * Set attributes for a location 406 * * 407 * * Valid attributes are listed in vfs->attributes, 408 * which may be extended by each derived class 409 * * string Path to location 410 * * relatives Relativity array (default: RELATIVE_CURRENT) 411 * * attributes Keyed array of attributes. Key is attribute 412 * name, value is attribute value. 413 * * @return Boolean. True on success, False otherwise. 414 */ 415 function set_attributes ($data) { return False; } 416 417 /** 418 * * Check if a location (file or directory) exists 419 * * 420 * * string Path to location 421 * * relatives Relativity array (default: RELATIVE_CURRENT) 422 * * @return Boolean. True if file exists, False otherwise. 423 */ 424 function file_exists ($data) { return False; } 425 426 /** 427 * * Determine size of location 428 * * 429 * * string Path to location 430 * * relatives Relativity array (default: RELATIVE_CURRENT) 431 * * checksubdirs Boolean. If set, include the size of 432 * all subdirectories recursively. 433 * * @return Integer. Size of location in bytes. 434 */ 435 function get_size ($data) { return 0; } 436 437 /** 438 * * Return detailed information for location(s) 439 * * 440 * * string Path to location 441 * * relatives Relativity array (default: RELATIVE_CURRENT) 442 * * checksubdirs Boolean. If set, return information for all 443 * subdirectories recursively. 444 * * mime String. Only return information for locations with MIME type 445 * specified. VFS classes must recogize these special types: 446 * "Directory" - Location is a directory 447 * " " - Location doesn't not have a MIME type 448 * * nofiles Boolean. If set and 'string' is a directory, return 449 * information about the directory, not the files in it. 450 * * @return Array of arrays of file information. 451 * Keys may vary depending on the implementation, but must include 452 * at least those attributes listed in $this->attributes. 453 */ 454 function ls ($data) { return array(array()); } 455 456 /* 457 * Linked directory functions. 458 * 459 * Overview: 460 * One 'special' feature that VFS classes must support 461 * is linking an otherwise unrelated 'real' directory into 462 * the virtual filesystem. For a traditional filesystem, this 463 * might mean linking /var/specialdir in the real filesystem to 464 * /home/user/specialdir in the VFS. For networked filesystems, 465 * this might mean linking 'another.host.com/dir' to 466 * 'this.host.com/home/user/somedir'. 467 * 468 * This is a feature that will be used mostly be administrators, 469 * in order to present a consistent view to users. Each VFS class 470 * will almost certainly need a new interface for the administrator 471 * to use to make links, but the concept is the same across all the 472 * VFS backends. 473 * 474 * Note that by using $this->linked_dirs in conjunction with 475 * $this->path_parts(), you can keep the implementation of linked 476 * directories very isolated in your code. 477 * 478 * PUBLIC functions (mandatory): 479 * 480 * make_link - Create a real to virtual directory link 481 */ 482 483 /** 484 * * Create a real to virtual directory link 485 * * 486 * * rdir Real directory to make link from/to 487 * * vdir Virtual directory to make link to/from 488 * * relatives Relativity array (default: RELATIVE_CURRENT, RELATIVE_CURRENT) 489 * * @return Boolean. True on success, False otherwise. 490 */ 491 function make_link ($data) { return False; } 492 493 /* 494 * Miscellaneous functions. 495 * 496 * PUBLIC functions (mandatory): 497 * 498 * update_real - Ensure that information about a location is 499 * up-to-date 500 * 501 * compress - Archives a file or set of files in a compressed file 502 * 503 * extract - Dearchives a file or set of files of a compressed file 504 */ 505 506 /** 507 * * Ensure that information about a location is up-to-date 508 * * 509 * * Some VFS backends store information about locations 510 * in a secondary location, for example in a database 511 * or in a cache file. update_real() can be called to 512 * ensure that the information in the secondary location 513 * is up-to-date. 514 * * string Path to location 515 * * relatives Relativity array (default: RELATIVE_CURRENT) 516 * * @return Boolean. True on success, False otherwise. 517 */ 518 function update_real ($data) { return False; } 519 520 /** 521 * * Creates an archive from a file or a set of files 522 * * 523 * * files File names to be stored in archive (array) 524 * * name Name of archive 525 * * type The type of compression, can be 'zip'(default)or 'gz' 526 * * relatives Relativity array (default: RELATIVE_CURRENT) 527 * * Note: the last item is the relativity of the dest archive 528 * * @return Boolean. True on success, False otherwise. 529 */ 530 531 function compress ($data) { return False; } 532 533 /** 534 * * Extracts a file (or files) from archive 535 * * 536 * * name Name of archive 537 * * dest The destination path of files to be extracted 538 * * type The type of compression, can be 'zip' or 'gz'. If 539 * * not specified, uses according to the extension 540 * * files Files to be extracted from archive 541 * * relatives Relativity array (default: RELATIVE_CURRENT) 542 * * Note: the first item is the relativity of the archive, the last of 543 * * the dest dir 544 * * @return Boolean. True on success, False otherwise. 545 */ 546 547 function extract ($data) { return False; } 548 549 550 551 /* 552 * SHARED FUNCTIONS 553 * 554 * The rest of the functions in this file are shared between 555 * all derived VFS classes. 556 * 557 * Derived classes can overload any of these functions if they 558 * see it fit to do so, as long as the prototypes and return 559 * values are the same for public functions, and the function 560 * accomplishes the same goal. 561 * 562 * PRIVATE functions: 563 * 564 * securitycheck - Check if location string is ok to use in VFS functions 565 * 566 * sanitize - Remove any possible security problems from a location 567 * string (i.e. remove leading '..') 568 * 569 * clean_string - Clean location string. This function is used if 570 * any special characters need to be escaped or removed 571 * before accessing a database, network protocol, etc. 572 * The default is to escape characters before doing an SQL 573 * query. 574 * 575 * getabsolutepath - Translate a location string depending on the 576 * relativity. This is the only function that is 577 * directly concerned with relativity. 578 * 579 * get_ext_mime_type - Return MIME type based on file extension 580 * 581 * PUBLIC functions (mandatory): 582 * 583 * set_relative - Sets the current relativity, the relativity used 584 * when RELATIVE_CURRENT is passed to a function 585 * 586 * get_relative - Return the current relativity 587 * 588 * path_parts - Return information about the component parts of a location string 589 * 590 * cd - Change current directory. This function is used to store the 591 * current directory in a standard way, so that it may be accessed 592 * throughout phpGroupWare to provide a consistent view for the user. 593 * 594 * pwd - Return current directory 595 * 596 * copy - Alias for cp 597 * 598 * move - Alias for mv 599 * 600 * delete - Alias for rm 601 * 602 * dir - Alias for ls 603 * 604 * command_line - Process and run a Unix-sytle command line 605 * 606 * compress - Archives a file or set of files in a compressed file 607 * 608 * extract - Dearchives a file or set of files of a compressed file 609 */ 610 611 /* PRIVATE functions */ 612 613 /** 614 * * Check if location string is ok to use in VFS functions 615 * * 616 * * Checks for basic violations such as .. 617 * If securitycheck () fails, run your string through $this->sanitize () 618 * * string Path to location 619 * * @return Boolean. True if string is ok, False otherwise. 620 */ 621 function securitycheck ($data) 622 { 623 if (!is_array ($data)) 624 { 625 $data = array (); 626 } 627 628 if (substr ($data['string'], 0, 1) == "\\" || strstr ($data['string'], "..") || strstr ($data['string'], "\\..") || strstr ($data['string'], ".\\.")) 629 { 630 return False; 631 } 632 else 633 { 634 return True; 635 } 636 } 637 638 /** 639 * * Remove any possible security problems from a location 640 * * 641 * string (i.e. remove leading '..') 642 * * You should not pass all filenames through sanitize () 643 * unless you plan on rejecting .files. Instead, pass 644 * the name through securitycheck () first, and if it fails, 645 * pass it through sanitize. 646 * * string Path to location 647 * * @return String. 'string' with any security problems fixed. 648 */ 649 function sanitize ($data) 650 { 651 if (!is_array ($data)) 652 { 653 $data = array (); 654 } 655 656 /* We use path_parts () just to parse the string, not translate paths */ 657 $p = $this->path_parts (array( 658 'string' => $data['string'], 659 'relatives' => array (RELATIVE_NONE) 660 ) 661 ); 662 663 return (ereg_replace ("^\.+", '', $p->fake_name)); 664 } 665 666 /** 667 * * Clean location string. This function is used if 668 * * 669 * any special characters need to be escaped or removed 670 * before accessing a database, network protocol, etc. 671 * The default is to escape characters before doing an SQL 672 * query. 673 * * string Location string to clean 674 * * @return String. Cleaned version of 'string'. 675 */ 676 function clean_string ($data) 677 { 678 if (!is_array ($data)) 679 { 680 $data = array (); 681 } 682 683 $string = $GLOBALS['egw']->db->db_addslashes ($data['string']); 684 685 return $string; 686 } 687 688 /** 689 * * Translate a location string depending on the 690 * * 691 * relativity. This is the only function that is 692 * directly concerned with relativity. 693 * * string Path to location, relative to mask[0]. 694 * * Defaults to empty string. 695 * * mask Relativity array (default: RELATIVE_CURRENT) 696 * * fake Boolean. If set, returns the 'fake' path, 697 * i.e. /home/user/dir/file. This is not always 698 * possible, use path_parts() instead. 699 * * @return String. Full fake or real path, or False on error. 700 */ 701 function getabsolutepath ($data) 702 { 703 if (!is_array ($data)) 704 { 705 $data = array (); 706 } 707 708 $default_values = array 709 ( 710 'string' => False, 711 'mask' => array (RELATIVE_CURRENT), 712 'fake' => True 713 ); 714 715 $data = array_merge ($this->default_values ($data, $default_values), $data); 716 717 $currentdir = $this->pwd (False); 718 719 /* If they supply just VFS_REAL, we assume they want current relativity */ 720 if ($data['mask'][0] == VFS_REAL) 721 { 722 $data['mask'][0] |= RELATIVE_CURRENT; 723 } 724 725 if (!$this->securitycheck (array( 726 'string' => $data['string'] 727 )) 728 ) 729 { 730 return False; 731 } 732 733 if ($data['mask'][0] & RELATIVE_NONE) 734 { 735 return $data['string']; 736 } 737 738 if ($data['fake']) 739 { 740 $sep = '/'; 741 } 742 else 743 { 744 $sep = SEP; 745 } 746 747 /* if RELATIVE_CURRENT, retrieve the current mask */ 748 if ($data['mask'][0] & RELATIVE_CURRENT) 749 { 750 $mask = $data['mask'][0]; 751 /* Respect any additional masks by re-adding them after retrieving the current mask*/ 752 $data['mask'][0] = $this->get_relative () + ($mask - RELATIVE_CURRENT); 753 } 754 755 if ($data['fake']) 756 { 757 $basedir = "/"; 758 } 759 else 760 { 761 $basedir = $this->basedir . $sep; 762 763 /* This allows all requests to use /'s */ 764 $data['string'] = preg_replace ("|/|", $sep, $data['string']); 765 } 766 767 if (($data['mask'][0] & RELATIVE_PATH) && $currentdir) 768 { 769 $basedir = $basedir . $currentdir . $sep; 770 } 771 elseif (($data['mask'][0] & RELATIVE_USER) || ($data['mask'][0] & RELATIVE_USER_APP)) 772 { 773 $basedir = $basedir . $this->fakebase . $sep; 774 } 775 776 if ($data['mask'][0] & RELATIVE_CURR_USER) 777 { 778 $basedir = $basedir . $this->working_lid . $sep; 779 } 780 781 if (($data['mask'][0] & RELATIVE_USER) || ($data['mask'][0] & RELATIVE_USER_APP)) 782 { 783 $basedir = $basedir . $GLOBALS['egw_info']['user']['account_lid'] . $sep; 784 } 785 786 if ($data['mask'][0] & RELATIVE_USER_APP) 787 { 788 $basedir = $basedir . "." . $GLOBALS['egw_info']['flags']['currentapp'] . $sep; 789 } 790 791 /* Don't add string if it's a /, just for aesthetics */ 792 if ($data['string'] && $data['string'] != $sep) 793 { 794 $basedir = $basedir . $data['string']; 795 } 796 797 /* Let's not return // */ 798 while (ereg ($sep . $sep, $basedir)) 799 { 800 $basedir = ereg_replace ($sep . $sep, $sep, $basedir); 801 } 802 803 $basedir = ereg_replace ($sep . '$', '', $basedir); 804 805 return $basedir; 806 } 807 808 /** 809 * * Return MIME type based on file extension 810 * * 811 * * Internal use only. Applications should call vfs->file_type () 812 * * @author skeeter 813 * * string Real path to file, with or without leading paths 814 * * @return String. MIME type based on file extension. 815 */ 816 function get_ext_mime_type ($data) 817 { 818 if (!is_array ($data)) 819 { 820 $data = array (); 821 } 822 823 $file=basename($data['string']); 824 $mimefile=EGW_API_INC.'/phpgw_mime.types'; 825 $fp=fopen($mimefile,'r'); 826 $contents = explode("\n",fread($fp,filesize($mimefile))); 827 fclose($fp); 828 829 $parts=explode('.',strtolower($file)); 830 $ext=$parts[(sizeof($parts)-1)]; 831 832 for($i=0;$i<sizeof($contents);$i++) 833 { 834 if (!ereg("^#",$contents[$i])) 835 { 836 $line=split("[[:space:]]+", $contents[$i]); 837 if (sizeof($line) >= 2) 838 { 839 for($j=1;$j<sizeof($line);$j++) 840 { 841 if($line[$j] == $ext) 842 { 843 return $line[0]; 844 } 845 } 846 } 847 } 848 } 849 850 return ''; 851 } 852 853 /* PUBLIC functions (mandatory) */ 854 855 /** 856 * * Sets the current relativity, the relativity used 857 * * 858 * when RELATIVE_CURRENT is passed to a function 859 * * mask Relative bitmask. If not set, relativity 860 * will be returned to the default. 861 * * @return Void 862 */ 863 function set_relative ($data) 864 { 865 if (!is_array ($data)) 866 { 867 $data = array (); 868 } 869 870 if (!$data['mask']) 871 { 872 unset ($this->relative); 873 } 874 else 875 { 876 $this->relative = $data['mask']; 877 } 878 } 879 880 /** 881 * * Return the current relativity 882 * * 883 * * Returns relativity bitmask, or the default 884 * of "completely relative" if unset 885 * * @return Integer. One of the RELATIVE_* defines. 886 */ 887 function get_relative () 888 { 889 if (isset ($this->relative) && $this->relative) 890 { 891 return $this->relative; 892 } 893 else 894 { 895 return RELATIVE_ALL; 896 } 897 } 898 899 /** 900 * * Return information about the component parts of a location string 901 * * 902 * * Most VFS functions call path_parts() with their 'string' and 903 * 'relatives' arguments before doing their work, in order to 904 * determine the file/directory to work on. 905 * * string Path to location 906 * * relatives Relativity array (default: RELATIVE_CURRENT) 907 * * object If set, return an object instead of an array 908 * * nolinks Don't check for linked directories (made with 909 * make_link()). Used internally to prevent recursion. 910 * * @return Array or object. Contains the fake and real component parts of the path. 911 * * Returned values are: 912 * mask 913 * outside 914 * fake_full_path 915 * fake_leading_dirs 916 * fake_extra_path BROKEN 917 * fake_name 918 * real_full_path 919 * real_leading_dirs 920 * real_extra_path BROKEN 921 * real_name 922 * fake_full_path_clean 923 * fake_leading_dirs_clean 924 * fake_extra_path_clean BROKEN 925 * fake_name_clean 926 * real_full_path_clean 927 * real_leading_dirs_clean 928 * real_extra_path_clean BROKEN 929 * real_name_clean 930 * "clean" values are run through vfs->clean_string () and 931 * are safe for use in SQL queries that use key='value' 932 * They should be used ONLY for SQL queries, so are used 933 * mostly internally 934 * mask is either RELATIVE_NONE or RELATIVE_NONE|VFS_REAL, 935 * and is used internally 936 * outside is boolean, True if 'relatives' contains VFS_REAL 937 */ 938 function path_parts ($data) 939 { 940 if (!is_array ($data)) 941 { 942 $data = array (); 943 } 944 945 $default_values = array 946 ( 947 'relatives' => array (RELATIVE_CURRENT), 948 'object' => True, 949 'nolinks' => False 950 ); 951 952 $data = array_merge ($this->default_values ($data, $default_values), $data); 953 954 $sep = SEP; 955 956 $rarray['mask'] = RELATIVE_NONE; 957 958 if (!($data['relatives'][0] & VFS_REAL)) 959 { 960 $rarray['outside'] = False; 961 $fake = True; 962 } 963 else 964 { 965 $rarray['outside'] = True; 966 $rarray['mask'] |= VFS_REAL; 967 } 968 969 $string = $this->getabsolutepath (array( 970 'string' => $data['string'], 971 'mask' => array ($data['relatives'][0]), 972 'fake' => $fake 973 ) 974 ); 975 976 if ($fake) 977 { 978 $base_sep = '/'; 979 $base = '/'; 980 981 $opp_base = $this->basedir . $sep; 982 983 $rarray['fake_full_path'] = $string; 984 } 985 else 986 { 987 $base_sep = $sep; 988 if (substr($string,0,strlen($this->basedir)+1) == $this->basedir . $sep) 989 { 990 $base = $this->basedir . $sep; 991 } 992 else 993 { 994 $base = $sep; 995 } 996 997 $opp_base = '/'; 998 999 $rarray['real_full_path'] = $string; 1000 } 1001 1002 /* This is needed because of substr's handling of negative lengths */ 1003 $baselen = strlen ($base); 1004 $lastslashpos = @strrpos ($string, $base_sep); 1005 $length = $lastslashpos < $baselen ? 0 : $lastslashpos - $baselen; 1006 1007 $extra_path = $rarray['fake_extra_path'] = $rarray['real_extra_path'] = substr ($string, strlen ($base), $length); 1008 if($string[1] != ':') 1009 { 1010 $name = $rarray['fake_name'] = $rarray['real_name'] = substr ($string, @strrpos ($string, $base_sep) + 1); 1011 } 1012 else 1013 { 1014 $name = $rarray['fake_name'] = $rarray['real_name'] = $string; 1015 } 1016 1017 if ($fake) 1018 { 1019 $rarray['real_extra_path'] ? $dispsep = $sep : $dispsep = ''; 1020 $rarray['real_full_path'] = $opp_base . $rarray['real_extra_path'] . $dispsep . $rarray['real_name']; 1021 if ($extra_path) 1022 { 1023 $rarray['fake_leading_dirs'] = $base . $extra_path; 1024 $rarray['real_leading_dirs'] = $opp_base . $extra_path; 1025 } 1026 elseif (@strrpos ($rarray['fake_full_path'], $sep) == 0) 1027 { 1028 /* If there is only one $sep in the path, we don't want to strip it off */ 1029 $rarray['fake_leading_dirs'] = $sep; 1030 $rarray['real_leading_dirs'] = substr ($opp_base, 0, strlen ($opp_base) - 1); 1031 } 1032 else 1033 { 1034 /* These strip the ending / */ 1035 $rarray['fake_leading_dirs'] = substr ($base, 0, strlen ($base) - 1); 1036 $rarray['real_leading_dirs'] = substr ($opp_base, 0, strlen ($opp_base) - 1); 1037 } 1038 } 1039 else 1040 { 1041 if($rarray['fake_name'][1] != ':') 1042 { 1043 $rarray['fake_full_path'] = $opp_base . $rarray['fake_extra_path'] . '/' . $rarray['fake_name']; 1044 } 1045 else 1046 { 1047 $rarray['fake_full_path'] = $rarray['fake_name']; 1048 } 1049 if ($extra_path) 1050 { 1051 $rarray['fake_leading_dirs'] = $opp_base . $extra_path; 1052 $rarray['real_leading_dirs'] = $base . $extra_path; 1053 } 1054 else 1055 { 1056 $rarray['fake_leading_dirs'] = substr ($opp_base, 0, strlen ($opp_base) - 1); 1057 $rarray['real_leading_dirs'] = substr ($base, 0, strlen ($base) - 1); 1058 } 1059 } 1060 1061 /* We check for linked dirs made with make_link (). This could be better, but it works */ 1062 if (!$data['nolinks']) 1063 { 1064 reset ($this->linked_dirs); 1065 while (list ($num, $link_info) = each ($this->linked_dirs)) 1066 { 1067 if (ereg ("^$link_info[directory]/$link_info[name](/|$)", $rarray['fake_full_path'])) 1068 { 1069 $rarray['real_full_path'] = ereg_replace ("^$this->basedir", '', $rarray['real_full_path']); 1070 $rarray['real_full_path'] = ereg_replace ("^$link_info[directory]" . SEP . "$link_info[name]", $link_info['link_directory'] . SEP . $link_info['link_name'], $rarray['real_full_path']); 1071 1072 $p = $this->path_parts (array( 1073 'string' => $rarray['real_full_path'], 1074 'relatives' => array (RELATIVE_NONE|VFS_REAL), 1075 'nolinks' => True 1076 ) 1077 ); 1078 1079 $rarray['real_leading_dirs'] = $p->real_leading_dirs; 1080 $rarray['real_extra_path'] = $p->real_extra_path; 1081 $rarray['real_name'] = $p->real_name; 1082 } 1083 } 1084 } 1085 1086 /* 1087 We have to count it before because new keys will be added, 1088 which would create an endless loop 1089 */ 1090 $count = count ($rarray); 1091 reset ($rarray); 1092 for ($i = 0; (list ($key, $value) = each ($rarray)) && $i != $count; $i++) 1093 { 1094 $rarray[$key . '_clean'] = $this->clean_string (array ('string' => $value)); 1095 } 1096 1097 if ($data['object']) 1098 { 1099 $robject =& new path_class; 1100 1101 reset ($rarray); 1102 while (list ($key, $value) = each ($rarray)) 1103 { 1104 $robject->$key = $value; 1105 } 1106 } 1107 1108 /* 1109 echo "<br>fake_full_path: $rarray[fake_full_path] 1110 <br>fake_leading_dirs: $rarray[fake_leading_dirs] 1111 <br>fake_extra_path: $rarray[fake_extra_path] 1112 <br>fake_name: $rarray[fake_name] 1113 <br>real_full_path: $rarray[real_full_path] 1114 <br>real_leading_dirs: $rarray[real_leading_dirs] 1115 <br>real_extra_path: $rarray[real_extra_path] 1116 <br>real_name: $rarray[real_name]"; 1117 */ 1118 1119 if ($data['object']) 1120 { 1121 return ($robject); 1122 } 1123 else 1124 { 1125 return ($rarray); 1126 } 1127 } 1128 1129 /** 1130 * * Change current directory. This function is used to store the 1131 * * 1132 * current directory in a standard way, so that it may be accessed 1133 * throughout phpGroupWare to provide a consistent view for the user. 1134 * * To cd to the root '/', use: 1135 * cd (array( 1136 * 'string' => '/', 1137 * 'relative' => False, 1138 * 'relatives' => array (RELATIVE_NONE) 1139 * )); 1140 * * string Directory location to cd into. Default is '/'. 1141 * * relative If set, add target to current path. 1142 * Else, pass 'relative' as mask to getabsolutepath() 1143 * Default is True. 1144 * * relatives Relativity array (default: RELATIVE_CURRENT) 1145 */ 1146 function cd ($data = '') 1147 { 1148 if (!is_array ($data)) 1149 { 1150 $noargs = 1; 1151 $data = array (); 1152 } 1153 1154 $default_values = array 1155 ( 1156 'string' => '/', 1157 'relative' => True, 1158 'relatives' => array (RELATIVE_CURRENT) 1159 ); 1160 1161 $data = array_merge ($this->default_values ($data, $default_values), $data); 1162 1163 if ($data['relatives'][0] & VFS_REAL) 1164 { 1165 $sep = SEP; 1166 } 1167 else 1168 { 1169 $sep = '/'; 1170 } 1171 1172 if ($data['relative'] == 'relative' || $data['relative'] == True) 1173 { 1174 /* if 'string' is "/" and 'relative' is set, we cd to the user/group home dir */ 1175 if ($data['string'] == '/') 1176 { 1177 $data['relatives'][0] = RELATIVE_USER; 1178 $basedir = $this->getabsolutepath (array( 1179 'string' => False, 1180 'mask' => array ($data['relatives'][0]), 1181 'fake' => True 1182 ) 1183 ); 1184 } 1185 else 1186 { 1187 $currentdir = $GLOBALS['egw']->session->appsession('vfs',''); 1188 $basedir = $this->getabsolutepath (array( 1189 'string' => $currentdir . $sep . $data['string'], 1190 'mask' => array ($data['relatives'][0]), 1191 'fake' => True 1192 ) 1193 ); 1194 } 1195 } 1196 else 1197 { 1198 $basedir = $this->getabsolutepath (array( 1199 'string' => $data['string'], 1200 'mask' => array ($data['relatives'][0]) 1201 ) 1202 ); 1203 } 1204 1205 $GLOBALS['egw']->session->appsession('vfs','',$basedir); 1206 1207 return True; 1208 } 1209 1210 /** 1211 * * Return current directory 1212 * * 1213 * * full If set, return full fake path, else just 1214 * the extra dirs (False strips the leading /). 1215 * Default is True. 1216 * * @return String. The current directory. 1217 */ 1218 function pwd ($data = '') 1219 { 1220 if (!is_array ($data)) 1221 { 1222 $data = array (); 1223 } 1224 1225 $default_values = array 1226 ( 1227 'full' => True 1228 ); 1229 1230 $data = array_merge ($this->default_values ($data, $default_values), $data); 1231 1232 $currentdir = $GLOBALS['egw']->session->appsession('vfs',''); 1233 1234 if (!$data['full']) 1235 { 1236 $currentdir = ereg_replace ("^/", '', $currentdir); 1237 } 1238 1239 if ($currentdir == '' && $data['full']) 1240 { 1241 $currentdir = '/'; 1242 } 1243 1244 $currentdir = trim ($currentdir); 1245 1246 return $currentdir; 1247 } 1248 1249 /** 1250 * * shortcut to cp 1251 * * 1252 */ 1253 function copy ($data) 1254 { 1255 return $this->cp ($data); 1256 } 1257 1258 /** 1259 * * shortcut to mv 1260 * * 1261 */ 1262 function move ($data) 1263 { 1264 return $this->mv ($data); 1265 } 1266 1267 /** 1268 * * shortcut to rm 1269 * * 1270 */ 1271 function delete ($data) 1272 { 1273 return $this->rm ($data); 1274 } 1275 1276 /** 1277 * * shortcut to ls 1278 * * 1279 */ 1280 function dir ($data) 1281 { 1282 return $this->ls ($data); 1283 } 1284 1285 /** 1286 * * Process and run a Unix-sytle command line 1287 * * 1288 * * EXPERIMENTAL. DANGEROUS. DO NOT USE THIS UNLESS YOU 1289 * KNOW WHAT YOU'RE DOING! 1290 * * This is mostly working, but the command parser needs 1291 * to be improved to take files with spaces into 1292 * consideration (those should be in ""). 1293 * * command_line Unix-style command line with one of the 1294 * commands in the $args array 1295 * * @return The return value of the actual VFS call 1296 */ 1297 function command_line ($data) 1298 { 1299 if (!is_array ($data)) 1300 { 1301 $data = array (); 1302 } 1303 1304 $args = array 1305 ( 1306 array ('name' => 'mv', 'params' => 2), 1307 array ('name' => 'cp', 'params' => 2), 1308 array ('name' => 'rm', 'params' => 1), 1309 array ('name' => 'ls', 'params' => -1), 1310 array ('name' => 'du', 'params' => 1, 'func' => get_size), 1311 array ('name' => 'cd', 'params' => 1), 1312 array ('name' => 'pwd', 'params' => 0), 1313 array ('name' => 'cat', 'params' => 1, 'func' => read), 1314 array ('name' => 'file', 'params' => 1, 'func' => file_type), 1315 array ('name' => 'mkdir', 'params' => 1), 1316 array ('name' => 'touch', 'params' => 1) 1317 ); 1318 1319 if (!$first_space = strpos ($data['command_line'], ' ')) 1320 { 1321 $first_space = strlen ($data['command_line']); 1322 } 1323 if ((!$last_space = strrpos ($data['command_line'], ' ')) || ($last_space == $first_space)) 1324 { 1325 $last_space = strlen ($data['command_line']) + 1; 1326 } 1327 $argv[0] = substr ($data['command_line'], 0, $first_space); 1328 if (strlen ($argv[0]) != strlen ($data['command_line'])) 1329 { 1330 $argv[1] = substr ($data['command_line'], $first_space + 1, $last_space - ($first_space + 1)); 1331 if ((strlen ($argv[0]) + 1 + strlen ($argv[1])) != strlen ($data['command_line'])) 1332 { 1333 $argv[2] = substr ($data['command_line'], $last_space + 1); 1334 } 1335 } 1336 $argc = count ($argv); 1337 1338 reset ($args); 1339 while (list (,$arg_info) = each ($args)) 1340 { 1341 if ($arg_info['name'] == $argv[0]) 1342 { 1343 $command_ok = 1; 1344 if (($argc == ($arg_info['params'] + 1)) || ($arg_info['params'] == -1)) 1345 { 1346 $param_count_ok = 1; 1347 } 1348 break; 1349 } 1350 } 1351 1352 if (!$command_ok) 1353 { 1354 // return E_VFS_BAD_COMMAND; 1355 return False; 1356 } 1357 if (!$param_count_ok) 1358 { 1359 // return E_VFS_BAD_PARAM_COUNT; 1360 return False; 1361 } 1362 1363 for ($i = 1; $i != ($arg_info['params'] + 1); $i++) 1364 { 1365 if (substr ($argv[$i], 0, 1) == "/") 1366 { 1367 $relatives[] = RELATIVE_NONE; 1368 } 1369 else 1370 { 1371 $relatives[] = RELATIVE_ALL; 1372 } 1373 } 1374 1375 $func = $arg_info['func'] ? $arg_info['func'] : $arg_info['name']; 1376 1377 if (!$argv[2]) 1378 { 1379 $rv = $this->$func (array( 1380 'string' => $argv[1], 1381 'relatives' => $relatives 1382 ) 1383 ); 1384 } 1385 else 1386 { 1387 $rv = $this->$func (array( 1388 'from' => $argv[1], 1389 'to' => $argv[2], 1390 'relatives' => $relatives 1391 ) 1392 ); 1393 } 1394 1395 return ($rv); 1396 } 1397 1398 /* Helper functions, not public */ 1399 1400 function default_values ($data, $default_values) 1401 { 1402 for ($i = 0; list ($key, $value) = each ($default_values); $i++) 1403 { 1404 if (!isset ($data[$key])) 1405 { 1406 $data[$key] = $value; 1407 } 1408 } 1409 1410 return $data; 1411 } 1412 1413 } 1414 1415 include (EGW_API_INC . '/class.vfs_' . $GLOBALS['egw_info']['server']['file_repository'] . '.inc.php');
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 17:20:01 2007 | par Balluche grâce à PHPXref 0.7 |