1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "OOXMLStreamImpl.hxx"
25 #include "OOXMLFastTokenHandler.hxx"
26 #include "ooxmlLoggers.hxx"
27 #include <iostream>
28
29 #ifndef _COM_SUN_STAR_CONTAINER_XHIERARCHICALSTORAGEACCESS_HPP_
30 #include <com/sun/star/embed/XHierarchicalStorageAccess.hpp>
31 #endif
32
33 //#define DEBUG_STREAM
34
35 namespace writerfilter {
36 namespace ooxml
37 {
38
39 using namespace ::std;
40
OOXMLStreamImpl(uno::Reference<uno::XComponentContext> xContext,uno::Reference<io::XInputStream> xStorageStream,StreamType_t nType)41 OOXMLStreamImpl::OOXMLStreamImpl
42 (uno::Reference<uno::XComponentContext> xContext,
43 uno::Reference<io::XInputStream> xStorageStream, StreamType_t nType)
44 throw (uno::Exception)
45 : mxContext(xContext), mxStorageStream(xStorageStream), mnStreamType(nType)
46 {
47 mxStorage.set
48 (comphelper::OStorageHelper::GetStorageOfFormatFromInputStream
49 (OFOPXML_STORAGE_FORMAT_STRING, mxStorageStream));
50 mxRelationshipAccess.set(mxStorage, uno::UNO_QUERY_THROW);
51
52 init();
53 }
54
OOXMLStreamImpl(OOXMLStreamImpl & rOOXMLStream,StreamType_t nStreamType)55 OOXMLStreamImpl::OOXMLStreamImpl
56 (OOXMLStreamImpl & rOOXMLStream, StreamType_t nStreamType)
57 throw (uno::Exception)
58 : mxContext(rOOXMLStream.mxContext),
59 mxStorageStream(rOOXMLStream.mxStorageStream),
60 mxStorage(rOOXMLStream.mxStorage),
61 mnStreamType(nStreamType),
62 msPath(rOOXMLStream.msPath)
63 {
64 mxRelationshipAccess.set(rOOXMLStream.mxDocumentStream, uno::UNO_QUERY_THROW);
65
66 init();
67 }
68
OOXMLStreamImpl(OOXMLStreamImpl & rOOXMLStream,const rtl::OUString & rId)69 OOXMLStreamImpl::OOXMLStreamImpl
70 (OOXMLStreamImpl & rOOXMLStream, const rtl::OUString & rId)
71 throw (uno::Exception)
72 : mxContext(rOOXMLStream.mxContext),
73 mxStorageStream(rOOXMLStream.mxStorageStream),
74 mxStorage(rOOXMLStream.mxStorage),
75 mnStreamType(UNKNOWN),
76 msId(rId),
77 msPath(rOOXMLStream.msPath)
78 {
79 mxRelationshipAccess.set(rOOXMLStream.mxDocumentStream, uno::UNO_QUERY_THROW);
80
81 init();
82 }
83
~OOXMLStreamImpl()84 OOXMLStreamImpl::~OOXMLStreamImpl()
85 {
86 #ifdef DEBUG_STREAM
87 debug_logger->endElement("stream");
88 #endif
89 }
90
getTarget() const91 const ::rtl::OUString & OOXMLStreamImpl::getTarget() const
92 {
93 return msTarget;
94 }
95
lcl_normalizeTarget(const::rtl::OUString & s)96 ::rtl::OUString lcl_normalizeTarget(const ::rtl::OUString & s)
97 {
98 const int nStringsToCut = 2;
99 const ::rtl::OUString aStringToCut[] = {
100 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("./")),
101 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"))
102 };
103
104 bool bDone = false;
105 sal_Int32 nIndex = 0;
106 while (!bDone)
107 {
108 for (int n = 0; n <= nStringsToCut; n++)
109 {
110 if (n == nStringsToCut)
111 {
112 bDone = true;
113 }
114 else
115 {
116 sal_Int32 nNewIndex = s.indexOf(aStringToCut[n], nIndex);
117
118 if (nIndex == nNewIndex)
119 {
120 sal_Int32 nLength = aStringToCut[n].getLength();
121 nIndex += nLength;
122
123 break;
124 }
125 }
126 }
127 }
128
129 return s.copy(nIndex);
130 }
131
lcl_getTarget(uno::Reference<embed::XRelationshipAccess> xRelationshipAccess,StreamType_t nStreamType,const::rtl::OUString & rId,::rtl::OUString & rDocumentTarget)132 bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess>
133 xRelationshipAccess,
134 StreamType_t nStreamType,
135 const ::rtl::OUString & rId,
136 ::rtl::OUString & rDocumentTarget)
137 {
138 bool bFound = false;
139
140 static rtl::OUString sType(RTL_CONSTASCII_USTRINGPARAM("Type"));
141 static rtl::OUString sId(RTL_CONSTASCII_USTRINGPARAM("Id"));
142 static rtl::OUString sDocumentType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"));
143 static rtl::OUString sStylesType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"));
144 static rtl::OUString sNumberingType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering"));
145 static rtl::OUString sFonttableType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable"));
146 static rtl::OUString sFootnotesType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes"));
147 static rtl::OUString sEndnotesType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes"));
148 static rtl::OUString sCommentsType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"));
149 static rtl::OUString sThemeType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"));
150 static rtl::OUString sSettingsType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings"));
151 static rtl::OUString sTarget(RTL_CONSTASCII_USTRINGPARAM("Target"));
152 static rtl::OUString sTargetMode(RTL_CONSTASCII_USTRINGPARAM("TargetMode"));
153 static rtl::OUString sExternal(RTL_CONSTASCII_USTRINGPARAM("External"));
154
155 rtl::OUString sStreamType;
156
157 switch (nStreamType)
158 {
159 case DOCUMENT:
160 sStreamType = sDocumentType;
161 break;
162 case STYLES:
163 sStreamType = sStylesType;
164 break;
165 case NUMBERING:
166 sStreamType = sNumberingType;
167 break;
168 case FONTTABLE:
169 sStreamType = sFonttableType;
170 break;
171 case FOOTNOTES:
172 sStreamType = sFootnotesType;
173 break;
174 case ENDNOTES:
175 sStreamType = sEndnotesType;
176 break;
177 case COMMENTS:
178 sStreamType = sCommentsType;
179 break;
180 case THEME:
181 sStreamType = sThemeType;
182 break;
183 case SETTINGS:
184 sStreamType = sSettingsType;
185 break;
186 default:
187 break;
188 }
189
190 if (xRelationshipAccess.is())
191 {
192 uno::Sequence< uno::Sequence< beans::StringPair > >aSeqs =
193 xRelationshipAccess->getAllRelationships();
194
195 for (sal_Int32 j = 0; j < aSeqs.getLength(); j++)
196 {
197 uno::Sequence< beans::StringPair > aSeq = aSeqs[j];
198
199 bool bExternalTarget = false;
200 ::rtl::OUString sMyTarget;
201 for (sal_Int32 i = 0; i < aSeq.getLength(); i++)
202 {
203 beans::StringPair aPair = aSeq[i];
204
205 if (aPair.First.compareTo(sType) == 0 &&
206 aPair.Second.compareTo(sStreamType) == 0)
207 bFound = true;
208 else if (aPair.First.compareTo(sId) == 0 &&
209 aPair.Second.compareTo(rId) == 0)
210 bFound = true;
211 else if (aPair.First.compareTo(sTarget) == 0)
212 sMyTarget = aPair.Second;
213 else if (aPair.First.compareTo(sTargetMode) == 0 &&
214 aPair.Second.compareTo(sExternal) == 0)
215 bExternalTarget = true;
216
217 }
218
219 if (bFound)
220 {
221 if (bExternalTarget)
222 rDocumentTarget = sMyTarget;
223 else
224 {
225 rDocumentTarget = msPath;
226 rDocumentTarget += lcl_normalizeTarget(sMyTarget);
227 }
228
229 break;
230 }
231 }
232 }
233
234 return bFound;
235 }
236
getTargetForId(const::rtl::OUString & rId)237 ::rtl::OUString OOXMLStreamImpl::getTargetForId(const ::rtl::OUString & rId)
238 {
239 ::rtl::OUString sTarget;
240
241 uno::Reference<embed::XRelationshipAccess> xRelationshipAccess
242 (mxDocumentStream, uno::UNO_QUERY_THROW);
243
244 if (lcl_getTarget(xRelationshipAccess, UNKNOWN, rId, sTarget))
245 return sTarget;
246
247 return ::rtl::OUString();
248 }
249
init()250 void OOXMLStreamImpl::init() throw (uno::Exception)
251 {
252 bool bFound = lcl_getTarget(mxRelationshipAccess,
253 mnStreamType, msId, msTarget);
254 #ifdef DEBUG_STREAM
255 debug_logger->startElement("stream");
256 debug_logger->attribute("target", msTarget);
257 #endif
258
259 if (bFound)
260 {
261 sal_Int32 nLastIndex = msTarget.lastIndexOf('/');
262 if (nLastIndex >= 0)
263 msPath = msTarget.copy(0, nLastIndex + 1);
264
265 uno::Reference<embed::XHierarchicalStorageAccess>
266 xHierarchicalStorageAccess(mxStorage, uno::UNO_QUERY);
267
268 if (xHierarchicalStorageAccess.is())
269 {
270 uno::Any aAny(xHierarchicalStorageAccess->
271 openStreamElementByHierarchicalName
272 (msTarget, embed::ElementModes::SEEKABLEREAD));
273 aAny >>= mxDocumentStream;
274 }
275 }
276 }
277
getDocumentStream()278 uno::Reference<io::XInputStream> OOXMLStreamImpl::getDocumentStream()
279 {
280 uno::Reference<io::XInputStream> xResult;
281
282 if (mxDocumentStream.is())
283 xResult = mxDocumentStream->getInputStream();
284
285 return xResult;
286 }
287
getStorageStream()288 uno::Reference<io::XInputStream> OOXMLStreamImpl::getStorageStream()
289 {
290 return mxStorageStream;
291 }
292
getParser()293 uno::Reference<xml::sax::XParser> OOXMLStreamImpl::getParser()
294 {
295 uno::Reference<lang::XMultiComponentFactory> xFactory =
296 uno::Reference<lang::XMultiComponentFactory>
297 (mxContext->getServiceManager());
298
299 uno::Reference<xml::sax::XParser> xParser
300 (xFactory->createInstanceWithContext
301 ( rtl::OUString::createFromAscii( "com.sun.star.xml.sax.Parser" ),
302 mxContext ),
303 uno::UNO_QUERY );
304
305 return xParser;
306 }
307
getContext()308 uno::Reference<uno::XComponentContext> OOXMLStreamImpl::getContext()
309 {
310 return mxContext;
311 }
312
313 uno::Reference <xml::sax::XFastTokenHandler>
getFastTokenHandler(uno::Reference<uno::XComponentContext> xContext)314 OOXMLStreamImpl::getFastTokenHandler
315 (uno::Reference<uno::XComponentContext> xContext)
316 {
317 if (! mxFastTokenHandler.is())
318 mxFastTokenHandler.set(new OOXMLFastTokenHandler(xContext));
319
320 return mxFastTokenHandler;
321 }
322
323 OOXMLStream::Pointer_t
createStream(uno::Reference<uno::XComponentContext> xContext,uno::Reference<io::XInputStream> rStream,OOXMLStream::StreamType_t nStreamType)324 OOXMLDocumentFactory::createStream
325 (uno::Reference<uno::XComponentContext> xContext,
326 uno::Reference<io::XInputStream> rStream,
327 OOXMLStream::StreamType_t nStreamType)
328 {
329 OOXMLStreamImpl * pStream = new OOXMLStreamImpl(xContext, rStream,
330 nStreamType);
331 return OOXMLStream::Pointer_t(pStream);
332 }
333
334 OOXMLStream::Pointer_t
createStream(OOXMLStream::Pointer_t pStream,OOXMLStream::StreamType_t nStreamType)335 OOXMLDocumentFactory::createStream
336 (OOXMLStream::Pointer_t pStream, OOXMLStream::StreamType_t nStreamType)
337 {
338 return OOXMLStream::Pointer_t
339 (new OOXMLStreamImpl(*dynamic_cast<OOXMLStreamImpl *>(pStream.get()),
340 nStreamType));
341 }
342
343 OOXMLStream::Pointer_t
createStream(OOXMLStream::Pointer_t pStream,const rtl::OUString & rId)344 OOXMLDocumentFactory::createStream
345 (OOXMLStream::Pointer_t pStream, const rtl::OUString & rId)
346 {
347 return OOXMLStream::Pointer_t
348 (new OOXMLStreamImpl(*dynamic_cast<OOXMLStreamImpl *>(pStream.get()),
349 rId));
350 }
351
352 }}
353