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