1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include "WPXSvStream.hxx"
11 #include <tools/stream.hxx>
12 #include <unotools/streamwrap.hxx>
13 #include <unotools/ucbstreamhelper.hxx>
17 using namespace ::com::sun::star::uno
;
18 using namespace ::com::sun::star::io
;
22 static void splitPath( std::vector
<OUString
> &rElems
, const OUString
&rPath
)
24 for (sal_Int32 i
= 0; i
>= 0;)
25 rElems
.push_back( rPath
.getToken( 0, '/', i
) );
28 } // anonymous namespace
33 } SotStorageRefWrapper
;
37 SotStorageStreamRef ref
;
38 } SotStorageStreamRefWrapper
;
40 class WPXSvInputStreamImpl
: public WPXInputStream
43 WPXSvInputStreamImpl( ::com::sun::star::uno::Reference
<
44 ::com::sun::star::io::XInputStream
> xStream
);
45 ~WPXSvInputStreamImpl();
48 WPXInputStream
* getDocumentOLEStream(const char *name
);
50 const unsigned char *read(unsigned long numBytes
, unsigned long &numBytesRead
);
51 int seek(long offset
, WPX_SEEK_TYPE seekType
);
55 ::std::vector
< SotStorageRefWrapper
> mxChildrenStorages
;
56 ::std::vector
< SotStorageStreamRefWrapper
> mxChildrenStreams
;
57 ::com::sun::star::uno::Reference
<
58 ::com::sun::star::io::XInputStream
> mxStream
;
59 ::com::sun::star::uno::Reference
<
60 ::com::sun::star::io::XSeekable
> mxSeekable
;
61 ::com::sun::star::uno::Sequence
< sal_Int8
> maData
;
65 WPXSvInputStreamImpl::WPXSvInputStreamImpl( Reference
< XInputStream
> xStream
) :
70 mxSeekable(xStream
, UNO_QUERY
),
73 if (!xStream
.is() || !mxStream
.is())
83 mnLength
= mxSeekable
->getLength();
87 SAL_WARN("writerperfect", "mnLength = mxSeekable->getLength() threw exception");
94 WPXSvInputStreamImpl::~WPXSvInputStreamImpl()
98 const unsigned char *WPXSvInputStreamImpl::read(unsigned long numBytes
, unsigned long &numBytesRead
)
102 if (numBytes
== 0 || atEOS())
105 numBytesRead
= mxStream
->readSomeBytes (maData
, numBytes
);
106 if (numBytesRead
== 0)
109 return (const unsigned char *)maData
.getConstArray();
112 long WPXSvInputStreamImpl::tell()
114 if ((mnLength
== 0) || !mxStream
.is() || !mxSeekable
.is())
118 sal_Int64 tmpPosition
= mxSeekable
->getPosition();
119 if ((tmpPosition
< 0) || (tmpPosition
> (std::numeric_limits
<long>::max
)()))
121 return (long)tmpPosition
;
125 int WPXSvInputStreamImpl::seek(long offset
, WPX_SEEK_TYPE seekType
)
127 if ((mnLength
== 0) || !mxStream
.is() || !mxSeekable
.is())
130 sal_Int64 tmpPosition
= mxSeekable
->getPosition();
131 if ((tmpPosition
< 0) || (tmpPosition
> (std::numeric_limits
<long>::max
)()))
134 sal_Int64 tmpOffset
= offset
;
135 if (seekType
== WPX_SEEK_CUR
)
136 tmpOffset
+= tmpPosition
;
137 if (seekType
== WPX_SEEK_END
)
138 tmpOffset
+= mnLength
;
146 if (offset
> mnLength
)
148 tmpOffset
= mnLength
;
154 mxSeekable
->seek(tmpOffset
);
159 SAL_WARN("writerperfect", "mxSeekable->seek(offset) threw exception");
164 bool WPXSvInputStreamImpl::atEOS()
166 if ((mnLength
== 0) || !mxStream
.is() || !mxSeekable
.is())
168 return (mxSeekable
->getPosition() >= mnLength
);
171 bool WPXSvInputStreamImpl::isOLEStream()
173 if ((mnLength
== 0) || !mxStream
.is() || !mxSeekable
.is())
176 sal_Int64 tmpPosition
= mxSeekable
->getPosition();
179 SvStream
*pStream
= utl::UcbStreamHelper::CreateStream( mxStream
);
180 bool bAns
= pStream
&& SotStorage::IsOLEStorage( pStream
);
184 mxSeekable
->seek(tmpPosition
);
189 WPXInputStream
*WPXSvInputStreamImpl::getDocumentOLEStream(const char *name
)
193 OUString
rPath(name
,strlen(name
),RTL_TEXTENCODING_UTF8
);
194 std::vector
<OUString
> aElems
;
195 splitPath( aElems
, rPath
);
197 if ((mnLength
== 0) || !mxStream
.is() || !mxSeekable
.is())
200 sal_Int64 tmpPosition
= mxSeekable
->getPosition();
203 SvStream
*pStream
= utl::UcbStreamHelper::CreateStream( mxStream
);
205 if (!pStream
|| !SotStorage::IsOLEStorage( pStream
))
207 mxSeekable
->seek(tmpPosition
);
211 SotStorageRefWrapper storageRefWrapper
;
212 storageRefWrapper
.ref
= new SotStorage( pStream
, sal_True
);
213 mxChildrenStorages
.push_back( storageRefWrapper
);
216 while (i
< aElems
.size())
218 if( mxChildrenStorages
.back().ref
->IsStream(aElems
[i
]))
220 else if (mxChildrenStorages
.back().ref
->IsStorage(aElems
[i
]))
222 SotStorageRef
tmpParent(mxChildrenStorages
.back().ref
);
223 storageRefWrapper
.ref
= tmpParent
->OpenSotStorage(aElems
[i
++], STREAM_STD_READ
);
224 mxChildrenStorages
.push_back(storageRefWrapper
);
231 // For the while don't return stream in this situation.
232 // Later, given how libcdr's zip stream implementation behaves,
233 // return the first stream in the storage if there is one.
234 if (i
>= aElems
.size())
237 SotStorageStreamRefWrapper storageStreamRefWrapper
;
238 storageStreamRefWrapper
.ref
= mxChildrenStorages
.back().ref
->OpenSotStream( aElems
[i
], STREAM_STD_READ
);
239 mxChildrenStreams
.push_back( storageStreamRefWrapper
);
241 mxSeekable
->seek(tmpPosition
);
243 if ( !mxChildrenStreams
.back().ref
.Is() || mxChildrenStreams
.back().ref
->GetError() )
245 mxSeekable
->seek(tmpPosition
);
249 Reference
< XInputStream
> xContents(new utl::OSeekableInputStreamWrapper( mxChildrenStreams
.back().ref
));
250 mxSeekable
->seek(tmpPosition
);
252 return new WPXSvInputStream( xContents
);
258 WPXSvInputStream::WPXSvInputStream( Reference
< XInputStream
> xStream
) :
259 mpImpl(new WPXSvInputStreamImpl(xStream
))
263 WPXSvInputStream::~WPXSvInputStream()
268 const unsigned char *WPXSvInputStream::read(unsigned long numBytes
, unsigned long &numBytesRead
)
270 return mpImpl
->read(numBytes
, numBytesRead
);
273 long WPXSvInputStream::tell()
275 return mpImpl
->tell();
278 int WPXSvInputStream::seek(long offset
, WPX_SEEK_TYPE seekType
)
280 return mpImpl
->seek(offset
, seekType
);
283 bool WPXSvInputStream::atEOS()
285 return mpImpl
->atEOS();
288 bool WPXSvInputStream::isOLEStream()
290 return mpImpl
->isOLEStream();
293 WPXInputStream
*WPXSvInputStream::getDocumentOLEStream(const char *name
)
295 return mpImpl
->getDocumentOLEStream(name
);
298 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */