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 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "OOXMLStreamImpl.hxx"
21 : #include "oox/core/fasttokenhandler.hxx"
22 : #include <iostream>
23 :
24 : #include <com/sun/star/embed/XHierarchicalStorageAccess.hpp>
25 : #include <com/sun/star/uri/UriReferenceFactory.hpp>
26 : #include <com/sun/star/xml/sax/Parser.hpp>
27 :
28 : //#define DEBUG_STREAM
29 :
30 : namespace writerfilter {
31 : namespace ooxml
32 : {
33 :
34 : using namespace com::sun::star;
35 :
36 5596 : OOXMLStreamImpl::OOXMLStreamImpl
37 : (uno::Reference<uno::XComponentContext> xContext,
38 : uno::Reference<io::XInputStream> xStorageStream,
39 : StreamType_t nType, bool bRepairStorage)
40 5596 : : mxContext(xContext), mxStorageStream(xStorageStream), mnStreamType(nType)
41 : {
42 : mxStorage.set
43 : (comphelper::OStorageHelper::GetStorageOfFormatFromInputStream
44 5596 : (OFOPXML_STORAGE_FORMAT_STRING, mxStorageStream, xContext, bRepairStorage));
45 5596 : mxRelationshipAccess.set(mxStorage, uno::UNO_QUERY_THROW);
46 :
47 5596 : init();
48 5596 : }
49 :
50 56212 : OOXMLStreamImpl::OOXMLStreamImpl
51 : (OOXMLStreamImpl & rOOXMLStream, StreamType_t nStreamType)
52 : : mxContext(rOOXMLStream.mxContext),
53 : mxStorageStream(rOOXMLStream.mxStorageStream),
54 : mxStorage(rOOXMLStream.mxStorage),
55 : mnStreamType(nStreamType),
56 56228 : msPath(rOOXMLStream.msPath)
57 : {
58 56212 : mxRelationshipAccess.set(rOOXMLStream.mxDocumentStream, uno::UNO_QUERY_THROW);
59 :
60 56212 : init();
61 56196 : }
62 :
63 2666 : OOXMLStreamImpl::OOXMLStreamImpl
64 : (OOXMLStreamImpl & rOOXMLStream, const OUString & rId)
65 : : mxContext(rOOXMLStream.mxContext),
66 : mxStorageStream(rOOXMLStream.mxStorageStream),
67 : mxStorage(rOOXMLStream.mxStorage),
68 : mnStreamType(UNKNOWN),
69 : msId(rId),
70 2666 : msPath(rOOXMLStream.msPath)
71 : {
72 2666 : mxRelationshipAccess.set(rOOXMLStream.mxDocumentStream, uno::UNO_QUERY_THROW);
73 :
74 2666 : init();
75 2666 : }
76 :
77 128916 : OOXMLStreamImpl::~OOXMLStreamImpl()
78 : {
79 128916 : }
80 :
81 3212 : const OUString & OOXMLStreamImpl::getTarget() const
82 : {
83 3212 : return msTarget;
84 : }
85 :
86 65128 : bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess>
87 : xRelationshipAccess,
88 : StreamType_t nStreamType,
89 : const OUString & rId,
90 : OUString & rDocumentTarget)
91 : {
92 65128 : static OUString sId("Id");
93 65128 : static OUString sTarget("Target");
94 65128 : static OUString sTargetMode("TargetMode");
95 65128 : static OUString sExternal("External");
96 65128 : if (maIdCache.empty())
97 : {
98 : // Cache is empty? Then let's build it!
99 64614 : uno::Sequence< uno::Sequence<beans::StringPair> >aSeqs = xRelationshipAccess->getAllRelationships();
100 4970088 : for (sal_Int32 i = 0; i < aSeqs.getLength(); ++i)
101 : {
102 4905474 : const uno::Sequence<beans::StringPair>& rSeq = aSeqs[i];
103 4905474 : OUString aId;
104 9810948 : OUString aTarget;
105 4905474 : bool bExternal = false;
106 20462568 : for (sal_Int32 j = 0; j < rSeq.getLength(); ++j)
107 : {
108 15557094 : const beans::StringPair& rPair = rSeq[j];
109 15557094 : if (rPair.First == sId)
110 4905474 : aId = rPair.Second;
111 10651620 : else if (rPair.First == sTarget)
112 4905458 : aTarget = rPair.Second;
113 5746162 : else if (rPair.First == sTargetMode && rPair.Second == sExternal)
114 840688 : bExternal = true;
115 : }
116 : // Only cache external targets, internal ones are more complex (see below)
117 4905474 : if (bExternal)
118 840688 : maIdCache[aId] = aTarget;
119 4970088 : }
120 : }
121 :
122 65128 : if (maIdCache.find(rId) != maIdCache.end())
123 : {
124 654 : rDocumentTarget = maIdCache[rId];
125 654 : return true;
126 : }
127 :
128 64474 : bool bFound = false;
129 64474 : static uno::Reference< com::sun::star::uri::XUriReferenceFactory > xFac = ::com::sun::star::uri::UriReferenceFactory::create( mxContext );
130 : // use '/' to representent the root of the zip package ( and provide a 'file' scheme to
131 : // keep the XUriReference implementation happy )
132 : // add mspath to represent the 'source' of this stream
133 64474 : uno::Reference< com::sun::star::uri::XUriReference > xBase = xFac->parse( OUString( "file:///" ) + msPath );
134 :
135 64474 : static OUString sType("Type");
136 64474 : static OUString sDocumentType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument");
137 64474 : static OUString sStylesType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles");
138 64474 : static OUString sNumberingType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering");
139 64474 : static OUString sFonttableType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable");
140 64474 : static OUString sFootnotesType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes");
141 64474 : static OUString sEndnotesType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes");
142 64474 : static OUString sCommentsType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments");
143 64474 : static OUString sThemeType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme");
144 64474 : static OUString sCustomType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml");
145 64474 : static OUString sCustomPropsType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlProps");
146 64474 : static OUString sActiveXType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/control");
147 64474 : static OUString sActiveXBinType("http://schemas.microsoft.com/office/2006/relationships/activeXControlBinary");
148 64474 : static OUString sGlossaryType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/glossaryDocument");
149 64474 : static OUString sWebSettings("http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings");
150 64474 : static OUString sSettingsType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings");
151 64474 : static OUString sChartType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart");
152 64474 : static OUString sEmbeddingsType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/package");
153 64474 : static OUString sFooterType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer");
154 64474 : static OUString sHeaderType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/header");
155 64474 : static OUString sOleObjectType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject");
156 64474 : static OUString sSignatureType("http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin");
157 : // OOXML strict
158 64474 : static OUString sDocumentTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/officeDocument");
159 64474 : static OUString sStylesTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/styles");
160 64474 : static OUString sNumberingTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/numbering");
161 64474 : static OUString sFonttableTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/fontTable");
162 64474 : static OUString sFootnotesTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/footnotes");
163 64474 : static OUString sEndnotesTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/endnotes");
164 64474 : static OUString sCommentsTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/comments");
165 64474 : static OUString sThemeTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/theme");
166 64474 : static OUString sCustomTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/customXml");
167 64474 : static OUString sCustomPropsTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/customXmlProps");
168 64474 : static OUString sActiveXTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/control");
169 64474 : static OUString sGlossaryTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/glossaryDocument");
170 64474 : static OUString sWebSettingsStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/webSettings");
171 64474 : static OUString sSettingsTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/settings");
172 64474 : static OUString sChartTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/chart");
173 64474 : static OUString sEmbeddingsTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/package");
174 64474 : static OUString sFootersTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/footer");
175 64474 : static OUString sHeaderTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/header");
176 64474 : static OUString sOleObjectTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/oleObject");
177 64474 : static OUString sVBAProjectType("http://schemas.microsoft.com/office/2006/relationships/vbaProject");
178 :
179 128948 : OUString sStreamType;
180 128948 : OUString sStreamTypeStrict;
181 :
182 64474 : switch (nStreamType)
183 : {
184 : case VBAPROJECT:
185 2798 : sStreamType = sVBAProjectType;
186 2798 : sStreamTypeStrict = sVBAProjectType;
187 2798 : break;
188 : case DOCUMENT:
189 2798 : sStreamType = sDocumentType;
190 2798 : sStreamTypeStrict = sDocumentTypeStrict;
191 2798 : break;
192 : case STYLES:
193 5622 : sStreamType = sStylesType;
194 5622 : sStreamTypeStrict = sStylesTypeStrict;
195 5622 : break;
196 : case NUMBERING:
197 5482 : sStreamType = sNumberingType;
198 5482 : sStreamTypeStrict = sNumberingTypeStrict;
199 5482 : break;
200 : case FONTTABLE:
201 5622 : sStreamType = sFonttableType;
202 5622 : sStreamTypeStrict = sFonttableTypeStrict;
203 5622 : break;
204 : case FOOTNOTES:
205 70 : sStreamType = sFootnotesType;
206 70 : sStreamTypeStrict = sFootnotesTypeStrict;
207 70 : break;
208 : case ENDNOTES:
209 18 : sStreamType = sEndnotesType;
210 18 : sStreamTypeStrict = sEndnotesTypeStrict;
211 18 : break;
212 : case COMMENTS:
213 34 : sStreamType = sCommentsType;
214 34 : sStreamTypeStrict = sCommentsTypeStrict;
215 34 : break;
216 : case THEME:
217 10964 : sStreamType = sThemeType;
218 10964 : sStreamTypeStrict = sThemeTypeStrict;
219 10964 : break;
220 : case CUSTOMXML:
221 1948 : sStreamType = sCustomType;
222 1948 : sStreamTypeStrict = sCustomTypeStrict;
223 1948 : break;
224 : case CUSTOMXMLPROPS:
225 974 : sStreamType = sCustomPropsType;
226 974 : sStreamTypeStrict = sCustomPropsTypeStrict;
227 974 : break;
228 : case ACTIVEX:
229 5556 : sStreamType = sActiveXType;
230 5556 : sStreamTypeStrict = sActiveXTypeStrict;
231 5556 : break;
232 : case ACTIVEXBIN:
233 2778 : sStreamType = sActiveXBinType;
234 2778 : sStreamTypeStrict = sActiveXBinType;
235 2778 : break;
236 : case SETTINGS:
237 5622 : sStreamType = sSettingsType;
238 5622 : sStreamTypeStrict = sSettingsTypeStrict;
239 5622 : break;
240 : case GLOSSARY:
241 5622 : sStreamType = sGlossaryType;
242 5622 : sStreamTypeStrict = sGlossaryTypeStrict;
243 5622 : break;
244 : case WEBSETTINGS:
245 140 : sStreamType = sWebSettings;
246 140 : sStreamTypeStrict = sWebSettingsStrict;
247 140 : break;
248 : case CHARTS:
249 184 : sStreamType = sChartType;
250 184 : sStreamTypeStrict = sChartTypeStrict;
251 184 : break;
252 : case EMBEDDINGS:
253 184 : sStreamType = sEmbeddingsType;
254 184 : sStreamTypeStrict = sEmbeddingsTypeStrict;
255 184 : break;
256 : case FOOTER:
257 1334 : sStreamType = sFooterType;
258 1334 : sStreamTypeStrict = sFootersTypeStrict;
259 1334 : break;
260 : case HEADER:
261 1260 : sStreamType = sHeaderType;
262 1260 : sStreamTypeStrict = sHeaderTypeStrict;
263 1260 : break;
264 : case SIGNATURE:
265 2798 : sStreamType = sSignatureType;
266 2798 : break;
267 : default:
268 2666 : break;
269 : }
270 :
271 64474 : if (xRelationshipAccess.is())
272 : {
273 : uno::Sequence< uno::Sequence< beans::StringPair > >aSeqs =
274 64474 : xRelationshipAccess->getAllRelationships();
275 :
276 2562594 : for (sal_Int32 j = 0; j < aSeqs.getLength(); j++)
277 : {
278 2532792 : const uno::Sequence< beans::StringPair > &rSeq = aSeqs[j];
279 :
280 2532792 : bool bExternalTarget = false;
281 2532792 : OUString sMyTarget;
282 10556012 : for (sal_Int32 i = 0; i < rSeq.getLength(); i++)
283 : {
284 8023220 : const beans::StringPair &rPair = rSeq[i];
285 :
286 11820164 : if (rPair.First == sType &&
287 3801472 : ( rPair.Second == sStreamType ||
288 1268680 : rPair.Second == sStreamTypeStrict ))
289 1264152 : bFound = true;
290 8027726 : else if(rPair.First == sType &&
291 2537014 : ((rPair.Second == sOleObjectType ||
292 1268642 : rPair.Second == sOleObjectTypeStrict) &&
293 : nStreamType == EMBEDDINGS))
294 : {
295 18 : bFound = true;
296 : }
297 9291842 : else if (rPair.First == sId &&
298 2532792 : rPair.Second == rId)
299 2666 : bFound = true;
300 6756384 : else if (rPair.First == sTarget)
301 : {
302 : // checking item[n].xml or activex[n].xml is not visited already.
303 2532778 : if(customTarget != rPair.Second && (sStreamType == sCustomType || sStreamType == sActiveXType || sStreamType == sChartType || sStreamType == sFooterType || sStreamType == sHeaderType))
304 : {
305 2325454 : bFound = false;
306 : }
307 : else
308 : {
309 207324 : sMyTarget = rPair.Second;
310 : }
311 : }
312 4648464 : else if (rPair.First == sTargetMode &&
313 424858 : rPair.Second == sExternal)
314 424858 : bExternalTarget = true;
315 :
316 : }
317 :
318 2532792 : if (bFound)
319 : {
320 34672 : if (bExternalTarget)
321 16 : rDocumentTarget = sMyTarget;
322 : else
323 : {
324 : // 'Target' is a relative Uri, so a 'Target=/path'
325 : // with a base Uri of file://base/foo will resolve to
326 : // file://base/word. We need something more than some
327 : // simple string concatination here to handle that.
328 34656 : uno::Reference< com::sun::star::uri::XUriReference > xPart = xFac->parse( sMyTarget );
329 69312 : uno::Reference< com::sun::star::uri::XUriReference > xAbs = xFac->makeAbsolute( xBase, xPart, sal_True, com::sun::star::uri::RelativeUriExcessParentSegments_RETAIN );
330 34656 : rDocumentTarget = xAbs->getPath();
331 : // path will start with the fragment separator. need to
332 : // remove that
333 34656 : rDocumentTarget = rDocumentTarget.copy( 1 );
334 34656 : if(sStreamType == sEmbeddingsType)
335 34820 : embeddingsTarget = rDocumentTarget;
336 : }
337 :
338 34672 : break;
339 : }
340 2562594 : }
341 : }
342 :
343 128948 : return bFound;
344 : }
345 :
346 654 : OUString OOXMLStreamImpl::getTargetForId(const OUString & rId)
347 : {
348 654 : OUString sTarget;
349 :
350 : uno::Reference<embed::XRelationshipAccess> xRelationshipAccess
351 1308 : (mxDocumentStream, uno::UNO_QUERY_THROW);
352 :
353 654 : if (lcl_getTarget(xRelationshipAccess, UNKNOWN, rId, sTarget))
354 654 : return sTarget;
355 :
356 654 : return OUString();
357 : }
358 :
359 64474 : void OOXMLStreamImpl::init()
360 : {
361 : bool bFound = lcl_getTarget(mxRelationshipAccess,
362 64474 : mnStreamType, msId, msTarget);
363 :
364 64474 : if (bFound)
365 : {
366 34672 : sal_Int32 nLastIndex = msTarget.lastIndexOf('/');
367 34672 : if (nLastIndex >= 0)
368 34664 : msPath = msTarget.copy(0, nLastIndex + 1);
369 :
370 : uno::Reference<embed::XHierarchicalStorageAccess>
371 34672 : xHierarchicalStorageAccess(mxStorage, uno::UNO_QUERY);
372 :
373 34672 : if (xHierarchicalStorageAccess.is())
374 : {
375 34672 : uno::Any aAny(xHierarchicalStorageAccess->
376 : openStreamElementByHierarchicalName
377 34672 : (msTarget, embed::ElementModes::SEEKABLEREAD));
378 34656 : aAny >>= mxDocumentStream;
379 : // Non-cached ID lookup works by accessing mxDocumentStream as an embed::XRelationshipAccess.
380 : // So when it changes, we should empty the cache.
381 34656 : maIdCache.clear();
382 34672 : }
383 : }
384 64458 : }
385 :
386 61724 : uno::Reference<io::XInputStream> OOXMLStreamImpl::getDocumentStream()
387 : {
388 61724 : uno::Reference<io::XInputStream> xResult;
389 :
390 61724 : if (mxDocumentStream.is())
391 31922 : xResult = mxDocumentStream->getInputStream();
392 :
393 61724 : return xResult;
394 : }
395 :
396 3212 : uno::Reference<io::XInputStream> OOXMLStreamImpl::getStorageStream()
397 : {
398 3212 : return mxStorageStream;
399 : }
400 :
401 0 : uno::Reference<xml::sax::XParser> OOXMLStreamImpl::getParser()
402 : {
403 0 : uno::Reference<xml::sax::XParser> xParser = xml::sax::Parser::create(mxContext);
404 0 : return xParser;
405 : }
406 :
407 44658 : uno::Reference<uno::XComponentContext> OOXMLStreamImpl::getContext()
408 : {
409 44658 : return mxContext;
410 : }
411 :
412 36644 : uno::Reference <xml::sax::XFastTokenHandler> OOXMLStreamImpl::getFastTokenHandler()
413 : {
414 36644 : if (! mxFastTokenHandler.is())
415 36644 : mxFastTokenHandler.set(new oox::core::FastTokenHandler());
416 :
417 36644 : return mxFastTokenHandler;
418 : }
419 :
420 : OOXMLStream::Pointer_t
421 5596 : OOXMLDocumentFactory::createStream
422 : (uno::Reference<uno::XComponentContext> xContext,
423 : uno::Reference<io::XInputStream> rStream,
424 : bool bRepairStorage,
425 : OOXMLStream::StreamType_t nStreamType)
426 : {
427 : OOXMLStreamImpl * pStream = new OOXMLStreamImpl(xContext, rStream,
428 5596 : nStreamType, bRepairStorage);
429 5596 : return OOXMLStream::Pointer_t(pStream);
430 : }
431 :
432 : OOXMLStream::Pointer_t
433 56212 : OOXMLDocumentFactory::createStream
434 : (OOXMLStream::Pointer_t pStream, OOXMLStream::StreamType_t nStreamType)
435 : {
436 56212 : OOXMLStream::Pointer_t pRet;
437 56212 : if (OOXMLStreamImpl* pImpl = dynamic_cast<OOXMLStreamImpl *>(pStream.get()))
438 56228 : pRet.reset(new OOXMLStreamImpl(*pImpl, nStreamType));
439 56196 : return pRet;
440 : }
441 :
442 : OOXMLStream::Pointer_t
443 2666 : OOXMLDocumentFactory::createStream
444 : (OOXMLStream::Pointer_t pStream, const OUString & rId)
445 : {
446 2666 : OOXMLStream::Pointer_t pRet;
447 2666 : if (OOXMLStreamImpl* pImpl = dynamic_cast<OOXMLStreamImpl *>(pStream.get()))
448 2666 : pRet.reset(new OOXMLStreamImpl(*pImpl, rId));
449 2666 : return pRet;
450 : }
451 :
452 114 : }}
453 :
454 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|