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_filter.hxx"
26 #include <iostream>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include <stdio.h>
30 #include <rtl/ustring.hxx>
31 #include <tools/urlobj.hxx>
32 #include "XmlFilterAdaptor.hxx"
33 #include <osl/diagnose.h>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/uno/RuntimeException.hpp>
36 #include <com/sun/star/io/XActiveDataSource.hpp>
37 #include <com/sun/star/io/XOutputStream.hpp>
38 #include <com/sun/star/io/XInputStream.hpp>
39 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
40 #include <com/sun/star/xml/sax/InputSource.hpp>
41 #include <com/sun/star/xml/sax/XParser.hpp>
42 #include <com/sun/star/frame/XConfigManager.hpp>
43 #include <com/sun/star/frame/XConfigManager.hpp>
44 #include <com/sun/star/xml/XImportFilter.hpp>
45 #include <com/sun/star/xml/XExportFilter.hpp>
46 #include <com/sun/star/frame/XModel.hpp>
47 #include <com/sun/star/frame/XController.hpp>
48 #include <com/sun/star/task/XStatusIndicator.hpp>
49 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
50 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
51 #include <com/sun/star/style/XStyleLoader.hpp>
52 #include <com/sun/star/container/XNameAccess.hpp>
53 #include <comphelper/sequenceashashmap.hxx>
54 #include <comphelper/mediadescriptor.hxx>
55 #include <com/sun/star/beans/PropertyAttribute.hpp>
56 #include <comphelper/genericpropertyset.hxx>
57 #include <comphelper/propertysetinfo.hxx>
58 
59 using namespace rtl;
60 using namespace comphelper;
61 using namespace com::sun::star::uno;
62 using namespace com::sun::star::lang;
63 using namespace com::sun::star::io;
64 using namespace com::sun::star::beans;
65 using namespace com::sun::star::container;
66 using namespace com::sun::star::document;
67 using namespace com::sun::star::style;
68 using namespace com::sun::star::xml;
69 using namespace com::sun::star::xml::sax;
70 using namespace ::com::sun::star::frame;
71 using namespace ::com::sun::star::task;
72 
73 #define MAP_LEN(x) x, sizeof(x) - 1
74 
75 Reference< com::sun::star::frame::XModel > xModel;
76 
importImpl(const Sequence<::com::sun::star::beans::PropertyValue> & aDescriptor)77 sal_Bool SAL_CALL XmlFilterAdaptor::importImpl( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
78 	throw (RuntimeException)
79 {
80     OUString udConvertClass=msUserData[0];
81     OUString udImport =msUserData[2];
82     sal_Int32 nSteps= 0;
83     sal_Int32 nProgressRange = 4;
84 
85     comphelper::MediaDescriptor aMediaMap(aDescriptor);
86     Reference< XStatusIndicator > xStatusIndicator(aMediaMap.getUnpackedValueOrDefault(
87         comphelper::MediaDescriptor::PROP_STATUSINDICATOR(), Reference< XStatusIndicator >()));
88 
89     if (xStatusIndicator.is()){
90 	    xStatusIndicator->start(OUString(  RTL_CONSTASCII_USTRINGPARAM( "Loading :" )),nProgressRange);
91     }
92 
93 	OUString sXMLImportService (  udImport  );
94 	const OUString sSaxParser ( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Parser") );
95 	Reference < XParser > xSaxParser( mxMSF->createInstance( sSaxParser ), UNO_QUERY );
96 
97     Sequence< Any > aAnys(1);
98     OUString aBaseURI;
99     if (aMediaMap.find(OUString::createFromAscii("URL"))->second >>= aBaseURI)
100     {
101         INetURLObject aURLObj(aBaseURI);
102         // base URI in this case is the URI of the actual saving location
103         // aURLObj.removeSegment();
104         aBaseURI = aURLObj.GetMainURL(INetURLObject::NO_DECODE);
105     }
106 
107     // create an XProperty set to configure the exporter for pretty printing
108     PropertyMapEntry aImportInfoMap[] =
109  	{
110         { MAP_LEN( "BaseURI" ), 0, &::getCppuType((const OUString*)0), PropertyAttribute::MAYBEVOID, 0},
111      	{ NULL, 0, 0, NULL, 0, 0 }
112  	};
113 
114  	Reference< XPropertySet > xInfoSet(
115         GenericPropertySet_CreateInstance( new PropertySetInfo( aImportInfoMap ) ) );
116  	xInfoSet->setPropertyValue(
117         OUString::createFromAscii( "BaseURI" ), makeAny( aBaseURI ));
118     aAnys[0] <<= xInfoSet;
119 
120 
121     Reference < XDocumentHandler > xHandler( mxMSF->createInstanceWithArguments( sXMLImportService, aAnys ), UNO_QUERY );
122     if(! xHandler.is()) {
123 	    OSL_ENSURE(sal_False, "XMLReader::Read: %s Unable to create service instance xHandler\n" );
124         return sal_False;
125     }
126 	Reference < XImporter > xImporter( xHandler, UNO_QUERY );
127 	xImporter->setTargetDocument ( mxDoc );
128 
129 	if (xStatusIndicator.is()){
130 	    xStatusIndicator->setValue(nSteps++);
131     }
132 
133 	//*********************
134 	// Creating a ConverterBridge instance
135 	//*********************
136 	Reference< XInterface > xConvBridge(mxMSF->createInstance( udConvertClass ), UNO_QUERY);
137 	if(! xConvBridge.is()){
138 	    OSL_ENSURE( sal_False,"XMLReader::Read: %s service missing\n" );
139 	    return sal_False;
140 	}
141 	if (xStatusIndicator.is())
142 	    xStatusIndicator->setValue(nSteps++);
143 
144 	Reference< XImportFilter > xConverter( xConvBridge, UNO_QUERY );
145 
146  	//********************
147 	//Template Loading if Required
148 	//********************
149 	if (!msTemplateName.equalsAscii("")){
150 		Reference< XStyleFamiliesSupplier > xstylefamiliessupplier(mxDoc, UNO_QUERY);
151 
152 		Reference< XNameAccess >xName;
153 		if(xstylefamiliessupplier.is()){
154 		    xName=xstylefamiliessupplier->getStyleFamilies();
155 		}
156 		Reference< XStyleLoader > xstyleLoader (xstylefamiliessupplier->getStyleFamilies(), UNO_QUERY);
157 
158 
159 		if(xstyleLoader.is()){
160 		    xName=xstylefamiliessupplier->getStyleFamilies();
161 		}
162 
163         Sequence < OUString > elementNames = xName->getElementNames();
164         if(xstyleLoader.is()){
165             Sequence<com::sun::star::beans::PropertyValue> pValue=xstyleLoader->getStyleLoaderOptions();
166 
167             //Load the Styles from the Template URL Supplied in the TypeDetection file
168             if(msTemplateName.indexOf(OUString::createFromAscii("file:"))==-1)
169             {
170                 Reference< XConfigManager >xCfgMgr ( mxMSF->createInstance(
171                     OUString::createFromAscii("com.sun.star.config.SpecialConfigManager") ), UNO_QUERY );
172                 OUString PathString=xCfgMgr->substituteVariables(OUString::createFromAscii("$(progurl)"));
173                 PathString=PathString.concat(OUString::createFromAscii("/"));
174                 msTemplateName=PathString.concat(msTemplateName);
175             }
176 
177             xstyleLoader->loadStylesFromURL(msTemplateName,pValue);
178         }
179     }
180 
181 //    sal_Bool xconv_ret = sal_True;
182 
183 	if (xStatusIndicator.is()){
184 	    xStatusIndicator->setValue(nSteps++);
185 	}
186 	//*********************
187 	// Calling Filtering Component
188 	//*********************
189 	try {
190         if (!xConverter->importer(aDescriptor,xHandler,msUserData)) {
191             if (xStatusIndicator.is())
192        	        xStatusIndicator->end();
193 	        return sal_False;
194         }
195 	}
196 #if OSL_DEBUG_LEVEL > 0
197 	catch( Exception& e )
198 #else
199 	catch( Exception& )
200 #endif
201 	{
202         if (xStatusIndicator.is())
203        	    xStatusIndicator->end();
204 
205 	    OSL_ENSURE( sal_False, ::rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US).getStr());
206 	    return sal_False;
207 	}
208     if (xStatusIndicator.is()) {
209 	    xStatusIndicator->setValue(nSteps++);
210         xStatusIndicator->end();
211     }
212 	return sal_True;
213 }
214 
exportImpl(const Sequence<::com::sun::star::beans::PropertyValue> & aDescriptor)215 sal_Bool SAL_CALL XmlFilterAdaptor::exportImpl( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
216 	throw (RuntimeException)
217 {
218 
219 	OUString udConvertClass = msUserData[0];
220 	OUString udExport = msUserData[3];
221 
222 	// Status Bar
223 	sal_Int32 nSteps= 1;
224 	sal_Int32 nProgressRange(3);
225     comphelper::MediaDescriptor aMediaMap(aDescriptor);
226     Reference< XStatusIndicator > xStatusIndicator(aMediaMap.getUnpackedValueOrDefault(
227         comphelper::MediaDescriptor::PROP_STATUSINDICATOR(), Reference< XStatusIndicator >()));
228 
229 	if (xStatusIndicator.is())
230 	   xStatusIndicator->start(OUString(  RTL_CONSTASCII_USTRINGPARAM( "Saving :" )),nProgressRange);
231 
232     // Set up converter bridge.
233 	Reference< com::sun::star::xml::XExportFilter > xConverter(mxMSF->createInstance(udConvertClass ), UNO_QUERY);
234 	if(! xConverter.is()){
235 	  OSL_ENSURE( sal_False, "xml export sub service missing" );
236 	  return sal_False;
237 	}
238 
239     if (xStatusIndicator.is())
240 	    xStatusIndicator->setValue(nSteps++);
241 
242 	//put filter component into exporting state
243     if (!xConverter->exporter(aDescriptor, msUserData)) {
244         if (xStatusIndicator.is())
245             xStatusIndicator->end();
246 	    return sal_False;
247 	}
248 	if (xStatusIndicator.is())
249 	    xStatusIndicator->setValue(nSteps++);
250 
251     try{
252         // create the xml exporter service and supply the converter component
253         // which implements the document handler
254 	    Sequence < Any > aAnys (2);
255 	    aAnys[0] <<= xConverter;
256 
257 
258         // pretty printing is confusing for some filters so it is disabled by default
259         sal_Bool bPrettyPrint =
260             (msUserData.getLength() > 6 && msUserData[6].equalsIgnoreAsciiCaseAscii("true"));
261 
262         // --> OD 2008-11-25 #b6761284#
263         // export of <text:number> element for <text:list-item> elements are
264         // needed for certain filters.
265         sal_Bool bExportTextNumberElementForListItems =
266                             ( msUserData.getLength() > 7 &&
267                               msUserData[7].equalsIgnoreAsciiCaseAscii("true") );
268         // <--
269 
270         // get the base URI, so we can use relative links
271         OUString aBaseURI;
272         if (aMediaMap.find(OUString::createFromAscii("URL"))->second >>= aBaseURI)
273         {
274             INetURLObject aURLObj(aBaseURI);
275             // base URI in this case is the URI of the actual saving location
276             // aURLObj.removeSegment();
277             aBaseURI = aURLObj.GetMainURL(INetURLObject::NO_DECODE);
278         }
279 
280         // create an XProperty set to configure the exporter for pretty printing
281      	PropertyMapEntry aImportInfoMap[] =
282  	    {
283  		    { MAP_LEN( "UsePrettyPrinting" ), 0, &::getCppuType((const sal_Bool*)0), PropertyAttribute::MAYBEVOID, 0},
284             // --> OD 2008-11-25 #b6761284#
285             { MAP_LEN( "ExportTextNumberElement" ), 0, &::getCppuType((const sal_Bool*)0), PropertyAttribute::MAYBEVOID, 0},
286             // <--
287             { MAP_LEN( "BaseURI" ), 0, &::getCppuType((const OUString*)0), PropertyAttribute::MAYBEVOID, 0},
288      		{ NULL, 0, 0, NULL, 0, 0 }
289  	    };
290 
291  	    Reference< XPropertySet > xInfoSet(
292             GenericPropertySet_CreateInstance( new PropertySetInfo( aImportInfoMap ) ) );
293  	    xInfoSet->setPropertyValue(
294             OUString::createFromAscii( "UsePrettyPrinting" ), makeAny( bPrettyPrint ));
295         // --> OD 2008-11-25 #b6761284#
296         xInfoSet->setPropertyValue(
297                         OUString::createFromAscii( "ExportTextNumberElement" ),
298                         makeAny( bExportTextNumberElementForListItems ));
299         // <--
300  	    xInfoSet->setPropertyValue(
301             OUString::createFromAscii( "BaseURI" ), makeAny( aBaseURI ));
302         aAnys[1] <<= xInfoSet;
303 
304 	    Reference< XExporter > xExporter( mxMSF->createInstanceWithArguments (
305 					   udExport, aAnys ), UNO_QUERY_THROW );
306 
307         // attach to source document
308         xExporter->setSourceDocument( mxDoc );
309 
310         // get XFilter interface
311 	    Reference< XFilter > xFilter( xExporter, UNO_QUERY_THROW );
312 
313         if (xStatusIndicator.is())
314 	        xStatusIndicator->setValue(nSteps++);
315 
316         // call the actual filtering component
317         if (!xFilter->filter(aDescriptor))
318 	    {
319 		    if (xStatusIndicator.is())
320        	    	xStatusIndicator->end();
321             return sal_False;
322         }
323     }
324 #if OSL_DEBUG_LEVEL > 0
325 	catch( Exception& exE )
326 #else
327 	catch( Exception& )
328 #endif
329 	{
330 	    OSL_ENSURE( sal_False, ::rtl::OUStringToOString( exE.Message, RTL_TEXTENCODING_ASCII_US).getStr());
331         if (xStatusIndicator.is())
332             xStatusIndicator->end();
333 	    return sal_False;
334 	}
335 
336     // done
337     if (xStatusIndicator.is())
338         xStatusIndicator->end();
339 	return sal_True;
340 }
341 
filter(const Sequence<::com::sun::star::beans::PropertyValue> & aDescriptor)342 sal_Bool SAL_CALL XmlFilterAdaptor::filter( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
343   throw (RuntimeException)
344 {
345 	return meType == FILTER_EXPORT ? exportImpl ( aDescriptor ) : importImpl ( aDescriptor );
346 }
cancel()347 void SAL_CALL XmlFilterAdaptor::cancel(  )
348 	throw (RuntimeException)
349 {
350 }
351 // XExporter
setSourceDocument(const Reference<::com::sun::star::lang::XComponent> & xDoc)352 void SAL_CALL XmlFilterAdaptor::setSourceDocument( const Reference< ::com::sun::star::lang::XComponent >& xDoc )
353 	throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException)
354 {
355 	meType = FILTER_EXPORT;
356 	mxDoc = xDoc;
357         com::sun::star::uno::Reference< com::sun::star::frame::XModel >rModel ( com::sun::star::uno::Reference< com::sun::star::frame::XModel >::query( xDoc ) );
358 	xModel=rModel;
359 
360 }
361 
362 // XImporter
setTargetDocument(const Reference<::com::sun::star::lang::XComponent> & xDoc)363 void SAL_CALL XmlFilterAdaptor::setTargetDocument( const Reference< ::com::sun::star::lang::XComponent >& xDoc )
364 	throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException)
365 {
366 	meType = FILTER_IMPORT;
367 	mxDoc = xDoc;
368 	//xModel = uno::Reference< frame::XModel >::query( xDoc );
369 }
370 // XInitialization
initialize(const Sequence<Any> & aArguments)371 void SAL_CALL XmlFilterAdaptor::initialize( const Sequence< Any >& aArguments )
372 	throw (Exception, RuntimeException)
373 {
374 	Sequence < PropertyValue > aAnySeq;
375 	sal_Int32 nLength = aArguments.getLength();
376 	if ( nLength && ( aArguments[0] >>= aAnySeq ) )
377 	{
378         comphelper::SequenceAsHashMap aMap(aAnySeq);
379         msFilterName = aMap.getUnpackedValueOrDefault(
380             OUString::createFromAscii("Type"), OUString());
381         msUserData = aMap.getUnpackedValueOrDefault(
382             OUString::createFromAscii("UserData"), Sequence< OUString >());
383         msTemplateName = aMap.getUnpackedValueOrDefault(
384             OUString::createFromAscii("TemplateName"), OUString());
385 	}
386 }
XmlFilterAdaptor_getImplementationName()387 OUString XmlFilterAdaptor_getImplementationName ()
388 	throw (RuntimeException)
389 {
390 	return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.XmlFilterAdaptor" ) );
391 }
392 #define SERVICE_NAME1 "com.sun.star.document.ExportFilter"
393 #define SERVICE_NAME2 "com.sun.star.document.ImportFilter"
XmlFilterAdaptor_supportsService(const OUString & ServiceName)394 sal_Bool SAL_CALL XmlFilterAdaptor_supportsService( const OUString& ServiceName )
395 	throw (RuntimeException)
396 {
397     return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) ) ||
398     	   ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME2 ) );
399 }
XmlFilterAdaptor_getSupportedServiceNames()400 Sequence< OUString > SAL_CALL XmlFilterAdaptor_getSupportedServiceNames(  )
401 	throw (RuntimeException)
402 {
403 	Sequence < OUString > aRet(2);
404     OUString* pArray = aRet.getArray();
405     pArray[0] =  OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) );
406     pArray[1] =  OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME2 ) );
407     return aRet;
408 }
409 #undef SERVICE_NAME1
410 #undef SERVICE_NAME2
411 
XmlFilterAdaptor_createInstance(const Reference<XMultiServiceFactory> & rSMgr)412 Reference< XInterface > SAL_CALL XmlFilterAdaptor_createInstance( const Reference< XMultiServiceFactory > & rSMgr)
413 	throw( Exception )
414 {
415 	return (cppu::OWeakObject*) new XmlFilterAdaptor( rSMgr );
416 }
417 
418 // XServiceInfo
getImplementationName()419 OUString SAL_CALL XmlFilterAdaptor::getImplementationName(  )
420 	throw (RuntimeException)
421 {
422 	return XmlFilterAdaptor_getImplementationName();
423 }
supportsService(const OUString & rServiceName)424 sal_Bool SAL_CALL XmlFilterAdaptor::supportsService( const OUString& rServiceName )
425 	throw (RuntimeException)
426 {
427     return XmlFilterAdaptor_supportsService( rServiceName );
428 }
getSupportedServiceNames()429 Sequence< OUString > SAL_CALL XmlFilterAdaptor::getSupportedServiceNames(  )
430 	throw (RuntimeException)
431 {
432     return XmlFilterAdaptor_getSupportedServiceNames();
433 }
434