/src/libreoffice/sfx2/source/bastyp/fltfnc.cxx
Line | Count | Source (jump to first uncovered line) |
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 | | |
21 | | #include <com/sun/star/uno/Exception.hpp> |
22 | | #include <com/sun/star/beans/PropertyValue.hpp> |
23 | | #include <com/sun/star/beans/NamedValue.hpp> |
24 | | #include <com/sun/star/container/XNameAccess.hpp> |
25 | | #include <com/sun/star/container/XEnumeration.hpp> |
26 | | #include <com/sun/star/document/XTypeDetection.hpp> |
27 | | #include <com/sun/star/container/XContainerQuery.hpp> |
28 | | #include <com/sun/star/io/XInputStream.hpp> |
29 | | #include <com/sun/star/task/XInteractionHandler.hpp> |
30 | | #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
31 | | |
32 | | #include <comphelper/sequenceashashmap.hxx> |
33 | | |
34 | | #include <sot/exchange.hxx> |
35 | | #include <utility> |
36 | | #include <vcl/svapp.hxx> |
37 | | #include <vcl/weld.hxx> |
38 | | #include <rtl/ustring.hxx> |
39 | | #include <rtl/ustrbuf.hxx> |
40 | | #include <sal/log.hxx> |
41 | | #include <svl/stritem.hxx> |
42 | | |
43 | | #include <comphelper/processfactory.hxx> |
44 | | |
45 | | #include <sal/types.h> |
46 | | #include <com/sun/star/uno/Reference.hxx> |
47 | | #include <unotools/moduleoptions.hxx> |
48 | | #include <unotools/mediadescriptor.hxx> |
49 | | #include <tools/urlobj.hxx> |
50 | | |
51 | | #include <unotools/syslocale.hxx> |
52 | | #include <unotools/charclass.hxx> |
53 | | |
54 | | #include <sfx2/docfilt.hxx> |
55 | | #include <sfx2/fcontnr.hxx> |
56 | | #include <sfxtypes.hxx> |
57 | | #include <sfx2/docfile.hxx> |
58 | | #include <sfx2/strings.hrc> |
59 | | #include <sfx2/sfxresid.hxx> |
60 | | #include <sfx2/objsh.hxx> |
61 | | #include <sfx2/sfxsids.hrc> |
62 | | #include "fltlst.hxx" |
63 | | #include <arrdecl.hxx> |
64 | | |
65 | | #include <vector> |
66 | | #include <memory> |
67 | | |
68 | | #if defined(DBG_UTIL) |
69 | | unsigned SfxStack::nLevel = 0; |
70 | | #endif |
71 | | |
72 | | using namespace com::sun::star; |
73 | | |
74 | | static SfxFilterList_Impl* pFilterArr = nullptr; |
75 | | static bool bFirstRead = true; |
76 | | |
77 | | static void CreateFilterArr() |
78 | 0 | { |
79 | 0 | static SfxFilterList_Impl theSfxFilterArray; |
80 | 0 | pFilterArr = &theSfxFilterArray; |
81 | 0 | static SfxFilterListener theSfxFilterListener; |
82 | 0 | } |
83 | | |
84 | | static OUString ToUpper_Impl( const OUString &rStr ) |
85 | 0 | { |
86 | 0 | return SvtSysLocale().GetCharClass().uppercase( rStr ); |
87 | 0 | } |
88 | | |
89 | | class SfxFilterContainer_Impl |
90 | | { |
91 | | public: |
92 | | OUString aName; |
93 | | |
94 | | explicit SfxFilterContainer_Impl( OUString _aName ) |
95 | 44 | : aName(std::move( _aName )) |
96 | 44 | { |
97 | 44 | } |
98 | | }; |
99 | | |
100 | | std::shared_ptr<const SfxFilter> SfxFilterContainer::GetFilter4EA(const OUString& rEA, SfxFilterFlags nMust, SfxFilterFlags nDont) const |
101 | 0 | { |
102 | 0 | SfxFilterMatcher aMatch(pImpl->aName); |
103 | 0 | return aMatch.GetFilter4EA(rEA, nMust, nDont); |
104 | 0 | } |
105 | | |
106 | | std::shared_ptr<const SfxFilter> SfxFilterContainer::GetFilter4Extension(const OUString& rExt, SfxFilterFlags nMust, SfxFilterFlags nDont) const |
107 | 0 | { |
108 | 0 | SfxFilterMatcher aMatch(pImpl->aName); |
109 | 0 | return aMatch.GetFilter4Extension(rExt, nMust, nDont); |
110 | 0 | } |
111 | | |
112 | | std::shared_ptr<const SfxFilter> SfxFilterContainer::GetFilter4FilterName(const OUString& rName, SfxFilterFlags nMust, SfxFilterFlags nDont) const |
113 | 0 | { |
114 | 0 | SfxFilterMatcher aMatch(pImpl->aName); |
115 | 0 | return aMatch.GetFilter4FilterName(rName, nMust, nDont); |
116 | 0 | } |
117 | | |
118 | | std::shared_ptr<const SfxFilter> SfxFilterContainer::GetAnyFilter( SfxFilterFlags nMust, SfxFilterFlags nDont ) const |
119 | 0 | { |
120 | 0 | SfxFilterMatcher aMatch( pImpl->aName ); |
121 | 0 | return aMatch.GetAnyFilter( nMust, nDont ); |
122 | 0 | } |
123 | | |
124 | | |
125 | | SfxFilterContainer::SfxFilterContainer( const OUString& rName ) |
126 | 44 | : pImpl( new SfxFilterContainer_Impl( rName ) ) |
127 | 44 | { |
128 | 44 | } |
129 | | |
130 | | |
131 | | SfxFilterContainer::~SfxFilterContainer() |
132 | 44 | { |
133 | 44 | } |
134 | | |
135 | | |
136 | | OUString const & SfxFilterContainer::GetName() const |
137 | 0 | { |
138 | 0 | return pImpl->aName; |
139 | 0 | } |
140 | | |
141 | | std::shared_ptr<const SfxFilter> SfxFilterContainer::GetDefaultFilter_Impl( std::u16string_view rName ) |
142 | 0 | { |
143 | | // Try to find out the type of factory. |
144 | | // Interpret given name as Service- and ShortName! |
145 | 0 | SvtModuleOptions aOpt; |
146 | 0 | SvtModuleOptions::EFactory eFactory = SvtModuleOptions::ClassifyFactoryByServiceName(rName); |
147 | 0 | if (eFactory == SvtModuleOptions::EFactory::UNKNOWN_FACTORY) |
148 | 0 | eFactory = SvtModuleOptions::ClassifyFactoryByShortName(rName); |
149 | | |
150 | | // could not classify factory by its service nor by its short name. |
151 | | // Must be an unknown factory! => return NULL |
152 | 0 | if (eFactory == SvtModuleOptions::EFactory::UNKNOWN_FACTORY) |
153 | 0 | return nullptr; |
154 | | |
155 | | // For the following code we need some additional information. |
156 | 0 | const OUString& sServiceName = aOpt.GetFactoryName(eFactory); |
157 | 0 | OUString sDefaultFilter = aOpt.GetFactoryDefaultFilter(eFactory); |
158 | | |
159 | | // Try to get the default filter. Don't forget to verify it. |
160 | | // May the set default filter does not exists any longer or |
161 | | // does not fit the given factory. |
162 | 0 | const SfxFilterMatcher aMatcher; |
163 | 0 | std::shared_ptr<const SfxFilter> pFilter = aMatcher.GetFilter4FilterName(sDefaultFilter); |
164 | |
|
165 | 0 | if ( |
166 | 0 | pFilter && |
167 | 0 | !pFilter->GetServiceName().equalsIgnoreAsciiCase(sServiceName) |
168 | 0 | ) |
169 | 0 | { |
170 | 0 | pFilter = nullptr; |
171 | 0 | } |
172 | | |
173 | | // If at least no default filter could be located - use any filter of this |
174 | | // factory. |
175 | 0 | if (!pFilter) |
176 | 0 | { |
177 | 0 | if ( bFirstRead ) |
178 | 0 | ReadFilters_Impl(); |
179 | |
|
180 | 0 | for (const std::shared_ptr<const SfxFilter>& pCheckFilter : *pFilterArr) |
181 | 0 | { |
182 | 0 | if ( pCheckFilter->GetServiceName().equalsIgnoreAsciiCase(sServiceName) ) |
183 | 0 | { |
184 | 0 | pFilter = pCheckFilter; |
185 | 0 | break; |
186 | 0 | } |
187 | 0 | } |
188 | 0 | } |
189 | |
|
190 | 0 | return pFilter; |
191 | 0 | } |
192 | | |
193 | | |
194 | | // Impl-Data is shared between all FilterMatchers of the same factory |
195 | | class SfxFilterMatcher_Impl |
196 | | { |
197 | | public: |
198 | | OUString aName; |
199 | | mutable SfxFilterList_Impl* pList; // is created on demand |
200 | | |
201 | | void InitForIterating() const; |
202 | | void Update() const; |
203 | | explicit SfxFilterMatcher_Impl(OUString _aName) |
204 | 0 | : aName(std::move(_aName)) |
205 | 0 | , pList(nullptr) |
206 | 0 | { |
207 | 0 | } |
208 | | ~SfxFilterMatcher_Impl() |
209 | 0 | { |
210 | | // SfxFilterMatcher_Impl::InitForIterating() will set pList to |
211 | | // either the global filter array matcher pFilterArr, or to |
212 | | // a new SfxFilterList_Impl. |
213 | 0 | if (pList != pFilterArr) |
214 | 0 | delete pList; |
215 | 0 | } |
216 | | }; |
217 | | |
218 | | namespace |
219 | | { |
220 | | std::vector<std::unique_ptr<SfxFilterMatcher_Impl> > aImplArr; |
221 | | int nSfxFilterMatcherCount; |
222 | | |
223 | | SfxFilterMatcher_Impl & getSfxFilterMatcher_Impl(const OUString &rName) |
224 | 0 | { |
225 | 0 | OUString aName; |
226 | |
|
227 | 0 | if (!rName.isEmpty()) |
228 | 0 | aName = SfxObjectShell::GetServiceNameFromFactory(rName); |
229 | | |
230 | | // find the impl-Data of any comparable FilterMatcher that was created |
231 | | // previously |
232 | 0 | for (std::unique_ptr<SfxFilterMatcher_Impl>& aImpl : aImplArr) |
233 | 0 | if (aImpl->aName == aName) |
234 | 0 | return *aImpl; |
235 | | |
236 | | // first Matcher created for this factory |
237 | 0 | aImplArr.push_back(std::make_unique<SfxFilterMatcher_Impl>(aName)); |
238 | 0 | return *aImplArr.back(); |
239 | 0 | } |
240 | | } |
241 | | |
242 | | SfxFilterMatcher::SfxFilterMatcher( const OUString& rName ) |
243 | 0 | : m_rImpl( getSfxFilterMatcher_Impl(rName) ) |
244 | 0 | { |
245 | 0 | ++nSfxFilterMatcherCount; |
246 | 0 | } |
247 | | |
248 | | SfxFilterMatcher::SfxFilterMatcher() |
249 | 0 | : m_rImpl( getSfxFilterMatcher_Impl(OUString()) ) |
250 | 0 | { |
251 | | // global FilterMatcher always uses global filter array (also created on |
252 | | // demand) |
253 | 0 | ++nSfxFilterMatcherCount; |
254 | 0 | } |
255 | | |
256 | | SfxFilterMatcher::~SfxFilterMatcher() |
257 | 0 | { |
258 | 0 | --nSfxFilterMatcherCount; |
259 | 0 | if (nSfxFilterMatcherCount == 0) |
260 | 0 | aImplArr.clear(); |
261 | 0 | } |
262 | | |
263 | | void SfxFilterMatcher_Impl::Update() const |
264 | 0 | { |
265 | 0 | if ( pList ) |
266 | 0 | { |
267 | | // this List was already used |
268 | 0 | pList->clear(); |
269 | 0 | for (const std::shared_ptr<const SfxFilter>& pFilter : *pFilterArr) |
270 | 0 | { |
271 | 0 | if ( pFilter->GetServiceName() == aName ) |
272 | 0 | pList->push_back( pFilter ); |
273 | 0 | } |
274 | 0 | } |
275 | 0 | } |
276 | | |
277 | | void SfxFilterMatcher_Impl::InitForIterating() const |
278 | 0 | { |
279 | 0 | if ( pList ) |
280 | 0 | return; |
281 | | |
282 | 0 | if ( bFirstRead ) |
283 | | // global filter array has not been created yet |
284 | 0 | SfxFilterContainer::ReadFilters_Impl(); |
285 | |
|
286 | 0 | if ( !aName.isEmpty() ) |
287 | 0 | { |
288 | | // matcher of factory: use only filters of that document type |
289 | 0 | pList = new SfxFilterList_Impl; |
290 | 0 | Update(); |
291 | 0 | } |
292 | 0 | else |
293 | 0 | { |
294 | | // global matcher: use global filter array |
295 | 0 | pList = pFilterArr; |
296 | 0 | } |
297 | 0 | } |
298 | | |
299 | | std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetAnyFilter( SfxFilterFlags nMust, SfxFilterFlags nDont ) const |
300 | 0 | { |
301 | 0 | m_rImpl.InitForIterating(); |
302 | 0 | for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList) |
303 | 0 | { |
304 | 0 | SfxFilterFlags nFlags = pFilter->GetFilterFlags(); |
305 | 0 | if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) ) |
306 | 0 | return pFilter; |
307 | 0 | } |
308 | | |
309 | 0 | return nullptr; |
310 | 0 | } |
311 | | |
312 | | |
313 | | ErrCode SfxFilterMatcher::GuessFilterIgnoringContent( |
314 | | SfxMedium const & rMedium, |
315 | | std::shared_ptr<const SfxFilter>& rpFilter ) const |
316 | 0 | { |
317 | 0 | uno::Reference<document::XTypeDetection> xDetection( |
318 | 0 | comphelper::getProcessServiceFactory()->createInstance(u"com.sun.star.document.TypeDetection"_ustr), uno::UNO_QUERY); |
319 | |
|
320 | 0 | OUString sTypeName; |
321 | 0 | try |
322 | 0 | { |
323 | 0 | sTypeName = xDetection->queryTypeByURL( rMedium.GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); |
324 | 0 | } |
325 | 0 | catch (uno::Exception&) |
326 | 0 | { |
327 | 0 | } |
328 | |
|
329 | 0 | rpFilter = nullptr; |
330 | 0 | if ( !sTypeName.isEmpty() ) |
331 | 0 | { |
332 | | // make sure filter list is initialized |
333 | 0 | m_rImpl.InitForIterating(); |
334 | 0 | rpFilter = GetFilter4EA( sTypeName ); |
335 | 0 | } |
336 | |
|
337 | 0 | return rpFilter ? ERRCODE_NONE : ERRCODE_ABORT; |
338 | 0 | } |
339 | | |
340 | | |
341 | | ErrCode SfxFilterMatcher::GuessFilter( SfxMedium& rMedium, std::shared_ptr<const SfxFilter>& rpFilter, SfxFilterFlags nMust, SfxFilterFlags nDont ) const |
342 | 0 | { |
343 | 0 | return GuessFilterControlDefaultUI( rMedium, rpFilter, nMust, nDont ); |
344 | 0 | } |
345 | | |
346 | | |
347 | | ErrCode SfxFilterMatcher::GuessFilterControlDefaultUI( SfxMedium& rMedium, std::shared_ptr<const SfxFilter>& rpFilter, SfxFilterFlags nMust, SfxFilterFlags nDont ) const |
348 | 0 | { |
349 | 0 | std::shared_ptr<const SfxFilter> pOldFilter = rpFilter; |
350 | | |
351 | | // no detection service -> nothing to do ! |
352 | 0 | uno::Reference<document::XTypeDetection> xDetection( |
353 | 0 | comphelper::getProcessServiceFactory()->createInstance(u"com.sun.star.document.TypeDetection"_ustr), uno::UNO_QUERY); |
354 | |
|
355 | 0 | if (!xDetection.is()) |
356 | 0 | return ERRCODE_ABORT; |
357 | | |
358 | 0 | try |
359 | 0 | { |
360 | | // open the stream one times only ... |
361 | | // Otherwise it will be tried more than once and show the same interaction more than once ... |
362 | |
|
363 | 0 | OUString sURL( rMedium.GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); |
364 | 0 | uno::Reference< io::XInputStream > xInStream = rMedium.GetInputStream(); |
365 | 0 | OUString aFilterName; |
366 | 0 | OUString sTypeName; |
367 | | |
368 | | // stream exists => deep detection (with preselection ... if possible) |
369 | 0 | if (xInStream.is()) |
370 | 0 | { |
371 | 0 | utl::MediaDescriptor aDescriptor; |
372 | |
|
373 | 0 | aDescriptor[utl::MediaDescriptor::PROP_URL ] <<= sURL; |
374 | 0 | aDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM ] <<= xInStream; |
375 | 0 | aDescriptor[utl::MediaDescriptor::PROP_INTERACTIONHANDLER] <<= rMedium.GetInteractionHandler(); |
376 | 0 | SfxStringItem const * it = rMedium.GetItemSet().GetItem(SID_REFERER); |
377 | 0 | if (it != nullptr) { |
378 | 0 | aDescriptor[utl::MediaDescriptor::PROP_REFERRER] |
379 | 0 | <<= it->GetValue(); |
380 | 0 | } |
381 | |
|
382 | 0 | if ( !m_rImpl.aName.isEmpty() ) |
383 | 0 | aDescriptor[utl::MediaDescriptor::PROP_DOCUMENTSERVICE] <<= m_rImpl.aName; |
384 | |
|
385 | 0 | if ( pOldFilter ) |
386 | 0 | { |
387 | 0 | aDescriptor[utl::MediaDescriptor::PROP_TYPENAME ] <<= pOldFilter->GetTypeName(); |
388 | 0 | aDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] <<= pOldFilter->GetFilterName(); |
389 | 0 | } |
390 | |
|
391 | 0 | uno::Sequence< beans::PropertyValue > lDescriptor = aDescriptor.getAsConstPropertyValueList(); |
392 | 0 | sTypeName = xDetection->queryTypeByDescriptor(lDescriptor, true); // lDescriptor is used as In/Out param ... don't use aDescriptor.getAsConstPropertyValueList() directly! |
393 | |
|
394 | 0 | for (const auto& rProp : lDescriptor) |
395 | 0 | { |
396 | 0 | if (rProp.Name == "FilterName") |
397 | | // Type detection picked a preferred filter for this format. |
398 | 0 | aFilterName = rProp.Value.get<OUString>(); |
399 | 0 | } |
400 | 0 | } |
401 | | // no stream exists => try flat detection without preselection as fallback |
402 | 0 | else |
403 | 0 | sTypeName = xDetection->queryTypeByURL(sURL); |
404 | |
|
405 | 0 | if (!sTypeName.isEmpty()) |
406 | 0 | { |
407 | 0 | std::shared_ptr<const SfxFilter> xNewFilter; |
408 | 0 | if (!aFilterName.isEmpty()) |
409 | | // Type detection returned a suitable filter for this. Use it. |
410 | 0 | xNewFilter = SfxFilter::GetFilterByName(aFilterName); |
411 | | |
412 | | // fdo#78742 respect requested document service if set |
413 | 0 | if (!xNewFilter || (!m_rImpl.aName.isEmpty() |
414 | 0 | && m_rImpl.aName != xNewFilter->GetServiceName())) |
415 | 0 | { |
416 | | // detect filter by given type |
417 | | // In case of this matcher is bound to a particular document type: |
418 | | // If there is no acceptable type for this document at all, the type detection has possibly returned something else. |
419 | | // The DocumentService property is only a preselection, and all preselections are considered as optional! |
420 | | // This "wrong" type will be sorted out now because we match only allowed filters to the detected type |
421 | 0 | uno::Sequence< beans::NamedValue > lQuery { { u"Name"_ustr, css::uno::Any(sTypeName) } }; |
422 | |
|
423 | 0 | xNewFilter = GetFilterForProps(lQuery, nMust, nDont); |
424 | 0 | } |
425 | |
|
426 | 0 | if (xNewFilter) |
427 | 0 | { |
428 | 0 | rpFilter = std::move(xNewFilter); |
429 | 0 | return ERRCODE_NONE; |
430 | 0 | } |
431 | 0 | } |
432 | 0 | } |
433 | 0 | catch (const uno::Exception&) |
434 | 0 | {} |
435 | | |
436 | 0 | return ERRCODE_ABORT; |
437 | 0 | } |
438 | | |
439 | | |
440 | | bool SfxFilterMatcher::IsFilterInstalled_Impl( const std::shared_ptr<const SfxFilter>& pFilter ) |
441 | 0 | { |
442 | 0 | if ( pFilter->GetFilterFlags() & SfxFilterFlags::MUSTINSTALL ) |
443 | 0 | { |
444 | | // Here could a re-installation be offered |
445 | 0 | OUString aText( SfxResId(STR_FILTER_NOT_INSTALLED) ); |
446 | 0 | aText = aText.replaceFirst( "$(FILTER)", pFilter->GetUIName() ); |
447 | 0 | std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(nullptr, |
448 | 0 | VclMessageType::Question, VclButtonsType::YesNo, |
449 | 0 | aText)); |
450 | 0 | xQueryBox->set_default_response(RET_YES); |
451 | |
|
452 | 0 | short nRet = xQueryBox->run(); |
453 | 0 | if ( nRet == RET_YES ) |
454 | 0 | { |
455 | | #ifdef DBG_UTIL |
456 | | // Start Setup |
457 | | std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr, |
458 | | VclMessageType::Info, VclButtonsType::Ok, |
459 | | u"Here should the Setup now be starting!"_ustr)); |
460 | | xInfoBox->run(); |
461 | | #endif |
462 | | // Installation must still give feedback if it worked or not, |
463 | | // then the Filterflag be deleted |
464 | 0 | } |
465 | |
|
466 | 0 | return ( !(pFilter->GetFilterFlags() & SfxFilterFlags::MUSTINSTALL) ); |
467 | 0 | } |
468 | 0 | else if ( pFilter->GetFilterFlags() & SfxFilterFlags::CONSULTSERVICE ) |
469 | 0 | { |
470 | 0 | OUString aText( SfxResId(STR_FILTER_CONSULT_SERVICE) ); |
471 | 0 | aText = aText.replaceFirst( "$(FILTER)", pFilter->GetUIName() ); |
472 | 0 | std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr, |
473 | 0 | VclMessageType::Info, VclButtonsType::Ok, |
474 | 0 | aText)); |
475 | 0 | xInfoBox->run(); |
476 | 0 | return false; |
477 | 0 | } |
478 | 0 | else |
479 | 0 | return true; |
480 | 0 | } |
481 | | |
482 | | |
483 | | ErrCode SfxFilterMatcher::DetectFilter( SfxMedium& rMedium, std::shared_ptr<const SfxFilter>& rpFilter ) const |
484 | | /* [Description] |
485 | | |
486 | | Here the Filter selection box is pulled up. Otherwise GuessFilter |
487 | | */ |
488 | | |
489 | 0 | { |
490 | 0 | std::shared_ptr<const SfxFilter> pFilter = rMedium.GetFilter(); |
491 | 0 | if ( pFilter ) |
492 | 0 | { |
493 | 0 | if( !IsFilterInstalled_Impl( pFilter ) ) |
494 | 0 | pFilter = nullptr; |
495 | 0 | else |
496 | 0 | { |
497 | 0 | const SfxStringItem* pSalvageItem = rMedium.GetItemSet().GetItem(SID_DOC_SALVAGE, false); |
498 | 0 | if ( ( pFilter->GetFilterFlags() & SfxFilterFlags::PACKED ) && pSalvageItem ) |
499 | | // Salvage is always done without packing |
500 | 0 | pFilter = nullptr; |
501 | 0 | } |
502 | 0 | } |
503 | |
|
504 | 0 | bool bPreview = rMedium.IsPreview_Impl(); |
505 | 0 | const SfxStringItem* pReferer = rMedium.GetItemSet().GetItem(SID_REFERER, false); |
506 | 0 | if ( bPreview && rMedium.IsRemote() && ( !pReferer || !pReferer->GetValue().match("private:searchfolder:") ) ) |
507 | 0 | return ERRCODE_ABORT; |
508 | | |
509 | 0 | ErrCode nErr = GuessFilter( rMedium, pFilter ); |
510 | 0 | if ( nErr == ERRCODE_ABORT ) |
511 | 0 | return nErr; |
512 | | |
513 | 0 | if ( nErr == ERRCODE_IO_PENDING ) |
514 | 0 | { |
515 | 0 | rpFilter = pFilter; |
516 | 0 | return nErr; |
517 | 0 | } |
518 | | |
519 | 0 | if ( !pFilter ) |
520 | 0 | { |
521 | 0 | std::shared_ptr<const SfxFilter> pInstallFilter; |
522 | | |
523 | | // Now test the filter which are not installed (ErrCode is irrelevant) |
524 | 0 | GuessFilter( rMedium, pInstallFilter, SfxFilterFlags::IMPORT, SfxFilterFlags::CONSULTSERVICE ); |
525 | 0 | if ( pInstallFilter ) |
526 | 0 | { |
527 | 0 | if ( IsFilterInstalled_Impl( pInstallFilter ) ) |
528 | 0 | { |
529 | | // Maybe the filter was installed afterwards. |
530 | 0 | pFilter = std::move(pInstallFilter); |
531 | 0 | } |
532 | 0 | } |
533 | 0 | else |
534 | 0 | { |
535 | | // Now test the filter, which first must be obtained by Star |
536 | | // (ErrCode is irrelevant) |
537 | 0 | GuessFilter( rMedium, pInstallFilter, SfxFilterFlags::IMPORT, SfxFilterFlags::NONE ); |
538 | 0 | if ( pInstallFilter ) |
539 | 0 | IsFilterInstalled_Impl( pInstallFilter ); |
540 | 0 | } |
541 | 0 | } |
542 | |
|
543 | 0 | bool bHidden = bPreview; |
544 | 0 | const SfxStringItem* pFlags = rMedium.GetItemSet().GetItem(SID_OPTIONS, false); |
545 | 0 | if ( !bHidden && pFlags ) |
546 | 0 | { |
547 | 0 | OUString aFlags( pFlags->GetValue() ); |
548 | 0 | aFlags = aFlags.toAsciiUpperCase(); |
549 | 0 | if( -1 != aFlags.indexOf( 'H' ) ) |
550 | 0 | bHidden = true; |
551 | 0 | } |
552 | 0 | rpFilter = pFilter; |
553 | |
|
554 | 0 | if ( bHidden ) |
555 | 0 | nErr = pFilter ? ERRCODE_NONE : ERRCODE_ABORT; |
556 | 0 | return nErr; |
557 | 0 | } |
558 | | |
559 | | std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilterForProps( const css::uno::Sequence < beans::NamedValue >& aSeq, SfxFilterFlags nMust, SfxFilterFlags nDont ) const |
560 | 0 | { |
561 | 0 | uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); |
562 | 0 | if( !xServiceManager ) |
563 | 0 | return nullptr; |
564 | | |
565 | 0 | static constexpr OUStringLiteral sTypeDetection = u"com.sun.star.document.TypeDetection"; |
566 | 0 | uno::Reference< container::XContainerQuery > xTypeCFG( xServiceManager->createInstance( sTypeDetection ), uno::UNO_QUERY ); |
567 | 0 | if ( !xTypeCFG ) |
568 | 0 | return nullptr; |
569 | | |
570 | | // make query for all types matching the properties |
571 | 0 | uno::Reference < css::container::XEnumeration > xEnum = xTypeCFG->createSubSetEnumerationByProperties( aSeq ); |
572 | 0 | uno::Sequence<beans::PropertyValue> aProps; |
573 | 0 | while ( xEnum->hasMoreElements() ) |
574 | 0 | { |
575 | 0 | static constexpr OUStringLiteral sPreferredFilter = u"PreferredFilter"; |
576 | 0 | static constexpr OUStringLiteral sName = u"Name"; |
577 | |
|
578 | 0 | xEnum->nextElement() >>= aProps; |
579 | 0 | OUString aValue, aName; |
580 | 0 | for( const auto & rPropVal : aProps) |
581 | 0 | { |
582 | 0 | if (rPropVal.Name == sPreferredFilter) |
583 | 0 | rPropVal.Value >>= aValue; |
584 | 0 | else if (rPropVal.Name == sName) |
585 | 0 | rPropVal.Value >>= aName; |
586 | 0 | } |
587 | | |
588 | | // try to get the preferred filter (works without loading all filters!) |
589 | 0 | if ( !aValue.isEmpty() ) |
590 | 0 | { |
591 | 0 | std::shared_ptr<const SfxFilter> pFilter = SfxFilter::GetFilterByName( aValue ); |
592 | 0 | if ( !pFilter || (pFilter->GetFilterFlags() & nMust) != nMust || (pFilter->GetFilterFlags() & nDont ) ) |
593 | | // check for filter flags |
594 | | // pFilter == 0: if preferred filter is a Writer filter, but Writer module is not installed |
595 | 0 | continue; |
596 | | |
597 | 0 | if ( !m_rImpl.aName.isEmpty() ) |
598 | 0 | { |
599 | | // if this is not the global FilterMatcher: check if filter matches the document type |
600 | 0 | if ( pFilter->GetServiceName() != m_rImpl.aName ) |
601 | 0 | { |
602 | | // preferred filter belongs to another document type; now we must search the filter |
603 | 0 | m_rImpl.InitForIterating(); |
604 | 0 | pFilter = GetFilter4EA( aName, nMust, nDont ); |
605 | 0 | if ( pFilter ) |
606 | 0 | return pFilter; |
607 | 0 | } |
608 | 0 | else |
609 | 0 | return pFilter; |
610 | 0 | } |
611 | 0 | else |
612 | 0 | return pFilter; |
613 | 0 | } |
614 | 0 | } |
615 | | |
616 | 0 | return nullptr; |
617 | 0 | } |
618 | | |
619 | | std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4Mime( const OUString& rMediaType, SfxFilterFlags nMust, SfxFilterFlags nDont ) const |
620 | 0 | { |
621 | 0 | if ( m_rImpl.pList ) |
622 | 0 | { |
623 | 0 | for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList) |
624 | 0 | { |
625 | 0 | SfxFilterFlags nFlags = pFilter->GetFilterFlags(); |
626 | 0 | if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetMimeType() == rMediaType ) |
627 | 0 | return pFilter; |
628 | 0 | } |
629 | | |
630 | 0 | return nullptr; |
631 | 0 | } |
632 | | |
633 | 0 | css::uno::Sequence < css::beans::NamedValue > aSeq { { u"MediaType"_ustr, css::uno::Any(rMediaType) } }; |
634 | 0 | return GetFilterForProps( aSeq, nMust, nDont ); |
635 | 0 | } |
636 | | |
637 | | std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4EA( const OUString& rType, SfxFilterFlags nMust, SfxFilterFlags nDont ) const |
638 | 0 | { |
639 | 0 | if ( m_rImpl.pList ) |
640 | 0 | { |
641 | 0 | std::shared_ptr<const SfxFilter> pFirst; |
642 | 0 | for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList) |
643 | 0 | { |
644 | 0 | SfxFilterFlags nFlags = pFilter->GetFilterFlags(); |
645 | 0 | if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetTypeName() == rType ) |
646 | 0 | { |
647 | 0 | if (nFlags & SfxFilterFlags::PREFERED) |
648 | 0 | return pFilter; |
649 | 0 | if (!pFirst) |
650 | 0 | pFirst = pFilter; |
651 | 0 | } |
652 | 0 | } |
653 | 0 | if (pFirst) |
654 | 0 | return pFirst; |
655 | | |
656 | 0 | return nullptr; |
657 | 0 | } |
658 | | |
659 | 0 | css::uno::Sequence < css::beans::NamedValue > aSeq { { u"Name"_ustr, css::uno::Any(rType) } }; |
660 | 0 | return GetFilterForProps( aSeq, nMust, nDont ); |
661 | 0 | } |
662 | | |
663 | | std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4Extension( const OUString& rExt, SfxFilterFlags nMust, SfxFilterFlags nDont ) const |
664 | 0 | { |
665 | 0 | if ( m_rImpl.pList ) |
666 | 0 | { |
667 | 0 | if (OUString sExt = ToUpper_Impl(rExt); !sExt.isEmpty()) |
668 | 0 | { |
669 | 0 | if (sExt[0] != '.') |
670 | 0 | sExt = "." + sExt; |
671 | |
|
672 | 0 | for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList) |
673 | 0 | { |
674 | 0 | SfxFilterFlags nFlags = pFilter->GetFilterFlags(); |
675 | 0 | if ((nFlags & nMust) == nMust && !(nFlags & nDont)) |
676 | 0 | { |
677 | 0 | OUString sWildCard = ToUpper_Impl(pFilter->GetWildcard().getGlob()); |
678 | |
|
679 | 0 | WildCard aCheck(sWildCard, ';'); |
680 | 0 | if (aCheck.Matches(sExt)) |
681 | 0 | return pFilter; |
682 | 0 | } |
683 | 0 | } |
684 | 0 | } |
685 | | |
686 | 0 | return nullptr; |
687 | 0 | } |
688 | | |
689 | | // Use extension without dot! |
690 | 0 | OUString sExt( rExt ); |
691 | 0 | if ( sExt.startsWith(".") ) |
692 | 0 | sExt = sExt.copy(1); |
693 | |
|
694 | 0 | css::uno::Sequence < css::beans::NamedValue > aSeq |
695 | 0 | { { u"Extensions"_ustr, css::uno::Any(uno::Sequence < OUString > { sExt } ) } }; |
696 | 0 | return GetFilterForProps( aSeq, nMust, nDont ); |
697 | 0 | } |
698 | | |
699 | | std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4ClipBoardId( SotClipboardFormatId nId, SfxFilterFlags nMust, SfxFilterFlags nDont ) const |
700 | 0 | { |
701 | 0 | if (nId == SotClipboardFormatId::NONE) |
702 | 0 | return nullptr; |
703 | | |
704 | 0 | css::uno::Sequence < css::beans::NamedValue > aSeq |
705 | 0 | { { u"ClipboardFormat"_ustr, css::uno::Any(SotExchange::GetFormatName( nId )) } }; |
706 | 0 | return GetFilterForProps( aSeq, nMust, nDont ); |
707 | 0 | } |
708 | | |
709 | | std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4UIName( std::u16string_view rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const |
710 | 0 | { |
711 | 0 | m_rImpl.InitForIterating(); |
712 | 0 | std::shared_ptr<const SfxFilter> pFirstFilter; |
713 | 0 | for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList) |
714 | 0 | { |
715 | 0 | SfxFilterFlags nFlags = pFilter->GetFilterFlags(); |
716 | 0 | if ( (nFlags & nMust) == nMust && |
717 | 0 | !(nFlags & nDont ) && pFilter->GetUIName() == rName ) |
718 | 0 | { |
719 | 0 | if ( pFilter->GetFilterFlags() & SfxFilterFlags::PREFERED ) |
720 | 0 | return pFilter; |
721 | 0 | else if ( !pFirstFilter ) |
722 | 0 | pFirstFilter = pFilter; |
723 | 0 | } |
724 | 0 | } |
725 | 0 | return pFirstFilter; |
726 | 0 | } |
727 | | |
728 | | std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4FilterName( const OUString& rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const |
729 | 0 | { |
730 | 0 | std::u16string_view aName( rName ); |
731 | 0 | sal_Int32 nIndex = rName.indexOf(": "); |
732 | 0 | if ( nIndex != -1 ) |
733 | 0 | { |
734 | 0 | SAL_WARN( "sfx.bastyp", "Old filter name used!"); |
735 | 0 | aName = rName.subView( nIndex + 2 ); |
736 | 0 | } |
737 | | |
738 | 0 | if ( bFirstRead ) |
739 | 0 | { |
740 | 0 | uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); |
741 | 0 | uno::Reference< container::XNameAccess > xFilterCFG ; |
742 | 0 | uno::Reference< container::XNameAccess > xTypeCFG ; |
743 | 0 | if( xServiceManager.is() ) |
744 | 0 | { |
745 | 0 | static constexpr OUStringLiteral sFilterFactory = u"com.sun.star.document.FilterFactory"; |
746 | 0 | static constexpr OUStringLiteral sTypeDetection = u"com.sun.star.document.TypeDetection"; |
747 | 0 | xFilterCFG.set( xServiceManager->createInstance( sFilterFactory ), uno::UNO_QUERY ); |
748 | 0 | xTypeCFG.set( xServiceManager->createInstance( sTypeDetection ), uno::UNO_QUERY ); |
749 | 0 | } |
750 | |
|
751 | 0 | if( xFilterCFG.is() && xTypeCFG.is() ) |
752 | 0 | { |
753 | 0 | if ( !pFilterArr ) |
754 | 0 | CreateFilterArr(); |
755 | 0 | else |
756 | 0 | { |
757 | 0 | for (const std::shared_ptr<const SfxFilter>& pFilter : *pFilterArr) |
758 | 0 | { |
759 | 0 | SfxFilterFlags nFlags = pFilter->GetFilterFlags(); |
760 | 0 | if ((nFlags & nMust) == nMust && !(nFlags & nDont) && pFilter->GetFilterName().equalsIgnoreAsciiCase(aName)) |
761 | 0 | return pFilter; |
762 | 0 | } |
763 | 0 | } |
764 | | |
765 | 0 | SfxFilterContainer::ReadSingleFilter_Impl( rName, xTypeCFG, xFilterCFG, false ); |
766 | 0 | } |
767 | 0 | } |
768 | | |
769 | 0 | SfxFilterList_Impl* pList = m_rImpl.pList; |
770 | 0 | if ( !pList ) |
771 | 0 | pList = pFilterArr; |
772 | |
|
773 | 0 | for (const std::shared_ptr<const SfxFilter>& pFilter : *pList) |
774 | 0 | { |
775 | 0 | SfxFilterFlags nFlags = pFilter->GetFilterFlags(); |
776 | 0 | if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetFilterName().equalsIgnoreAsciiCase(aName)) |
777 | 0 | return pFilter; |
778 | 0 | } |
779 | | |
780 | 0 | return nullptr; |
781 | 0 | } |
782 | | |
783 | | IMPL_LINK( SfxFilterMatcher, MaybeFileHdl_Impl, OUString*, pString, bool ) |
784 | 0 | { |
785 | 0 | std::shared_ptr<const SfxFilter> pFilter = GetFilter4Extension( *pString ); |
786 | 0 | return pFilter && |
787 | 0 | !pFilter->GetWildcard().Matches(u"") && |
788 | 0 | !pFilter->GetWildcard().Matches(u"*.*") && |
789 | 0 | !pFilter->GetWildcard().Matches(u"*"); |
790 | 0 | } |
791 | | |
792 | | |
793 | | SfxFilterMatcherIter::SfxFilterMatcherIter( |
794 | | const SfxFilterMatcher& rMatcher, |
795 | | SfxFilterFlags nOrMaskP, SfxFilterFlags nAndMaskP ) |
796 | 0 | : nOrMask( nOrMaskP ), nAndMask( nAndMaskP ), |
797 | 0 | nCurrent(0), m_rMatch(rMatcher.m_rImpl) |
798 | 0 | { |
799 | 0 | if( nOrMask == static_cast<SfxFilterFlags>(0xffff) ) //Due to faulty build on s |
800 | 0 | nOrMask = SfxFilterFlags::NONE; |
801 | 0 | m_rMatch.InitForIterating(); |
802 | 0 | } |
803 | | |
804 | | |
805 | | std::shared_ptr<const SfxFilter> SfxFilterMatcherIter::Find_Impl() |
806 | 0 | { |
807 | 0 | std::shared_ptr<const SfxFilter> pFilter; |
808 | 0 | while( nCurrent < m_rMatch.pList->size() ) |
809 | 0 | { |
810 | 0 | pFilter = (*m_rMatch.pList)[nCurrent++]; |
811 | 0 | SfxFilterFlags nFlags = pFilter->GetFilterFlags(); |
812 | 0 | if( ((nFlags & nOrMask) == nOrMask ) && !(nFlags & nAndMask ) ) |
813 | 0 | break; |
814 | 0 | pFilter = nullptr; |
815 | 0 | } |
816 | |
|
817 | 0 | return pFilter; |
818 | 0 | } |
819 | | |
820 | | std::shared_ptr<const SfxFilter> SfxFilterMatcherIter::First() |
821 | 0 | { |
822 | 0 | nCurrent = 0; |
823 | 0 | return Find_Impl(); |
824 | 0 | } |
825 | | |
826 | | |
827 | | std::shared_ptr<const SfxFilter> SfxFilterMatcherIter::Next() |
828 | 0 | { |
829 | 0 | return Find_Impl(); |
830 | 0 | } |
831 | | |
832 | | /*--------------------------------------------------------------- |
833 | | helper to build own formatted string from given stringlist by |
834 | | using given separator |
835 | | ---------------------------------------------------------------*/ |
836 | | static OUString implc_convertStringlistToString( const uno::Sequence< OUString >& lList , |
837 | | sal_Unicode cSeparator, |
838 | | std::u16string_view sPrefix ) |
839 | 0 | { |
840 | 0 | OUStringBuffer sString ( 1000 ) ; |
841 | 0 | sal_Int32 nCount = lList.getLength(); |
842 | 0 | sal_Int32 nItem = 0 ; |
843 | 0 | for( nItem=0; nItem<nCount; ++nItem ) |
844 | 0 | { |
845 | 0 | if( !sPrefix.empty() ) |
846 | 0 | { |
847 | 0 | sString.append( sPrefix ); |
848 | 0 | } |
849 | 0 | sString.append( lList[nItem] ); |
850 | 0 | if( nItem+1<nCount ) |
851 | 0 | { |
852 | 0 | sString.append( cSeparator ); |
853 | 0 | } |
854 | 0 | } |
855 | 0 | return sString.makeStringAndClear(); |
856 | 0 | } |
857 | | |
858 | | |
859 | | void SfxFilterContainer::ReadSingleFilter_Impl( |
860 | | const OUString& rName, |
861 | | const uno::Reference< container::XNameAccess >& xTypeCFG, |
862 | | const uno::Reference< container::XNameAccess >& xFilterCFG, |
863 | | bool bUpdate |
864 | | ) |
865 | 0 | { |
866 | 0 | OUString sFilterName( rName ); |
867 | 0 | SfxFilterList_Impl& rList = *pFilterArr; |
868 | 0 | uno::Sequence< beans::PropertyValue > lFilterProperties; |
869 | 0 | uno::Any aResult; |
870 | 0 | try |
871 | 0 | { |
872 | 0 | aResult = xFilterCFG->getByName( sFilterName ); |
873 | 0 | } |
874 | 0 | catch( container::NoSuchElementException& ) |
875 | 0 | { |
876 | 0 | aResult = uno::Any(); |
877 | 0 | } |
878 | |
|
879 | 0 | if( !(aResult >>= lFilterProperties) ) |
880 | 0 | return; |
881 | | |
882 | | // collect information to add filter to container |
883 | | // (attention: some information aren't available on filter directly ... you must search for corresponding type too!) |
884 | 0 | SfxFilterFlags nFlags = SfxFilterFlags::NONE; |
885 | 0 | SotClipboardFormatId nClipboardId = SotClipboardFormatId::NONE; |
886 | 0 | sal_Int32 nFormatVersion = 0 ; |
887 | 0 | OUString sMimeType ; |
888 | 0 | OUString sType ; |
889 | 0 | OUString sUIName ; |
890 | 0 | OUString sHumanName ; |
891 | 0 | OUString sDefaultTemplate ; |
892 | 0 | OUString sUserData ; |
893 | 0 | OUString sExtension ; |
894 | 0 | OUString sServiceName ; |
895 | 0 | bool bEnabled = true ; |
896 | | |
897 | | // first get directly available properties |
898 | 0 | for (const auto& rFilterProperty : lFilterProperties) |
899 | 0 | { |
900 | 0 | if ( rFilterProperty.Name == "FileFormatVersion" ) |
901 | 0 | { |
902 | 0 | rFilterProperty.Value >>= nFormatVersion; |
903 | 0 | } |
904 | 0 | else if ( rFilterProperty.Name == "TemplateName" ) |
905 | 0 | { |
906 | 0 | rFilterProperty.Value >>= sDefaultTemplate; |
907 | 0 | } |
908 | 0 | else if ( rFilterProperty.Name == "Flags" ) |
909 | 0 | { |
910 | 0 | sal_Int32 nTmp(0); |
911 | 0 | rFilterProperty.Value >>= nTmp; |
912 | 0 | assert((nTmp & ~o3tl::typed_flags<SfxFilterFlags>::mask) == 0); |
913 | 0 | nFlags = static_cast<SfxFilterFlags>(nTmp); |
914 | 0 | } |
915 | 0 | else if ( rFilterProperty.Name == "UIName" ) |
916 | 0 | { |
917 | 0 | rFilterProperty.Value >>= sUIName; |
918 | 0 | } |
919 | 0 | else if ( rFilterProperty.Name == "UserData" ) |
920 | 0 | { |
921 | 0 | uno::Sequence< OUString > lUserData; |
922 | 0 | rFilterProperty.Value >>= lUserData; |
923 | 0 | sUserData = implc_convertStringlistToString( lUserData, ',', u"" ); |
924 | 0 | } |
925 | 0 | else if ( rFilterProperty.Name == "DocumentService" ) |
926 | 0 | { |
927 | 0 | rFilterProperty.Value >>= sServiceName; |
928 | 0 | } |
929 | 0 | else if (rFilterProperty.Name == "ExportExtension") |
930 | 0 | { |
931 | | // Extension preferred by the filter. This takes precedence |
932 | | // over those that are given in the file format type. |
933 | 0 | rFilterProperty.Value >>= sExtension; |
934 | 0 | sExtension = "*." + sExtension; |
935 | 0 | } |
936 | 0 | else if ( rFilterProperty.Name == "Type" ) |
937 | 0 | { |
938 | 0 | rFilterProperty.Value >>= sType; |
939 | | // Try to get filter .. but look for any exceptions! |
940 | | // May be filter was deleted by another thread ... |
941 | 0 | try |
942 | 0 | { |
943 | 0 | aResult = xTypeCFG->getByName( sType ); |
944 | 0 | } |
945 | 0 | catch (const container::NoSuchElementException&) |
946 | 0 | { |
947 | 0 | aResult = uno::Any(); |
948 | 0 | } |
949 | |
|
950 | 0 | uno::Sequence< beans::PropertyValue > lTypeProperties; |
951 | 0 | if( aResult >>= lTypeProperties ) |
952 | 0 | { |
953 | | // get indirect available properties then (types) |
954 | 0 | for (const auto& rTypeProperty : lTypeProperties) |
955 | 0 | { |
956 | 0 | if ( rTypeProperty.Name == "ClipboardFormat" ) |
957 | 0 | { |
958 | 0 | rTypeProperty.Value >>= sHumanName; |
959 | 0 | } |
960 | 0 | else if ( rTypeProperty.Name == "MediaType" ) |
961 | 0 | { |
962 | 0 | rTypeProperty.Value >>= sMimeType; |
963 | 0 | } |
964 | 0 | else if ( rTypeProperty.Name == "Extensions" ) |
965 | 0 | { |
966 | 0 | if (sExtension.isEmpty()) |
967 | 0 | { |
968 | 0 | uno::Sequence< OUString > lExtensions; |
969 | 0 | rTypeProperty.Value >>= lExtensions; |
970 | 0 | sExtension = implc_convertStringlistToString( lExtensions, ';', u"*." ); |
971 | 0 | } |
972 | 0 | } |
973 | 0 | } |
974 | 0 | } |
975 | 0 | } |
976 | 0 | else if ( rFilterProperty.Name == "Enabled" ) |
977 | 0 | { |
978 | 0 | rFilterProperty.Value >>= bEnabled; |
979 | 0 | } |
980 | |
|
981 | 0 | } |
982 | |
|
983 | 0 | if ( sServiceName.isEmpty() ) |
984 | 0 | return; |
985 | | |
986 | | // old formats are found ... using HumanPresentableName! |
987 | 0 | if( !sHumanName.isEmpty() ) |
988 | 0 | { |
989 | 0 | nClipboardId = SotExchange::RegisterFormatName( sHumanName ); |
990 | | |
991 | | // For external filters ignore clipboard IDs |
992 | 0 | if(nFlags & SfxFilterFlags::STARONEFILTER) |
993 | 0 | { |
994 | 0 | nClipboardId = SotClipboardFormatId::NONE; |
995 | 0 | } |
996 | 0 | } |
997 | | // register SfxFilter |
998 | | // first erase module name from old filter names! |
999 | | // e.g: "scalc: DIF" => "DIF" |
1000 | 0 | sal_Int32 nStartRealName = sFilterName.indexOf( ": " ); |
1001 | 0 | if( nStartRealName != -1 ) |
1002 | 0 | { |
1003 | 0 | SAL_WARN( "sfx.bastyp", "Old format, not supported!"); |
1004 | 0 | sFilterName = sFilterName.copy( nStartRealName+2 ); |
1005 | 0 | } |
1006 | | |
1007 | 0 | std::shared_ptr<const SfxFilter> pFilter = bUpdate ? SfxFilter::GetFilterByName( sFilterName ) : nullptr; |
1008 | 0 | if (!pFilter) |
1009 | 0 | { |
1010 | 0 | pFilter = std::make_shared<SfxFilter>( sFilterName , |
1011 | 0 | sExtension , |
1012 | 0 | nFlags , |
1013 | 0 | nClipboardId , |
1014 | 0 | sType , |
1015 | 0 | sMimeType , |
1016 | 0 | sUserData , |
1017 | 0 | sServiceName , |
1018 | 0 | bEnabled ); |
1019 | 0 | rList.push_back( pFilter ); |
1020 | 0 | } |
1021 | 0 | else |
1022 | 0 | { |
1023 | 0 | SfxFilter* pFilt = const_cast<SfxFilter*>(pFilter.get()); |
1024 | 0 | pFilt->maFilterName = sFilterName; |
1025 | 0 | pFilt->aWildCard = WildCard(sExtension, ';'); |
1026 | 0 | pFilt->nFormatType = nFlags; |
1027 | 0 | pFilt->lFormat = nClipboardId; |
1028 | 0 | pFilt->aTypeName = sType; |
1029 | 0 | pFilt->aMimeType = sMimeType; |
1030 | 0 | pFilt->aUserData = sUserData; |
1031 | 0 | pFilt->aServiceName = sServiceName; |
1032 | 0 | pFilt->mbEnabled = bEnabled; |
1033 | 0 | } |
1034 | |
|
1035 | 0 | SfxFilter* pFilt = const_cast<SfxFilter*>(pFilter.get()); |
1036 | | |
1037 | | // Don't forget to set right UIName! |
1038 | | // Otherwise internal name is used as fallback ... |
1039 | 0 | pFilt->SetUIName( sUIName ); |
1040 | 0 | pFilt->SetDefaultTemplate( sDefaultTemplate ); |
1041 | 0 | if( nFormatVersion ) |
1042 | 0 | { |
1043 | 0 | pFilt->SetVersion( nFormatVersion ); |
1044 | 0 | } |
1045 | 0 | } |
1046 | | |
1047 | | void SfxFilterContainer::ReadFilters_Impl( bool bUpdate ) |
1048 | 0 | { |
1049 | 0 | if ( !pFilterArr ) |
1050 | 0 | { |
1051 | 0 | CreateFilterArr(); |
1052 | 0 | assert(pFilterArr); |
1053 | 0 | } |
1054 | |
|
1055 | 0 | bFirstRead = false; |
1056 | 0 | SfxFilterList_Impl& rList = *pFilterArr; |
1057 | |
|
1058 | 0 | try |
1059 | 0 | { |
1060 | | // get the FilterFactory service to access the registered filters ... and types! |
1061 | 0 | uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); |
1062 | 0 | uno::Reference< container::XNameAccess > xFilterCFG ; |
1063 | 0 | uno::Reference< container::XNameAccess > xTypeCFG ; |
1064 | 0 | if( xServiceManager.is() ) |
1065 | 0 | { |
1066 | 0 | xFilterCFG.set( xServiceManager->createInstance( u"com.sun.star.document.FilterFactory"_ustr ), uno::UNO_QUERY ); |
1067 | 0 | xTypeCFG.set( xServiceManager->createInstance( u"com.sun.star.document.TypeDetection"_ustr ), uno::UNO_QUERY ); |
1068 | 0 | } |
1069 | |
|
1070 | 0 | if( xFilterCFG.is() && xTypeCFG.is() ) |
1071 | 0 | { |
1072 | | // select right query to get right set of filters for search module |
1073 | 0 | const uno::Sequence< OUString > lFilterNames = xFilterCFG->getElementNames(); |
1074 | 0 | if ( lFilterNames.hasElements() ) |
1075 | 0 | { |
1076 | | // If list of filters already exist ... |
1077 | | // ReadExternalFilters must work in update mode. |
1078 | | // Best way seems to mark all filters NOT_INSTALLED |
1079 | | // and change it back for all valid filters afterwards. |
1080 | 0 | if( !rList.empty() ) |
1081 | 0 | { |
1082 | 0 | bUpdate = true; |
1083 | 0 | for (const std::shared_ptr<const SfxFilter>& pFilter : rList) |
1084 | 0 | { |
1085 | 0 | SfxFilter* pNonConstFilter = const_cast<SfxFilter*>(pFilter.get()); |
1086 | 0 | pNonConstFilter->nFormatType |= SFX_FILTER_NOTINSTALLED; |
1087 | 0 | } |
1088 | 0 | } |
1089 | | |
1090 | | // get all properties of filters ... put it into the filter container |
1091 | 0 | for( const OUString& sFilterName : lFilterNames ) |
1092 | 0 | { |
1093 | | // Try to get filter .. but look for any exceptions! |
1094 | | // May be filter was deleted by another thread ... |
1095 | 0 | ReadSingleFilter_Impl( sFilterName, xTypeCFG, xFilterCFG, bUpdate ); |
1096 | 0 | } |
1097 | 0 | } |
1098 | 0 | } |
1099 | 0 | } |
1100 | 0 | catch(const uno::Exception&) |
1101 | 0 | { |
1102 | 0 | SAL_WARN( "sfx.bastyp", "SfxFilterContainer::ReadFilter()\nException detected. Possible not all filters could be cached." ); |
1103 | 0 | } |
1104 | | |
1105 | 0 | if ( bUpdate ) |
1106 | 0 | { |
1107 | | // global filter array was modified, factory specific ones might need an |
1108 | | // update too |
1109 | 0 | for (const auto& aImpl : aImplArr) |
1110 | 0 | aImpl->Update(); |
1111 | 0 | } |
1112 | 0 | } |
1113 | | |
1114 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |