Branch data 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 "OOXMLFastTokenHandler.hxx"
22 : : #include "ooxmlLoggers.hxx"
23 : : #include <iostream>
24 : :
25 : : #include <com/sun/star/embed/XHierarchicalStorageAccess.hpp>
26 : : #include <com/sun/star/uri/UriReferenceFactory.hpp>
27 : :
28 : : //#define DEBUG_STREAM
29 : :
30 : : namespace writerfilter {
31 : : namespace ooxml
32 : : {
33 : :
34 : : using namespace ::std;
35 : :
36 : 191 : OOXMLStreamImpl::OOXMLStreamImpl
37 : : (uno::Reference<uno::XComponentContext> xContext,
38 : : uno::Reference<io::XInputStream> xStorageStream, StreamType_t nType)
39 : 191 : : mxContext(xContext), mxStorageStream(xStorageStream), mnStreamType(nType)
40 : : {
41 : : mxStorage.set
42 : : (comphelper::OStorageHelper::GetStorageOfFormatFromInputStream
43 [ + - ][ + - ]: 191 : (OFOPXML_STORAGE_FORMAT_STRING, mxStorageStream));
[ + - ]
44 [ + - ]: 191 : mxRelationshipAccess.set(mxStorage, uno::UNO_QUERY_THROW);
45 : :
46 [ + - ]: 191 : init();
47 : 191 : }
48 : :
49 : 1332 : OOXMLStreamImpl::OOXMLStreamImpl
50 : : (OOXMLStreamImpl & rOOXMLStream, StreamType_t nStreamType)
51 : : : mxContext(rOOXMLStream.mxContext),
52 : : mxStorageStream(rOOXMLStream.mxStorageStream),
53 : : mxStorage(rOOXMLStream.mxStorage),
54 : : mnStreamType(nStreamType),
55 : 1332 : msPath(rOOXMLStream.msPath)
56 : : {
57 [ + - ]: 1332 : mxRelationshipAccess.set(rOOXMLStream.mxDocumentStream, uno::UNO_QUERY_THROW);
58 : :
59 [ + - ]: 1332 : init();
60 : 1332 : }
61 : :
62 : 30 : OOXMLStreamImpl::OOXMLStreamImpl
63 : : (OOXMLStreamImpl & rOOXMLStream, const OUString & rId)
64 : : : mxContext(rOOXMLStream.mxContext),
65 : : mxStorageStream(rOOXMLStream.mxStorageStream),
66 : : mxStorage(rOOXMLStream.mxStorage),
67 : : mnStreamType(UNKNOWN),
68 : : msId(rId),
69 : 30 : msPath(rOOXMLStream.msPath)
70 : : {
71 [ + - ]: 30 : mxRelationshipAccess.set(rOOXMLStream.mxDocumentStream, uno::UNO_QUERY_THROW);
72 : :
73 [ + - ]: 30 : init();
74 : 30 : }
75 : :
76 : 1553 : OOXMLStreamImpl::~OOXMLStreamImpl()
77 : : {
78 : : #ifdef DEBUG_STREAM
79 : : debug_logger->endElement("stream");
80 : : #endif
81 [ - + ]: 3106 : }
82 : :
83 : 57 : const OUString & OOXMLStreamImpl::getTarget() const
84 : : {
85 : 57 : return msTarget;
86 : : }
87 : :
88 : 1553 : bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess>
89 : : xRelationshipAccess,
90 : : StreamType_t nStreamType,
91 : : const OUString & rId,
92 : : OUString & rDocumentTarget)
93 : : {
94 : 1553 : bool bFound = false;
95 [ + + ][ + - ]: 1553 : static uno::Reference< com::sun::star::uri::XUriReferenceFactory > xFac = ::com::sun::star::uri::UriReferenceFactory::create( mxContext );
[ + - ][ # # ]
96 : : // use '/' to representent the root of the zip package ( and provide a 'file' scheme to
97 : : // keep the XUriReference implementation happy )
98 : : // add mspath to represent the 'source' of this stream
99 [ + - ][ + - ]: 1553 : uno::Reference< com::sun::star::uri::XUriReference > xBase = xFac->parse( OUString( "file:///" ) + msPath );
100 : :
101 [ + - ][ + + ]: 1553 : static OUString sType("Type");
102 [ + + ][ + - ]: 1553 : static OUString sId("Id");
103 [ + + ][ + - ]: 1553 : static OUString sDocumentType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument");
104 [ + + ][ + - ]: 1553 : static OUString sStylesType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles");
105 [ + + ][ + - ]: 1553 : static OUString sNumberingType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering");
106 [ + + ][ + - ]: 1553 : static OUString sFonttableType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable");
107 [ + + ][ + - ]: 1553 : static OUString sFootnotesType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes");
108 [ + + ][ + - ]: 1553 : static OUString sEndnotesType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes");
109 [ + + ][ + - ]: 1553 : static OUString sCommentsType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments");
110 [ + + ][ + - ]: 1553 : static OUString sThemeType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme");
111 [ + + ][ + - ]: 1553 : static OUString sSettingsType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings");
112 [ + + ][ + - ]: 1553 : static OUString sTarget("Target");
113 [ + + ][ + - ]: 1553 : static OUString sTargetMode("TargetMode");
114 [ + + ][ + - ]: 1553 : static OUString sExternal("External");
115 [ + + ][ + - ]: 1553 : static OUString sVBAProjectType("http://schemas.microsoft.com/office/2006/relationships/vbaProject");
116 : :
117 : 1553 : OUString sStreamType;
118 : :
119 [ + + + + : 1553 : switch (nStreamType)
+ - - + +
+ + ]
120 : : {
121 : : case VBAPROJECT:
122 : 191 : sStreamType = sVBAProjectType;
123 : 191 : break;
124 : : case DOCUMENT:
125 : 191 : sStreamType = sDocumentType;
126 : 191 : break;
127 : : case STYLES:
128 : 227 : sStreamType = sStylesType;
129 : 227 : break;
130 : : case NUMBERING:
131 : 227 : sStreamType = sNumberingType;
132 : 227 : break;
133 : : case FONTTABLE:
134 : 227 : sStreamType = sFonttableType;
135 : 227 : break;
136 : : case FOOTNOTES:
137 : 0 : sStreamType = sFootnotesType;
138 : 0 : break;
139 : : case ENDNOTES:
140 : 0 : sStreamType = sEndnotesType;
141 : 0 : break;
142 : : case COMMENTS:
143 : 6 : sStreamType = sCommentsType;
144 : 6 : break;
145 : : case THEME:
146 : 227 : sStreamType = sThemeType;
147 : 227 : break;
148 : : case SETTINGS:
149 : 227 : sStreamType = sSettingsType;
150 : 227 : break;
151 : : default:
152 : 30 : break;
153 : : }
154 : :
155 [ + - ]: 1553 : if (xRelationshipAccess.is())
156 : : {
157 : : uno::Sequence< uno::Sequence< beans::StringPair > >aSeqs =
158 [ + - ][ + - ]: 1553 : xRelationshipAccess->getAllRelationships();
159 : :
160 [ + + ]: 6194 : for (sal_Int32 j = 0; j < aSeqs.getLength(); j++)
161 : : {
162 [ + - ][ + - ]: 4641 : uno::Sequence< beans::StringPair > aSeq = aSeqs[j];
163 : :
164 : 4641 : bool bExternalTarget = false;
165 : 4641 : OUString sMyTarget;
166 [ + + ]: 18564 : for (sal_Int32 i = 0; i < aSeq.getLength(); i++)
167 : : {
168 [ + - ]: 13923 : beans::StringPair aPair = aSeq[i];
169 : :
170 [ + + ]: 18564 : if (aPair.First.compareTo(sType) == 0 &&
[ + + + + ]
171 : 4641 : aPair.Second.compareTo(sStreamType) == 0)
172 : 829 : bFound = true;
173 [ + + + + ]: 17735 : else if (aPair.First.compareTo(sId) == 0 &&
[ + + ]
174 : 4641 : aPair.Second.compareTo(rId) == 0)
175 : 30 : bFound = true;
176 [ + + ]: 13064 : else if (aPair.First.compareTo(sTarget) == 0)
177 : 4641 : sMyTarget = aPair.Second;
178 [ - + # # ]: 8423 : else if (aPair.First.compareTo(sTargetMode) == 0 &&
[ - + ]
179 : 0 : aPair.Second.compareTo(sExternal) == 0)
180 : 0 : bExternalTarget = true;
181 : :
182 : 13923 : }
183 : :
184 [ + + ]: 4641 : if (bFound)
185 : : {
186 [ - + ]: 859 : if (bExternalTarget)
187 : 0 : rDocumentTarget = sMyTarget;
188 : : else
189 : : {
190 : : // 'Target' is a relative Uri, so a 'Target=/path'
191 : : // with a base Uri of file://base/foo will resolve to
192 : : // file://base/word. We need something more than some
193 : : // simple string concatination here to handle that.
194 [ + - ][ + - ]: 859 : uno::Reference< com::sun::star::uri::XUriReference > xPart = xFac->parse( sMyTarget );
195 [ + - ][ + - ]: 859 : uno::Reference< com::sun::star::uri::XUriReference > xAbs = xFac->makeAbsolute( xBase, xPart, sal_True, com::sun::star::uri::RelativeUriExcessParentSegments_RETAIN );
196 [ + - ][ + - ]: 859 : rDocumentTarget = xAbs->getPath();
197 : : // path will start with the fragment separator. need to
198 : : // remove that
199 : 4641 : rDocumentTarget = rDocumentTarget.copy( 1 );
200 : : }
201 : :
202 : : break;
203 : : }
204 [ + + ][ + - ]: 6194 : }
[ + + ][ + - ]
205 : : }
206 : :
207 : 1553 : return bFound;
208 : : }
209 : :
210 : 0 : OUString OOXMLStreamImpl::getTargetForId(const OUString & rId)
211 : : {
212 : 0 : OUString sTarget;
213 : :
214 : : uno::Reference<embed::XRelationshipAccess> xRelationshipAccess
215 [ # # ]: 0 : (mxDocumentStream, uno::UNO_QUERY_THROW);
216 : :
217 [ # # ][ # # ]: 0 : if (lcl_getTarget(xRelationshipAccess, UNKNOWN, rId, sTarget))
218 : 0 : return sTarget;
219 : :
220 : 0 : return OUString();
221 : : }
222 : :
223 : 1553 : void OOXMLStreamImpl::init()
224 : : {
225 : : bool bFound = lcl_getTarget(mxRelationshipAccess,
226 [ + - ]: 1553 : mnStreamType, msId, msTarget);
227 : : #ifdef DEBUG_STREAM
228 : : debug_logger->startElement("stream");
229 : : debug_logger->attribute("target", msTarget);
230 : : #endif
231 : :
232 [ + + ]: 1553 : if (bFound)
233 : : {
234 : 859 : sal_Int32 nLastIndex = msTarget.lastIndexOf('/');
235 [ + - ]: 859 : if (nLastIndex >= 0)
236 : 859 : msPath = msTarget.copy(0, nLastIndex + 1);
237 : :
238 : : uno::Reference<embed::XHierarchicalStorageAccess>
239 [ + - ]: 859 : xHierarchicalStorageAccess(mxStorage, uno::UNO_QUERY);
240 : :
241 [ + - ]: 859 : if (xHierarchicalStorageAccess.is())
242 : : {
243 [ + - ]: 859 : uno::Any aAny(xHierarchicalStorageAccess->
244 : : openStreamElementByHierarchicalName
245 [ + - ][ + - ]: 859 : (msTarget, embed::ElementModes::SEEKABLEREAD));
246 [ + - ]: 859 : aAny >>= mxDocumentStream;
247 : 859 : }
248 : : }
249 : 1553 : }
250 : :
251 : 1553 : uno::Reference<io::XInputStream> OOXMLStreamImpl::getDocumentStream()
252 : : {
253 : 1553 : uno::Reference<io::XInputStream> xResult;
254 : :
255 [ + + ]: 1553 : if (mxDocumentStream.is())
256 [ + - ][ + - ]: 859 : xResult = mxDocumentStream->getInputStream();
[ + - ]
257 : :
258 : 1553 : return xResult;
259 : : }
260 : :
261 : 57 : uno::Reference<io::XInputStream> OOXMLStreamImpl::getStorageStream()
262 : : {
263 : 57 : return mxStorageStream;
264 : : }
265 : :
266 : 0 : uno::Reference<xml::sax::XParser> OOXMLStreamImpl::getParser()
267 : : {
268 : : uno::Reference<lang::XMultiComponentFactory> xFactory =
269 : : uno::Reference<lang::XMultiComponentFactory>
270 [ # # ][ # # ]: 0 : (mxContext->getServiceManager());
271 : :
272 : : uno::Reference<xml::sax::XParser> xParser
273 [ # # ]: 0 : (xFactory->createInstanceWithContext
274 : : ( OUString("com.sun.star.xml.sax.Parser"),
275 : 0 : mxContext ),
276 [ # # ][ # # ]: 0 : uno::UNO_QUERY );
277 : :
278 : 0 : return xParser;
279 : : }
280 : :
281 : 1362 : uno::Reference<uno::XComponentContext> OOXMLStreamImpl::getContext()
282 : : {
283 : 1362 : return mxContext;
284 : : }
285 : :
286 : : uno::Reference <xml::sax::XFastTokenHandler>
287 : 1362 : OOXMLStreamImpl::getFastTokenHandler
288 : : (uno::Reference<uno::XComponentContext> xContext)
289 : : {
290 [ + + ]: 1362 : if (! mxFastTokenHandler.is())
291 [ + - ][ + - ]: 227 : mxFastTokenHandler.set(new OOXMLFastTokenHandler(xContext));
292 : :
293 : 1362 : return mxFastTokenHandler;
294 : : }
295 : :
296 : : OOXMLStream::Pointer_t
297 : 191 : OOXMLDocumentFactory::createStream
298 : : (uno::Reference<uno::XComponentContext> xContext,
299 : : uno::Reference<io::XInputStream> rStream,
300 : : OOXMLStream::StreamType_t nStreamType)
301 : : {
302 : : OOXMLStreamImpl * pStream = new OOXMLStreamImpl(xContext, rStream,
303 [ + - ][ + - ]: 191 : nStreamType);
304 : 191 : return OOXMLStream::Pointer_t(pStream);
305 : : }
306 : :
307 : : OOXMLStream::Pointer_t
308 : 1332 : OOXMLDocumentFactory::createStream
309 : : (OOXMLStream::Pointer_t pStream, OOXMLStream::StreamType_t nStreamType)
310 : : {
311 : : return OOXMLStream::Pointer_t
312 : 1332 : (new OOXMLStreamImpl(*dynamic_cast<OOXMLStreamImpl *>(pStream.get()),
313 [ + - ][ - + ]: 1332 : nStreamType));
314 : : }
315 : :
316 : : OOXMLStream::Pointer_t
317 : 30 : OOXMLDocumentFactory::createStream
318 : : (OOXMLStream::Pointer_t pStream, const OUString & rId)
319 : : {
320 : : return OOXMLStream::Pointer_t
321 : 30 : (new OOXMLStreamImpl(*dynamic_cast<OOXMLStreamImpl *>(pStream.get()),
322 [ + - ][ - + ]: 30 : rId));
323 : : }
324 : :
325 [ + - ][ + - ]: 60 : }}
326 : :
327 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|