[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Joomla! Content Management System 5 * 6 * @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org> 7 * @license GNU General Public License version 2 or later; see LICENSE.txt 8 */ 9 10 namespace Joomla\CMS\Filesystem; 11 12 use Joomla\CMS\Language\Text; 13 use Joomla\CMS\Object\CMSObject; 14 15 // phpcs:disable PSR1.Files.SideEffects 16 \defined('JPATH_PLATFORM') or die; 17 // phpcs:enable PSR1.Files.SideEffects 18 19 /** 20 * Joomla! Stream Interface 21 * 22 * The Joomla! stream interface is designed to handle files as streams 23 * where as the legacy File static class treated files in a rather 24 * atomic manner. 25 * 26 * @note This class adheres to the stream wrapper operations: 27 * @link https://www.php.net/manual/en/function.stream-get-wrappers.php 28 * @link https://www.php.net/manual/en/intro.stream.php PHP Stream Manual 29 * @link https://www.php.net/manual/en/wrappers.php Stream Wrappers 30 * @link https://www.php.net/manual/en/filters.php Stream Filters 31 * @link https://www.php.net/manual/en/transports.php Socket Transports (used by some options, particularly HTTP proxy) 32 * @since 1.7.0 33 */ 34 class Stream extends CMSObject 35 { 36 /** 37 * File Mode 38 * 39 * @var integer 40 * @since 1.7.0 41 */ 42 protected $filemode = 0644; 43 44 /** 45 * Directory Mode 46 * 47 * @var integer 48 * @since 1.7.0 49 */ 50 protected $dirmode = 0755; 51 52 /** 53 * Default Chunk Size 54 * 55 * @var integer 56 * @since 1.7.0 57 */ 58 protected $chunksize = 8192; 59 60 /** 61 * Filename 62 * 63 * @var string 64 * @since 1.7.0 65 */ 66 protected $filename; 67 68 /** 69 * Prefix of the connection for writing 70 * 71 * @var string 72 * @since 1.7.0 73 */ 74 protected $writeprefix; 75 76 /** 77 * Prefix of the connection for reading 78 * 79 * @var string 80 * @since 1.7.0 81 */ 82 protected $readprefix; 83 84 /** 85 * Read Processing method 86 * @var string gz, bz, f 87 * If a scheme is detected, fopen will be defaulted 88 * To use compression with a network stream use a filter 89 * @since 1.7.0 90 */ 91 protected $processingmethod = 'f'; 92 93 /** 94 * Filters applied to the current stream 95 * 96 * @var array 97 * @since 1.7.0 98 */ 99 protected $filters = array(); 100 101 /** 102 * File Handle 103 * 104 * @var resource 105 * @since 3.0.0 106 */ 107 protected $fh; 108 109 /** 110 * File size 111 * 112 * @var integer 113 * @since 3.0.0 114 */ 115 protected $filesize; 116 117 /** 118 * Context to use when opening the connection 119 * 120 * @var resource 121 * @since 3.0.0 122 */ 123 protected $context = null; 124 125 /** 126 * Context options; used to rebuild the context 127 * 128 * @var array 129 * @since 3.0.0 130 */ 131 protected $contextOptions; 132 133 /** 134 * The mode under which the file was opened 135 * 136 * @var string 137 * @since 3.0.0 138 */ 139 protected $openmode; 140 141 /** 142 * Constructor 143 * 144 * @param string $writeprefix Prefix of the stream (optional). Unlike the JPATH_*, this has a final path separator! 145 * @param string $readprefix The read prefix (optional). 146 * @param array $context The context options (optional). 147 * 148 * @since 1.7.0 149 */ 150 public function __construct($writeprefix = '', $readprefix = '', $context = array()) 151 { 152 $this->writeprefix = $writeprefix; 153 $this->readprefix = $readprefix; 154 $this->contextOptions = $context; 155 $this->_buildContext(); 156 } 157 158 /** 159 * Destructor 160 * 161 * @since 1.7.0 162 */ 163 public function __destruct() 164 { 165 // Attempt to close on destruction if there is a file handle 166 if ($this->fh) { 167 @$this->close(); 168 } 169 } 170 171 /** 172 * Generic File Operations 173 * 174 * Open a stream with some lazy loading smarts 175 * 176 * @param string $filename Filename 177 * @param string $mode Mode string to use 178 * @param boolean $useIncludePath Use the PHP include path 179 * @param resource $context Context to use when opening 180 * @param boolean $usePrefix Use a prefix to open the file 181 * @param boolean $relative Filename is a relative path (if false, strips JPATH_ROOT to make it relative) 182 * @param boolean $detectProcessingMode Detect the processing method for the file and use the appropriate function 183 * to handle output automatically 184 * 185 * @return boolean 186 * 187 * @since 1.7.0 188 */ 189 public function open( 190 $filename, 191 $mode = 'r', 192 $useIncludePath = false, 193 $context = null, 194 $usePrefix = false, 195 $relative = false, 196 $detectProcessingMode = false 197 ) { 198 $filename = $this->_getFilename($filename, $mode, $usePrefix, $relative); 199 200 if (!$filename) { 201 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILENAME')); 202 203 return false; 204 } 205 206 $this->filename = $filename; 207 $this->openmode = $mode; 208 209 $url = parse_url($filename); 210 $retval = false; 211 212 if (isset($url['scheme'])) { 213 // If we're dealing with a Joomla! stream, load it 214 if (FilesystemHelper::isJoomlaStream($url['scheme'])) { 215 require_once __DIR__ . '/streams/' . $url['scheme'] . '.php'; 216 } 217 218 // We have a scheme! force the method to be f 219 $this->processingmethod = 'f'; 220 } elseif ($detectProcessingMode) { 221 $ext = strtolower(File::getExt($this->filename)); 222 223 switch ($ext) { 224 case 'tgz': 225 case 'gz': 226 case 'gzip': 227 $this->processingmethod = 'gz'; 228 break; 229 230 case 'tbz2': 231 case 'bz2': 232 case 'bzip2': 233 $this->processingmethod = 'bz'; 234 break; 235 236 default: 237 $this->processingmethod = 'f'; 238 break; 239 } 240 } 241 242 // Capture PHP errors 243 $php_errormsg = 'Error Unknown whilst opening a file'; 244 $track_errors = ini_get('track_errors'); 245 ini_set('track_errors', true); 246 247 // Decide which context to use: 248 switch ($this->processingmethod) { 249 // Gzip doesn't support contexts or streams 250 case 'gz': 251 $this->fh = gzopen($filename, $mode, $useIncludePath); 252 break; 253 254 // Bzip2 is much like gzip except it doesn't use the include path 255 case 'bz': 256 $this->fh = bzopen($filename, $mode); 257 break; 258 259 // Fopen can handle streams 260 case 'f': 261 default: 262 // One supplied at open; overrides everything 263 if ($context) { 264 $this->fh = fopen($filename, $mode, $useIncludePath, $context); 265 } elseif ($this->context) { 266 // One provided at initialisation 267 $this->fh = fopen($filename, $mode, $useIncludePath, $this->context); 268 } else { 269 // No context; all defaults 270 $this->fh = fopen($filename, $mode, $useIncludePath); 271 } 272 273 break; 274 } 275 276 if (!$this->fh) { 277 $this->setError($php_errormsg); 278 } else { 279 $retval = true; 280 } 281 282 // Restore error tracking to what it was before 283 ini_set('track_errors', $track_errors); 284 285 // Return the result 286 return $retval; 287 } 288 289 /** 290 * Attempt to close a file handle 291 * 292 * Will return false if it failed and true on success 293 * If the file is not open the system will return true, this function destroys the file handle as well 294 * 295 * @return boolean 296 * 297 * @since 1.7.0 298 */ 299 public function close() 300 { 301 if (!$this->fh) { 302 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); 303 304 return true; 305 } 306 307 $retval = false; 308 309 // Capture PHP errors 310 $php_errormsg = 'Error Unknown'; 311 $track_errors = ini_get('track_errors'); 312 ini_set('track_errors', true); 313 314 switch ($this->processingmethod) { 315 case 'gz': 316 $res = gzclose($this->fh); 317 break; 318 319 case 'bz': 320 $res = bzclose($this->fh); 321 break; 322 323 case 'f': 324 default: 325 $res = fclose($this->fh); 326 break; 327 } 328 329 if (!$res) { 330 $this->setError($php_errormsg); 331 } else { 332 // Reset this 333 $this->fh = null; 334 $retval = true; 335 } 336 337 // If we wrote, chmod the file after it's closed 338 if ($this->openmode[0] == 'w') { 339 $this->chmod(); 340 } 341 342 // Restore error tracking to what it was before 343 ini_set('track_errors', $track_errors); 344 345 // Return the result 346 return $retval; 347 } 348 349 /** 350 * Work out if we're at the end of the file for a stream 351 * 352 * @return boolean 353 * 354 * @since 1.7.0 355 */ 356 public function eof() 357 { 358 if (!$this->fh) { 359 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); 360 361 return false; 362 } 363 364 // Capture PHP errors 365 $php_errormsg = ''; 366 $track_errors = ini_get('track_errors'); 367 ini_set('track_errors', true); 368 369 switch ($this->processingmethod) { 370 case 'gz': 371 $res = gzeof($this->fh); 372 break; 373 374 case 'bz': 375 case 'f': 376 default: 377 $res = feof($this->fh); 378 break; 379 } 380 381 if ($php_errormsg) { 382 $this->setError($php_errormsg); 383 } 384 385 // Restore error tracking to what it was before 386 ini_set('track_errors', $track_errors); 387 388 // Return the result 389 return $res; 390 } 391 392 /** 393 * Retrieve the file size of the path 394 * 395 * @return mixed 396 * 397 * @since 1.7.0 398 */ 399 public function filesize() 400 { 401 if (!$this->filename) { 402 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); 403 404 return false; 405 } 406 407 $retval = false; 408 409 // Capture PHP errors 410 $php_errormsg = ''; 411 $track_errors = ini_get('track_errors'); 412 ini_set('track_errors', true); 413 $res = @filesize($this->filename); 414 415 if (!$res) { 416 $tmp_error = ''; 417 418 if ($php_errormsg) { 419 // Something went wrong. 420 // Store the error in case we need it. 421 $tmp_error = $php_errormsg; 422 } 423 424 $res = FilesystemHelper::remotefsize($this->filename); 425 426 if (!$res) { 427 if ($tmp_error) { 428 // Use the php_errormsg from before 429 $this->setError($tmp_error); 430 } else { 431 // Error but nothing from php? How strange! Create our own 432 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_SIZE')); 433 } 434 } else { 435 $this->filesize = $res; 436 $retval = $res; 437 } 438 } else { 439 $this->filesize = $res; 440 $retval = $res; 441 } 442 443 // Restore error tracking to what it was before. 444 ini_set('track_errors', $track_errors); 445 446 // Return the result 447 return $retval; 448 } 449 450 /** 451 * Get a line from the stream source. 452 * 453 * @param integer $length The number of bytes (optional) to read. 454 * 455 * @return mixed 456 * 457 * @since 1.7.0 458 */ 459 public function gets($length = 0) 460 { 461 if (!$this->fh) { 462 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); 463 464 return false; 465 } 466 467 $retval = false; 468 469 // Capture PHP errors 470 $php_errormsg = 'Error Unknown'; 471 $track_errors = ini_get('track_errors'); 472 ini_set('track_errors', true); 473 474 switch ($this->processingmethod) { 475 case 'gz': 476 $res = $length ? gzgets($this->fh, $length) : gzgets($this->fh); 477 break; 478 479 case 'bz': 480 case 'f': 481 default: 482 $res = $length ? fgets($this->fh, $length) : fgets($this->fh); 483 break; 484 } 485 486 if (!$res) { 487 $this->setError($php_errormsg); 488 } else { 489 $retval = $res; 490 } 491 492 // Restore error tracking to what it was before 493 ini_set('track_errors', $track_errors); 494 495 // Return the result 496 return $retval; 497 } 498 499 /** 500 * Read a file 501 * 502 * Handles user space streams appropriately otherwise any read will return 8192 503 * 504 * @param integer $length Length of data to read 505 * 506 * @return mixed 507 * 508 * @link https://www.php.net/manual/en/function.fread.php 509 * @since 1.7.0 510 */ 511 public function read($length = 0) 512 { 513 if (!$this->filesize && !$length) { 514 // Get the filesize 515 $this->filesize(); 516 517 if (!$this->filesize) { 518 // Set it to the biggest and then wait until eof 519 $length = -1; 520 } else { 521 $length = $this->filesize; 522 } 523 } 524 525 if (!$this->fh) { 526 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); 527 528 return false; 529 } 530 531 $retval = false; 532 533 // Capture PHP errors 534 $php_errormsg = 'Error Unknown'; 535 $track_errors = ini_get('track_errors'); 536 ini_set('track_errors', true); 537 $remaining = $length; 538 539 do { 540 // Do chunked reads where relevant 541 switch ($this->processingmethod) { 542 case 'bz': 543 $res = ($remaining > 0) ? bzread($this->fh, $remaining) : bzread($this->fh, $this->chunksize); 544 break; 545 546 case 'gz': 547 $res = ($remaining > 0) ? gzread($this->fh, $remaining) : gzread($this->fh, $this->chunksize); 548 break; 549 550 case 'f': 551 default: 552 $res = ($remaining > 0) ? fread($this->fh, $remaining) : fread($this->fh, $this->chunksize); 553 break; 554 } 555 556 if (!$res) { 557 $this->setError($php_errormsg); 558 559 // Jump from the loop 560 $remaining = 0; 561 } else { 562 if (!$retval) { 563 $retval = ''; 564 } 565 566 $retval .= $res; 567 568 if (!$this->eof()) { 569 $len = \strlen($res); 570 $remaining -= $len; 571 } else { 572 // If it's the end of the file then we've nothing left to read; reset remaining and len 573 $remaining = 0; 574 $length = \strlen($retval); 575 } 576 } 577 } while ($remaining || !$length); 578 579 // Restore error tracking to what it was before 580 ini_set('track_errors', $track_errors); 581 582 // Return the result 583 return $retval; 584 } 585 586 /** 587 * Seek the file 588 * 589 * Note: the return value is different to that of fseek 590 * 591 * @param integer $offset Offset to use when seeking. 592 * @param integer $whence Seek mode to use. 593 * 594 * @return boolean True on success, false on failure 595 * 596 * @link https://www.php.net/manual/en/function.fseek.php 597 * @since 1.7.0 598 */ 599 public function seek($offset, $whence = SEEK_SET) 600 { 601 if (!$this->fh) { 602 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); 603 604 return false; 605 } 606 607 $retval = false; 608 609 // Capture PHP errors 610 $php_errormsg = ''; 611 $track_errors = ini_get('track_errors'); 612 ini_set('track_errors', true); 613 614 switch ($this->processingmethod) { 615 case 'gz': 616 $res = gzseek($this->fh, $offset, $whence); 617 break; 618 619 case 'bz': 620 case 'f': 621 default: 622 $res = fseek($this->fh, $offset, $whence); 623 break; 624 } 625 626 // Seek, interestingly, returns 0 on success or -1 on failure. 627 if ($res == -1) { 628 $this->setError($php_errormsg); 629 } else { 630 $retval = true; 631 } 632 633 // Restore error tracking to what it was before 634 ini_set('track_errors', $track_errors); 635 636 // Return the result 637 return $retval; 638 } 639 640 /** 641 * Returns the current position of the file read/write pointer. 642 * 643 * @return mixed 644 * 645 * @since 1.7.0 646 */ 647 public function tell() 648 { 649 if (!$this->fh) { 650 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); 651 652 return false; 653 } 654 655 // Capture PHP errors 656 $php_errormsg = ''; 657 $track_errors = ini_get('track_errors'); 658 ini_set('track_errors', true); 659 660 switch ($this->processingmethod) { 661 case 'gz': 662 $res = gztell($this->fh); 663 break; 664 665 case 'bz': 666 case 'f': 667 default: 668 $res = ftell($this->fh); 669 break; 670 } 671 672 // May return 0 so check if it's really false 673 if ($res === false) { 674 $this->setError($php_errormsg); 675 } 676 677 // Restore error tracking to what it was before 678 ini_set('track_errors', $track_errors); 679 680 // Return the result 681 return $res; 682 } 683 684 /** 685 * File write 686 * 687 * Whilst this function accepts a reference, the underlying fwrite 688 * will do a copy! This will roughly double the memory allocation for 689 * any write you do. Specifying chunked will get around this by only 690 * writing in specific chunk sizes. This defaults to 8192 which is a 691 * sane number to use most of the time (change the default with 692 * JStream::set('chunksize', newsize);) 693 * Note: This doesn't support gzip/bzip2 writing like reading does 694 * 695 * @param string $string Reference to the string to write. 696 * @param integer $length Length of the string to write. 697 * @param integer $chunk Size of chunks to write in. 698 * 699 * @return boolean 700 * 701 * @link https://www.php.net/manual/en/function.fwrite.php 702 * @since 1.7.0 703 */ 704 public function write(&$string, $length = 0, $chunk = 0) 705 { 706 if (!$this->fh) { 707 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); 708 709 return false; 710 } 711 712 // If the length isn't set, set it to the length of the string. 713 if (!$length) { 714 $length = \strlen($string); 715 } 716 717 // If the chunk isn't set, set it to the default. 718 if (!$chunk) { 719 $chunk = $this->chunksize; 720 } 721 722 $retval = true; 723 724 // Capture PHP errors 725 $php_errormsg = ''; 726 $track_errors = ini_get('track_errors'); 727 ini_set('track_errors', true); 728 $remaining = $length; 729 $start = 0; 730 731 do { 732 // If the amount remaining is greater than the chunk size, then use the chunk 733 $amount = ($remaining > $chunk) ? $chunk : $remaining; 734 $res = fwrite($this->fh, substr($string, $start), $amount); 735 736 // Returns false on error or the number of bytes written 737 if ($res === false) { 738 // Returned error 739 $this->setError($php_errormsg); 740 $retval = false; 741 $remaining = 0; 742 } elseif ($res === 0) { 743 // Wrote nothing? 744 $remaining = 0; 745 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_NO_DATA_WRITTEN')); 746 } else { 747 // Wrote something 748 $start += $amount; 749 $remaining -= $res; 750 } 751 } while ($remaining); 752 753 // Restore error tracking to what it was before. 754 ini_set('track_errors', $track_errors); 755 756 // Return the result 757 return $retval; 758 } 759 760 /** 761 * Chmod wrapper 762 * 763 * @param string $filename File name. 764 * @param mixed $mode Mode to use. 765 * 766 * @return boolean 767 * 768 * @since 1.7.0 769 */ 770 public function chmod($filename = '', $mode = 0) 771 { 772 if (!$filename) { 773 if (!isset($this->filename) || !$this->filename) { 774 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILENAME')); 775 776 return false; 777 } 778 779 $filename = $this->filename; 780 } 781 782 // If no mode is set use the default 783 if (!$mode) { 784 $mode = $this->filemode; 785 } 786 787 $retval = false; 788 789 // Capture PHP errors 790 $php_errormsg = ''; 791 $track_errors = ini_get('track_errors'); 792 ini_set('track_errors', true); 793 $sch = parse_url($filename, PHP_URL_SCHEME); 794 795 // Scheme specific options; ftp's chmod support is fun. 796 switch ($sch) { 797 case 'ftp': 798 case 'ftps': 799 $res = FilesystemHelper::ftpChmod($filename, $mode); 800 break; 801 802 default: 803 $res = chmod($filename, $mode); 804 break; 805 } 806 807 // Seek, interestingly, returns 0 on success or -1 on failure 808 if (!$res) { 809 $this->setError($php_errormsg); 810 } else { 811 $retval = true; 812 } 813 814 // Restore error tracking to what it was before. 815 ini_set('track_errors', $track_errors); 816 817 // Return the result 818 return $retval; 819 } 820 821 /** 822 * Get the stream metadata 823 * 824 * @return array|boolean header/metadata 825 * 826 * @link https://www.php.net/manual/en/function.stream-get-meta-data.php 827 * @since 1.7.0 828 */ 829 public function get_meta_data() 830 { 831 if (!$this->fh) { 832 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_FILE_NOT_OPEN')); 833 834 return false; 835 } 836 837 return stream_get_meta_data($this->fh); 838 } 839 840 /** 841 * Stream contexts 842 * Builds the context from the array 843 * 844 * @return mixed 845 * 846 * @since 1.7.0 847 */ 848 public function _buildContext() 849 { 850 // According to the manual this always works! 851 if (\count($this->contextOptions)) { 852 $this->context = @stream_context_create($this->contextOptions); 853 } else { 854 $this->context = null; 855 } 856 } 857 858 /** 859 * Updates the context to the array 860 * 861 * Format is the same as the options for stream_context_create 862 * 863 * @param array $context Options to create the context with 864 * 865 * @return void 866 * 867 * @link https://www.php.net/stream_context_create 868 * @since 1.7.0 869 */ 870 public function setContextOptions($context) 871 { 872 $this->contextOptions = $context; 873 $this->_buildContext(); 874 } 875 876 /** 877 * Adds a particular options to the context 878 * 879 * @param string $wrapper The wrapper to use 880 * @param string $name The option to set 881 * @param string $value The value of the option 882 * 883 * @return void 884 * 885 * @link https://www.php.net/stream_context_create Stream Context Creation 886 * @link https://www.php.net/manual/en/context.php Context Options for various streams 887 * @since 1.7.0 888 */ 889 public function addContextEntry($wrapper, $name, $value) 890 { 891 $this->contextOptions[$wrapper][$name] = $value; 892 $this->_buildContext(); 893 } 894 895 /** 896 * Deletes a particular setting from a context 897 * 898 * @param string $wrapper The wrapper to use 899 * @param string $name The option to unset 900 * 901 * @return void 902 * 903 * @link https://www.php.net/stream_context_create 904 * @since 1.7.0 905 */ 906 public function deleteContextEntry($wrapper, $name) 907 { 908 // Check whether the wrapper is set 909 if (isset($this->contextOptions[$wrapper])) { 910 // Check that entry is set for that wrapper 911 if (isset($this->contextOptions[$wrapper][$name])) { 912 // Unset the item 913 unset($this->contextOptions[$wrapper][$name]); 914 915 // Check that there are still items there 916 if (!\count($this->contextOptions[$wrapper])) { 917 // Clean up an empty wrapper context option 918 unset($this->contextOptions[$wrapper]); 919 } 920 } 921 } 922 923 // Rebuild the context and apply it to the stream 924 $this->_buildContext(); 925 } 926 927 /** 928 * Applies the current context to the stream 929 * 930 * Use this to change the values of the context after you've opened a stream 931 * 932 * @return mixed 933 * 934 * @since 1.7.0 935 */ 936 public function applyContextToStream() 937 { 938 $retval = false; 939 940 if ($this->fh) { 941 // Capture PHP errors 942 $php_errormsg = 'Unknown error setting context option'; 943 $track_errors = ini_get('track_errors'); 944 ini_set('track_errors', true); 945 $retval = @stream_context_set_option($this->fh, $this->contextOptions); 946 947 if (!$retval) { 948 $this->setError($php_errormsg); 949 } 950 951 // Restore error tracking to what it was before 952 ini_set('track_errors', $track_errors); 953 } 954 955 return $retval; 956 } 957 958 /** 959 * Stream filters 960 * Append a filter to the chain 961 * 962 * @param string $filterName The key name of the filter. 963 * @param integer $readWrite Optional. Defaults to STREAM_FILTER_READ. 964 * @param array $params An array of params for the stream_filter_append call. 965 * 966 * @return mixed 967 * 968 * @link https://www.php.net/manual/en/function.stream-filter-append.php 969 * @since 1.7.0 970 */ 971 public function appendFilter($filterName, $readWrite = STREAM_FILTER_READ, $params = array()) 972 { 973 $res = false; 974 975 if ($this->fh) { 976 // Capture PHP errors 977 $php_errormsg = ''; 978 $track_errors = ini_get('track_errors'); 979 ini_set('track_errors', true); 980 981 $res = @stream_filter_append($this->fh, $filterName, $readWrite, $params); 982 983 if (!$res && $php_errormsg) { 984 $this->setError($php_errormsg); 985 } else { 986 $this->filters[] = &$res; 987 } 988 989 // Restore error tracking to what it was before. 990 ini_set('track_errors', $track_errors); 991 } 992 993 return $res; 994 } 995 996 /** 997 * Prepend a filter to the chain 998 * 999 * @param string $filterName The key name of the filter. 1000 * @param integer $readWrite Optional. Defaults to STREAM_FILTER_READ. 1001 * @param array $params An array of params for the stream_filter_prepend call. 1002 * 1003 * @return mixed 1004 * 1005 * @link https://www.php.net/manual/en/function.stream-filter-prepend.php 1006 * @since 1.7.0 1007 */ 1008 public function prependFilter($filterName, $readWrite = STREAM_FILTER_READ, $params = array()) 1009 { 1010 $res = false; 1011 1012 if ($this->fh) { 1013 // Capture PHP errors 1014 $php_errormsg = ''; 1015 $track_errors = ini_get('track_errors'); 1016 ini_set('track_errors', true); 1017 $res = @stream_filter_prepend($this->fh, $filterName, $readWrite, $params); 1018 1019 if (!$res && $php_errormsg) { 1020 // Set the error msg 1021 $this->setError($php_errormsg); 1022 } else { 1023 array_unshift($res, ''); 1024 $res[0] = &$this->filters; 1025 } 1026 1027 // Restore error tracking to what it was before. 1028 ini_set('track_errors', $track_errors); 1029 } 1030 1031 return $res; 1032 } 1033 1034 /** 1035 * Remove a filter, either by resource (handed out from the append or prepend function) 1036 * or via getting the filter list) 1037 * 1038 * @param resource $resource The resource. 1039 * @param boolean $byindex The index of the filter. 1040 * 1041 * @return boolean Result of operation 1042 * 1043 * @since 1.7.0 1044 */ 1045 public function removeFilter(&$resource, $byindex = false) 1046 { 1047 // Capture PHP errors 1048 $php_errormsg = ''; 1049 $track_errors = ini_get('track_errors'); 1050 ini_set('track_errors', true); 1051 1052 if ($byindex) { 1053 $res = stream_filter_remove($this->filters[$resource]); 1054 } else { 1055 $res = stream_filter_remove($resource); 1056 } 1057 1058 if ($res && $php_errormsg) { 1059 $this->setError($php_errormsg); 1060 } 1061 1062 // Restore error tracking to what it was before. 1063 ini_set('track_errors', $track_errors); 1064 1065 return $res; 1066 } 1067 1068 /** 1069 * Copy a file from src to dest 1070 * 1071 * @param string $src The file path to copy from. 1072 * @param string $dest The file path to copy to. 1073 * @param resource $context A valid context resource (optional) created with stream_context_create. 1074 * @param boolean $usePrefix Controls the use of a prefix (optional). 1075 * @param boolean $relative Determines if the filename given is relative. Relative paths do not have JPATH_ROOT stripped. 1076 * 1077 * @return mixed 1078 * 1079 * @since 1.7.0 1080 */ 1081 public function copy($src, $dest, $context = null, $usePrefix = true, $relative = false) 1082 { 1083 // Capture PHP errors 1084 $php_errormsg = ''; 1085 $track_errors = ini_get('track_errors'); 1086 ini_set('track_errors', true); 1087 1088 $chmodDest = $this->_getFilename($dest, 'w', $usePrefix, $relative); 1089 1090 // Since we're going to open the file directly we need to get the filename. 1091 // We need to use the same prefix so force everything to write. 1092 $src = $this->_getFilename($src, 'w', $usePrefix, $relative); 1093 $dest = $this->_getFilename($dest, 'w', $usePrefix, $relative); 1094 1095 if ($context) { 1096 // Use the provided context 1097 $res = @copy($src, $dest, $context); 1098 } elseif ($this->context) { 1099 // Use the objects context 1100 $res = @copy($src, $dest, $this->context); 1101 } else { 1102 // Don't use any context 1103 $res = @copy($src, $dest); 1104 } 1105 1106 if (!$res && $php_errormsg) { 1107 $this->setError($php_errormsg); 1108 } else { 1109 $this->chmod($chmodDest); 1110 } 1111 1112 // Restore error tracking to what it was before 1113 ini_set('track_errors', $track_errors); 1114 1115 return $res; 1116 } 1117 1118 /** 1119 * Moves a file 1120 * 1121 * @param string $src The file path to move from. 1122 * @param string $dest The file path to move to. 1123 * @param resource $context A valid context resource (optional) created with stream_context_create. 1124 * @param boolean $usePrefix Controls the use of a prefix (optional). 1125 * @param boolean $relative Determines if the filename given is relative. Relative paths do not have JPATH_ROOT stripped. 1126 * 1127 * @return mixed 1128 * 1129 * @since 1.7.0 1130 */ 1131 public function move($src, $dest, $context = null, $usePrefix = true, $relative = false) 1132 { 1133 // Capture PHP errors 1134 $php_errormsg = ''; 1135 $track_errors = ini_get('track_errors'); 1136 ini_set('track_errors', true); 1137 1138 $src = $this->_getFilename($src, 'w', $usePrefix, $relative); 1139 $dest = $this->_getFilename($dest, 'w', $usePrefix, $relative); 1140 1141 if ($context) { 1142 // Use the provided context 1143 $res = @rename($src, $dest, $context); 1144 } elseif ($this->context) { 1145 // Use the object's context 1146 $res = @rename($src, $dest, $this->context); 1147 } else { 1148 // Don't use any context 1149 $res = @rename($src, $dest); 1150 } 1151 1152 if (!$res && $php_errormsg) { 1153 $this->setError($php_errormsg()); 1154 } 1155 1156 $this->chmod($dest); 1157 1158 // Restore error tracking to what it was before 1159 ini_set('track_errors', $track_errors); 1160 1161 return $res; 1162 } 1163 1164 /** 1165 * Delete a file 1166 * 1167 * @param string $filename The file path to delete. 1168 * @param resource $context A valid context resource (optional) created with stream_context_create. 1169 * @param boolean $usePrefix Controls the use of a prefix (optional). 1170 * @param boolean $relative Determines if the filename given is relative. Relative paths do not have JPATH_ROOT stripped. 1171 * 1172 * @return mixed 1173 * 1174 * @since 1.7.0 1175 */ 1176 public function delete($filename, $context = null, $usePrefix = true, $relative = false) 1177 { 1178 // Capture PHP errors 1179 $php_errormsg = ''; 1180 $track_errors = ini_get('track_errors'); 1181 ini_set('track_errors', true); 1182 1183 $filename = $this->_getFilename($filename, 'w', $usePrefix, $relative); 1184 1185 if ($context) { 1186 // Use the provided context 1187 $res = @unlink($filename, $context); 1188 } elseif ($this->context) { 1189 // Use the object's context 1190 $res = @unlink($filename, $this->context); 1191 } else { 1192 // Don't use any context 1193 $res = @unlink($filename); 1194 } 1195 1196 if (!$res && $php_errormsg) { 1197 $this->setError($php_errormsg()); 1198 } 1199 1200 // Restore error tracking to what it was before. 1201 ini_set('track_errors', $track_errors); 1202 1203 return $res; 1204 } 1205 1206 /** 1207 * Upload a file 1208 * 1209 * @param string $src The file path to copy from (usually a temp folder). 1210 * @param string $dest The file path to copy to. 1211 * @param resource $context A valid context resource (optional) created with stream_context_create. 1212 * @param boolean $usePrefix Controls the use of a prefix (optional). 1213 * @param boolean $relative Determines if the filename given is relative. Relative paths do not have JPATH_ROOT stripped. 1214 * 1215 * @return mixed 1216 * 1217 * @since 1.7.0 1218 */ 1219 public function upload($src, $dest, $context = null, $usePrefix = true, $relative = false) 1220 { 1221 if (is_uploaded_file($src)) { 1222 // Make sure it's an uploaded file 1223 return $this->copy($src, $dest, $context, $usePrefix, $relative); 1224 } else { 1225 $this->setError(Text::_('JLIB_FILESYSTEM_ERROR_STREAMS_NOT_UPLOADED_FILE')); 1226 1227 return false; 1228 } 1229 } 1230 1231 /** 1232 * Writes a chunk of data to a file. 1233 * 1234 * @param string $filename The file name. 1235 * @param string $buffer The data to write to the file. 1236 * 1237 * @return boolean 1238 * 1239 * @since 1.7.0 1240 */ 1241 public function writeFile($filename, &$buffer) 1242 { 1243 if ($this->open($filename, 'w')) { 1244 $result = $this->write($buffer); 1245 $this->chmod(); 1246 $this->close(); 1247 1248 return $result; 1249 } 1250 1251 return false; 1252 } 1253 1254 /** 1255 * Determine the appropriate 'filename' of a file 1256 * 1257 * @param string $filename Original filename of the file 1258 * @param string $mode Mode string to retrieve the filename 1259 * @param boolean $usePrefix Controls the use of a prefix 1260 * @param boolean $relative Determines if the filename given is relative. Relative paths do not have JPATH_ROOT stripped. 1261 * 1262 * @return string 1263 * 1264 * @since 1.7.0 1265 */ 1266 public function _getFilename($filename, $mode, $usePrefix, $relative) 1267 { 1268 if ($usePrefix) { 1269 // Get rid of binary or t, should be at the end of the string 1270 $tmode = trim($mode, 'btf123456789'); 1271 1272 // Check if it's a write mode then add the appropriate prefix 1273 // Get rid of JPATH_ROOT (legacy compat) along the way 1274 if (\in_array($tmode, FilesystemHelper::getWriteModes())) { 1275 if (!$relative && $this->writeprefix) { 1276 $filename = str_replace(JPATH_ROOT, '', $filename); 1277 } 1278 1279 $filename = $this->writeprefix . $filename; 1280 } else { 1281 if (!$relative && $this->readprefix) { 1282 $filename = str_replace(JPATH_ROOT, '', $filename); 1283 } 1284 1285 $filename = $this->readprefix . $filename; 1286 } 1287 } 1288 1289 return $filename; 1290 } 1291 1292 /** 1293 * Return the internal file handle 1294 * 1295 * @return resource File handler 1296 * 1297 * @since 1.7.0 1298 */ 1299 public function getFileHandle() 1300 { 1301 return $this->fh; 1302 } 1303 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |