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

Generated by: LCOV version 1.11