Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <sal/config.h>
21 :
22 : #include <boost/noncopyable.hpp>
23 : #include <cppuhelper/compbase6.hxx>
24 : #include <com/sun/star/lang/XServiceInfo.hpp>
25 : #include <com/sun/star/document/XDocumentProperties.hpp>
26 : #include <com/sun/star/lang/XInitialization.hpp>
27 : #include <com/sun/star/util/XCloneable.hpp>
28 : #include <com/sun/star/util/XModifiable.hpp>
29 : #include <com/sun/star/xml/sax/XSAXSerializable.hpp>
30 :
31 : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
32 : #include <com/sun/star/lang/EventObject.hpp>
33 : #include <com/sun/star/beans/XPropertySet.hpp>
34 : #include <com/sun/star/beans/XPropertySetInfo.hpp>
35 : #include <com/sun/star/beans/PropertyAttribute.hpp>
36 : #include <com/sun/star/task/ErrorCodeIOException.hpp>
37 : #include <com/sun/star/embed/XStorage.hpp>
38 : #include <com/sun/star/embed/XTransactedObject.hpp>
39 : #include <com/sun/star/embed/ElementModes.hpp>
40 : #include <com/sun/star/io/XActiveDataControl.hpp>
41 : #include <com/sun/star/io/XActiveDataSource.hpp>
42 : #include <com/sun/star/io/XStream.hpp>
43 : #include <com/sun/star/document/XImporter.hpp>
44 : #include <com/sun/star/document/XExporter.hpp>
45 : #include <com/sun/star/document/XFilter.hpp>
46 : #include <com/sun/star/xml/sax/Parser.hpp>
47 : #include <com/sun/star/xml/sax/Writer.hpp>
48 : #include <com/sun/star/xml/dom/XDocument.hpp>
49 : #include <com/sun/star/xml/dom/XElement.hpp>
50 : #include <com/sun/star/xml/dom/DocumentBuilder.hpp>
51 : #include <com/sun/star/xml/dom/XSAXDocumentBuilder.hpp>
52 : #include <com/sun/star/xml/dom/NodeType.hpp>
53 : #include <com/sun/star/xml/xpath/XPathAPI.hpp>
54 : #include <com/sun/star/util/Date.hpp>
55 : #include <com/sun/star/util/Time.hpp>
56 : #include <com/sun/star/util/DateWithTimezone.hpp>
57 : #include <com/sun/star/util/DateTimeWithTimezone.hpp>
58 : #include <com/sun/star/util/Duration.hpp>
59 :
60 : #include <rtl/ref.hxx>
61 : #include <rtl/ustrbuf.hxx>
62 : #include <tools/debug.hxx>
63 : #include <tools/datetime.hxx>
64 : #include <osl/mutex.hxx>
65 : #include <cppuhelper/basemutex.hxx>
66 : #include <cppuhelper/interfacecontainer.hxx>
67 : #include <comphelper/storagehelper.hxx>
68 : #include <unotools/mediadescriptor.hxx>
69 : #include <comphelper/sequenceasvector.hxx>
70 : #include <sot/storage.hxx>
71 : #include <sfx2/docfile.hxx>
72 : #include <sax/tools/converter.hxx>
73 : #include <i18nlangtag/languagetag.hxx>
74 :
75 : #include <utility>
76 : #include <vector>
77 : #include <map>
78 : #include <cstring>
79 : #include <limits>
80 :
81 :
82 : #include <cppuhelper/implbase1.hxx>
83 : #include <cppuhelper/supportsservice.hxx>
84 : #include <com/sun/star/document/XCompatWriterDocProperties.hpp>
85 : #include <com/sun/star/beans/PropertyBag.hpp>
86 :
87 : /**
88 : * This file contains the implementation of the service
89 : * com.sun.star.document.DocumentProperties.
90 : * This service enables access to the meta-data stored in documents.
91 : * Currently, this service only handles documents in ODF format.
92 : *
93 : * The implementation uses an XML DOM to store the properties.
94 : * This approach was taken because it allows for preserving arbitrary XML data
95 : * in loaded documents, which will be stored unmodified when saving the
96 : * document again.
97 : *
98 : * Upon access, some properties are directly read from and updated in the DOM.
99 : * Exception: it seems impossible to get notified upon addition of a property
100 : * to a com.sun.star.beans.PropertyBag, which is used for storing user-defined
101 : * properties; because of this, user-defined properties are updated in the
102 : * XML DOM only when storing the document.
103 : * Exception 2: when setting certain properties which correspond to attributes
104 : * in the XML DOM, we want to remove the corresponding XML element. Detecting
105 : * this condition can get messy, so we store all such properties as members,
106 : * and update the DOM tree only when storing the document (in
107 : * <method>updateUserDefinedAndAttributes</method>).
108 : *
109 : * @author mst
110 : */
111 :
112 : /// anonymous implementation namespace
113 : namespace {
114 :
115 : /// a list of attribute-lists, where attribute means name and content
116 : typedef std::vector<std::vector<std::pair<const char*, OUString> > >
117 : AttrVector;
118 :
119 : typedef ::cppu::WeakComponentImplHelper6<
120 : css::lang::XServiceInfo,
121 : css::document::XDocumentProperties,
122 : css::lang::XInitialization,
123 : css::util::XCloneable,
124 : css::util::XModifiable,
125 : css::xml::sax::XSAXSerializable>
126 : SfxDocumentMetaData_Base;
127 :
128 : class SfxDocumentMetaData:
129 : private ::cppu::BaseMutex,
130 : public SfxDocumentMetaData_Base,
131 : private boost::noncopyable
132 : {
133 : public:
134 : explicit SfxDocumentMetaData(
135 : css::uno::Reference< css::uno::XComponentContext > const & context);
136 :
137 : // ::com::sun::star::lang::XServiceInfo:
138 : virtual OUString SAL_CALL getImplementationName()
139 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
140 : virtual sal_Bool SAL_CALL supportsService(
141 : const OUString & ServiceName) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
142 : virtual css::uno::Sequence< OUString > SAL_CALL
143 : getSupportedServiceNames() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
144 :
145 : // ::com::sun::star::lang::XComponent:
146 : virtual void SAL_CALL dispose() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
147 :
148 : // ::com::sun::star::document::XDocumentProperties:
149 : virtual OUString SAL_CALL getAuthor()
150 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
151 : virtual void SAL_CALL setAuthor(const OUString & the_value)
152 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
153 : virtual OUString SAL_CALL getGenerator()
154 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
155 : virtual void SAL_CALL setGenerator(const OUString & the_value)
156 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
157 : virtual css::util::DateTime SAL_CALL getCreationDate()
158 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
159 : virtual void SAL_CALL setCreationDate(const css::util::DateTime & the_value)
160 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
161 : virtual OUString SAL_CALL getTitle()
162 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
163 : virtual void SAL_CALL setTitle(const OUString & the_value)
164 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
165 : virtual OUString SAL_CALL getSubject()
166 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
167 : virtual void SAL_CALL setSubject(const OUString & the_value)
168 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
169 : virtual OUString SAL_CALL getDescription()
170 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
171 : virtual void SAL_CALL setDescription(const OUString & the_value)
172 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
173 : virtual css::uno::Sequence< OUString > SAL_CALL getKeywords()
174 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
175 : virtual void SAL_CALL setKeywords(
176 : const css::uno::Sequence< OUString > & the_value)
177 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
178 : virtual css::lang::Locale SAL_CALL getLanguage()
179 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
180 : virtual void SAL_CALL setLanguage(const css::lang::Locale & the_value)
181 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
182 : virtual OUString SAL_CALL getModifiedBy()
183 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
184 : virtual void SAL_CALL setModifiedBy(const OUString & the_value)
185 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
186 : virtual css::util::DateTime SAL_CALL getModificationDate()
187 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
188 : virtual void SAL_CALL setModificationDate(
189 : const css::util::DateTime & the_value)
190 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
191 : virtual OUString SAL_CALL getPrintedBy()
192 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
193 : virtual void SAL_CALL setPrintedBy(const OUString & the_value)
194 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
195 : virtual css::util::DateTime SAL_CALL getPrintDate()
196 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
197 : virtual void SAL_CALL setPrintDate(const css::util::DateTime & the_value)
198 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
199 : virtual OUString SAL_CALL getTemplateName()
200 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
201 : virtual void SAL_CALL setTemplateName(const OUString & the_value)
202 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
203 : virtual OUString SAL_CALL getTemplateURL()
204 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
205 : virtual void SAL_CALL setTemplateURL(const OUString & the_value)
206 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
207 : virtual css::util::DateTime SAL_CALL getTemplateDate()
208 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
209 : virtual void SAL_CALL setTemplateDate(const css::util::DateTime & the_value)
210 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
211 : virtual OUString SAL_CALL getAutoloadURL()
212 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
213 : virtual void SAL_CALL setAutoloadURL(const OUString & the_value)
214 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
215 : virtual ::sal_Int32 SAL_CALL getAutoloadSecs()
216 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
217 : virtual void SAL_CALL setAutoloadSecs(::sal_Int32 the_value)
218 : throw (css::uno::RuntimeException, css::lang::IllegalArgumentException, std::exception) SAL_OVERRIDE;
219 : virtual OUString SAL_CALL getDefaultTarget()
220 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
221 : virtual void SAL_CALL setDefaultTarget(const OUString & the_value)
222 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
223 : virtual css::uno::Sequence< css::beans::NamedValue > SAL_CALL
224 : getDocumentStatistics() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
225 : virtual void SAL_CALL setDocumentStatistics(
226 : const css::uno::Sequence< css::beans::NamedValue > & the_value)
227 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
228 : virtual ::sal_Int16 SAL_CALL getEditingCycles()
229 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
230 : virtual void SAL_CALL setEditingCycles(::sal_Int16 the_value)
231 : throw (css::uno::RuntimeException, css::lang::IllegalArgumentException, std::exception) SAL_OVERRIDE;
232 : virtual ::sal_Int32 SAL_CALL getEditingDuration()
233 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
234 : virtual void SAL_CALL setEditingDuration(::sal_Int32 the_value)
235 : throw (css::uno::RuntimeException, css::lang::IllegalArgumentException, std::exception) SAL_OVERRIDE;
236 : virtual void SAL_CALL resetUserData(const OUString & the_value)
237 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
238 : virtual css::uno::Reference< css::beans::XPropertyContainer > SAL_CALL
239 : getUserDefinedProperties() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
240 : virtual void SAL_CALL loadFromStorage(
241 : const css::uno::Reference< css::embed::XStorage > & Storage,
242 : const css::uno::Sequence< css::beans::PropertyValue > & Medium)
243 : throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
244 : css::io::WrongFormatException,
245 : css::lang::WrappedTargetException, css::io::IOException, std::exception) SAL_OVERRIDE;
246 : virtual void SAL_CALL loadFromMedium(const OUString & URL,
247 : const css::uno::Sequence< css::beans::PropertyValue > & Medium)
248 : throw (css::uno::RuntimeException,
249 : css::io::WrongFormatException,
250 : css::lang::WrappedTargetException, css::io::IOException, std::exception) SAL_OVERRIDE;
251 : virtual void SAL_CALL storeToStorage(
252 : const css::uno::Reference< css::embed::XStorage > & Storage,
253 : const css::uno::Sequence< css::beans::PropertyValue > & Medium)
254 : throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
255 : css::lang::WrappedTargetException, css::io::IOException, std::exception) SAL_OVERRIDE;
256 : virtual void SAL_CALL storeToMedium(const OUString & URL,
257 : const css::uno::Sequence< css::beans::PropertyValue > & Medium)
258 : throw (css::uno::RuntimeException,
259 : css::lang::WrappedTargetException, css::io::IOException, std::exception) SAL_OVERRIDE;
260 :
261 : // ::com::sun::star::lang::XInitialization:
262 : virtual void SAL_CALL initialize(
263 : const css::uno::Sequence< css::uno::Any > & aArguments)
264 : throw (css::uno::RuntimeException, css::uno::Exception, std::exception) SAL_OVERRIDE;
265 :
266 : // ::com::sun::star::util::XCloneable:
267 : virtual css::uno::Reference<css::util::XCloneable> SAL_CALL createClone()
268 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
269 :
270 : // ::com::sun::star::util::XModifiable:
271 : virtual sal_Bool SAL_CALL isModified( )
272 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
273 : virtual void SAL_CALL setModified( sal_Bool bModified )
274 : throw (css::beans::PropertyVetoException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
275 :
276 : // ::com::sun::star::util::XModifyBroadcaster:
277 : virtual void SAL_CALL addModifyListener(
278 : const css::uno::Reference< css::util::XModifyListener > & xListener)
279 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
280 : virtual void SAL_CALL removeModifyListener(
281 : const css::uno::Reference< css::util::XModifyListener > & xListener)
282 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
283 :
284 : // ::com::sun::star::xml::sax::XSAXSerializable
285 : virtual void SAL_CALL serialize(
286 : const css::uno::Reference<css::xml::sax::XDocumentHandler>& i_xHandler,
287 : const css::uno::Sequence< css::beans::StringPair >& i_rNamespaces)
288 : throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception) SAL_OVERRIDE;
289 :
290 : protected:
291 16686 : virtual ~SfxDocumentMetaData() {}
292 1096 : virtual SfxDocumentMetaData* createMe( css::uno::Reference< css::uno::XComponentContext > const & context ) { return new SfxDocumentMetaData( context ); };
293 : const css::uno::Reference< css::uno::XComponentContext > m_xContext;
294 :
295 : /// for notification
296 : ::cppu::OInterfaceContainerHelper m_NotifyListeners;
297 : /// flag: false means not initialized yet, or disposed
298 : bool m_isInitialized;
299 : /// flag
300 : bool m_isModified;
301 : /// meta-data DOM tree
302 : css::uno::Reference< css::xml::dom::XDocument > m_xDoc;
303 : /// meta-data super node in the meta-data DOM tree
304 : css::uno::Reference< css::xml::dom::XNode> m_xParent;
305 : /// standard meta data (single occurrence)
306 : std::map< OUString, css::uno::Reference<css::xml::dom::XNode> >
307 : m_meta;
308 : /// standard meta data (multiple occurrences)
309 : std::map< OUString,
310 : std::vector<css::uno::Reference<css::xml::dom::XNode> > > m_metaList;
311 : /// user-defined meta data (meta:user-defined) @ATTENTION may be null!
312 : css::uno::Reference<css::beans::XPropertyContainer> m_xUserDefined;
313 : // now for some meta-data attributes; these are not updated directly in the
314 : // DOM because updates (detecting "empty" elements) would be quite messy
315 : OUString m_TemplateName;
316 : OUString m_TemplateURL;
317 : css::util::DateTime m_TemplateDate;
318 : OUString m_AutoloadURL;
319 : sal_Int32 m_AutoloadSecs;
320 : OUString m_DefaultTarget;
321 :
322 : /// check if we are initialized properly
323 : void SAL_CALL checkInit() const;
324 : /// initialize state from given DOM tree
325 : void SAL_CALL init(css::uno::Reference<css::xml::dom::XDocument> i_xDom);
326 : /// update element in DOM tree
327 : void SAL_CALL updateElement(const char *i_name,
328 : std::vector<std::pair<const char *, OUString> >* i_pAttrs = 0);
329 : /// update user-defined meta data and attributes in DOM tree
330 : void SAL_CALL updateUserDefinedAndAttributes();
331 : /// create empty DOM tree (XDocument)
332 : css::uno::Reference<css::xml::dom::XDocument> SAL_CALL createDOM() const;
333 : /// extract base URL (necessary for converting relative links)
334 : css::uno::Reference<css::beans::XPropertySet> SAL_CALL getURLProperties(
335 : const css::uno::Sequence<css::beans::PropertyValue> & i_rMedium) const;
336 : /// get text of standard meta data element
337 : OUString SAL_CALL getMetaText(const char* i_name) const;
338 : /// set text of standard meta data element iff not equal to existing text
339 : bool SAL_CALL setMetaText(const char* i_name,
340 : const OUString & i_rValue);
341 : /// set text of standard meta data element iff not equal to existing text
342 : void SAL_CALL setMetaTextAndNotify(const char* i_name,
343 : const OUString & i_rValue);
344 : /// get text of standard meta data element's attribute
345 : OUString SAL_CALL getMetaAttr(const char* i_name,
346 : const char* i_attr) const;
347 : /// get text of a list of standard meta data elements (multiple occ.)
348 : css::uno::Sequence< OUString > SAL_CALL getMetaList(
349 : const char* i_name) const;
350 : /// set text of a list of standard meta data elements (multiple occ.)
351 : bool SAL_CALL setMetaList(const char* i_name,
352 : const css::uno::Sequence< OUString > & i_rValue,
353 : AttrVector const* = 0);
354 : void createUserDefined();
355 : };
356 :
357 : typedef ::cppu::ImplInheritanceHelper1< SfxDocumentMetaData, css::document::XCompatWriterDocProperties > CompatWriterDocPropsImpl_BASE;
358 :
359 0 : class CompatWriterDocPropsImpl : public CompatWriterDocPropsImpl_BASE
360 : {
361 : OUString msManager;
362 : OUString msCategory;
363 : OUString msCompany;
364 : protected:
365 0 : virtual SfxDocumentMetaData* createMe( css::uno::Reference< css::uno::XComponentContext > const & context ) SAL_OVERRIDE { return new CompatWriterDocPropsImpl( context ); };
366 : public:
367 0 : CompatWriterDocPropsImpl( css::uno::Reference< css::uno::XComponentContext > const & context) : CompatWriterDocPropsImpl_BASE( context ) {}
368 : // XCompatWriterDocPropsImpl
369 0 : virtual OUString SAL_CALL getManager() throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE { return msManager; }
370 0 : virtual void SAL_CALL setManager( const OUString& _manager ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE { msManager = _manager; }
371 0 : virtual OUString SAL_CALL getCategory() throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE { return msCategory; }
372 0 : virtual void SAL_CALL setCategory( const OUString& _category ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE { msCategory = _category; }
373 0 : virtual OUString SAL_CALL getCompany() throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE { return msCompany; }
374 0 : virtual void SAL_CALL setCompany( const OUString& _company ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE { msCompany = _company; }
375 :
376 : // XServiceInfo
377 0 : virtual OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
378 : {
379 0 : return OUString("CompatWriterDocPropsImpl");
380 : }
381 :
382 0 : virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
383 : {
384 0 : return cppu::supportsService(this, ServiceName);
385 : }
386 :
387 0 : virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
388 : {
389 0 : css::uno::Sequence< OUString > aServiceNames(1);
390 0 : aServiceNames[ 0 ] = "com.sun.star.writer.DocumentProperties";
391 0 : return aServiceNames;
392 : }
393 : };
394 :
395 32 : bool operator== (const css::util::DateTime &i_rLeft,
396 : const css::util::DateTime &i_rRight)
397 : {
398 32 : return i_rLeft.Year == i_rRight.Year
399 30 : && i_rLeft.Month == i_rRight.Month
400 30 : && i_rLeft.Day == i_rRight.Day
401 30 : && i_rLeft.Hours == i_rRight.Hours
402 30 : && i_rLeft.Minutes == i_rRight.Minutes
403 30 : && i_rLeft.Seconds == i_rRight.Seconds
404 30 : && i_rLeft.NanoSeconds == i_rRight.NanoSeconds
405 62 : && i_rLeft.IsUTC == i_rRight.IsUTC;
406 : }
407 :
408 : // NB: keep these two arrays in sync!
409 : const char* s_stdStatAttrs[] = {
410 : "meta:page-count",
411 : "meta:table-count",
412 : "meta:draw-count",
413 : "meta:image-count",
414 : "meta:object-count",
415 : "meta:ole-object-count",
416 : "meta:paragraph-count",
417 : "meta:word-count",
418 : "meta:character-count",
419 : "meta:row-count",
420 : "meta:frame-count",
421 : "meta:sentence-count",
422 : "meta:syllable-count",
423 : "meta:non-whitespace-character-count",
424 : "meta:cell-count",
425 : 0
426 : };
427 :
428 : // NB: keep these two arrays in sync!
429 : const char* s_stdStats[] = {
430 : "PageCount",
431 : "TableCount",
432 : "DrawCount",
433 : "ImageCount",
434 : "ObjectCount",
435 : "OLEObjectCount",
436 : "ParagraphCount",
437 : "WordCount",
438 : "CharacterCount",
439 : "RowCount",
440 : "FrameCount",
441 : "SentenceCount",
442 : "SyllableCount",
443 : "NonWhitespaceCharacterCount",
444 : "CellCount",
445 : 0
446 : };
447 :
448 : const char* s_stdMeta[] = {
449 : "meta:generator", // string
450 : "dc:title", // string
451 : "dc:description", // string
452 : "dc:subject", // string
453 : "meta:initial-creator", // string
454 : "dc:creator", // string
455 : "meta:printed-by", // string
456 : "meta:creation-date", // dateTime
457 : "dc:date", // dateTime
458 : "meta:print-date", // dateTime
459 : "meta:template", // XLink
460 : "meta:auto-reload",
461 : "meta:hyperlink-behaviour",
462 : "dc:language", // language
463 : "meta:editing-cycles", // nonNegativeInteger
464 : "meta:editing-duration", // duration
465 : "meta:document-statistic", // ... // note: statistic is singular, no s!
466 : 0
467 : };
468 :
469 : const char* s_stdMetaList[] = {
470 : "meta:keyword", // string*
471 : "meta:user-defined", // ...*
472 : 0
473 : };
474 :
475 : const char* s_nsXLink = "http://www.w3.org/1999/xlink";
476 : const char* s_nsDC = "http://purl.org/dc/elements/1.1/";
477 : const char* s_nsODF = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
478 : const char* s_nsODFMeta = "urn:oasis:names:tc:opendocument:xmlns:meta:1.0";
479 : // const char* s_nsOOo = "http://openoffice.org/2004/office"; // not used (yet?)
480 :
481 : static const char s_meta [] = "meta.xml";
482 :
483 2 : bool isValidDate(const css::util::Date & i_rDate)
484 : {
485 2 : return i_rDate.Month > 0;
486 : }
487 :
488 10836 : bool isValidDateTime(const css::util::DateTime & i_rDateTime)
489 : {
490 10836 : return i_rDateTime.Month > 0;
491 : }
492 :
493 : std::pair< OUString, OUString > SAL_CALL
494 448341 : getQualifier(const char* i_name) {
495 448341 : OUString nm = OUString::createFromAscii(i_name);
496 448341 : sal_Int32 ix = nm.indexOf(static_cast<sal_Unicode> (':'));
497 448341 : if (ix == -1) {
498 0 : return std::make_pair(OUString(), nm);
499 : } else {
500 448341 : return std::make_pair(nm.copy(0,ix), nm.copy(ix+1));
501 448341 : }
502 : }
503 :
504 : // get namespace for standard qualified names
505 : // NB: only call this with statically known strings!
506 265755 : OUString SAL_CALL getNameSpace(const char* i_qname) throw ()
507 : {
508 : DBG_ASSERT(i_qname, "SfxDocumentMetaData: getNameSpace: argument is null");
509 265755 : const char * ns = "";
510 265755 : OUString n = getQualifier(i_qname).first;
511 265755 : if ( n == "xlink" ) ns = s_nsXLink;
512 265755 : if ( n == "dc" ) ns = s_nsDC;
513 265755 : if ( n == "office" ) ns = s_nsODF;
514 265755 : if ( n == "meta" ) ns = s_nsODFMeta;
515 : DBG_ASSERT(*ns, "SfxDocumentMetaData: unknown namespace prefix");
516 265755 : return OUString::createFromAscii(ns);
517 : }
518 :
519 : bool SAL_CALL
520 8 : textToDateOrDateTime(css::util::Date & io_rd, css::util::DateTime & io_rdt,
521 : bool & o_rIsDateTime, boost::optional<sal_Int16> & o_rTimeZone,
522 : const OUString& i_text) throw ()
523 : {
524 8 : if (::sax::Converter::parseDateOrDateTime(
525 : &io_rd, io_rdt, o_rIsDateTime, &o_rTimeZone, i_text)) {
526 8 : return true;
527 : } else {
528 : SAL_WARN_IF(!i_text.isEmpty(), "sfx.doc", "Invalid date: " << i_text);
529 0 : return false;
530 : }
531 : }
532 :
533 : // convert string to date/time
534 : bool SAL_CALL
535 21420 : textToDateTime(css::util::DateTime & io_rdt, const OUString& i_text) throw ()
536 : {
537 21420 : if (::sax::Converter::parseDateTime(io_rdt, 0, i_text)) {
538 2424 : return true;
539 : } else {
540 : SAL_WARN_IF(!i_text.isEmpty(), "sfx.doc", "Invalid date: " << i_text);
541 18996 : return false;
542 : }
543 : }
544 :
545 : // convert string to date/time with default return value
546 : css::util::DateTime SAL_CALL
547 21420 : textToDateTimeDefault(const OUString& i_text) throw ()
548 : {
549 21420 : css::util::DateTime dt;
550 21420 : static_cast<void> (textToDateTime(dt, i_text));
551 : // on conversion error: return default value (unchanged)
552 21420 : return dt;
553 : }
554 :
555 : // convert date to string
556 : OUString SAL_CALL
557 2 : dateToText(css::util::Date const& i_rd,
558 : sal_Int16 const*const pTimeZone = 0) throw ()
559 : {
560 2 : if (isValidDate(i_rd)) {
561 2 : OUStringBuffer buf;
562 2 : ::sax::Converter::convertDate(buf, i_rd, pTimeZone);
563 2 : return buf.makeStringAndClear();
564 : } else {
565 0 : return OUString();
566 : }
567 : }
568 :
569 :
570 : // convert date/time to string
571 : OUString SAL_CALL
572 9116 : dateTimeToText(css::util::DateTime const& i_rdt,
573 : sal_Int16 const*const pTimeZone = 0) throw ()
574 : {
575 9116 : if (isValidDateTime(i_rdt)) {
576 8236 : OUStringBuffer buf;
577 8236 : ::sax::Converter::convertDateTime(buf, i_rdt, pTimeZone, true);
578 8236 : return buf.makeStringAndClear();
579 : } else {
580 880 : return OUString();
581 : }
582 : }
583 :
584 : // convert string to duration
585 : bool
586 18756 : textToDuration(css::util::Duration& io_rDur, OUString const& i_rText)
587 : throw ()
588 : {
589 18756 : if (::sax::Converter::convertDuration(io_rDur, i_rText)) {
590 1014 : return true;
591 : } else {
592 : SAL_WARN_IF(!i_rText.isEmpty(), "sfx.doc", "Invalid duration: " << i_rText);
593 17742 : return false;
594 : }
595 : }
596 :
597 18752 : sal_Int32 textToDuration(OUString const& i_rText) throw ()
598 : {
599 18752 : css::util::Duration d;
600 18752 : if (textToDuration(d, i_rText)) {
601 : // #i107372#: approximate years/months
602 1010 : const sal_Int32 days( (d.Years * 365) + (d.Months * 30) + d.Days );
603 1010 : return (days * (24*3600))
604 1010 : + (d.Hours * 3600) + (d.Minutes * 60) + d.Seconds;
605 : } else {
606 17742 : return 0; // default
607 : }
608 : }
609 :
610 : // convert duration to string
611 3128 : OUString durationToText(css::util::Duration const& i_rDur) throw ()
612 : {
613 3128 : OUStringBuffer buf;
614 3128 : ::sax::Converter::convertDuration(buf, i_rDur);
615 3128 : return buf.makeStringAndClear();
616 : }
617 :
618 : // convert duration to string
619 3124 : OUString SAL_CALL durationToText(sal_Int32 i_value) throw ()
620 : {
621 3124 : css::util::Duration ud;
622 3124 : ud.Days = static_cast<sal_Int16>(i_value / (24 * 3600));
623 3124 : ud.Hours = static_cast<sal_Int16>((i_value % (24 * 3600)) / 3600);
624 3124 : ud.Minutes = static_cast<sal_Int16>((i_value % 3600) / 60);
625 3124 : ud.Seconds = static_cast<sal_Int16>(i_value % 60);
626 3124 : ud.NanoSeconds = 0;
627 3124 : return durationToText(ud);
628 : }
629 :
630 : // extract base URL (necessary for converting relative links)
631 : css::uno::Reference< css::beans::XPropertySet > SAL_CALL
632 34 : SfxDocumentMetaData::getURLProperties(
633 : const css::uno::Sequence< css::beans::PropertyValue > & i_rMedium) const
634 : {
635 34 : css::uno::Reference< css::beans::XPropertyBag> xPropArg = css::beans::PropertyBag::createDefault( m_xContext );
636 : try {
637 34 : css::uno::Any baseUri;
638 160 : for (sal_Int32 i = 0; i < i_rMedium.getLength(); ++i) {
639 126 : if (i_rMedium[i].Name == "DocumentBaseURL") {
640 0 : baseUri = i_rMedium[i].Value;
641 126 : } else if (i_rMedium[i].Name == "URL") {
642 34 : if (!baseUri.hasValue()) {
643 34 : baseUri = i_rMedium[i].Value;
644 : }
645 92 : } else if (i_rMedium[i].Name == "HierarchicalDocumentName") {
646 0 : xPropArg->addProperty(
647 : OUString("StreamRelPath"),
648 : css::beans::PropertyAttribute::MAYBEVOID,
649 0 : i_rMedium[i].Value);
650 : }
651 : }
652 34 : if (baseUri.hasValue()) {
653 34 : xPropArg->addProperty(
654 : "BaseURI", css::beans::PropertyAttribute::MAYBEVOID,
655 34 : baseUri);
656 : }
657 34 : xPropArg->addProperty(OUString("StreamName"),
658 : css::beans::PropertyAttribute::MAYBEVOID,
659 34 : css::uno::makeAny(OUString(s_meta)));
660 0 : } catch (const css::uno::Exception &) {
661 : // ignore
662 : }
663 : return css::uno::Reference< css::beans::XPropertySet>(xPropArg,
664 34 : css::uno::UNO_QUERY_THROW);
665 : }
666 :
667 : // return the text of the (hopefully unique, i.e., normalize first!) text
668 : // node _below_ the given node
669 : OUString SAL_CALL
670 21682 : getNodeText(css::uno::Reference<css::xml::dom::XNode> i_xNode)
671 : throw (css::uno::RuntimeException)
672 : {
673 21682 : if (!i_xNode.is()) throw css::uno::RuntimeException(
674 0 : OUString("SfxDocumentMetaData::getNodeText: argument is null"), i_xNode);
675 43364 : for (css::uno::Reference<css::xml::dom::XNode> c = i_xNode->getFirstChild();
676 : c.is();
677 0 : c = c->getNextSibling()) {
678 21464 : if (c->getNodeType() == css::xml::dom::NodeType_TEXT_NODE) {
679 : try {
680 21464 : return c->getNodeValue();
681 0 : } catch (const css::xml::dom::DOMException &) { // too big?
682 0 : return OUString();
683 : }
684 : }
685 218 : }
686 218 : return OUString();
687 : }
688 :
689 : OUString SAL_CALL
690 28332 : SfxDocumentMetaData::getMetaText(const char* i_name) const
691 : // throw (css::uno::RuntimeException)
692 : {
693 28332 : checkInit();
694 :
695 28332 : const OUString name( OUString::createFromAscii(i_name) );
696 : DBG_ASSERT(m_meta.find(name) != m_meta.end(),
697 : "SfxDocumentMetaData::getMetaText: not found");
698 56664 : css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
699 56664 : return (xNode.is()) ? getNodeText(xNode) : OUString();
700 : }
701 :
702 : bool SAL_CALL
703 29666 : SfxDocumentMetaData::setMetaText(const char* i_name,
704 : const OUString & i_rValue)
705 : // throw (css::uno::RuntimeException)
706 : {
707 29666 : checkInit();
708 :
709 29666 : const OUString name( OUString::createFromAscii(i_name) );
710 : DBG_ASSERT(m_meta.find(name) != m_meta.end(),
711 : "SfxDocumentMetaData::setMetaText: not found");
712 59332 : css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
713 :
714 : try {
715 29666 : if (i_rValue.isEmpty()) {
716 3126 : if (xNode.is()) { // delete
717 28 : m_xParent->removeChild(xNode);
718 28 : xNode.clear();
719 28 : m_meta[name] = xNode;
720 28 : return true;
721 : } else {
722 3098 : return false;
723 : }
724 : } else {
725 26540 : if (xNode.is()) { // update
726 2280 : for (css::uno::Reference<css::xml::dom::XNode> c =
727 1140 : xNode->getFirstChild();
728 : c.is();
729 0 : c = c->getNextSibling()) {
730 1138 : if (c->getNodeType() == css::xml::dom::NodeType_TEXT_NODE) {
731 1138 : if (!c->getNodeValue().equals(i_rValue)) {
732 188 : c->setNodeValue(i_rValue);
733 188 : return true;
734 : } else {
735 950 : return false;
736 : }
737 : }
738 2 : }
739 : } else { // insert
740 25400 : xNode.set(m_xDoc->createElementNS(getNameSpace(i_name), name),
741 25400 : css::uno::UNO_QUERY_THROW);
742 25400 : m_xParent->appendChild(xNode);
743 25400 : m_meta[name] = xNode;
744 : }
745 : css::uno::Reference<css::xml::dom::XNode> xTextNode(
746 25402 : m_xDoc->createTextNode(i_rValue), css::uno::UNO_QUERY_THROW);
747 25402 : xNode->appendChild(xTextNode);
748 25402 : return true;
749 : }
750 0 : } catch (const css::xml::dom::DOMException & e) {
751 0 : css::uno::Any a(e);
752 : throw css::lang::WrappedTargetRuntimeException(
753 : OUString("SfxDocumentMetaData::setMetaText: DOM exception"),
754 0 : css::uno::Reference<css::uno::XInterface>(*this), a);
755 29666 : }
756 : }
757 :
758 : void SAL_CALL
759 29602 : SfxDocumentMetaData::setMetaTextAndNotify(const char* i_name,
760 : const OUString & i_rValue)
761 : // throw (css::uno::RuntimeException)
762 : {
763 29602 : ::osl::ClearableMutexGuard g(m_aMutex);
764 29602 : if (setMetaText(i_name, i_rValue)) {
765 25572 : g.clear();
766 25572 : setModified(true);
767 29602 : }
768 29602 : }
769 :
770 : OUString SAL_CALL
771 336384 : SfxDocumentMetaData::getMetaAttr(const char* i_name, const char* i_attr) const
772 : // throw (css::uno::RuntimeException)
773 : {
774 336384 : OUString name = OUString::createFromAscii(i_name);
775 : DBG_ASSERT(m_meta.find(name) != m_meta.end(),
776 : "SfxDocumentMetaData::getMetaAttr: not found");
777 672768 : css::uno::Reference<css::xml::dom::XNode> xNode = m_meta.find(name)->second;
778 336384 : if (xNode.is()) {
779 : css::uno::Reference<css::xml::dom::XElement> xElem(xNode,
780 182586 : css::uno::UNO_QUERY_THROW);
781 182586 : return xElem->getAttributeNS(getNameSpace(i_attr),
782 182586 : getQualifier(i_attr).second);
783 : } else {
784 153798 : return OUString();
785 336384 : }
786 : }
787 :
788 : css::uno::Sequence< OUString> SAL_CALL
789 1172 : SfxDocumentMetaData::getMetaList(const char* i_name) const
790 : // throw (css::uno::RuntimeException)
791 : {
792 1172 : checkInit();
793 1172 : OUString name = OUString::createFromAscii(i_name);
794 : DBG_ASSERT(m_metaList.find(name) != m_metaList.end(),
795 : "SfxDocumentMetaData::getMetaList: not found");
796 : std::vector<css::uno::Reference<css::xml::dom::XNode> > const & vec =
797 1172 : m_metaList.find(name)->second;
798 1172 : css::uno::Sequence< OUString> ret(vec.size());
799 1214 : for (size_t i = 0; i < vec.size(); ++i) {
800 42 : ret[i] = getNodeText(vec.at(i));
801 : }
802 1172 : return ret;
803 : }
804 :
805 : bool SAL_CALL
806 1932 : SfxDocumentMetaData::setMetaList(const char* i_name,
807 : const css::uno::Sequence< OUString> & i_rValue,
808 : AttrVector const* i_pAttrs)
809 : // throw (css::uno::RuntimeException)
810 : {
811 1932 : checkInit();
812 : DBG_ASSERT((i_pAttrs == 0) ||
813 : (static_cast<size_t>(i_rValue.getLength()) == i_pAttrs->size()),
814 : "SfxDocumentMetaData::setMetaList: invalid args");
815 :
816 : try {
817 1932 : OUString name = OUString::createFromAscii(i_name);
818 : DBG_ASSERT(m_metaList.find(name) != m_metaList.end(),
819 : "SfxDocumentMetaData::setMetaList: not found");
820 : std::vector<css::uno::Reference<css::xml::dom::XNode> > & vec =
821 1932 : m_metaList[name];
822 :
823 : // if nothing changed, do nothing
824 : // alas, this does not check for permutations, or attributes...
825 1932 : if ((0 == i_pAttrs)) {
826 212 : if (static_cast<size_t>(i_rValue.getLength()) == vec.size()) {
827 182 : bool isEqual(true);
828 182 : for (sal_Int32 i = 0; i < i_rValue.getLength(); ++i) {
829 2 : css::uno::Reference<css::xml::dom::XNode> xNode(vec.at(i));
830 2 : if (xNode.is()) {
831 2 : OUString val = getNodeText(xNode);
832 2 : if (!val.equals(i_rValue[i])) {
833 2 : isEqual = false;
834 2 : break;
835 0 : }
836 : }
837 0 : }
838 182 : if (isEqual) return false;
839 : }
840 : }
841 :
842 : // remove old meta data nodes
843 : {
844 : std::vector<css::uno::Reference<css::xml::dom::XNode> >
845 1752 : ::reverse_iterator it(vec.rbegin());
846 : try {
847 2068 : for ( ;it != vec.rend(); ++it)
848 : {
849 316 : m_xParent->removeChild(*it);
850 : }
851 : }
852 0 : catch (...)
853 : {
854 : // Clean up already removed nodes
855 0 : vec.erase(it.base(), vec.end());
856 0 : throw;
857 : }
858 1752 : vec.clear();
859 : }
860 :
861 : // insert new meta data nodes into DOM tree
862 7014 : for (sal_Int32 i = 0; i < i_rValue.getLength(); ++i) {
863 : css::uno::Reference<css::xml::dom::XElement> xElem(
864 5262 : m_xDoc->createElementNS(getNameSpace(i_name), name),
865 5262 : css::uno::UNO_QUERY_THROW);
866 : css::uno::Reference<css::xml::dom::XNode> xNode(xElem,
867 10524 : css::uno::UNO_QUERY_THROW);
868 : css::uno::Reference<css::xml::dom::XNode> xTextNode(
869 10524 : m_xDoc->createTextNode(i_rValue[i]), css::uno::UNO_QUERY_THROW);
870 : // set attributes
871 5262 : if (i_pAttrs != 0) {
872 43512 : for (std::vector<std::pair<const char*, OUString> >
873 5184 : ::const_iterator it = (*i_pAttrs)[i].begin();
874 29008 : it != (*i_pAttrs)[i].end(); ++it) {
875 18640 : xElem->setAttributeNS(getNameSpace(it->first),
876 9320 : OUString::createFromAscii(it->first),
877 27960 : it->second);
878 : }
879 : }
880 5262 : xNode->appendChild(xTextNode);
881 5262 : m_xParent->appendChild(xNode);
882 5262 : vec.push_back(xNode);
883 5262 : }
884 :
885 1752 : return true;
886 0 : } catch (const css::xml::dom::DOMException & e) {
887 0 : css::uno::Any a(e);
888 : throw css::lang::WrappedTargetRuntimeException(
889 : OUString("SfxDocumentMetaData::setMetaList: DOM exception"),
890 0 : css::uno::Reference<css::uno::XInterface>(*this), a);
891 : }
892 : }
893 :
894 : // convert property list to string list and attribute list
895 : std::pair<css::uno::Sequence< OUString>, AttrVector> SAL_CALL
896 1720 : propsToStrings(css::uno::Reference<css::beans::XPropertySet> const & i_xPropSet)
897 : {
898 1720 : ::comphelper::SequenceAsVector< OUString > values;
899 3440 : AttrVector attrs;
900 :
901 : css::uno::Reference<css::beans::XPropertySetInfo> xSetInfo
902 3440 : = i_xPropSet->getPropertySetInfo();
903 3440 : css::uno::Sequence<css::beans::Property> props = xSetInfo->getProperties();
904 :
905 6904 : for (sal_Int32 i = 0; i < props.getLength(); ++i) {
906 5184 : if (props[i].Attributes & css::beans::PropertyAttribute::TRANSIENT) {
907 0 : continue;
908 : }
909 5184 : const OUString name = props[i].Name;
910 10368 : css::uno::Any any;
911 : try {
912 5184 : any = i_xPropSet->getPropertyValue(name);
913 0 : } catch (const css::uno::Exception &) {
914 : // ignore
915 : }
916 5184 : const css::uno::Type & type = any.getValueType();
917 10368 : std::vector<std::pair<const char*, OUString> > as;
918 : as.push_back(std::make_pair(static_cast<const char*>("meta:name"),
919 5184 : name));
920 5184 : const char* vt = "meta:value-type";
921 :
922 : // convert according to type
923 5184 : if (type == ::cppu::UnoType<bool>::get()) {
924 3232 : bool b = false;
925 3232 : any >>= b;
926 3232 : OUStringBuffer buf;
927 3232 : ::sax::Converter::convertBool(buf, b);
928 3232 : values.push_back(buf.makeStringAndClear());
929 : as.push_back(std::make_pair(vt,
930 3232 : OUString("boolean")));
931 1952 : } else if (type == ::cppu::UnoType< OUString>::get()) {
932 1110 : OUString s;
933 1110 : any >>= s;
934 1110 : values.push_back(s);
935 : // #i90847# OOo 2.x does stupid things if value-type="string";
936 : // fortunately string is default anyway, so we can just omit it
937 : // #i107502#: however, OOo 2.x only reads 4 user-defined without @value-type
938 : // => best backward compatibility: first 4 without @value-type, rest with
939 1110 : if (4 <= i)
940 : {
941 : as.push_back(std::make_pair(vt,
942 62 : OUString("string")));
943 1110 : }
944 842 : } else if (type == ::cppu::UnoType<css::util::DateTime>::get()) {
945 6 : css::util::DateTime dt;
946 6 : any >>= dt;
947 6 : values.push_back(dateTimeToText(dt));
948 : as.push_back(std::make_pair(vt,
949 6 : OUString("date")));
950 836 : } else if (type == ::cppu::UnoType<css::util::Date>::get()) {
951 2 : css::util::Date d;
952 2 : any >>= d;
953 2 : values.push_back(dateToText(d));
954 : as.push_back(std::make_pair(vt,
955 2 : OUString("date")));
956 834 : } else if (type == ::cppu::UnoType<css::util::DateTimeWithTimezone>::get()) {
957 0 : css::util::DateTimeWithTimezone dttz;
958 0 : any >>= dttz;
959 0 : values.push_back(dateTimeToText(dttz.DateTimeInTZ, &dttz.Timezone));
960 : as.push_back(std::make_pair(vt,
961 0 : OUString("date")));
962 834 : } else if (type == ::cppu::UnoType<css::util::DateWithTimezone>::get()) {
963 0 : css::util::DateWithTimezone dtz;
964 0 : any >>= dtz;
965 0 : values.push_back(dateToText(dtz.DateInTZ, &dtz.Timezone));
966 : as.push_back(std::make_pair(vt,
967 0 : OUString("date")));
968 834 : } else if (type == ::cppu::UnoType<css::util::Time>::get()) {
969 : // #i97029#: replaced by Duration
970 : // Time is supported for backward compatibility with OOo 3.x, x<=2
971 2 : css::util::Time ut;
972 2 : any >>= ut;
973 2 : css::util::Duration ud;
974 2 : ud.Hours = ut.Hours;
975 2 : ud.Minutes = ut.Minutes;
976 2 : ud.Seconds = ut.Seconds;
977 2 : ud.NanoSeconds = ut.NanoSeconds;
978 2 : values.push_back(durationToText(ud));
979 : as.push_back(std::make_pair(vt,
980 2 : OUString("time")));
981 832 : } else if (type == ::cppu::UnoType<css::util::Duration>::get()) {
982 2 : css::util::Duration ud;
983 2 : any >>= ud;
984 2 : values.push_back(durationToText(ud));
985 : as.push_back(std::make_pair(vt,
986 2 : OUString("time")));
987 830 : } else if (::cppu::UnoType<double>::get().isAssignableFrom(type)) {
988 : // support not just double, but anything that can be converted
989 830 : double d = 0;
990 830 : any >>= d;
991 830 : OUStringBuffer buf;
992 830 : ::sax::Converter::convertDouble(buf, d);
993 830 : values.push_back(buf.makeStringAndClear());
994 : as.push_back(std::make_pair(vt,
995 830 : OUString("float")));
996 : } else {
997 : SAL_WARN("sfx.doc", "Unsupported property type: " << any.getValueTypeName() );
998 0 : continue;
999 : }
1000 5184 : attrs.push_back(as);
1001 5184 : }
1002 :
1003 3440 : return std::make_pair(values.getAsConstList(), attrs);
1004 : }
1005 :
1006 : // remove the given element from the DOM, and iff i_pAttrs != 0 insert new one
1007 : void SAL_CALL
1008 14575 : SfxDocumentMetaData::updateElement(const char *i_name,
1009 : std::vector<std::pair<const char *, OUString> >* i_pAttrs)
1010 : {
1011 14575 : OUString name = OUString::createFromAscii(i_name);
1012 : try {
1013 : // remove old element
1014 : css::uno::Reference<css::xml::dom::XNode> xNode =
1015 14575 : m_meta.find(name)->second;
1016 14575 : if (xNode.is()) {
1017 5897 : m_xParent->removeChild(xNode);
1018 5897 : xNode.clear();
1019 : }
1020 : // add new element
1021 14575 : if (0 != i_pAttrs) {
1022 : css::uno::Reference<css::xml::dom::XElement> xElem(
1023 10261 : m_xDoc->createElementNS(getNameSpace(i_name), name),
1024 10261 : css::uno::UNO_QUERY_THROW);
1025 10261 : xNode.set(xElem, css::uno::UNO_QUERY_THROW);
1026 : // set attributes
1027 129561 : for (std::vector<std::pair<const char *, OUString> >
1028 10261 : ::const_iterator it = i_pAttrs->begin();
1029 86374 : it != i_pAttrs->end(); ++it) {
1030 65852 : xElem->setAttributeNS(getNameSpace(it->first),
1031 65852 : OUString::createFromAscii(it->first), it->second);
1032 : }
1033 10261 : m_xParent->appendChild(xNode);
1034 : }
1035 14575 : m_meta[name] = xNode;
1036 0 : } catch (const css::xml::dom::DOMException & e) {
1037 0 : css::uno::Any a(e);
1038 : throw css::lang::WrappedTargetRuntimeException(
1039 : OUString("SfxDocumentMetaData::updateElement: DOM exception"),
1040 0 : css::uno::Reference<css::uno::XInterface>(*this), a);
1041 14575 : }
1042 14575 : }
1043 :
1044 : // update user-defined meta data in DOM tree
1045 1720 : void SAL_CALL SfxDocumentMetaData::updateUserDefinedAndAttributes()
1046 : {
1047 1720 : createUserDefined();
1048 : const css::uno::Reference<css::beans::XPropertySet> xPSet(m_xUserDefined,
1049 1720 : css::uno::UNO_QUERY_THROW);
1050 : const std::pair<css::uno::Sequence< OUString>, AttrVector>
1051 3440 : udStringsAttrs( propsToStrings(xPSet) );
1052 : (void) setMetaList("meta:user-defined", udStringsAttrs.first,
1053 1720 : &udStringsAttrs.second);
1054 :
1055 : // update elements with attributes
1056 3440 : std::vector<std::pair<const char *, OUString> > attributes;
1057 4318 : if (!m_TemplateName.isEmpty() || !m_TemplateURL.isEmpty()
1058 2598 : || isValidDateTime(m_TemplateDate)) {
1059 : attributes.push_back(std::make_pair(
1060 : static_cast<const char*>("xlink:type"),
1061 842 : OUString("simple")));
1062 : attributes.push_back(std::make_pair(
1063 : static_cast<const char*>("xlink:actuate"),
1064 842 : OUString("onRequest")));
1065 : attributes.push_back(std::make_pair(
1066 842 : static_cast<const char*>("xlink:title"), m_TemplateName));
1067 : attributes.push_back(std::make_pair(
1068 842 : static_cast<const char*>("xlink:href" ), m_TemplateURL ));
1069 842 : if (isValidDateTime(m_TemplateDate)) {
1070 : attributes.push_back(std::make_pair(
1071 : static_cast<const char*>("meta:date" ),
1072 2 : dateTimeToText(m_TemplateDate)));
1073 : }
1074 842 : updateElement("meta:template", &attributes);
1075 : } else {
1076 878 : updateElement("meta:template");
1077 : }
1078 1720 : attributes.clear();
1079 :
1080 1720 : if (!m_AutoloadURL.isEmpty() || (0 != m_AutoloadSecs)) {
1081 : attributes.push_back(std::make_pair(
1082 2 : static_cast<const char*>("xlink:href" ), m_AutoloadURL ));
1083 : attributes.push_back(std::make_pair(
1084 : static_cast<const char*>("meta:delay" ),
1085 2 : durationToText(m_AutoloadSecs)));
1086 2 : updateElement("meta:auto-reload", &attributes);
1087 : } else {
1088 1718 : updateElement("meta:auto-reload");
1089 : }
1090 1720 : attributes.clear();
1091 :
1092 1720 : if (!m_DefaultTarget.isEmpty()) {
1093 : attributes.push_back(std::make_pair(
1094 : static_cast<const char*>("office:target-frame-name"),
1095 2 : m_DefaultTarget));
1096 : // xlink:show: _blank -> new, any other value -> replace
1097 2 : const sal_Char* show = m_DefaultTarget == "_blank" ? "new" : "replace";
1098 : attributes.push_back(std::make_pair(
1099 : static_cast<const char*>("xlink:show"),
1100 2 : OUString::createFromAscii(show)));
1101 2 : updateElement("meta:hyperlink-behaviour", &attributes);
1102 : } else {
1103 1718 : updateElement("meta:hyperlink-behaviour");
1104 : }
1105 3440 : attributes.clear();
1106 1720 : }
1107 :
1108 : // create empty DOM tree (XDocument)
1109 : css::uno::Reference<css::xml::dom::XDocument> SAL_CALL
1110 16702 : SfxDocumentMetaData::createDOM() const // throw (css::uno::RuntimeException)
1111 : {
1112 16702 : css::uno::Reference<css::lang::XMultiComponentFactory> xMsf ( m_xContext->getServiceManager());
1113 33404 : css::uno::Reference<css::xml::dom::XDocumentBuilder> xBuilder( css::xml::dom::DocumentBuilder::create(m_xContext) );
1114 16702 : css::uno::Reference<css::xml::dom::XDocument> xDoc = xBuilder->newDocument();
1115 16702 : if (!xDoc.is()) throw css::uno::RuntimeException(
1116 : OUString("SfxDocumentMetaData::createDOM: "
1117 : "cannot create new document"),
1118 0 : *const_cast<SfxDocumentMetaData*>(this));
1119 33404 : return xDoc;
1120 : }
1121 :
1122 : void SAL_CALL
1123 177658 : SfxDocumentMetaData::checkInit() const // throw (css::uno::RuntimeException)
1124 : {
1125 177658 : if (!m_isInitialized) {
1126 : throw css::uno::RuntimeException(OUString(
1127 : "SfxDocumentMetaData::checkInit: not initialized"),
1128 0 : *const_cast<SfxDocumentMetaData*>(this));
1129 : }
1130 : DBG_ASSERT((m_xDoc.is() && m_xParent.is() ),
1131 : "SfxDocumentMetaData::checkInit: reference is null");
1132 177658 : }
1133 :
1134 : // initialize state from DOM tree
1135 17684 : void SAL_CALL SfxDocumentMetaData::init(
1136 : css::uno::Reference<css::xml::dom::XDocument> i_xDoc)
1137 : {
1138 17684 : if (!i_xDoc.is()) throw css::uno::RuntimeException(
1139 0 : OUString("SfxDocumentMetaData::init: no DOM tree given"), *this);
1140 :
1141 17684 : css::uno::Reference<css::xml::xpath::XXPathAPI> xPath = css::xml::xpath::XPathAPI::create(m_xContext);
1142 :
1143 17684 : m_isInitialized = false;
1144 17684 : m_xDoc = i_xDoc;
1145 :
1146 : // select nodes for standard meta data stuff
1147 17684 : xPath->registerNS(OUString("xlink"),
1148 17684 : OUString::createFromAscii(s_nsXLink));
1149 17684 : xPath->registerNS(OUString("dc"),
1150 17684 : OUString::createFromAscii(s_nsDC));
1151 17684 : xPath->registerNS(OUString("office"),
1152 17684 : OUString::createFromAscii(s_nsODF));
1153 17684 : xPath->registerNS(OUString("meta"),
1154 17684 : OUString::createFromAscii(s_nsODFMeta));
1155 : // NB: we do not handle the single-XML-file ODF variant, which would
1156 : // have the root element office:document.
1157 : // The root of such documents must be converted in the importer!
1158 : OUString prefix(
1159 35368 : "/child::office:document-meta/child::office:meta");
1160 : css::uno::Reference<css::xml::dom::XNode> xDocNode(
1161 35368 : m_xDoc, css::uno::UNO_QUERY_THROW);
1162 17684 : m_xParent.clear();
1163 : try {
1164 17684 : m_xParent = xPath->selectSingleNode(xDocNode, prefix);
1165 15606 : } catch (const com::sun::star::uno::Exception &) {
1166 : }
1167 :
1168 17684 : if (!m_xParent.is()) {
1169 : // all this create/append stuff may throw DOMException
1170 : try {
1171 15742 : css::uno::Reference<css::xml::dom::XElement> xRElem;
1172 : css::uno::Reference<css::xml::dom::XNode> xNode(
1173 31484 : i_xDoc->getFirstChild());
1174 31484 : while (xNode.is()) {
1175 136 : if (css::xml::dom::NodeType_ELEMENT_NODE ==xNode->getNodeType())
1176 : {
1177 136 : if ( xNode->getNamespaceURI().equalsAscii(s_nsODF) && xNode->getLocalName() == "document-meta" )
1178 : {
1179 136 : xRElem.set(xNode, css::uno::UNO_QUERY_THROW);
1180 136 : break;
1181 : }
1182 : else
1183 : {
1184 : OSL_TRACE("SfxDocumentMetaData::init(): "
1185 : "deleting unexpected root element: %s",
1186 : OUStringToOString(xNode->getLocalName(),
1187 : RTL_TEXTENCODING_UTF8).getStr());
1188 0 : i_xDoc->removeChild(xNode);
1189 0 : xNode = i_xDoc->getFirstChild(); // start over
1190 : }
1191 : } else {
1192 0 : xNode = xNode->getNextSibling();
1193 : }
1194 : }
1195 15742 : if (!xRElem.is()) {
1196 46818 : xRElem = i_xDoc->createElementNS(
1197 : OUString::createFromAscii(s_nsODF),
1198 31212 : OUString("office:document-meta"));
1199 : css::uno::Reference<css::xml::dom::XNode> xRNode(xRElem,
1200 15606 : css::uno::UNO_QUERY_THROW);
1201 15606 : i_xDoc->appendChild(xRNode);
1202 : }
1203 15742 : xRElem->setAttributeNS(OUString::createFromAscii(s_nsODF),
1204 : OUString("office:version"),
1205 15742 : OUString("1.0"));
1206 : // does not exist, otherwise m_xParent would not be null
1207 : css::uno::Reference<css::xml::dom::XNode> xParent (
1208 15742 : i_xDoc->createElementNS(
1209 : OUString::createFromAscii(s_nsODF),
1210 15742 : OUString("office:meta")),
1211 31484 : css::uno::UNO_QUERY_THROW);
1212 15742 : xRElem->appendChild(xParent);
1213 31484 : m_xParent = xParent;
1214 0 : } catch (const css::xml::dom::DOMException & e) {
1215 0 : css::uno::Any a(e);
1216 : throw css::lang::WrappedTargetRuntimeException(
1217 : OUString("SfxDocumentMetaData::init: DOM exception"),
1218 0 : css::uno::Reference<css::uno::XInterface>(*this), a);
1219 : }
1220 : }
1221 :
1222 :
1223 : // select nodes for elements of which we only handle one occurrence
1224 318312 : for (const char **pName = s_stdMeta; *pName != 0; ++pName) {
1225 300628 : OUString name = OUString::createFromAscii(*pName);
1226 : // NB: If a document contains more than one occurrence of a
1227 : // meta-data element, we arbitrarily pick one of them here.
1228 : // We do not remove the others, i.e., when we write the
1229 : // document, it will contain the duplicates unchanged.
1230 : // The ODF spec says that handling multiple occurrences is
1231 : // application-specific.
1232 : css::uno::Reference<css::xml::dom::XNode> xNode =
1233 300628 : xPath->selectSingleNode(m_xParent,
1234 601256 : OUString("child::") + name);
1235 : // Do not create an empty element if it is missing;
1236 : // for certain elements, such as dateTime, this would be invalid
1237 300628 : m_meta[name] = xNode;
1238 300628 : }
1239 :
1240 : // select nodes for elements of which we handle all occurrences
1241 53052 : for (const char **pName = s_stdMetaList; *pName != 0; ++pName) {
1242 35368 : OUString name = OUString::createFromAscii(*pName);
1243 : css::uno::Reference<css::xml::dom::XNodeList> nodes =
1244 35368 : xPath->selectNodeList(m_xParent,
1245 70736 : OUString("child::") + name);
1246 70736 : std::vector<css::uno::Reference<css::xml::dom::XNode> > v;
1247 41070 : for (sal_Int32 i = 0; i < nodes->getLength(); ++i) {
1248 5702 : v.push_back(nodes->item(i));
1249 : }
1250 35368 : m_metaList[name] = v;
1251 35368 : }
1252 :
1253 : // initialize members corresponding to attributes from DOM nodes
1254 17684 : m_TemplateName = getMetaAttr("meta:template", "xlink:title");
1255 17684 : m_TemplateURL = getMetaAttr("meta:template", "xlink:href");
1256 : m_TemplateDate =
1257 17684 : textToDateTimeDefault(getMetaAttr("meta:template", "meta:date"));
1258 17684 : m_AutoloadURL = getMetaAttr("meta:auto-reload", "xlink:href");
1259 : m_AutoloadSecs =
1260 17684 : textToDuration(getMetaAttr("meta:auto-reload", "meta:delay"));
1261 35368 : m_DefaultTarget =
1262 17684 : getMetaAttr("meta:hyperlink-behaviour", "office:target-frame-name");
1263 :
1264 :
1265 : std::vector<css::uno::Reference<css::xml::dom::XNode> > & vec =
1266 17684 : m_metaList[OUString("meta:user-defined")];
1267 17684 : m_xUserDefined.clear(); // #i105826#: reset (may be re-initialization)
1268 17684 : if ( !vec.empty() )
1269 : {
1270 916 : createUserDefined();
1271 : }
1272 :
1273 : // user-defined meta data: initialize PropertySet from DOM nodes
1274 70056 : for (std::vector<css::uno::Reference<css::xml::dom::XNode> >::iterator
1275 64388 : it = vec.begin(); it != vec.end(); ++it) {
1276 5668 : css::uno::Reference<css::xml::dom::XElement> xElem(*it,
1277 5668 : css::uno::UNO_QUERY_THROW);
1278 11336 : css::uno::Any any;
1279 5668 : OUString name = xElem->getAttributeNS(
1280 : OUString::createFromAscii(s_nsODFMeta),
1281 11336 : OUString("name"));
1282 5668 : OUString type = xElem->getAttributeNS(
1283 : OUString::createFromAscii(s_nsODFMeta),
1284 11336 : OUString("value-type"));
1285 11336 : OUString text = getNodeText(*it);
1286 5668 : if ( type == "float" ) {
1287 : double d;
1288 876 : if (::sax::Converter::convertDouble(d, text)) {
1289 876 : any <<= d;
1290 : } else {
1291 : SAL_WARN("sfx.doc", "Invalid float: " << text);
1292 0 : continue;
1293 : }
1294 4792 : } else if ( type == "date" ) {
1295 : bool isDateTime;
1296 8 : css::util::Date d;
1297 8 : css::util::DateTime dt;
1298 8 : boost::optional<sal_Int16> nTimeZone;
1299 8 : if (textToDateOrDateTime(d, dt, isDateTime, nTimeZone, text)) {
1300 8 : if (isDateTime) {
1301 6 : if (nTimeZone.is_initialized()) {
1302 0 : any <<= css::util::DateTimeWithTimezone(dt,
1303 0 : nTimeZone.get());
1304 : } else {
1305 6 : any <<= dt;
1306 : }
1307 : } else {
1308 2 : if (nTimeZone.is_initialized()) {
1309 0 : any <<= css::util::DateWithTimezone(d, nTimeZone.get());
1310 : } else {
1311 2 : any <<= d;
1312 : }
1313 : }
1314 : } else {
1315 : SAL_WARN("sfx.doc", "Invalid date: " << text);
1316 0 : continue;
1317 8 : }
1318 4784 : } else if ( type == "time" ) {
1319 4 : css::util::Duration ud;
1320 4 : if (textToDuration(ud, text)) {
1321 4 : any <<= ud;
1322 : } else {
1323 : SAL_WARN("sfx.doc", "Invalid time: " << text);
1324 0 : continue;
1325 : }
1326 4780 : } else if ( type == "boolean" ) {
1327 : bool b;
1328 3416 : if (::sax::Converter::convertBool(b, text)) {
1329 3416 : any <<= b;
1330 : } else {
1331 : SAL_WARN("sfx.doc", "Invalid boolean: " << text);
1332 0 : continue;
1333 : }
1334 1364 : } else if ( type == "string" || true) { // default
1335 1364 : any <<= text;
1336 : }
1337 : try {
1338 5668 : m_xUserDefined->addProperty(name,
1339 5668 : css::beans::PropertyAttribute::REMOVABLE, any);
1340 0 : } catch (const css::beans::PropertyExistException &) {
1341 : SAL_WARN("sfx.doc", "Duplicate: " << name);
1342 : // ignore; duplicate
1343 0 : } catch (const css::beans::IllegalTypeException &) {
1344 : OSL_TRACE("SfxDocumentMetaData: illegal type: %s",
1345 : OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr());
1346 0 : } catch (const css::lang::IllegalArgumentException &) {
1347 : OSL_TRACE("SfxDocumentMetaData: illegal arg: %s",
1348 : OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr());
1349 : }
1350 5668 : }
1351 :
1352 17684 : m_isModified = false;
1353 35368 : m_isInitialized = true;
1354 17684 : }
1355 :
1356 :
1357 :
1358 8352 : SfxDocumentMetaData::SfxDocumentMetaData(
1359 : css::uno::Reference< css::uno::XComponentContext > const & context)
1360 : : BaseMutex()
1361 : , SfxDocumentMetaData_Base(m_aMutex)
1362 : , m_xContext(context)
1363 : , m_NotifyListeners(m_aMutex)
1364 : , m_isInitialized(false)
1365 : , m_isModified(false)
1366 8352 : , m_AutoloadSecs(0)
1367 : {
1368 : DBG_ASSERT(context.is(), "SfxDocumentMetaData: context is null");
1369 : DBG_ASSERT(context->getServiceManager().is(),
1370 : "SfxDocumentMetaData: context has no service manager");
1371 8352 : init(createDOM());
1372 8352 : }
1373 :
1374 : // com.sun.star.uno.XServiceInfo:
1375 : OUString SAL_CALL
1376 0 : SfxDocumentMetaData::getImplementationName() throw (css::uno::RuntimeException, std::exception)
1377 : {
1378 0 : return OUString("SfxDocumentMetaData");
1379 : }
1380 :
1381 : sal_Bool SAL_CALL
1382 0 : SfxDocumentMetaData::supportsService(OUString const & serviceName)
1383 : throw (css::uno::RuntimeException, std::exception)
1384 : {
1385 0 : return cppu::supportsService(this, serviceName);
1386 : }
1387 :
1388 : css::uno::Sequence< OUString > SAL_CALL
1389 0 : SfxDocumentMetaData::getSupportedServiceNames()
1390 : throw (css::uno::RuntimeException, std::exception)
1391 : {
1392 0 : css::uno::Sequence< OUString > s(1);
1393 0 : s[0] = "com.sun.star.document.DocumentProperties";
1394 0 : return s;
1395 : }
1396 :
1397 :
1398 : // ::com::sun::star::lang::XComponent:
1399 8343 : void SAL_CALL SfxDocumentMetaData::dispose() throw (css::uno::RuntimeException, std::exception)
1400 : {
1401 8343 : ::osl::MutexGuard g(m_aMutex);
1402 8343 : if (!m_isInitialized) {
1403 8343 : return;
1404 : }
1405 8343 : WeakComponentImplHelperBase::dispose(); // superclass
1406 : m_NotifyListeners.disposeAndClear(css::lang::EventObject(
1407 8343 : static_cast< ::cppu::OWeakObject* >(this)));
1408 8343 : m_isInitialized = false;
1409 8343 : m_meta.clear();
1410 8343 : m_metaList.clear();
1411 8343 : m_xParent.clear();
1412 8343 : m_xDoc.clear();
1413 8343 : m_xUserDefined.clear();
1414 : }
1415 :
1416 :
1417 : // ::com::sun::star::document::XDocumentProperties:
1418 : OUString SAL_CALL
1419 5914 : SfxDocumentMetaData::getAuthor() throw (css::uno::RuntimeException, std::exception)
1420 : {
1421 5914 : ::osl::MutexGuard g(m_aMutex);
1422 5914 : return getMetaText("meta:initial-creator");
1423 : }
1424 :
1425 4060 : void SAL_CALL SfxDocumentMetaData::setAuthor(const OUString & the_value)
1426 : throw (css::uno::RuntimeException, std::exception)
1427 : {
1428 4060 : setMetaTextAndNotify("meta:initial-creator", the_value);
1429 4060 : }
1430 :
1431 :
1432 : OUString SAL_CALL
1433 4580 : SfxDocumentMetaData::getGenerator() throw (css::uno::RuntimeException, std::exception)
1434 : {
1435 4580 : ::osl::MutexGuard g(m_aMutex);
1436 4580 : return getMetaText("meta:generator");
1437 : }
1438 :
1439 : void SAL_CALL
1440 4738 : SfxDocumentMetaData::setGenerator(const OUString & the_value)
1441 : throw (css::uno::RuntimeException, std::exception)
1442 : {
1443 4738 : setMetaTextAndNotify("meta:generator", the_value);
1444 4738 : }
1445 :
1446 : css::util::DateTime SAL_CALL
1447 1282 : SfxDocumentMetaData::getCreationDate() throw (css::uno::RuntimeException, std::exception)
1448 : {
1449 1282 : ::osl::MutexGuard g(m_aMutex);
1450 1282 : return textToDateTimeDefault(getMetaText("meta:creation-date"));
1451 : }
1452 :
1453 : void SAL_CALL
1454 4676 : SfxDocumentMetaData::setCreationDate(const css::util::DateTime & the_value)
1455 : throw (css::uno::RuntimeException, std::exception)
1456 : {
1457 4676 : setMetaTextAndNotify("meta:creation-date", dateTimeToText(the_value));
1458 4676 : }
1459 :
1460 : OUString SAL_CALL
1461 2632 : SfxDocumentMetaData::getTitle() throw (css::uno::RuntimeException, std::exception)
1462 : {
1463 2632 : ::osl::MutexGuard g(m_aMutex);
1464 2632 : return getMetaText("dc:title");
1465 : }
1466 :
1467 670 : void SAL_CALL SfxDocumentMetaData::setTitle(const OUString & the_value)
1468 : throw (css::uno::RuntimeException, std::exception)
1469 : {
1470 670 : setMetaTextAndNotify("dc:title", the_value);
1471 670 : }
1472 :
1473 : OUString SAL_CALL
1474 1282 : SfxDocumentMetaData::getSubject() throw (css::uno::RuntimeException, std::exception)
1475 : {
1476 1282 : ::osl::MutexGuard g(m_aMutex);
1477 1282 : return getMetaText("dc:subject");
1478 : }
1479 :
1480 : void SAL_CALL
1481 298 : SfxDocumentMetaData::setSubject(const OUString & the_value)
1482 : throw (css::uno::RuntimeException, std::exception)
1483 : {
1484 298 : setMetaTextAndNotify("dc:subject", the_value);
1485 298 : }
1486 :
1487 : OUString SAL_CALL
1488 1172 : SfxDocumentMetaData::getDescription() throw (css::uno::RuntimeException, std::exception)
1489 : {
1490 1172 : ::osl::MutexGuard g(m_aMutex);
1491 1172 : return getMetaText("dc:description");
1492 : }
1493 :
1494 : void SAL_CALL
1495 176 : SfxDocumentMetaData::setDescription(const OUString & the_value)
1496 : throw (css::uno::RuntimeException, std::exception)
1497 : {
1498 176 : setMetaTextAndNotify("dc:description", the_value);
1499 176 : }
1500 :
1501 : css::uno::Sequence< OUString >
1502 1172 : SAL_CALL SfxDocumentMetaData::getKeywords() throw (css::uno::RuntimeException, std::exception)
1503 : {
1504 1172 : ::osl::MutexGuard g(m_aMutex);
1505 1172 : return getMetaList("meta:keyword");
1506 : }
1507 :
1508 : void SAL_CALL
1509 212 : SfxDocumentMetaData::setKeywords(
1510 : const css::uno::Sequence< OUString > & the_value)
1511 : throw (css::uno::RuntimeException, std::exception)
1512 : {
1513 212 : ::osl::ClearableMutexGuard g(m_aMutex);
1514 212 : if (setMetaList("meta:keyword", the_value)) {
1515 32 : g.clear();
1516 32 : setModified(true);
1517 212 : }
1518 212 : }
1519 :
1520 : css::lang::Locale SAL_CALL
1521 942 : SfxDocumentMetaData::getLanguage() throw (css::uno::RuntimeException, std::exception)
1522 : {
1523 942 : ::osl::MutexGuard g(m_aMutex);
1524 942 : css::lang::Locale loc( LanguageTag( getMetaText("dc:language")).getLocale( false));
1525 942 : return loc;
1526 : }
1527 :
1528 : void SAL_CALL
1529 1042 : SfxDocumentMetaData::setLanguage(const css::lang::Locale & the_value)
1530 : throw (css::uno::RuntimeException, std::exception)
1531 : {
1532 1042 : OUString text( LanguageTag::convertToBcp47( the_value, false));
1533 1042 : setMetaTextAndNotify("dc:language", text);
1534 1042 : }
1535 :
1536 : OUString SAL_CALL
1537 5908 : SfxDocumentMetaData::getModifiedBy() throw (css::uno::RuntimeException, std::exception)
1538 : {
1539 5908 : ::osl::MutexGuard g(m_aMutex);
1540 5908 : return getMetaText("dc:creator");
1541 : }
1542 :
1543 : void SAL_CALL
1544 2896 : SfxDocumentMetaData::setModifiedBy(const OUString & the_value)
1545 : throw (css::uno::RuntimeException, std::exception)
1546 : {
1547 2896 : setMetaTextAndNotify("dc:creator", the_value);
1548 2896 : }
1549 :
1550 : css::util::DateTime SAL_CALL
1551 1280 : SfxDocumentMetaData::getModificationDate() throw (css::uno::RuntimeException, std::exception)
1552 : {
1553 1280 : ::osl::MutexGuard g(m_aMutex);
1554 1280 : return textToDateTimeDefault(getMetaText("dc:date"));
1555 : }
1556 :
1557 : void SAL_CALL
1558 3346 : SfxDocumentMetaData::setModificationDate(const css::util::DateTime & the_value)
1559 : throw (css::uno::RuntimeException, std::exception)
1560 : {
1561 3346 : setMetaTextAndNotify("dc:date", dateTimeToText(the_value));
1562 3346 : }
1563 :
1564 : OUString SAL_CALL
1565 30 : SfxDocumentMetaData::getPrintedBy() throw (css::uno::RuntimeException, std::exception)
1566 : {
1567 30 : ::osl::MutexGuard g(m_aMutex);
1568 30 : return getMetaText("meta:printed-by");
1569 : }
1570 :
1571 : void SAL_CALL
1572 354 : SfxDocumentMetaData::setPrintedBy(const OUString & the_value)
1573 : throw (css::uno::RuntimeException, std::exception)
1574 : {
1575 354 : setMetaTextAndNotify("meta:printed-by", the_value);
1576 354 : }
1577 :
1578 : css::util::DateTime SAL_CALL
1579 1174 : SfxDocumentMetaData::getPrintDate() throw (css::uno::RuntimeException, std::exception)
1580 : {
1581 1174 : ::osl::MutexGuard g(m_aMutex);
1582 1174 : return textToDateTimeDefault(getMetaText("meta:print-date"));
1583 : }
1584 :
1585 : void SAL_CALL
1586 1062 : SfxDocumentMetaData::setPrintDate(const css::util::DateTime & the_value)
1587 : throw (css::uno::RuntimeException, std::exception)
1588 : {
1589 1062 : setMetaTextAndNotify("meta:print-date", dateTimeToText(the_value));
1590 1062 : }
1591 :
1592 : OUString SAL_CALL
1593 1398 : SfxDocumentMetaData::getTemplateName() throw (css::uno::RuntimeException, std::exception)
1594 : {
1595 1398 : ::osl::MutexGuard g(m_aMutex);
1596 1398 : checkInit();
1597 1398 : return m_TemplateName;
1598 : }
1599 :
1600 : void SAL_CALL
1601 2850 : SfxDocumentMetaData::setTemplateName(const OUString & the_value)
1602 : throw (css::uno::RuntimeException, std::exception)
1603 : {
1604 2850 : ::osl::ClearableMutexGuard g(m_aMutex);
1605 2850 : checkInit();
1606 2850 : if (m_TemplateName != the_value) {
1607 2748 : m_TemplateName = the_value;
1608 2748 : g.clear();
1609 2748 : setModified(true);
1610 2850 : }
1611 2850 : }
1612 :
1613 : OUString SAL_CALL
1614 1584 : SfxDocumentMetaData::getTemplateURL() throw (css::uno::RuntimeException, std::exception)
1615 : {
1616 1584 : ::osl::MutexGuard g(m_aMutex);
1617 1584 : checkInit();
1618 1584 : return m_TemplateURL;
1619 : }
1620 :
1621 : void SAL_CALL
1622 1158 : SfxDocumentMetaData::setTemplateURL(const OUString & the_value)
1623 : throw (css::uno::RuntimeException, std::exception)
1624 : {
1625 1158 : ::osl::ClearableMutexGuard g(m_aMutex);
1626 1158 : checkInit();
1627 1158 : if (m_TemplateURL != the_value) {
1628 34 : m_TemplateURL = the_value;
1629 34 : g.clear();
1630 34 : setModified(true);
1631 1158 : }
1632 1158 : }
1633 :
1634 : css::util::DateTime SAL_CALL
1635 26 : SfxDocumentMetaData::getTemplateDate() throw (css::uno::RuntimeException, std::exception)
1636 : {
1637 26 : ::osl::MutexGuard g(m_aMutex);
1638 26 : checkInit();
1639 26 : return m_TemplateDate;
1640 : }
1641 :
1642 : void SAL_CALL
1643 32 : SfxDocumentMetaData::setTemplateDate(const css::util::DateTime & the_value)
1644 : throw (css::uno::RuntimeException, std::exception)
1645 : {
1646 32 : ::osl::ClearableMutexGuard g(m_aMutex);
1647 32 : checkInit();
1648 32 : if (!(m_TemplateDate == the_value)) {
1649 2 : m_TemplateDate = the_value;
1650 2 : g.clear();
1651 2 : setModified(true);
1652 32 : }
1653 32 : }
1654 :
1655 : OUString SAL_CALL
1656 9031 : SfxDocumentMetaData::getAutoloadURL() throw (css::uno::RuntimeException, std::exception)
1657 : {
1658 9031 : ::osl::MutexGuard g(m_aMutex);
1659 9031 : checkInit();
1660 9031 : return m_AutoloadURL;
1661 : }
1662 :
1663 : void SAL_CALL
1664 1006 : SfxDocumentMetaData::setAutoloadURL(const OUString & the_value)
1665 : throw (css::uno::RuntimeException, std::exception)
1666 : {
1667 1006 : ::osl::ClearableMutexGuard g(m_aMutex);
1668 1006 : checkInit();
1669 1006 : if (m_AutoloadURL != the_value) {
1670 4 : m_AutoloadURL = the_value;
1671 4 : g.clear();
1672 4 : setModified(true);
1673 1006 : }
1674 1006 : }
1675 :
1676 : ::sal_Int32 SAL_CALL
1677 8071 : SfxDocumentMetaData::getAutoloadSecs() throw (css::uno::RuntimeException, std::exception)
1678 : {
1679 8071 : ::osl::MutexGuard g(m_aMutex);
1680 8071 : checkInit();
1681 8071 : return m_AutoloadSecs;
1682 : }
1683 :
1684 : void SAL_CALL
1685 24 : SfxDocumentMetaData::setAutoloadSecs(::sal_Int32 the_value)
1686 : throw (css::uno::RuntimeException, css::lang::IllegalArgumentException, std::exception)
1687 : {
1688 24 : if (the_value < 0) throw css::lang::IllegalArgumentException(
1689 : OUString("SfxDocumentMetaData::setAutoloadSecs: argument is negative"),
1690 0 : *this, 0);
1691 24 : ::osl::ClearableMutexGuard g(m_aMutex);
1692 24 : checkInit();
1693 24 : if (m_AutoloadSecs != the_value) {
1694 2 : m_AutoloadSecs = the_value;
1695 2 : g.clear();
1696 2 : setModified(true);
1697 24 : }
1698 24 : }
1699 :
1700 : OUString SAL_CALL
1701 54 : SfxDocumentMetaData::getDefaultTarget() throw (css::uno::RuntimeException, std::exception)
1702 : {
1703 54 : ::osl::MutexGuard g(m_aMutex);
1704 54 : checkInit();
1705 54 : return m_DefaultTarget;
1706 : }
1707 :
1708 : void SAL_CALL
1709 24 : SfxDocumentMetaData::setDefaultTarget(const OUString & the_value)
1710 : throw (css::uno::RuntimeException, std::exception)
1711 : {
1712 24 : ::osl::ClearableMutexGuard g(m_aMutex);
1713 24 : checkInit();
1714 24 : if (m_DefaultTarget != the_value) {
1715 0 : m_DefaultTarget = the_value;
1716 0 : g.clear();
1717 0 : setModified(true);
1718 24 : }
1719 24 : }
1720 :
1721 : css::uno::Sequence< css::beans::NamedValue > SAL_CALL
1722 15352 : SfxDocumentMetaData::getDocumentStatistics() throw (css::uno::RuntimeException, std::exception)
1723 : {
1724 15352 : ::osl::MutexGuard g(m_aMutex);
1725 15352 : checkInit();
1726 30704 : ::comphelper::SequenceAsVector<css::beans::NamedValue> stats;
1727 245632 : for (size_t i = 0; s_stdStats[i] != 0; ++i) {
1728 230280 : const char * aName = s_stdStatAttrs[i];
1729 230280 : OUString text = getMetaAttr("meta:document-statistic", aName);
1730 230280 : if (text.isEmpty()) continue;
1731 68376 : css::beans::NamedValue stat;
1732 34188 : stat.Name = OUString::createFromAscii(s_stdStats[i]);
1733 : sal_Int32 val;
1734 68376 : css::uno::Any any;
1735 34188 : if (!::sax::Converter::convertNumber(val, text, 0,
1736 34188 : std::numeric_limits<sal_Int32>::max()) || (val < 0)) {
1737 0 : val = 0;
1738 : SAL_WARN("sfx.doc", "Invalid number: " << text);
1739 : }
1740 34188 : any <<= val;
1741 34188 : stat.Value = any;
1742 34188 : stats.push_back(stat);
1743 34188 : }
1744 :
1745 30704 : return stats.getAsConstList();
1746 : }
1747 :
1748 : void SAL_CALL
1749 9415 : SfxDocumentMetaData::setDocumentStatistics(
1750 : const css::uno::Sequence< css::beans::NamedValue > & the_value)
1751 : throw (css::uno::RuntimeException, std::exception)
1752 : {
1753 9415 : ::osl::ClearableMutexGuard g(m_aMutex);
1754 9415 : checkInit();
1755 18830 : std::vector<std::pair<const char *, OUString> > attributes;
1756 38963 : for (sal_Int32 i = 0; i < the_value.getLength(); ++i) {
1757 29548 : const OUString name = the_value[i].Name;
1758 : // inefficently search for matching attribute
1759 168942 : for (size_t j = 0; s_stdStats[j] != 0; ++j) {
1760 168942 : if (name.equalsAscii(s_stdStats[j])) {
1761 29548 : const css::uno::Any any = the_value[i].Value;
1762 29548 : sal_Int32 val = 0;
1763 29548 : if (any >>= val) {
1764 29548 : OUStringBuffer buf;
1765 29548 : ::sax::Converter::convertNumber(buf, val);
1766 : attributes.push_back(std::make_pair(s_stdStatAttrs[j],
1767 29548 : buf.makeStringAndClear()));
1768 : } else {
1769 : SAL_WARN("sfx.doc", "Invalid statistic: " << name);
1770 : }
1771 29548 : break;
1772 : }
1773 : }
1774 29548 : }
1775 9415 : updateElement("meta:document-statistic", &attributes);
1776 9415 : g.clear();
1777 18830 : setModified(true);
1778 9415 : }
1779 :
1780 : ::sal_Int16 SAL_CALL
1781 1068 : SfxDocumentMetaData::getEditingCycles() throw (css::uno::RuntimeException, std::exception)
1782 : {
1783 1068 : ::osl::MutexGuard g(m_aMutex);
1784 2136 : OUString text = getMetaText("meta:editing-cycles");
1785 : sal_Int32 ret;
1786 1068 : if (::sax::Converter::convertNumber(ret, text,
1787 1068 : 0, std::numeric_limits<sal_Int16>::max())) {
1788 1068 : return static_cast<sal_Int16>(ret);
1789 : } else {
1790 0 : return 0;
1791 1068 : }
1792 : }
1793 :
1794 : void SAL_CALL
1795 3170 : SfxDocumentMetaData::setEditingCycles(::sal_Int16 the_value)
1796 : throw (css::uno::RuntimeException, css::lang::IllegalArgumentException, std::exception)
1797 : {
1798 3170 : if (the_value < 0) throw css::lang::IllegalArgumentException(
1799 : OUString("SfxDocumentMetaData::setEditingCycles: argument is negative"),
1800 0 : *this, 0);
1801 3170 : OUStringBuffer buf;
1802 3170 : ::sax::Converter::convertNumber(buf, the_value);
1803 3170 : setMetaTextAndNotify("meta:editing-cycles", buf.makeStringAndClear());
1804 3170 : }
1805 :
1806 : ::sal_Int32 SAL_CALL
1807 1068 : SfxDocumentMetaData::getEditingDuration() throw (css::uno::RuntimeException, std::exception)
1808 : {
1809 1068 : ::osl::MutexGuard g(m_aMutex);
1810 1068 : return textToDuration(getMetaText("meta:editing-duration"));
1811 : }
1812 :
1813 : void SAL_CALL
1814 3114 : SfxDocumentMetaData::setEditingDuration(::sal_Int32 the_value)
1815 : throw (css::uno::RuntimeException, css::lang::IllegalArgumentException, std::exception)
1816 : {
1817 3114 : if (the_value < 0) throw css::lang::IllegalArgumentException(
1818 : OUString("SfxDocumentMetaData::setEditingDuration: argument is negative"),
1819 0 : *this, 0);
1820 3114 : setMetaTextAndNotify("meta:editing-duration", durationToText(the_value));
1821 3114 : }
1822 :
1823 : void SAL_CALL
1824 8 : SfxDocumentMetaData::resetUserData(const OUString & the_value)
1825 : throw (css::uno::RuntimeException, std::exception)
1826 : {
1827 8 : ::osl::ClearableMutexGuard g(m_aMutex);
1828 :
1829 8 : bool bModified( false );
1830 8 : bModified |= setMetaText("meta:initial-creator", the_value);
1831 8 : ::DateTime now( ::DateTime::SYSTEM );
1832 24 : css::util::DateTime uDT(now.GetNanoSec(), now.GetSec(), now.GetMin(),
1833 32 : now.GetHour(), now.GetDay(), now.GetMonth(), now.GetYear(), false);
1834 8 : bModified |= setMetaText("meta:creation-date", dateTimeToText(uDT));
1835 8 : bModified |= setMetaText("dc:creator", OUString());
1836 8 : bModified |= setMetaText("meta:printed-by", OUString());
1837 8 : bModified |= setMetaText("dc:date", dateTimeToText(css::util::DateTime()));
1838 : bModified |= setMetaText("meta:print-date",
1839 8 : dateTimeToText(css::util::DateTime()));
1840 8 : bModified |= setMetaText("meta:editing-duration", durationToText(0));
1841 : bModified |= setMetaText("meta:editing-cycles",
1842 8 : OUString("1"));
1843 :
1844 8 : if (bModified) {
1845 8 : g.clear();
1846 8 : setModified(true);
1847 8 : }
1848 8 : }
1849 :
1850 :
1851 : css::uno::Reference< css::beans::XPropertyContainer > SAL_CALL
1852 20210 : SfxDocumentMetaData::getUserDefinedProperties()
1853 : throw (css::uno::RuntimeException, std::exception)
1854 : {
1855 20210 : ::osl::MutexGuard g(m_aMutex);
1856 20210 : checkInit();
1857 20210 : createUserDefined();
1858 20210 : return m_xUserDefined;
1859 : }
1860 :
1861 :
1862 : void SAL_CALL
1863 28 : SfxDocumentMetaData::loadFromStorage(
1864 : const css::uno::Reference< css::embed::XStorage > & xStorage,
1865 : const css::uno::Sequence< css::beans::PropertyValue > & Medium)
1866 : throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
1867 : css::io::WrongFormatException,
1868 : css::lang::WrappedTargetException, css::io::IOException, std::exception)
1869 : {
1870 28 : if (!xStorage.is()) throw css::lang::IllegalArgumentException(
1871 0 : OUString("SfxDocumentMetaData::loadFromStorage: argument is null"), *this, 0);
1872 28 : ::osl::MutexGuard g(m_aMutex);
1873 :
1874 : // open meta data file
1875 : css::uno::Reference<css::io::XStream> xStream(
1876 28 : xStorage->openStreamElement(
1877 : OUString(s_meta),
1878 56 : css::embed::ElementModes::READ) );
1879 28 : if (!xStream.is()) throw css::uno::RuntimeException();
1880 : css::uno::Reference<css::io::XInputStream> xInStream =
1881 56 : xStream->getInputStream();
1882 28 : if (!xInStream.is()) throw css::uno::RuntimeException();
1883 :
1884 : // create DOM parser service
1885 : css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
1886 56 : m_xContext->getServiceManager());
1887 56 : css::uno::Reference<css::xml::sax::XParser> xParser = css::xml::sax::Parser::create(m_xContext);
1888 56 : css::xml::sax::InputSource input;
1889 28 : input.aInputStream = xInStream;
1890 :
1891 28 : sal_uInt64 version = SotStorage::GetVersion( xStorage );
1892 : // Oasis is also the default (0)
1893 28 : bool bOasis = ( version > SOFFICE_FILEFORMAT_60 || version == 0 );
1894 : const sal_Char *pServiceName = bOasis
1895 : ? "com.sun.star.document.XMLOasisMetaImporter"
1896 28 : : "com.sun.star.document.XMLMetaImporter";
1897 :
1898 : // set base URL
1899 : css::uno::Reference<css::beans::XPropertySet> xPropArg =
1900 56 : getURLProperties(Medium);
1901 : try {
1902 28 : xPropArg->getPropertyValue("BaseURI")
1903 28 : >>= input.sSystemId;
1904 28 : input.sSystemId += "/" + OUString(s_meta);
1905 0 : } catch (const css::uno::Exception &) {
1906 0 : input.sSystemId = OUString(s_meta);
1907 : }
1908 56 : css::uno::Sequence< css::uno::Any > args(1);
1909 28 : args[0] <<= xPropArg;
1910 :
1911 : css::uno::Reference<css::xml::sax::XDocumentHandler> xDocHandler (
1912 28 : xMsf->createInstanceWithArgumentsAndContext(
1913 28 : OUString::createFromAscii(pServiceName), args, m_xContext),
1914 56 : css::uno::UNO_QUERY_THROW);
1915 28 : if (!xDocHandler.is()) throw css::uno::RuntimeException(
1916 : OUString("SfxDocumentMetaData::loadFromStorage:"
1917 0 : " cannot create XMLOasisMetaImporter service"), *this);
1918 : css::uno::Reference<css::document::XImporter> xImp (xDocHandler,
1919 56 : css::uno::UNO_QUERY_THROW);
1920 28 : xImp->setTargetDocument(css::uno::Reference<css::lang::XComponent>(this));
1921 28 : xParser->setDocumentHandler(xDocHandler);
1922 : try {
1923 28 : xParser->parseStream(input);
1924 0 : } catch (const css::xml::sax::SAXException &) {
1925 : throw css::io::WrongFormatException(OUString(
1926 : "SfxDocumentMetaData::loadFromStorage:"
1927 0 : " XML parsing exception"), *this);
1928 : }
1929 : // NB: the implementation of XMLOasisMetaImporter calls initialize
1930 56 : checkInit();
1931 28 : }
1932 :
1933 : void SAL_CALL
1934 6 : SfxDocumentMetaData::storeToStorage(
1935 : const css::uno::Reference< css::embed::XStorage > & xStorage,
1936 : const css::uno::Sequence< css::beans::PropertyValue > & Medium)
1937 : throw (css::uno::RuntimeException, css::lang::IllegalArgumentException,
1938 : css::lang::WrappedTargetException, css::io::IOException, std::exception)
1939 : {
1940 6 : if (!xStorage.is()) throw css::lang::IllegalArgumentException(
1941 : OUString("SfxDocumentMetaData::storeToStorage:"
1942 0 : " argument is null"), *this, 0);
1943 6 : ::osl::MutexGuard g(m_aMutex);
1944 6 : checkInit();
1945 :
1946 : // update user-defined meta data in DOM tree
1947 : // updateUserDefinedAndAttributes(); // this will be done in serialize!
1948 :
1949 : // write into storage
1950 : css::uno::Reference<css::io::XStream> xStream =
1951 6 : xStorage->openStreamElement(OUString(s_meta),
1952 : css::embed::ElementModes::WRITE
1953 12 : | css::embed::ElementModes::TRUNCATE);
1954 6 : if (!xStream.is()) throw css::uno::RuntimeException();
1955 : css::uno::Reference< css::beans::XPropertySet > xStreamProps(xStream,
1956 12 : css::uno::UNO_QUERY_THROW);
1957 6 : xStreamProps->setPropertyValue(
1958 : OUString("MediaType"),
1959 6 : css::uno::makeAny(OUString("text/xml")));
1960 6 : xStreamProps->setPropertyValue(
1961 : OUString("Compressed"),
1962 6 : css::uno::makeAny(false));
1963 6 : xStreamProps->setPropertyValue(
1964 : OUString("UseCommonStoragePasswordEncryption"),
1965 6 : css::uno::makeAny(false));
1966 : css::uno::Reference<css::io::XOutputStream> xOutStream =
1967 12 : xStream->getOutputStream();
1968 6 : if (!xOutStream.is()) throw css::uno::RuntimeException();
1969 : css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (
1970 12 : m_xContext->getServiceManager());
1971 : css::uno::Reference<css::xml::sax::XWriter> xSaxWriter(
1972 12 : css::xml::sax::Writer::create(m_xContext));
1973 6 : xSaxWriter->setOutputStream(xOutStream);
1974 :
1975 6 : const sal_uInt64 version = SotStorage::GetVersion( xStorage );
1976 : // Oasis is also the default (0)
1977 6 : const bool bOasis = ( version > SOFFICE_FILEFORMAT_60 || version == 0 );
1978 : const sal_Char *pServiceName = bOasis
1979 : ? "com.sun.star.document.XMLOasisMetaExporter"
1980 6 : : "com.sun.star.document.XMLMetaExporter";
1981 :
1982 : // set base URL
1983 : css::uno::Reference<css::beans::XPropertySet> xPropArg =
1984 12 : getURLProperties(Medium);
1985 12 : css::uno::Sequence< css::uno::Any > args(2);
1986 6 : args[0] <<= xSaxWriter;
1987 6 : args[1] <<= xPropArg;
1988 :
1989 : css::uno::Reference<css::document::XExporter> xExp(
1990 6 : xMsf->createInstanceWithArgumentsAndContext(
1991 6 : OUString::createFromAscii(pServiceName), args, m_xContext),
1992 12 : css::uno::UNO_QUERY_THROW);
1993 6 : xExp->setSourceDocument(css::uno::Reference<css::lang::XComponent>(this));
1994 : css::uno::Reference<css::document::XFilter> xFilter(xExp,
1995 12 : css::uno::UNO_QUERY_THROW);
1996 6 : if (xFilter->filter(css::uno::Sequence< css::beans::PropertyValue >())) {
1997 : css::uno::Reference<css::embed::XTransactedObject> xTransaction(
1998 6 : xStorage, css::uno::UNO_QUERY);
1999 6 : if (xTransaction.is()) {
2000 6 : xTransaction->commit();
2001 6 : }
2002 : } else {
2003 : throw css::io::IOException(OUString(
2004 0 : "SfxDocumentMetaData::storeToStorage: cannot filter"), *this);
2005 6 : }
2006 6 : }
2007 :
2008 : void SAL_CALL
2009 34 : SfxDocumentMetaData::loadFromMedium(const OUString & URL,
2010 : const css::uno::Sequence< css::beans::PropertyValue > & Medium)
2011 : throw (css::uno::RuntimeException, css::io::WrongFormatException,
2012 : css::lang::WrappedTargetException, css::io::IOException, std::exception)
2013 : {
2014 34 : css::uno::Reference<css::io::XInputStream> xIn;
2015 68 : utl::MediaDescriptor md(Medium);
2016 : // if we have an URL parameter, it replaces the one in the media descriptor
2017 34 : if (!URL.isEmpty()) {
2018 32 : md[ utl::MediaDescriptor::PROP_URL() ] <<= URL;
2019 : }
2020 34 : if (md.addInputStream()) {
2021 28 : md[ utl::MediaDescriptor::PROP_INPUTSTREAM() ] >>= xIn;
2022 : }
2023 68 : css::uno::Reference<css::embed::XStorage> xStorage;
2024 : try {
2025 34 : if (xIn.is()) {
2026 56 : xStorage = ::comphelper::OStorageHelper::GetStorageFromInputStream(
2027 28 : xIn, m_xContext);
2028 : } else { // fallback to url parameter
2029 6 : xStorage = ::comphelper::OStorageHelper::GetStorageFromURL(
2030 0 : URL, css::embed::ElementModes::READ, m_xContext);
2031 : }
2032 0 : } catch (const css::uno::RuntimeException &) {
2033 0 : throw;
2034 0 : } catch (const css::io::IOException &) {
2035 0 : throw;
2036 12 : } catch (const css::uno::Exception & e) {
2037 : throw css::lang::WrappedTargetException(
2038 : OUString("SfxDocumentMetaData::loadFromMedium: exception"),
2039 : css::uno::Reference<css::uno::XInterface>(*this),
2040 6 : css::uno::makeAny(e));
2041 : }
2042 28 : if (!xStorage.is()) {
2043 : throw css::uno::RuntimeException(OUString(
2044 : "SfxDocumentMetaData::loadFromMedium: cannot get Storage"),
2045 0 : *this);
2046 : }
2047 62 : loadFromStorage(xStorage, md.getAsConstPropertyValueList());
2048 28 : }
2049 :
2050 : void SAL_CALL
2051 6 : SfxDocumentMetaData::storeToMedium(const OUString & URL,
2052 : const css::uno::Sequence< css::beans::PropertyValue > & Medium)
2053 : throw (css::uno::RuntimeException,
2054 : css::lang::WrappedTargetException, css::io::IOException, std::exception)
2055 : {
2056 6 : utl::MediaDescriptor md(Medium);
2057 6 : if (!URL.isEmpty()) {
2058 4 : md[ utl::MediaDescriptor::PROP_URL() ] <<= URL;
2059 : }
2060 12 : SfxMedium aMedium(md.getAsConstPropertyValueList());
2061 : css::uno::Reference<css::embed::XStorage> xStorage
2062 12 : = aMedium.GetOutputStorage();
2063 :
2064 :
2065 6 : if (!xStorage.is()) {
2066 : throw css::uno::RuntimeException(OUString(
2067 : "SfxDocumentMetaData::storeToMedium: cannot get Storage"),
2068 0 : *this);
2069 : }
2070 : // set MIME type of the storage
2071 : utl::MediaDescriptor::const_iterator iter
2072 6 : = md.find(utl::MediaDescriptor::PROP_MEDIATYPE());
2073 6 : if (iter != md.end()) {
2074 : css::uno::Reference< css::beans::XPropertySet > xProps(xStorage,
2075 6 : css::uno::UNO_QUERY_THROW);
2076 6 : xProps->setPropertyValue(
2077 6 : utl::MediaDescriptor::PROP_MEDIATYPE(),
2078 12 : iter->second);
2079 : }
2080 6 : storeToStorage(xStorage, md.getAsConstPropertyValueList());
2081 :
2082 :
2083 6 : const bool bOk = aMedium.Commit();
2084 6 : aMedium.Close();
2085 6 : if ( !bOk ) {
2086 0 : sal_uInt32 nError = aMedium.GetError();
2087 0 : if ( nError == ERRCODE_NONE ) {
2088 0 : nError = ERRCODE_IO_GENERAL;
2089 : }
2090 :
2091 : throw css::task::ErrorCodeIOException(
2092 0 : ("SfxDocumentMetaData::storeToMedium <" + URL + "> Commit failed: "
2093 0 : "0x" + OUString::number(nError, 16)),
2094 0 : css::uno::Reference< css::uno::XInterface >(), nError);
2095 :
2096 6 : }
2097 6 : }
2098 :
2099 : // ::com::sun::star::lang::XInitialization:
2100 : void SAL_CALL
2101 8236 : SfxDocumentMetaData::initialize(
2102 : const css::uno::Sequence< ::com::sun::star::uno::Any > & aArguments)
2103 : throw (css::uno::RuntimeException, css::uno::Exception, std::exception)
2104 : {
2105 : // possible arguments:
2106 : // - no argument: default initialization (empty DOM)
2107 : // - 1 argument, XDocument: initialize with given DOM and empty base URL
2108 : // NB: links in document must be absolute
2109 :
2110 8236 : ::osl::MutexGuard g(m_aMutex);
2111 16472 : css::uno::Reference<css::xml::dom::XDocument> xDoc;
2112 :
2113 9218 : for (sal_Int32 i = 0; i < aArguments.getLength(); ++i) {
2114 982 : const css::uno::Any any = aArguments[i];
2115 982 : if (any >>= xDoc) {
2116 982 : if (!xDoc.is()) {
2117 : throw css::lang::IllegalArgumentException(
2118 : OUString("SfxDocumentMetaData::"
2119 : "initialize: argument is null"),
2120 0 : *this, static_cast<sal_Int16>(i));
2121 : }
2122 : } else {
2123 : throw css::lang::IllegalArgumentException(
2124 : OUString("SfxDocumentMetaData::"
2125 : "initialize: argument must be XDocument"),
2126 0 : *this, static_cast<sal_Int16>(i));
2127 : }
2128 982 : }
2129 :
2130 8236 : if (!xDoc.is()) {
2131 : // For a new document, we create a new DOM tree here.
2132 7254 : xDoc = createDOM();
2133 : }
2134 :
2135 16472 : init(xDoc);
2136 8236 : }
2137 :
2138 : // ::com::sun::star::util::XCloneable:
2139 : css::uno::Reference<css::util::XCloneable> SAL_CALL
2140 1096 : SfxDocumentMetaData::createClone()
2141 : throw (css::uno::RuntimeException, std::exception)
2142 : {
2143 1096 : ::osl::MutexGuard g(m_aMutex);
2144 1096 : checkInit();
2145 :
2146 1096 : SfxDocumentMetaData *pNew = createMe(m_xContext);
2147 :
2148 : // NB: do not copy the modification listeners, only DOM
2149 2192 : css::uno::Reference<css::xml::dom::XDocument> xDoc = createDOM();
2150 : try {
2151 1096 : updateUserDefinedAndAttributes();
2152 : // deep copy of root node
2153 : css::uno::Reference<css::xml::dom::XNode> xRoot(
2154 1096 : m_xDoc->getDocumentElement(), css::uno::UNO_QUERY_THROW);
2155 : css::uno::Reference<css::xml::dom::XNode> xRootNew(
2156 2192 : xDoc->importNode(xRoot, true));
2157 1096 : xDoc->appendChild(xRootNew);
2158 2192 : pNew->init(xDoc);
2159 0 : } catch (const css::uno::RuntimeException &) {
2160 0 : throw;
2161 0 : } catch (const css::uno::Exception & e) {
2162 0 : css::uno::Any a(e);
2163 : throw css::lang::WrappedTargetRuntimeException(
2164 : OUString("SfxDocumentMetaData::createClone: exception"),
2165 0 : css::uno::Reference<css::uno::XInterface>(*this), a);
2166 : }
2167 2192 : return css::uno::Reference<css::util::XCloneable> (pNew);
2168 : }
2169 :
2170 : // ::com::sun::star::util::XModifiable:
2171 0 : sal_Bool SAL_CALL SfxDocumentMetaData::isModified( )
2172 : throw (css::uno::RuntimeException, std::exception)
2173 : {
2174 0 : ::osl::MutexGuard g(m_aMutex);
2175 0 : checkInit();
2176 : css::uno::Reference<css::util::XModifiable> xMB(m_xUserDefined,
2177 0 : css::uno::UNO_QUERY);
2178 0 : return m_isModified || (xMB.is() ? xMB->isModified() : sal_False);
2179 : }
2180 :
2181 37817 : void SAL_CALL SfxDocumentMetaData::setModified( sal_Bool bModified )
2182 : throw (css::beans::PropertyVetoException, css::uno::RuntimeException, std::exception)
2183 : {
2184 37817 : css::uno::Reference<css::util::XModifiable> xMB;
2185 : { // do not lock mutex while notifying (#i93514#) to prevent deadlock
2186 37817 : ::osl::MutexGuard g(m_aMutex);
2187 37817 : checkInit();
2188 37817 : m_isModified = bModified;
2189 37817 : if ( !bModified && m_xUserDefined.is() )
2190 : {
2191 0 : xMB.set(m_xUserDefined, css::uno::UNO_QUERY);
2192 : DBG_ASSERT(xMB.is(),
2193 : "SfxDocumentMetaData::setModified: PropertyBag not Modifiable?");
2194 37817 : }
2195 : }
2196 37817 : if (bModified) {
2197 : try {
2198 37817 : css::uno::Reference<css::uno::XInterface> xThis(*this);
2199 75634 : css::lang::EventObject event(xThis);
2200 : m_NotifyListeners.notifyEach(&css::util::XModifyListener::modified,
2201 75634 : event);
2202 0 : } catch (const css::uno::RuntimeException &) {
2203 0 : throw;
2204 0 : } catch (const css::uno::Exception & e) {
2205 : // ignore
2206 : SAL_WARN("sfx.doc", "setModified: exception: " << e.Message);
2207 : }
2208 : } else {
2209 0 : if (xMB.is()) {
2210 0 : xMB->setModified(false);
2211 : }
2212 37817 : }
2213 37817 : }
2214 :
2215 : // ::com::sun::star::util::XModifyBroadcaster:
2216 6748 : void SAL_CALL SfxDocumentMetaData::addModifyListener(
2217 : const css::uno::Reference< css::util::XModifyListener > & xListener)
2218 : throw (css::uno::RuntimeException, std::exception)
2219 : {
2220 6748 : ::osl::MutexGuard g(m_aMutex);
2221 6748 : checkInit();
2222 6748 : m_NotifyListeners.addInterface(xListener);
2223 : css::uno::Reference<css::util::XModifyBroadcaster> xMB(m_xUserDefined,
2224 13496 : css::uno::UNO_QUERY);
2225 6748 : if (xMB.is()) {
2226 2 : xMB->addModifyListener(xListener);
2227 6748 : }
2228 6748 : }
2229 :
2230 2 : void SAL_CALL SfxDocumentMetaData::removeModifyListener(
2231 : const css::uno::Reference< css::util::XModifyListener > & xListener)
2232 : throw (css::uno::RuntimeException, std::exception)
2233 : {
2234 2 : ::osl::MutexGuard g(m_aMutex);
2235 2 : checkInit();
2236 2 : m_NotifyListeners.removeInterface(xListener);
2237 : css::uno::Reference<css::util::XModifyBroadcaster> xMB(m_xUserDefined,
2238 4 : css::uno::UNO_QUERY);
2239 2 : if (xMB.is()) {
2240 2 : xMB->removeModifyListener(xListener);
2241 2 : }
2242 2 : }
2243 :
2244 : // ::com::sun::star::xml::sax::XSAXSerializable
2245 624 : void SAL_CALL SfxDocumentMetaData::serialize(
2246 : const css::uno::Reference<css::xml::sax::XDocumentHandler>& i_xHandler,
2247 : const css::uno::Sequence< css::beans::StringPair >& i_rNamespaces)
2248 : throw (css::uno::RuntimeException, css::xml::sax::SAXException, std::exception)
2249 : {
2250 624 : ::osl::MutexGuard g(m_aMutex);
2251 624 : checkInit();
2252 624 : updateUserDefinedAndAttributes();
2253 : css::uno::Reference<css::xml::sax::XSAXSerializable> xSAXable(m_xDoc,
2254 1248 : css::uno::UNO_QUERY_THROW);
2255 1248 : xSAXable->serialize(i_xHandler, i_rNamespaces);
2256 624 : }
2257 :
2258 22846 : void SfxDocumentMetaData::createUserDefined()
2259 : {
2260 : // user-defined meta data: create PropertyBag which only accepts property
2261 : // values of allowed types
2262 22846 : if ( !m_xUserDefined.is() )
2263 : {
2264 4618 : css::uno::Sequence<css::uno::Type> types(13);
2265 4618 : types[ 0] = ::cppu::UnoType<bool>::get();
2266 4618 : types[ 1] = ::cppu::UnoType< OUString>::get();
2267 4618 : types[ 2] = ::cppu::UnoType<css::util::DateTime>::get();
2268 4618 : types[ 3] = ::cppu::UnoType<css::util::Date>::get();
2269 4618 : types[ 4] = ::cppu::UnoType<css::util::DateTimeWithTimezone>::get();
2270 4618 : types[ 5] = ::cppu::UnoType<css::util::DateWithTimezone>::get();
2271 4618 : types[ 6] = ::cppu::UnoType<css::util::Duration>::get();
2272 4618 : types[ 7] = ::cppu::UnoType<float>::get();
2273 4618 : types[ 8] = ::cppu::UnoType<double>::get();
2274 4618 : types[ 9] = ::cppu::UnoType<sal_Int16>::get();
2275 4618 : types[10] = ::cppu::UnoType<sal_Int32>::get();
2276 4618 : types[11] = ::cppu::UnoType<sal_Int64>::get();
2277 : // Time is supported for backward compatibility with OOo 3.x, x<=2
2278 4618 : types[12] = ::cppu::UnoType<css::util::Time>::get();
2279 : // #i94175#: ODF allows empty user-defined property names!
2280 : m_xUserDefined.set(
2281 : css::beans::PropertyBag::createWithTypes( m_xContext, types, sal_True/*AllowEmptyPropertyName*/, sal_False/*AutomaticAddition*/ ),
2282 4618 : css::uno::UNO_QUERY_THROW);
2283 :
2284 : const css::uno::Reference<css::util::XModifyBroadcaster> xMB(
2285 9236 : m_xUserDefined, css::uno::UNO_QUERY);
2286 4618 : if (xMB.is())
2287 : {
2288 : const css::uno::Sequence<css::uno::Reference<css::uno::XInterface> >
2289 4618 : listeners(m_NotifyListeners.getElements());
2290 8060 : for (css::uno::Reference< css::uno::XInterface > const * iter = listeners.begin(); iter != listeners.end(); ++iter) {
2291 3442 : xMB->addModifyListener(
2292 : css::uno::Reference< css::util::XModifyListener >(*iter,
2293 3442 : css::uno::UNO_QUERY));
2294 4618 : }
2295 4618 : }
2296 : }
2297 22846 : }
2298 :
2299 : } // closing anonymous implementation namespace
2300 :
2301 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
2302 0 : CompatWriterDocPropsImpl_get_implementation(
2303 : css::uno::XComponentContext *context,
2304 : css::uno::Sequence<css::uno::Any> const &)
2305 : {
2306 0 : return cppu::acquire(new CompatWriterDocPropsImpl(context));
2307 : }
2308 :
2309 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
2310 7256 : SfxDocumentMetaData_get_implementation(
2311 : css::uno::XComponentContext *context,
2312 : css::uno::Sequence<css::uno::Any> const &)
2313 : {
2314 7256 : return cppu::acquire(new SfxDocumentMetaData(context));
2315 : }
2316 :
2317 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|