/************************************************************** * * 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 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sfx2.hxx" #include #include #include #include #include #include #include #include #include #include #include #include "oleprops.hxx" // ============================================================================ // stream names #define STREAM_SUMMARYINFO "\005SummaryInformation" #define STREAM_DOCSUMMARYINFO "\005DocumentSummaryInformation" // usings using namespace ::com::sun::star; namespace sfx2 { sal_uInt32 SFX2_DLLPUBLIC LoadOlePropertySet( uno::Reference< document::XDocumentProperties> i_xDocProps, SotStorage* i_pStorage ) { // *** global properties from stream "005SummaryInformation" *** // load the property set SfxOlePropertySet aGlobSet; ErrCode nGlobError = aGlobSet.LoadPropertySet(i_pStorage, String( RTL_CONSTASCII_USTRINGPARAM( STREAM_SUMMARYINFO ) ) ); // global section SfxOleSectionRef xGlobSect = aGlobSet.GetSection( SECTION_GLOBAL ); if( xGlobSect.get() ) { // set supported properties String aStrValue; util::DateTime aDateTime; if( xGlobSect->GetStringValue( aStrValue, PROPID_TITLE ) ) i_xDocProps->setTitle( aStrValue ); if( xGlobSect->GetStringValue( aStrValue, PROPID_SUBJECT ) ) i_xDocProps->setSubject( aStrValue ); if( xGlobSect->GetStringValue( aStrValue, PROPID_KEYWORDS ) ) { i_xDocProps->setKeywords( ::comphelper::string::convertCommaSeparated(aStrValue) ); } if( xGlobSect->GetStringValue( aStrValue, PROPID_TEMPLATE ) ) i_xDocProps->setTemplateName( aStrValue ); if( xGlobSect->GetStringValue( aStrValue, PROPID_COMMENTS ) ) i_xDocProps->setDescription( aStrValue ); util::DateTime aInvalid; if( xGlobSect->GetStringValue( aStrValue, PROPID_AUTHOR) ) i_xDocProps->setAuthor( aStrValue ); else i_xDocProps->setAuthor( ::rtl::OUString() ); if( xGlobSect->GetFileTimeValue( aDateTime, PROPID_CREATED ) ) i_xDocProps->setCreationDate( aDateTime ); else i_xDocProps->setCreationDate( aInvalid ); if( xGlobSect->GetStringValue( aStrValue, PROPID_LASTAUTHOR) ) i_xDocProps->setModifiedBy( aStrValue ); else i_xDocProps->setModifiedBy( ::rtl::OUString() ); if( xGlobSect->GetFileTimeValue( aDateTime, PROPID_LASTSAVED ) ) i_xDocProps->setModificationDate( aDateTime ); else i_xDocProps->setModificationDate( aInvalid ); i_xDocProps->setPrintedBy( ::rtl::OUString() ); if( xGlobSect->GetFileTimeValue( aDateTime, PROPID_LASTPRINTED ) ) i_xDocProps->setPrintDate( aDateTime ); else i_xDocProps->setPrintDate( aInvalid ); if( xGlobSect->GetStringValue( aStrValue, PROPID_REVNUMBER ) ) { sal_Int16 nRevision = static_cast< sal_Int16 >( aStrValue.ToInt32() ); if ( nRevision > 0 ) i_xDocProps->setEditingCycles( nRevision ); } if( xGlobSect->GetFileTimeValue( aDateTime, PROPID_EDITTIME ) ) { // subtract offset 1601-01-01 aDateTime.Year -= 1601; aDateTime.Month -= 1; aDateTime.Day -= 1; try { i_xDocProps->setEditingDuration( aDateTime.Day * 60*60*24 + aDateTime.Hours * 60*60 + aDateTime.Minutes * 60 + aDateTime.Seconds ); } catch (lang::IllegalArgumentException &) { // ignore } } } // *** custom properties from stream "005DocumentSummaryInformation" *** // load the property set SfxOlePropertySet aDocSet; ErrCode nDocError = aDocSet.LoadPropertySet(i_pStorage, String( RTL_CONSTASCII_USTRINGPARAM( STREAM_DOCSUMMARYINFO ) ) ); // custom properties SfxOleSectionRef xCustomSect = aDocSet.GetSection( SECTION_CUSTOM ); if( xCustomSect.get() ) { uno::Reference < beans::XPropertyContainer > xUserDefined( i_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW); ::std::vector< sal_Int32 > aPropIds; xCustomSect->GetPropertyIds( aPropIds ); for( ::std::vector< sal_Int32 >::const_iterator aIt = aPropIds.begin(), aEnd = aPropIds.end(); aIt != aEnd; ++aIt ) { ::rtl::OUString aPropName = xCustomSect->GetPropertyName( *aIt ); uno::Any aPropValue = xCustomSect->GetAnyValue( *aIt ); if( (aPropName.getLength() > 0) && aPropValue.hasValue() ) { try { xUserDefined->addProperty( aPropName, beans::PropertyAttribute::REMOVEABLE, aPropValue ); } catch ( uno::Exception& ) { //ignore } } } } // return code return (nGlobError != ERRCODE_NONE) ? nGlobError : nDocError; } bool SFX2_DLLPUBLIC SaveOlePropertySet( uno::Reference< document::XDocumentProperties> i_xDocProps, SotStorage* i_pStorage, const uno::Sequence * i_pThumb, const uno::Sequence * i_pGuid, const uno::Sequence * i_pHyperlinks) { // *** global properties into stream "005SummaryInformation" *** SfxOlePropertySet aGlobSet; // set supported properties SfxOleSection& rGlobSect = aGlobSet.AddSection( SECTION_GLOBAL ); rGlobSect.SetStringValue( PROPID_TITLE, i_xDocProps->getTitle() ); rGlobSect.SetStringValue( PROPID_SUBJECT, i_xDocProps->getSubject() ); String aStr = ::comphelper::string::convertCommaSeparated( i_xDocProps->getKeywords() ); rGlobSect.SetStringValue( PROPID_KEYWORDS, aStr ); rGlobSect.SetStringValue( PROPID_TEMPLATE, i_xDocProps->getTemplateName() ); rGlobSect.SetStringValue( PROPID_COMMENTS, i_xDocProps->getDescription() ); rGlobSect.SetStringValue( PROPID_AUTHOR, i_xDocProps->getAuthor() ); rGlobSect.SetFileTimeValue(PROPID_CREATED, i_xDocProps->getCreationDate()); rGlobSect.SetStringValue( PROPID_LASTAUTHOR, i_xDocProps->getModifiedBy() ); rGlobSect.SetFileTimeValue(PROPID_LASTSAVED, i_xDocProps->getModificationDate() ); // note: apparently PrintedBy is not supported in file format rGlobSect.SetFileTimeValue(PROPID_LASTPRINTED, i_xDocProps->getPrintDate()); sal_Int32 dur = i_xDocProps->getEditingDuration(); util::DateTime aEditTime; // add offset 1601-01-01 aEditTime.Year = 1601; aEditTime.Month = 1; aEditTime.Day = 1; aEditTime.Hours = static_cast(dur / 3600); aEditTime.Minutes = static_cast((dur % 3600) / 60); aEditTime.Seconds = static_cast(dur % 60); rGlobSect.SetFileTimeValue( PROPID_EDITTIME, aEditTime ); rGlobSect.SetStringValue( PROPID_REVNUMBER, String::CreateFromInt32( i_xDocProps->getEditingCycles() ) ); if ( i_pThumb && i_pThumb->getLength() ) rGlobSect.SetThumbnailValue( PROPID_THUMBNAIL, *i_pThumb ); // save the property set ErrCode nGlobError = aGlobSet.SavePropertySet(i_pStorage, String( RTL_CONSTASCII_USTRINGPARAM( STREAM_SUMMARYINFO ) ) ); // *** custom properties into stream "005DocumentSummaryInformation" *** SfxOlePropertySet aDocSet; // set builtin properties aDocSet.AddSection( SECTION_BUILTIN ); // set custom properties SfxOleSection& rCustomSect = aDocSet.AddSection( SECTION_CUSTOM ); // write GUID if (i_pGuid) { const sal_Int32 nPropId = rCustomSect.GetFreePropertyId(); rCustomSect.SetBlobValue( nPropId, *i_pGuid ); rCustomSect.SetPropertyName( nPropId, ::rtl::OUString::createFromAscii("_PID_GUID") ); } // write hyperlinks if (i_pHyperlinks) { const sal_Int32 nPropId = rCustomSect.GetFreePropertyId(); rCustomSect.SetBlobValue( nPropId, *i_pHyperlinks ); rCustomSect.SetPropertyName( nPropId, ::rtl::OUString::createFromAscii("_PID_HLINKS") ); } uno::Reference xUserDefinedProps( i_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW); DBG_ASSERT(xUserDefinedProps.is(), "UserDefinedProperties is null"); uno::Reference xPropInfo = xUserDefinedProps->getPropertySetInfo(); DBG_ASSERT(xPropInfo.is(), "UserDefinedProperties Info is null"); uno::Sequence props = xPropInfo->getProperties(); for (sal_Int32 i = 0; i < props.getLength(); ++i) { try { // skip transient properties if (~props[i].Attributes & beans::PropertyAttribute::TRANSIENT) { const ::rtl::OUString name = props[i].Name; const sal_Int32 nPropId = rCustomSect.GetFreePropertyId(); if (rCustomSect.SetAnyValue( nPropId, xUserDefinedProps->getPropertyValue(name))) { rCustomSect.SetPropertyName( nPropId, name ); } } } catch (uno::Exception &) { // may happen with concurrent modification... DBG_WARNING("SavePropertySet: exception"); } } // save the property set ErrCode nDocError = aDocSet.SavePropertySet(i_pStorage, String( RTL_CONSTASCII_USTRINGPARAM( STREAM_DOCSUMMARYINFO ) ) ); // return code return (nGlobError == ERRCODE_NONE) && (nDocError == ERRCODE_NONE); } uno::Sequence SFX2_DLLPUBLIC convertMetaFile(GDIMetaFile* i_pThumb) { if (i_pThumb) { BitmapEx aBitmap; SvMemoryStream aStream; // magic value 160 taken from GraphicHelper::getThumbnailFormatFromGDI_Impl() if( i_pThumb->CreateThumbnail( 160, aBitmap ) ) { aBitmap.GetBitmap().Write( aStream, sal_False, sal_False ); // uno::Sequence aSeq(aStream.GetSize()); // WRONG aStream.Seek(STREAM_SEEK_TO_END); uno::Sequence aSeq(aStream.Tell()); const sal_uInt8* pBlob( static_cast(aStream.GetData())); for (sal_Int32 j = 0; j < aSeq.getLength(); ++j) { aSeq[j] = pBlob[j]; } return aSeq; } } return uno::Sequence(); } } // namespace sfx2