Вход Регистрация
Файл: ips_kernel/classXMLArchive.php
Строк: 399
<?php

/**
 * <pre>
 * Invision Power Services
 * IP.Board v3.3.3
 * XML Archive Hanlder: Can create XML Archives (gzips) of multiple files, binary and ascii
 * Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
 * </pre>
 *
 * @author         $Author: bfarber $
 * @copyright    (c) 2001 - 2009 Invision Power Services, Inc.
 * @license        http://www.invisionpower.com/company/standards.php#license
 * @package        IP.Board
 * @subpackage    Kernel
 * @link        http://www.invisionpower.com
 * @since        25th February 2004
 * @version        $Revision: 10721 $
 *
 *
 * Example Usage:
 * <code>
 * Sample file set:
 *
 * someDir/
 * someDir/index.html
 * someDir/file.html
 * someDir/images/
 * someDir/images/pic.jpg
 * anotherDir/
 * anotherDir/anotherFile.html
 *
 * # READING ARCHIVE
 * $archive = new classXMLArchive();
 * try
 * {
 *    $archive->read( "/path/to/archive.xml" );
 * }
 * catch ( Exception $err ) {}
 *
 * print $archive->getFile('someDir/file.html');
 * print_r( $archive->asArray() );
 *
 * # CREATING ARCHIVE
 *
 * $archive = new classXMLArchive();
 *
 * try
 * {
 *    $archive->add( "someDir" );
 *  $archive->add( "anotherDir/anotherFile.html" );
 *  $archive->add( "Create a new file from scratch!", "anotherDir/brandNewFile.html" );
 * }
 * catch ( Exception $err ) {}
 *
 * # Save gzipped
 * $archive->saveGZIP( "/path/to/archive.xml.gzip" );
 * # Save normally
 * $archive->save( "/path/to/archive.xml" );
 * # Just return the data
 * $archive->getArchiveContents();
 * </code>
 *
 *
 * Exception Codes:
 * <ul>
 * <li>FILE_OR_DIR_NOT_EXISTS: No such directory or file
 * <li>NOT_A_DIR: Not a directory
 * <li>CANNOT_WRITE_TO_DISK: Could not write archive to disk
 * <li>NOTHING_TO_SAVE: No XML document to save
 * <li>COULD_NOT_LOAD_XML_DATA: Could not load xml data
 * <li>WRITE_NOT_VALID_INPUT: The input (XML or filename) is not valid
 * <li>NO_FILES_TO_WRITE: The archive contains nothing to write back
 * </ul>
 *
 */

