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 "FilterConfigCache.hxx"
21
22 #include <vcl/graphicfilter.hxx>
23 #include <unotools/configmgr.hxx>
24 #include <tools/svlibrary.h>
25 #include <com/sun/star/uno/Any.h>
26 #include <comphelper/processfactory.hxx>
27 #include <comphelper/sequence.hxx>
28 #include <com/sun/star/uno/Exception.hpp>
29 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
30 #include <com/sun/star/beans/PropertyValue.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/configuration/theDefaultProvider.hpp>
33 #include <com/sun/star/container/XNameAccess.hpp>
34
35 using namespace ::com::sun::star::lang ; // XMultiServiceFactory
36 using namespace ::com::sun::star::container ; // XNameAccess
37 using namespace ::com::sun::star::uno ; // Reference
38 using namespace ::com::sun::star::beans ; // PropertyValue
39 using namespace ::com::sun::star::configuration ;
40
41 const char* FilterConfigCache::FilterConfigCacheEntry::InternalPixelFilterNameList[] =
42 {
43 IMP_BMP, IMP_GIF, IMP_PNG,IMP_JPEG, IMP_XBM, IMP_XPM,
44 EXP_BMP, EXP_JPEG, EXP_PNG, IMP_MOV, nullptr
45 };
46
47 const char* FilterConfigCache::FilterConfigCacheEntry::InternalVectorFilterNameList[] =
48 {
49 IMP_SVMETAFILE, IMP_WMF, IMP_EMF, IMP_SVG, IMP_PDF,
50 EXP_SVMETAFILE, EXP_WMF, EXP_EMF, EXP_SVG, EXP_PDF, nullptr
51 };
52
53 const char* FilterConfigCache::FilterConfigCacheEntry::ExternalPixelFilterNameList[] =
54 {
55 "egi", "icd", "ipd", "ipx", "ipb", "epb", "epg",
56 "epp", "ira", "era", "itg", "iti", "eti", "exp", nullptr
57 };
58
CreateFilterName(const OUString & rUserDataEntry)59 void FilterConfigCache::FilterConfigCacheEntry::CreateFilterName( const OUString& rUserDataEntry )
60 {
61 bIsPixelFormat = bIsInternalFilter = false;
62 sFilterName = rUserDataEntry;
63 const char** pPtr;
64 for ( pPtr = InternalPixelFilterNameList; *pPtr && !bIsInternalFilter; pPtr++ )
65 {
66 if ( sFilterName.equalsIgnoreAsciiCaseAscii( *pPtr ) )
67 {
68 bIsInternalFilter = true;
69 bIsPixelFormat = true;
70 }
71 }
72 for ( pPtr = InternalVectorFilterNameList; *pPtr && !bIsInternalFilter; pPtr++ )
73 {
74 if ( sFilterName.equalsIgnoreAsciiCaseAscii( *pPtr ) )
75 bIsInternalFilter = true;
76 }
77 if ( !bIsInternalFilter )
78 {
79 for ( pPtr = ExternalPixelFilterNameList; *pPtr && !bIsPixelFormat; pPtr++ )
80 {
81 if ( sFilterName.equalsIgnoreAsciiCaseAscii( *pPtr ) )
82 bIsPixelFormat = true;
83 }
84 sExternalFilterName = sFilterName;
85 sFilterName = SVLIBRARY("gie");
86 }
87 }
88
GetShortName()89 OUString FilterConfigCache::FilterConfigCacheEntry::GetShortName()
90 {
91 OUString aShortName;
92 if ( !lExtensionList.empty() )
93 {
94 aShortName = lExtensionList[ 0 ];
95 if ( aShortName.startsWith( "*." ) )
96 aShortName = aShortName.replaceAt( 0, 2, "" );
97 }
98 return aShortName;
99 }
100
101 /** helper to open the configuration root of the underlying
102 config package
103
104 @param sPackage
105 specify, which config package should be opened.
106 Must be one of "types" or "filters"
107
108 @return A valid object if open was successful. The access on opened
109 data will be readonly. It returns NULL in case open failed.
110
111 @throws It let pass RuntimeExceptions only.
112 */
openConfig(const char * sPackage)113 static Reference< XInterface > openConfig(const char* sPackage)
114 {
115 Reference< XComponentContext > xContext(
116 comphelper::getProcessComponentContext() );
117 Reference< XInterface > xCfg;
118 try
119 {
120 // get access to config API (not to file!)
121 Reference< XMultiServiceFactory > xConfigProvider = theDefaultProvider::get( xContext );
122
123 Sequence< Any > lParams(1);
124 PropertyValue aParam ;
125
126 // define cfg path for open
127 aParam.Name = "nodepath";
128 if (rtl_str_compareIgnoreAsciiCase(sPackage, "types") == 0)
129 aParam.Value <<= OUString( "/org.openoffice.TypeDetection.Types/Types" );
130 if (rtl_str_compareIgnoreAsciiCase(sPackage, "filters") == 0)
131 aParam.Value <<= OUString( "/org.openoffice.TypeDetection.GraphicFilter/Filters" );
132 lParams[0] <<= aParam;
133
134 // get access to file
135 xCfg = xConfigProvider->createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess", lParams);
136 }
137 catch(const RuntimeException&)
138 { throw; }
139 catch(const Exception&)
140 { xCfg.clear(); }
141
142 return xCfg;
143 }
144
ImplInit()145 void FilterConfigCache::ImplInit()
146 {
147 OUString const STYPE ( "Type" );
148 OUString const SUINAME ( "UIName" );
149 OUString const SFLAGS ( "Flags" );
150 OUString const SMEDIATYPE ( "MediaType" );
151 OUString const SEXTENSIONS ( "Extensions" );
152 OUString const SFORMATNAME ( "FormatName" );
153 OUString const SREALFILTERNAME ( "RealFilterName" );
154
155 // get access to config
156 Reference< XNameAccess > xTypeAccess ( openConfig("types" ), UNO_QUERY );
157 Reference< XNameAccess > xFilterAccess( openConfig("filters"), UNO_QUERY );
158
159 if ( xTypeAccess.is() && xFilterAccess.is() )
160 {
161 const Sequence< OUString > lAllFilter = xFilterAccess->getElementNames();
162
163 for ( const OUString& sInternalFilterName : lAllFilter )
164 {
165 Reference< XPropertySet > xFilterSet;
166 xFilterAccess->getByName( sInternalFilterName ) >>= xFilterSet;
167 if (!xFilterSet.is())
168 continue;
169
170 FilterConfigCacheEntry aEntry;
171
172 aEntry.sInternalFilterName = sInternalFilterName;
173 xFilterSet->getPropertyValue(STYPE) >>= aEntry.sType;
174 xFilterSet->getPropertyValue(SUINAME) >>= aEntry.sUIName;
175 xFilterSet->getPropertyValue(SREALFILTERNAME) >>= aEntry.sFilterType;
176 Sequence< OUString > lFlags;
177 xFilterSet->getPropertyValue(SFLAGS) >>= lFlags;
178 if (lFlags.getLength()!=1 || lFlags[0].isEmpty())
179 continue;
180 if (lFlags[0].equalsIgnoreAsciiCase("import"))
181 aEntry.nFlags = 1;
182 else if (lFlags[0].equalsIgnoreAsciiCase("export"))
183 aEntry.nFlags = 2;
184
185 OUString sFormatName;
186 xFilterSet->getPropertyValue(SFORMATNAME) >>= sFormatName;
187 aEntry.CreateFilterName( sFormatName );
188
189 Reference< XPropertySet > xTypeSet;
190 xTypeAccess->getByName( aEntry.sType ) >>= xTypeSet;
191 if (!xTypeSet.is())
192 continue;
193
194 xTypeSet->getPropertyValue(SMEDIATYPE) >>= aEntry.sMediaType;
195 css::uno::Sequence<OUString> tmp;
196 if (xTypeSet->getPropertyValue(SEXTENSIONS) >>= tmp)
197 aEntry.lExtensionList = comphelper::sequenceToContainer<std::vector<OUString>>(tmp);
198
199 // The first extension will be used
200 // to generate our internal FilterType ( BMP, WMF ... )
201 OUString aExtension( aEntry.GetShortName() );
202 if (aExtension.getLength() != 3)
203 continue;
204
205 if ( aEntry.nFlags & 1 )
206 aImport.push_back( aEntry );
207 if ( aEntry.nFlags & 2 )
208 aExport.push_back( aEntry );
209
210 // bFilterEntryCreated!?
211 if (!( aEntry.nFlags & 3 ))
212 continue; //? Entry was already inserted ... but following code will be suppressed?!
213 }
214 }
215 };
216
217 const char* FilterConfigCache::InternalFilterListForSvxLight[] =
218 {
219 "bmp","1","SVBMP",
220 "bmp","2","SVBMP",
221 "dxf","1","idx",
222 "eps","1","ips",
223 "eps","2","eps",
224 "gif","1","SVIGIF",
225 "gif","2","egi",
226 "jpg","1","SVIJPEG",
227 "jpg","2","SVEJPEG",
228 "mov","1","SVMOV",
229 "mov","2","SVMOV",
230 "met","1","ime",
231 "png","1","SVIPNG",
232 "png","2","SVEPNG",
233 "pct","1","ipt",
234 "pct","2","ept",
235 "pcd","1","icd",
236 "psd","1","ipd",
237 "pcx","1","ipx",
238 "pbm","1","ipb",
239 "pgm","1","ipb",
240 "ppm","1","ipb",
241 "ras","1","ira",
242 "ras","2","era",
243 "svm","1","SVMETAFILE",
244 "svm","2","SVMETAFILE",
245 "tga","1","itg",
246 "tif","1","iti",
247 "tif","2","eti",
248 "emf","1","SVEMF",
249 "emf","2","SVEMF",
250 "wmf","1","SVWMF",
251 "wmf","2","SVWMF",
252 "xbm","1","SVIXBM",
253 "xpm","1","SVIXPM",
254 "xpm","2","exp",
255 "svg","1","SVISVG",
256 "svg","2","SVESVG",
257 nullptr
258 };
259
ImplInitSmart()260 void FilterConfigCache::ImplInitSmart()
261 {
262 const char** pPtr;
263 for ( pPtr = InternalFilterListForSvxLight; *pPtr; pPtr++ )
264 {
265 FilterConfigCacheEntry aEntry;
266
267 OUString sExtension( OUString::createFromAscii( *pPtr++ ) );
268
269 aEntry.lExtensionList.push_back(sExtension);
270
271 aEntry.sType = sExtension;
272 aEntry.sUIName = sExtension;
273
274 OString sFlags( *pPtr++ );
275 aEntry.nFlags = sFlags.toInt32();
276
277 OUString sUserData( OUString::createFromAscii( *pPtr ) );
278 aEntry.CreateFilterName( sUserData );
279
280 if ( aEntry.nFlags & 1 )
281 aImport.push_back( aEntry );
282 if ( aEntry.nFlags & 2 )
283 aExport.push_back( aEntry );
284 }
285 }
286
FilterConfigCache(bool bConfig)287 FilterConfigCache::FilterConfigCache( bool bConfig )
288 {
289 if (bConfig)
290 bConfig = !utl::ConfigManager::IsFuzzing();
291 if (bConfig)
292 ImplInit();
293 else
294 ImplInitSmart();
295 }
296
~FilterConfigCache()297 FilterConfigCache::~FilterConfigCache()
298 {
299 }
300
GetImportFilterName(sal_uInt16 nFormat)301 OUString FilterConfigCache::GetImportFilterName( sal_uInt16 nFormat )
302 {
303 if( nFormat < aImport.size() )
304 return aImport[ nFormat ].sFilterName;
305 return OUString();
306 }
307
GetImportFormatNumber(const OUString & rFormatName)308 sal_uInt16 FilterConfigCache::GetImportFormatNumber( const OUString& rFormatName )
309 {
310 sal_uInt16 nPos = 0;
311 for (auto const& elem : aImport)
312 {
313 if ( elem.sUIName.equalsIgnoreAsciiCase( rFormatName ) )
314 return nPos;
315 ++nPos;
316 }
317 return GRFILTER_FORMAT_NOTFOUND;
318 }
319
320 /// get the index of the filter that matches this extension
GetImportFormatNumberForExtension(const OUString & rExt)321 sal_uInt16 FilterConfigCache::GetImportFormatNumberForExtension( const OUString& rExt )
322 {
323 sal_uInt16 nPos = 0;
324 for (auto const& elem : aImport)
325 {
326 for ( OUString const & s : elem.lExtensionList )
327 {
328 if ( s.equalsIgnoreAsciiCase( rExt ) )
329 return nPos;
330 }
331 ++nPos;
332 }
333 return GRFILTER_FORMAT_NOTFOUND;
334 }
335
GetImportFormatNumberForShortName(const OUString & rShortName)336 sal_uInt16 FilterConfigCache::GetImportFormatNumberForShortName( const OUString& rShortName )
337 {
338 sal_uInt16 nPos = 0;
339 for (auto & elem : aImport)
340 {
341 if ( elem.GetShortName().equalsIgnoreAsciiCase( rShortName ) )
342 return nPos;
343 ++nPos;
344 }
345 return GRFILTER_FORMAT_NOTFOUND;
346 }
347
GetImportFormatNumberForTypeName(const OUString & rType)348 sal_uInt16 FilterConfigCache::GetImportFormatNumberForTypeName( const OUString& rType )
349 {
350 sal_uInt16 nPos = 0;
351 for (auto const& elem : aImport)
352 {
353 if ( elem.sType.equalsIgnoreAsciiCase( rType ) )
354 return nPos;
355 ++nPos;
356 }
357 return GRFILTER_FORMAT_NOTFOUND;
358 }
359
GetImportFormatName(sal_uInt16 nFormat)360 OUString FilterConfigCache::GetImportFormatName( sal_uInt16 nFormat )
361 {
362 if( nFormat < aImport.size() )
363 return aImport[ nFormat ].sUIName;
364 return OUString();
365 }
366
GetImportFormatMediaType(sal_uInt16 nFormat)367 OUString FilterConfigCache::GetImportFormatMediaType( sal_uInt16 nFormat )
368 {
369 if( nFormat < aImport.size() )
370 return aImport[ nFormat ].sMediaType;
371 return OUString();
372 }
373
GetImportFormatShortName(sal_uInt16 nFormat)374 OUString FilterConfigCache::GetImportFormatShortName( sal_uInt16 nFormat )
375 {
376 if( nFormat < aImport.size() )
377 return aImport[ nFormat ].GetShortName();
378 return OUString();
379 }
380
GetImportFormatExtension(sal_uInt16 nFormat,sal_Int32 nEntry)381 OUString FilterConfigCache::GetImportFormatExtension( sal_uInt16 nFormat, sal_Int32 nEntry )
382 {
383 if ( (nFormat < aImport.size()) && (size_t(nEntry) < aImport[ nFormat ].lExtensionList.size()) )
384 return aImport[ nFormat ].lExtensionList[ nEntry ];
385 return OUString();
386 }
387
GetImportFilterType(sal_uInt16 nFormat)388 OUString FilterConfigCache::GetImportFilterType( sal_uInt16 nFormat )
389 {
390 if( nFormat < aImport.size() )
391 return aImport[ nFormat ].sType;
392 return OUString();
393 }
394
GetImportFilterTypeName(sal_uInt16 nFormat)395 OUString FilterConfigCache::GetImportFilterTypeName( sal_uInt16 nFormat )
396 {
397 if( nFormat < aImport.size() )
398 return aImport[ nFormat ].sFilterType;
399 return OUString();
400 }
401
GetExternalFilterName(sal_uInt16 nFormat,bool bExport)402 OUString FilterConfigCache::GetExternalFilterName(sal_uInt16 nFormat, bool bExport)
403 {
404 if (bExport)
405 {
406 if (nFormat < aExport.size())
407 return aExport[nFormat].sExternalFilterName;
408 }
409 else
410 {
411 if (nFormat < aImport.size())
412 return aImport[nFormat].sExternalFilterName;
413 }
414 return OUString();
415 }
416
GetImportWildcard(sal_uInt16 nFormat,sal_Int32 nEntry)417 OUString FilterConfigCache::GetImportWildcard(sal_uInt16 nFormat, sal_Int32 nEntry)
418 {
419 OUString aWildcard( GetImportFormatExtension( nFormat, nEntry ) );
420 if ( !aWildcard.isEmpty() )
421 aWildcard = aWildcard.replaceAt( 0, 0, "*." );
422 return aWildcard;
423 }
424
IsImportInternalFilter(sal_uInt16 nFormat)425 bool FilterConfigCache::IsImportInternalFilter( sal_uInt16 nFormat )
426 {
427 return (nFormat < aImport.size()) && aImport[ nFormat ].bIsInternalFilter;
428 }
429
GetExportFilterName(sal_uInt16 nFormat)430 OUString FilterConfigCache::GetExportFilterName( sal_uInt16 nFormat )
431 {
432 if( nFormat < aExport.size() )
433 return aExport[ nFormat ].sFilterName;
434 return OUString();
435 }
436
GetExportFormatNumber(const OUString & rFormatName)437 sal_uInt16 FilterConfigCache::GetExportFormatNumber(const OUString& rFormatName)
438 {
439 sal_uInt16 nPos = 0;
440 for (auto const& elem : aExport)
441 {
442 if ( elem.sUIName.equalsIgnoreAsciiCase( rFormatName ) )
443 return nPos;
444 ++nPos;
445 }
446 return GRFILTER_FORMAT_NOTFOUND;
447 }
448
GetExportFormatNumberForMediaType(const OUString & rMediaType)449 sal_uInt16 FilterConfigCache::GetExportFormatNumberForMediaType( const OUString& rMediaType )
450 {
451 sal_uInt16 nPos = 0;
452 for (auto const& elem : aExport)
453 {
454 if ( elem.sMediaType.equalsIgnoreAsciiCase( rMediaType ) )
455 return nPos;
456 ++nPos;
457 }
458 return GRFILTER_FORMAT_NOTFOUND;
459 }
460
GetExportFormatNumberForShortName(const OUString & rShortName)461 sal_uInt16 FilterConfigCache::GetExportFormatNumberForShortName( const OUString& rShortName )
462 {
463 sal_uInt16 nPos = 0;
464 for (auto & elem : aExport)
465 {
466 if ( elem.GetShortName().equalsIgnoreAsciiCase( rShortName ) )
467 return nPos;
468 ++nPos;
469 }
470 return GRFILTER_FORMAT_NOTFOUND;
471 }
472
GetExportFormatNumberForTypeName(const OUString & rType)473 sal_uInt16 FilterConfigCache::GetExportFormatNumberForTypeName( const OUString& rType )
474 {
475 sal_uInt16 nPos = 0;
476 for (auto const& elem : aExport)
477 {
478 if ( elem.sType.equalsIgnoreAsciiCase( rType ) )
479 return nPos;
480 ++nPos;
481 }
482 return GRFILTER_FORMAT_NOTFOUND;
483 }
484
GetExportFormatName(sal_uInt16 nFormat)485 OUString FilterConfigCache::GetExportFormatName( sal_uInt16 nFormat )
486 {
487 if( nFormat < aExport.size() )
488 return aExport[ nFormat ].sUIName;
489 return OUString();
490 }
491
GetExportFormatMediaType(sal_uInt16 nFormat)492 OUString FilterConfigCache::GetExportFormatMediaType( sal_uInt16 nFormat )
493 {
494 if( nFormat < aExport.size() )
495 return aExport[ nFormat ].sMediaType;
496 return OUString();
497 }
498
GetExportFormatShortName(sal_uInt16 nFormat)499 OUString FilterConfigCache::GetExportFormatShortName( sal_uInt16 nFormat )
500 {
501 if( nFormat < aExport.size() )
502 return aExport[ nFormat ].GetShortName();
503 return OUString();
504 }
505
GetExportFormatExtension(sal_uInt16 nFormat,sal_Int32 nEntry)506 OUString FilterConfigCache::GetExportFormatExtension( sal_uInt16 nFormat, sal_Int32 nEntry )
507 {
508 if ( (nFormat < aExport.size()) && (size_t(nEntry) < aExport[ nFormat ].lExtensionList.size()) )
509 return aExport[ nFormat ].lExtensionList[ nEntry ];
510 return OUString();
511 }
512
GetExportInternalFilterName(sal_uInt16 nFormat)513 OUString FilterConfigCache::GetExportInternalFilterName( sal_uInt16 nFormat )
514 {
515 if( nFormat < aExport.size() )
516 return aExport[ nFormat ].sInternalFilterName;
517 return OUString();
518 }
519
GetExportWildcard(sal_uInt16 nFormat,sal_Int32 nEntry)520 OUString FilterConfigCache::GetExportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry )
521 {
522 OUString aWildcard( GetExportFormatExtension( nFormat, nEntry ) );
523 if ( !aWildcard.isEmpty() )
524 aWildcard = aWildcard.replaceAt( 0, 0, "*." );
525 return aWildcard;
526 }
527
IsExportInternalFilter(sal_uInt16 nFormat)528 bool FilterConfigCache::IsExportInternalFilter( sal_uInt16 nFormat )
529 {
530 return (nFormat < aExport.size()) && aExport[ nFormat ].bIsInternalFilter;
531 }
532
IsExportPixelFormat(sal_uInt16 nFormat)533 bool FilterConfigCache::IsExportPixelFormat( sal_uInt16 nFormat )
534 {
535 return (nFormat < aExport.size()) && aExport[ nFormat ].bIsPixelFormat;
536 }
537
538 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
539