1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "docprophandler.hxx"
29 
30 #include <com/sun/star/beans/PropertyAttribute.hpp>
31 #include <com/sun/star/beans/PropertyExistException.hpp>
32 #include <com/sun/star/lang/Locale.hpp>
33 
34 #include <osl/time.h>
35 
36 #include "oox/helper/attributelist.hxx"
37 
38 using namespace ::com::sun::star;
39 
40 namespace oox {
41 namespace docprop {
42 
43 // ------------------------------------------------
44 OOXMLDocPropHandler::OOXMLDocPropHandler( const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< document::XDocumentProperties > xDocProp )
45 : m_xContext( xContext )
46 , m_xDocProp( xDocProp )
47 , m_nState( 0 )
48 , m_nBlock( 0 )
49 , m_nType( 0 )
50 , m_nInBlock( 0 )
51 {
52     if ( !xContext.is() || !xDocProp.is() )
53         throw uno::RuntimeException();
54 }
55 
56 // ------------------------------------------------
57 OOXMLDocPropHandler::~OOXMLDocPropHandler()
58 {
59 }
60 
61 // ------------------------------------------------
62 void OOXMLDocPropHandler::InitNew()
63 {
64     m_nState = 0;
65     m_nBlock = 0;
66     m_aCustomPropertyName = ::rtl::OUString();
67     m_nType = 0;
68     m_nInBlock = 0;
69 }
70 
71 // ------------------------------------------------
72 void OOXMLDocPropHandler::AddCustomProperty( const uno::Any& aAny )
73 {
74     if ( m_aCustomPropertyName.getLength() )
75     {
76         const uno::Reference< beans::XPropertyContainer > xUserProps =
77             m_xDocProp->getUserDefinedProperties();
78         if ( !xUserProps.is() )
79             throw uno::RuntimeException();
80 
81         try
82         {
83             xUserProps->addProperty( m_aCustomPropertyName,
84                     beans::PropertyAttribute::REMOVEABLE, aAny );
85         }
86         catch( beans::PropertyExistException& )
87         {
88             // conflicts with core and extended properties are possible
89         }
90         catch( uno::Exception& )
91         {
92             OSL_ASSERT( "Can not add custom property!" );
93         }
94     }
95 }
96 
97 // ------------------------------------------------
98 util::DateTime OOXMLDocPropHandler::GetDateTimeFromW3CDTF( const ::rtl::OUString& aChars )
99 {
100     oslDateTime aOslDTime = { 0, 0, 0, 0, 0, 0, 0, 0 };
101     sal_Int32 nLen = aChars.getLength();
102     if ( nLen >= 4 )
103     {
104         aOslDTime.Year = (sal_uInt16)aChars.copy( 0, 4 ).toInt32();
105 
106         if ( nLen >= 7 && aChars.getStr()[4] == (sal_Unicode)'-' )
107         {
108             aOslDTime.Month = (sal_uInt16)aChars.copy( 5, 2 ).toInt32();
109 
110             if ( nLen >= 10 && aChars.getStr()[7] == (sal_Unicode)'-' )
111             {
112                 aOslDTime.Day = (sal_uInt16)aChars.copy( 8, 2 ).toInt32();
113 
114                 if ( nLen >= 16 && aChars.getStr()[10] == (sal_Unicode)'T' && aChars.getStr()[13] == (sal_Unicode)':' )
115                 {
116                     aOslDTime.Hours = (sal_uInt16)aChars.copy( 11, 2 ).toInt32();
117                     aOslDTime.Minutes = (sal_uInt16)aChars.copy( 14, 2 ).toInt32();
118 
119                     sal_Int32 nOptTime = 0;
120                     if ( nLen >= 19 && aChars.getStr()[16] == (sal_Unicode)':' )
121                     {
122                         aOslDTime.Seconds = (sal_uInt16)aChars.copy( 17, 2 ).toInt32();
123                         nOptTime += 3;
124                         if ( nLen >= 21 && aChars.getStr()[19] == (sal_Unicode)'.' )
125                         {
126                             aOslDTime.NanoSeconds = (sal_uInt32)(aChars.copy( 20, 1 ).toInt32() * 10e8);
127                             nOptTime += 2;
128                         }
129                     }
130 
131                     sal_Int32 nModif = 0;
132                     if ( nLen >= 16 + nOptTime + 6 )
133                     {
134                         if ( ( aChars.getStr()[16 + nOptTime] == (sal_Unicode)'+' || aChars.getStr()[16 + nOptTime] == (sal_Unicode)'-' )
135                           && aChars.getStr()[16 + nOptTime + 3] == (sal_Unicode)':' )
136 
137                         {
138                             nModif = aChars.copy( 16 + nOptTime + 1, 2 ).toInt32() * 3600;
139                             nModif += aChars.copy( 16 + nOptTime + 4, 2 ).toInt32() * 60;
140                             if ( aChars.getStr()[16 + nOptTime] == (sal_Unicode)'-' )
141                                 nModif *= -1;
142                         }
143                     }
144 
145                     if ( nModif )
146                     {
147                         // convert to UTC time
148                         TimeValue aTmp;
149                         if ( osl_getTimeValueFromDateTime( &aOslDTime, &aTmp ) )
150                         {
151                             aTmp.Seconds += nModif;
152                             osl_getDateTimeFromTimeValue( &aTmp, &aOslDTime );
153                         }
154                     }
155                 }
156             }
157         }
158     }
159 
160     return util::DateTime( (sal_uInt16)( aOslDTime.NanoSeconds / 1e7 ), aOslDTime.Seconds, aOslDTime.Minutes, aOslDTime.Hours, aOslDTime.Day, aOslDTime.Month, aOslDTime.Year );
161 }
162 
163 // ------------------------------------------------
164 uno::Sequence< ::rtl::OUString > OOXMLDocPropHandler::GetKeywordsSet( const ::rtl::OUString& aChars )
165 {
166     if ( aChars.getLength() )
167     {
168         uno::Sequence< ::rtl::OUString > aResult( 20 );
169         sal_Int32 nCounter = 0;
170 
171         const sal_Unicode* pStr = aChars.getStr();
172         for( sal_Int32 nInd = 0; nInd < aChars.getLength() && pStr[nInd] != 0; nInd++ )
173         {
174             switch( pStr[nInd] )
175             {
176                 case (sal_Unicode)' ':
177                 case (sal_Unicode)',':
178                 case (sal_Unicode)';':
179                 case (sal_Unicode)':':
180                 case (sal_Unicode)'\t':
181                     // this is a delimiter
182                     // unfortunately I did not find any specification for the possible delimiters
183                     if ( aResult[nCounter].getLength() )
184                     {
185                         if ( nCounter >= aResult.getLength() )
186                             aResult.realloc( nCounter + 10 );
187                         nCounter++;
188                     }
189                     break;
190 
191                 default:
192                     // this should be a part of keyword
193                         aResult[nCounter] += ::rtl::OUString( (sal_Unicode)pStr[nInd] );
194             }
195         }
196 
197         aResult.realloc( nCounter + 1 );
198         return aResult;
199     }
200 
201     return uno::Sequence< ::rtl::OUString >();
202 }
203 // ------------------------------------------------
204 lang::Locale OOXMLDocPropHandler::GetLanguage( const ::rtl::OUString& aChars )
205 {
206     lang::Locale aResult;
207     if ( aChars.getLength() >= 2 )
208     {
209         aResult.Language = aChars.copy( 0, 2 );
210         if ( aChars.getLength() >= 5 && aChars.getStr()[2] == (sal_Unicode)'-' )
211             aResult.Country = aChars.copy( 3, 2 );
212 
213         // TODO/LATER: the variant could be also detected
214     }
215 
216     return aResult;
217 }
218 
219 // ------------------------------------------------
220 void OOXMLDocPropHandler::UpdateDocStatistic( const ::rtl::OUString& aChars )
221 {
222     uno::Sequence< beans::NamedValue > aSet = m_xDocProp->getDocumentStatistics();
223     ::rtl::OUString aName;
224 
225     switch( m_nBlock )
226     {
227         case EXTPR_TOKEN( Characters ):
228             aName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CharacterCount" ) );
229             break;
230 
231         case EXTPR_TOKEN( Pages ):
232             aName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageCount" ) );
233             break;
234 
235         case EXTPR_TOKEN( Words ):
236             aName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "WordCount" ) );
237             break;
238 
239         case EXTPR_TOKEN( Paragraphs ):
240             aName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParagraphCount" ) );
241             break;
242 
243         default:
244             OSL_ASSERT( "Unexpected statistic!" );
245             break;
246     }
247 
248     if ( aName.getLength() )
249     {
250         sal_Bool bFound = sal_False;
251         sal_Int32 nLen = aSet.getLength();
252         for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
253             if ( aSet[nInd].Name.equals( aName ) )
254             {
255                 aSet[nInd].Value = uno::makeAny( aChars.toInt32() );
256                 bFound = sal_True;
257                 break;
258             }
259 
260         if ( !bFound )
261         {
262             aSet.realloc( nLen + 1 );
263             aSet[nLen].Name = aName;
264             aSet[nLen].Value = uno::makeAny( aChars.toInt32() );
265         }
266 
267         m_xDocProp->setDocumentStatistics( aSet );
268     }
269 }
270 
271 // ------------------------------------------------
272 // com.sun.star.xml.sax.XFastDocumentHandler
273 // ------------------------------------------------
274 void SAL_CALL OOXMLDocPropHandler::startDocument()
275     throw (xml::sax::SAXException, uno::RuntimeException)
276 {
277 }
278 
279 // ------------------------------------------------
280 void SAL_CALL OOXMLDocPropHandler::endDocument()
281     throw (xml::sax::SAXException, uno::RuntimeException)
282 {
283     InitNew();
284 }
285 
286 // ------------------------------------------------
287 void SAL_CALL OOXMLDocPropHandler::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& )
288     throw (xml::sax::SAXException, uno::RuntimeException)
289 {
290 }
291 
292 
293 // com.sun.star.xml.sax.XFastContextHandler
294 // ------------------------------------------------
295 void SAL_CALL OOXMLDocPropHandler::startFastElement( ::sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttribs )
296     throw (xml::sax::SAXException, uno::RuntimeException)
297 {
298     if ( !m_nInBlock && !m_nState )
299     {
300         if ( nElement == COREPR_TOKEN( coreProperties )
301           || nElement == EXTPR_TOKEN( Properties )
302           || nElement == CUSTPR_TOKEN( Properties ) )
303         {
304             m_nState = nElement;
305         }
306         else
307         {
308                 OSL_ASSERT( "Unexpected file format!" );
309         }
310     }
311     else if ( m_nState && m_nInBlock == 1 ) // that tag should contain the property name
312     {
313         // Currently the attributes are ignored for the core properties since the only
314         // known attribute is xsi:type that can only be used with dcterms:created and
315         // dcterms:modified, and this element is allowed currently to have only one value dcterms:W3CDTF
316         m_nBlock = nElement;
317 
318         if ( xAttribs.is() && xAttribs->hasAttribute( XML_name ) )
319             m_aCustomPropertyName = xAttribs->getValue( XML_name );
320     }
321     else if ( m_nState && m_nInBlock && m_nInBlock == 2 && getNamespace( nElement ) == NMSP_officeDocPropsVT )
322     {
323         m_nType = nElement;
324     }
325     else
326     {
327         OSL_ASSERT( "For now unexpected tags are ignored!" );
328     }
329 
330     if ( m_nInBlock == SAL_MAX_INT32 )
331         throw uno::RuntimeException();
332 
333     m_nInBlock++;
334 }
335 
336 // ------------------------------------------------
337 void SAL_CALL OOXMLDocPropHandler::startUnknownElement( const ::rtl::OUString& aNamespace, const ::rtl::OUString& aName, const uno::Reference< xml::sax::XFastAttributeList >& )
338     throw (xml::sax::SAXException, uno::RuntimeException)
339 {
340     ::rtl::OUString aUnknown = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unknown element" ) );
341     aUnknown += aNamespace;
342     aUnknown += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":" ) );
343     aUnknown += aName;
344     OSL_ASSERT( ::rtl::OUStringToOString( aUnknown, RTL_TEXTENCODING_UTF8 ).getStr() );
345 
346     if ( m_nInBlock == SAL_MAX_INT32 )
347         throw uno::RuntimeException();
348 
349     m_nInBlock++;
350 }
351 
352 // ------------------------------------------------
353 void SAL_CALL OOXMLDocPropHandler::endFastElement( ::sal_Int32 )
354     throw (xml::sax::SAXException, uno::RuntimeException)
355 {
356     if ( m_nInBlock )
357     {
358         m_nInBlock--;
359 
360         if ( !m_nInBlock )
361             m_nState = 0;
362         else if ( m_nInBlock == 1 )
363         {
364             m_nBlock = 0;
365             m_aCustomPropertyName = ::rtl::OUString();
366         }
367         else if ( m_nInBlock == 2 )
368             m_nType = 0;
369     }
370 }
371 
372 // ------------------------------------------------
373 void SAL_CALL OOXMLDocPropHandler::endUnknownElement( const ::rtl::OUString&, const ::rtl::OUString& )
374     throw (xml::sax::SAXException, uno::RuntimeException)
375 {
376     if ( m_nInBlock )
377         m_nInBlock--;
378 }
379 
380 // ------------------------------------------------
381 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL OOXMLDocPropHandler::createFastChildContext( ::sal_Int32, const uno::Reference< xml::sax::XFastAttributeList >& )
382     throw (xml::sax::SAXException, uno::RuntimeException)
383 {
384     // Should the arguments be parsed?
385     return uno::Reference< xml::sax::XFastContextHandler >( static_cast< xml::sax::XFastContextHandler* >( this ) );
386 }
387 
388 // ------------------------------------------------
389 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL OOXMLDocPropHandler::createUnknownChildContext( const ::rtl::OUString&, const ::rtl::OUString&, const uno::Reference< xml::sax::XFastAttributeList >& )
390     throw (xml::sax::SAXException, uno::RuntimeException)
391 {
392     return uno::Reference< xml::sax::XFastContextHandler >( static_cast< xml::sax::XFastContextHandler* >( this ) );
393 }
394 
395 // ------------------------------------------------
396 void SAL_CALL OOXMLDocPropHandler::characters( const ::rtl::OUString& aChars )
397     throw (xml::sax::SAXException, uno::RuntimeException)
398 {
399     try
400     {
401         if ( (m_nInBlock == 2) || ((m_nInBlock == 3) && m_nType) )
402         {
403             if ( m_nState == COREPR_TOKEN( coreProperties ) )
404             {
405                 switch( m_nBlock )
406                 {
407                     case COREPR_TOKEN( category ):
408                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "category" ) );
409                         AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type
410                         break;
411 
412                     case COREPR_TOKEN( contentStatus ):
413                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "contentStatus" ) );
414                         AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type
415                         break;
416 
417                     case COREPR_TOKEN( contentType ):
418                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "contentType" ) );
419                         AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type
420                         break;
421 
422                     case COREPR_TOKEN( identifier ):
423                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "identifier" ) );
424                         AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type
425                         break;
426 
427                     case COREPR_TOKEN( version ):
428                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "version" ) );
429                         AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type
430                         break;
431 
432                     case DCT_TOKEN( created ):
433                         if ( aChars.getLength() >= 4 )
434                             m_xDocProp->setCreationDate( GetDateTimeFromW3CDTF( aChars ) );
435                         break;
436 
437                     case DC_TOKEN( creator ):
438                         m_xDocProp->setAuthor( aChars );
439                         break;
440 
441                     case DC_TOKEN( description ):
442                         m_xDocProp->setDescription( aChars );
443                         break;
444 
445                     case COREPR_TOKEN( keywords ):
446                         m_xDocProp->setKeywords( GetKeywordsSet( aChars ) );
447                         break;
448 
449                     case DC_TOKEN( language ):
450                         if ( aChars.getLength() >= 2 )
451                             m_xDocProp->setLanguage( GetLanguage( aChars ) );
452                         break;
453 
454                     case COREPR_TOKEN( lastModifiedBy ):
455                         m_xDocProp->setModifiedBy( aChars );
456                         break;
457 
458                     case COREPR_TOKEN( lastPrinted ):
459                         if ( aChars.getLength() >= 4 )
460                             m_xDocProp->setPrintDate( GetDateTimeFromW3CDTF( aChars ) );
461                         break;
462 
463                     case DCT_TOKEN( modified ):
464                         if ( aChars.getLength() >= 4 )
465                             m_xDocProp->setModificationDate( GetDateTimeFromW3CDTF( aChars ) );
466                         break;
467 
468                     case COREPR_TOKEN( revision ):
469                         try
470                         {
471                             m_xDocProp->setEditingCycles(
472                                 static_cast<sal_Int16>(aChars.toInt32()) );
473                         }
474                         catch (lang::IllegalArgumentException &)
475                         {
476                             // ignore
477                         }
478                         break;
479 
480                     case DC_TOKEN( subject ):
481                         m_xDocProp->setSubject( aChars );
482                         break;
483 
484                     case DC_TOKEN( title ):
485                         m_xDocProp->setTitle( aChars );
486                         break;
487 
488                     default:
489                         OSL_ASSERT( "Unexpected core property!" );
490                 }
491             }
492             else if ( m_nState == EXTPR_TOKEN( Properties ) )
493             {
494                 switch( m_nBlock )
495                 {
496                     case EXTPR_TOKEN( Application ):
497                         m_xDocProp->setGenerator( aChars );
498                         break;
499 
500                     case EXTPR_TOKEN( Template ):
501                         m_xDocProp->setTemplateName( aChars );
502                         break;
503 
504                     case EXTPR_TOKEN( TotalTime ):
505                         try
506                         {
507                             m_xDocProp->setEditingDuration( aChars.toInt32() );
508                         }
509                         catch (lang::IllegalArgumentException &)
510                         {
511                             // ignore
512                         }
513                         break;
514 
515                     case EXTPR_TOKEN( Characters ):
516                     case EXTPR_TOKEN( Pages ):
517                     case EXTPR_TOKEN( Words ):
518                     case EXTPR_TOKEN( Paragraphs ):
519                         UpdateDocStatistic( aChars );
520                         break;
521 
522                     case EXTPR_TOKEN( HyperlinksChanged ):
523                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HyperlinksChanged" ) );
524                         AddCustomProperty( uno::makeAny( aChars.toBoolean() ) ); // the property has boolean type
525                         break;
526 
527                     case EXTPR_TOKEN( LinksUpToDate ):
528                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LinksUpToDate" ) );
529                         AddCustomProperty( uno::makeAny( aChars.toBoolean() ) ); // the property has boolean type
530                         break;
531 
532                     case EXTPR_TOKEN( ScaleCrop ):
533                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScaleCrop" ) );
534                         AddCustomProperty( uno::makeAny( aChars.toBoolean() ) ); // the property has boolean type
535                         break;
536 
537                     case EXTPR_TOKEN( SharedDoc ):
538                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ShareDoc" ) );
539                         AddCustomProperty( uno::makeAny( aChars.toBoolean() ) ); // the property has boolean type
540                         break;
541 
542                     case EXTPR_TOKEN( DocSecurity ):
543                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocSecurity" ) );
544                         AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // the property has sal_Int32 type
545                         break;
546 
547                     case EXTPR_TOKEN( HiddenSlides ):
548                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HiddenSlides" ) );
549                         AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // the property has sal_Int32 type
550                         break;
551 
552                     case EXTPR_TOKEN( MMClips ):
553                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MMClips" ) );
554                         AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // the property has sal_Int32 type
555                         break;
556 
557                     case EXTPR_TOKEN( Notes ):
558                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Notes" ) );
559                         AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // the property has sal_Int32 type
560                         break;
561 
562                     case EXTPR_TOKEN( Slides ):
563                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Slides" ) );
564                         AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // the property has sal_Int32 type
565                         break;
566 
567                     case EXTPR_TOKEN( AppVersion ):
568                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AppVersion" ) );
569                         AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type
570                         break;
571 
572                     case EXTPR_TOKEN( Company ):
573                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Company" ) );
574                         AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type
575                         break;
576 
577                     case EXTPR_TOKEN( HyperlinkBase ):
578                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HyperlinkBase" ) );
579                         AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type
580                         break;
581 
582                     case EXTPR_TOKEN( Manager ):
583                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Manager" ) );
584                         AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type
585                         break;
586 
587                     case EXTPR_TOKEN( PresentationFormat ):
588                         m_aCustomPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PresentationFormat" ) );
589                         AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type
590                         break;
591 
592                     case EXTPR_TOKEN( CharactersWithSpaces ):
593                     case EXTPR_TOKEN( Lines ):
594                     case EXTPR_TOKEN( DigSig ):
595                     case EXTPR_TOKEN( HeadingPairs ):
596                     case EXTPR_TOKEN( HLinks ):
597                     case EXTPR_TOKEN( TitlesOfParts ):
598                         // ignored during the import currently
599                         break;
600 
601                     default:
602                         OSL_ASSERT( "Unexpected extended property!" );
603                 }
604             }
605             else if ( m_nState == CUSTPR_TOKEN( Properties ) )
606             {
607                 if ( m_nBlock == CUSTPR_TOKEN( property ) )
608                 {
609                     // this is a custom property
610                     switch( m_nType )
611                     {
612                         case VT_TOKEN( bool ):
613                             AddCustomProperty( uno::makeAny( aChars.toBoolean() ) );
614                             break;
615 
616                         case VT_TOKEN( bstr ):
617                         case VT_TOKEN( lpstr ):
618                         case VT_TOKEN( lpwstr ):
619                             AddCustomProperty( uno::makeAny( AttributeConversion::decodeXString( aChars ) ) ); // the property has string type
620                             break;
621 
622                         case VT_TOKEN( date ):
623                         case VT_TOKEN( filetime ):
624                             AddCustomProperty( uno::makeAny( GetDateTimeFromW3CDTF( aChars ) ) );
625 
626                         case VT_TOKEN( i1 ):
627                         case VT_TOKEN( i2 ):
628                             AddCustomProperty( uno::makeAny( (sal_Int16)aChars.toInt32() ) );
629                             break;
630 
631                         case VT_TOKEN( i4 ):
632                         case VT_TOKEN( int ):
633                             AddCustomProperty( uno::makeAny( aChars.toInt32() ) );
634                             break;
635 
636                         case VT_TOKEN( i8 ):
637                             AddCustomProperty( uno::makeAny( aChars.toInt64() ) );
638                             break;
639 
640                         case VT_TOKEN( r4 ):
641                             AddCustomProperty( uno::makeAny( aChars.toFloat() ) );
642                             break;
643 
644                         case VT_TOKEN( r8 ):
645                             AddCustomProperty( uno::makeAny( aChars.toDouble() ) );
646                             break;
647 
648                         default:
649                             // all the other types are ignored;
650                             break;
651                     }
652                 }
653                 else
654                 {
655                     OSL_ASSERT( "Unexpected tag in custom property!" );
656                 }
657             }
658         }
659     }
660     catch( uno::RuntimeException& )
661     {
662         throw;
663     }
664     catch( xml::sax::SAXException& )
665     {
666         throw;
667     }
668     catch( uno::Exception& e )
669     {
670         throw xml::sax::SAXException(
671             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Error while setting document property!" ) ),
672             uno::Reference< uno::XInterface >(),
673             uno::makeAny( e ) );
674     }
675 }
676 
677 // ------------------------------------------------
678 void SAL_CALL OOXMLDocPropHandler::ignorableWhitespace( const ::rtl::OUString& )
679     throw (xml::sax::SAXException, uno::RuntimeException)
680 {
681 }
682 
683 // ------------------------------------------------
684 void SAL_CALL OOXMLDocPropHandler::processingInstruction( const ::rtl::OUString&, const ::rtl::OUString& )
685     throw (xml::sax::SAXException, uno::RuntimeException)
686 {
687 }
688 
689 } // namespace docprop
690 } // namespace oox
691 
692