/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include "docprophandler.hxx" #include #include #include #include #include #include #include #include #include #include #include "oox/helper/attributelist.hxx" using namespace ::com::sun::star; namespace oox { namespace docprop { OOXMLDocPropHandler::OOXMLDocPropHandler( const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< document::XDocumentProperties >& rDocProp ) : m_xDocProp( rDocProp ) , m_nState( 0 ) , m_nBlock( 0 ) , m_nType( 0 ) , m_nInBlock( 0 ) , m_CustomStringPropertyState(NONE) { if ( !xContext.is() || !rDocProp.is() ) throw uno::RuntimeException(); } OOXMLDocPropHandler::~OOXMLDocPropHandler() { } void OOXMLDocPropHandler::InitNew() { m_nState = 0; m_nBlock = 0; m_aCustomPropertyName.clear(); m_nType = 0; m_nInBlock = 0; m_CustomStringPropertyState = NONE; } void OOXMLDocPropHandler::AddCustomProperty( const uno::Any& aAny ) { if ( !m_aCustomPropertyName.isEmpty() ) { const uno::Reference< beans::XPropertyContainer > xUserProps = m_xDocProp->getUserDefinedProperties(); if ( !xUserProps.is() ) throw uno::RuntimeException(); try { xUserProps->addProperty( m_aCustomPropertyName, beans::PropertyAttribute::REMOVABLE, aAny ); } catch( beans::PropertyExistException& ) { // conflicts with core and extended properties are possible } catch( uno::Exception& ) { OSL_FAIL( "Can not add custom property!" ); } } } util::DateTime OOXMLDocPropHandler::GetDateTimeFromW3CDTF( const OUString& aChars ) { oslDateTime aOslDTime = { 0, 0, 0, 0, 0, 0, 0, 0 }; const sal_Int32 nLen = aChars.getLength(); if ( nLen >= 4 ) { aOslDTime.Year = (sal_Int16)aChars.copy( 0, 4 ).toInt32(); if ( nLen >= 7 && aChars[4] == (sal_Unicode)'-' ) { aOslDTime.Month = (sal_uInt16)aChars.copy( 5, 2 ).toInt32(); if ( nLen >= 10 && aChars[7] == (sal_Unicode)'-' ) { aOslDTime.Day = (sal_uInt16)aChars.copy( 8, 2 ).toInt32(); if ( nLen >= 16 && aChars[10] == (sal_Unicode)'T' && aChars[13] == (sal_Unicode)':' ) { aOslDTime.Hours = (sal_uInt16)aChars.copy( 11, 2 ).toInt32(); aOslDTime.Minutes = (sal_uInt16)aChars.copy( 14, 2 ).toInt32(); sal_Int32 nOptTime = 0; if ( nLen >= 19 && aChars[16] == (sal_Unicode)':' ) { aOslDTime.Seconds = (sal_uInt16)aChars.copy( 17, 2 ).toInt32(); nOptTime += 3; if ( nLen >= 20 && aChars[19] == (sal_Unicode)'.' ) { nOptTime += 1; sal_Int32 digitPos = 20; while (nLen > digitPos && digitPos < 29) { sal_Unicode c = aChars[digitPos]; if ( c < '0' || c > '9') break; aOslDTime.NanoSeconds *= 10; aOslDTime.NanoSeconds += c - '0'; ++digitPos; } if ( digitPos < 29 ) { // read less digits than 9 // add correct exponent of 10 nOptTime += digitPos - 20; for(; digitPos<29; ++digitPos) { aOslDTime.NanoSeconds *= 10; } } else { //skip digits with more precision than we can handle while(nLen > digitPos) { sal_Unicode c = aChars[digitPos]; if ( c < '0' || c > '9') break; ++digitPos; } nOptTime += digitPos - 20; } } } sal_Int32 nModif = 0; if ( nLen >= 16 + nOptTime + 6 ) { if ( ( aChars[16 + nOptTime] == (sal_Unicode)'+' || aChars[16 + nOptTime] == (sal_Unicode)'-' ) && aChars[16 + nOptTime + 3] == (sal_Unicode)':' ) { nModif = aChars.copy( 16 + nOptTime + 1, 2 ).toInt32() * 3600; nModif += aChars.copy( 16 + nOptTime + 4, 2 ).toInt32() * 60; if ( aChars[16 + nOptTime] == (sal_Unicode)'-' ) nModif *= -1; } } if ( nModif ) { // convert to UTC time TimeValue aTmp; if ( osl_getTimeValueFromDateTime( &aOslDTime, &aTmp ) ) { aTmp.Seconds -= nModif; osl_getDateTimeFromTimeValue( &aTmp, &aOslDTime ); } } } } } } return util::DateTime( aOslDTime.NanoSeconds, aOslDTime.Seconds, aOslDTime.Minutes, aOslDTime.Hours, aOslDTime.Day, aOslDTime.Month, aOslDTime.Year, false); } uno::Sequence< OUString > OOXMLDocPropHandler::GetKeywordsSet( const OUString& aChars ) { if ( !aChars.isEmpty() ) { std::string aUtf8Chars = OUStringToOString( aChars, RTL_TEXTENCODING_UTF8 ).getStr(); std::vector aUtf8Result; boost::split( aUtf8Result, aUtf8Chars, boost::is_any_of(" ,;:\t"), boost::token_compress_on ); if (!aUtf8Result.empty()) { uno::Sequence< OUString > aResult( aUtf8Result.size() ); OUString* pResultValues = aResult.getArray(); for ( std::vector< std::string >::const_iterator i = aUtf8Result.begin(); i != aUtf8Result.end(); ++i, ++pResultValues ) *pResultValues = OUString( i->c_str(), static_cast< sal_Int32 >( i->size() ),RTL_TEXTENCODING_UTF8 ); return aResult; } } return uno::Sequence< OUString >(); } void OOXMLDocPropHandler::UpdateDocStatistic( const OUString& aChars ) { uno::Sequence< beans::NamedValue > aSet = m_xDocProp->getDocumentStatistics(); OUString aName; switch( m_nBlock ) { case EXTPR_TOKEN( Characters ): aName = "NonWhitespaceCharacterCount"; break; case EXTPR_TOKEN( CharactersWithSpaces ): aName = "CharacterCount"; break; case EXTPR_TOKEN( Pages ): aName = "PageCount"; break; case EXTPR_TOKEN( Words ): aName = "WordCount"; break; case EXTPR_TOKEN( Paragraphs ): aName = "ParagraphCount"; break; default: OSL_FAIL( "Unexpected statistic!" ); break; } if ( !aName.isEmpty() ) { bool bFound = false; sal_Int32 nLen = aSet.getLength(); for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ ) if ( aSet[nInd].Name.equals( aName ) ) { aSet[nInd].Value = uno::makeAny( aChars.toInt32() ); bFound = true; break; } if ( !bFound ) { aSet.realloc( nLen + 1 ); aSet[nLen].Name = aName; aSet[nLen].Value = uno::makeAny( aChars.toInt32() ); } m_xDocProp->setDocumentStatistics( aSet ); } } // com.sun.star.xml.sax.XFastDocumentHandler void SAL_CALL OOXMLDocPropHandler::startDocument() { } void SAL_CALL OOXMLDocPropHandler::endDocument() { InitNew(); } void SAL_CALL OOXMLDocPropHandler::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& ) { } // com.sun.star.xml.sax.XFastContextHandler void SAL_CALL OOXMLDocPropHandler::startFastElement( ::sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttribs ) { if ( !m_nInBlock && !m_nState ) { if ( nElement == COREPR_TOKEN( coreProperties ) || nElement == EXTPR_TOKEN( Properties ) || nElement == CUSTPR_TOKEN( Properties ) ) { m_nState = nElement; } else { OSL_FAIL( "Unexpected file format!" ); } } else if ( m_nState && m_nInBlock == 1 ) // that tag should contain the property name { // Currently the attributes are ignored for the core properties since the only // known attribute is xsi:type that can only be used with dcterms:created and // dcterms:modified, and this element is allowed currently to have only one value dcterms:W3CDTF m_nBlock = nElement; if ( xAttribs.is() && xAttribs->hasAttribute( XML_name ) ) m_aCustomPropertyName = xAttribs->getValue( XML_name ); } else if ( m_nState && m_nInBlock == 2 && getNamespace( nElement ) == NMSP_officeDocPropsVT ) { m_nType = nElement; } else { SAL_WARN("oox", "OOXMLDocPropHandler::startFastElement: unknown element " << getBaseToken(nElement)); } if ( m_nInBlock == SAL_MAX_INT32 ) throw uno::RuntimeException(); m_nInBlock++; } void SAL_CALL OOXMLDocPropHandler::startUnknownElement( const OUString& aNamespace, const OUString& aName, const uno::Reference< xml::sax::XFastAttributeList >& ) { SAL_WARN("oox", "Unknown element " << aNamespace << ":" << aName); if ( m_nInBlock == SAL_MAX_INT32 ) throw uno::RuntimeException(); m_nInBlock++; } void SAL_CALL OOXMLDocPropHandler::endFastElement( ::sal_Int32 ) { if ( m_nInBlock ) { m_nInBlock--; if ( !m_nInBlock ) m_nState = 0; else if ( m_nInBlock == 1 ) { m_nBlock = 0; m_aCustomPropertyName.clear(); } else if ( m_nInBlock == 2 ) { if ( m_nState == CUSTPR_TOKEN(Properties) && m_nBlock == CUSTPR_TOKEN(property)) { switch (m_nType) { case VT_TOKEN(bstr): case VT_TOKEN(lpstr): case VT_TOKEN(lpwstr): if (!m_aCustomPropertyName.isEmpty() && INSERTED != m_CustomStringPropertyState) { // the property has string type, so it is valid // even with an empty value - characters() has // not been called in that case AddCustomProperty(uno::makeAny(OUString())); } break; } } m_CustomStringPropertyState = NONE; m_nType = 0; } } } void SAL_CALL OOXMLDocPropHandler::endUnknownElement( const OUString&, const OUString& ) { if ( m_nInBlock ) m_nInBlock--; } uno::Reference< xml::sax::XFastContextHandler > SAL_CALL OOXMLDocPropHandler::createFastChildContext( ::sal_Int32, const uno::Reference< xml::sax::XFastAttributeList >& ) { // Should the arguments be parsed? return uno::Reference< xml::sax::XFastContextHandler >( static_cast< xml::sax::XFastContextHandler* >( this ) ); } uno::Reference< xml::sax::XFastContextHandler > SAL_CALL OOXMLDocPropHandler::createUnknownChildContext( const OUString&, const OUString&, const uno::Reference< xml::sax::XFastAttributeList >& ) { return uno::Reference< xml::sax::XFastContextHandler >( static_cast< xml::sax::XFastContextHandler* >( this ) ); } void SAL_CALL OOXMLDocPropHandler::characters( const OUString& aChars ) { try { if ( (m_nInBlock == 2) || ((m_nInBlock == 3) && m_nType) ) { if ( m_nState == COREPR_TOKEN( coreProperties ) ) { switch( m_nBlock ) { case COREPR_TOKEN( category ): m_aCustomPropertyName = "category"; AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type break; case COREPR_TOKEN( contentStatus ): m_aCustomPropertyName = "contentStatus"; AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type break; case COREPR_TOKEN( contentType ): m_aCustomPropertyName = "contentType"; AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type break; case COREPR_TOKEN( identifier ): m_aCustomPropertyName = "identifier"; AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type break; case COREPR_TOKEN( version ): m_aCustomPropertyName = "version"; AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type break; case DCT_TOKEN( created ): if ( aChars.getLength() >= 4 ) m_xDocProp->setCreationDate( GetDateTimeFromW3CDTF( aChars ) ); break; case DC_TOKEN( creator ): m_xDocProp->setAuthor( aChars ); break; case DC_TOKEN( description ): m_xDocProp->setDescription( aChars ); break; case COREPR_TOKEN( keywords ): m_xDocProp->setKeywords( GetKeywordsSet( aChars ) ); break; case DC_TOKEN( language ): if ( aChars.getLength() >= 2 ) m_xDocProp->setLanguage( LanguageTag::convertToLocale( aChars) ); break; case COREPR_TOKEN( lastModifiedBy ): m_xDocProp->setModifiedBy( aChars ); break; case COREPR_TOKEN( lastPrinted ): if ( aChars.getLength() >= 4 ) m_xDocProp->setPrintDate( GetDateTimeFromW3CDTF( aChars ) ); break; case DCT_TOKEN( modified ): if ( aChars.getLength() >= 4 ) m_xDocProp->setModificationDate( GetDateTimeFromW3CDTF( aChars ) ); break; case COREPR_TOKEN( revision ): try { m_xDocProp->setEditingCycles( static_cast(aChars.toInt32()) ); } catch (lang::IllegalArgumentException &) { // ignore } break; case DC_TOKEN( subject ): m_xDocProp->setSubject( m_xDocProp->getSubject() + aChars ); break; case DC_TOKEN( title ): m_xDocProp->setTitle( m_xDocProp->getTitle() + aChars ); break; default: OSL_FAIL( "Unexpected core property!" ); } } else if ( m_nState == EXTPR_TOKEN( Properties ) ) { switch( m_nBlock ) { case EXTPR_TOKEN( Application ): m_xDocProp->setGenerator( aChars ); break; case EXTPR_TOKEN( Template ): m_xDocProp->setTemplateName( aChars ); break; case EXTPR_TOKEN( TotalTime ): try { // The TotalTime is in mins as per ECMA specification. m_xDocProp->setEditingDuration( aChars.toInt32() * 60 ); } catch (lang::IllegalArgumentException &) { // ignore } break; case EXTPR_TOKEN( Characters ): case EXTPR_TOKEN( CharactersWithSpaces ): case EXTPR_TOKEN( Pages ): case EXTPR_TOKEN( Words ): case EXTPR_TOKEN( Paragraphs ): UpdateDocStatistic( aChars ); break; case EXTPR_TOKEN( HyperlinksChanged ): m_aCustomPropertyName = "HyperlinksChanged"; AddCustomProperty( uno::makeAny( aChars.toBoolean() ) ); // the property has boolean type break; case EXTPR_TOKEN( LinksUpToDate ): m_aCustomPropertyName = "LinksUpToDate"; AddCustomProperty( uno::makeAny( aChars.toBoolean() ) ); // the property has boolean type break; case EXTPR_TOKEN( ScaleCrop ): m_aCustomPropertyName = "ScaleCrop"; AddCustomProperty( uno::makeAny( aChars.toBoolean() ) ); // the property has boolean type break; case EXTPR_TOKEN( SharedDoc ): m_aCustomPropertyName = "ShareDoc"; AddCustomProperty( uno::makeAny( aChars.toBoolean() ) ); // the property has boolean type break; case EXTPR_TOKEN( DocSecurity ): m_aCustomPropertyName = "DocSecurity"; AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // the property has sal_Int32 type break; case EXTPR_TOKEN( HiddenSlides ): m_aCustomPropertyName = "HiddenSlides"; AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // the property has sal_Int32 type break; case EXTPR_TOKEN( MMClips ): m_aCustomPropertyName = "MMClips"; AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // the property has sal_Int32 type break; case EXTPR_TOKEN( Notes ): m_aCustomPropertyName = "Notes"; AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // the property has sal_Int32 type break; case EXTPR_TOKEN( Slides ): m_aCustomPropertyName = "Slides"; AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // the property has sal_Int32 type break; case EXTPR_TOKEN( AppVersion ): m_aCustomPropertyName = "AppVersion"; AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type break; case EXTPR_TOKEN( Company ): m_aCustomPropertyName = "Company"; AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type break; case EXTPR_TOKEN( HyperlinkBase ): m_aCustomPropertyName = "HyperlinkBase"; AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type break; case EXTPR_TOKEN( Manager ): m_aCustomPropertyName = "Manager"; AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type break; case EXTPR_TOKEN( PresentationFormat ): m_aCustomPropertyName = "PresentationFormat"; AddCustomProperty( uno::makeAny( aChars ) ); // the property has string type break; case EXTPR_TOKEN( Lines ): case EXTPR_TOKEN( DigSig ): case EXTPR_TOKEN( HeadingPairs ): case EXTPR_TOKEN( HLinks ): case EXTPR_TOKEN( TitlesOfParts ): // ignored during the import currently break; default: OSL_FAIL( "Unexpected extended property!" ); } } else if ( m_nState == CUSTPR_TOKEN( Properties ) ) { if ( m_nBlock == CUSTPR_TOKEN( property ) ) { // this is a custom property switch( m_nType ) { case VT_TOKEN( bool ): AddCustomProperty( uno::makeAny( aChars.toBoolean() ) ); break; case VT_TOKEN( bstr ): case VT_TOKEN( lpstr ): case VT_TOKEN( lpwstr ): // the property has string type AddCustomProperty( uno::makeAny( AttributeConversion::decodeXString( aChars ) ) ); m_CustomStringPropertyState = INSERTED; break; case VT_TOKEN( date ): case VT_TOKEN( filetime ): AddCustomProperty( uno::makeAny( GetDateTimeFromW3CDTF( aChars ) ) ); break; case VT_TOKEN( i1 ): case VT_TOKEN( i2 ): AddCustomProperty( uno::makeAny( (sal_Int16)aChars.toInt32() ) ); break; case VT_TOKEN( i4 ): case VT_TOKEN( int ): AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); break; case VT_TOKEN( i8 ): AddCustomProperty( uno::makeAny( aChars.toInt64() ) ); break; case VT_TOKEN( r4 ): AddCustomProperty( uno::makeAny( aChars.toFloat() ) ); break; case VT_TOKEN( r8 ): AddCustomProperty( uno::makeAny( aChars.toDouble() ) ); break; default: // all the other types are ignored; break; } } else { OSL_FAIL( "Unexpected tag in custom property!" ); } } } } catch( uno::RuntimeException& ) { throw; } catch( xml::sax::SAXException& ) { throw; } catch( uno::Exception& e ) { throw xml::sax::SAXException( "Error while setting document property!", uno::Reference< uno::XInterface >(), uno::makeAny( e ) ); } } } // namespace docprop } // namespace oox /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ LibreOffice 核心代码仓库文档基金会
summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2015-04-22Various #include <sal/log.hxx> fixupsStephan Bergmann
rtl/string.hxx and rtl/ustring.hxx both unnecessarily #include <sal/log.hxx> (and don't make use of it themselves), but many other files happen to depend on it. Cleaned up some, but something like grep -FwL sal/log.hxx $(git grep -Elw \ 'SAL_INFO|SAL_INFO_IF|SAL_WARN|SAL_WARN_IF') -- \*.cxx) shows lots more files that potentially need fixing before the include can be removed from rtl/string.hxx and rtl/ustring.hxx. Change-Id: Ibf033363e83d37851776f392dc0b077381cd8b90
2015-04-02loplugin:staticmethodsNoel Grandin
Change-Id: I3ae555fd9f0dc3c11ea301ee1cb2c799fbec820d
2015-04-01Add isReadOnly() support to simplified configuration accessStephan Bergmann
[API CHANGE]: extends the css.configuration.XReadWriteAccess in an incompatible way, but that is unpublished, has been commented as "still unpublished and unstable," and was specifically introduced for internal use by the simplified configuration access, so should not affect 3rd party code. Change-Id: I99ce045f5bd8c598e689d46fb0d3626dfaa6d0a0
2015-04-01Add support for cppu::UnoType<void>Stephan Bergmann
Change-Id: I88259ffaffc73979c240721d2db166c79d3085f1
2015-03-11V668 no sense in testing the result of new against nullCaolán McNamara
Change-Id: I4a33bd92fc8448638a4bfe1eab7e5041a4c5cc39
2015-02-16incomplete type error under some compilersCaolán McNamara
Change-Id: I87740d4d035bc4e430d566f4672bfd338511d3a8
2015-02-16restore dependenciesCaolán McNamara
Change-Id: I20645122bc80d729093dff8d1a8094c6fbf7d68a
2015-02-16boost::noncopyable->'= delete'Caolán McNamara
Change-Id: If0f898a1e912fcd2095d8ba88b2b8046596e16ea
2015-02-16boost::foo_ptr->std::foo_ptrCaolán McNamara
Change-Id: I9219619b538b6530a89f5932ac51eb3b62eb396a
2015-02-12coverity#1269597 Uncaught exceptionCaolán McNamara
and coverity#1269596 Uncaught exception Change-Id: I0466e66cd33dd842296131f73376bc95308254e4
2015-02-11loplugin:unreffunStephan Bergmann
Change-Id: I6cfa63043460a5776873087c62cfbb2753c88f83
2015-02-11tdf#46723 - enable configmgr unit testsRadu Ioan
Known limitation: Disabled testThreads because it fails on writerThreads libreoffice/configmgr/qa/unit/test.cxx:500:(anonymous namespace)::Test::testThreads assertion failed - Expression: success Some exception is catched for some writerThread Change-Id: I5b891bec25599c4536827ffa7ea514b1cdf08b46 Signed-off-by: Stephan Bergmann <sbergman@redhat.com>
2015-02-10cppcheck: assertWithSideEffectCaolán McNamara
Change-Id: I6601e857394d7b460a105e851529350a62d1a2a6
2015-02-06fdo#75757: Remove inheritance from std::vectorMatthew Pottage
Deprecated comphelper/sequenceasvector.hxx. Rewritten code using it. Using instead the functions containerToSequence and sequenceToContainer, found in include/comphelper/sequence.hxx. One class that inherits from it (in framework/inc/stdtypes.h), and the code using that has been left. Signed-off-by: Michael Stahl <mstahl@redhat.com> Conflicts: writerfilter/source/dmapper/DomainMapper.cxx writerfilter/source/dmapper/TblStylePrHandler.hxx writerfilter/source/dmapper/WrapPolygonHandler.hxx Change-Id: Ice61c94ffb052e389281aebb7cdf185134221061
2014-12-16configmgr: Use appropriate OUString functions on string constantsStephan Bergmann
Change-Id: I7345234957aab62e884c0e884ac0b3b8a21e9cc5