xref: /trunk/main/svx/workben/msview/xmlconfig.cxx (revision f6e50924)
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 
25 // MARKER(update_precomp.py): autogen include statement, do not remove
26 #include "precompiled_svx.hxx"
27 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
28 #include <com/sun/star/xml/sax/InputSource.hpp>
29 #include <com/sun/star/xml/sax/XParser.hpp>
30 #include <com/sun/star/xml/sax/SAXParseException.hpp>
31 #include <com/sun/star/io/IOException.hpp>
32 #include <cppuhelper/implbase1.hxx>
33 #include <comphelper/processfactory.hxx>
34 #include <unotools/ucbstreamhelper.hxx>
35 #include <unotools/streamwrap.hxx>
36 #include <tools/debug.hxx>
37 #include "comphelper/anytostring.hxx"
38 #include "cppuhelper/exc_hlp.hxx"
39 #include "rtl/ref.hxx"
40 
41 #include <svx/msdffimp.hxx>
42 
43 #include "xmlconfig.hxx"
44 
45 #include <stdio.h>
46 #include <ctype.h>
47 #include <stack>
48 
49 using ::rtl::OUString;
50 using ::com::sun::star::io::XInputStream;
51 using ::com::sun::star::io::IOException;
52 
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::xml::sax;
55 
56 ///////////////////////////////////////////////////////////////////////
57 
58 AtomConfigMap gAtomConfigMap;
59 
60 ///////////////////////////////////////////////////////////////////////
61 
62 class ConfigHandler : public ::cppu::WeakAggImplHelper1<XDocumentHandler>
63 {
64 public:
65 	// XDocumentHandler
66 	virtual void SAL_CALL startDocument(void) throw( SAXException, RuntimeException );
67 	virtual void SAL_CALL endDocument(void) throw( SAXException, RuntimeException );
68 	virtual void SAL_CALL startElement(const OUString& aName, const Reference< XAttributeList > & xAttribs) throw( SAXException, RuntimeException );
69 	virtual void SAL_CALL endElement(const OUString& aName) throw( SAXException, RuntimeException );
70 	virtual void SAL_CALL characters(const OUString& aChars) throw( SAXException, RuntimeException );
71 	virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) throw( SAXException, RuntimeException );
72 	virtual void SAL_CALL processingInstruction(const OUString& aTarget, const OUString& aData) throw( SAXException, RuntimeException );
73 	virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator) throw( SAXException, RuntimeException );
74 
75 private:
76 	void errorThrow( const OUString& rErrorMessage ) throw (SAXException );
77 	ElementConfigType parseType( const OUString& rErrorMessage ) throw ( SAXException );
78 	void addElement( ElementConfigPtr& rElementConfig ) throw ( SAXException );
79 	OUString getAttribute( const Reference< XAttributeList > & xAttribs, const sal_Char* pName ) throw( SAXException );
80 
81 	ElementConfigPtr importAtomConfig( const Reference< XAttributeList > & xAttribs, bool bIsContainer ) throw( SAXException );
82 	ElementConfigPtr importElementConfig( const Reference< XAttributeList > & xAttribs ) throw( SAXException );
83 	ElementConfigPtr importSwitchConfig( const Reference< XAttributeList > & xAttribs ) throw( SAXException );
84 	ElementConfigPtr importCaseConfig( const Reference< XAttributeList > & xAttribs ) throw( SAXException );
85 	ElementConfigPtr importValueElementConfig( const Reference< XAttributeList > & xAttribs ) throw( SAXException );
86 
87 	std::stack< ElementConfigPtr > maElementStack;
88 };
89 
errorThrow(const OUString & rErrorMessage)90 void ConfigHandler::errorThrow( const OUString& rErrorMessage ) throw (SAXException )
91 {
92 	Reference< XInterface > aContext;
93 	Any aWrappedException;
94     throw SAXException(rErrorMessage, aContext, aWrappedException);
95 }
96 
parseType(const OUString & sType)97 ElementConfigType ConfigHandler::parseType( const OUString& sType ) throw (SAXException )
98 {
99 	if( sType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("uint") ) )
100 	{
101 		return ECT_UINT;
102 	}
103 	else if( sType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("byte") ) )
104 	{
105 		return ECT_BYTE;
106 	}
107 	else if( sType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unistring") ) )
108 	{
109 		return ECT_UNISTRING;
110 	}
111 	else if( sType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("float") ) )
112 	{
113 		return ETC_FLOAT;
114 	}
115 	else if( sType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("hexdump") ) )
116 	{
117 	}
118 	else
119 	{
120 		OUString aMessage( RTL_CONSTASCII_USTRINGPARAM( "unknown type: " ) );
121 		aMessage += sType;
122 		errorThrow( aMessage );
123 	}
124 
125 	return ECT_HEXDUMP;
126 }
127 
addElement(ElementConfigPtr & rElementConfig)128 void ConfigHandler::addElement( ElementConfigPtr& rElementConfig ) throw ( SAXException )
129 {
130 	ElementConfigContainer* pParent = dynamic_cast< ElementConfigContainer* >( maElementStack.top().get() );
131 
132 	if( !pParent )
133 		errorThrow( OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal parent for element" ) ) );
134 
135 
136 	pParent->addElementConfig( rElementConfig );
137 }
138 
getAttribute(const Reference<XAttributeList> & xAttribs,const sal_Char * pName)139 OUString ConfigHandler::getAttribute( const Reference< XAttributeList > & xAttribs, const sal_Char* pName ) throw( SAXException )
140 {
141 	OUString aName( OUString::createFromAscii( pName ) );
142 
143 	const sal_Int16 nAttrCount = xAttribs.is() ? xAttribs->getLength() : 0;
144 	sal_Int16 i;
145 	for(i=0; i < nAttrCount; i++)
146 	{
147 		if( xAttribs->getNameByIndex( i ) == aName )
148 			return xAttribs->getValueByIndex( i );
149 	}
150 
151 	OUString aMessage( RTL_CONSTASCII_USTRINGPARAM( "missing required attribute: ") );
152 	aMessage += aName;
153 	errorThrow( aMessage );
154 
155 	return OUString();
156 }
157 
startDocument(void)158 void SAL_CALL ConfigHandler::startDocument(void) throw( SAXException, RuntimeException )
159 {
160 }
161 
endDocument(void)162 void SAL_CALL ConfigHandler::endDocument(void) throw( SAXException, RuntimeException )
163 {
164 }
165 
startElement(const OUString & aName,const Reference<XAttributeList> & xAttribs)166 void SAL_CALL ConfigHandler::startElement(const OUString& aName, const Reference< XAttributeList > & xAttribs) throw( SAXException, RuntimeException )
167 {
168 	ElementConfigPtr pElement;
169 
170 	if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "config" ) ) )
171 	{
172 		return;
173 	}
174 
175 	if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "container" ) ) )
176 	{
177 		pElement = importAtomConfig( xAttribs, true );
178 	}
179 	else if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "atom" ) ) )
180 	{
181 		pElement = importAtomConfig( xAttribs, false );
182 	}
183 	else if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "element" ) ) )
184 	{
185 		pElement = importElementConfig( xAttribs );
186 	}
187 	else if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "value" ) ) )
188 	{
189 		pElement = importValueElementConfig( xAttribs );
190 	}
191 	else if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "switch" ) ) )
192 	{
193 		pElement = importSwitchConfig( xAttribs );
194 	}
195 	else if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "case" ) ) )
196 	{
197 		pElement = importCaseConfig( xAttribs );
198 	}
199 
200 	if( !pElement.get() )
201 	{
202 		OUString aMessage( OUString( RTL_CONSTASCII_USTRINGPARAM("unknown config element: ")) );
203 		aMessage += aName;
204 		errorThrow( aMessage  );
205 	}
206 
207 	maElementStack.push( pElement );
208 }
209 
toInt(const OUString & rText)210 sal_Int32 toInt( const OUString& rText )
211 {
212 	if( rText.compareToAscii("0x",2) == 0)
213 	{
214 		sal_Int32 nValue = 0;
215 		const sal_Unicode *p = rText;
216 		p += 2;
217 		sal_Int32 nLength = rText.getLength() - 2;
218 		while( (nLength--) > 0 )
219 		{
220 			nValue <<= 4;
221 			if( *p >= '0' && *p <= '9' )
222 			{
223 				nValue += *p - '0';
224 			}
225 			else if( *p >= 'a' && *p <= 'f' )
226 			{
227 				nValue += *p - ('a' - 10);
228 			}
229 			else if( *p >= 'A' && *p <= 'F' )
230 			{
231 				nValue += *p - ('A' - 10 );
232 			}
233 			p++;
234 		}
235 
236 		return nValue;
237 	}
238 	else
239 	{
240 		return rText.toInt32();
241 	}
242 }
243 
importAtomConfig(const Reference<XAttributeList> & xAttribs,bool bIsContainer)244 ElementConfigPtr ConfigHandler::importAtomConfig( const Reference< XAttributeList > & xAttribs, bool bIsContainer ) throw (SAXException)
245 {
246 	if( !maElementStack.empty() )
247 		errorThrow( OUString( RTL_CONSTASCII_USTRINGPARAM("atom elements must be root" ) ) );
248 
249 	ElementConfigPtr aPtr( new AtomConfig( getAttribute(xAttribs,"name"), bIsContainer ) );
250 	gAtomConfigMap[ (UINT16)toInt(getAttribute(xAttribs,"id"))] = aPtr;
251 	return aPtr;
252 }
253 
importElementConfig(const Reference<XAttributeList> & xAttribs)254 ElementConfigPtr ConfigHandler::importElementConfig( const Reference< XAttributeList > & xAttribs ) throw (SAXException)
255 {
256 	ElementConfigType nType = parseType( getAttribute( xAttribs, "type" ) );
257 	ElementConfigPtr pElementConfig( new ElementConfigContainer( getAttribute( xAttribs, "name" ), nType ) );
258 	addElement( pElementConfig );
259 	return pElementConfig;
260 }
261 
importValueElementConfig(const Reference<XAttributeList> & xAttribs)262 ElementConfigPtr ConfigHandler::importValueElementConfig( const Reference< XAttributeList > & xAttribs ) throw (SAXException)
263 {
264 	ElementConfigPtr pElementConfig( new ElementValueConfig( getAttribute( xAttribs, "name" ), getAttribute( xAttribs, "value" ) ) );
265 	addElement( pElementConfig );
266 	return pElementConfig;
267 }
268 
importSwitchConfig(const Reference<XAttributeList> & xAttribs)269 ElementConfigPtr ConfigHandler::importSwitchConfig( const Reference< XAttributeList > & xAttribs ) throw (SAXException)
270 {
271 	ElementConfigType nType = parseType( getAttribute( xAttribs, "type" ) );
272 	ElementConfigPtr pElementConfig( new SwitchElementConfig( nType ) );
273 	addElement( pElementConfig );
274 	return pElementConfig;
275 }
276 
importCaseConfig(const Reference<XAttributeList> & xAttribs)277 ElementConfigPtr ConfigHandler::importCaseConfig( const Reference< XAttributeList > & xAttribs ) throw (SAXException)
278 {
279 	ElementConfigPtr pElementConfig( new CaseElementConfig( getAttribute( xAttribs, "value" ) ) );
280 	addElement( pElementConfig );
281 	return pElementConfig;
282 }
283 
endElement(const OUString & aName)284 void SAL_CALL ConfigHandler::endElement(const OUString& aName) throw( SAXException, RuntimeException )
285 {
286 	if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "config" ) ) )
287 	{
288 		return;
289 	}
290 
291 	maElementStack.pop();
292 }
293 
characters(const OUString & aChars)294 void SAL_CALL ConfigHandler::characters(const OUString& aChars) throw( SAXException, RuntimeException )
295 {
296 }
297 
ignorableWhitespace(const OUString & aWhitespaces)298 void SAL_CALL ConfigHandler::ignorableWhitespace(const OUString& aWhitespaces) throw( SAXException, RuntimeException )
299 {
300 }
301 
processingInstruction(const OUString & aTarget,const OUString & aData)302 void SAL_CALL ConfigHandler::processingInstruction(const OUString& aTarget, const OUString& aData) throw( SAXException, RuntimeException )
303 {
304 }
305 
setDocumentLocator(const Reference<XLocator> & xLocator)306 void SAL_CALL ConfigHandler::setDocumentLocator(const Reference< XLocator > & xLocator) throw( SAXException, RuntimeException )
307 {
308 }
309 
load_config(const OUString & rPath)310 void load_config( const OUString& rPath )
311 {
312 	try
313 	{
314 		// create stream
315 		SvStream*	pIStm = ::utl::UcbStreamHelper::CreateStream( rPath, STREAM_READ );
316 		Reference<XInputStream> xInputStream( new utl::OInputStreamWrapper( pIStm, sal_True ) );
317 
318 		// prepare ParserInputSrouce
319 		InputSource aParserInput;
320 		aParserInput.sSystemId = rPath;
321 		aParserInput.aInputStream = xInputStream;
322 
323 		// get parser
324 		Reference< XParser > xParser(
325 			comphelper::getProcessServiceFactory()->createInstance(
326 				OUString::createFromAscii("com.sun.star.xml.sax.Parser") ),
327 			UNO_QUERY_THROW );
328 
329 		// get filter
330 		ConfigHandler* pConfigHandler = new ConfigHandler();
331 		Reference< XDocumentHandler > xFilter( pConfigHandler );
332 
333 		// connect parser and filter
334 		xParser->setDocumentHandler( xFilter );
335 
336 		// finally, parser the stream
337 		xParser->parseStream( aParserInput );
338 	}
339 	catch( Exception& r )
340 	{
341 		DBG_ERROR(
342 			(rtl::OString("load_config(), "
343                      "exception caught: ") +
344              rtl::OUStringToOString(
345                  comphelper::anyToString( cppu::getCaughtException() ),
346                  RTL_TEXTENCODING_UTF8 )).getStr() );
347 
348 		(void)r;
349 	}
350 }
351 
352 ///////////////////////////////////////////////////////////////////////
353 
format(SvStream & rStream,sal_Size & nLength) const354 rtl::OUString ElementConfig::format( SvStream& rStream, sal_Size& nLength ) const
355 {
356 	OUString aRet;
357 	if( maName.getLength() )
358 	{
359 		aRet += maName;
360 		aRet += OUString( RTL_CONSTASCII_USTRINGPARAM( " = " ) );
361 	}
362 
363 	switch( mnType )
364 	{
365 	case ECT_BYTE:		aRet += dump_byte( rStream, nLength ); break;
366 	case ECT_UINT:		aRet += dump_uint( rStream, nLength ); break;
367 	case ECT_UNISTRING:	aRet += dump_unistring( rStream, nLength ); break;
368 	case ETC_FLOAT:		aRet += dump_float( rStream, nLength ); break;
369 	case ECT_HEXDUMP:
370 	default:			aRet += dump_hex( rStream, nLength ); break;
371 	}
372 
373 	return aRet;
374 }
375 
dump_hex(SvStream & rStream,sal_Size & nLength)376 rtl::OUString ElementConfig::dump_hex( SvStream& rStream, sal_Size& nLength )
377 {
378 	char buffer[128];
379 	OUString aOut, aEmpty;
380 	OUString aHex, aAscii;
381 	sal_Char c;
382 	int nRow = 0;
383 	while( nLength && (rStream.GetError() == 0) )
384 	{
385 		rStream >> c;
386 		nLength--;
387 
388 		unsigned int i = c;
389 		i &= 0xff;
390 		sprintf( buffer, "%02x ", i );
391 		aHex += OUString::createFromAscii( buffer );
392 
393 		if( !isprint( c ) )
394 			c = '.';
395 
396 		aAscii += OUString( (sal_Unicode) c );
397 		nRow++;
398 
399 		if( (nRow == 16) || (nLength==0) )
400 		{
401 			while( aHex.getLength() < (16*3) )
402 				aHex += OUString( RTL_CONSTASCII_USTRINGPARAM(" ") );
403 			aOut += aHex;
404 			aOut += aAscii;
405 			aOut += OUString( RTL_CONSTASCII_USTRINGPARAM( "\n\r" ) );
406 			aHex = aEmpty;
407 			aAscii = aEmpty;
408 			nRow = 0;
409 		}
410 	}
411 
412 	aOut += aHex;
413 	aOut += aAscii;
414 
415 	return aOut;
416 }
417 
dump_byte(SvStream & rStream,sal_Size & nLength)418 rtl::OUString ElementConfig::dump_byte( SvStream& rStream, sal_Size& nLength )
419 {
420 	OUString aRet;
421 	if( nLength >= sizeof(sal_Char) )
422 	{
423 		sal_Char c;
424 		rStream >> c;
425 
426 		char buffer[128];
427 		sprintf( buffer, "%u", (int)c );
428 		aRet += OUString::createFromAscii( buffer );
429 		nLength -= sizeof(sal_Char);
430 	}
431 
432 	return aRet;
433 }
434 
dump_uint(SvStream & rStream,sal_Size & nLength)435 rtl::OUString ElementConfig::dump_uint( SvStream& rStream, sal_Size& nLength )
436 {
437 	OUString aRet;
438 	if( nLength >= sizeof( sal_uInt32 ) )
439 	{
440 		sal_uInt32 c;
441 		rStream >> c;
442 
443 		char buffer[128];
444 		sprintf( buffer, "%u", c );
445 		aRet += OUString::createFromAscii( buffer );
446 		nLength-= sizeof( sal_uInt32 );
447 	}
448 
449 	return aRet;
450 }
451 
dump_unistring(SvStream & rStream,sal_Size & nLength)452 rtl::OUString ElementConfig::dump_unistring( SvStream& rStream, sal_Size& nLength )
453 {
454 	String aString;
455 	SvxMSDffManager::MSDFFReadZString( rStream, aString, nLength, sal_True );
456 	nLength = 0;
457 	return aString;
458 }
459 
dump_float(SvStream & rStream,sal_Size & nLength)460 rtl::OUString ElementConfig::dump_float( SvStream& rStream, sal_Size& nLength )
461 {
462 	OUString aRet;
463 	if( nLength >= sizeof( float ) )
464 	{
465 		float c;
466 		rStream >> c;
467 
468 		char buffer[128];
469 		sprintf( buffer, "%g", (double)c );
470 		aRet += OUString::createFromAscii( buffer );
471 		nLength-= sizeof( float );
472 	}
473 
474 	return aRet;
475 }
476 
477 ///////////////////////////////////////////////////////////////////////
478 
format(SvStream & rStream,sal_Size & nLength) const479 rtl::OUString ElementConfigContainer::format( SvStream& rStream, sal_Size& nLength ) const
480 {
481 	OUString aRet;
482 
483 	if( getType() == ETC_CONTAINER )
484 	{
485 
486 		ElementConfigList::const_iterator aIter( maElementConfigList.begin() );
487 		const ElementConfigList::const_iterator aEnd( maElementConfigList.end() );
488 		while( (aIter != aEnd) && (nLength > 0) )
489 		{
490 			aRet += (*aIter++)->format( rStream, nLength );
491 			if( (aIter != aEnd) || (nLength != 0) )
492 				aRet += OUString( RTL_CONSTASCII_USTRINGPARAM( "\n\r" ) );
493 		}
494 
495 		if( nLength )
496 			aRet += ElementConfig::dump_hex( rStream, nLength );
497 	}
498 	else
499 	{
500 		aRet = getName();
501 		if( aRet.getLength() )
502 			aRet += OUString( RTL_CONSTASCII_USTRINGPARAM( " = " ) );
503 
504 		OUString aValue;
505 		switch( getType() )
506 		{
507 		case ECT_BYTE:		aValue = dump_byte( rStream, nLength ); break;
508 		case ECT_UINT:		aValue = dump_uint( rStream, nLength ); break;
509 		case ECT_UNISTRING:	aValue = dump_unistring( rStream, nLength ); break;
510 		case ETC_FLOAT:		aValue = dump_float( rStream, nLength ); break;
511 		case ECT_HEXDUMP:
512 		default:			aValue = dump_hex( rStream, nLength ); break;
513 		}
514 
515 		if( aValue.getLength() )
516 		{
517 			if( !maElementConfigList.empty() )
518 			{
519 				ElementConfigList::const_iterator aIter( maElementConfigList.begin() );
520 				const ElementConfigList::const_iterator aEnd( maElementConfigList.end() );
521 				while( (aIter != aEnd) && (nLength > 0) )
522 				{
523 					ElementValueConfig* pValue = dynamic_cast< ElementValueConfig* >( (*aIter++).get() );
524 					if( pValue && pValue->getValue() == aValue )
525 					{
526 						aValue = pValue->getName();
527 						break;
528 					}
529 				}
530 			}
531 		}
532 		else
533 		{
534 			aValue = OUString( RTL_CONSTASCII_USTRINGPARAM("<empty!?>") );
535 		}
536 
537 		aRet += aValue;
538 	}
539 
540 	return aRet;
541 }
542 
543 ///////////////////////////////////////////////////////////////////////
544 
format(SvStream & rStream,sal_Size & nLength) const545 rtl::OUString SwitchElementConfig::format( SvStream& rStream, sal_Size& nLength ) const
546 {
547 	OUString aValue;
548 
549 	switch( getType() )
550 	{
551 	case ECT_BYTE:			aValue = dump_byte( rStream, nLength );	break;
552 	case ECT_UINT:			aValue = dump_uint( rStream, nLength ); break;
553 	case ETC_FLOAT:			aValue = dump_float( rStream, nLength ); break;
554 	case ECT_UNISTRING:		aValue = dump_unistring( rStream, nLength ); break;
555 	}
556 
557 	if( aValue.getLength()  )
558 	{
559 		ElementConfigList::const_iterator aIter( maElementConfigList.begin() );
560 		const ElementConfigList::const_iterator aEnd( maElementConfigList.end() );
561 		while( (aIter != aEnd) && (nLength > 0) )
562 		{
563 			CaseElementConfig* pCase = dynamic_cast< CaseElementConfig* >( (*aIter++).get() );
564 			if( pCase && pCase->getValue() == aValue )
565 				return pCase->format( rStream, nLength );
566 		}
567 	}
568 
569 	return ElementConfig::dump_hex( rStream, nLength );
570 }
571 
572