Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : */
9 :
10 : #include "WPXSvStream.hxx"
11 : #include <tools/stream.hxx>
12 : #include <unotools/streamwrap.hxx>
13 : #include <unotools/ucbstreamhelper.hxx>
14 : #include <limits>
15 : #include <vector>
16 :
17 : using namespace ::com::sun::star::uno;
18 : using namespace ::com::sun::star::io;
19 :
20 : namespace
21 : {
22 0 : static void splitPath( std::vector<OUString> &rElems, const OUString &rPath )
23 : {
24 0 : for (sal_Int32 i = 0; i >= 0;)
25 0 : rElems.push_back( rPath.getToken( 0, '/', i ) );
26 0 : }
27 :
28 : } // anonymous namespace
29 :
30 : typedef struct
31 0 : {
32 : SotStorageRef ref;
33 0 : } SotStorageRefWrapper;
34 :
35 : typedef struct
36 0 : {
37 : SotStorageStreamRef ref;
38 0 : } SotStorageStreamRefWrapper;
39 :
40 : class WPXSvInputStreamImpl : public WPXInputStream
41 : {
42 : public :
43 : WPXSvInputStreamImpl( ::com::sun::star::uno::Reference<
44 : ::com::sun::star::io::XInputStream > xStream );
45 : ~WPXSvInputStreamImpl();
46 :
47 : bool isOLEStream();
48 : WPXInputStream * getDocumentOLEStream(const char *name);
49 :
50 : const unsigned char *read(unsigned long numBytes, unsigned long &numBytesRead);
51 : int seek(long offset, WPX_SEEK_TYPE seekType);
52 : long tell();
53 : bool atEOS();
54 : private:
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;
62 : sal_Int64 mnLength;
63 : };
64 :
65 72 : WPXSvInputStreamImpl::WPXSvInputStreamImpl( Reference< XInputStream > xStream ) :
66 : WPXInputStream(),
67 : mxChildrenStorages(),
68 : mxChildrenStreams(),
69 : mxStream(xStream),
70 : mxSeekable(xStream, UNO_QUERY),
71 72 : maData(0)
72 : {
73 72 : if (!xStream.is() || !mxStream.is())
74 0 : mnLength = 0;
75 : else
76 : {
77 72 : if (!mxSeekable.is())
78 0 : mnLength = 0;
79 : else
80 : {
81 : try
82 : {
83 72 : mnLength = mxSeekable->getLength();
84 : }
85 0 : catch ( ... )
86 : {
87 : SAL_WARN("writerperfect", "mnLength = mxSeekable->getLength() threw exception");
88 0 : mnLength = 0;
89 : }
90 : }
91 : }
92 72 : }
93 :
94 144 : WPXSvInputStreamImpl::~WPXSvInputStreamImpl()
95 : {
96 144 : }
97 :
98 1584 : const unsigned char *WPXSvInputStreamImpl::read(unsigned long numBytes, unsigned long &numBytesRead)
99 : {
100 1584 : numBytesRead = 0;
101 :
102 1584 : if (numBytes == 0 || atEOS())
103 0 : return 0;
104 :
105 1584 : numBytesRead = mxStream->readSomeBytes (maData, numBytes);
106 1584 : if (numBytesRead == 0)
107 0 : return 0;
108 :
109 1584 : return (const unsigned char *)maData.getConstArray();
110 : }
111 :
112 1494 : long WPXSvInputStreamImpl::tell()
113 : {
114 1494 : if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
115 0 : return -1L;
116 : else
117 : {
118 1494 : sal_Int64 tmpPosition = mxSeekable->getPosition();
119 1494 : if ((tmpPosition < 0) || (tmpPosition > (std::numeric_limits<long>::max)()))
120 0 : return -1L;
121 1494 : return (long)tmpPosition;
122 : }
123 : }
124 :
125 2070 : int WPXSvInputStreamImpl::seek(long offset, WPX_SEEK_TYPE seekType)
126 : {
127 2070 : if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
128 0 : return -1;
129 :
130 2070 : sal_Int64 tmpPosition = mxSeekable->getPosition();
131 2070 : if ((tmpPosition < 0) || (tmpPosition > (std::numeric_limits<long>::max)()))
132 0 : return -1;
133 :
134 2070 : sal_Int64 tmpOffset = offset;
135 2070 : if (seekType == WPX_SEEK_CUR)
136 0 : tmpOffset += tmpPosition;
137 : #if defined(LIBWPD_STREAM_VERSION_MAJOR) && defined(LIBWPD_STREAM_VERSION_MINOR) && defined(LIBWPD_STREAM_VERSION_REVISION) \
138 : && (LIBWPD_STREAM_VERSION_MAJOR > 0 || (LIBWPD_STREAM_VERSION_MAJOR == 0 && (LIBWPD_STREAM_VERSION_MINOR > 9 \
139 : || (LIBWPD_STREAM_VERSION_MINOR == 9 && LIBWPD_STREAM_VERSION_REVISION >= 5))))
140 : if (seekType == WPX_SEEK_END)
141 : tmpOffset += mnLength;
142 : #endif
143 :
144 2070 : int retVal = 0;
145 2070 : if (tmpOffset < 0)
146 : {
147 0 : tmpOffset = 0;
148 0 : retVal = -1;
149 : }
150 2070 : if (offset > mnLength)
151 : {
152 72 : tmpOffset = mnLength;
153 72 : retVal = -1;
154 : }
155 :
156 : try
157 : {
158 2070 : mxSeekable->seek(tmpOffset);
159 2070 : return retVal;
160 : }
161 0 : catch (...)
162 : {
163 : SAL_WARN("writerperfect", "mxSeekable->seek(offset) threw exception");
164 0 : return -1;
165 : }
166 : }
167 :
168 4590 : bool WPXSvInputStreamImpl::atEOS()
169 : {
170 4590 : if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
171 0 : return true;
172 4590 : return (mxSeekable->getPosition() >= mnLength);
173 : }
174 :
175 0 : bool WPXSvInputStreamImpl::isOLEStream()
176 : {
177 0 : if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
178 0 : return false;
179 :
180 0 : sal_Int64 tmpPosition = mxSeekable->getPosition();
181 0 : mxSeekable->seek(0);
182 :
183 0 : SvStream *pStream = utl::UcbStreamHelper::CreateStream( mxStream );
184 0 : bool bAns = pStream && SotStorage::IsOLEStorage( pStream );
185 0 : if (pStream)
186 0 : delete pStream;
187 :
188 0 : mxSeekable->seek(tmpPosition);
189 :
190 0 : return bAns;
191 : }
192 :
193 0 : WPXInputStream *WPXSvInputStreamImpl::getDocumentOLEStream(const char *name)
194 : {
195 0 : if (!name)
196 0 : return 0;
197 0 : OUString rPath(name,strlen(name),RTL_TEXTENCODING_UTF8);
198 0 : std::vector<OUString> aElems;
199 0 : splitPath( aElems, rPath );
200 :
201 0 : if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
202 0 : return 0;
203 :
204 0 : sal_Int64 tmpPosition = mxSeekable->getPosition();
205 0 : mxSeekable->seek(0);
206 :
207 0 : SvStream *pStream = utl::UcbStreamHelper::CreateStream( mxStream );
208 :
209 0 : if (!pStream || !SotStorage::IsOLEStorage( pStream ))
210 : {
211 0 : mxSeekable->seek(tmpPosition);
212 0 : return 0;
213 : }
214 :
215 0 : SotStorageRefWrapper storageRefWrapper;
216 0 : storageRefWrapper.ref = new SotStorage( pStream, sal_True );
217 0 : mxChildrenStorages.push_back( storageRefWrapper );
218 :
219 0 : unsigned i = 0;
220 0 : while (i < aElems.size())
221 : {
222 0 : if( mxChildrenStorages.back().ref->IsStream(aElems[i]))
223 0 : break;
224 0 : else if (mxChildrenStorages.back().ref->IsStorage(aElems[i]))
225 : {
226 0 : SotStorageRef tmpParent(mxChildrenStorages.back().ref);
227 0 : storageRefWrapper.ref = tmpParent->OpenSotStorage(aElems[i++], STREAM_STD_READ);
228 0 : mxChildrenStorages.push_back(storageRefWrapper);
229 : }
230 : else
231 : // should not happen
232 0 : return 0;
233 : }
234 :
235 : // For the while don't return stream in this situation.
236 : // Later, given how libcdr's zip stream implementation behaves,
237 : // return the first stream in the storage if there is one.
238 0 : if (i >= aElems.size())
239 0 : return 0;
240 :
241 0 : SotStorageStreamRefWrapper storageStreamRefWrapper;
242 0 : storageStreamRefWrapper.ref = mxChildrenStorages.back().ref->OpenSotStream( aElems[i], STREAM_STD_READ );
243 0 : mxChildrenStreams.push_back( storageStreamRefWrapper );
244 :
245 0 : mxSeekable->seek(tmpPosition);
246 :
247 0 : if ( !mxChildrenStreams.back().ref.Is() || mxChildrenStreams.back().ref->GetError() )
248 : {
249 0 : mxSeekable->seek(tmpPosition);
250 0 : return 0;
251 : }
252 :
253 0 : Reference < XInputStream > xContents(new utl::OSeekableInputStreamWrapper( mxChildrenStreams.back().ref ));
254 0 : mxSeekable->seek(tmpPosition);
255 0 : if (xContents.is())
256 0 : return new WPXSvInputStream( xContents );
257 : else
258 0 : return 0;
259 : }
260 :
261 :
262 72 : WPXSvInputStream::WPXSvInputStream( Reference< XInputStream > xStream ) :
263 72 : mpImpl(new WPXSvInputStreamImpl(xStream))
264 : {
265 72 : }
266 :
267 144 : WPXSvInputStream::~WPXSvInputStream()
268 : {
269 72 : delete mpImpl;
270 72 : }
271 :
272 1584 : const unsigned char *WPXSvInputStream::read(unsigned long numBytes, unsigned long &numBytesRead)
273 : {
274 1584 : return mpImpl->read(numBytes, numBytesRead);
275 : }
276 :
277 1494 : long WPXSvInputStream::tell()
278 : {
279 1494 : return mpImpl->tell();
280 : }
281 :
282 2070 : int WPXSvInputStream::seek(long offset, WPX_SEEK_TYPE seekType)
283 : {
284 2070 : return mpImpl->seek(offset, seekType);
285 : }
286 :
287 3006 : bool WPXSvInputStream::atEOS()
288 : {
289 3006 : return mpImpl->atEOS();
290 : }
291 :
292 0 : bool WPXSvInputStream::isOLEStream()
293 : {
294 0 : return mpImpl->isOLEStream();
295 : }
296 :
297 0 : WPXInputStream *WPXSvInputStream::getDocumentOLEStream(const char *name)
298 : {
299 0 : return mpImpl->getDocumentOLEStream(name);
300 : }
301 :
302 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|