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_getTarget(uno::Reference<embed::XRelationshipAccess> xRelationshipAccess,StreamType_t nStreamType,const::rtl::OUString & rId,::rtl::OUString & rDocumentTarget)93 bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess>
94                                     xRelationshipAccess,
95                                     StreamType_t nStreamType,
96                                     const ::rtl::OUString & rId,
97                                     ::rtl::OUString & rDocumentTarget)
98 {
99     bool bFound = false;
100 
101     static rtl::OUString sType(RTL_CONSTASCII_USTRINGPARAM("Type"));
102     static rtl::OUString sId(RTL_CONSTASCII_USTRINGPARAM("Id"));
103     static rtl::OUString sDocumentType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"));
104     static rtl::OUString sStylesType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"));
105     static rtl::OUString sNumberingType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering"));
106     static rtl::OUString sFonttableType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable"));
107     static rtl::OUString sFootnotesType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes"));
108     static rtl::OUString sEndnotesType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes"));
109     static rtl::OUString sCommentsType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"));
110     static rtl::OUString sThemeType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"));
111     static rtl::OUString sSettingsType(RTL_CONSTASCII_USTRINGPARAM("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings"));
112     static rtl::OUString sTarget(RTL_CONSTASCII_USTRINGPARAM("Target"));
113     static rtl::OUString sTargetMode(RTL_CONSTASCII_USTRINGPARAM("TargetMode"));
114     static rtl::OUString sExternal(RTL_CONSTASCII_USTRINGPARAM("External"));
115 
116     rtl::OUString sStreamType;
117 
118     switch (nStreamType)
119     {
120         case DOCUMENT:
121             sStreamType = sDocumentType;
122             break;
123         case STYLES:
124             sStreamType = sStylesType;
125 			break;
126         case NUMBERING:
127             sStreamType = sNumberingType;
128             break;
129         case FONTTABLE:
130             sStreamType = sFonttableType;
131             break;
132         case FOOTNOTES:
133             sStreamType = sFootnotesType;
134             break;
135         case ENDNOTES:
136             sStreamType = sEndnotesType;
137             break;
138         case COMMENTS:
139             sStreamType = sCommentsType;
140             break;
141         case THEME:
142             sStreamType = sThemeType;
143             break;
144         case SETTINGS:
145             sStreamType = sSettingsType;
146             break;
147         default:
148             break;
149     }
150 
151     if (xRelationshipAccess.is())
152     {
153         uno::Sequence< uno::Sequence< beans::StringPair > >aSeqs =
154             xRelationshipAccess->getAllRelationships();
155 
156         for (sal_Int32 j = 0; j < aSeqs.getLength(); j++)
157         {
158             uno::Sequence< beans::StringPair > aSeq = aSeqs[j];
159 
160             bool bExternalTarget = false;
161             ::rtl::OUString sMyTarget;
162             for (sal_Int32 i = 0; i < aSeq.getLength(); i++)
163             {
164                 beans::StringPair aPair = aSeq[i];
165 
166                 if (aPair.First.compareTo(sType) == 0 &&
167                     aPair.Second.compareTo(sStreamType) == 0)
168                     bFound = true;
169                 else if (aPair.First.compareTo(sId) == 0 &&
170                          aPair.Second.compareTo(rId) == 0)
171                     bFound = true;
172                 else if (aPair.First.compareTo(sTarget) == 0)
173                     sMyTarget = aPair.Second;
174                 else if (aPair.First.compareTo(sTargetMode) == 0 &&
175                          aPair.Second.compareTo(sExternal) == 0)
176                     bExternalTarget = true;
177 
178             }
179 
180             if (bFound)
181             {
182                 if (bExternalTarget)
183                     rDocumentTarget = sMyTarget;
184                 else
185                 {
186                     rDocumentTarget = msPath;
187                     rDocumentTarget += sMyTarget;
188                 }
189 
190                 break;
191             }
192         }
193     }
194 
195     return bFound;
196 }
197 
getTargetForId(const::rtl::OUString & rId)198 ::rtl::OUString OOXMLStreamImpl::getTargetForId(const ::rtl::OUString & rId)
199 {
200     ::rtl::OUString sTarget;
201 
202     uno::Reference<embed::XRelationshipAccess> xRelationshipAccess
203         (mxDocumentStream, uno::UNO_QUERY_THROW);
204 
205     if (lcl_getTarget(xRelationshipAccess, UNKNOWN, rId, sTarget))
206         return sTarget;
207 
208     return ::rtl::OUString();
209 }
210 
init()211 void OOXMLStreamImpl::init()
212 {
213     bool bFound = lcl_getTarget(mxRelationshipAccess,
214                                 mnStreamType, msId, msTarget);
215 #ifdef DEBUG_STREAM
216     debug_logger->startElement("stream");
217     debug_logger->attribute("target", msTarget);
218 #endif
219 
220     if (bFound)
221     {
222         sal_Int32 nLastIndex = msTarget.lastIndexOf('/');
223         if (nLastIndex >= 0)
224             msPath = msTarget.copy(0, nLastIndex + 1);
225 
226         uno::Reference<embed::XHierarchicalStorageAccess>
227             xHierarchicalStorageAccess(mxStorage, uno::UNO_QUERY);
228 
229         if (xHierarchicalStorageAccess.is())
230         {
231             uno::Any aAny(xHierarchicalStorageAccess->
232                           openStreamElementByHierarchicalName
233                           (msTarget, embed::ElementModes::SEEKABLEREAD));
234             aAny >>= mxDocumentStream;
235         }
236     }
237 }
238 
getDocumentStream()239 uno::Reference<io::XInputStream> OOXMLStreamImpl::getDocumentStream()
240 {
241     uno::Reference<io::XInputStream> xResult;
242 
243     if (mxDocumentStream.is())
244         xResult = mxDocumentStream->getInputStream();
245 
246     return xResult;
247 }
248 
getStorageStream()249 uno::Reference<io::XInputStream> OOXMLStreamImpl::getStorageStream()
250 {
251     return mxStorageStream;
252 }
253 
getParser()254 uno::Reference<xml::sax::XParser> OOXMLStreamImpl::getParser()
255 {
256     uno::Reference<lang::XMultiComponentFactory> xFactory =
257         uno::Reference<lang::XMultiComponentFactory>
258         (mxContext->getServiceManager());
259 
260     uno::Reference<xml::sax::XParser> xParser
261         (xFactory->createInstanceWithContext
262         ( rtl::OUString::createFromAscii( "com.sun.star.xml.sax.Parser" ),
263           mxContext ),
264         uno::UNO_QUERY );
265 
266     return xParser;
267 }
268 
getContext()269 uno::Reference<uno::XComponentContext> OOXMLStreamImpl::getContext()
270 {
271     return mxContext;
272 }
273 
274 uno::Reference <xml::sax::XFastTokenHandler>
getFastTokenHandler(uno::Reference<uno::XComponentContext> xContext)275 OOXMLStreamImpl::getFastTokenHandler
276 (uno::Reference<uno::XComponentContext> xContext)
277 {
278     if (! mxFastTokenHandler.is())
279         mxFastTokenHandler.set(new OOXMLFastTokenHandler(xContext));
280 
281     return mxFastTokenHandler;
282 }
283 
284 OOXMLStream::Pointer_t
createStream(uno::Reference<uno::XComponentContext> xContext,uno::Reference<io::XInputStream> rStream,OOXMLStream::StreamType_t nStreamType)285 OOXMLDocumentFactory::createStream
286 (uno::Reference<uno::XComponentContext> xContext,
287  uno::Reference<io::XInputStream> rStream,
288  OOXMLStream::StreamType_t nStreamType)
289 {
290     OOXMLStreamImpl * pStream = new OOXMLStreamImpl(xContext, rStream,
291                                                     nStreamType);
292     return OOXMLStream::Pointer_t(pStream);
293 }
294 
295 OOXMLStream::Pointer_t
createStream(OOXMLStream::Pointer_t pStream,OOXMLStream::StreamType_t nStreamType)296 OOXMLDocumentFactory::createStream
297 (OOXMLStream::Pointer_t pStream,  OOXMLStream::StreamType_t nStreamType)
298 {
299     return OOXMLStream::Pointer_t
300         (new OOXMLStreamImpl(*dynamic_cast<OOXMLStreamImpl *>(pStream.get()),
301                              nStreamType));
302 }
303 
304 OOXMLStream::Pointer_t
createStream(OOXMLStream::Pointer_t pStream,const rtl::OUString & rId)305 OOXMLDocumentFactory::createStream
306 (OOXMLStream::Pointer_t pStream, const rtl::OUString & rId)
307 {
308     return OOXMLStream::Pointer_t
309         (new OOXMLStreamImpl(*dynamic_cast<OOXMLStreamImpl *>(pStream.get()),
310                              rId));
311 }
312 
313 }}
314