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.h"
11 : #include "filter/FilterInternal.hxx"
12 : #include <tools/stream.hxx>
13 : #include <unotools/streamwrap.hxx>
14 : #include <unotools/ucbstreamhelper.hxx>
15 : #include <limits>
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<rtl::OUString> &rElems, const ::rtl::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 0 : WPXSvInputStream::WPXSvInputStream( Reference< XInputStream > xStream ) :
31 : WPXInputStream(),
32 : mxChildrenStorages(),
33 : mxChildrenStreams(),
34 : mxStream(xStream),
35 : mxSeekable(xStream, UNO_QUERY),
36 0 : maData(0)
37 : {
38 0 : if (!xStream.is() || !mxStream.is())
39 0 : mnLength = 0;
40 : else
41 : {
42 0 : if (!mxSeekable.is())
43 0 : mnLength = 0;
44 : else
45 : {
46 : try
47 : {
48 0 : mnLength = mxSeekable->getLength();
49 : }
50 0 : catch ( ... )
51 : {
52 : WRITER_DEBUG_MSG(("mnLength = mxSeekable->getLength() threw exception\n"));
53 0 : mnLength = 0;
54 : }
55 : }
56 : }
57 0 : }
58 :
59 0 : WPXSvInputStream::~WPXSvInputStream()
60 : {
61 0 : }
62 :
63 0 : const unsigned char *WPXSvInputStream::read(unsigned long numBytes, unsigned long &numBytesRead)
64 : {
65 0 : numBytesRead = 0;
66 :
67 0 : if (numBytes == 0 || atEOS())
68 0 : return 0;
69 :
70 0 : numBytesRead = mxStream->readSomeBytes (maData, numBytes);
71 0 : if (numBytesRead == 0)
72 0 : return 0;
73 :
74 0 : return (const unsigned char *)maData.getConstArray();
75 : }
76 :
77 0 : long WPXSvInputStream::tell()
78 : {
79 0 : if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
80 0 : return -1L;
81 : else
82 : {
83 0 : sal_Int64 tmpPosition = mxSeekable->getPosition();
84 0 : if ((tmpPosition < 0) || (tmpPosition > (std::numeric_limits<long>::max)()))
85 0 : return -1L;
86 0 : return (long)tmpPosition;
87 : }
88 : }
89 :
90 0 : int WPXSvInputStream::seek(long offset, WPX_SEEK_TYPE seekType)
91 : {
92 0 : if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
93 0 : return -1;
94 :
95 0 : sal_Int64 tmpPosition = mxSeekable->getPosition();
96 0 : if ((tmpPosition < 0) || (tmpPosition > (std::numeric_limits<long>::max)()))
97 0 : return -1;
98 :
99 0 : sal_Int64 tmpOffset = offset;
100 0 : if (seekType == WPX_SEEK_CUR)
101 0 : tmpOffset += tmpPosition;
102 : #if defined(LIBWPD_STREAM_VERSION_MAJOR) && defined(LIBWPD_STREAM_VERSION_MINOR) && defined(LIBWPD_STREAM_VERSION_REVISION) \
103 : && (LIBWPD_STREAM_VERSION_MAJOR > 0 || (LIBWPD_STREAM_VERSION_MAJOR == 0 && (LIBWPD_STREAM_VERSION_MINOR > 9 \
104 : || (LIBWPD_STREAM_VERSION_MINOR == 9 && LIBWPD_STREAM_VERSION_REVISION >= 5))))
105 : if (seekType == WPX_SEEK_END)
106 : tmpOffset += mnLength;
107 : #endif
108 :
109 0 : int retVal = 0;
110 0 : if (tmpOffset < 0)
111 : {
112 0 : tmpOffset = 0;
113 0 : retVal = -1;
114 : }
115 0 : if (offset > mnLength)
116 : {
117 0 : tmpOffset = mnLength;
118 0 : retVal = -1;
119 : }
120 :
121 : try
122 : {
123 0 : mxSeekable->seek(tmpOffset);
124 0 : return retVal;
125 : }
126 0 : catch (...)
127 : {
128 : WRITER_DEBUG_MSG(("mxSeekable->seek(offset) threw exception\n"));
129 0 : return -1;
130 : }
131 : }
132 :
133 0 : bool WPXSvInputStream::atEOS()
134 : {
135 0 : if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
136 0 : return true;
137 0 : return (mxSeekable->getPosition() >= mnLength);
138 : }
139 :
140 0 : bool WPXSvInputStream::isOLEStream()
141 : {
142 0 : if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
143 0 : return false;
144 :
145 0 : sal_Int64 tmpPosition = mxSeekable->getPosition();
146 0 : mxSeekable->seek(0);
147 :
148 0 : SvStream *pStream = utl::UcbStreamHelper::CreateStream( mxStream );
149 0 : bool bAns = pStream && SotStorage::IsOLEStorage( pStream );
150 0 : if (pStream)
151 0 : delete pStream;
152 :
153 0 : mxSeekable->seek(tmpPosition);
154 :
155 0 : return bAns;
156 : }
157 :
158 0 : WPXInputStream *WPXSvInputStream::getDocumentOLEStream(const char *name)
159 : {
160 0 : if (!name)
161 0 : return 0;
162 0 : rtl::OUString rPath(name,strlen(name),RTL_TEXTENCODING_UTF8);
163 0 : std::vector<rtl::OUString> aElems;
164 0 : splitPath( aElems, rPath );
165 :
166 0 : if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
167 0 : return 0;
168 :
169 0 : sal_Int64 tmpPosition = mxSeekable->getPosition();
170 0 : mxSeekable->seek(0);
171 :
172 0 : SvStream *pStream = utl::UcbStreamHelper::CreateStream( mxStream );
173 :
174 0 : if (!pStream || !SotStorage::IsOLEStorage( pStream ))
175 : {
176 0 : mxSeekable->seek(tmpPosition);
177 0 : return 0;
178 : }
179 :
180 0 : SotStorageRefWrapper storageRefWrapper;
181 0 : storageRefWrapper.ref = new SotStorage( pStream, sal_True );
182 0 : mxChildrenStorages.push_back( storageRefWrapper );
183 :
184 0 : unsigned i = 0;
185 0 : while (i < aElems.size())
186 : {
187 0 : if( mxChildrenStorages.back().ref->IsStream(aElems[i]))
188 0 : break;
189 0 : else if (mxChildrenStorages.back().ref->IsStorage(aElems[i]))
190 : {
191 0 : SotStorageRef tmpParent(mxChildrenStorages.back().ref);
192 0 : storageRefWrapper.ref = tmpParent->OpenSotStorage(aElems[i++], STREAM_STD_READ);
193 0 : mxChildrenStorages.push_back(storageRefWrapper);
194 : }
195 : else
196 : // should not happen
197 0 : return 0;
198 : }
199 :
200 : // For the while don't return stream in this situation.
201 : // Later, given how libcdr's zip stream implementation behaves,
202 : // return the first stream in the storage if there is one.
203 0 : if (i >= aElems.size())
204 0 : return 0;
205 :
206 0 : SotStorageStreamRefWrapper storageStreamRefWrapper;
207 0 : storageStreamRefWrapper.ref = mxChildrenStorages.back().ref->OpenSotStream( aElems[i], STREAM_STD_READ );
208 0 : mxChildrenStreams.push_back( storageStreamRefWrapper );
209 :
210 0 : mxSeekable->seek(tmpPosition);
211 :
212 0 : if ( !mxChildrenStreams.back().ref.Is() || mxChildrenStreams.back().ref->GetError() )
213 : {
214 0 : mxSeekable->seek(tmpPosition);
215 0 : return 0;
216 : }
217 :
218 0 : Reference < XInputStream > xContents(new utl::OSeekableInputStreamWrapper( mxChildrenStreams.back().ref ));
219 0 : mxSeekable->seek(tmpPosition);
220 0 : if (xContents.is())
221 0 : return new WPXSvInputStream( xContents );
222 : else
223 0 : return 0;
224 : }
225 :
226 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|