Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <com/sun/star/beans/PropertyValue.hpp>
21 : #include <com/sun/star/configuration/theDefaultProvider.hpp>
22 : #include <com/sun/star/container/XContainerQuery.hpp>
23 : #include <com/sun/star/document/XTypeDetection.hpp>
24 :
25 : #include <osl/diagnose.h>
26 :
27 : #include <comphelper/fileformat.h>
28 : #include <comphelper/mimeconfighelper.hxx>
29 : #include <comphelper/processfactory.hxx>
30 : #include <comphelper/classids.hxx>
31 : #include <comphelper/sequenceashashmap.hxx>
32 : #include <comphelper/documentconstants.hxx>
33 :
34 :
35 : using namespace ::com::sun::star;
36 : using namespace comphelper;
37 :
38 :
39 990 : MimeConfigurationHelper::MimeConfigurationHelper( const uno::Reference< uno::XComponentContext >& rxContext )
40 990 : : m_xContext( rxContext )
41 : {
42 990 : if ( !m_xContext.is() )
43 0 : throw uno::RuntimeException();
44 990 : }
45 :
46 :
47 1014 : OUString MimeConfigurationHelper::GetStringClassIDRepresentation( const uno::Sequence< sal_Int8 >& aClassID )
48 : {
49 1014 : OUString aResult;
50 :
51 1014 : if ( aClassID.getLength() == 16 )
52 : {
53 17238 : for ( sal_Int32 nInd = 0; nInd < aClassID.getLength(); nInd++ )
54 : {
55 16224 : if ( nInd == 4 || nInd == 6 || nInd == 8 || nInd == 10 )
56 4056 : aResult += "-";
57 :
58 16224 : sal_Int32 nDigit1 = (sal_Int32)( (sal_uInt8)aClassID[nInd] / 16 );
59 16224 : sal_Int32 nDigit2 = (sal_uInt8)aClassID[nInd] % 16;
60 16224 : aResult += OUString::number( nDigit1, 16 );
61 16224 : aResult += OUString::number( nDigit2, 16 );
62 : }
63 : }
64 :
65 1014 : return aResult;
66 : }
67 :
68 :
69 2496 : sal_uInt8 GetDigit_Impl( sal_Char aChar )
70 : {
71 2496 : if ( aChar >= '0' && aChar <= '9' )
72 1704 : return aChar - '0';
73 792 : else if ( aChar >= 'a' && aChar <= 'f' )
74 98 : return aChar - 'a' + 10;
75 694 : else if ( aChar >= 'A' && aChar <= 'F' )
76 694 : return aChar - 'A' + 10;
77 : else
78 0 : return 16;
79 : }
80 :
81 :
82 132 : uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassIDRepresentation( const OUString& aClassID )
83 : {
84 132 : sal_Int32 nLength = aClassID.getLength();
85 132 : if ( nLength == 36 )
86 : {
87 78 : OString aCharClassID = OUStringToOString( aClassID, RTL_TEXTENCODING_ASCII_US );
88 78 : const sal_Char* pString = aCharClassID.getStr();
89 78 : if ( pString )
90 : {
91 78 : uno::Sequence< sal_Int8 > aResult( 16 );
92 :
93 78 : sal_Int32 nStrPointer = 0;
94 78 : sal_Int32 nSeqInd = 0;
95 1404 : while( nSeqInd < 16 && nStrPointer + 1 < nLength )
96 : {
97 1248 : sal_uInt8 nDigit1 = GetDigit_Impl( pString[nStrPointer++] );
98 1248 : sal_uInt8 nDigit2 = GetDigit_Impl( pString[nStrPointer++] );
99 :
100 1248 : if ( nDigit1 > 15 || nDigit2 > 15 )
101 : break;
102 :
103 1248 : aResult[nSeqInd++] = (sal_Int8)( nDigit1 * 16 + nDigit2 );
104 :
105 1248 : if ( nStrPointer < nLength && pString[nStrPointer] == '-' )
106 312 : nStrPointer++;
107 : }
108 :
109 78 : if ( nSeqInd == 16 && nStrPointer == nLength )
110 78 : return aResult;
111 0 : }
112 : }
113 :
114 54 : return uno::Sequence< sal_Int8 >();
115 : }
116 :
117 :
118 117 : uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetConfigurationByPath( const OUString& aPath )
119 : {
120 117 : osl::MutexGuard aGuard( m_aMutex );
121 :
122 117 : uno::Reference< container::XNameAccess > xConfig;
123 :
124 : try
125 : {
126 117 : if ( !m_xConfigProvider.is() )
127 63 : m_xConfigProvider = configuration::theDefaultProvider::get( m_xContext );
128 :
129 117 : uno::Sequence< uno::Any > aArgs( 1 );
130 234 : beans::PropertyValue aPathProp;
131 117 : aPathProp.Name = "nodepath";
132 117 : aPathProp.Value <<= aPath;
133 117 : aArgs[0] <<= aPathProp;
134 :
135 234 : xConfig = uno::Reference< container::XNameAccess >(
136 117 : m_xConfigProvider->createInstanceWithArguments(
137 : OUString( "com.sun.star.configuration.ConfigurationAccess" ),
138 117 : aArgs ),
139 234 : uno::UNO_QUERY );
140 : }
141 0 : catch( uno::Exception& )
142 : {}
143 :
144 117 : return xConfig;
145 : }
146 :
147 :
148 1139 : uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetObjConfiguration()
149 : {
150 1139 : osl::MutexGuard aGuard( m_aMutex );
151 :
152 1139 : if ( !m_xObjectConfig.is() )
153 126 : m_xObjectConfig = GetConfigurationByPath(
154 63 : OUString( "/org.openoffice.Office.Embedding/Objects" ) );
155 :
156 1139 : return m_xObjectConfig;
157 : }
158 :
159 :
160 3727 : uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetVerbsConfiguration()
161 : {
162 3727 : osl::MutexGuard aGuard( m_aMutex );
163 :
164 3727 : if ( !m_xVerbsConfig.is() )
165 62 : m_xVerbsConfig = GetConfigurationByPath(
166 31 : OUString( "/org.openoffice.Office.Embedding/Verbs" ));
167 :
168 3727 : return m_xVerbsConfig;
169 : }
170 :
171 :
172 108 : uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetMediaTypeConfiguration()
173 : {
174 108 : osl::MutexGuard aGuard( m_aMutex );
175 :
176 108 : if ( !m_xMediaTypeConfig.is() )
177 46 : m_xMediaTypeConfig = GetConfigurationByPath(
178 23 : OUString( "/org.openoffice.Office.Embedding/MimeTypeClassIDRelations" ));
179 :
180 108 : return m_xMediaTypeConfig;
181 : }
182 :
183 :
184 1049 : uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetFilterFactory()
185 : {
186 1049 : osl::MutexGuard aGuard( m_aMutex );
187 :
188 1049 : if ( !m_xFilterFactory.is() )
189 : m_xFilterFactory.set(
190 1898 : m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", m_xContext),
191 949 : uno::UNO_QUERY );
192 :
193 1049 : return m_xFilterFactory;
194 : }
195 :
196 :
197 125 : OUString MimeConfigurationHelper::GetDocServiceNameFromFilter( const OUString& aFilterName )
198 : {
199 125 : OUString aDocServiceName;
200 :
201 : try
202 : {
203 : uno::Reference< container::XNameAccess > xFilterFactory(
204 : GetFilterFactory(),
205 125 : uno::UNO_SET_THROW );
206 :
207 250 : uno::Any aFilterAnyData = xFilterFactory->getByName( aFilterName );
208 250 : uno::Sequence< beans::PropertyValue > aFilterData;
209 125 : if ( aFilterAnyData >>= aFilterData )
210 : {
211 1750 : for ( sal_Int32 nInd = 0; nInd < aFilterData.getLength(); nInd++ )
212 1625 : if ( aFilterData[nInd].Name == "DocumentService" )
213 125 : aFilterData[nInd].Value >>= aDocServiceName;
214 125 : }
215 : }
216 0 : catch( uno::Exception& )
217 : {}
218 :
219 125 : return aDocServiceName;
220 : }
221 :
222 :
223 108 : OUString MimeConfigurationHelper::GetDocServiceNameFromMediaType( const OUString& aMediaType )
224 : {
225 : uno::Reference< container::XContainerQuery > xTypeCFG(
226 216 : m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_xContext),
227 108 : uno::UNO_QUERY );
228 :
229 108 : if ( xTypeCFG.is() )
230 : {
231 : try
232 : {
233 : // make query for all types matching the properties
234 108 : uno::Sequence < beans::NamedValue > aSeq( 1 );
235 108 : aSeq[0].Name = "MediaType";
236 108 : aSeq[0].Value <<= aMediaType;
237 :
238 108 : uno::Reference < container::XEnumeration > xEnum = xTypeCFG->createSubSetEnumerationByProperties( aSeq );
239 216 : while ( xEnum->hasMoreElements() )
240 : {
241 108 : uno::Sequence< beans::PropertyValue > aType;
242 108 : if ( xEnum->nextElement() >>= aType )
243 : {
244 648 : for ( sal_Int32 nInd = 0; nInd < aType.getLength(); nInd++ )
245 : {
246 648 : OUString aFilterName;
247 1296 : if ( aType[nInd].Name == "PreferredFilter"
248 648 : && ( aType[nInd].Value >>= aFilterName ) && !aFilterName.isEmpty() )
249 : {
250 108 : OUString aDocumentName = GetDocServiceNameFromFilter( aFilterName );
251 108 : if ( !aDocumentName.isEmpty() )
252 108 : return aDocumentName;
253 : }
254 540 : }
255 : }
256 0 : }
257 : }
258 0 : catch( uno::Exception& )
259 : {}
260 : }
261 :
262 0 : return OUString();
263 : }
264 :
265 :
266 3727 : bool MimeConfigurationHelper::GetVerbByShortcut( const OUString& aVerbShortcut,
267 : embed::VerbDescriptor& aDescriptor )
268 : {
269 3727 : bool bResult = false;
270 :
271 3727 : uno::Reference< container::XNameAccess > xVerbsConfig = GetVerbsConfiguration();
272 7454 : uno::Reference< container::XNameAccess > xVerbsProps;
273 : try
274 : {
275 3727 : if ( xVerbsConfig.is() && ( xVerbsConfig->getByName( aVerbShortcut ) >>= xVerbsProps ) && xVerbsProps.is() )
276 : {
277 3727 : embed::VerbDescriptor aTempDescr;
278 14908 : if ( ( xVerbsProps->getByName("VerbID") >>= aTempDescr.VerbID )
279 7454 : && ( xVerbsProps->getByName("VerbUIName") >>= aTempDescr.VerbName )
280 7454 : && ( xVerbsProps->getByName("VerbFlags") >>= aTempDescr.VerbFlags )
281 18635 : && ( xVerbsProps->getByName("VerbAttributes") >>= aTempDescr.VerbAttributes ) )
282 : {
283 3727 : aDescriptor = aTempDescr;
284 3727 : bResult = true;
285 3727 : }
286 : }
287 : }
288 0 : catch( uno::Exception& )
289 : {
290 : }
291 :
292 7454 : return bResult;
293 : }
294 :
295 :
296 571 : uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjPropsFromConfigEntry(
297 : const uno::Sequence< sal_Int8 >& aClassID,
298 : const uno::Reference< container::XNameAccess >& xObjectProps )
299 : {
300 571 : uno::Sequence< beans::NamedValue > aResult;
301 :
302 571 : if ( aClassID.getLength() == 16 )
303 : {
304 : try
305 : {
306 571 : uno::Sequence< OUString > aObjPropNames = xObjectProps->getElementNames();
307 :
308 571 : aResult.realloc( aObjPropNames.getLength() + 1 );
309 571 : aResult[0].Name = "ClassID";
310 571 : aResult[0].Value <<= aClassID;
311 :
312 3426 : for ( sal_Int32 nInd = 0; nInd < aObjPropNames.getLength(); nInd++ )
313 : {
314 2855 : aResult[nInd + 1].Name = aObjPropNames[nInd];
315 :
316 2855 : if ( aObjPropNames[nInd] == "ObjectVerbs" )
317 : {
318 571 : uno::Sequence< OUString > aVerbShortcuts;
319 571 : if ( xObjectProps->getByName( aObjPropNames[nInd] ) >>= aVerbShortcuts )
320 : {
321 571 : uno::Sequence< embed::VerbDescriptor > aVerbDescriptors( aVerbShortcuts.getLength() );
322 4298 : for ( sal_Int32 nVerbI = 0; nVerbI < aVerbShortcuts.getLength(); nVerbI++ )
323 3727 : if ( !GetVerbByShortcut( aVerbShortcuts[nVerbI], aVerbDescriptors[nVerbI] ) )
324 0 : throw uno::RuntimeException();
325 :
326 571 : aResult[nInd+1].Value <<= aVerbDescriptors;
327 : }
328 : else
329 0 : throw uno::RuntimeException();
330 : }
331 : else
332 2284 : aResult[nInd+1].Value = xObjectProps->getByName( aObjPropNames[nInd] );
333 571 : }
334 : }
335 0 : catch( uno::Exception& )
336 : {
337 0 : aResult.realloc( 0 );
338 : }
339 : }
340 :
341 571 : return aResult;
342 : }
343 :
344 :
345 108 : OUString MimeConfigurationHelper::GetExplicitlyRegisteredObjClassID( const OUString& aMediaType )
346 : {
347 108 : OUString aStringClassID;
348 :
349 216 : uno::Reference< container::XNameAccess > xMediaTypeConfig = GetMediaTypeConfiguration();
350 : try
351 : {
352 108 : if ( xMediaTypeConfig.is() )
353 108 : xMediaTypeConfig->getByName( aMediaType ) >>= aStringClassID;
354 : }
355 108 : catch( uno::Exception& )
356 : {
357 : }
358 :
359 216 : return aStringClassID;
360 :
361 : }
362 :
363 :
364 54 : uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByStringClassID(
365 : const OUString& aStringClassID )
366 : {
367 54 : uno::Sequence< beans::NamedValue > aObjProps;
368 :
369 108 : uno::Sequence< sal_Int8 > aClassID = GetSequenceClassIDRepresentation( aStringClassID );
370 54 : if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) )
371 : {
372 0 : aObjProps.realloc(2);
373 0 : aObjProps[0].Name = "ObjectFactory";
374 0 : aObjProps[0].Value <<= OUString( "com.sun.star.embed.OOoSpecialEmbeddedObjectFactory" );
375 0 : aObjProps[1].Name = "ClassID";
376 0 : aObjProps[1].Value <<= aClassID;
377 0 : return aObjProps;
378 : }
379 :
380 54 : if ( aClassID.getLength() == 16 )
381 : {
382 0 : uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
383 0 : uno::Reference< container::XNameAccess > xObjectProps;
384 : try
385 : {
386 : // TODO/LATER: allow to provide ClassID string in any format, only digits are counted
387 0 : if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() )
388 0 : aObjProps = GetObjPropsFromConfigEntry( aClassID, xObjectProps );
389 : }
390 0 : catch( uno::Exception& )
391 : {
392 0 : }
393 : }
394 :
395 54 : return aObjProps;
396 : }
397 :
398 :
399 507 : uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByClassID(
400 : const uno::Sequence< sal_Int8 >& aClassID )
401 : {
402 507 : uno::Sequence< beans::NamedValue > aObjProps;
403 507 : if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) )
404 : {
405 7 : aObjProps.realloc(2);
406 7 : aObjProps[0].Name = "ObjectFactory";
407 7 : aObjProps[0].Value <<= OUString( "com.sun.star.embed.OOoSpecialEmbeddedObjectFactory" );
408 7 : aObjProps[1].Name = "ClassID";
409 7 : aObjProps[1].Value <<= aClassID;
410 : }
411 :
412 1014 : OUString aStringClassID = GetStringClassIDRepresentation( aClassID );
413 507 : if ( !aStringClassID.isEmpty() )
414 : {
415 507 : uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
416 1014 : uno::Reference< container::XNameAccess > xObjectProps;
417 : try
418 : {
419 514 : if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() )
420 500 : aObjProps = GetObjPropsFromConfigEntry( aClassID, xObjectProps );
421 : }
422 7 : catch( uno::Exception& )
423 : {
424 507 : }
425 : }
426 :
427 1014 : return aObjProps;
428 : }
429 :
430 :
431 54 : uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByMediaType( const OUString& aMediaType )
432 : {
433 : uno::Sequence< beans::NamedValue > aObject =
434 54 : GetObjectPropsByStringClassID( GetExplicitlyRegisteredObjClassID( aMediaType ) );
435 54 : if ( aObject.getLength() )
436 0 : return aObject;
437 :
438 108 : OUString aDocumentName = GetDocServiceNameFromMediaType( aMediaType );
439 54 : if ( !aDocumentName.isEmpty() )
440 54 : return GetObjectPropsByDocumentName( aDocumentName );
441 :
442 54 : return uno::Sequence< beans::NamedValue >();
443 : }
444 :
445 :
446 17 : uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByFilter( const OUString& aFilterName )
447 : {
448 17 : OUString aDocumentName = GetDocServiceNameFromFilter( aFilterName );
449 17 : if ( !aDocumentName.isEmpty() )
450 17 : return GetObjectPropsByDocumentName( aDocumentName );
451 :
452 0 : return uno::Sequence< beans::NamedValue >();
453 : }
454 :
455 :
456 71 : uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByDocumentName( const OUString& aDocName )
457 : {
458 71 : if ( !aDocName.isEmpty() )
459 : {
460 71 : uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
461 71 : if ( xObjConfig.is() )
462 : {
463 : try
464 : {
465 71 : uno::Sequence< OUString > aClassIDs = xObjConfig->getElementNames();
466 160 : for ( sal_Int32 nInd = 0; nInd < aClassIDs.getLength(); nInd++ )
467 : {
468 160 : uno::Reference< container::XNameAccess > xObjectProps;
469 249 : OUString aEntryDocName;
470 :
471 800 : if ( ( xObjConfig->getByName( aClassIDs[nInd] ) >>= xObjectProps ) && xObjectProps.is()
472 320 : && ( xObjectProps->getByName("ObjectDocumentServiceName") >>= aEntryDocName )
473 640 : && aEntryDocName == aDocName )
474 : {
475 71 : return GetObjPropsFromConfigEntry( GetSequenceClassIDRepresentation( aClassIDs[nInd] ),
476 71 : xObjectProps );
477 : }
478 89 : }
479 : }
480 0 : catch( uno::Exception& )
481 : {}
482 0 : }
483 : }
484 :
485 0 : return uno::Sequence< beans::NamedValue >();
486 : }
487 :
488 :
489 507 : OUString MimeConfigurationHelper::GetFactoryNameByClassID( const uno::Sequence< sal_Int8 >& aClassID )
490 : {
491 507 : return GetFactoryNameByStringClassID( GetStringClassIDRepresentation( aClassID ) );
492 : }
493 :
494 :
495 561 : OUString MimeConfigurationHelper::GetFactoryNameByStringClassID( const OUString& aStringClassID )
496 : {
497 561 : OUString aResult;
498 :
499 561 : if ( !aStringClassID.isEmpty() )
500 : {
501 507 : uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
502 1007 : uno::Reference< container::XNameAccess > xObjectProps;
503 : try
504 : {
505 514 : if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() )
506 500 : xObjectProps->getByName("ObjectFactory") >>= aResult;
507 : }
508 7 : catch( uno::Exception& )
509 : {
510 7 : uno::Sequence< sal_Int8 > aClassID = GetSequenceClassIDRepresentation( aStringClassID );
511 7 : if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) )
512 7 : return OUString( "com.sun.star.embed.OOoSpecialEmbeddedObjectFactory" );
513 500 : }
514 : }
515 :
516 554 : return aResult;
517 : }
518 :
519 :
520 54 : OUString MimeConfigurationHelper::GetFactoryNameByDocumentName( const OUString& aDocName )
521 : {
522 54 : OUString aResult;
523 :
524 54 : if ( !aDocName.isEmpty() )
525 : {
526 54 : uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
527 54 : if ( xObjConfig.is() )
528 : {
529 : try
530 : {
531 54 : uno::Sequence< OUString > aClassIDs = xObjConfig->getElementNames();
532 127 : for ( sal_Int32 nInd = 0; nInd < aClassIDs.getLength(); nInd++ )
533 : {
534 127 : uno::Reference< container::XNameAccess > xObjectProps;
535 200 : OUString aEntryDocName;
536 :
537 635 : if ( ( xObjConfig->getByName( aClassIDs[nInd] ) >>= xObjectProps ) && xObjectProps.is()
538 381 : && ( xObjectProps->getByName(
539 381 : OUString( "ObjectDocumentServiceName" ) ) >>= aEntryDocName )
540 508 : && aEntryDocName == aDocName )
541 : {
542 54 : xObjectProps->getByName("ObjectFactory") >>= aResult;
543 54 : break;
544 : }
545 127 : }
546 : }
547 0 : catch( uno::Exception& )
548 : {}
549 54 : }
550 : }
551 :
552 54 : return aResult;
553 : }
554 :
555 :
556 :
557 54 : OUString MimeConfigurationHelper::GetFactoryNameByMediaType( const OUString& aMediaType )
558 : {
559 54 : OUString aResult = GetFactoryNameByStringClassID( GetExplicitlyRegisteredObjClassID( aMediaType ) );
560 :
561 54 : if ( aResult.isEmpty() )
562 : {
563 54 : OUString aDocumentName = GetDocServiceNameFromMediaType( aMediaType );
564 54 : if ( !aDocumentName.isEmpty() )
565 54 : aResult = GetFactoryNameByDocumentName( aDocumentName );
566 : }
567 :
568 54 : return aResult;
569 : }
570 :
571 :
572 38 : OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName(
573 : uno::Sequence< beans::PropertyValue >& aMediaDescr,
574 : bool bIgnoreType )
575 : {
576 38 : OUString aFilterName;
577 :
578 148 : for ( sal_Int32 nInd = 0; nInd < aMediaDescr.getLength(); nInd++ )
579 110 : if ( aMediaDescr[nInd].Name == "FilterName" )
580 34 : aMediaDescr[nInd].Value >>= aFilterName;
581 :
582 38 : if ( aFilterName.isEmpty() )
583 : {
584 : // filter name is not specified, so type detection should be done
585 :
586 : uno::Reference< document::XTypeDetection > xTypeDetection(
587 8 : m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_xContext),
588 4 : uno::UNO_QUERY );
589 :
590 4 : if ( !xTypeDetection.is() )
591 0 : throw uno::RuntimeException(); // TODO
592 :
593 : // typedetection can change the mode, add a stream and so on, thus a copy should be used
594 8 : uno::Sequence< beans::PropertyValue > aTempMD( aMediaDescr );
595 :
596 : // get TypeName
597 8 : OUString aTypeName = xTypeDetection->queryTypeByDescriptor( aTempMD, sal_True );
598 :
599 : // get FilterName
600 16 : for ( sal_Int32 nInd = 0; nInd < aTempMD.getLength(); nInd++ )
601 12 : if ( aTempMD[nInd].Name == "FilterName" )
602 0 : aTempMD[nInd].Value >>= aFilterName;
603 :
604 4 : if ( !aFilterName.isEmpty() )
605 : {
606 0 : sal_Int32 nOldLen = aMediaDescr.getLength();
607 0 : aMediaDescr.realloc( nOldLen + 1 );
608 0 : aMediaDescr[nOldLen].Name = "FilterName";
609 0 : aMediaDescr[ nOldLen ].Value <<= aFilterName;
610 :
611 : }
612 4 : else if ( !aTypeName.isEmpty() && !bIgnoreType )
613 : {
614 4 : uno::Reference< container::XNameAccess > xNameAccess( xTypeDetection, uno::UNO_QUERY );
615 8 : uno::Sequence< beans::PropertyValue > aTypes;
616 :
617 4 : if ( xNameAccess.is() && ( xNameAccess->getByName( aTypeName ) >>= aTypes ) )
618 : {
619 24 : for ( sal_Int32 nInd = 0; nInd < aTypes.getLength(); nInd++ )
620 : {
621 24 : if ( aTypes[nInd].Name == "PreferredFilter" && ( aTypes[nInd].Value >>= aFilterName ) )
622 : {
623 4 : sal_Int32 nOldLen = aMediaDescr.getLength();
624 4 : aMediaDescr.realloc( nOldLen + 1 );
625 4 : aMediaDescr[nOldLen].Name = "FilterName";
626 4 : aMediaDescr[ nOldLen ].Value = aTypes[nInd].Value;
627 4 : break;
628 : }
629 : }
630 4 : }
631 4 : }
632 : }
633 :
634 38 : return aFilterName;
635 : }
636 :
637 0 : OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName(
638 : uno::Sequence< beans::PropertyValue >& aMediaDescr,
639 : uno::Sequence< beans::NamedValue >& aObject )
640 : {
641 0 : OUString aDocName;
642 0 : for ( sal_Int32 nInd = 0; nInd < aObject.getLength(); nInd++ )
643 0 : if ( aObject[nInd].Name == "ObjectDocumentServiceName" )
644 : {
645 0 : aObject[nInd].Value >>= aDocName;
646 0 : break;
647 : }
648 :
649 : OSL_ENSURE( !aDocName.isEmpty(), "The name must exist at this point!\n" );
650 :
651 :
652 0 : bool bNeedsAddition = true;
653 0 : for ( sal_Int32 nMedInd = 0; nMedInd < aMediaDescr.getLength(); nMedInd++ )
654 0 : if ( aMediaDescr[nMedInd].Name == "DocumentService" )
655 : {
656 0 : aMediaDescr[nMedInd].Value <<= aDocName;
657 0 : bNeedsAddition = false;
658 0 : break;
659 : }
660 :
661 0 : if ( bNeedsAddition )
662 : {
663 0 : sal_Int32 nOldLen = aMediaDescr.getLength();
664 0 : aMediaDescr.realloc( nOldLen + 1 );
665 0 : aMediaDescr[nOldLen].Name = "DocumentService";
666 0 : aMediaDescr[nOldLen].Value <<= aDocName;
667 : }
668 :
669 0 : return UpdateMediaDescriptorWithFilterName( aMediaDescr, true );
670 : }
671 :
672 : #ifdef WNT
673 :
674 : SfxFilterFlags MimeConfigurationHelper::GetFilterFlags( const OUString& aFilterName )
675 : {
676 : SfxFilterFlags nFlags = SfxFilterFlags::NONE;
677 : try
678 : {
679 : if ( !aFilterName.isEmpty() )
680 : {
681 : uno::Reference< container::XNameAccess > xFilterFactory(
682 : GetFilterFactory(),
683 : uno::UNO_SET_THROW );
684 :
685 : uno::Any aFilterAny = xFilterFactory->getByName( aFilterName );
686 : uno::Sequence< beans::PropertyValue > aData;
687 : if ( aFilterAny >>= aData )
688 : {
689 : SequenceAsHashMap aFilterHM( aData );
690 : nFlags = static_cast<SfxFilterFlags>(aFilterHM.getUnpackedValueOrDefault( "Flags", (sal_Int32)0 ));
691 : }
692 : }
693 : } catch( uno::Exception& )
694 : {}
695 :
696 : return nFlags;
697 : }
698 :
699 : bool MimeConfigurationHelper::AddFilterNameCheckOwnFile(
700 : uno::Sequence< beans::PropertyValue >& aMediaDescr )
701 : {
702 : OUString aFilterName = UpdateMediaDescriptorWithFilterName( aMediaDescr, sal_False );
703 : if ( !aFilterName.isEmpty() )
704 : {
705 : SfxFilterFlags nFlags = GetFilterFlags( aFilterName );
706 : // check the OWN flag
707 : return bool(nFlags & SfxFilterFlags::OWN);
708 : }
709 :
710 : return false;
711 : }
712 :
713 : #endif
714 :
715 924 : OUString MimeConfigurationHelper::GetDefaultFilterFromServiceName( const OUString& aServiceName, sal_Int32 nVersion )
716 : {
717 924 : OUString aResult;
718 :
719 924 : if ( !aServiceName.isEmpty() && nVersion )
720 : try
721 : {
722 : uno::Reference< container::XContainerQuery > xFilterQuery(
723 : GetFilterFactory(),
724 924 : uno::UNO_QUERY_THROW );
725 :
726 1848 : uno::Sequence< beans::NamedValue > aSearchRequest( 2 );
727 924 : aSearchRequest[0].Name = "DocumentService";
728 924 : aSearchRequest[0].Value <<= aServiceName;
729 924 : aSearchRequest[1].Name = "FileFormatVersion";
730 924 : aSearchRequest[1].Value <<= nVersion;
731 :
732 : uno::Reference< container::XEnumeration > xFilterEnum =
733 1848 : xFilterQuery->createSubSetEnumerationByProperties( aSearchRequest );
734 :
735 : // use the first filter that is found
736 924 : if ( xFilterEnum.is() )
737 2420 : while ( xFilterEnum->hasMoreElements() )
738 : {
739 931 : uno::Sequence< beans::PropertyValue > aProps;
740 931 : if ( xFilterEnum->nextElement() >>= aProps )
741 : {
742 931 : SequenceAsHashMap aPropsHM( aProps );
743 931 : SfxFilterFlags nFlags = static_cast<SfxFilterFlags>(aPropsHM.getUnpackedValueOrDefault( "Flags", (sal_Int32)0 ));
744 :
745 : // that should be import, export, own filter and not a template filter ( TemplatePath flag )
746 : SfxFilterFlags const nRequired = (SfxFilterFlags::OWN
747 : // fdo#78159 for OOoXML, there is code to convert
748 : // to ODF in OCommonEmbeddedObject::store*
749 : // so accept it even though there's no export
750 931 : | (SOFFICE_FILEFORMAT_60 == nVersion ? SfxFilterFlags::NONE : SfxFilterFlags::EXPORT)
751 931 : | SfxFilterFlags::IMPORT );
752 931 : if ( ( ( nFlags & nRequired ) == nRequired ) && !( nFlags & SfxFilterFlags::TEMPLATEPATH ) )
753 : {
754 : // if there are more than one filter the preffered one should be used
755 : // if there is no preffered filter the first one will be used
756 924 : if ( aResult.isEmpty() || ( nFlags & SfxFilterFlags::PREFERED ) )
757 924 : aResult = aPropsHM.getUnpackedValueOrDefault( "Name", OUString() );
758 924 : if ( nFlags & SfxFilterFlags::PREFERED )
759 359 : break; // the preferred filter was found
760 572 : }
761 : }
762 1496 : }
763 : }
764 0 : catch( uno::Exception& )
765 : {}
766 :
767 924 : return aResult;
768 : }
769 :
770 :
771 0 : OUString MimeConfigurationHelper::GetExportFilterFromImportFilter( const OUString& aImportFilterName )
772 : {
773 0 : OUString aExportFilterName;
774 :
775 : try
776 : {
777 0 : if ( !aImportFilterName.isEmpty() )
778 : {
779 : uno::Reference< container::XNameAccess > xFilterFactory(
780 : GetFilterFactory(),
781 0 : uno::UNO_SET_THROW );
782 :
783 0 : uno::Any aImpFilterAny = xFilterFactory->getByName( aImportFilterName );
784 0 : uno::Sequence< beans::PropertyValue > aImpData;
785 0 : if ( aImpFilterAny >>= aImpData )
786 : {
787 0 : SequenceAsHashMap aImpFilterHM( aImpData );
788 0 : SfxFilterFlags nFlags = static_cast<SfxFilterFlags>(aImpFilterHM.getUnpackedValueOrDefault( "Flags", (sal_Int32)0 ));
789 :
790 0 : if ( !( nFlags & SfxFilterFlags::IMPORT ) )
791 : {
792 : OSL_FAIL( "This is no import filter!" );
793 0 : throw uno::Exception();
794 : }
795 :
796 0 : if ( nFlags & SfxFilterFlags::EXPORT )
797 : {
798 0 : aExportFilterName = aImportFilterName;
799 : }
800 : else
801 : {
802 0 : OUString aDocumentServiceName = aImpFilterHM.getUnpackedValueOrDefault( "DocumentService", OUString() );
803 0 : OUString aTypeName = aImpFilterHM.getUnpackedValueOrDefault( "Type", OUString() );
804 :
805 : OSL_ENSURE( !aDocumentServiceName.isEmpty() && !aTypeName.isEmpty(), "Incomplete filter data!" );
806 0 : if ( !(aDocumentServiceName.isEmpty() || aTypeName.isEmpty()) )
807 : {
808 0 : uno::Sequence< beans::NamedValue > aSearchRequest( 2 );
809 0 : aSearchRequest[0].Name = "Type";
810 0 : aSearchRequest[0].Value <<= aTypeName;
811 0 : aSearchRequest[1].Name = "DocumentService";
812 0 : aSearchRequest[1].Value <<= aDocumentServiceName;
813 :
814 : uno::Sequence< beans::PropertyValue > aExportFilterProps = SearchForFilter(
815 : uno::Reference< container::XContainerQuery >( xFilterFactory, uno::UNO_QUERY_THROW ),
816 : aSearchRequest,
817 : SfxFilterFlags::EXPORT,
818 0 : SfxFilterFlags::INTERNAL );
819 :
820 0 : if ( aExportFilterProps.getLength() )
821 : {
822 0 : SequenceAsHashMap aExpPropsHM( aExportFilterProps );
823 0 : aExportFilterName = aExpPropsHM.getUnpackedValueOrDefault( "Name", OUString() );
824 0 : }
825 0 : }
826 0 : }
827 0 : }
828 : }
829 : }
830 0 : catch( uno::Exception& )
831 : {}
832 :
833 0 : return aExportFilterName;
834 : }
835 :
836 :
837 : // static
838 0 : uno::Sequence< beans::PropertyValue > MimeConfigurationHelper::SearchForFilter(
839 : const uno::Reference< container::XContainerQuery >& xFilterQuery,
840 : const uno::Sequence< beans::NamedValue >& aSearchRequest,
841 : SfxFilterFlags nMustFlags,
842 : SfxFilterFlags nDontFlags )
843 : {
844 0 : uno::Sequence< beans::PropertyValue > aFilterProps;
845 : uno::Reference< container::XEnumeration > xFilterEnum =
846 0 : xFilterQuery->createSubSetEnumerationByProperties( aSearchRequest );
847 :
848 : // the first default filter will be taken,
849 : // if there is no filter with flag default the first acceptable filter will be taken
850 0 : if ( xFilterEnum.is() )
851 : {
852 0 : while ( xFilterEnum->hasMoreElements() )
853 : {
854 0 : uno::Sequence< beans::PropertyValue > aProps;
855 0 : if ( xFilterEnum->nextElement() >>= aProps )
856 : {
857 0 : SequenceAsHashMap aPropsHM( aProps );
858 : SfxFilterFlags nFlags = static_cast<SfxFilterFlags>(aPropsHM.getUnpackedValueOrDefault("Flags",
859 0 : (sal_Int32)0 ));
860 0 : if ( ( ( nFlags & nMustFlags ) == nMustFlags ) && !( nFlags & nDontFlags ) )
861 : {
862 0 : if ( ( nFlags & SfxFilterFlags::DEFAULT ) == SfxFilterFlags::DEFAULT )
863 : {
864 0 : aFilterProps = aProps;
865 0 : break;
866 : }
867 0 : else if ( !aFilterProps.getLength() )
868 0 : aFilterProps = aProps;
869 0 : }
870 : }
871 0 : }
872 : }
873 :
874 0 : return aFilterProps;
875 : }
876 :
877 :
878 :
879 568 : bool MimeConfigurationHelper::ClassIDsEqual( const uno::Sequence< sal_Int8 >& aClassID1, const uno::Sequence< sal_Int8 >& aClassID2 )
880 : {
881 568 : if ( aClassID1.getLength() != aClassID2.getLength() )
882 54 : return false;
883 :
884 738 : for ( sal_Int32 nInd = 0; nInd < aClassID1.getLength(); nInd++ )
885 724 : if ( aClassID1[nInd] != aClassID2[nInd] )
886 500 : return false;
887 :
888 14 : return true;
889 : }
890 :
891 :
892 568 : uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassID( sal_uInt32 n1, sal_uInt16 n2, sal_uInt16 n3,
893 : sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11,
894 : sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15 )
895 : {
896 568 : uno::Sequence< sal_Int8 > aResult( 16 );
897 568 : aResult[0] = (sal_Int8)( n1 >> 24 );
898 568 : aResult[1] = (sal_Int8)( ( n1 << 8 ) >> 24 );
899 568 : aResult[2] = (sal_Int8)( ( n1 << 16 ) >> 24 );
900 568 : aResult[3] = (sal_Int8)( ( n1 << 24 ) >> 24 );
901 568 : aResult[4] = (sal_Int8)( n2 >> 8 );
902 568 : aResult[5] = (sal_Int8)( ( n2 << 8 ) >> 8 );
903 568 : aResult[6] = (sal_Int8)( n3 >> 8 );
904 568 : aResult[7] = (sal_Int8)( ( n3 << 8 ) >> 8 );
905 568 : aResult[8] = b8;
906 568 : aResult[9] = b9;
907 568 : aResult[10] = b10;
908 568 : aResult[11] = b11;
909 568 : aResult[12] = b12;
910 568 : aResult[13] = b13;
911 568 : aResult[14] = b14;
912 568 : aResult[15] = b15;
913 :
914 568 : return aResult;
915 : }
916 :
917 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|