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