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