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