/************************************************************************* * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: docinf.cxx,v $ * * $Revision: 1.53 $ * * last change: $Author: obo $ $Date: 2008-02-26 15:08:01 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. * * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2005 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * ************************************************************************/ // 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 ) ) i_xDocProps->setEditingCycles( static_cast< sal_Int16 >( aStrValue.ToInt32() ) ); if( xGlobSect->GetFileTimeValue( aDateTime, PROPID_EDITTIME ) ) { // subtract offset 1601-01-01 aDateTime.Year -= 1601; aDateTime.Month -= 1; aDateTime.Day -= 1; i_xDocProps->setEditingDuration( aDateTime.Day * 60*60*24 + aDateTime.Hours * 60*60 + aDateTime.Minutes * 60 + aDateTime.Seconds ); } } // *** 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, FALSE, 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