cvs: pear /File_Archive Archive.php /File_Archive/Archive Reader.php /File_Archive/Archive/Reader Ar.php Bzip2.php Concat.php Directory.php File.php
Gzip.php Memory.php Relay.php Tar.php Zip.php /File_Archive/Archive/Writer Bzip2.php Files.php

From: Date: Sat, 28 May 2005 21:34:15 +0000
Subject: cvs: pear /File_Archive Archive.php /File_Archive/Archive Reader.php /File_Archive/Archive/Reader Ar.php Bzip2.php Concat.php Directory.php File.php
Gzip.php Memory.php Relay.php Tar.php Zip.php /File_Archive/Archive/Writer Bzip2.php Files.php
Groups: php.pear.cvs 
Request: Send a blank email to pear-cvs+get-32197@lists.php.net to get a copy of this message
vincentlascaux Sat May 28 17:34:15 2005 EDT Modified files: /pear/File_Archive Archive.php /pear/File_Archive/Archive Reader.php /pear/File_Archive/Archive/Reader Ar.php Bzip2.php Concat.php Directory.php File.php Gzip.php Memory.php Relay.php Tar.php Zip.php /pear/File_Archive/Archive/Writer Bzip2.php Files.php Log: + Change again the Reader interface to allow editing archives + tar, gz and bzip2 (which also mean tgz and tbz) archives can be edited (append / remove / modify files) Even nested archives can be edited!

