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 : mxContext(xContext), mxStorageStream(xStorageStream), mnStreamType(nType)
45 {
46 mxStorage.set
47 (comphelper::OStorageHelper::GetStorageOfFormatFromInputStream
48 (OFOPXML_STORAGE_FORMAT_STRING, mxStorageStream));
49 mxRelationshipAccess.set(mxStorage, uno::UNO_QUERY_THROW);
50
51 init();
52 }
53
OOXMLStreamImpl(OOXMLStreamImpl & rOOXMLStream,StreamType_t nStreamType)54 OOXMLStreamImpl::OOXMLStreamImpl
55 (OOXMLStreamImpl & rOOXMLStream, StreamType_t nStreamType)
56 : mxContext(rOOXMLStream.mxContext),
57 mxStorageStream(rOOXMLStream.mxStorageStream),
58 mxStorage(rOOXMLStream.mxStorage),
59 mnStreamType(nStreamType),
60 msPath(rOOXMLStream.msPath)
61 {
62 mxRelationshipAccess.set(rOOXMLStream.mxDocumentStream, uno::UNO_QUERY_THROW);
63
64 init();
65 }
66
OOXMLStreamImpl(OOXMLStreamImpl & rOOXMLStream,const rtl::OUString & rId)67 OOXMLStreamImpl::OOXMLStreamImpl
68 (OOXMLStreamImpl & rOOXMLStream, const rtl::OUString & rId)
69 : mxContext(rOOXMLStream.mxContext),
70 mxStorageStream(rOOXMLStream.mxStorageStream),
71 mxStorage(rOOXMLStream.mxStorage),
72 mnStreamType(UNKNOWN),
73 msId(rId),
74 msPath(rOOXMLStream.msPath)
75 {
76 mxRelationshipAccess.set(rOOXMLStream.mxDocumentStream, uno::UNO_QUERY_THROW);
77
78 init();
79 }
80
~OOXMLStreamImpl()81 OOXMLStreamImpl::~OOXMLStreamImpl()
82 {
83 #ifdef DEBUG_STREAM
84 debug_logger->endElement("stream");
85 #endif
86 }
87
getTarget() const88 const ::rtl::OUString & OOXMLStreamImpl::getTarget() const
89 {
90 return msTarget;
91 }
92
lcl_normalizeTarget(const::rtl::OUString & s)93 ::rtl::OUString lcl_normalizeTarget(const ::rtl::OUString & s)
94 {
95 const int nStringsToCut = 2;
96 const ::rtl::OUString aStringToCut[] = {
97 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("./")),
98 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"))
99 };
100
101 bool bDone = false;
102 sal_Int32 nIndex = 0;
103 while (!bDone)
104 {
105 for (int n = 0; n <= nStringsToCut; n++)
106 {
107 if (n == nStringsToCut)
108 {
109 bDone = true;
110 }
111 else
112 {
113 sal_Int32 nNewIndex = s.indexOf(aStringToCut[n], nIndex);
114
115 if (nIndex == nNewIndex)
116 {
117 sal_Int32 nLength = aStringToCut[n].getLength();
118 nIndex += nLength;
119
120 break;
121 }
122 }
123 }
124 }
125
126 return s.copy(nIndex);
127 }
128
lcl_getTarget(uno::Reference<embed::XRelationshipAccess> xRelationshipAccess,StreamType_t nStreamType,const::rtl::OUString & rId,::rtl::OUString & rDocumentTarget)129 bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess>
130 xRelationshipAccess,
131 StreamType_t nStreamType,
132 const ::rtl::OUString & rId,
133 ::rtl::OUString & rDocumentTarget)
134 {
135 bool bFound = false;
136
137 static rtl::OUString sType(RTL_CONSTASCII_USTRINGPARAM("Type"));
138 static rtl::OUString sId(RTL_CONSTASCII_USTRINGPARAM("Id"));
139 static rtl::OUString sDocumentType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"));
140 static rtl::OUString sStylesType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"));
141 static rtl::OUString sNumberingType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering"));
142 static rtl::OUString sFonttableType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable"));
143 static rtl::OUString sFootnotesType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes"));
144 static rtl::OUString sEndnotesType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes"));
145 static rtl::OUString sCommentsType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"));
146 static rtl::OUString sThemeType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"));
147 static rtl::OUString sSettingsType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings"));
148 static rtl::OUString sTarget(RTL_CONSTASCII_USTRINGPARAM("Target"));
149 static rtl::OUString sTargetMode(RTL_CONSTASCII_USTRINGPARAM("TargetMode"));
150 static rtl::OUString sExternal(RTL_CONSTASCII_USTRINGPARAM("External"));
151
152 rtl::OUString sStreamType;
153
154 switch (nStreamType)
155 {
156 case DOCUMENT:
157 sStreamType = sDocumentType;
158 break;
159 case STYLES:
160 sStreamType = sStylesType;
161 break;
162 case NUMBERING:
163 sStreamType = sNumberingType;
164 break;
165 case FONTTABLE:
166 sStreamType = sFonttableType;
167 break;
168 case FOOTNOTES:
169 sStreamType = sFootnotesType;
170 break;
171 case ENDNOTES:
172 sStreamType = sEndnotesType;
173 break;
174 case COMMENTS:
175 sStreamType = sCommentsType;
176 break;
177 case THEME:
178 sStreamType = sThemeType;
179 break;
180 case SETTINGS:
181 sStreamType = sSettingsType;
182 break;
183 default:
184 break;
185 }
186
187 if (xRelationshipAccess.is())
188 {
189 uno::Sequence< uno::Sequence< beans::StringPair > >aSeqs =
190 xRelationshipAccess->getAllRelationships();
191
192 for (sal_Int32 j = 0; j < aSeqs.getLength(); j++)
193 {
194 uno::Sequence< beans::StringPair > aSeq = aSeqs[j];
195
196 bool bExternalTarget = false;
197 ::rtl::OUString sMyTarget;
198 for (sal_Int32 i = 0; i < aSeq.getLength(); i++)
199 {
200 beans::StringPair aPair = aSeq[i];
201
202 if (aPair.First.compareTo(sType) == 0 &&
203 aPair.Second.compareTo(sStreamType) == 0)
204 bFound = true;
205 else if (aPair.First.compareTo(sId) == 0 &&
206 aPair.Second.compareTo(rId) == 0)
207 bFound = true;
208 else if (aPair.First.compareTo(sTarget) == 0)
209 sMyTarget = aPair.Second;
210 else if (aPair.First.compareTo(sTargetMode) == 0 &&
211 aPair.Second.compareTo(sExternal) == 0)
212 bExternalTarget = true;
213
214 }
215
216 if (bFound)
217 {
218 if (bExternalTarget)
219 rDocumentTarget = sMyTarget;
220 else
221 {
222 rDocumentTarget = msPath;
223 rDocumentTarget += lcl_normalizeTarget(sMyTarget);
224 }
225
226 break;
227 }
228 }
229 }
230
231 return bFound;
232 }
233
getTargetForId(const::rtl::OUString & rId)234 ::rtl::OUString OOXMLStreamImpl::getTargetForId(const ::rtl::OUString & rId)
235 {
236 ::rtl::OUString sTarget;
237
238 uno::Reference<embed::XRelationshipAccess> xRelationshipAccess
239 (mxDocumentStream, uno::UNO_QUERY_THROW);
240
241 if (lcl_getTarget(xRelationshipAccess, UNKNOWN, rId, sTarget))
242 return sTarget;
243
244 return ::rtl::OUString();
245 }
246
init()247 void OOXMLStreamImpl::init()
248 {
249 bool bFound = lcl_getTarget(mxRelationshipAccess,
250 mnStreamType, msId, msTarget);
251 #ifdef DEBUG_STREAM
252 debug_logger->startElement("stream");
253 debug_logger->attribute("target", msTarget);
254 #endif
255
256 if (bFound)
257 {
258 sal_Int32 nLastIndex = msTarget.lastIndexOf('/');
259 if (nLastIndex >= 0)
260 msPath = msTarget.copy(0, nLastIndex + 1);
261
262 uno::Reference<embed::XHierarchicalStorageAccess>
263 xHierarchicalStorageAccess(mxStorage, uno::UNO_QUERY);
264
265 if (xHierarchicalStorageAccess.is())
266 {
267 uno::Any aAny(xHierarchicalStorageAccess->
268 openStreamElementByHierarchicalName
269 (msTarget, embed::ElementModes::SEEKABLEREAD));
270 aAny >>= mxDocumentStream;
271 }
272 }
273 }
274
getDocumentStream()275 uno::Reference<io::XInputStream> OOXMLStreamImpl::getDocumentStream()
276 {
277 uno::Reference<io::XInputStream> xResult;
278
279 if (mxDocumentStream.is())
280 xResult = mxDocumentStream->getInputStream();
281
282 return xResult;
283 }
284
getStorageStream()285 uno::Reference<io::XInputStream> OOXMLStreamImpl::getStorageStream()
286 {
287 return mxStorageStream;
288 }
289
getParser()290 uno::Reference<xml::sax::XParser> OOXMLStreamImpl::getParser()
291 {
292 uno::Reference<lang::XMultiComponentFactory> xFactory =
293 uno::Reference<lang::XMultiComponentFactory>
294 (mxContext->getServiceManager());
295
296 uno::Reference<xml::sax::XParser> xParser
297 (xFactory->createInstanceWithContext
298 ( rtl::OUString::createFromAscii( "com.sun.star.xml.sax.Parser" ),
299 mxContext ),
300 uno::UNO_QUERY );
301
302 return xParser;
303 }
304
getContext()305 uno::Reference<uno::XComponentContext> OOXMLStreamImpl::getContext()
306 {
307 return mxContext;
308 }
309
310 uno::Reference <xml::sax::XFastTokenHandler>
getFastTokenHandler(uno::Reference<uno::XComponentContext> xContext)311 OOXMLStreamImpl::getFastTokenHandler
312 (uno::Reference<uno::XComponentContext> xContext)
313 {
314 if (! mxFastTokenHandler.is())
315 mxFastTokenHandler.set(new OOXMLFastTokenHandler(xContext));
316
317 return mxFastTokenHandler;
318 }
319
320 OOXMLStream::Pointer_t
createStream(uno::Reference<uno::XComponentContext> xContext,uno::Reference<io::XInputStream> rStream,OOXMLStream::StreamType_t nStreamType)321 OOXMLDocumentFactory::createStream
322 (uno::Reference<uno::XComponentContext> xContext,
323 uno::Reference<io::XInputStream> rStream,
324 OOXMLStream::StreamType_t nStreamType)
325 {
326 OOXMLStreamImpl * pStream = new OOXMLStreamImpl(xContext, rStream,
327 nStreamType);
328 return OOXMLStream::Pointer_t(pStream);
329 }
330
331 OOXMLStream::Pointer_t
createStream(OOXMLStream::Pointer_t pStream,OOXMLStream::StreamType_t nStreamType)332 OOXMLDocumentFactory::createStream
333 (OOXMLStream::Pointer_t pStream, OOXMLStream::StreamType_t nStreamType)
334 {
335 return OOXMLStream::Pointer_t
336 (new OOXMLStreamImpl(*dynamic_cast<OOXMLStreamImpl *>(pStream.get()),
337 nStreamType));
338 }
339
340 OOXMLStream::Pointer_t
createStream(OOXMLStream::Pointer_t pStream,const rtl::OUString & rId)341 OOXMLDocumentFactory::createStream
342 (OOXMLStream::Pointer_t pStream, const rtl::OUString & rId)
343 {
344 return OOXMLStream::Pointer_t
345 (new OOXMLStreamImpl(*dynamic_cast<OOXMLStreamImpl *>(pStream.get()),
346 rId));
347 }
348
349 }}
350