1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <sfx2/docinf.hxx>
32 #include <com/sun/star/beans/PropertyAttribute.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/beans/XPropertyContainer.hpp>
35 #include <com/sun/star/document/XDocumentProperties.hpp>
36 #include <com/sun/star/document/XCompatWriterDocProperties.hpp>
37 #include <com/sun/star/uno/Exception.hpp>
39 #include <rtl/ustring.hxx>
40 #include <tools/debug.hxx>
41 #include <comphelper/string.hxx>
42 #include <sot/storage.hxx>
43 #include <vcl/gdimtf.hxx>
45 #include "oleprops.hxx"
46 // ============================================================================
49 #define STREAM_SUMMARYINFO "\005SummaryInformation"
50 #define STREAM_DOCSUMMARYINFO "\005DocumentSummaryInformation"
53 using namespace ::com::sun::star
;
58 sal_uInt32 SFX2_DLLPUBLIC
LoadOlePropertySet(
59 uno::Reference
< document::XDocumentProperties
> i_xDocProps
,
60 SotStorage
* i_pStorage
)
62 // *** global properties from stream "005SummaryInformation" ***
64 // load the property set
65 SfxOlePropertySet aGlobSet
;
66 ErrCode nGlobError
= aGlobSet
.LoadPropertySet(i_pStorage
,
67 String( STREAM_SUMMARYINFO
) );
70 SfxOleSectionRef xGlobSect
= aGlobSet
.GetSection( SECTION_GLOBAL
);
73 // set supported properties
75 util::DateTime aDateTime
;
77 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_TITLE
) )
78 i_xDocProps
->setTitle( aStrValue
);
79 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_SUBJECT
) )
80 i_xDocProps
->setSubject( aStrValue
);
81 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_KEYWORDS
) ) {
82 i_xDocProps
->setKeywords(
83 ::comphelper::string::convertCommaSeparated(aStrValue
) );
85 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_TEMPLATE
) )
86 i_xDocProps
->setTemplateName( aStrValue
);
87 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_COMMENTS
) )
88 i_xDocProps
->setDescription( aStrValue
);
90 util::DateTime aInvalid
;
91 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_AUTHOR
) )
92 i_xDocProps
->setAuthor( aStrValue
);
94 i_xDocProps
->setAuthor( ::rtl::OUString() );
95 if( xGlobSect
->GetFileTimeValue( aDateTime
, PROPID_CREATED
) )
96 i_xDocProps
->setCreationDate( aDateTime
);
98 i_xDocProps
->setCreationDate( aInvalid
);
100 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_LASTAUTHOR
) )
101 i_xDocProps
->setModifiedBy( aStrValue
);
103 i_xDocProps
->setModifiedBy( ::rtl::OUString() );
104 if( xGlobSect
->GetFileTimeValue( aDateTime
, PROPID_LASTSAVED
) )
105 i_xDocProps
->setModificationDate( aDateTime
);
107 i_xDocProps
->setModificationDate( aInvalid
);
109 i_xDocProps
->setPrintedBy( ::rtl::OUString() );
110 if( xGlobSect
->GetFileTimeValue( aDateTime
, PROPID_LASTPRINTED
) )
111 i_xDocProps
->setPrintDate( aDateTime
);
113 i_xDocProps
->setPrintDate( aInvalid
);
115 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_REVNUMBER
) )
117 sal_Int16 nRevision
= static_cast< sal_Int16
>( aStrValue
.ToInt32() );
119 i_xDocProps
->setEditingCycles( nRevision
);
122 if( xGlobSect
->GetFileTimeValue( aDateTime
, PROPID_EDITTIME
) )
124 // subtract offset 1601-01-01
125 aDateTime
.Year
-= 1601;
126 aDateTime
.Month
-= 1;
130 i_xDocProps
->setEditingDuration(
131 aDateTime
.Day
* 60*60*24 +
132 aDateTime
.Hours
* 60*60 +
133 aDateTime
.Minutes
* 60 +
136 catch (const lang::IllegalArgumentException
&)
143 // *** custom properties from stream "005DocumentSummaryInformation" ***
145 // load the property set
146 SfxOlePropertySet aDocSet
;
147 ErrCode nDocError
= aDocSet
.LoadPropertySet(i_pStorage
,
148 String( STREAM_DOCSUMMARYINFO
) );
151 SfxOleSectionRef xCustomSect
= aDocSet
.GetSection( SECTION_CUSTOM
);
152 if( xCustomSect
.get() )
154 uno::Reference
< beans::XPropertyContainer
> xUserDefined(
155 i_xDocProps
->getUserDefinedProperties(), uno::UNO_QUERY_THROW
);
156 ::std::vector
< sal_Int32
> aPropIds
;
157 xCustomSect
->GetPropertyIds( aPropIds
);
158 for( ::std::vector
< sal_Int32
>::const_iterator aIt
= aPropIds
.begin(),
159 aEnd
= aPropIds
.end(); aIt
!= aEnd
; ++aIt
)
161 ::rtl::OUString aPropName
= xCustomSect
->GetPropertyName( *aIt
);
162 uno::Any aPropValue
= xCustomSect
->GetAnyValue( *aIt
);
163 if( !aPropName
.isEmpty() && aPropValue
.hasValue() )
167 xUserDefined
->addProperty( aPropName
,
168 beans::PropertyAttribute::REMOVEABLE
, aPropValue
);
170 catch (const uno::Exception
&)
178 uno::Reference
< document::XCompatWriterDocProperties
> xWriterProps( i_xDocProps
, uno::UNO_QUERY
);
179 if ( xWriterProps
.is() )
181 SfxOleSectionRef xBuiltin
= aDocSet
.GetSection( SECTION_BUILTIN
);
182 if ( xBuiltin
.get() )
187 if ( xBuiltin
->GetStringValue( aStrValue
, PROPID_MANAGER
) )
188 xWriterProps
->setManager( aStrValue
);
189 if ( xBuiltin
->GetStringValue( aStrValue
, PROPID_CATEGORY
) )
190 xWriterProps
->setCategory( aStrValue
);
191 if ( xBuiltin
->GetStringValue( aStrValue
, PROPID_COMPANY
) )
192 xWriterProps
->setCompany( aStrValue
);
194 catch (const uno::Exception
&)
201 return (nGlobError
!= ERRCODE_NONE
) ? nGlobError
: nDocError
;
204 bool SFX2_DLLPUBLIC
SaveOlePropertySet(
205 uno::Reference
< document::XDocumentProperties
> i_xDocProps
,
206 SotStorage
* i_pStorage
,
207 const uno::Sequence
<sal_uInt8
> * i_pThumb
,
208 const uno::Sequence
<sal_uInt8
> * i_pGuid
,
209 const uno::Sequence
<sal_uInt8
> * i_pHyperlinks
)
211 // *** global properties into stream "005SummaryInformation" ***
213 SfxOlePropertySet aGlobSet
;
215 // set supported properties
216 SfxOleSection
& rGlobSect
= aGlobSet
.AddSection( SECTION_GLOBAL
);
217 rGlobSect
.SetStringValue( PROPID_TITLE
, i_xDocProps
->getTitle() );
218 rGlobSect
.SetStringValue( PROPID_SUBJECT
, i_xDocProps
->getSubject() );
219 String aStr
= ::comphelper::string::convertCommaSeparated(
220 i_xDocProps
->getKeywords() );
221 rGlobSect
.SetStringValue( PROPID_KEYWORDS
, aStr
);
222 rGlobSect
.SetStringValue( PROPID_TEMPLATE
, i_xDocProps
->getTemplateName() );
223 rGlobSect
.SetStringValue( PROPID_COMMENTS
, i_xDocProps
->getDescription() );
224 rGlobSect
.SetStringValue( PROPID_AUTHOR
, i_xDocProps
->getAuthor() );
225 rGlobSect
.SetFileTimeValue(PROPID_CREATED
, i_xDocProps
->getCreationDate());
226 rGlobSect
.SetStringValue( PROPID_LASTAUTHOR
, i_xDocProps
->getModifiedBy() );
227 rGlobSect
.SetFileTimeValue(PROPID_LASTSAVED
,
228 i_xDocProps
->getModificationDate() );
229 // note: apparently PrintedBy is not supported in file format
230 rGlobSect
.SetFileTimeValue(PROPID_LASTPRINTED
, i_xDocProps
->getPrintDate());
232 sal_Int32 dur
= i_xDocProps
->getEditingDuration();
233 util::DateTime aEditTime
;
234 // add offset 1601-01-01
235 aEditTime
.Year
= 1601;
238 aEditTime
.Hours
= static_cast<sal_Int16
>(dur
/ 3600);
239 aEditTime
.Minutes
= static_cast<sal_Int16
>((dur
% 3600) / 60);
240 aEditTime
.Seconds
= static_cast<sal_Int16
>(dur
% 60);
241 rGlobSect
.SetFileTimeValue( PROPID_EDITTIME
, aEditTime
);
243 rGlobSect
.SetStringValue( PROPID_REVNUMBER
,
244 rtl::OUString::valueOf( static_cast<sal_Int32
>(i_xDocProps
->getEditingCycles()) ) );
245 if ( i_pThumb
&& i_pThumb
->getLength() )
246 rGlobSect
.SetThumbnailValue( PROPID_THUMBNAIL
, *i_pThumb
);
248 // save the property set
249 ErrCode nGlobError
= aGlobSet
.SavePropertySet(i_pStorage
,
250 ::rtl::OUString(STREAM_SUMMARYINFO
));
252 // *** custom properties into stream "005DocumentSummaryInformation" ***
254 SfxOlePropertySet aDocSet
;
256 // set builtin properties
257 aDocSet
.AddSection( SECTION_BUILTIN
);
259 // set custom properties
260 SfxOleSection
& rCustomSect
= aDocSet
.AddSection( SECTION_CUSTOM
);
264 const sal_Int32 nPropId
= rCustomSect
.GetFreePropertyId();
265 rCustomSect
.SetBlobValue( nPropId
, *i_pGuid
);
266 rCustomSect
.SetPropertyName( nPropId
,
267 ::rtl::OUString("_PID_GUID") );
272 const sal_Int32 nPropId
= rCustomSect
.GetFreePropertyId();
273 rCustomSect
.SetBlobValue( nPropId
, *i_pHyperlinks
);
274 rCustomSect
.SetPropertyName( nPropId
,
275 ::rtl::OUString("_PID_HLINKS") );
278 uno::Reference
<beans::XPropertySet
> xUserDefinedProps(
279 i_xDocProps
->getUserDefinedProperties(), uno::UNO_QUERY_THROW
);
280 DBG_ASSERT(xUserDefinedProps
.is(), "UserDefinedProperties is null");
281 uno::Reference
<beans::XPropertySetInfo
> xPropInfo
=
282 xUserDefinedProps
->getPropertySetInfo();
283 DBG_ASSERT(xPropInfo
.is(), "UserDefinedProperties Info is null");
284 uno::Sequence
<beans::Property
> props
= xPropInfo
->getProperties();
285 for (sal_Int32 i
= 0; i
< props
.getLength(); ++i
)
289 // skip transient properties
290 if (~props
[i
].Attributes
& beans::PropertyAttribute::TRANSIENT
)
292 const ::rtl::OUString name
= props
[i
].Name
;
293 const sal_Int32 nPropId
= rCustomSect
.GetFreePropertyId();
294 if (rCustomSect
.SetAnyValue( nPropId
,
295 xUserDefinedProps
->getPropertyValue(name
))) {
296 rCustomSect
.SetPropertyName( nPropId
, name
);
300 catch (const uno::Exception
&)
302 // may happen with concurrent modification...
303 DBG_WARNING("SavePropertySet: exception");
307 // save the property set
308 ErrCode nDocError
= aDocSet
.SavePropertySet(i_pStorage
,
309 String( STREAM_DOCSUMMARYINFO
) );
312 return (nGlobError
== ERRCODE_NONE
) && (nDocError
== ERRCODE_NONE
);
315 uno::Sequence
<sal_uInt8
> SFX2_DLLPUBLIC
convertMetaFile(GDIMetaFile
* i_pThumb
)
319 SvMemoryStream aStream
;
320 // magic value 160 taken from GraphicHelper::getThumbnailFormatFromGDI_Impl()
321 if( i_pThumb
->CreateThumbnail( 160, aBitmap
) ) {
322 aBitmap
.GetBitmap().Write( aStream
, sal_False
, sal_False
);
323 aStream
.Seek(STREAM_SEEK_TO_END
);
324 uno::Sequence
<sal_uInt8
> aSeq(aStream
.Tell());
325 const sal_uInt8
* pBlob(
326 static_cast<const sal_uInt8
*>(aStream
.GetData()));
327 for (sal_Int32 j
= 0; j
< aSeq
.getLength(); ++j
) {
333 return uno::Sequence
<sal_uInt8
>();
338 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */