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