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