LCOV - code coverage report
Current view: top level - xmloff/source/meta - xmlversion.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 9 200 4.5 %
Date: 2014-11-03 Functions: 2 17 11.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <com/sun/star/embed/ElementModes.hpp>
      21             : #include <unotools/streamwrap.hxx>
      22             : #include <xmlversion.hxx>
      23             : #include <xmloff/xmlmetae.hxx>
      24             : 
      25             : #include <xmloff/xmltoken.hxx>
      26             : #include <comphelper/processfactory.hxx>
      27             : #include <com/sun/star/io/XActiveDataSource.hpp>
      28             : #include <com/sun/star/io/XOutputStream.hpp>
      29             : #include <com/sun/star/util/DateTime.hpp>
      30             : #include <com/sun/star/util/MeasureUnit.hpp>
      31             : #include <com/sun/star/xml/sax/InputSource.hpp>
      32             : #include <com/sun/star/xml/sax/Parser.hpp>
      33             : #include <com/sun/star/xml/sax/Writer.hpp>
      34             : 
      35             : using namespace ::com::sun::star::xml::sax;
      36             : using namespace ::com::sun::star::uno;
      37             : using namespace ::com::sun::star;
      38             : 
      39             : const char XMLN_VERSIONSLIST[] = "VersionList.xml";
      40             : 
      41             : // #110897#
      42           0 : XMLVersionListExport::XMLVersionListExport(
      43             :     const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > xContext,
      44             :     const com::sun::star::uno::Sequence < com::sun::star::util::RevisionTag >& rVersions,
      45             :     const OUString &rFileName,
      46             :     Reference< XDocumentHandler > &rHandler )
      47             : :   SvXMLExport( xContext, "", rFileName, util::MeasureUnit::CM, rHandler ),
      48           0 :     maVersions( rVersions )
      49             : {
      50           0 :     _GetNamespaceMap().AddAtIndex( XML_NAMESPACE_DC_IDX, xmloff::token::GetXMLToken(xmloff::token::XML_NP_DC),
      51           0 :                                    xmloff::token::GetXMLToken(xmloff::token::XML_N_DC), XML_NAMESPACE_DC );
      52           0 :     _GetNamespaceMap().AddAtIndex( XML_NAMESPACE_FRAMEWORK_IDX, xmloff::token::GetXMLToken(xmloff::token::XML_NP_VERSIONS_LIST),
      53           0 :                                    xmloff::token::GetXMLToken(xmloff::token::XML_N_VERSIONS_LIST), XML_NAMESPACE_FRAMEWORK );
      54           0 : }
      55             : 
      56           0 : sal_uInt32 XMLVersionListExport::exportDoc( enum ::xmloff::token::XMLTokenEnum )
      57             : {
      58           0 :     GetDocHandler()->startDocument();
      59             : 
      60           0 :     addChaffWhenEncryptedStorage();
      61             : 
      62           0 :     sal_uInt16 nPos = _GetNamespaceMap().GetIndexByKey( XML_NAMESPACE_DC );
      63             : 
      64           0 :     AddAttribute( XML_NAMESPACE_NONE, _GetNamespaceMap().GetAttrNameByIndex( nPos ),
      65           0 :                              _GetNamespaceMap().GetNameByIndex ( nPos ) );
      66             : 
      67           0 :     nPos = _GetNamespaceMap().GetIndexByKey( XML_NAMESPACE_FRAMEWORK );
      68           0 :     AddAttribute( XML_NAMESPACE_NONE, _GetNamespaceMap().GetAttrNameByIndex( nPos ),
      69           0 :                              _GetNamespaceMap().GetNameByIndex ( nPos ) );
      70             : 
      71             :     {
      72             :         // the following object will write all collected attributes in its dtor
      73           0 :         SvXMLElementExport aRoot( *this, XML_NAMESPACE_FRAMEWORK, xmloff::token::XML_VERSION_LIST, true, true );
      74             : 
      75           0 :         for ( sal_Int32 n=0; n<maVersions.getLength(); n++ )
      76             :         {
      77           0 :             const util::RevisionTag& rInfo = maVersions[n];
      78             :             AddAttribute( XML_NAMESPACE_FRAMEWORK,
      79             :                           xmloff::token::XML_TITLE,
      80           0 :                           OUString( rInfo.Identifier ) );
      81             :             AddAttribute( XML_NAMESPACE_FRAMEWORK,
      82             :                           xmloff::token::XML_COMMENT,
      83           0 :                           OUString( rInfo.Comment ) );
      84             :             AddAttribute( XML_NAMESPACE_FRAMEWORK,
      85             :                           xmloff::token::XML_CREATOR,
      86           0 :                           OUString( rInfo.Author ) );
      87             : 
      88             :             OUString aDateStr =
      89           0 :                 SvXMLMetaExport::GetISODateTimeString( rInfo.TimeStamp );
      90             : 
      91           0 :             AddAttribute( XML_NAMESPACE_DC, xmloff::token::XML_DATE_TIME, aDateStr );
      92             : 
      93             :             // the following object will write all collected attributes in its dtor
      94           0 :             SvXMLElementExport aEntry( *this, XML_NAMESPACE_FRAMEWORK, xmloff::token::XML_VERSION_ENTRY, true, true );
      95           0 :         }
      96             :     }
      97           0 :     GetDocHandler()->endDocument();
      98           0 :     return 0;
      99             : }
     100             : 
     101           0 : XMLVersionListImport::XMLVersionListImport(
     102             :     const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > xContext,
     103             :     com::sun::star::uno::Sequence < com::sun::star::util::RevisionTag >& rVersions )
     104             : :   SvXMLImport(xContext, ""),
     105           0 :     maVersions( rVersions )
     106             : {
     107           0 :     GetNamespaceMap().AddAtIndex( XML_NAMESPACE_FRAMEWORK_IDX, xmloff::token::GetXMLToken(xmloff::token::XML_NP_VERSIONS_LIST),
     108           0 :                                   xmloff::token::GetXMLToken(xmloff::token::XML_N_VERSIONS_LIST), XML_NAMESPACE_FRAMEWORK );
     109           0 : }
     110             : 
     111           0 : XMLVersionListImport::~XMLVersionListImport( void ) throw()
     112           0 : {}
     113             : 
     114           0 : SvXMLImportContext *XMLVersionListImport::CreateContext(
     115             :         sal_uInt16 nPrefix,
     116             :         const OUString& rLocalName,
     117             :         const Reference< XAttributeList > & xAttrList )
     118             : {
     119           0 :     SvXMLImportContext *pContext = 0;
     120             : 
     121           0 :     if ( XML_NAMESPACE_FRAMEWORK == nPrefix &&
     122           0 :         rLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_VERSION_LIST) )
     123             :     {
     124           0 :         pContext = new XMLVersionListContext( *this, nPrefix, rLocalName, xAttrList );
     125             :     }
     126             :     else
     127             :     {
     128           0 :         pContext = SvXMLImport::CreateContext( nPrefix, rLocalName, xAttrList );
     129             :     }
     130             : 
     131           0 :     return pContext;
     132             : }
     133             : 
     134           0 : XMLVersionListContext::XMLVersionListContext( XMLVersionListImport& rImport,
     135             :                                         sal_uInt16 nPrefix,
     136             :                                         const OUString& rLocalName,
     137             :                                         const Reference< XAttributeList > & )
     138             :     : SvXMLImportContext( rImport, nPrefix, rLocalName )
     139           0 :     , rLocalRef( rImport )
     140             : {
     141           0 : }
     142             : 
     143           0 : XMLVersionListContext::~XMLVersionListContext( void )
     144           0 : {}
     145             : 
     146           0 : SvXMLImportContext *XMLVersionListContext::CreateChildContext( sal_uInt16 nPrefix,
     147             :                                         const OUString& rLocalName,
     148             :                                         const Reference< XAttributeList > & xAttrList )
     149             : {
     150           0 :     SvXMLImportContext *pContext = 0;
     151             : 
     152           0 :     if ( nPrefix == XML_NAMESPACE_FRAMEWORK &&
     153           0 :          rLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_VERSION_ENTRY) )
     154             :     {
     155           0 :         pContext = new XMLVersionContext( rLocalRef, nPrefix, rLocalName, xAttrList );
     156             :     }
     157             :     else
     158             :     {
     159           0 :         pContext = new SvXMLImportContext( rLocalRef, nPrefix, rLocalName );
     160             :     }
     161             : 
     162           0 :     return pContext;
     163             : }
     164             : 
     165           0 : XMLVersionContext::XMLVersionContext( XMLVersionListImport& rImport,
     166             :                                         sal_uInt16 nPref,
     167             :                                         const OUString& rLocalName,
     168             :                                         const Reference< XAttributeList > & xAttrList )
     169             :     : SvXMLImportContext( rImport, nPref, rLocalName )
     170           0 :     , rLocalRef( rImport )
     171             : {
     172           0 :     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
     173             : 
     174           0 :     if ( !nAttrCount )
     175           0 :         return;
     176             : 
     177           0 :     util::RevisionTag aInfo;
     178           0 :     for ( sal_Int16 i=0; i < nAttrCount; i++ )
     179             :     {
     180           0 :         OUString        aLocalName;
     181           0 :         const OUString& rAttrName   = xAttrList->getNameByIndex( i );
     182           0 :         sal_uInt16      nPrefix     = rImport.GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName );
     183             : 
     184           0 :         if ( XML_NAMESPACE_FRAMEWORK == nPrefix )
     185             :         {
     186           0 :             if ( aLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_TITLE) )
     187             :             {
     188           0 :                 const OUString& rAttrValue = xAttrList->getValueByIndex( i );
     189           0 :                 aInfo.Identifier = rAttrValue;
     190             :             }
     191           0 :             else if ( aLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_COMMENT) )
     192             :             {
     193           0 :                 const OUString& rAttrValue = xAttrList->getValueByIndex( i );
     194           0 :                 aInfo.Comment = rAttrValue;
     195             :             }
     196           0 :             else if ( aLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_CREATOR) )
     197             :             {
     198           0 :                 const OUString& rAttrValue = xAttrList->getValueByIndex( i );
     199           0 :                 aInfo.Author = rAttrValue;
     200             :             }
     201             :         }
     202           0 :         else if ( ( XML_NAMESPACE_DC == nPrefix ) &&
     203           0 :                   ( aLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_DATE_TIME) ) )
     204             :         {
     205           0 :             const OUString& rAttrValue = xAttrList->getValueByIndex( i );
     206           0 :             util::DateTime aTime;
     207           0 :             if ( ParseISODateTimeString( rAttrValue, aTime ) )
     208           0 :                 aInfo.TimeStamp = aTime;
     209             :         }
     210           0 :     }
     211             : 
     212           0 :     uno::Sequence < util::RevisionTag >& aList = rLocalRef.GetList();
     213           0 :     sal_Int32 nLength = aList.getLength();
     214           0 :     aList.realloc( nLength+1 );
     215           0 :     aList[nLength] = aInfo;
     216             : }
     217             : 
     218           0 : XMLVersionContext::~XMLVersionContext( void )
     219           0 : {}
     220             : 
     221           0 : bool XMLVersionContext::ParseISODateTimeString(
     222             :                                 const OUString& rString,
     223             :                                 util::DateTime& rDateTime )
     224             : {
     225           0 :     bool bSuccess = true;
     226             : 
     227           0 :     OUString aDateStr, aTimeStr;
     228           0 :     sal_Int32 nPos = rString.indexOf( (sal_Unicode) 'T' );
     229           0 :     if ( nPos >= 0 )
     230             :     {
     231           0 :         aDateStr = rString.copy( 0, nPos );
     232           0 :         aTimeStr = rString.copy( nPos + 1 );
     233             :     }
     234             :     else
     235           0 :         aDateStr = rString;         // no separator: only date part
     236             : 
     237           0 :     sal_Int32 nYear  = 0;
     238           0 :     sal_Int32 nMonth = 1;
     239           0 :     sal_Int32 nDay   = 1;
     240           0 :     sal_Int32 nHour  = 0;
     241           0 :     sal_Int32 nMin   = 0;
     242           0 :     sal_Int32 nSec   = 0;
     243             : 
     244           0 :     const sal_Unicode* pStr = aDateStr.getStr();
     245           0 :     sal_Int32 nDateTokens = 1;
     246           0 :     while ( *pStr )
     247             :     {
     248           0 :         if ( *pStr == '-' )
     249           0 :             nDateTokens++;
     250           0 :         pStr++;
     251             :     }
     252           0 :     if ( nDateTokens > 3 || aDateStr.isEmpty() )
     253           0 :         bSuccess = false;
     254             :     else
     255             :     {
     256           0 :         sal_Int32 n = 0;
     257           0 :         nYear = aDateStr.getToken( 0, '-', n ).toInt32();
     258           0 :         if ( nYear > 9999 )
     259           0 :             bSuccess = false;
     260           0 :         else if ( nDateTokens >= 2 )
     261             :         {
     262           0 :             nMonth = aDateStr.getToken( 0, '-', n ).toInt32();
     263           0 :             if ( nMonth > 12 )
     264           0 :                 bSuccess = false;
     265           0 :             else if ( nDateTokens >= 3 )
     266             :             {
     267           0 :                 nDay = aDateStr.getToken( 0, '-', n ).toInt32();
     268           0 :                 if ( nDay > 31 )
     269           0 :                     bSuccess = false;
     270             :             }
     271             :         }
     272             :     }
     273             : 
     274           0 :     if ( bSuccess && !aTimeStr.isEmpty() )         // time is optional
     275             :     {
     276           0 :         pStr = aTimeStr.getStr();
     277           0 :         sal_Int32 nTimeTokens = 1;
     278           0 :         while ( *pStr )
     279             :         {
     280           0 :             if ( *pStr == ':' )
     281           0 :                 nTimeTokens++;
     282           0 :             pStr++;
     283             :         }
     284           0 :         if ( nTimeTokens > 3 )
     285           0 :             bSuccess = false;
     286             :         else
     287             :         {
     288           0 :             sal_Int32 n = 0;
     289           0 :             nHour = aTimeStr.getToken( 0, ':', n ).toInt32();
     290           0 :             if ( nHour > 23 )
     291           0 :                 bSuccess = false;
     292           0 :             else if ( nTimeTokens >= 2 )
     293             :             {
     294           0 :                 nMin = aTimeStr.getToken( 0, ':', n ).toInt32();
     295           0 :                 if ( nMin > 59 )
     296           0 :                     bSuccess = false;
     297           0 :                 else if ( nTimeTokens >= 3 )
     298             :                 {
     299           0 :                     nSec = aTimeStr.getToken( 0, ':', n ).toInt32();
     300           0 :                     if ( nSec > 59 )
     301           0 :                         bSuccess = false;
     302             :                 }
     303             :             }
     304             :         }
     305             :     }
     306             : 
     307           0 :     if ( bSuccess )
     308             :     {
     309           0 :         rDateTime.Day = sal::static_int_cast< sal_uInt16 >(nDay);
     310           0 :         rDateTime.Month = sal::static_int_cast< sal_uInt16 >(nMonth);
     311           0 :         rDateTime.Year = sal::static_int_cast< sal_uInt16 >(nYear);
     312           0 :         rDateTime.Hours = sal::static_int_cast< sal_uInt16 >(nHour);
     313           0 :         rDateTime.Minutes = sal::static_int_cast< sal_uInt16 >(nMin);
     314           0 :         rDateTime.Seconds = sal::static_int_cast< sal_uInt16 >(nSec);
     315             :     }
     316             : 
     317           0 :     return bSuccess;
     318             : }
     319             : 
     320           0 : void SAL_CALL XMLVersionListPersistence::store( const uno::Reference< embed::XStorage >& xRoot, const uno::Sequence< util::RevisionTag >& rVersions )
     321             :     throw (::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException, std::exception)
     322             : {
     323             :     // no storage, no version list!
     324           0 :     if ( xRoot.is() )
     325             :     {
     326             :         // get the services needed for writing the xml data
     327             :         Reference< uno::XComponentContext > xContext =
     328           0 :                 comphelper::getProcessComponentContext();
     329             : 
     330           0 :         Reference< XWriter > xWriter = Writer::create(xContext);
     331             : 
     332             :         // check whether there's already a sub storage with the version info
     333             :         // and delete it
     334           0 :         OUString sVerName( XMLN_VERSIONSLIST  );
     335             : 
     336             :         try {
     337             :             // open (create) the sub storage with the version info
     338           0 :             uno::Reference< io::XStream > xVerStream = xRoot->openStreamElement(
     339             :                                             sVerName,
     340           0 :                                             embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
     341           0 :             if ( !xVerStream.is() )
     342           0 :                 throw uno::RuntimeException();
     343             : 
     344           0 :             Reference< io::XOutputStream > xOut = xVerStream->getOutputStream();
     345           0 :             if ( !xOut.is() )
     346           0 :                 throw uno::RuntimeException(); // the stream was successfully opened for writing already
     347             : 
     348           0 :             Reference< io::XActiveDataSource > xSrc( xWriter, uno::UNO_QUERY );
     349           0 :             xSrc->setOutputStream(xOut);
     350             : 
     351           0 :             Reference< XDocumentHandler > xHandler( xWriter, uno::UNO_QUERY );
     352             : 
     353           0 :             XMLVersionListExport aExp( xContext, rVersions, sVerName, xHandler );
     354             : 
     355           0 :             aExp.exportDoc( ::xmloff::token::XML_VERSION );
     356             : 
     357           0 :             xVerStream = uno::Reference< io::XStream >(); // use refcounting for now to dispose
     358             :         }
     359           0 :         catch( uno::Exception& )
     360             :         {
     361             :             // TODO: error handling
     362           0 :         }
     363             :     }
     364           0 : }
     365             : 
     366        3836 : uno::Sequence< util::RevisionTag > SAL_CALL XMLVersionListPersistence::load( const uno::Reference< embed::XStorage >& xRoot )
     367             :         throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException, std::exception)
     368             : {
     369        3836 :     com::sun::star::uno::Sequence < com::sun::star::util::RevisionTag > aVersions;
     370             : 
     371        7672 :     const OUString sDocName( XMLN_VERSIONSLIST  );
     372        7672 :     uno::Reference< container::XNameAccess > xRootNames( xRoot, uno::UNO_QUERY );
     373             : 
     374             :     try {
     375        3836 :         if ( xRootNames.is() && xRootNames->hasByName( sDocName ) && xRoot->isStreamElement( sDocName ) )
     376             :         {
     377           0 :             Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
     378             : 
     379           0 :             InputSource aParserInput;
     380             : 
     381           0 :             uno::Reference< beans::XPropertySet > xProps( xRoot, uno::UNO_QUERY );
     382             :             OSL_ENSURE( xProps.is(), "Storage must implement XPropertySet!\n" );
     383           0 :             if ( xProps.is() )
     384             :             {
     385             :                 try {
     386           0 :                     xProps->getPropertyValue("URL") >>= aParserInput.sSystemId;
     387             :                 }
     388           0 :                 catch( uno::Exception& )
     389             :                 {}
     390             :             }
     391             : 
     392           0 :             uno::Reference< io::XStream > xDocStream = xRoot->openStreamElement(
     393             :                                                             sDocName,
     394           0 :                                                             embed::ElementModes::READ );
     395           0 :             if ( !xDocStream.is() )
     396           0 :                 throw uno::RuntimeException();
     397             : 
     398           0 :             aParserInput.aInputStream = xDocStream->getInputStream();
     399             :             OSL_ENSURE( aParserInput.aInputStream.is(),
     400             :                         "The stream was successfully opened for reading, the input part must be accessible!\n" );
     401           0 :             if ( !aParserInput.aInputStream.is() )
     402           0 :                 throw uno::RuntimeException();
     403             : 
     404             :             // get filter
     405           0 :             Reference< XDocumentHandler > xFilter = new XMLVersionListImport( xContext, aVersions );
     406             : 
     407             :             // connect parser and filter
     408           0 :             Reference< XParser > xParser = xml::sax::Parser::create(xContext);
     409           0 :             xParser->setDocumentHandler( xFilter );
     410             : 
     411             :             // parse
     412             :             try
     413             :             {
     414           0 :                 xParser->parseStream( aParserInput );
     415             :             }
     416           0 :             catch( SAXParseException&  ) {}
     417           0 :             catch( SAXException&  )      {}
     418           0 :             catch( io::IOException& )    {}
     419             :         }
     420             :     }
     421        2942 :     catch( uno::Exception& )
     422             :     {
     423             :         // TODO: error handling
     424             :     }
     425             : 
     426        7672 :     return aVersions;
     427             : }
     428             : 
     429             : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
     430        3838 : XMLVersionListPersistence_get_implementation(
     431             :     css::uno::XComponentContext *,
     432             :     css::uno::Sequence<css::uno::Any> const &)
     433             : {
     434        3838 :     return cppu::acquire(new XMLVersionListPersistence());
     435             : }
     436             : 
     437             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10