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