1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: docinf.cxx,v $
10 * $Revision: 1.54.174.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #include <sfx2/docinf.hxx>
36 #include <com/sun/star/beans/PropertyAttribute.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/beans/XPropertyContainer.hpp>
39 #include <com/sun/star/document/XDocumentProperties.hpp>
40 #include <com/sun/star/document/XCompatWriterDocProperties.hpp>
41 #include <com/sun/star/uno/Exception.hpp>
43 #include <rtl/ustring.hxx>
44 #include <tools/debug.hxx>
45 #include <comphelper/string.hxx>
46 #include <sot/storage.hxx>
47 #include <vcl/gdimtf.hxx>
49 #include "oleprops.hxx"
50 // ============================================================================
53 #define STREAM_SUMMARYINFO "\005SummaryInformation"
54 #define STREAM_DOCSUMMARYINFO "\005DocumentSummaryInformation"
57 using namespace ::com::sun::star
;
62 sal_uInt32 SFX2_DLLPUBLIC
LoadOlePropertySet(
63 uno::Reference
< document::XDocumentProperties
> i_xDocProps
,
64 SotStorage
* i_pStorage
)
66 // *** global properties from stream "005SummaryInformation" ***
68 // load the property set
69 SfxOlePropertySet aGlobSet
;
70 ErrCode nGlobError
= aGlobSet
.LoadPropertySet(i_pStorage
,
71 String( RTL_CONSTASCII_USTRINGPARAM( STREAM_SUMMARYINFO
) ) );
74 SfxOleSectionRef xGlobSect
= aGlobSet
.GetSection( SECTION_GLOBAL
);
77 // set supported properties
79 util::DateTime aDateTime
;
81 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_TITLE
) )
82 i_xDocProps
->setTitle( aStrValue
);
83 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_SUBJECT
) )
84 i_xDocProps
->setSubject( aStrValue
);
85 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_KEYWORDS
) ) {
86 i_xDocProps
->setKeywords(
87 ::comphelper::string::convertCommaSeparated(aStrValue
) );
89 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_TEMPLATE
) )
90 i_xDocProps
->setTemplateName( aStrValue
);
91 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_COMMENTS
) )
92 i_xDocProps
->setDescription( aStrValue
);
94 util::DateTime aInvalid
;
95 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_AUTHOR
) )
96 i_xDocProps
->setAuthor( aStrValue
);
98 i_xDocProps
->setAuthor( ::rtl::OUString() );
99 if( xGlobSect
->GetFileTimeValue( aDateTime
, PROPID_CREATED
) )
100 i_xDocProps
->setCreationDate( aDateTime
);
102 i_xDocProps
->setCreationDate( aInvalid
);
104 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_LASTAUTHOR
) )
105 i_xDocProps
->setModifiedBy( aStrValue
);
107 i_xDocProps
->setModifiedBy( ::rtl::OUString() );
108 if( xGlobSect
->GetFileTimeValue( aDateTime
, PROPID_LASTSAVED
) )
109 i_xDocProps
->setModificationDate( aDateTime
);
111 i_xDocProps
->setModificationDate( aInvalid
);
113 i_xDocProps
->setPrintedBy( ::rtl::OUString() );
114 if( xGlobSect
->GetFileTimeValue( aDateTime
, PROPID_LASTPRINTED
) )
115 i_xDocProps
->setPrintDate( aDateTime
);
117 i_xDocProps
->setPrintDate( aInvalid
);
119 if( xGlobSect
->GetStringValue( aStrValue
, PROPID_REVNUMBER
) )
121 sal_Int16 nRevision
= static_cast< sal_Int16
>( aStrValue
.ToInt32() );
123 i_xDocProps
->setEditingCycles( nRevision
);
126 if( xGlobSect
->GetFileTimeValue( aDateTime
, PROPID_EDITTIME
) )
128 // subtract offset 1601-01-01
129 aDateTime
.Year
-= 1601;
130 aDateTime
.Month
-= 1;
134 i_xDocProps
->setEditingDuration(
135 aDateTime
.Day
* 60*60*24 +
136 aDateTime
.Hours
* 60*60 +
137 aDateTime
.Minutes
* 60 +
140 catch (lang::IllegalArgumentException
&)
147 // *** custom properties from stream "005DocumentSummaryInformation" ***
149 // load the property set
150 SfxOlePropertySet aDocSet
;
151 ErrCode nDocError
= aDocSet
.LoadPropertySet(i_pStorage
,
152 String( RTL_CONSTASCII_USTRINGPARAM( STREAM_DOCSUMMARYINFO
) ) );
155 SfxOleSectionRef xCustomSect
= aDocSet
.GetSection( SECTION_CUSTOM
);
156 if( xCustomSect
.get() )
158 uno::Reference
< beans::XPropertyContainer
> xUserDefined(
159 i_xDocProps
->getUserDefinedProperties(), uno::UNO_QUERY_THROW
);
160 ::std::vector
< sal_Int32
> aPropIds
;
161 xCustomSect
->GetPropertyIds( aPropIds
);
162 for( ::std::vector
< sal_Int32
>::const_iterator aIt
= aPropIds
.begin(),
163 aEnd
= aPropIds
.end(); aIt
!= aEnd
; ++aIt
)
165 ::rtl::OUString aPropName
= xCustomSect
->GetPropertyName( *aIt
);
166 uno::Any aPropValue
= xCustomSect
->GetAnyValue( *aIt
);
167 if( (aPropName
.getLength() > 0) && aPropValue
.hasValue() ) {
169 xUserDefined
->addProperty( aPropName
,
170 beans::PropertyAttribute::REMOVEABLE
, aPropValue
);
171 } catch ( 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 ( 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 String::CreateFromInt32( 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 String( RTL_CONSTASCII_USTRINGPARAM( 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::createFromAscii("_PID_GUID") );
272 const sal_Int32 nPropId
= rCustomSect
.GetFreePropertyId();
273 rCustomSect
.SetBlobValue( nPropId
, *i_pHyperlinks
);
274 rCustomSect
.SetPropertyName( nPropId
,
275 ::rtl::OUString::createFromAscii("_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
) {
287 // skip transient properties
288 if (~props
[i
].Attributes
& beans::PropertyAttribute::TRANSIENT
)
290 const ::rtl::OUString name
= props
[i
].Name
;
291 const sal_Int32 nPropId
= rCustomSect
.GetFreePropertyId();
292 if (rCustomSect
.SetAnyValue( nPropId
,
293 xUserDefinedProps
->getPropertyValue(name
))) {
294 rCustomSect
.SetPropertyName( nPropId
, name
);
297 } catch (uno::Exception
&) {
298 // may happen with concurrent modification...
299 DBG_WARNING("SavePropertySet: exception");
303 // save the property set
304 ErrCode nDocError
= aDocSet
.SavePropertySet(i_pStorage
,
305 String( RTL_CONSTASCII_USTRINGPARAM( STREAM_DOCSUMMARYINFO
) ) );
308 return (nGlobError
== ERRCODE_NONE
) && (nDocError
== ERRCODE_NONE
);
311 uno::Sequence
<sal_uInt8
> SFX2_DLLPUBLIC
convertMetaFile(GDIMetaFile
* i_pThumb
)
315 SvMemoryStream aStream
;
316 // magic value 160 taken from GraphicHelper::getThumbnailFormatFromGDI_Impl()
317 if( i_pThumb
->CreateThumbnail( 160, aBitmap
) ) {
318 aBitmap
.GetBitmap().Write( aStream
, FALSE
, FALSE
);
319 // uno::Sequence<sal_uInt8> aSeq(aStream.GetSize()); // WRONG
320 aStream
.Seek(STREAM_SEEK_TO_END
);
321 uno::Sequence
<sal_uInt8
> aSeq(aStream
.Tell());
322 const sal_uInt8
* pBlob(
323 static_cast<const sal_uInt8
*>(aStream
.GetData()));
324 for (sal_Int32 j
= 0; j
< aSeq
.getLength(); ++j
) {
330 return uno::Sequence
<sal_uInt8
>();