PclZip::privExtractFile PHP Method

privExtractFile() public method

--------------------------------------------------------------------------------
public privExtractFile ( &$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options )
    public function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
    {
        $v_result = 1;
        // ----- Read the file header
        if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
            // ----- Return
            return $v_result;
        }
        // ----- Check that the file header is coherent with $p_entry info
        if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
            // TBC
        }
        // ----- Look for all path to remove
        if ($p_remove_all_path == true) {
            // ----- Look for folder entry that not need to be extracted
            if (($p_entry['external'] & 0x10) == 0x10) {
                $p_entry['status'] = 'filtered';
                return $v_result;
            }
            // ----- Get the basename of the path
            $p_entry['filename'] = basename($p_entry['filename']);
        } elseif ($p_remove_path != '') {
            if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2) {
                // ----- Change the file status
                $p_entry['status'] = 'filtered';
                // ----- Return
                return $v_result;
            }
            $p_remove_path_size = strlen($p_remove_path);
            if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path) {
                // ----- Remove the path
                $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
            }
        }
        // ----- Add the path
        if ($p_path != '') {
            $p_entry['filename'] = $p_path . '/' . $p_entry['filename'];
        }
        // ----- Check a base_dir_restriction
        if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) {
            $v_inclusion = PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION], $p_entry['filename']);
            if ($v_inclusion == 0) {
                PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION, "Filename '" . $p_entry['filename'] . "' is " . 'outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION');
                return PclZip::errorCode();
            }
        }
        // ----- Look for pre-extract callback
        if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
            // ----- Generate a local information
            $v_local_header = array();
            $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
            // ----- Call the callback
            // Here I do not use call_user_func() because I need to send a reference to the
            // header.
            //      eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
            $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
            if ($v_result == 0) {
                // ----- Change the file status
                $p_entry['status'] = 'skipped';
                $v_result = 1;
            }
            // ----- Look for abort result
            if ($v_result == 2) {
                // ----- This status is internal and will be changed in 'skipped'
                $p_entry['status'] = 'aborted';
                $v_result = PCLZIP_ERR_USER_ABORTED;
            }
            // ----- Update the informations
            // Only some fields can be modified
            $p_entry['filename'] = $v_local_header['filename'];
        }
        // ----- Look if extraction should be done
        if ($p_entry['status'] == 'ok') {
            // ----- Look for specific actions while the file exist
            if (file_exists($p_entry['filename'])) {
                // ----- Look if file is a directory
                if (is_dir($p_entry['filename'])) {
                    // ----- Change the file status
                    $p_entry['status'] = 'already_a_directory';
                    // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
                    // For historical reason first PclZip implementation does not stop
                    // when this kind of error occurs.
                    if (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]) && $p_options[PCLZIP_OPT_STOP_ON_ERROR] === true) {
                        PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY, "Filename '" . $p_entry['filename'] . "' is " . 'already used by an existing directory');
                        return PclZip::errorCode();
                    }
                } elseif (!is_writable($p_entry['filename'])) {
                    // ----- Change the file status
                    $p_entry['status'] = 'write_protected';
                    // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
                    // For historical reason first PclZip implementation does not stop
                    // when this kind of error occurs.
                    if (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]) && $p_options[PCLZIP_OPT_STOP_ON_ERROR] === true) {
                        PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, "Filename '" . $p_entry['filename'] . "' exists " . 'and is write protected');
                        return PclZip::errorCode();
                    }
                } elseif (filemtime($p_entry['filename']) > $p_entry['mtime']) {
                    // ----- Change the file status
                    if (isset($p_options[PCLZIP_OPT_REPLACE_NEWER]) && $p_options[PCLZIP_OPT_REPLACE_NEWER] === true) {
                    } else {
                        $p_entry['status'] = 'newer_exist';
                        // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
                        // For historical reason first PclZip implementation does not stop
                        // when this kind of error occurs.
                        if (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]) && $p_options[PCLZIP_OPT_STOP_ON_ERROR] === true) {
                            PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, "Newer version of '" . $p_entry['filename'] . "' exists " . 'and option PCLZIP_OPT_REPLACE_NEWER is not selected');
                            return PclZip::errorCode();
                        }
                    }
                } else {
                }
            } else {
                if (($p_entry['external'] & 0x10) == 0x10 || substr($p_entry['filename'], -1) == '/') {
                    $v_dir_to_check = $p_entry['filename'];
                } elseif (!strstr($p_entry['filename'], '/')) {
                    $v_dir_to_check = '';
                } else {
                    $v_dir_to_check = dirname($p_entry['filename']);
                }
                if (($v_result = $this->privDirCheck($v_dir_to_check, ($p_entry['external'] & 0x10) == 0x10)) != 1) {
                    // ----- Change the file status
                    $p_entry['status'] = 'path_creation_fail';
                    // ----- Return
                    //return $v_result;
                    $v_result = 1;
                }
            }
        }
        // ----- Look if extraction should be done
        if ($p_entry['status'] == 'ok') {
            // ----- Do the extraction (if not a folder)
            if (!(($p_entry['external'] & 0x10) == 0x10)) {
                // ----- Look for not compressed file
                if ($p_entry['compression'] == 0) {
                    // ----- Opening destination file
                    if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
                        // ----- Change the file status
                        $p_entry['status'] = 'write_error';
                        // ----- Return
                        return $v_result;
                    }
                    // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
                    $v_size = $p_entry['compressed_size'];
                    while ($v_size != 0) {
                        $v_read_size = $v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE;
                        $v_buffer = @fread($this->zip_fd, $v_read_size);
                        /* Try to speed up the code
                           $v_binary_data = pack('a'.$v_read_size, $v_buffer);
                           @fwrite($v_dest_file, $v_binary_data, $v_read_size);
                           */
                        @fwrite($v_dest_file, $v_buffer, $v_read_size);
                        $v_size -= $v_read_size;
                    }
                    // ----- Closing the destination file
                    fclose($v_dest_file);
                    // ----- Change the file mtime
                    touch($p_entry['filename'], $p_entry['mtime']);
                } else {
                    // ----- TBC
                    // Need to be finished
                    if (($p_entry['flag'] & 1) == 1) {
                        PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \'' . $p_entry['filename'] . '\' is encrypted. Encrypted files are not supported.');
                        return PclZip::errorCode();
                    }
                    // ----- Look for using temporary file to unzip
                    if (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]) && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON]) || isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) && $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) {
                        $v_result = $this->privExtractFileUsingTempFile($p_entry, $p_options);
                        if ($v_result < PCLZIP_ERR_NO_ERROR) {
                            return $v_result;
                        }
                    } else {
                        // ----- Read the compressed file in a buffer (one shot)
                        $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
                        // ----- Decompress the file
                        $v_file_content = @gzinflate($v_buffer);
                        unset($v_buffer);
                        if ($v_file_content === false) {
                            // ----- Change the file status
                            // TBC
                            $p_entry['status'] = 'error';
                            return $v_result;
                        }
                        // ----- Opening destination file
                        if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
                            // ----- Change the file status
                            $p_entry['status'] = 'write_error';
                            return $v_result;
                        }
                        // ----- Write the uncompressed data
                        @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
                        unset($v_file_content);
                        // ----- Closing the destination file
                        @fclose($v_dest_file);
                    }
                    // ----- Change the file mtime
                    @touch($p_entry['filename'], $p_entry['mtime']);
                }
                // ----- Look for chmod option
                if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) {
                    // ----- Change the mode of the file
                    @chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]);
                }
            }
        }
        // ----- Change abort status
        if ($p_entry['status'] == 'aborted') {
            $p_entry['status'] = 'skipped';
        } elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
            // ----- Generate a local information
            $v_local_header = array();
            $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
            // ----- Call the callback
            // Here I do not use call_user_func() because I need to send a reference to the
            // header.
            //      eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
            $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
            // ----- Look for abort result
            if ($v_result == 2) {
                $v_result = PCLZIP_ERR_USER_ABORTED;
            }
        }
        // ----- Return
        return $v_result;
    }