1d119d52dSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3d119d52dSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4d119d52dSAndrew Rist * or more contributor license agreements. See the NOTICE file 5d119d52dSAndrew Rist * distributed with this work for additional information 6d119d52dSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7d119d52dSAndrew Rist * to you under the Apache License, Version 2.0 (the 8d119d52dSAndrew Rist * "License"); you may not use this file except in compliance 9d119d52dSAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11d119d52dSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13d119d52dSAndrew Rist * Unless required by applicable law or agreed to in writing, 14d119d52dSAndrew Rist * software distributed under the License is distributed on an 15d119d52dSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16d119d52dSAndrew Rist * KIND, either express or implied. See the License for the 17d119d52dSAndrew Rist * specific language governing permissions and limitations 18d119d52dSAndrew Rist * under the License. 19cdf0e10cSrcweir * 20d119d52dSAndrew Rist *************************************************************/ 21d119d52dSAndrew Rist 22d119d52dSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_sfx2.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <sfx2/docinf.hxx> 28cdf0e10cSrcweir #include <com/sun/star/beans/PropertyAttribute.hpp> 29cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp> 30cdf0e10cSrcweir #include <com/sun/star/beans/XPropertyContainer.hpp> 31cdf0e10cSrcweir #include <com/sun/star/document/XDocumentProperties.hpp> 32cdf0e10cSrcweir #include <com/sun/star/uno/Exception.hpp> 33cdf0e10cSrcweir #include <rtl/ustring.hxx> 34cdf0e10cSrcweir #include <tools/debug.hxx> 35cdf0e10cSrcweir #include <comphelper/string.hxx> 36cdf0e10cSrcweir #include <sot/storage.hxx> 37cdf0e10cSrcweir #include <vcl/gdimtf.hxx> 38*45fd3b9aSArmin Le Grand #include <vcl/dibtools.hxx> 39cdf0e10cSrcweir #include "oleprops.hxx" 40cdf0e10cSrcweir 41cdf0e10cSrcweir // ============================================================================ 42cdf0e10cSrcweir 43cdf0e10cSrcweir // stream names 44cdf0e10cSrcweir #define STREAM_SUMMARYINFO "\005SummaryInformation" 45cdf0e10cSrcweir #define STREAM_DOCSUMMARYINFO "\005DocumentSummaryInformation" 46cdf0e10cSrcweir 47cdf0e10cSrcweir // usings 48cdf0e10cSrcweir using namespace ::com::sun::star; 49cdf0e10cSrcweir 50cdf0e10cSrcweir 51cdf0e10cSrcweir namespace sfx2 { 52cdf0e10cSrcweir 53cdf0e10cSrcweir sal_uInt32 SFX2_DLLPUBLIC LoadOlePropertySet( 54cdf0e10cSrcweir uno::Reference< document::XDocumentProperties> i_xDocProps, 55cdf0e10cSrcweir SotStorage* i_pStorage ) 56cdf0e10cSrcweir { 57cdf0e10cSrcweir // *** global properties from stream "005SummaryInformation" *** 58cdf0e10cSrcweir 59cdf0e10cSrcweir // load the property set 60cdf0e10cSrcweir SfxOlePropertySet aGlobSet; 61cdf0e10cSrcweir ErrCode nGlobError = aGlobSet.LoadPropertySet(i_pStorage, 62cdf0e10cSrcweir String( RTL_CONSTASCII_USTRINGPARAM( STREAM_SUMMARYINFO ) ) ); 63cdf0e10cSrcweir 64cdf0e10cSrcweir // global section 65cdf0e10cSrcweir SfxOleSectionRef xGlobSect = aGlobSet.GetSection( SECTION_GLOBAL ); 66cdf0e10cSrcweir if( xGlobSect.get() ) 67cdf0e10cSrcweir { 68cdf0e10cSrcweir // set supported properties 69cdf0e10cSrcweir String aStrValue; 70cdf0e10cSrcweir util::DateTime aDateTime; 71cdf0e10cSrcweir 72cdf0e10cSrcweir if( xGlobSect->GetStringValue( aStrValue, PROPID_TITLE ) ) 73cdf0e10cSrcweir i_xDocProps->setTitle( aStrValue ); 74cdf0e10cSrcweir if( xGlobSect->GetStringValue( aStrValue, PROPID_SUBJECT ) ) 75cdf0e10cSrcweir i_xDocProps->setSubject( aStrValue ); 76cdf0e10cSrcweir if( xGlobSect->GetStringValue( aStrValue, PROPID_KEYWORDS ) ) { 77cdf0e10cSrcweir i_xDocProps->setKeywords( 78cdf0e10cSrcweir ::comphelper::string::convertCommaSeparated(aStrValue) ); 79cdf0e10cSrcweir } 80cdf0e10cSrcweir if( xGlobSect->GetStringValue( aStrValue, PROPID_TEMPLATE ) ) 81cdf0e10cSrcweir i_xDocProps->setTemplateName( aStrValue ); 82cdf0e10cSrcweir if( xGlobSect->GetStringValue( aStrValue, PROPID_COMMENTS ) ) 83cdf0e10cSrcweir i_xDocProps->setDescription( aStrValue ); 84cdf0e10cSrcweir 85cdf0e10cSrcweir util::DateTime aInvalid; 86cdf0e10cSrcweir if( xGlobSect->GetStringValue( aStrValue, PROPID_AUTHOR) ) 87cdf0e10cSrcweir i_xDocProps->setAuthor( aStrValue ); 88cdf0e10cSrcweir else 89cdf0e10cSrcweir i_xDocProps->setAuthor( ::rtl::OUString() ); 90cdf0e10cSrcweir if( xGlobSect->GetFileTimeValue( aDateTime, PROPID_CREATED ) ) 91cdf0e10cSrcweir i_xDocProps->setCreationDate( aDateTime ); 92cdf0e10cSrcweir else 93cdf0e10cSrcweir i_xDocProps->setCreationDate( aInvalid ); 94cdf0e10cSrcweir 95cdf0e10cSrcweir if( xGlobSect->GetStringValue( aStrValue, PROPID_LASTAUTHOR) ) 96cdf0e10cSrcweir i_xDocProps->setModifiedBy( aStrValue ); 97cdf0e10cSrcweir else 98cdf0e10cSrcweir i_xDocProps->setModifiedBy( ::rtl::OUString() ); 99cdf0e10cSrcweir if( xGlobSect->GetFileTimeValue( aDateTime, PROPID_LASTSAVED ) ) 100cdf0e10cSrcweir i_xDocProps->setModificationDate( aDateTime ); 101cdf0e10cSrcweir else 102cdf0e10cSrcweir i_xDocProps->setModificationDate( aInvalid ); 103cdf0e10cSrcweir 104cdf0e10cSrcweir i_xDocProps->setPrintedBy( ::rtl::OUString() ); 105cdf0e10cSrcweir if( xGlobSect->GetFileTimeValue( aDateTime, PROPID_LASTPRINTED ) ) 106cdf0e10cSrcweir i_xDocProps->setPrintDate( aDateTime ); 107cdf0e10cSrcweir else 108cdf0e10cSrcweir i_xDocProps->setPrintDate( aInvalid ); 109cdf0e10cSrcweir 110cdf0e10cSrcweir if( xGlobSect->GetStringValue( aStrValue, PROPID_REVNUMBER ) ) 111cdf0e10cSrcweir { 112cdf0e10cSrcweir sal_Int16 nRevision = static_cast< sal_Int16 >( aStrValue.ToInt32() ); 113cdf0e10cSrcweir if ( nRevision > 0 ) 114cdf0e10cSrcweir i_xDocProps->setEditingCycles( nRevision ); 115cdf0e10cSrcweir } 116cdf0e10cSrcweir 117cdf0e10cSrcweir if( xGlobSect->GetFileTimeValue( aDateTime, PROPID_EDITTIME ) ) 118cdf0e10cSrcweir { 119cdf0e10cSrcweir // subtract offset 1601-01-01 120cdf0e10cSrcweir aDateTime.Year -= 1601; 121cdf0e10cSrcweir aDateTime.Month -= 1; 122cdf0e10cSrcweir aDateTime.Day -= 1; 123cdf0e10cSrcweir try 124cdf0e10cSrcweir { 125cdf0e10cSrcweir i_xDocProps->setEditingDuration( 126cdf0e10cSrcweir aDateTime.Day * 60*60*24 + 127cdf0e10cSrcweir aDateTime.Hours * 60*60 + 128cdf0e10cSrcweir aDateTime.Minutes * 60 + 129cdf0e10cSrcweir aDateTime.Seconds ); 130cdf0e10cSrcweir } 131cdf0e10cSrcweir catch (lang::IllegalArgumentException &) 132cdf0e10cSrcweir { 133cdf0e10cSrcweir // ignore 134cdf0e10cSrcweir } 135cdf0e10cSrcweir } 136cdf0e10cSrcweir } 137cdf0e10cSrcweir 138cdf0e10cSrcweir // *** custom properties from stream "005DocumentSummaryInformation" *** 139cdf0e10cSrcweir 140cdf0e10cSrcweir // load the property set 141cdf0e10cSrcweir SfxOlePropertySet aDocSet; 142cdf0e10cSrcweir ErrCode nDocError = aDocSet.LoadPropertySet(i_pStorage, 143cdf0e10cSrcweir String( RTL_CONSTASCII_USTRINGPARAM( STREAM_DOCSUMMARYINFO ) ) ); 144cdf0e10cSrcweir 145cdf0e10cSrcweir // custom properties 146cdf0e10cSrcweir SfxOleSectionRef xCustomSect = aDocSet.GetSection( SECTION_CUSTOM ); 147cdf0e10cSrcweir if( xCustomSect.get() ) 148cdf0e10cSrcweir { 149cdf0e10cSrcweir uno::Reference < beans::XPropertyContainer > xUserDefined( 150cdf0e10cSrcweir i_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW); 151cdf0e10cSrcweir ::std::vector< sal_Int32 > aPropIds; 152cdf0e10cSrcweir xCustomSect->GetPropertyIds( aPropIds ); 153cdf0e10cSrcweir for( ::std::vector< sal_Int32 >::const_iterator aIt = aPropIds.begin(), 154cdf0e10cSrcweir aEnd = aPropIds.end(); aIt != aEnd; ++aIt ) 155cdf0e10cSrcweir { 156cdf0e10cSrcweir ::rtl::OUString aPropName = xCustomSect->GetPropertyName( *aIt ); 157cdf0e10cSrcweir uno::Any aPropValue = xCustomSect->GetAnyValue( *aIt ); 158cdf0e10cSrcweir if( (aPropName.getLength() > 0) && aPropValue.hasValue() ) { 159cdf0e10cSrcweir try { 160cdf0e10cSrcweir xUserDefined->addProperty( aPropName, 161cdf0e10cSrcweir beans::PropertyAttribute::REMOVEABLE, aPropValue ); 162cdf0e10cSrcweir } catch ( uno::Exception& ) { 163cdf0e10cSrcweir //ignore 164cdf0e10cSrcweir } 165cdf0e10cSrcweir } 166cdf0e10cSrcweir } 167cdf0e10cSrcweir } 168cdf0e10cSrcweir 169cdf0e10cSrcweir // return code 170cdf0e10cSrcweir return (nGlobError != ERRCODE_NONE) ? nGlobError : nDocError; 171cdf0e10cSrcweir } 172cdf0e10cSrcweir 173cdf0e10cSrcweir bool SFX2_DLLPUBLIC SaveOlePropertySet( 174cdf0e10cSrcweir uno::Reference< document::XDocumentProperties> i_xDocProps, 175cdf0e10cSrcweir SotStorage* i_pStorage, 176cdf0e10cSrcweir const uno::Sequence<sal_uInt8> * i_pThumb, 177cdf0e10cSrcweir const uno::Sequence<sal_uInt8> * i_pGuid, 178cdf0e10cSrcweir const uno::Sequence<sal_uInt8> * i_pHyperlinks) 179cdf0e10cSrcweir { 180cdf0e10cSrcweir // *** global properties into stream "005SummaryInformation" *** 181cdf0e10cSrcweir 182cdf0e10cSrcweir SfxOlePropertySet aGlobSet; 183cdf0e10cSrcweir 184cdf0e10cSrcweir // set supported properties 185cdf0e10cSrcweir SfxOleSection& rGlobSect = aGlobSet.AddSection( SECTION_GLOBAL ); 186cdf0e10cSrcweir rGlobSect.SetStringValue( PROPID_TITLE, i_xDocProps->getTitle() ); 187cdf0e10cSrcweir rGlobSect.SetStringValue( PROPID_SUBJECT, i_xDocProps->getSubject() ); 188cdf0e10cSrcweir String aStr = ::comphelper::string::convertCommaSeparated( 189cdf0e10cSrcweir i_xDocProps->getKeywords() ); 190cdf0e10cSrcweir rGlobSect.SetStringValue( PROPID_KEYWORDS, aStr ); 191cdf0e10cSrcweir rGlobSect.SetStringValue( PROPID_TEMPLATE, i_xDocProps->getTemplateName() ); 192cdf0e10cSrcweir rGlobSect.SetStringValue( PROPID_COMMENTS, i_xDocProps->getDescription() ); 193cdf0e10cSrcweir rGlobSect.SetStringValue( PROPID_AUTHOR, i_xDocProps->getAuthor() ); 194cdf0e10cSrcweir rGlobSect.SetFileTimeValue(PROPID_CREATED, i_xDocProps->getCreationDate()); 195cdf0e10cSrcweir rGlobSect.SetStringValue( PROPID_LASTAUTHOR, i_xDocProps->getModifiedBy() ); 196cdf0e10cSrcweir rGlobSect.SetFileTimeValue(PROPID_LASTSAVED, 197cdf0e10cSrcweir i_xDocProps->getModificationDate() ); 198cdf0e10cSrcweir // note: apparently PrintedBy is not supported in file format 199cdf0e10cSrcweir rGlobSect.SetFileTimeValue(PROPID_LASTPRINTED, i_xDocProps->getPrintDate()); 200cdf0e10cSrcweir 201cdf0e10cSrcweir sal_Int32 dur = i_xDocProps->getEditingDuration(); 202cdf0e10cSrcweir util::DateTime aEditTime; 203cdf0e10cSrcweir // add offset 1601-01-01 204cdf0e10cSrcweir aEditTime.Year = 1601; 205cdf0e10cSrcweir aEditTime.Month = 1; 206cdf0e10cSrcweir aEditTime.Day = 1; 207cdf0e10cSrcweir aEditTime.Hours = static_cast<sal_Int16>(dur / 3600); 208cdf0e10cSrcweir aEditTime.Minutes = static_cast<sal_Int16>((dur % 3600) / 60); 209cdf0e10cSrcweir aEditTime.Seconds = static_cast<sal_Int16>(dur % 60); 210cdf0e10cSrcweir rGlobSect.SetFileTimeValue( PROPID_EDITTIME, aEditTime ); 211cdf0e10cSrcweir 212cdf0e10cSrcweir rGlobSect.SetStringValue( PROPID_REVNUMBER, 213cdf0e10cSrcweir String::CreateFromInt32( i_xDocProps->getEditingCycles() ) ); 214cdf0e10cSrcweir if ( i_pThumb && i_pThumb->getLength() ) 215cdf0e10cSrcweir rGlobSect.SetThumbnailValue( PROPID_THUMBNAIL, *i_pThumb ); 216cdf0e10cSrcweir 217cdf0e10cSrcweir // save the property set 218cdf0e10cSrcweir ErrCode nGlobError = aGlobSet.SavePropertySet(i_pStorage, 219cdf0e10cSrcweir String( RTL_CONSTASCII_USTRINGPARAM( STREAM_SUMMARYINFO ) ) ); 220cdf0e10cSrcweir 221cdf0e10cSrcweir // *** custom properties into stream "005DocumentSummaryInformation" *** 222cdf0e10cSrcweir 223cdf0e10cSrcweir SfxOlePropertySet aDocSet; 224cdf0e10cSrcweir 225cdf0e10cSrcweir // set builtin properties 226cdf0e10cSrcweir aDocSet.AddSection( SECTION_BUILTIN ); 227cdf0e10cSrcweir 228cdf0e10cSrcweir // set custom properties 229cdf0e10cSrcweir SfxOleSection& rCustomSect = aDocSet.AddSection( SECTION_CUSTOM ); 230cdf0e10cSrcweir 231cdf0e10cSrcweir // write GUID 232cdf0e10cSrcweir if (i_pGuid) { 233cdf0e10cSrcweir const sal_Int32 nPropId = rCustomSect.GetFreePropertyId(); 234cdf0e10cSrcweir rCustomSect.SetBlobValue( nPropId, *i_pGuid ); 235cdf0e10cSrcweir rCustomSect.SetPropertyName( nPropId, 236cdf0e10cSrcweir ::rtl::OUString::createFromAscii("_PID_GUID") ); 237cdf0e10cSrcweir } 238cdf0e10cSrcweir 239cdf0e10cSrcweir // write hyperlinks 240cdf0e10cSrcweir if (i_pHyperlinks) { 241cdf0e10cSrcweir const sal_Int32 nPropId = rCustomSect.GetFreePropertyId(); 242cdf0e10cSrcweir rCustomSect.SetBlobValue( nPropId, *i_pHyperlinks ); 243cdf0e10cSrcweir rCustomSect.SetPropertyName( nPropId, 244cdf0e10cSrcweir ::rtl::OUString::createFromAscii("_PID_HLINKS") ); 245cdf0e10cSrcweir } 246cdf0e10cSrcweir 247cdf0e10cSrcweir uno::Reference<beans::XPropertySet> xUserDefinedProps( 248cdf0e10cSrcweir i_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW); 249cdf0e10cSrcweir DBG_ASSERT(xUserDefinedProps.is(), "UserDefinedProperties is null"); 250cdf0e10cSrcweir uno::Reference<beans::XPropertySetInfo> xPropInfo = 251cdf0e10cSrcweir xUserDefinedProps->getPropertySetInfo(); 252cdf0e10cSrcweir DBG_ASSERT(xPropInfo.is(), "UserDefinedProperties Info is null"); 253cdf0e10cSrcweir uno::Sequence<beans::Property> props = xPropInfo->getProperties(); 254cdf0e10cSrcweir for (sal_Int32 i = 0; i < props.getLength(); ++i) { 255cdf0e10cSrcweir try { 256cdf0e10cSrcweir // skip transient properties 257cdf0e10cSrcweir if (~props[i].Attributes & beans::PropertyAttribute::TRANSIENT) 258cdf0e10cSrcweir { 259cdf0e10cSrcweir const ::rtl::OUString name = props[i].Name; 260cdf0e10cSrcweir const sal_Int32 nPropId = rCustomSect.GetFreePropertyId(); 261cdf0e10cSrcweir if (rCustomSect.SetAnyValue( nPropId, 262cdf0e10cSrcweir xUserDefinedProps->getPropertyValue(name))) { 263cdf0e10cSrcweir rCustomSect.SetPropertyName( nPropId, name ); 264cdf0e10cSrcweir } 265cdf0e10cSrcweir } 266cdf0e10cSrcweir } catch (uno::Exception &) { 267cdf0e10cSrcweir // may happen with concurrent modification... 268cdf0e10cSrcweir DBG_WARNING("SavePropertySet: exception"); 269cdf0e10cSrcweir } 270cdf0e10cSrcweir } 271cdf0e10cSrcweir 272cdf0e10cSrcweir // save the property set 273cdf0e10cSrcweir ErrCode nDocError = aDocSet.SavePropertySet(i_pStorage, 274cdf0e10cSrcweir String( RTL_CONSTASCII_USTRINGPARAM( STREAM_DOCSUMMARYINFO ) ) ); 275cdf0e10cSrcweir 276cdf0e10cSrcweir // return code 277cdf0e10cSrcweir return (nGlobError == ERRCODE_NONE) && (nDocError == ERRCODE_NONE); 278cdf0e10cSrcweir } 279cdf0e10cSrcweir 280cdf0e10cSrcweir uno::Sequence<sal_uInt8> SFX2_DLLPUBLIC convertMetaFile(GDIMetaFile* i_pThumb) 281cdf0e10cSrcweir { 282cdf0e10cSrcweir if (i_pThumb) { 283cdf0e10cSrcweir BitmapEx aBitmap; 284cdf0e10cSrcweir SvMemoryStream aStream; 285cdf0e10cSrcweir // magic value 160 taken from GraphicHelper::getThumbnailFormatFromGDI_Impl() 286cdf0e10cSrcweir if( i_pThumb->CreateThumbnail( 160, aBitmap ) ) { 287*45fd3b9aSArmin Le Grand WriteDIB(aBitmap.GetBitmap(), aStream, false, false); 288cdf0e10cSrcweir // uno::Sequence<sal_uInt8> aSeq(aStream.GetSize()); // WRONG 289cdf0e10cSrcweir aStream.Seek(STREAM_SEEK_TO_END); 290cdf0e10cSrcweir uno::Sequence<sal_uInt8> aSeq(aStream.Tell()); 291cdf0e10cSrcweir const sal_uInt8* pBlob( 292cdf0e10cSrcweir static_cast<const sal_uInt8*>(aStream.GetData())); 293cdf0e10cSrcweir for (sal_Int32 j = 0; j < aSeq.getLength(); ++j) { 294cdf0e10cSrcweir aSeq[j] = pBlob[j]; 295cdf0e10cSrcweir } 296cdf0e10cSrcweir return aSeq; 297cdf0e10cSrcweir } 298cdf0e10cSrcweir } 299cdf0e10cSrcweir return uno::Sequence<sal_uInt8>(); 300cdf0e10cSrcweir } 301cdf0e10cSrcweir 302cdf0e10cSrcweir } // namespace sfx2 303cdf0e10cSrcweir 304