581 lines
12 KiB
PHP
581 lines
12 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Invision Power Services
|
|
* IP.Board v3.0.5
|
|
* Wrapper for retrieving file contents. Methods available for removing files and directories as well.
|
|
* Last Updated: $Date: 2009-12-02 21:34:26 -0500 (Wed, 02 Dec 2009) $
|
|
*
|
|
* @author $Author: bfarber $
|
|
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
|
* @license http://www.iinvisionpower.com/community/board/license.html
|
|
* @package Invision Power Services Kernel
|
|
* @link http://www.iinvisionpower.com
|
|
* @since Tuesday 22nd February 2005 (16:55)
|
|
* @version $Revision: 350 $
|
|
*/
|
|
|
|
if ( ! defined( 'IPS_CLASSES_PATH' ) )
|
|
{
|
|
/**
|
|
* Define classes path
|
|
*/
|
|
define( 'IPS_CLASSES_PATH', dirname(__FILE__) );
|
|
}
|
|
|
|
class classFileManagement
|
|
{
|
|
/**
|
|
* Use sockets flag
|
|
*
|
|
* @access public
|
|
* @var integer
|
|
*/
|
|
public $use_sockets = 0;
|
|
|
|
/**
|
|
* Error array
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
public $errors = array();
|
|
|
|
/**
|
|
* HTTP Status Code/Text
|
|
*
|
|
* @access public
|
|
* @var integer HTTP Status code
|
|
* @var string HTTP Status text
|
|
*/
|
|
public $http_status_code = 0;
|
|
public $http_status_text = "";
|
|
|
|
/**#@+
|
|
* Set Authentication
|
|
*
|
|
* @access public
|
|
* @var string
|
|
* @var string
|
|
* @var string
|
|
*/
|
|
public $auth_req = 0;
|
|
public $auth_user;
|
|
public $auth_pass;
|
|
/**#@-*/
|
|
|
|
/**
|
|
* Timeout setting
|
|
*
|
|
* @access public
|
|
* @var int
|
|
*/
|
|
public $timeout = 15;
|
|
|
|
/**
|
|
* Get file contents (accepts URL or path)
|
|
*
|
|
* @access public
|
|
* @param string URI / File path
|
|
* @param string HTTP User
|
|
* @param string HTTP Pass
|
|
* @return string File data
|
|
*/
|
|
public function getFileContents( $file_location, $http_user='', $http_pass='' )
|
|
{
|
|
//-------------------------------
|
|
// INIT
|
|
//-------------------------------
|
|
|
|
$contents = "";
|
|
$file_location = str_replace( '&', '&', $file_location );
|
|
|
|
//-----------------------------------------
|
|
// Inline user/pass?
|
|
//-----------------------------------------
|
|
|
|
if ( $http_user and $http_pass )
|
|
{
|
|
$this->auth_req = 1;
|
|
$this->auth_user = $http_user;
|
|
$this->auth_pass = $http_pass;
|
|
}
|
|
|
|
//-------------------------------
|
|
// Hello
|
|
//-------------------------------
|
|
|
|
if ( ! $file_location )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( ! stristr( $file_location, 'http://' ) AND ! stristr( $file_location, 'https://' ) )
|
|
{
|
|
//-------------------------------
|
|
// It's a path!
|
|
//-------------------------------
|
|
|
|
if ( ! file_exists( $file_location ) )
|
|
{
|
|
$this->errors[] = "Файл '{$file_location}' не существует, Проверье правильность пути.";
|
|
return;
|
|
}
|
|
|
|
$contents = $this->_getContentsWithFopen( $file_location );
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------
|
|
// Is URL, try curl and then fall back
|
|
//-------------------------------
|
|
|
|
if( ($contents = $this->_getContentsWithCurl( $file_location )) === false )
|
|
{
|
|
if ( $this->use_sockets )
|
|
{
|
|
$contents = $this->_getContentsWithSocket( $file_location );
|
|
}
|
|
else
|
|
{
|
|
$contents = $this->_getContentsWithFopen( $file_location );
|
|
}
|
|
}
|
|
}
|
|
|
|
return $contents;
|
|
}
|
|
|
|
/**
|
|
* Get file contents (with PHP's fopen)
|
|
*
|
|
* @access private
|
|
* @param string File location
|
|
* @return string File data
|
|
*/
|
|
private function _getContentsWithFopen( $file_location )
|
|
{
|
|
//-------------------------------
|
|
// INIT
|
|
//-------------------------------
|
|
|
|
$buffer = "";
|
|
|
|
@clearstatcache();
|
|
|
|
if ( $FILE = fopen( $file_location, "r" ) )
|
|
{
|
|
@stream_set_timeout( $FILE, $this->timeout );
|
|
$status = @stream_get_meta_data($FILE);
|
|
|
|
while ( ! feof( $FILE ) && ! $status['timed_out'] )
|
|
{
|
|
$buffer .= fgets( $FILE, 4096 );
|
|
|
|
$status = stream_get_meta_data($FILE);
|
|
}
|
|
|
|
fclose($FILE);
|
|
}
|
|
|
|
if ( $buffer )
|
|
{
|
|
$this->http_status_code = 200;
|
|
}
|
|
|
|
return $buffer;
|
|
}
|
|
|
|
/**
|
|
* Get file contents (with sockets)
|
|
*
|
|
* @access private
|
|
* @param string File location
|
|
* @return string File data
|
|
*/
|
|
private function _getContentsWithSocket( $file_location )
|
|
{
|
|
//-------------------------------
|
|
// INIT
|
|
//-------------------------------
|
|
|
|
$data = null;
|
|
$fsocket_timeout = $this->timeout;
|
|
|
|
//-------------------------------
|
|
// Parse URL
|
|
//-------------------------------
|
|
|
|
$url_parts = @parse_url($file_location);
|
|
|
|
if ( ! $url_parts['host'] )
|
|
{
|
|
$this->errors[] = "Не найден хост в URL '{$file_location}'!";
|
|
return FALSE;
|
|
}
|
|
|
|
//-------------------------------
|
|
// Finalize
|
|
//-------------------------------
|
|
|
|
$host = $url_parts['host'];
|
|
$port = ( isset($url_parts['port']) ) ? $url_parts['port'] : ( $url_parts['scheme'] == 'https' ? 443 : 80 );
|
|
|
|
//-------------------------------
|
|
// Tidy up path
|
|
//-------------------------------
|
|
|
|
if ( !empty( $url_parts["path"] ) )
|
|
{
|
|
$path = $url_parts["path"];
|
|
}
|
|
else
|
|
{
|
|
$path = "/";
|
|
}
|
|
|
|
if ( !empty( $url_parts["query"] ) )
|
|
{
|
|
$path .= "?" . $url_parts["query"];
|
|
}
|
|
|
|
//-------------------------------
|
|
// Open connection
|
|
//-------------------------------
|
|
|
|
if ( ! $fp = @fsockopen( $host, $port, $errno, $errstr, $fsocket_timeout ) )
|
|
{
|
|
$this->errors[] = "Не могу установить соединение с {$host}";
|
|
return FALSE;
|
|
|
|
}
|
|
else
|
|
{
|
|
$final_carriage = "";
|
|
|
|
if ( ! $this->auth_req )
|
|
{
|
|
$final_carriage = "\r\n";
|
|
}
|
|
|
|
if ( ! fputs( $fp, "GET $path HTTP/1.0\r\nHost:$host\r\nConnection: Keep-Alive\r\n{$final_carriage}" ) )
|
|
{
|
|
$this->errors[] = "Невозможно отправить запрос на $host!";
|
|
return FALSE;
|
|
}
|
|
|
|
if ( $this->auth_req )
|
|
{
|
|
if ( $this->auth_user && $this->auth_pass )
|
|
{
|
|
$header = "Authorization: Basic ".base64_encode("{$this->auth_user}:{$this->auth_pass}")."\r\n\r\n";
|
|
|
|
if ( ! fputs( $fp, $header ) )
|
|
{
|
|
$this->errors[] = "Неверные данные авторизации!";
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@stream_set_timeout($fp, $fsocket_timeout);
|
|
|
|
$status = @stream_get_meta_data($fp);
|
|
|
|
while( ! feof($fp) && ! $status['timed_out'] )
|
|
{
|
|
$data .= fgets ($fp,8192);
|
|
$status = stream_get_meta_data($fp);
|
|
}
|
|
|
|
fclose ($fp);
|
|
|
|
//-------------------------------
|
|
// Strip headers
|
|
//-------------------------------
|
|
|
|
// HTTP/1.1 ### ABCD
|
|
$this->http_status_code = substr( $data, 9, 3 );
|
|
$this->http_status_text = substr( $data, 13, ( strpos( $data, "\r\n" ) - 13 ) );
|
|
|
|
//-----------------------------------------
|
|
// Try to deal with chunked..
|
|
//-----------------------------------------
|
|
|
|
$_chunked = false;
|
|
|
|
if( preg_match( "/Transfer\-Encoding:\s*chunked/i", $data ) )
|
|
{
|
|
$_chunked = true;
|
|
}
|
|
|
|
$tmp = split("\r\n\r\n", $data, 2);
|
|
$data = trim($tmp[1]);
|
|
|
|
//-----------------------------------------
|
|
// Easy way out :P
|
|
//-----------------------------------------
|
|
|
|
if( $_chunked )
|
|
{
|
|
$lines = explode( "\n", $data );
|
|
array_pop($lines);
|
|
array_shift($lines);
|
|
$data = implode( "\n", $lines );
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Get file contents (with cURL)
|
|
*
|
|
* @access private
|
|
* @param string File location
|
|
* @return string File data
|
|
*/
|
|
private function _getContentsWithCurl( $file_location )
|
|
{
|
|
if ( function_exists( 'curl_init' ) AND function_exists("curl_exec") )
|
|
{
|
|
$ch = curl_init( $file_location );
|
|
|
|
curl_setopt( $ch, CURLOPT_HEADER , 0);
|
|
curl_setopt( $ch, CURLOPT_TIMEOUT , $this->timeout );
|
|
curl_setopt( $ch, CURLOPT_POST , 0 );
|
|
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
|
|
curl_setopt( $ch, CURLOPT_FAILONERROR , 1 );
|
|
curl_setopt( $ch, CURLOPT_MAXREDIRS , 10 );
|
|
|
|
/**
|
|
* Cannot set this when safe_mode or open_basedir is enabled
|
|
* @link http://forums.invisionpower.com/index.php?autocom=tracker&showissue=11334
|
|
*/
|
|
if( !ini_get('open_basedir') AND !ini_get('safe_mode') )
|
|
{
|
|
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 );
|
|
}
|
|
|
|
if( $this->auth_req )
|
|
{
|
|
curl_setopt( $ch, CURLOPT_USERPWD , "{$this->auth_user}:{$this->auth_pass}" );
|
|
}
|
|
|
|
$data = curl_exec($ch);
|
|
curl_close($ch);
|
|
|
|
if ( $data )
|
|
{
|
|
$this->http_status_code = 200;
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Copies contents of one directory to another, creating if necessary
|
|
*
|
|
* @access public
|
|
* @param string File location [from]
|
|
* @param string File location [destination]
|
|
* @param string [Optional] CHMOD mode to set
|
|
* @return boolean Copy successful
|
|
*/
|
|
public function copyDirectory($from_path, $to_path, $mode = 0777)
|
|
{
|
|
$this->errors = array();
|
|
|
|
//-----------------------------------------
|
|
// Strip off trailing slashes...
|
|
//-----------------------------------------
|
|
|
|
$from_path = rtrim( $from_path, '/' );
|
|
$to_path = rtrim( $to_path, '/' );
|
|
|
|
if ( ! is_dir( $from_path ) )
|
|
{
|
|
$this->errors[] = "Невозможно найти директорию '{$from_path}'";
|
|
return false;
|
|
}
|
|
|
|
if ( ! is_dir( $to_path ) )
|
|
{
|
|
if ( ! @mkdir( $to_path, $mode ) )
|
|
{
|
|
$this->errors[] = "Невозможно создать директорию '{$to_path}', проверьте права доступа и попробуйте снова";
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
@chmod( $to_path, $mode );
|
|
}
|
|
}
|
|
|
|
if ( is_dir( $from_path ) )
|
|
{
|
|
$handle = opendir($from_path);
|
|
|
|
while ( ($file = readdir($handle)) !== false )
|
|
{
|
|
if ( ($file != ".") && ($file != "..") )
|
|
{
|
|
if ( is_dir( $from_path."/".$file ) )
|
|
{
|
|
$this->copyDirectory( $from_path."/".$file, $to_path."/".$file );
|
|
}
|
|
|
|
if ( is_file( $from_path."/".$file ) )
|
|
{
|
|
copy( $from_path."/".$file, $to_path."/".$file );
|
|
@chmod( $to_path."/".$file, 0777 );
|
|
}
|
|
}
|
|
}
|
|
|
|
closedir($handle);
|
|
}
|
|
|
|
if ( ! count( $this->errors ) )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes a directory
|
|
*
|
|
* @access public
|
|
* @param string File location [from]
|
|
* @return boolean Removal successful
|
|
*/
|
|
public function removeDirectory($file)
|
|
{
|
|
$errors = 0;
|
|
|
|
//-----------------------------------------
|
|
// Remove trailing slashes..
|
|
//-----------------------------------------
|
|
|
|
$file = rtrim( $file, '/' );
|
|
|
|
if ( file_exists($file) )
|
|
{
|
|
//-----------------------------------------
|
|
// Attempt CHMOD
|
|
//-----------------------------------------
|
|
|
|
@chmod( $file, 0777 );
|
|
|
|
if ( is_dir( $file ) )
|
|
{
|
|
$handle = opendir( $file );
|
|
|
|
while ( ($filename = readdir($handle)) !== false )
|
|
{
|
|
if ( ($filename != ".") && ($filename != "..") )
|
|
{
|
|
$this->removeDirectory( $file."/".$filename );
|
|
}
|
|
}
|
|
|
|
closedir($handle);
|
|
|
|
if ( ! @rmdir($file) )
|
|
{
|
|
$errors++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ! @unlink($file) )
|
|
{
|
|
$errors++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( $errors == 0 )
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Empties a directory
|
|
*
|
|
* @access public
|
|
* @param string File location [from]
|
|
* @param int In a loop (not root folder)
|
|
* @return boolean Empty successful
|
|
*/
|
|
public function emptyDirectory($file, $inLoop=0)
|
|
{
|
|
$errors = 0;
|
|
|
|
//-----------------------------------------
|
|
// Remove trailing slashes..
|
|
//-----------------------------------------
|
|
|
|
$file = rtrim( $file, '/' );
|
|
|
|
if ( file_exists($file) )
|
|
{
|
|
//-----------------------------------------
|
|
// Attempt CHMOD
|
|
//-----------------------------------------
|
|
|
|
@chmod( $file, 0777 );
|
|
|
|
if ( is_dir( $file ) )
|
|
{
|
|
$handle = opendir( $file );
|
|
|
|
while ( ($filename = readdir($handle)) !== false )
|
|
{
|
|
if ( ($filename != ".") && ($filename != "..") )
|
|
{
|
|
$this->emptyDirectory( $file."/".$filename, 1 );
|
|
}
|
|
}
|
|
|
|
closedir($handle);
|
|
|
|
if ( $inLoop )
|
|
{
|
|
if ( ! @rmdir($file) )
|
|
{
|
|
$errors++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ! @unlink($file) )
|
|
{
|
|
$errors++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( $errors == 0 )
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
} |