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