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