http://cvs.php.net/diff.php/pear/File_Archive/Archive.php?r1=1.50&r2=1.51&ty=u Index: pear/File_Archive/Archive.php diff -u pear/File_Archive/Archive.php:1.50 pear/File_Archive/Archive.php:1.51 --- pear/File_Archive/Archive.php:1.50 Thu May 26 17:30:18 2005 +++ pear/File_Archive/Archive.php Sat May 28 17:34:15 2005 @@ -27,7 +27,7 @@ * @author Vincent Lascaux <vincentlascaux@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.gnu.org/copyleft/lesser.html LGPL - * @version CVS: $Id: Archive.php,v 1.50 2005/05/26 21:30:18 vincentlascaux Exp $ + * @version CVS: $Id: Archive.php,v 1.51 2005/05/28 21:34:15 vincentlascaux Exp $ * @link http://pear.php.net/package/File_Archive */ @@ -879,6 +879,17 @@ } return $source->extract($dest, $autoClose, $bufferSize); } + + /** + * Create a writer that allows appending new files to an existing archive + */ + function append(&$source) + { + if (PEAR::isError($source)) { + return $source; + } + return $source->makeAppendWriter(); + } } ?> \ No newline at end of file http://cvs.php.net/diff.php/pear/File_Archive/Archive/Reader.php?r1=1.25&r2=1.26&ty=u Index: pear/File_Archive/Archive/Reader.php diff -u pear/File_Archive/Archive/Reader.php:1.25 pear/File_Archive/Archive/Reader.php:1.26 --- pear/File_Archive/Archive/Reader.php:1.25 Fri May 27 20:58:46 2005 +++ pear/File_Archive/Archive/Reader.php Sat May 28 17:34:15 2005 @@ -27,7 +27,7 @@ * @author Vincent Lascaux <vincentlascaux@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.gnu.org/copyleft/lesser.html LGPL - * @version CVS: $Id: Reader.php,v 1.25 2005/05/28 00:58:46 vincentlascaux Exp $ + * @version CVS: $Id: Reader.php,v 1.26 2005/05/28 21:34:15 vincentlascaux Exp $ * @link http://pear.php.net/package/File_Archive */ @@ -188,7 +188,7 @@ * return strlen(getData($length)) * But could be far more efficient */ - function skip($length) + function skip($length = -1) { $data = $this->getData($length); if (PEAR::isError($data)) { @@ -208,7 +208,7 @@ * @return the number of bytes really rewinded (which may be less than * $length if the current pos is less than $length */ - function rewind($length) + function rewind($length = -1) { return PEAR::raiseError('Rewind function is not implemented on this reader'); } @@ -330,125 +330,64 @@ } /** - * Remove the current file from the archive - * After having removed a file from an archive, the current position in the - * archive is set to the next file in the archive - */ - function remove() - { - } - - /** - * Remove some data from the current file in the archive - * After having removed a block of data, the current position in the archive - * is will be after the removed block of data, in the current file that may have - * been moved + * Return a writer that allows appending files to the archive + * After having called makeAppendWriter, $this is closed and should not be used until the returned + * writer is closed. * - * @param int $seek Relative position of the begining of the block that must - * be removed, from the current pos - * @param int $size Size of the block (in bytes) to remove, or -1 to remove to - * the end of the file + * @return a writer that will allow to append files to an existing archive + * @see makeWriter */ - function removeBlock($seek = 0, $size = -1) + function makeAppendWriter() { + return PEAR::raiseError("Reader abstract function call (makeAppendWriter)"); } /** - * Create a writer to append files to the archive - * After having called this function, $this will be closed and should no longer be used - * - * @return File_Archive_Writer writer on which you can call newFile to append new files - * in the archive + * Return a writer that has the same properties as the one returned by makeAppendWriter, but after + * having removed the current file */ - function makeAppendWriter() + function makeWriterRemove() { - $this->skip(-1); - return $this->makeDataWriter(); + return PEAR::raiseError("Reader abstract function call (makeWriterRemove)"); } /** - * Create a writer to append data to the current file, erasing it from current pos - * After having called this function, $this will be closed and should no longer be used - * The order of the files in the archive may not be preserved - * - * Note: if you won't modify the data of the file, use makeAppendWriter which is way faster - * - * @return File_Archive_Writer writer on which you can call writeData to append data to the - * current file in the archive, or newFile to append files + * Removes the current file from the archive + * After a call to remove, $this is closed */ - function makeDataWriter($seek = 0) + function remove() { + $writer = $this->makeWriterRemove(); + if (PEAR::isError($writer)) { + return $writer; + } + $writer->close(); } /** - * Returns a writer that will start writing at the current pos in the source - * Any data (from current file or any other file) located after current pos - * will be erased. - * For security reasons, calling makeWriter on a directory reader will not erase any file - * though. - * $this->close will be called and after this function the reader is invalid (and - * should no longer be used). - * - * If $fileModif is true, the writer will allow editing the current file (or the - * last file if the end of the archive has been reached) - * Thus it is an error to call makeWriter with fileModif to true if the reader - * has not been opened (no call to next() have been done, or first call to next - * returned false). - * In this case, $seek allows to change the position from where the file must be - * edited - * - * If $fileModif is false, the writer will not allow to edit the current file, and - * the first function call should be new file. The current file will be left unchanged - * If the first function call is writeData, the behaviour is undefined (it - * will generally result in invalid archives). - * In this case, $seek is not used + * Return a writer that has the same properties as the one returned by makeWriter, but after + * having removed a block of data from the current file. The writer will append data to the current file + * no data (other than the block) will be removed * - * Here is how to append a single file to an existing zip archive - * <sample> - * $archive = File_Archive::read('archive.zip/'); - * $file = File_Archive::read('foo.txt'); - * $file->extract($source->makeAppendWriter()); - * </sample> - * - * Append the content of a tgz archive to an existing zip archive - * <sample> - * $archive = File_Archive::read('archive.zip/'); - * $file = File_Archive::read('archive.tgz/'); - * $file->extract($source->makeAppendWriter()); - * </sample> - * - * @param int $seek The new writer will be opened seek bytes after the current position - * Seek can be positive or negative - * If current file pos + seek < 0 or current file pos + seek > current file size, - * we have an undefined behaviour - * @param bool $fileModif Set to false only if you will call newFile or close first on the - * returned writer (and thus will not modify the current file of the reader) - * Setting this parameter to false can speed up a lot the process - * If $fileModif is false, $seek will not be taken into account (since the writer will - * not write in the current file) - * @return File_Archive_Writer Writer that appends data to the ressource of this reader, - * starting at the current location + * @param array Lengths of the blocks. The first one will be discarded, the second one kept, the third + * one discarded... If the sum of the blocks is less than the size of the file, the comportment is the + * same as if a last block was set in the array to reach the size of the file + * if $length is -1, the file is truncated from the specified pos + * It is possible to specify blocks of size 0 + * @param int $seek relative pos of the block */ - function makeWriter($fileModif = true, $seek = 0) + function makeWriterRemoveBlocks($blocks, $seek = 0) { - return PEAR::raiseError("Reader abstract function call (makeWriter)"); + return PEAR::raiseError("Reader abstract function call (makeWriterRemoveBlocks)"); } /** - * This is equivalent to move to the end of the archive and calling makeWriter - * - * @return a writer that will allow to append files to an existing archive - * @see makeWriter + * Equivalent to makeWriterRemoveBlocks(array(0)), but may be more efficient + * It creates a writer to append data to a file */ - function makeAppendWriter($fileModif = true) + function makeWriter() { - while ( ($error = $this->next()) === true ) { } - if (PEAR::isError($error)) { - $this->close(); - return $error; - } else { - return $this->makeWriter($fileModif); - } + return $this->makeWriterRemoveBlocks(array(0)); } } http://cvs.php.net/diff.php/pear/File_Archive/Archive/Reader/Ar.php?r1=1.8&r2=1.9&ty=u Index: pear/File_Archive/Archive/Reader/Ar.php diff -u pear/File_Archive/Archive/Reader/Ar.php:1.8 pear/File_Archive/Archive/Reader/Ar.php:1.9 --- pear/File_Archive/Archive/Reader/Ar.php:1.8 Fri May 27 20:58:48 2005 +++ pear/File_Archive/Archive/Reader/Ar.php Sat May 28 17:34:15 2005 @@ -196,7 +196,7 @@ /** * @see File_Archive_Reader::skip */ - function skip($length) + function skip($length = -1) { if ($length == -1) { $length = $this->_nbBytesLeft; @@ -214,7 +214,7 @@ /** * @see File_Archive_Reader::rewind */ - function rewind($length) + function rewind($length = -1) { if ($length == -1) { $length = $this->_currentStat[7] - $this->_nbBytesLeft; @@ -232,17 +232,5 @@ } } - /** - * @see File_Archive_Reader::makeWriter - */ - function makeWriter($seek = 0, $fileModif = true) - { - require_once "File/Archive/Writer/Ar.php"; - - $writer = $this->source->makeWriter(); - $this->source = null; - $this->close(); - return new File_Archive_Writer_Ar(null, $writer); - } } ?> \ No newline at end of file http://cvs.php.net/diff.php/pear/File_Archive/Archive/Reader/Bzip2.php?r1=1.12&r2=1.13&ty=u Index: pear/File_Archive/Archive/Reader/Bzip2.php diff -u pear/File_Archive/Archive/Reader/Bzip2.php:1.12 pear/File_Archive/Archive/Reader/Bzip2.php:1.13 --- pear/File_Archive/Archive/Reader/Bzip2.php:1.12 Fri May 27 20:58:48 2005 +++ pear/File_Archive/Archive/Reader/Bzip2.php Sat May 28 17:34:15 2005 @@ -25,11 +25,11 @@ * @author Vincent Lascaux <vincentlascaux@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.gnu.org/copyleft/lesser.html LGPL - * @version CVS: $Id: Bzip2.php,v 1.12 2005/05/28 00:58:48 vincentlascaux Exp $ + * @version CVS: $Id: Bzip2.php,v 1.13 2005/05/28 21:34:15 vincentlascaux Exp $ * @link http://pear.php.net/package/File_Archive */ -require_once "File/Archive/Writer/Archive.php"; +require_once "File/Archive/Reader/Archive.php"; require_once "File/Archive/Writer/Files.php"; /** @@ -40,7 +40,7 @@ var $nbRead = 0; var $bzfile = null; var $tmpName = null; - var $pos = 0; + var $filePos = 0; /** * @see File_Archive_Reader::close() @@ -53,7 +53,7 @@ unlink($this->tmpName); $this->nbRead = 0; - $this->pos = 0; + $this->filePos = 0; return parent::close($innerClose); } @@ -117,7 +117,7 @@ $newData = bzread($this->bzfile); $data .= $newData; } while ($newData != ''); - $this->pos += strlen($data); + $this->filePos += strlen($data); } else if ($length == 0) { return ''; } else { @@ -125,9 +125,10 @@ //The loop is here to correct what appears to be a bzread bug while (strlen($data) < $length) { - $data .= bzread($this->bzfile, $length - strlen($data)); + $newData = bzread($this->bzfile, $length - strlen($data)); + $data .= $newData; } - $this->pos += strlen($data); + $this->filePos += strlen($data); } return $data == '' ? null : $data; @@ -136,71 +137,102 @@ /** * @see File_Archive_Reader::rewind */ - function rewind($length) + function rewind($length = -1) + { + $before = $this->filePos; + + bzclose($this->bzfile); + if ($this->tmpName == null) { + $this->bzfile = bzopen($this->source->getDataFilename(), 'r'); + } else { + $this->bzfile = bzopen($this->tmpName, 'r'); + } + $this->filePos = 0; + + if ($length != -1) { + $this->skip($before - $length); + } + return $before - $this->filePos; + } + + /** + * @see File_Archive_Reader::makeAppendWriter() + */ + function makeAppendWriter() + { + return PEAR::raiseError('Unable to append files to a bzip2 archive'); + } + + /** + * @see File_Archive_Reader::makeWriterRemove() + */ + function makeWriterRemove() { - //TODO: implement rewind - return parent::rewind($length); + return PEAR::raiseError('Unable to remove files from a bzip2 archive'); } /** - * @see File_Archive_Reader::makeWriter + * @see File_Archive_Reader::makeWriterRemoveBlocks() */ - function makeWriter($fileModif = true, $seek = 0) + function makeWriterRemoveBlocks($blocks, $seek = 0) { require_once "File/Archive/Writer/Bzip2.php"; - if ($fileModif == false) { - return PEAR::raiseError( - 'A Bzip archive contains one single file. '. - 'makeWriter must be called with $fileModif set to true' - ); + if ($this->nbRead == 0) { + return PEAR::raiseError('No file selected'); } - if ($this->nbRead == 0) { - return new File_Archive_Writer_Bzip2( - null, $this->source->makeWriter() - ); - } else { - //Uncompress data to a temporary file - $tmp = tmpfile(); + //Uncompress data to a temporary file + $tmp = fopen('debug', 'w+');//tmpfile(); + $expectedPos = $this->filePos + $seek; - $toRead = $this->pos + $seek; + $this->rewind(); - //bzseek($this->bzfile, 0); - bzclose($this->bzfile); - if ($this->tmpName == null) { - $this->bzfile = bzopen($this->source->getDataFilename(), 'r'); + //Read the begining of the file + while ($this->filePos < $expectedPos && + ($data = $this->getData(min($expectedPos - $this->filePos, 8192))) != null) { + fwrite($tmp, $data); + } + + $keep = false; + foreach ($blocks as $length) { + if ($keep) { + $expectedPos = $this->filePos + $length; + while ($this->filePos < $expectedPos && + ($data = $this->getData(min($expectedPos - $this->filePos, 8192))) != null) { + fwrite($tmp, $data); + } } else { - $this->bzfile = bzopen($this->tmpName, 'r'); + $this->skip($length); } - - - while ($toRead > 0 && - ($data = bzread($this->bzfile, min($toRead, 8192))) != '') { - $toRead -= strlen($data); + $keep = !$keep; + } + if ($keep) { + //Read the end of the file + while(($data = $this->getData(8192)) != null) { fwrite($tmp, $data); } - fseek($tmp, 0); - - //Create the writer - $innerWriter = $this->source->makeWriter(); - $this->source = null; - $writer = new File_Archive_Writer_Bzip2(null, $innerWriter); - - //And compress data from the temporary file - while (!feof($tmp)) { - $data = fread($tmp, 8192); - $writer->writeData($data); - } - fclose($tmp); + } + fseek($tmp, 0); - //Do not close inner writer since makeWriter was called - $this->close(); + //Create the writer + $this->source->rewind(); + $innerWriter = $this->source->makeWriterRemoveBlocks(array()); //Truncate the source + $this->source = null; + $writer = new File_Archive_Writer_Bzip2(null, $innerWriter); - return $writer; + //And compress data from the temporary file + while (!feof($tmp)) { + $data = fread($tmp, 8192); + $writer->writeData($data); } - } + fclose($tmp); + //Do not close inner writer since makeWriter was called + $this->close(); + + return $writer; + } } ?> \ No newline at end of file http://cvs.php.net/diff.php/pear/File_Archive/Archive/Reader/Concat.php?r1=1.13&r2=1.14&ty=u Index: pear/File_Archive/Archive/Reader/Concat.php diff -u pear/File_Archive/Archive/Reader/Concat.php:1.13 pear/File_Archive/Archive/Reader/Concat.php:1.14 --- pear/File_Archive/Archive/Reader/Concat.php:1.13 Fri May 27 20:58:48 2005 +++ pear/File_Archive/Archive/Reader/Concat.php Sat May 28 17:34:15 2005 @@ -25,7 +25,7 @@ * @author Vincent Lascaux <vincentlascaux@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.gnu.org/copyleft/lesser.html LGPL - * @version CVS: $Id: Concat.php,v 1.13 2005/05/28 00:58:48 vincentlascaux Exp $ + * @version CVS: $Id: Concat.php,v 1.14 2005/05/28 21:34:15 vincentlascaux Exp $ * @link http://pear.php.net/package/File_Archive */ @@ -133,7 +133,7 @@ /** * @see File_Archive_Reader::skip() */ - function skip($length) + function skip($length = -1) { $skipped = 0; while ($skipped < $length) { @@ -148,7 +148,7 @@ /** * @see File_Archive_Reader::rewind() */ - function rewind($length) + function rewind($length = -1) { //TODO: implement rewind return parent::rewind($length); http://cvs.php.net/diff.php/pear/File_Archive/Archive/Reader/Directory.php?r1=1.14&r2=1.15&ty=u Index: pear/File_Archive/Archive/Reader/Directory.php diff -u pear/File_Archive/Archive/Reader/Directory.php:1.14 pear/File_Archive/Archive/Reader/Directory.php:1.15 --- pear/File_Archive/Archive/Reader/Directory.php:1.14 Thu May 26 17:30:18 2005 +++ pear/File_Archive/Archive/Reader/Directory.php Sat May 28 17:34:15 2005 @@ -25,7 +25,7 @@ * @author Vincent Lascaux <vincentlascaux@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.gnu.org/copyleft/lesser.html LGPL - * @version CVS: $Id: Directory.php,v 1.14 2005/05/26 21:30:18 vincentlascaux Exp $ + * @version CVS: $Id: Directory.php,v 1.15 2005/05/28 21:34:15 vincentlascaux Exp $ * @link http://pear.php.net/package/File_Archive */ @@ -69,6 +69,7 @@ $this->symbolic = $this->getStandardURL($symbolic); $this->maxRecurs = $maxRecurs; } + /** * @see File_Archive_Reader::close() */ @@ -76,11 +77,12 @@ { $error = parent::close(); + closedir($this->directoryHandle); $this->directoryHandle = null; - $this->source = null; return $error; } + /** * @see File_Archive_Reader::next() * @@ -133,27 +135,69 @@ function getFilename() { return $this->symbolic . parent::getFilename(); } /** - * @see File_Archive_Reader::makeWriter + * @see File_Archive_Reader::makeWriterRemove() */ - function makeWriter($fileModif = true, $seek = 0) + function makeWriterRemove() { + $lastSource = &$this->getLastSource(); + if ($lastSource === null) { + return PEAR::raiseError('No file selected'); + } + require_once "File/Archive/Writer/Files.php"; - if ($this->source == null || - (!$fileModif && is_a($source, 'File_Archive_Reader_File')) - ) { - $writer = new File_Archive_Writer_Files($directory); + $writer = $lastSource->makeWriterRemove(); + if (!PEAR::isError($writer)) { + $writer->basePath = $this->directory; + $this->close(); + } + + return $writer; + } + + function getLastSource() + { + if ($this->source === null || + is_a($this->source, 'File_Archive_Reader_File')) { + return &$this->source; } else { - $writer = $this->source->makeWriter($fileModif, $seek); + return &$this->source->getLastSource(); } + } - $toUnlink = array(); - while ($this->next()) { - $toUnlink[] = $this->getDataFilename(); + /** + * @see File_Archive_Reader::makeWriterRemoveBlocks() + */ + function makeWriterRemoveBlocks($blocks, $seek = 0) + { + $lastSource = &$this->getLastSource(); + if ($lastSource === null) { + return PEAR::raiseError('No file selected'); } - foreach ($toUnlink as $filename) { - unlink($filename); + require_once "File/Archive/Writer/Files.php"; + + $writer = $lastSource->makeWriterRemoveBlocks($blocks, $seek); + if (!PEAR::isError($writer)) { + $writer->basePath = $this->directory; + $this->close(); + } + + return $writer; + } + + /** + * @see File_Archive_Reader::makeAppendWriter + */ + function makeAppendWriter() + { + require_once "File/Archive/Writer/Files.php"; + + if ($this->source == null || + is_a($this->source, 'File_Archive_Reader_File') ) { + $writer = new File_Archive_Writer_Files($this->directory); + } else { + $writer = $this->source->makeAppendWriter($seek); } $this->close(); http://cvs.php.net/diff.php/pear/File_Archive/Archive/Reader/File.php?r1=1.19&r2=1.20&ty=u Index: pear/File_Archive/Archive/Reader/File.php diff -u pear/File_Archive/Archive/Reader/File.php:1.19 pear/File_Archive/Archive/Reader/File.php:1.20 --- pear/File_Archive/Archive/Reader/File.php:1.19 Fri May 27 20:58:48 2005 +++ pear/File_Archive/Archive/Reader/File.php Sat May 28 17:34:15 2005 @@ -25,7 +25,7 @@ * @author Vincent Lascaux <vincentlascaux@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.gnu.org/copyleft/lesser.html LGPL - * @version CVS: $Id: File.php,v 1.19 2005/05/28 00:58:48 vincentlascaux Exp $ + * @version CVS: $Id: File.php,v 1.20 2005/05/28 21:34:15 vincentlascaux Exp $ * @link http://pear.php.net/package/File_Archive */ @@ -172,7 +172,7 @@ /** * @see File_Archive_Reader::skip() */ - function skip($length) + function skip($length = -1) { $before = ftell($this->handle); if (($length == -1 && @fseek($this->handle, 0, SEEK_END) === -1) || @@ -186,7 +186,7 @@ /** * @see File_Archive_Reader::rewind */ - function rewind($length) + function rewind($length = -1) { $before = ftell($this->handle); if (($length == -1 && @fseek($this->handle, 0, SEEK_SET) === -1) || @@ -198,20 +198,23 @@ } /** - * @see File_Archive_Reader::makeWriter + * @see File_Archive_Reader::makeWriterRemove() */ - function makeWriter($fileModif = true, $seek = 0) + function makeWriterRemove() + { + return PEAR::raiseError( + 'File_Archive_Reader_File represents a single file, you cant remove it'); + } + + /** + * @see File_Archive_Reader::makeWriterRemoveBlocks() + */ + function makeWriterRemoveBlocks($blocks, $seek = 0) { require_once "File/Archive/Writer/Files.php"; $writer = new File_Archive_Writer_Files(); - if ($fileModif == false) { - return PEAR::raiseError( - 'To append data to a file, you must set $fileModif to true' - ); - } - if ($this->handle != null) { $file = $this->getDataFilename(); $stat = $this->getStat(); @@ -220,11 +223,22 @@ $this->close(); - $writer->openFile($file, $pos + $seek, $stat, $mime); + $writer->openFileRemoveBlock($file, $pos + $seek, $blocks, $stat, $mime); } return $writer; } + + /** + * @see File_Archive_Reader::makeAppendWriter + */ + function makeAppendWriter() + { + return PEAR::raiseError( + 'File_Archive_Reader_File represents a single file.'. + ' makeAppendWriter cant be executed on it' + ); + } } ?> \ No newline at end of file http://cvs.php.net/diff.php/pear/File_Archive/Archive/Reader/Gzip.php?r1=1.21&r2=1.22&ty=u Index: pear/File_Archive/Archive/Reader/Gzip.php diff -u pear/File_Archive/Archive/Reader/Gzip.php:1.21 pear/File_Archive/Archive/Reader/Gzip.php:1.22 --- pear/File_Archive/Archive/Reader/Gzip.php:1.21 Fri May 27 20:58:48 2005 +++ pear/File_Archive/Archive/Reader/Gzip.php Sat May 28 17:34:15 2005 @@ -25,7 +25,7 @@ * @author Vincent Lascaux <vincentlascaux@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.gnu.org/copyleft/lesser.html LGPL - * @version CVS: $Id: Gzip.php,v 1.21 2005/05/28 00:58:48 vincentlascaux Exp $ + * @version CVS: $Id: Gzip.php,v 1.22 2005/05/28 21:34:15 vincentlascaux Exp $ * @link http://pear.php.net/package/File_Archive */ @@ -143,7 +143,7 @@ /** * @see File_Archive_Reader::skip() */ - function skip($length) + function skip($length = -1) { if($length == -1) { do @@ -164,7 +164,7 @@ /** * @see File_Archive_Reader::rewind() */ - function rewind($length) + function rewind($length = -1) { if ($length == -1) { if (@gzseek($this->gzfile, 0) === -1) { @@ -185,70 +185,84 @@ } } + /** + * @see File_Archive_Reader::makeAppendWriter() + */ + function makeAppendWriter() + { + return PEAR::raiseError('Unable to append files to a gzip archive'); + } /** - * @see File_Archive_Reader::makeWriter + * @see File_Archive_Reader::makeWriterRemove() */ - function makeWriter($fileModif = true, $seek = 0) + function makeWriterRemove() { - require_once "File/Archive/Writer/Gzip.php"; + return PEAR::raiseError('Unable to remove files from a gzip archive'); + } - if ($fileModif == false) { - return PEAR::raiseError( - 'A GZip archive contains one single file. '. - 'makeWriter must be called with $fileModif set to true' - ); - } + /** + * @see File_Archive_Reader::makeWriterRemoveBlocks() + */ + function makeWriterRemoveBlocks($blocks, $seek = 0) + { + require_once "File/Archive/Writer/Gzip.php"; if ($this->nbRead == 0) { - return new File_Archive_Writer_Gzip( - null, $this->source->makeWriter() - ); - } else { - //Uncompress data to a temporary file - $tmp = tmpfile(); - - if ($this->nbRead == 1) { - $toRead = gztell($this->gzfile) + $seek; - - gzseek($this->gzfile, 0); + return PEAR::raiseError('No file selected'); + } - while ($toRead > 0 && - ($data = gzread($this->gzfile, min($toRead, 8192))) != '') { - $toRead -= strlen($data); + //Uncompress data to a temporary file + $tmp = tmpfile(); + $expectedPos = $this->filePos + $seek; + $this->rewind(); + + //Read the begining of the file + while ($this->filePos < $expectedPos && + ($data = $this->getData(min($expectedPos - $this->filePos, 8192))) != null) { + fwrite($tmp, $data); + } + + $keep = false; + foreach ($blocks as $length) { + if ($keep) { + $expectedPos = $this->filePos + $length; + while ($this->filePos < $expectedPos && + ($data = $this->getData(min($expectedPos - $this->filePos, 8192))) != null) { fwrite($tmp, $data); } } else { - gzseek($this->gzfile, 0); - while (($data = $this->getData(8192)) !== null) { - fwrite($tmp, $data); - } - if ($seek < 0) { - echo "removing $seek from file\n"; - ftruncate($tmp, ftell($tmp) + $seek); - } + $this->skip($length); } - - fseek($tmp, 0); - - //Create the writer - $innerWriter = $this->source->makeWriter(); - $this->source = null; - $writer = new File_Archive_Writer_Gzip(null, $innerWriter); - - //And compress data from the temporary file - while (!feof($tmp)) { - $data = fread($tmp, 8192); - $writer->writeData($data); + $keep = !$keep; + } + if ($keep) { + //Read the end of the file + while(($data = $this->getData(8192)) != null) { + fwrite($tmp, $data); } - fclose($tmp); + } + fseek($tmp, 0); - //Do not close inner writer since makeWriter was called - $this->close(); + //Create the writer + $this->source->rewind(); + $innerWriter = $this->source->makeWriterRemoveBlocks(array()); //Truncate the source + $this->source = null; + $writer = new File_Archive_Writer_Gzip(null, $innerWriter); - return $writer; + //And compress data from the temporary file + while (!feof($tmp)) { + $data = fread($tmp, 8192); + $writer->writeData($data); } + fclose($tmp); + + //Do not close inner writer since makeWriter was called + $this->close(); + + return $writer; } + } ?> \ No newline at end of file http://cvs.php.net/diff.php/pear/File_Archive/Archive/Reader/Memory.php?r1=1.15&r2=1.16&ty=u Index: pear/File_Archive/Archive/Reader/Memory.php diff -u pear/File_Archive/Archive/Reader/Memory.php:1.15 pear/File_Archive/Archive/Reader/Memory.php:1.16 --- pear/File_Archive/Archive/Reader/Memory.php:1.15 Fri May 27 20:58:48 2005 +++ pear/File_Archive/Archive/Reader/Memory.php Sat May 28 17:34:15 2005 @@ -25,7 +25,7 @@ * @author Vincent Lascaux <vincentlascaux@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.gnu.org/copyleft/lesser.html LGPL - * @version CVS: $Id: Memory.php,v 1.15 2005/05/28 00:58:48 vincentlascaux Exp $ + * @version CVS: $Id: Memory.php,v 1.16 2005/05/28 21:34:15 vincentlascaux Exp $ * @link http://pear.php.net/package/File_Archive */ @@ -137,7 +137,7 @@ /** * @see File_Archive_Reader::skip() */ - function skip($length) + function skip($length = -1) { if ($length == -1) { $length = strlen($this->memory) - $this->offset; @@ -151,7 +151,7 @@ /** * @see File_Archive_Reader::rewind() */ - function rewind($length) + function rewind($length = -1) { if ($length == -1) { $tmp = $this->offset; @@ -174,21 +174,44 @@ } /** - * @see File_Archive_Reader::makeWriter + * @see File_Archive_Reader::makeAppendWriter() */ - function makeWriter($fileModif = true, $seek = 0) + function makeAppendWriter() { - if ($fileModif == false) { - return PEAR::raiseError( - 'A Memory reader contains one single file. '. - 'makeWriter must be called with $fileModif set to true' - ); - } + return PEAR::raiseError('Unable to append files to a memory archive'); + } + + /** + * @see File_Archive_Reader::makeWriterRemove() + */ + function makeWriterRemove() + { + return PEAR::raiseError('Unable to remove files from a memory archive'); + } + /** + * @see File_Archive_Reader::makeWriterRemoveBlocks() + */ + function makeWriterRemoveBlocks($blocks, $seek = 0) + { require_once "File/Archive/Writer/Memory.php"; - $writer = new File_Archive_Writer_Memory($this->memory, $this->offset + $seek); - $this->close(); - return $writer; + $data = substr($this->memory, 0, $this->offset + $seek); + $this->memory = substr($this->memory, $this->offset + $seek); + + $keep = false; + foreach ($blocks as $length) { + if ($keep) { + $data .= substr($this->memory, 0, $length); + } + $this->memory = substr($this->memory, $length); + $keep = !$keep; + } + if ($keep) { + $this->memory = data . $this->memory; + } else { + $this->memory = data; + } + return new File_Archive_Writer_Memory($this->memory, strlen($this->memory)); } } http://cvs.php.net/diff.php/pear/File_Archive/Archive/Reader/Relay.php?r1=1.13&r2=1.14&ty=u Index: pear/File_Archive/Archive/Reader/Relay.php diff -u pear/File_Archive/Archive/Reader/Relay.php:1.13 pear/File_Archive/Archive/Reader/Relay.php:1.14 --- pear/File_Archive/Archive/Reader/Relay.php:1.13 Fri May 27 20:58:48 2005 +++ pear/File_Archive/Archive/Reader/Relay.php Sat May 28 17:34:15 2005 @@ -25,7 +25,7 @@ * @author Vincent Lascaux <vincentlascaux@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.gnu.org/copyleft/lesser.html LGPL - * @version CVS: $Id: Relay.php,v 1.13 2005/05/28 00:58:48 vincentlascaux Exp $ + * @version CVS: $Id: Relay.php,v 1.14 2005/05/28 21:34:15 vincentlascaux Exp $ * @link http://pear.php.net/package/File_Archive */ @@ -77,11 +77,11 @@ /** * @see File_Archive_Reader::skip() */ - function skip($length) { return $this->source->skip($length); } + function skip($length = -1) { return $this->source->skip($length); } /** * @see File_Archive_Reader::rewind() */ - function rewind($length) { return $this->source->rewind($length); } + function rewind($length = -1) { return $this->source->rewind($length); } /** * @see File_Archive_Reader::close() */ @@ -92,12 +92,28 @@ } } /** - * @see File_Archive_Reader::makeWriter + * @see File_Archive_Reader::makeAppendWriter() */ - function makeWriter($fileModif = true, $seek = 0) + function makeAppendWriter() { return $this->source->makeAppendWriter(); } + /** + * @see File_Archive_Reader::makeWriterRemove() + */ + function makeWriterRemove() { return $this->source->makeWriterRemove(); } + /** + * @see File_Archive_Reader::remove() + */ + function remove() { return $this->source->remove(); } + /** + * @see File_Archive_Reader::makeWriterRemoveBlocks() + */ + function makeWriterRemoveBlocks($blocks, $seek = 0) { - return $this->source->makeWriter($fileModif, $seek); + return $this->source->makeWriterRemoveBlocks($blocks, $seek); } + /** + * @see File_Archive_Reader::makeWriter() + */ + function makeWriter() { return $this->source->makeWriter(); } } ?> \ No newline at end of file http://cvs.php.net/diff.php/pear/File_Archive/Archive/Reader/Tar.php?r1=1.21&r2=1.22&ty=u Index: pear/File_Archive/Archive/Reader/Tar.php diff -u pear/File_Archive/Archive/Reader/Tar.php:1.21 pear/File_Archive/Archive/Reader/Tar.php:1.22 --- pear/File_Archive/Archive/Reader/Tar.php:1.21 Fri May 27 20:58:48 2005 +++ pear/File_Archive/Archive/Reader/Tar.php Sat May 28 17:34:15 2005 @@ -25,7 +25,7 @@ * @author Vincent Lascaux <vincentlascaux@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.gnu.org/copyleft/lesser.html LGPL - * @version CVS: $Id: Tar.php,v 1.21 2005/05/28 00:58:48 vincentlascaux Exp $ + * @version CVS: $Id: Tar.php,v 1.22 2005/05/28 21:34:15 vincentlascaux Exp $ * @link http://pear.php.net/package/File_Archive */ @@ -69,7 +69,7 @@ /** * @see File_Archive_Reader::skip() */ - function skip($length) + function skip($length = -1) { if ($length == -1) { $length = $this->leftLength; @@ -86,7 +86,7 @@ /** * @see File_Archive_Reader::rewind() */ - function rewind($length) + function rewind($length = -1) { if ($length == -1) { $length = $this->currentStat[7] - $this->leftLength; @@ -221,48 +221,95 @@ } /** - * @see File_Archive_Reader::makeWriter + * @see File_Archive_Reader::makeWriterRemove() */ - function makeWriter($seek = 0, $fileModif = true) + function makeWriterRemove() { require_once "File/Archive/Writer/Tar.php"; - if ($fileModif) { - if ($this->seekToEnd != null) { - //Seek before the stat of the last file - $innerSeek = -$this->seekToEnd - $this->currentStat[7] - 512; - if ($this->currentStat[7] % 512 != 0) { - $innerSeek += 512 - $this->currentStat[7] % 512; - } - } else { - //Seek before the stat of the current file - $innerSeek = -$this->currentStat[7] + $this->leftLength - 512; - } - } else { - if ($this->seekToEnd != null) { - //Seek before the empty header - $innerSeek = -$this->seekToEnd; + if ($this->seekToEnd !== null || $this->currentFilename === null) { + return PEAR::raiseError('No file selected'); + } + + $size = $seek = 512 + $this->currentStat[7] + $this->footerLength; + while ($this->next()) { + $seek += 512 + $this->currentStat[7] + $this->footerLength; + } + $seek += $this->seekToEnd; + + return new File_Archive_Writer_Tar(null, $this->source->makeWriterRemoveBlocks( + array( + $size, //Remove the file + $seek - $size - $this->seekToEnd,//Keep other files + //Remove end empty file + ), -$seek) + ); + } + + /** + * @see File_Archive_Reader::makeWriterRemoveBlocks() + */ + function makeWriterRemoveBlocks($blocks, $seek = 0) + { + if ($this->seekToEnd !== null || $this->currentStat === null) { + return PEAR::raiseError('No file selected'); + } + + $blockPos = $this->currentStat[7] - $this->leftLength + $seek; + + $this->rewind(); + $keep = false; + + //TODO: write this data to a temp file? + $data = $this->getData($blockPos); + foreach ($blocks as $length) { + if ($keep) { + $data .= $this->getData($length); } else { - //Seek to the end of the current file - $innerSeek = $this->leftLength; + $this->skip($length); } + $keep = !$keep; } + if ($keep) { + $data .= $this->getData(); + } + + $filename = $this->currentFilename; + $stat = $this->currentStat; - $innerWriter = $this->source->makeWriter($innerSeek); + $writer = $this->makeWriterRemove(); + if (PEAR::isError($writer)) { + return $writer; + } + + unset($stat[7]); + $writer->newFile($filename, $stat); + $writer->writeData($data); + return $writer; + } + + /** + * @see File_Archive_Reader::makeAppendWriter + */ + function makeAppendWriter() + { + require_once "File/Archive/Writer/Tar.php"; + + while (($error = $this->next()) === true) { } + if (PEAR::isError($error)) { + $this->close(); + return $error; + } + + $innerWriter = $this->source->makeWriterRemoveBlocks(array(), -$this->seekToEnd); if (PEAR::isError($innerWriter)) { return $innerWriter; } $this->source = null; $this->close(); - $writer = new File_Archive_Writer_Tar(null, $writer); - - if ($fileModif) { - //Rewrite the file + $writer = new File_Archive_Writer_Tar(null, $innerWriter); - //TODO: inner modification of archives - return PEAR::raiseError("Modification of nested archives not available"); - } return $writer; } } http://cvs.php.net/diff.php/pear/File_Archive/Archive/Reader/Zip.php?r1=1.19&r2=1.20&ty=u Index: pear/File_Archive/Archive/Reader/Zip.php diff -u pear/File_Archive/Archive/Reader/Zip.php:1.19 pear/File_Archive/Archive/Reader/Zip.php:1.20 --- pear/File_Archive/Archive/Reader/Zip.php:1.19 Fri May 27 20:58:49 2005 +++ pear/File_Archive/Archive/Reader/Zip.php Sat May 28 17:34:15 2005 @@ -25,7 +25,7 @@ * @author Vincent Lascaux <vincentlascaux@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.gnu.org/copyleft/lesser.html LGPL - * @version CVS: $Id: Zip.php,v 1.19 2005/05/28 00:58:49 vincentlascaux Exp $ + * @version CVS: $Id: Zip.php,v 1.20 2005/05/28 21:34:15 vincentlascaux Exp $ * @link http://pear.php.net/package/File_Archive */ @@ -163,6 +163,7 @@ } else { //Begining of central area $this->seekToEnd = 4; + $this->currentFilename = null; return false; } } @@ -213,7 +214,7 @@ /** * @see File_Archive_Reader::skip() */ - function skip($length) + function skip($length = -1) { $before = $this->offset; if ($length == -1) { @@ -226,7 +227,7 @@ /** * @see File_Archive_Reader::rewind() */ - function rewind($length) + function rewind($length = -1) { $before = $this->offset; if ($length == -1) { @@ -234,7 +235,7 @@ } else { $this->offset = min(0, $this->offset - $length); } - return before - $this->offset; + return $before - $this->offset; } function uncompressData() @@ -257,43 +258,103 @@ } /** - * @see File_Archive_Reader::makeWriter + * @see File_Archive_Reader::makeWriterRemove() */ - function makeWriter($fileModif = true, $seek = 0) + function makeWriterRemove() { - if ($fileModif) { - //TODO: inner modification of archives - return PEAR::raiseError('Modification of nested archives not available'); + require_once "File/Archive/Writer/Zip.php"; + + if ($this->currentFilename === null) { + return PEAR::raiseError('No file selected'); } - require_once "File/Archive/Writer/Zip.php"; + $seek = $size = 30 + $this->header['File'] + $this->header['Extra'] + $this->header['CLen']; + array_pop($this->files); + while ($this->next()) { + $seek += 30 + $this->header['File'] + $this->header['Extra'] + $this->header['CLen']; + } + $seek += 4; + + $writer = new File_Archive_Writer_Zip(null, + $this->source->makeWriterRemoveBlocks( + array( + $size, //Remove the current file + $seek - $size - 4, //Keep the other files + //Remove the end (central dir...) + ), -$seek + ) + ); + if (PEAR::isError($writer)) { + return $writer; + } - if ($this->currentFilename == null) { - //The zip file was not even opened - $writer = new File_Archive_Writer_Zip(null, $this->source->makeWriter()); - } else { - if ($this->seekToEnd == 0) { - $seekToEnd = 26 + $this->header['File'] + $this->header['Extra'] + ($this->data == null ? 0 : $this->header['CRC']); - } else { - $seekToEnd = $this->seekToEnd; - } + foreach ($this->files as $file) { + $writer->alreadyWrittenFile($file['name'], $file['stat'], $file['CRC'], $file['CLen']); + } - $writer = new File_Archive_Writer_Zip(null, $this->source->makeWriter(true, - $seekToEnd)); + $this->source = null; + $this->close(); + return $writer; + } - if (!empty($this->files) && $this->seekToEnd == 0) { - //Last file will be rewritten - array_pop($this->files); - } - foreach ($this->files as $file) { - $writer->alreadyWrittenFile($file['name'], $file['stat'], $file['CRC'], $file['CLen']); - } + /** + * @see File_Archive_Reader::makeWriterRemoveBlocks() + */ + function makeWriterRemoveBlocks($blocks, $seek = 0) + { + if ($this->currentFilename === null) { + return PEAR::raiseError('No file selected'); + } - if ($this->seekToEnd == 0) { - $writer->newFile($this->getFilename(), - $this->getStat(), - $this->getMime()); - $writer->writeData($this->data == null ? '' : substr($this->data, 0, $this->offset + $seek)); + $keep = false; + + $this->uncompressData(); + $newData = substr($this->data, 0, $this->offset + $seek); + $this->data = substr($this->data, $this->offset + $seek); + foreach ($blocks as $length) { + if ($keep) { + $newData .= substr($this->data, 0, $length); } + $this->data = substr($this->data, $length); + $keep = !$keep; + } + if ($keep) { + $newData .= $this->data; + } + + $filename = $this->currentFilename; + $stat = $this->currentStat; + + $writer = $this->makeWriterRemove(); + if (PEAR::isError($writer)) { + return $writer; + } + + unset($stat[7]); + $writer->newFile($filename, $stat); + $writer->writeData($newData); + return $writer; + } + + /** + * @see File_Archive_Reader::makeAppendWriter + */ + function makeAppendWriter() + { + require_once "File/Archive/Writer/Zip.php"; + + while (($error = $this->next()) === true) { } + if (PEAR::isError($error)) { + $this->close(); + return $error; + } + + $writer = new File_Archive_Writer_Zip(null, + $this->source->makeWriterRemoveBlocks(array(), -4) + ); + + foreach ($this->files as $file) { + $writer->alreadyWrittenFile($file['name'], $file['stat'], $file['CRC'], $file['CLen']); } $this->source = null; http://cvs.php.net/diff.php/pear/File_Archive/Archive/Writer/Bzip2.php?r1=1.6&r2=1.7&ty=u Index: pear/File_Archive/Archive/Writer/Bzip2.php diff -u pear/File_Archive/Archive/Writer/Bzip2.php:1.6 pear/File_Archive/Archive/Writer/Bzip2.php:1.7 --- pear/File_Archive/Archive/Writer/Bzip2.php:1.6 Mon May 23 14:54:36 2005 +++ pear/File_Archive/Archive/Writer/Bzip2.php Sat May 28 17:34:15 2005 @@ -25,7 +25,7 @@ * @author Vincent Lascaux <vincentlascaux@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.gnu.org/copyleft/lesser.html LGPL - * @version CVS: $Id: Bzip2.php,v 1.6 2005/05/23 18:54:36 vincentlascaux Exp $ + * @version CVS: $Id: Bzip2.php,v 1.7 2005/05/28 21:34:15 vincentlascaux Exp $ * @link http://pear.php.net/package/File_Archive */ @@ -100,7 +100,6 @@ return true; } - /** * Actually write the tmp file to the inner writer * Close and delete temporary file http://cvs.php.net/diff.php/pear/File_Archive/Archive/Writer/Files.php?r1=1.15&r2=1.16&ty=u Index: pear/File_Archive/Archive/Writer/Files.php diff -u pear/File_Archive/Archive/Writer/Files.php:1.15 pear/File_Archive/Archive/Writer/Files.php:1.16 --- pear/File_Archive/Archive/Writer/Files.php:1.15 Thu May 26 14:30:43 2005 +++ pear/File_Archive/Archive/Writer/Files.php Sat May 28 17:34:15 2005 @@ -25,7 +25,7 @@ * @author Vincent Lascaux <vincentlascaux@php.net> * @copyright 1997-2005 The PHP Group * @license http://www.gnu.org/copyleft/lesser.html LGPL - * @version CVS: $Id: Files.php,v 1.15 2005/05/26 18:30:43 vincentlascaux Exp $ + * @version CVS: $Id: Files.php,v 1.16 2005/05/28 21:34:15 vincentlascaux Exp $ * @link http://pear.php.net/package/File_Archive */ @@ -107,11 +107,44 @@ return PEAR::raiseError("Unable to open file $filename"); } - if (fseek($this->handle, $pos) == -1) { - fread($this->handle, $pos); + if ($pos > 0) { + if (fseek($this->handle, $pos) == -1) { + fread($this->handle, $pos); + } + } + } + + /** + * Open a file for appending after having removed a block of data from it + * See File_Archive_Reader::makeWriterRemoveBlocks + */ + function openFileRemoveBlock($filename, $pos, $blocks, $stat = array(), $mime = "application/octet-stream") + { + $this->openFile($filename, $pos, $stat, $mime); + + //TODO: Might be a lot in memory... + $keep = false; + $data = ''; + foreach ($blocks as $length) { + if ($keep && $length > 0) { + $data .= fread($this->handle, $length); + } else { + fseek($this->handle, $length, SEEK_CUR); + } + $keep = !$keep; } + if ($keep) { + while(!feof($this->handle)) { + $data .= fread($this->handle, 8196); + } + } + + fseek($this->handle, $pos); + fwrite($this->handle, $data); + ftruncate($this->handle, ftell($this->handle)); } + /** * @see File_Archive_Writer::newFile() */
« previous php.pear.cvs (#32197) next »