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