| /************************************************************** |
| * |
| * 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 <sfx2/docinf.hxx> |
| #include <com/sun/star/beans/PropertyAttribute.hpp> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/beans/XPropertyContainer.hpp> |
| #include <com/sun/star/document/XDocumentProperties.hpp> |
| #include <com/sun/star/uno/Exception.hpp> |
| #include <rtl/ustring.hxx> |
| #include <tools/debug.hxx> |
| #include <comphelper/string.hxx> |
| #include <sot/storage.hxx> |
| #include <vcl/gdimtf.hxx> |
| #include <vcl/dibtools.hxx> |
| #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<sal_uInt8> * i_pThumb, |
| const uno::Sequence<sal_uInt8> * i_pGuid, |
| const uno::Sequence<sal_uInt8> * 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<sal_Int16>(dur / 3600); |
| aEditTime.Minutes = static_cast<sal_Int16>((dur % 3600) / 60); |
| aEditTime.Seconds = static_cast<sal_Int16>(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<beans::XPropertySet> xUserDefinedProps( |
| i_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW); |
| DBG_ASSERT(xUserDefinedProps.is(), "UserDefinedProperties is null"); |
| uno::Reference<beans::XPropertySetInfo> xPropInfo = |
| xUserDefinedProps->getPropertySetInfo(); |
| DBG_ASSERT(xPropInfo.is(), "UserDefinedProperties Info is null"); |
| uno::Sequence<beans::Property> 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<sal_uInt8> 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 ) ) { |
| WriteDIB(aBitmap.GetBitmap(), aStream, false, false); |
| // uno::Sequence<sal_uInt8> aSeq(aStream.GetSize()); // WRONG |
| aStream.Seek(STREAM_SEEK_TO_END); |
| uno::Sequence<sal_uInt8> aSeq(aStream.Tell()); |
| const sal_uInt8* pBlob( |
| static_cast<const sal_uInt8*>(aStream.GetData())); |
| for (sal_Int32 j = 0; j < aSeq.getLength(); ++j) { |
| aSeq[j] = pBlob[j]; |
| } |
| return aSeq; |
| } |
| } |
| return uno::Sequence<sal_uInt8>(); |
| } |
| |
| } // namespace sfx2 |
| |