class classXMLArchive
{
    
/**
     * XML Object
     *
     * @var         object
     */
    
protected $_xml                = null;
    
    
/**
     * File array
     *
     * @var         array
     */
    
public $_fileArray        = array();
    
    
/**
     * Error number
     *
     * @var         integer
     */
    
public $error_number      = 0;
    
    
/**
     * Error message
     *
     * @var         string
     */
    
public $error_message     = "";
    
    
/**
     * Work files
     *
     * @var         array
     */
    
public $_workFiles    = array();
    
    
/**
     * Non binary file extensions
     *
     * @var         string
     */
    
public $non_binary        = 'txt htm html xml css js cgi php php3';
    
    
/**
     * Strip path
     *
     * @var         string
     */
    
public $_stripPathString        = "";
    
    
/**
     * Allow hidden files
     *
     * @var        boolean
     */
    
protected $_allowHiddenFiles  = FALSE;
    
    
/**
     * Root tag values
     *
     * @var        array
     */
    
protected $_defaultRootValues = array();
    
    
/**
     * Constructor
     *
     * @param    string        Script root path
     * @return    @e void
     */
    
public function __construct()
    {
        
//-----------------------------------
        // Get the XML class
        //-----------------------------------
        
        
require_once( dirname( __FILE__ ) . '/classXML.php' );/*noLibHook*/
        
$this->_xml = new classXML( IPS_DOC_CHAR_SET );
        
        
/* Set up the root values */
        
$this->_defaultRootValues = array( 'generator' => 'IPS_KERNEL', 'created' => time() );
        
        
$this->error_number = 0;
    }
    
    
/**
     * Adds values to the root tag
     *
     * @return    @e void
     */
    
public function addRootTagValues( $array=array() )
    {
        if ( 
is_array( $array ) AND count( $array ) )
        {
            foreach( 
$array as $k => $v )
            {
                if ( 
$k and $v != '' )
                {
                    
$this->_defaultRootValues[ $k ] = $v;
                }
            }
        }
    }

    
/**
     * Allow hidden files to be added when using addDir
     *
     * @return    @e void
     */
    
public function allowHiddenFiles()
    {
        
$this->_allowHiddenFiles = TRUE;
    }
    
    
/**
     * Set the path to 'strip' from the path data
     *
     * @param    string        Full path to remove
     * @return    @e void
     */
    
public function setStripPath( $path )
    {
        
/* Ensure that there is no trailing slash */
        
$path = rtrim( $path, '/' );
        
        
$this->_stripPathString = $path;
    }
    
    
/**
     * Return file data as array
     *
     * @return    @e array
     */
    
public function asArray()
    {
        return 
$this->_fileArray;
    }
    
    
/**
     * Return a file from the fileArray
     *
     * @param    string    Key
     * @return    @e string
     */
    
public function getFile( $key )
    {
        if ( isset( 
$this->_fileArray[ $key ] ) )
        {
            return 
$this->_fileArray[ $key ]['content'];
        }
        else
        {
            return 
'';
        }
    }
    
    
/**
     * Return number of files contained in the expanded archive
     *
     * @return    @e integer
     */
    
public function countFileArray()
    {
        return 
intval( count( $this->_fileArray ) );
    }
    
    
/**
     * Read an XML document from disk
     *
     * @param    string    File name
     * @return    @e void
     */
    
public function read( $filename )
    {
        if ( 
is_file( $filename ) )
        {
            if ( 
strstr( $filename, '.gz' ) )
            {
                if ( 
$FH = @gzopen( $filename, 'r' ) )
                {
                    
$data = @gzread( $FH, $filename );
                    @
gzclose( $FH );
                }
                else
                {
                    throw new 
Exception( "COULD_NOT_LOAD_XML_DATA" );
                }
            }
            else
            {
                if ( 
$FH = @fopen( $filename, 'r' ) )
                {
                    
$data = @fread( $FH, filesize( $filename ) );
                    @
fclose( $FH );
                }
                else
                {
                    throw new 
Exception( "COULD_NOT_LOAD_XML_DATA" );
                }
            }
            
            
$this->readXML( $data );
        }
        else
        {
            throw new 
Exception( "FILE_OR_DIR_NOT_EXISTS" );
        }
    }
    
    
/**
     * Read an XML document from passed data
     *
     * @param    string    Raw XML Data
     * @return    @e void
     */
    
public function readXML( $data )
    {
        if ( 
$data )
        {
            
$this->_xml->loadXML( $data );
            
            foreach( 
$this->_xml->fetchElements('file') as $file )
            {
                
$_file = $this->_xml->fetchElementsFromRecord( $file );
                
$_file['content'] = base64_decode( preg_replace( "/s/", "", $_file['content'] ) );
                
                
$this->_fileArray[ ltrim( $_file['path'] . '/' . $_file['filename'], '/' ) ] = $_file;
            }
        }
    }
    
    
/**
     * Write out the XML document as a GZIP file
     *
     * @param    string    Filename
     * @return    @e void
     */
    
public function saveGZIP( $filename )
    {
        
$this->_create();
        
        if ( 
$this->_xml->fetchDocument() )
        {
            if ( 
$FH = @gzopen( $filename, 'wb' ) )
            {
                @
gzwrite( $FH, $this->_xml->fetchDocument() );
                @
gzclose( $FH );
            }
            else
            {
                throw new 
Exception( "CANNOT_WRITE_TO_DISK" );
            }
        }
        else
        {
            throw new 
Exception( "NOTHING_TO_SAVE" );
        }
    }
    
    
/**
     * Write out the XML document as a normal file
     *
     * @param    string    FIlename
     * @return    @e void
     */
    
public function save( $filename )
    {
        
$this->_create();
        
        
$_doc = $this->_xml->fetchDocument();
        
        if ( 
$_doc )
        {
            if ( 
$FH = @fopen( $filename, 'wb' ) )
            {
                @
fwrite( $FH, $_doc );
                @
fclose( $FH );
            }
            else
            {
                throw new 
Exception( "CANNOT_WRITE_TO_DISK" );
            }
        }
        else
        {
            throw new 
Exception( "NOTHING_TO_SAVE" );
        }
    }
    
    
/**
     * Method of getting XML document from this class
     *
     * @return    string    XML document
     */
    
public function getArchiveContents()
    {
        
$this->_create();
        return 
$this->_xml->fetchDocument();
    }
    
    
/**
     * Write the archive back to disk
     *
     * Note: Ensure that if you intend to make XMLArchives available for others
     * that you create it with setStripPath otherwise you may get unexpected results!
     *
     * @param    mixed        Filename (must end with .xml or .gz) or raw data
     * @param    string        Base path to write to
     * @return    @e boolean
     * @throws    Exception
     *
     * Exception Codes:
     * WRITE_NOT_VALID_INPUT        The input (XML or filename) is not valid
     * NO_FILES_TO_WRITE            The archive contains nothing to write back
     */
    
public function write( $input, $basePath='/' )
    {
        
/* Gather the data */
        
if ( substr( $input, -3 ) == '.gz' OR substr( $input, -3 ) == '.xml' )
        {
            try
            {
                
$this->read( $input );
            }
            catch( 
Exception $e )
            {
                return 
$e->getMessage();
            }
        }
        else if ( 
strstr( $input, '<xmlarchive' ) )
        {
            
$this->readXML( $input );
        }
        else
        {
            throw new 
Exception( "WRITE_NOT_VALID_INPUT" );
        }
        
        
/* Did we get anything? */
        
if ( ! $this->countFileArray() )
        {
            throw new 
Exception( "NO_FILES_TO_WRITE" );
        }
        
        
$basePath = rtrim( $basePath, '/' );
        
        
/* So, write 'em! */
        
$files = $this->asArray();
        
        foreach( 
$files as $path => $data )
        {
            
$path = trim( $path, '/' );
            
            if ( 
$this->_writeContents( $basePath . '/' . $path, $data['content'] ) !== TRUE )
            {
                return 
FALSE;
            }
        }
        
        
/* Done */
        
return TRUE;
    }
    
    
/**
     * Main "Add" function  handles a lot of stuff.
     * It's good like that!
     *
     * @param    string        Filename or data
     * @param    string        File to store as
     * @return    @e mixed
     */
    
public function add( $data, $saveName='' )
    {
        
/* Is this just data? */
        
if ( $saveName )
        {
            return 
$this->addData( $data, $saveName );
        }
        else if ( 
is_dir( $data ) )
        {
            return 
$this->addDirectory( $data );
        }
        else
        {
            return 
$this->addFile( $data );
        }
    }
    
    
/**
     * Shorthand function
     *
     * @return    @e mixed
     * @see        addDirectory()
     */
    
public function addDir( $dir )
    {
        return 
$this->addDirectory( $dir );
    }
    
    
/**
     * Add directory to archive
     *
     * @param    string        Directory to add
     * @return    @e mixed
     * @throws    Exception
     */
    
public function addDirectory( $dir )
    {
        
//-----------------------------------
        // Got dir?
        //-----------------------------------
        
        
if ( ! is_dir($dir) )
        {
            throw new 
Exception( "FILE_OR_DIR_NOT_EXISTS" );
            return 
false;
        }
        
        
$dir = rtrim( $dir, '/' );
        
        
//-----------------------------------
        // Populate this->workfiles
        //-----------------------------------
        
        
$this->_workFiles = array();
        
$this->_getDirContents( $dir );
        
        
//-----------------------------------
        // Add them into the file array
        //-----------------------------------
        
        
foreach ( $this->_workFiles as $f )
        {
            
$this->addFile( $f );
        }
        
        
$this->_workFiles = array();
    }
    
    
/**
     * Add file to archive
     *
     * @param    string        File to add
     * @param    array         Extra tags
     * @return    @e mixed
     */
    
public function addFile( $filename, $extra_tags=array() )
    {
        
//-----------------------------------
        // Kill hidden files
        //-----------------------------------
        
        
$_temp = explode( '/', $filename );
        
        
$actual_file = array_pop( $_temp );
        
        if ( 
in_array( strtolower($actual_file), array( '.ds_store', 'thumbs.db' ) ) )
        {
            return 
false;
        }

        if ( 
file_exists( $filename ) )
        {
            if ( 
$FH = @fopen( $filename, 'rb' ) )
            {
                
$data = @fread( $FH, filesize( $filename ) );
                @
fclose( $FH );
            }
            
            
$this->addData( $data, $filename, $extra_tags );
        }
        else
        {
            throw new 
Exception( "FILE_OR_DIR_NOT_EXISTS" );
        }
    }

    
/**
     * Add filecontents to archive
     *
     * @param    string        File data
     * @param    string        File name
     * @param    array         Extra tags
     * @return    @e void
     */
    
public function addData( $data, $filename, $extra_tags=array() )
    {
        
$ext = preg_replace( "/.*.(.+?)$/", "\1", $filename );
        
        
$binary = 1;
        
        
//-----------------------------------
        // ASCII?
        //-----------------------------------
        
        
if ( strstr( ' ' . $this->non_binary . ' ', ' '.$ext.' ' ) )
        {
            
$binary = 0;
        }
        
        
//-----------------------------------
        // Get dir / filename
        //-----------------------------------
        
        
$dir_path = array();
        
$dir_path = explode( "/", $filename );
        
        if ( 
count( $dir_path ) )
        {
            
$real_filename = array_pop( $dir_path );
        }
        
        
$real_filename = $real_filename ? $real_filename : $filename;
        
        
$path = implode( "/", $dir_path );
        
        
$path = $this->_stripPath( $path );
        
        
$this_array = array(
                            
'filename'    => $real_filename,
                            
'content'    => $data,
                            
'path'        => $path,
                            
'binary'    => $binary
                          
);
                          
        foreach( 
$extra_tags as $k => $v )
        {
            if ( 
$k and ! in_array( $k, array_keys($this_array) ) )
            {
                
$this_array[ $k ] = $v;
            }
        }
        
        
$this->_fileArray[] = $this_array;
    }
    
    
/**
     * Create the XML archive
     *
     * @return    @e void
     */
    
protected function _create()
    {
        
$this->_xml->newXMLDocument();
        
$this->_xml->addElement( 'xmlarchive', '', (array)$this->_defaultRootValues );
        
$this->_xml->addElement( 'fileset', 'xmlarchive' );
        
        foreach( 
$this->_fileArray as $f )
        {
            
$f['content'] = chunk_split(base64_encode($f['content']));
            
            
$this->_xml->addElementAsRecord( 'fileset', 'file', $f );
        }
    }
    
    
/**
     * Write contents of a file to disk
     * Creates directories, etc as it goes
     *
     * @param    string        Path with filename to write to
     * @param    string        Data to write
     * @return    @e boolean
     */
    
protected function _writeContents( $path, $content )
    {
        
$path      = $this->_stripPath( $path );
        
$_path     = DOC_IPS_ROOT_PATH;
        
$_dirParts = explode( '/', str_replace( DOC_IPS_ROOT_PATH, '', $path ) );
        
$file      = array_pop( $_dirParts );

        foreach( 
$_dirParts as $_p )
        {
            
$_path .= '/' . $_p;
            
            if ( ! 
is_dir( $_path ) )
            {
                if ( ! @
mkdir( $_path, IPS_FOLDER_PERMISSION ) )
                {
                    return 
FALSE;
                }
                else
                {
                    @
chmod( $_path, IPS_FOLDER_PERMISSION );
                }
            }
        }
        
        if ( ! @
file_put_contents( $_path . '/' . $file, $content ) )
        {
            return 
FALSE;
        }
        
        @
chmod( $_path . '/' . $file, IPS_FILE_PERMISSION );
        
        return 
TRUE;
    }
    
    
/**
     * Strip path information from the real path
     *
     * @param    string        Input path
     * @return    @e string
     */
    
protected function _stripPath( $path )
    {
        if ( 
$this->_stripPathString )
        {
            
$path = trim( str_ireplace( $this->_stripPathString, '', $path ), '/' );
        }
    
        return 
$path;
    }
    
    
/**
     * Get directory contents
     *
     * @param    string        Directory
     * @return    @e boolean
     */
    
protected function _getDirContents( $dir )
    {
        if ( 
file_exists( $dir ) AND is_dir( $dir ) )
        {
            try
            {
                foreach( new 
DirectoryIterator( $dir ) as $file )
                {
                    if ( ! 
$file->isDot() )
                    {
                        
$filename = $file->getFileName();
                
                        
/* Allow files? */
                        
if ( $this->_allowHiddenFiles !== TRUE )
                        {
                            if ( 
substr( $filename, 0, 1 ) == '.' )
                            {
                                continue;
                            }
                        }
                
                        if ( 
is_dir( $dir."/".$filename ) )
                        {
                            
$this->_getDirContents( $dir . "/" . $filename );
                        }
                        else
                        {
                            
$this->_workFiles[] = $dir . "/" . $filename;
                        }
                    }
                }
            } catch ( 
Exception $e ) {}
                
            return 
true;
        }
        else
        {
            throw new 
Exception( "FILE_OR_DIR_NOT_EXISTS" );
            return 
false;
        }
    }
}
Онлайн: 4
Реклама