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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_xmloff.hxx"
26 #include <com/sun/star/document/XImporter.hpp>
27 #include <com/sun/star/util/XModifiable.hpp>
28 #include <com/sun/star/util/XModifiable2.hpp>
29 #include <com/sun/star/frame/XStorable.hpp>
30 
31 // #110680#
32 //#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
33 //#include <comphelper/processfactory.hxx>
34 //#endif
35 #include <tools/globname.hxx>
36 #include <sot/clsids.hxx>
37 #include <tools/globname.hxx>
38 #include <sot/clsids.hxx>
39 #include <xmloff/nmspmap.hxx>
40 #include <xmloff/xmlimp.hxx>
41 #include "xmloff/xmlnmspe.hxx"
42 #include <xmloff/xmltoken.hxx>
43 #include "xmloff/xmlerror.hxx"
44 #include <xmloff/attrlist.hxx>
45 #include "xmloff/XMLFilterServiceNames.h"
46 #include "XMLEmbeddedObjectImportContext.hxx"
47 
48 using ::rtl::OUString;
49 using ::rtl::OUStringBuffer;
50 
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::util;
53 using namespace ::com::sun::star::beans;
54 using namespace ::com::sun::star::lang;
55 using namespace ::com::sun::star::frame;
56 using namespace ::com::sun::star::document;
57 using namespace ::com::sun::star::xml::sax;
58 using namespace ::xmloff::token;
59 
60 struct XMLServiceMapEntry_Impl
61 {
62 	enum XMLTokenEnum eClass;
63 	const sal_Char *sFilterService;
64 	sal_Int32	   nFilterServiceLen;
65 };
66 
67 #define SERVICE_MAP_ENTRY( cls, app ) \
68 	{ XML_##cls, \
69 	  XML_IMPORT_FILTER_##app, sizeof(XML_IMPORT_FILTER_##app)-1}
70 
71 const XMLServiceMapEntry_Impl aServiceMap[] =
72 {
73 	SERVICE_MAP_ENTRY( TEXT, WRITER ),
74 	SERVICE_MAP_ENTRY( ONLINE_TEXT, WRITER ),
75 	SERVICE_MAP_ENTRY( SPREADSHEET, CALC ),
76 	SERVICE_MAP_ENTRY( DRAWING, DRAW ),
77 	SERVICE_MAP_ENTRY( GRAPHICS, DRAW ),
78 	SERVICE_MAP_ENTRY( PRESENTATION, IMPRESS ),
79 	SERVICE_MAP_ENTRY( CHART, CHART ),
80 	{ XML_TOKEN_INVALID, 0, 0 }
81 };
82 
83 class XMLEmbeddedObjectImportContext_Impl : public SvXMLImportContext
84 {
85 	::com::sun::star::uno::Reference<
86 		::com::sun::star::xml::sax::XDocumentHandler > xHandler;
87 
88 public:
89 	TYPEINFO();
90 
91 	XMLEmbeddedObjectImportContext_Impl( SvXMLImport& rImport, sal_uInt16 nPrfx,
92 									const ::rtl::OUString& rLName,
93 	const ::com::sun::star::uno::Reference<
94 		::com::sun::star::xml::sax::XDocumentHandler >& rHandler );
95 
96 	virtual ~XMLEmbeddedObjectImportContext_Impl();
97 
98 	virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
99 								   const ::rtl::OUString& rLocalName,
100 								   const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList );
101 
102 	virtual void StartElement( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList );
103 
104 	virtual void EndElement();
105 
106 	virtual void Characters( const ::rtl::OUString& rChars );
107 };
108 
109 TYPEINIT1( XMLEmbeddedObjectImportContext_Impl, SvXMLImportContext );
110 
XMLEmbeddedObjectImportContext_Impl(SvXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const Reference<XDocumentHandler> & rHandler)111 XMLEmbeddedObjectImportContext_Impl::XMLEmbeddedObjectImportContext_Impl(
112 		SvXMLImport& rImport, sal_uInt16 nPrfx,
113 		const OUString& rLName,
114 		const Reference< XDocumentHandler >& rHandler ) :
115 	SvXMLImportContext( rImport, nPrfx, rLName ),
116 	xHandler( rHandler )
117 {
118 }
119 
~XMLEmbeddedObjectImportContext_Impl()120 XMLEmbeddedObjectImportContext_Impl::~XMLEmbeddedObjectImportContext_Impl()
121 {
122 }
123 
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<XAttributeList> &)124 SvXMLImportContext *XMLEmbeddedObjectImportContext_Impl::CreateChildContext(
125 		sal_uInt16 nPrefix,
126 		const OUString& rLocalName,
127 		const Reference< XAttributeList >& )
128 {
129 	return new XMLEmbeddedObjectImportContext_Impl( GetImport(),
130 													nPrefix, rLocalName,
131 												    xHandler );
132 }
133 
StartElement(const Reference<XAttributeList> & xAttrList)134 void XMLEmbeddedObjectImportContext_Impl::StartElement(
135 		const Reference< XAttributeList >& xAttrList )
136 {
137 	xHandler->startElement( GetImport().GetNamespaceMap().GetQNameByKey(
138 								GetPrefix(), GetLocalName() ),
139 							xAttrList );
140 }
141 
EndElement()142 void XMLEmbeddedObjectImportContext_Impl::EndElement()
143 {
144 	xHandler->endElement( GetImport().GetNamespaceMap().GetQNameByKey(
145 								GetPrefix(), GetLocalName() ) );
146 }
147 
Characters(const OUString & rChars)148 void XMLEmbeddedObjectImportContext_Impl::Characters( const OUString& rChars )
149 {
150 	xHandler->characters( rChars );
151 }
152 
153 //-----------------------------------------------------------------------------
154 
155 TYPEINIT1( XMLEmbeddedObjectImportContext, SvXMLImportContext );
156 
SetComponent(Reference<XComponent> & rComp)157 sal_Bool XMLEmbeddedObjectImportContext::SetComponent(
158 		Reference< XComponent >& rComp )
159 {
160 	if( !rComp.is() || !sFilterService.getLength() )
161 		return sal_False;
162 
163 
164 	Sequence<Any> aArgs( 0 );
165 
166 	// #110680#
167 	// Reference< XMultiServiceFactory > xServiceFactory = comphelper::getProcessServiceFactory();
168 	Reference< XMultiServiceFactory > xServiceFactory = GetImport().getServiceFactory();
169 
170 	xHandler = Reference < XDocumentHandler >(
171 		xServiceFactory->createInstanceWithArguments( sFilterService, aArgs),
172 											   UNO_QUERY);
173 
174 	if( !xHandler.is() )
175 		return sal_False;
176 
177 	try
178 	{
179 		Reference < XModifiable2 > xModifiable2( rComp, UNO_QUERY_THROW );
180 		xModifiable2->disableSetModified();
181 	}
182 	catch( Exception& )
183 	{
184 	}
185 
186 	Reference < XImporter > xImporter( xHandler, UNO_QUERY );
187 	xImporter->setTargetDocument( rComp );
188 
189 	xComp = rComp;	// keep ref to component only if there is a handler
190 
191 	return sal_True;
192 }
193 
XMLEmbeddedObjectImportContext(SvXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const Reference<XAttributeList> & xAttrList)194 XMLEmbeddedObjectImportContext::XMLEmbeddedObjectImportContext(
195 		SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
196 		const Reference< XAttributeList >& xAttrList ) :
197 	SvXMLImportContext( rImport, nPrfx, rLName )
198 {
199 	SvGlobalName aName;
200 
201 	if( nPrfx == XML_NAMESPACE_MATH &&
202 		IsXMLToken( rLName, XML_MATH ) )
203 	{
204 		sFilterService = OUString( RTL_CONSTASCII_USTRINGPARAM(XML_IMPORT_FILTER_MATH) );
205 		aName = SvGlobalName(SO3_SM_CLASSID);
206 	}
207 	else if( nPrfx == XML_NAMESPACE_OFFICE &&
208 		IsXMLToken( rLName, XML_DOCUMENT ) )
209 	{
210 		OUString sMime;
211 
212 		sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
213 		for( sal_Int16 i=0; i < nAttrCount; i++ )
214 		{
215 			const OUString& rAttrName = xAttrList->getNameByIndex( i );
216 			OUString aLocalName;
217 			sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,	&aLocalName );
218 			if( nPrefix == XML_NAMESPACE_OFFICE &&
219 				IsXMLToken( aLocalName, XML_MIMETYPE ) )
220 			{
221 				sMime = xAttrList->getValueByIndex( i );
222 				break;
223 			}
224 		}
225 
226 		OUString sClass;
227 		static const char * aTmp[] =
228 		{
229 			"application/vnd.oasis.openoffice.",
230 			"application/x-vnd.oasis.openoffice.",
231 			"application/vnd.oasis.opendocument.",
232 			"application/x-vnd.oasis.opendocument.",
233 			NULL
234 		};
235 		for (int k=0; aTmp[k]; k++)
236 		{
237 			::rtl::OUString sTmpString = ::rtl::OUString::createFromAscii(aTmp[k]);
238 			if( sMime.matchAsciiL( aTmp[k], sTmpString.getLength() ) )
239 			{
240 				sClass = sMime.copy( sTmpString.getLength() );
241 				break;
242 			}
243 		}
244 
245 		if( sClass.getLength() )
246 		{
247 			const XMLServiceMapEntry_Impl *pEntry = aServiceMap;
248 			while( pEntry->eClass != XML_TOKEN_INVALID )
249 			{
250 				if( IsXMLToken( sClass, pEntry->eClass ) )
251 				{
252 					sFilterService = OUString( pEntry->sFilterService,
253 											   pEntry->nFilterServiceLen,
254 											   RTL_TEXTENCODING_ASCII_US );
255 
256 					switch( pEntry->eClass )
257 					{
258 					case XML_TEXT:			aName = SvGlobalName(SO3_SW_CLASSID); break;
259 					case XML_ONLINE_TEXT:	aName = SvGlobalName(SO3_SWWEB_CLASSID); break;
260 					case XML_SPREADSHEET:	aName = SvGlobalName(SO3_SC_CLASSID); break;
261 					case XML_DRAWING:
262 					case XML_GRAPHICS:
263 					case XML_IMAGE:		aName = SvGlobalName(SO3_SDRAW_CLASSID); break;
264 					case XML_PRESENTATION:	aName = SvGlobalName(SO3_SIMPRESS_CLASSID); break;
265 					case XML_CHART:			aName = SvGlobalName(SO3_SCH_CLASSID); break;
266 					default:
267 						break;
268 					}
269 
270 					break;
271 				}
272 				pEntry++;
273 			}
274 		}
275 	}
276 
277 	sCLSID = aName.GetHexName();
278 }
279 
~XMLEmbeddedObjectImportContext()280 XMLEmbeddedObjectImportContext::~XMLEmbeddedObjectImportContext()
281 {
282 }
283 
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<XAttributeList> &)284 SvXMLImportContext *XMLEmbeddedObjectImportContext::CreateChildContext(
285 		sal_uInt16 nPrefix, const OUString& rLocalName,
286 		const Reference< XAttributeList >& )
287 {
288 	if( xHandler.is() )
289 		return new XMLEmbeddedObjectImportContext_Impl( GetImport(),
290 														nPrefix, rLocalName,
291 														xHandler );
292 	else
293 		return new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
294 }
295 
StartElement(const Reference<XAttributeList> & rAttrList)296 void XMLEmbeddedObjectImportContext::StartElement(
297 		const Reference< XAttributeList >& rAttrList )
298 {
299 	if( xHandler.is() )
300 	{
301 		xHandler->startDocument();
302 		// #i34042: copy namespace declarations
303 		SvXMLAttributeList *pAttrList = new SvXMLAttributeList( rAttrList );
304 		Reference< XAttributeList > xAttrList( pAttrList );
305 		const SvXMLNamespaceMap& rNamespaceMap = GetImport().GetNamespaceMap();
306 		sal_uInt16 nPos = rNamespaceMap.GetFirstKey();
307 		while( USHRT_MAX != nPos )
308 		{
309 			OUString aAttrName( rNamespaceMap.GetAttrNameByKey( nPos ) );
310 			if( 0 == xAttrList->getValueByName( aAttrName ).getLength() )
311 			{
312 				pAttrList->AddAttribute( aAttrName,
313 									 	 rNamespaceMap.GetNameByKey( nPos ) );
314 			}
315 			nPos = rNamespaceMap.GetNextKey( nPos );
316 		}
317 		xHandler->startElement( GetImport().GetNamespaceMap().GetQNameByKey(
318 									GetPrefix(), GetLocalName() ),
319 								xAttrList );
320 	}
321 }
322 
EndElement()323 void XMLEmbeddedObjectImportContext::EndElement()
324 {
325 	if( xHandler.is() )
326 	{
327 		xHandler->endElement( GetImport().GetNamespaceMap().GetQNameByKey(
328 									GetPrefix(), GetLocalName() ) );
329 		xHandler->endDocument();
330 
331 
332 		// storing part is commented out since it should be done through the object, not the model
333 		// TODO/LATER: probably an object should be provided here an be stored here
334 
335 //		// Save the object. That's required because the object should not be
336 //		// modified (it has been loaded just now). Setting it to unmodified
337 //		// only does not work, because it is then assumed that it has been
338 //		// stored.
339 //		Reference < XStorable > xStorable( xComp, UNO_QUERY );
340 //		if( xStorable.is() )
341 //		{
342 //			try
343 //			{
344 //				xStorable->store();
345 //			}
346 //			catch( ::com::sun::star::beans::PropertyVetoException& )
347 //			{
348 //				Sequence<OUString> aSeq( 0 );
349 //				GetImport().SetError( XMLERROR_FLAG_WARNING |
350 //								  XMLERROR_API,
351 //								  aSeq );
352 //			}
353 //		}
354 
355 	try
356 	{
357 		Reference < XModifiable2 > xModifiable2( xComp, UNO_QUERY_THROW );
358 		xModifiable2->enableSetModified();
359 		xModifiable2->setModified( sal_True ); // trigger new replacement image generation
360 	}
361 	catch( Exception& )
362 	{
363 	}
364 
365 
366 //		// reset modifies state for the object since it has been imported
367 //		// completely and therefor hasn't been modified.
368 //		Reference < XModifiable > xModifiable( xComp, UNO_QUERY );
369 //		if( xModifiable.is() )
370 //		{
371 //			try
372 //			{
373 //				xModifiable->setModified( sal_False );
374 //			}
375 //			catch( ::com::sun::star::beans::PropertyVetoException& e )
376 //			{
377 //				Sequence<OUString> aSeq( 0 );
378 //				GetImport().SetError( XMLERROR_FLAG_WARNING |
379 //								  XMLERROR_API,
380 //								  aSeq );
381 //			}
382 //		}
383 	}
384 }
385 
Characters(const::rtl::OUString & rChars)386 void XMLEmbeddedObjectImportContext::Characters( const ::rtl::OUString& rChars )
387 {
388 	if( xHandler.is() )
389 		xHandler->characters( rChars );
390 }
391 
392