xref: /AOO41X/main/svx/workben/msview/xmlconfig.cxx (revision f6e50924346d0b8c0b07c91832a97665dd718b0c)
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