summaryrefslogtreecommitdiff
path: root/package
diff options
context:
space:
mode:
authorMartin Gallwey <mtg@openoffice.org>2001-08-08 17:29:56 +0000
committerMartin Gallwey <mtg@openoffice.org>2001-08-08 17:29:56 +0000
commitde8cb713b0e13ce8c1be624a00a4fc89ec219dbc (patch)
treeb679003029ddb0b2fc8ecd7fa470b2c9ec3ae690 /package
parenta54919ae91b851fc9179efe689dcc4f57b46123a (diff)
#86708#,#87673#,#88979# write the full zip file to a tempfile before over-writing, thus fixing 87673 and 88979. Also, some new code for pack'n'go (should work on windows now)
Diffstat (limited to 'package')
-rw-r--r--package/source/zippackage/ZipPackage.cxx417
1 files changed, 341 insertions, 76 deletions
diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx
index df4c7cad7420..3fbb7af48f18 100644
--- a/package/source/zippackage/ZipPackage.cxx
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: ZipPackage.cxx,v $
*
- * $Revision: 1.52 $
+ * $Revision: 1.53 $
*
- * last change: $Author: mtg $ $Date: 2001-07-19 13:17:15 $
+ * last change: $Author: mtg $ $Date: 2001-08-08 18:29:56 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -109,6 +109,7 @@
#ifndef _INTERACTION_REQUEST_HXX_
#include <InteractionRequest.hxx>
#endif
+#include <memory>
using namespace rtl;
using namespace ucb;
@@ -132,6 +133,39 @@ using namespace com::sun::star::packages::zip;
using namespace com::sun::star::packages::manifest;
using namespace com::sun::star::packages::zip::ZipConstants;
+struct SuffixGenerator
+{
+ sal_Char mpSuffix[30], *mpSuffixMid, *mpSuffixEnd;
+ sal_uInt16 mnDigits;
+ SuffixGenerator(): mnDigits (2), mpSuffixMid ( mpSuffix), mpSuffixEnd ( mpSuffix + 2)
+ {
+ memset ( mpSuffix, 0, 30 );
+ mpSuffixMid[0] = 'a';
+ mpSuffixMid[1] = 'a'; // first generated suffix will be .ab
+ }
+ void generateFileName( OUString &rFileName, const OUString &rPrefix );
+};
+
+void SuffixGenerator::generateFileName( OUString &rFileName, const OUString &rPrefix )
+{
+ // same file prefix, different extension
+ OUStringBuffer aStringBuf;
+ sal_Char *p;
+ for ( p = mpSuffixEnd-1; *p == 'z'; p--)
+ *p = 'a';
+ ++(*p);
+ if (*p == 'z' && p == mpSuffixMid )
+ {
+ ++mnDigits;
+ ++mpSuffixMid;
+ *mpSuffixEnd++ = 'a';
+ *mpSuffixEnd++ = 'a';
+ }
+ aStringBuf.append ( rPrefix );
+ aStringBuf.appendAscii ( mpSuffix );
+ rFileName = aStringBuf.makeStringAndClear();
+}
+
ZipPackage::ZipPackage (const Reference < XMultiServiceFactory > &xNewFactory)
: pContent(NULL)
, pZipFile(NULL)
@@ -164,7 +198,7 @@ ZipPackage::~ZipPackage( void )
void ZipPackage::getZipFileContents()
{
- ZipEnumeration *pEnum = pZipFile->entries();
+ auto_ptr < ZipEnumeration > pEnum ( pZipFile->entries() );
Reference< XNameContainer > xCurrent;
ZipPackageStream *pPkgStream;
ZipPackageFolder *pPkgFolder;
@@ -367,10 +401,10 @@ void SAL_CALL ZipPackage::initialize( const Sequence< Any >& aArguments )
const sal_Int8 *pSeq = aSequence.getConstArray();
if (pSeq[0] == 'P' &&
pSeq[1] == 'K' &&
- pSeq[2] == '7' &&
- pSeq[3] == '8' )
+ pSeq[2] == 7 &&
+ pSeq[3] == 8 )
bSpanned = sal_True;
- }
+ }
else
bHaveZipFile = sal_False;
}
@@ -385,12 +419,13 @@ void SAL_CALL ZipPackage::initialize( const Sequence< Any >& aArguments )
{
try
{
- /*
if ( bSpanned)
+ {
+ xContentStream = unSpanFile ( xContentStream );
pZipFile = new ZipFile ( xContentStream, sURL );
+ }
else
- */
- pZipFile = new ZipFile ( xContentStream, sal_True);
+ pZipFile = new ZipFile ( xContentStream, sal_True);
getZipFileContents();
}
catch ( IOException & )
@@ -607,7 +642,7 @@ char * ImplGetChars( const OUString & rString )
// and no longer
sal_Int32 nLength = rString.getLength();
const sal_Unicode *pString = rString.getStr();
- char * pChar = new char [nLength];
+ char * pChar = new char [nLength+1];
for ( sal_Int16 i = 0; i < nLength; i++ )
{
pChar[i] = static_cast < char > (pString[i]);
@@ -620,7 +655,7 @@ void SAL_CALL ZipPackage::commitChanges( )
throw(WrappedTargetException, RuntimeException)
{
ThreadedBuffer *pBuffer;
- Reference < XOutputStream > xOutBuffer = (pBuffer = new ThreadedBuffer ( n_ConstBufferSize, nSegmentSize, *this ));
+ Reference < XOutputStream > xOutBuffer = (pBuffer = new ThreadedBuffer ( n_ConstBufferSize, *this ));
Reference < XInputStream > xInBuffer ( pBuffer );
ZipOutputStream aZipOut ( xOutBuffer, nSegmentSize != 0);
pBuffer->setZipOutputStream ( aZipOut );
@@ -635,13 +670,40 @@ void SAL_CALL ZipPackage::commitChanges( )
const OUString sMeta ( RTL_CONSTASCII_USTRINGPARAM ( "META-INF" ) );
if (xRootFolder->hasByName( sMeta ) )
xRootFolder->removeByName( sMeta );
+ /// >>>>>>>>
+ // Then create a tempfile...
+ OUString sServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) );
+
+ Reference < XOutputStream > xTempOut = Reference < XOutputStream > ( xFactory->createInstance ( sServiceName ), UNO_QUERY );
+#ifdef MTG_DEBUG
+ fprintf(stderr, "We have a %s tempfile!\n", xTempOut.is() ? "good" : "bad" );
+#endif
+ Reference < XInputStream > xTempIn = Reference < XInputStream > ( xTempOut, UNO_QUERY );
+ Reference < XSeekable > xTempSeek = Reference < XSeekable > ( xTempOut, UNO_QUERY );
+ // Then write the full package to the temp file...
+ Sequence < sal_Int8 > aBuffer;
+ sal_Int64 nRead;
+
+ do
+ {
+ nRead = xInBuffer->readBytes ( aBuffer, n_ConstBufferSize );
+ xTempOut->writeBytes( aBuffer );
+ }
+ while ( nRead == n_ConstBufferSize );
+
+ // seek back to the beginning of the temp file so we can read segments from it
+ xTempSeek->seek ( 0 );
+ xContentStream = xTempIn;
+ xContentSeek = xTempSeek;
+ pZipFile->setInputStream ( xTempIn );
+ // <<<<<<<<<<
if (!nSegmentSize )
{
try
{
- pContent->writeStream ( xInBuffer, sal_True );
+ pContent->writeStream ( xTempIn, sal_True );
}
catch (::com::sun::star::uno::Exception& r)
{
@@ -649,6 +711,8 @@ void SAL_CALL ZipPackage::commitChanges( )
static_cast < OWeakObject * > ( this ), makeAny( r ) );
}
Reference < XActiveDataSink > xSink = new ZipPackageSink;
+ /*
+ * We want to reference the temp file, not the one we just wrote
try
{
// Update our references to point to the new file
@@ -662,26 +726,34 @@ void SAL_CALL ZipPackage::commitChanges( )
throw WrappedTargetException( OUString::createFromAscii( "Unable to read Zip File content!" ),
static_cast < OWeakObject * > ( this ), makeAny( r ) );
}
+ */
}
else
{
// We want to span...first, make sure we have an interaction handler...
getInteractionHandler();
- sal_Int16 nDiskNum = 0;
- sal_Int32 nDot = sURL.lastIndexOf ( '.' );
- OUStringBuffer aStringBuf;
- Sequence < sal_Int8 > aBuffer;
-
- // If we don't have a specified segment size, don't span
-#ifdef UNX
- sal_Int32 nPrefixLength = sURL.lastIndexOf ( '/' );
-#else
- sal_Int32 nPrefixLength = 2 + sURL.lastIndexOf ( ':' );
-#endif
- OUString sMountPath ( sURL.copy ( 0, nPrefixLength ) );
+ sal_Int16 nDiskNum = 0;
VolumeInfo aInfo ( osl_VolumeInfo_Mask_FreeSpace | osl_VolumeInfo_Mask_DeviceHandle | osl_VolumeInfo_Mask_Attributes );
- FileBase::RC aRC = Directory::getVolumeInfo ( sMountPath, aInfo );
+ FileBase::RC aRC = Directory::getVolumeInfo ( sURL, aInfo );
+#ifdef MTG_DEBUG
+ fprintf(stderr, "MTG: url is %s getVolumeInfo returned %d\n", ImplGetChars ( sURL), aRC);
+ fprintf(stderr, "MTG: isRemovable returned %d\n", aInfo.getRemoveableFlag() );
+ fprintf(stderr, "MTG: isValid osl_VolumeInfo_Mask_FreeSpace returned %d\n", aInfo.isValid(osl_VolumeInfo_Mask_FreeSpace) );
+ fprintf(stderr, "MTG: isValid osl_VolumeInfo_Mask_DeviceHandle returned %d\n", aInfo.isValid(osl_VolumeInfo_Mask_DeviceHandle) );
+ fprintf(stderr, "MTG: isValid osl_VolumeInfo_Mask_Attributes returned %d\n", aInfo.isValid(osl_VolumeInfo_Mask_Attributes) );
+ fprintf(stderr, "MTG: getFreeSpace returned %ld\n", static_cast < sal_Int32 > ( aInfo.getFreeSpace() ) );
+ fprintf(stderr, "MTG: getUsedSpace returned %ld\n", static_cast < sal_Int32 > ( aInfo.getUsedSpace() ) );
+ fprintf(stderr, "MTG: getTotalSpace returned %ld\n", static_cast < sal_Int32 > ( aInfo.getTotalSpace() ) );
+#endif
+ VolumeDevice aDevice = aInfo.getDeviceHandle();
+ OUString sFileName, sMountPath = aDevice.getMountPath();
+#ifdef MTG_DEBUG
+ fprintf(stderr, "MTG: mount path is %s %d\n", ImplGetChars ( sMountPath ), aRC);
+#endif
+ sal_Int32 nLastSlash = sURL.lastIndexOf ( '/' );
+ OUString sFilePrefix = sURL.copy ( 1 + nLastSlash, sURL.lastIndexOf ( '.' ) - nLastSlash );
+
#ifdef MTG_DEBUG
fprintf(stderr, "MTG: url is %s first getVolumeInfo on %s returned %d\n", ImplGetChars ( sURL), ImplGetChars ( sMountPath), aRC);
#endif
@@ -689,46 +761,47 @@ void SAL_CALL ZipPackage::commitChanges( )
#ifdef MTG_DEBUG
fprintf(stderr, "MTG: Removable flag is %d\n", bIsRemovable);
#endif
+ SegmentEnum eRet = e_Finished;
+ SuffixGenerator aGenerator;
do
{
- pBuffer->nextSegment( ++nDiskNum);
- sal_Int32 nLastSlash = sURL.lastIndexOf ( '/' );
- if (nDiskNum == 1 )
- {
- // Everything after the last slash is file name
- aStringBuf.append ( sURL.copy ( 1 + nLastSlash ) );
- }
+ //pBuffer->nextSegment( ++nDiskNum);
+ nDiskNum++;
+ sal_Int64 nCurrentPos = xTempSeek->getPosition();
+ if ( nDiskNum == 1 )
+ sFileName = sURL.copy ( 1 + nLastSlash );
else
- {
- // same file prefix, different extension
- aStringBuf.append ( sURL.copy ( 1 + nLastSlash, sURL.lastIndexOf ( '.' ) - nLastSlash ) );
- aStringBuf.appendAscii ( nDiskNum -1 < 10 ? "s0" : "s" );
- aStringBuf.append ( static_cast < sal_Int32 > ( nDiskNum -1 ) );
-
- }
- OUString sFileName ( aStringBuf.makeStringAndClear() );
+ aGenerator.generateFileName ( sFileName, sFilePrefix );
if ( bIsRemovable )
{
if ( nDiskNum > 1 && RequestDisk( sMountPath, nDiskNum ) < 0 )
return;
- sal_Bool bRetry;
+
do
{
- bRetry = sal_False;
- SegmentEnum eRet = writeSegment ( sFileName, sMountPath, xInBuffer, aBuffer, bRetry, nDiskNum );
+ eRet = writeSegment ( sFileName, sMountPath, xTempIn, nDiskNum );
if (eRet == e_Aborted)
return;
+ else if ( eRet == e_Retry )
+ xTempSeek->seek ( nCurrentPos );
}
- while ( bRetry );
+ while ( eRet == e_Retry );
}
else
{
OUString sFullPath = sURL.copy ( 0, nLastSlash + 1 ) + sFileName;
- Content aContent (sFullPath, Reference < XCommandEnvironment >() );
- aContent.writeStream ( xInBuffer, sal_True );
+ do
+ {
+ eRet = writeSegment ( sFullPath, xTempIn );
+ if (eRet == e_Aborted)
+ return;
+ else if ( eRet == e_Retry )
+ xTempSeek->seek ( nCurrentPos );
+ }
+ while ( eRet == e_Retry );
}
}
- while ( !pBuffer->isOutputFinished() );
+ while ( eRet != e_Finished );
}
#ifdef MTG_DEBUG
fprintf ( stderr, "MTG: ZipPackage Commit finished\n");
@@ -768,7 +841,7 @@ sal_Int32 ZipPackage::RequestDisk ( OUString &rMountPath, sal_Int16 nDiskNum)
Any aExceptionAny, aMediumException;
InteractiveWrongMediumException aException;
- aMediumException <<= nDiskNum;
+ aMediumException <<= static_cast < sal_Int16 > (nDiskNum-1);
aException.Medium = aMediumException;
aExceptionAny <<= aException;
if ( !HandleError ( aExceptionAny, EC_YES|EC_ABORT ) )
@@ -792,11 +865,12 @@ sal_Int32 ZipPackage::RequestDisk ( OUString &rMountPath, sal_Int16 nDiskNum)
#endif
return FileBase::E_None;
}
-SegmentEnum ZipPackage::writeSegment ( const OUString &rFileName, OUString &rMountPath, Reference < XInputStream > &xInBuffer, Sequence < sal_Int8 > &rBuffer, sal_Bool bRetry, const sal_Int16 nDiskNum )
+SegmentEnum ZipPackage::writeSegment ( const OUString &rFileName, OUString &rMountPath, Reference < XInputStream > &xInBuffer, const sal_Int16 nDiskNum )
{
File *pFile = NULL;
FileBase::RC aRC;
sal_Bool bDynamicSpan = nSegmentSize < 0;
+ Sequence < sal_Int8 > aBuffer;
sal_Int32 nRead = n_ConstBufferSize;
sal_uInt64 nLeft, nWritten;
@@ -826,10 +900,10 @@ SegmentEnum ZipPackage::writeSegment ( const OUString &rFileName, OUString &rMou
bReCheck = sal_False;
sal_uInt64 nFree = aInfo.getFreeSpace();
#ifdef MTG_DEBUG
- fprintf(stderr, "MTG: free is %d\n", nFree );
+ fprintf(stderr, "MTG: free is %d\n", static_cast < sal_Int32 > ( nFree ) );
#endif
- if (( bDynamicSpan && nFree < 1000) ||
- !bDynamicSpan && nFree < nSegmentSize )
+ if ( ( bDynamicSpan && nFree < 1000 ) ||
+ ( !bDynamicSpan && nFree < nSegmentSize ) )
{
if ( !HandleError ( osl_File_E_NOSPC, EC_RETRY|EC_ABORT, sFullPath )
|| RequestDisk ( rMountPath, nDiskNum ) < 0 )
@@ -848,7 +922,7 @@ SegmentEnum ZipPackage::writeSegment ( const OUString &rFileName, OUString &rMou
{
nLeft = bDynamicSpan ? nFree : nSegmentSize;
#ifdef MTG_DEBUG
- fprintf(stderr, "MTG: left is %d\n", nLeft );
+ fprintf(stderr, "MTG: left is %ld\n", static_cast < sal_Int32 > ( nLeft ) );
#endif
}
}
@@ -880,33 +954,18 @@ SegmentEnum ZipPackage::writeSegment ( const OUString &rFileName, OUString &rMou
// dynamic spanning and 1000 bytes if dynamic spanning.
- /*
- if ( rOffset )
- {
- sal_uInt64 nLeft = rBuffer.getLength() - rOffset;
- sal_uInt64 nToWrite = (nSegmentSize - nTotalWritten ) > nLeft ? nLeft : nSegmentSize - nTotalWritten;
- aRC = aFile.write ( rBuffer.getConstArray() + rOffset, nToWrite, nWritten );
- VOS_ENSURE ( aRC == FileBase::E_None, "Unable to write to file!");
- nTotalWritten += nWritten;
- if ( nWritten != nToWrite )
- {
- rOffset += nWritten;
- // Need an interaction handler!
- }
- }
- */
-
// Let's read it all into the buffer in case something goes wrong and also
// so that the spannable checks in ByteChucker and ZipOutputStream work
- if (!bRetry)
- nRead = xInBuffer->readBytes ( rBuffer, static_cast < sal_Int32 > ( nLeft ) );
+ nRead = xInBuffer->readBytes ( aBuffer, static_cast < sal_Int32 > ( nLeft ) );
- aRC = pFile->write ( rBuffer.getConstArray(), nRead, nWritten );
+ aRC = pFile->write ( aBuffer.getConstArray(), nRead, nWritten );
#ifdef MTG_DEBUG
fprintf ( stderr, "MTG: write returned %d\n", aRC );
#endif
+ sal_Bool bRetry = sal_False;
+
if ( nWritten != nRead || aRC != FileBase::E_None )
bRetry = sal_True;
else
@@ -919,7 +978,111 @@ SegmentEnum ZipPackage::writeSegment ( const OUString &rFileName, OUString &rMou
bRetry = sal_True;
}
delete pFile;
- return bRetry ? e_Retry : e_Success;
+ return nRead < nLeft ? e_Finished : bRetry ? e_Retry : e_Success;
+}
+
+SegmentEnum ZipPackage::writeSegment ( const OUString &rFileName, Reference < XInputStream > &xInBuffer )
+{
+ FileBase::RC aRC;
+ Sequence < sal_Int8 > aBuffer ( nSegmentSize );
+
+ sal_Int32 nRead = n_ConstBufferSize;
+ sal_uInt64 nWritten;
+
+ nRead = xInBuffer->readBytes ( aBuffer, static_cast < sal_Int32 > ( nSegmentSize ) );
+
+ File aFile ( rFileName );
+ aRC = aFile.open ( osl_File_OpenFlag_Create | osl_File_OpenFlag_Write );
+ if ( aRC == FileBase::E_EXIST )
+ aRC = aFile.open ( osl_File_OpenFlag_Write );
+ if ( aRC != FileBase::E_None )
+ {
+ if ( ! HandleError ( (oslFileError) aRC, EC_RETRY|EC_ABORT, rFileName ) )
+ return e_Aborted;
+ }
+
+ aRC = aFile.write ( aBuffer.getConstArray(), nRead, nWritten );
+#ifdef MTG_DEBUG
+ fprintf ( stderr, "MTG: write returned %d\n", aRC );
+#endif
+
+ sal_Bool bRetry = sal_False;
+ if ( nWritten != nRead || aRC != FileBase::E_None )
+ bRetry = sal_True;
+ else
+ {
+ aRC = aFile.close ();
+#ifdef MTG_DEBUG
+ fprintf ( stderr, "MTG: close returned %d\n", aRC );
+#endif
+ if ( aRC != FileBase::E_None )
+ bRetry = sal_True;
+ }
+ return nRead < nSegmentSize ? e_Finished : bRetry ? e_Retry : e_Success;
+}
+
+SegmentEnum ZipPackage::readSegment ( const OUString &rFileName, OUString &rMountPath, Reference < XOutputStream > &xTempOut, const sal_Int16 nDiskNum )
+{
+ File *pFile = NULL;
+ FileBase::RC aRC;
+ SegmentEnum eRet;
+
+ OUStringBuffer aStringBuffer;
+ aStringBuffer.append ( rMountPath );
+ if ( rMountPath.lastIndexOf ( '/' ) != rMountPath.getLength()-1 )
+ aStringBuffer.appendAscii ( "/" );
+ aStringBuffer.append ( rFileName );
+ OUString sFullPath ( aStringBuffer.makeStringAndClear() );
+
+ DirectoryItem aItem;
+ do
+ {
+ aRC = DirectoryItem::get ( sFullPath, aItem );
+ if ( aRC != FileBase::E_None && !HandleError ( (oslFileError) aRC, EC_RETRY|EC_ABORT, sFullPath ) )
+ return e_Aborted;
+ }
+ while (aRC != FileBase::E_None );
+ do
+ {
+ pFile = new File ( sFullPath );
+ aRC = pFile->open ( osl_File_OpenFlag_Read );
+ if ( aRC != FileBase::E_None )
+ {
+ delete pFile;
+ if ( ! HandleError ( (oslFileError) aRC, EC_RETRY|EC_ABORT, sFullPath ) )
+ return e_Aborted;
+ }
+ }
+ while (aRC != FileBase::E_None );
+
+ FileStatus aStatus ( FileStatusMask_FileSize );
+ aItem.getFileStatus ( aStatus );
+ sal_uInt64 nRead, nLeft = aStatus.getFileSize(), nToRead;
+
+ Sequence < sal_Int8 > aBuffer ( n_ConstBufferSize );
+ do
+ {
+ nToRead = nLeft < n_ConstBufferSize ? nLeft : n_ConstBufferSize;
+ aRC = pFile->read ( static_cast < void* > ( aBuffer.getArray() ), nToRead, nRead );
+ if ( aRC != FileBase::E_None )
+ {
+ if ( ! HandleError ( (oslFileError) aRC, EC_RETRY|EC_ABORT, sFullPath ) )
+ return e_Aborted;
+ }
+ else
+ {
+ Sequence < sal_Int8 > aReadBuf ( aBuffer.getConstArray(), static_cast < sal_Int32 > ( nRead ) );
+ nLeft -= nRead;
+ xTempOut->writeBytes ( aReadBuf );
+ if (nLeft == 0)
+ eRet = checkEnd ( aReadBuf ) ? e_Finished : e_Success;
+ }
+ }
+ while (nLeft > 0 );
+
+ aRC = pFile->close ();
+ delete pFile;
+ return eRet;
}
sal_Bool SAL_CALL ZipPackage::hasPendingChanges( )
@@ -1047,8 +1210,6 @@ void SAL_CALL ZipPackage::setPropertyValue( const OUString& aPropertyName, const
{
if (!( aValue >>= nSegmentSize ) )
throw IllegalArgumentException();
- // always force the value back to 0 as this feature is not complete
- nSegmentSize = 0;
}
else
throw UnknownPropertyException();
@@ -1187,7 +1348,7 @@ sal_Bool ZipPackage::HandleError ( Any &rAny, sal_uInt16 eContinuations )
return nSelection == EC_YES || nSelection == EC_RETRY;
}
-sal_Bool ZipPackage::HandleError ( oslFileError aRC, sal_uInt16 eContinuations, OUString &rFileName )
+sal_Bool ZipPackage::HandleError ( oslFileError aRC, sal_uInt16 eContinuations, const OUString &rFileName )
{
Any aAny;
InteractiveFileIOException aException;
@@ -1196,3 +1357,107 @@ sal_Bool ZipPackage::HandleError ( oslFileError aRC, sal_uInt16 eContinuations,
aAny <<= aException;
return HandleError (aAny, eContinuations );
}
+
+Reference < XInputStream > ZipPackage::unSpanFile ( Reference < XInputStream > &rStream )
+{
+ const OUString sServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) );
+ Reference < XInputStream > xTempIn = Reference < XInputStream > ( xFactory->createInstance ( sServiceName ), UNO_QUERY );
+ Reference < XOutputStream > xTempOut = Reference < XOutputStream > ( xTempIn, UNO_QUERY );
+ Reference < XSeekable > xTempSeek = Reference < XSeekable > ( xTempIn, UNO_QUERY );
+ Reference < XSeekable > xInSeek = Reference < XSeekable > ( rStream, UNO_QUERY );
+
+ Sequence < sal_Int8 > aBuffer;
+ sal_Int64 nRead;
+ xInSeek->seek ( 0 ); // Skip spanned header
+ do
+ {
+ nRead = rStream->readBytes ( aBuffer, n_ConstBufferSize );
+ xTempOut->writeBytes ( aBuffer );
+ }
+ while ( nRead == n_ConstBufferSize );
+
+ // Check if the buffer just read is the last one
+ if ( checkEnd ( aBuffer ) )
+ return xTempIn;
+
+ sal_Int16 nDiskNum = 1;
+ VolumeInfo aInfo ( osl_VolumeInfo_Mask_FreeSpace | osl_VolumeInfo_Mask_DeviceHandle | osl_VolumeInfo_Mask_Attributes );
+ FileBase::RC aRC = Directory::getVolumeInfo ( sURL, aInfo );
+ VolumeDevice aDevice = aInfo.getDeviceHandle();
+ sal_Bool bIsRemovable = aInfo.getRemoveableFlag();
+
+ sal_Int32 nLastSlash = sURL.lastIndexOf ( '/' );
+ OUString sFileName, sMountPath = aDevice.getMountPath();
+ const OUString sFilePrefix = sURL.copy ( 1 + nLastSlash, sURL.lastIndexOf ( '.' ) - nLastSlash );
+ SegmentEnum eRet = e_Finished;
+ SuffixGenerator aGenerator;
+ do
+ {
+ //pBuffer->nextSegment( ++nDiskNum);
+ nDiskNum++;
+ aGenerator.generateFileName ( sFileName, sFilePrefix );
+ if ( bIsRemovable )
+ {
+ // We need an interaction handler to request disks
+ getInteractionHandler();
+ if ( RequestDisk( sMountPath, nDiskNum ) < 0 )
+ return Reference < XInputStream > ();
+ eRet = readSegment ( sFileName, sMountPath, xTempOut, nDiskNum );
+ if (eRet == e_Aborted)
+ return Reference < XInputStream > ();
+ }
+ else
+ {
+ OUString sFullPath = sURL.copy ( 0, nLastSlash + 1 ) + sFileName;
+ Reference < XInputStream > xStream;
+ Content aContent (sFullPath, Reference < XCommandEnvironment >() );
+ Reference < XActiveDataSink > xSink = new ZipPackageSink;
+ try
+ {
+ if (aContent.openStream ( xSink ) )
+ xStream = xSink->getInputStream();
+ if ( xStream.is() )
+ {
+ do
+ {
+ nRead = xStream->readBytes ( aBuffer, n_ConstBufferSize );
+ xTempOut->writeBytes ( aBuffer );
+ }
+ while ( nRead == n_ConstBufferSize );
+ eRet = checkEnd ( aBuffer ) ? e_Finished : e_Success;
+ }
+ }
+ catch (com::sun::star::uno::Exception&)
+ {
+ // bad juju
+ //
+ }
+ }
+ }
+ while ( eRet != e_Finished );
+
+ return xTempIn;
+}
+
+sal_Bool ZipPackage::checkEnd ( Sequence < sal_Int8 > &rSequence )
+{
+ sal_Int32 nLength, nPos, nEnd;
+
+ nLength = static_cast <sal_Int32 > (rSequence.getLength());
+ // Start at what should be the beginning of the end header
+ if ( nLength == 0 || nLength < ENDHDR )
+ return sal_False;
+ nPos = nLength - ENDHDR - ZIP_MAXNAMELEN;
+ // We'll only look for the END signature within a sane range (ZIP_MAXNAMELEN)
+ nEnd = nPos >= 0 ? nPos : 0;
+
+ const sal_Int8 *pBuffer = rSequence.getConstArray();
+ nPos = nLength - ENDHDR;
+ while ( nPos >= nEnd )
+ {
+ if (pBuffer[nPos] == 'P' && pBuffer[nPos+1] == 'K' && pBuffer[nPos+2] == 5 && pBuffer[nPos+3] == 6 )
+ return sal_True;
+ nPos--;
+ }
+ return sal_False;
+}