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 2040 : MimeConfigurationHelper::MimeConfigurationHelper( const uno::Reference< uno::XComponentContext >& rxContext )
38 2040 : : m_xContext( rxContext )
39 : {
40 2040 : if ( !m_xContext.is() )
41 0 : throw uno::RuntimeException();
42 2040 : }
43 :
44 :
45 1792 : OUString MimeConfigurationHelper::GetStringClassIDRepresentation( const uno::Sequence< sal_Int8 >& aClassID )
46 : {
47 1792 : OUString aResult;
48 :
49 1792 : if ( aClassID.getLength() == 16 )
50 : {
51 30464 : for ( sal_Int32 nInd = 0; nInd < aClassID.getLength(); nInd++ )
52 : {
53 28672 : if ( nInd == 4 || nInd == 6 || nInd == 8 || nInd == 10 )
54 7168 : aResult += "-";
55 :
56 28672 : sal_Int32 nDigit1 = (sal_Int32)( (sal_uInt8)aClassID[nInd] / 16 );
57 28672 : sal_Int32 nDigit2 = (sal_uInt8)aClassID[nInd] % 16;
58 28672 : aResult += OUString::number( nDigit1, 16 );
59 28672 : aResult += OUString::number( nDigit2, 16 );
60 : }
61 : }
62 :
63 1792 : return aResult;
64 : }
65 :
66 :
67 4480 : sal_uInt8 GetDigit_Impl( sal_Char aChar )
68 : {
69 4480 : if ( aChar >= '0' && aChar <= '9' )
70 3112 : return aChar - '0';
71 1368 : else if ( aChar >= 'a' && aChar <= 'f' )
72 84 : return aChar - 'a' + 10;
73 1284 : else if ( aChar >= 'A' && aChar <= 'F' )
74 1284 : return aChar - 'A' + 10;
75 : else
76 0 : return 16;
77 : }
78 :
79 :
80 240 : uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassIDRepresentation( const OUString& aClassID )
81 : {
82 240 : sal_Int32 nLength = aClassID.getLength();
83 240 : if ( nLength == 36 )
84 : {
85 140 : OString aCharClassID = OUStringToOString( aClassID, RTL_TEXTENCODING_ASCII_US );
86 140 : const sal_Char* pString = aCharClassID.getStr();
87 140 : if ( pString )
88 : {
89 140 : uno::Sequence< sal_Int8 > aResult( 16 );
90 :
91 140 : sal_Int32 nStrPointer = 0;
92 140 : sal_Int32 nSeqInd = 0;
93 2520 : while( nSeqInd < 16 && nStrPointer + 1 < nLength )
94 : {
95 2240 : sal_uInt8 nDigit1 = GetDigit_Impl( pString[nStrPointer++] );
96 2240 : sal_uInt8 nDigit2 = GetDigit_Impl( pString[nStrPointer++] );
97 :
98 2240 : if ( nDigit1 > 15 || nDigit2 > 15 )
99 : break;
100 :
101 2240 : aResult[nSeqInd++] = (sal_Int8)( nDigit1 * 16 + nDigit2 );
102 :
103 2240 : if ( nStrPointer < nLength && pString[nStrPointer] == '-' )
104 560 : nStrPointer++;
105 : }
106 :
107 140 : if ( nSeqInd == 16 && nStrPointer == nLength )
108 140 : return aResult;
109 0 : }
110 : }
111 :
112 100 : return uno::Sequence< sal_Int8 >();
113 : }
114 :
115 :
116 214 : uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetConfigurationByPath( const OUString& aPath )
117 : {
118 214 : osl::MutexGuard aGuard( m_aMutex );
119 :
120 214 : uno::Reference< container::XNameAccess > xConfig;
121 :
122 : try
123 : {
124 214 : if ( !m_xConfigProvider.is() )
125 116 : m_xConfigProvider = configuration::theDefaultProvider::get( m_xContext );
126 :
127 214 : uno::Sequence< uno::Any > aArgs( 1 );
128 428 : beans::PropertyValue aPathProp;
129 214 : aPathProp.Name = "nodepath";
130 214 : aPathProp.Value <<= aPath;
131 214 : aArgs[0] <<= aPathProp;
132 :
133 428 : xConfig = uno::Reference< container::XNameAccess >(
134 214 : m_xConfigProvider->createInstanceWithArguments(
135 : OUString( "com.sun.star.configuration.ConfigurationAccess" ),
136 214 : aArgs ),
137 428 : uno::UNO_QUERY );
138 : }
139 0 : catch( uno::Exception& )
140 : {}
141 :
142 214 : return xConfig;
143 : }
144 :
145 :
146 2026 : uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetObjConfiguration()
147 : {
148 2026 : osl::MutexGuard aGuard( m_aMutex );
149 :
150 2026 : if ( !m_xObjectConfig.is() )
151 232 : m_xObjectConfig = GetConfigurationByPath(
152 116 : OUString( "/org.openoffice.Office.Embedding/Objects" ) );
153 :
154 2026 : return m_xObjectConfig;
155 : }
156 :
157 :
158 6738 : uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetVerbsConfiguration()
159 : {
160 6738 : osl::MutexGuard aGuard( m_aMutex );
161 :
162 6738 : if ( !m_xVerbsConfig.is() )
163 116 : m_xVerbsConfig = GetConfigurationByPath(
164 58 : OUString( "/org.openoffice.Office.Embedding/Verbs" ));
165 :
166 6738 : return m_xVerbsConfig;
167 : }
168 :
169 :
170 200 : uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetMediaTypeConfiguration()
171 : {
172 200 : osl::MutexGuard aGuard( m_aMutex );
173 :
174 200 : if ( !m_xMediaTypeConfig.is() )
175 80 : m_xMediaTypeConfig = GetConfigurationByPath(
176 40 : OUString( "/org.openoffice.Office.Embedding/MimeTypeClassIDRelations" ));
177 :
178 200 : return m_xMediaTypeConfig;
179 : }
180 :
181 :
182 2152 : uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetFilterFactory()
183 : {
184 2152 : osl::MutexGuard aGuard( m_aMutex );
185 :
186 2152 : if ( !m_xFilterFactory.is() )
187 : m_xFilterFactory.set(
188 3924 : m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", m_xContext),
189 1962 : uno::UNO_QUERY );
190 :
191 2152 : return m_xFilterFactory;
192 : }
193 :
194 :
195 234 : OUString MimeConfigurationHelper::GetDocServiceNameFromFilter( const OUString& aFilterName )
196 : {
197 234 : OUString aDocServiceName;
198 :
199 : try
200 : {
201 : uno::Reference< container::XNameAccess > xFilterFactory(
202 : GetFilterFactory(),
203 234 : uno::UNO_SET_THROW );
204 :
205 468 : uno::Any aFilterAnyData = xFilterFactory->getByName( aFilterName );
206 468 : uno::Sequence< beans::PropertyValue > aFilterData;
207 234 : if ( aFilterAnyData >>= aFilterData )
208 : {
209 3070 : for ( sal_Int32 nInd = 0; nInd < aFilterData.getLength(); nInd++ )
210 2836 : if ( aFilterData[nInd].Name == "DocumentService" )
211 234 : aFilterData[nInd].Value >>= aDocServiceName;
212 234 : }
213 : }
214 0 : catch( uno::Exception& )
215 : {}
216 :
217 234 : return aDocServiceName;
218 : }
219 :
220 :
221 200 : OUString MimeConfigurationHelper::GetDocServiceNameFromMediaType( const OUString& aMediaType )
222 : {
223 : uno::Reference< container::XContainerQuery > xTypeCFG(
224 400 : m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_xContext),
225 200 : uno::UNO_QUERY );
226 :
227 200 : if ( xTypeCFG.is() )
228 : {
229 : try
230 : {
231 : // make query for all types matching the properties
232 200 : uno::Sequence < beans::NamedValue > aSeq( 1 );
233 200 : aSeq[0].Name = "MediaType";
234 200 : aSeq[0].Value <<= aMediaType;
235 :
236 200 : uno::Reference < container::XEnumeration > xEnum = xTypeCFG->createSubSetEnumerationByProperties( aSeq );
237 400 : while ( xEnum->hasMoreElements() )
238 : {
239 200 : uno::Sequence< beans::PropertyValue > aType;
240 200 : if ( xEnum->nextElement() >>= aType )
241 : {
242 2200 : for ( sal_Int32 nInd = 0; nInd < aType.getLength(); nInd++ )
243 : {
244 2200 : OUString aFilterName;
245 4400 : if ( aType[nInd].Name == "PreferredFilter"
246 2200 : && ( aType[nInd].Value >>= aFilterName ) && !aFilterName.isEmpty() )
247 : {
248 200 : OUString aDocumentName = GetDocServiceNameFromFilter( aFilterName );
249 200 : if ( !aDocumentName.isEmpty() )
250 200 : return aDocumentName;
251 : }
252 2000 : }
253 : }
254 0 : }
255 : }
256 0 : catch( uno::Exception& )
257 : {}
258 : }
259 :
260 0 : return OUString();
261 : }
262 :
263 :
264 6738 : bool MimeConfigurationHelper::GetVerbByShortcut( const OUString& aVerbShortcut,
265 : embed::VerbDescriptor& aDescriptor )
266 : {
267 6738 : bool bResult = false;
268 :
269 6738 : uno::Reference< container::XNameAccess > xVerbsConfig = GetVerbsConfiguration();
270 13476 : uno::Reference< container::XNameAccess > xVerbsProps;
271 : try
272 : {
273 6738 : if ( xVerbsConfig.is() && ( xVerbsConfig->getByName( aVerbShortcut ) >>= xVerbsProps ) && xVerbsProps.is() )
274 : {
275 6738 : embed::VerbDescriptor aTempDescr;
276 26952 : if ( ( xVerbsProps->getByName("VerbID") >>= aTempDescr.VerbID )
277 13476 : && ( xVerbsProps->getByName("VerbUIName") >>= aTempDescr.VerbName )
278 13476 : && ( xVerbsProps->getByName("VerbFlags") >>= aTempDescr.VerbFlags )
279 33690 : && ( xVerbsProps->getByName("VerbAttributes") >>= aTempDescr.VerbAttributes ) )
280 : {
281 6738 : aDescriptor = aTempDescr;
282 6738 : bResult = true;
283 6738 : }
284 : }
285 : }
286 0 : catch( uno::Exception& )
287 : {
288 : }
289 :
290 13476 : return bResult;
291 : }
292 :
293 :
294 1024 : uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjPropsFromConfigEntry(
295 : const uno::Sequence< sal_Int8 >& aClassID,
296 : const uno::Reference< container::XNameAccess >& xObjectProps )
297 : {
298 1024 : uno::Sequence< beans::NamedValue > aResult;
299 :
300 1024 : if ( aClassID.getLength() == 16 )
301 : {
302 : try
303 : {
304 1024 : uno::Sequence< OUString > aObjPropNames = xObjectProps->getElementNames();
305 :
306 1024 : aResult.realloc( aObjPropNames.getLength() + 1 );
307 1024 : aResult[0].Name = "ClassID";
308 1024 : aResult[0].Value <<= aClassID;
309 :
310 6144 : for ( sal_Int32 nInd = 0; nInd < aObjPropNames.getLength(); nInd++ )
311 : {
312 5120 : aResult[nInd + 1].Name = aObjPropNames[nInd];
313 :
314 5120 : if ( aObjPropNames[nInd] == "ObjectVerbs" )
315 : {
316 1024 : uno::Sequence< OUString > aVerbShortcuts;
317 1024 : if ( xObjectProps->getByName( aObjPropNames[nInd] ) >>= aVerbShortcuts )
318 : {
319 1024 : uno::Sequence< embed::VerbDescriptor > aVerbDescriptors( aVerbShortcuts.getLength() );
320 7762 : for ( sal_Int32 nVerbI = 0; nVerbI < aVerbShortcuts.getLength(); nVerbI++ )
321 6738 : if ( !GetVerbByShortcut( aVerbShortcuts[nVerbI], aVerbDescriptors[nVerbI] ) )
322 0 : throw uno::RuntimeException();
323 :
324 1024 : aResult[nInd+1].Value <<= aVerbDescriptors;
325 : }
326 : else
327 0 : throw uno::RuntimeException();
328 : }
329 : else
330 4096 : aResult[nInd+1].Value = xObjectProps->getByName( aObjPropNames[nInd] );
331 1024 : }
332 : }
333 0 : catch( uno::Exception& )
334 : {
335 0 : aResult.realloc( 0 );
336 : }
337 : }
338 :
339 1024 : return aResult;
340 : }
341 :
342 :
343 200 : OUString MimeConfigurationHelper::GetExplicitlyRegisteredObjClassID( const OUString& aMediaType )
344 : {
345 200 : OUString aStringClassID;
346 :
347 400 : uno::Reference< container::XNameAccess > xMediaTypeConfig = GetMediaTypeConfiguration();
348 : try
349 : {
350 200 : if ( xMediaTypeConfig.is() )
351 200 : xMediaTypeConfig->getByName( aMediaType ) >>= aStringClassID;
352 : }
353 200 : catch( uno::Exception& )
354 : {
355 : }
356 :
357 400 : return aStringClassID;
358 :
359 : }
360 :
361 :
362 100 : uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByStringClassID(
363 : const OUString& aStringClassID )
364 : {
365 100 : uno::Sequence< beans::NamedValue > aObjProps;
366 :
367 200 : uno::Sequence< sal_Int8 > aClassID = GetSequenceClassIDRepresentation( aStringClassID );
368 100 : 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 100 : 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 100 : return aObjProps;
394 : }
395 :
396 :
397 896 : uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByClassID(
398 : const uno::Sequence< sal_Int8 >& aClassID )
399 : {
400 896 : uno::Sequence< beans::NamedValue > aObjProps;
401 896 : if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) )
402 : {
403 6 : aObjProps.realloc(2);
404 6 : aObjProps[0].Name = "ObjectFactory";
405 6 : aObjProps[0].Value <<= OUString( "com.sun.star.embed.OOoSpecialEmbeddedObjectFactory" );
406 6 : aObjProps[1].Name = "ClassID";
407 6 : aObjProps[1].Value <<= aClassID;
408 : }
409 :
410 1792 : OUString aStringClassID = GetStringClassIDRepresentation( aClassID );
411 896 : if ( !aStringClassID.isEmpty() )
412 : {
413 896 : uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
414 1792 : uno::Reference< container::XNameAccess > xObjectProps;
415 : try
416 : {
417 902 : if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() )
418 890 : aObjProps = GetObjPropsFromConfigEntry( aClassID, xObjectProps );
419 : }
420 6 : catch( uno::Exception& )
421 : {
422 896 : }
423 : }
424 :
425 1792 : return aObjProps;
426 : }
427 :
428 :
429 100 : uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByMediaType( const OUString& aMediaType )
430 : {
431 : uno::Sequence< beans::NamedValue > aObject =
432 100 : GetObjectPropsByStringClassID( GetExplicitlyRegisteredObjClassID( aMediaType ) );
433 100 : if ( aObject.getLength() )
434 0 : return aObject;
435 :
436 200 : OUString aDocumentName = GetDocServiceNameFromMediaType( aMediaType );
437 100 : if ( !aDocumentName.isEmpty() )
438 100 : return GetObjectPropsByDocumentName( aDocumentName );
439 :
440 100 : return uno::Sequence< beans::NamedValue >();
441 : }
442 :
443 :
444 34 : uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByFilter( const OUString& aFilterName )
445 : {
446 34 : OUString aDocumentName = GetDocServiceNameFromFilter( aFilterName );
447 34 : if ( !aDocumentName.isEmpty() )
448 34 : return GetObjectPropsByDocumentName( aDocumentName );
449 :
450 0 : return uno::Sequence< beans::NamedValue >();
451 : }
452 :
453 :
454 134 : uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByDocumentName( const OUString& aDocName )
455 : {
456 134 : if ( !aDocName.isEmpty() )
457 : {
458 134 : uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
459 134 : if ( xObjConfig.is() )
460 : {
461 : try
462 : {
463 134 : uno::Sequence< OUString > aClassIDs = xObjConfig->getElementNames();
464 280 : for ( sal_Int32 nInd = 0; nInd < aClassIDs.getLength(); nInd++ )
465 : {
466 280 : uno::Reference< container::XNameAccess > xObjectProps;
467 426 : OUString aEntryDocName;
468 :
469 1400 : if ( ( xObjConfig->getByName( aClassIDs[nInd] ) >>= xObjectProps ) && xObjectProps.is()
470 560 : && ( xObjectProps->getByName("ObjectDocumentServiceName") >>= aEntryDocName )
471 1120 : && aEntryDocName == aDocName )
472 : {
473 134 : return GetObjPropsFromConfigEntry( GetSequenceClassIDRepresentation( aClassIDs[nInd] ),
474 134 : xObjectProps );
475 : }
476 146 : }
477 : }
478 0 : catch( uno::Exception& )
479 : {}
480 0 : }
481 : }
482 :
483 0 : return uno::Sequence< beans::NamedValue >();
484 : }
485 :
486 :
487 896 : OUString MimeConfigurationHelper::GetFactoryNameByClassID( const uno::Sequence< sal_Int8 >& aClassID )
488 : {
489 896 : return GetFactoryNameByStringClassID( GetStringClassIDRepresentation( aClassID ) );
490 : }
491 :
492 :
493 996 : OUString MimeConfigurationHelper::GetFactoryNameByStringClassID( const OUString& aStringClassID )
494 : {
495 996 : OUString aResult;
496 :
497 996 : if ( !aStringClassID.isEmpty() )
498 : {
499 896 : uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
500 1786 : uno::Reference< container::XNameAccess > xObjectProps;
501 : try
502 : {
503 902 : if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() )
504 890 : xObjectProps->getByName("ObjectFactory") >>= aResult;
505 : }
506 6 : catch( uno::Exception& )
507 : {
508 6 : uno::Sequence< sal_Int8 > aClassID = GetSequenceClassIDRepresentation( aStringClassID );
509 6 : if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) )
510 6 : return OUString( "com.sun.star.embed.OOoSpecialEmbeddedObjectFactory" );
511 890 : }
512 : }
513 :
514 990 : return aResult;
515 : }
516 :
517 :
518 100 : OUString MimeConfigurationHelper::GetFactoryNameByDocumentName( const OUString& aDocName )
519 : {
520 100 : OUString aResult;
521 :
522 100 : if ( !aDocName.isEmpty() )
523 : {
524 100 : uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration();
525 100 : if ( xObjConfig.is() )
526 : {
527 : try
528 : {
529 100 : uno::Sequence< OUString > aClassIDs = xObjConfig->getElementNames();
530 214 : for ( sal_Int32 nInd = 0; nInd < aClassIDs.getLength(); nInd++ )
531 : {
532 214 : uno::Reference< container::XNameAccess > xObjectProps;
533 328 : OUString aEntryDocName;
534 :
535 1070 : if ( ( xObjConfig->getByName( aClassIDs[nInd] ) >>= xObjectProps ) && xObjectProps.is()
536 642 : && ( xObjectProps->getByName(
537 642 : OUString( "ObjectDocumentServiceName" ) ) >>= aEntryDocName )
538 856 : && aEntryDocName == aDocName )
539 : {
540 100 : xObjectProps->getByName("ObjectFactory") >>= aResult;
541 100 : break;
542 : }
543 214 : }
544 : }
545 0 : catch( uno::Exception& )
546 : {}
547 100 : }
548 : }
549 :
550 100 : return aResult;
551 : }
552 :
553 :
554 :
555 100 : OUString MimeConfigurationHelper::GetFactoryNameByMediaType( const OUString& aMediaType )
556 : {
557 100 : OUString aResult = GetFactoryNameByStringClassID( GetExplicitlyRegisteredObjClassID( aMediaType ) );
558 :
559 100 : if ( aResult.isEmpty() )
560 : {
561 100 : OUString aDocumentName = GetDocServiceNameFromMediaType( aMediaType );
562 100 : if ( !aDocumentName.isEmpty() )
563 100 : aResult = GetFactoryNameByDocumentName( aDocumentName );
564 : }
565 :
566 100 : return aResult;
567 : }
568 :
569 :
570 76 : OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName(
571 : uno::Sequence< beans::PropertyValue >& aMediaDescr,
572 : bool bIgnoreType )
573 : {
574 76 : OUString aFilterName;
575 :
576 296 : for ( sal_Int32 nInd = 0; nInd < aMediaDescr.getLength(); nInd++ )
577 220 : if ( aMediaDescr[nInd].Name == "FilterName" )
578 68 : aMediaDescr[nInd].Value >>= aFilterName;
579 :
580 76 : if ( aFilterName.isEmpty() )
581 : {
582 : // filter name is not specified, so type detection should be done
583 :
584 : uno::Reference< document::XTypeDetection > xTypeDetection(
585 16 : m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_xContext),
586 8 : uno::UNO_QUERY );
587 :
588 8 : 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 16 : uno::Sequence< beans::PropertyValue > aTempMD( aMediaDescr );
593 :
594 : // get TypeName
595 16 : OUString aTypeName = xTypeDetection->queryTypeByDescriptor( aTempMD, sal_True );
596 :
597 : // get FilterName
598 32 : for ( sal_Int32 nInd = 0; nInd < aTempMD.getLength(); nInd++ )
599 24 : if ( aTempMD[nInd].Name == "FilterName" )
600 0 : aTempMD[nInd].Value >>= aFilterName;
601 :
602 8 : if ( !aFilterName.isEmpty() )
603 : {
604 0 : sal_Int32 nOldLen = aMediaDescr.getLength();
605 0 : aMediaDescr.realloc( nOldLen + 1 );
606 0 : aMediaDescr[nOldLen].Name = "FilterName";
607 0 : aMediaDescr[ nOldLen ].Value <<= aFilterName;
608 :
609 : }
610 8 : else if ( !aTypeName.isEmpty() && !bIgnoreType )
611 : {
612 8 : uno::Reference< container::XNameAccess > xNameAccess( xTypeDetection, uno::UNO_QUERY );
613 16 : uno::Sequence< beans::PropertyValue > aTypes;
614 :
615 8 : if ( xNameAccess.is() && ( xNameAccess->getByName( aTypeName ) >>= aTypes ) )
616 : {
617 88 : for ( sal_Int32 nInd = 0; nInd < aTypes.getLength(); nInd++ )
618 : {
619 88 : if ( aTypes[nInd].Name == "PreferredFilter" && ( aTypes[nInd].Value >>= aFilterName ) )
620 : {
621 8 : sal_Int32 nOldLen = aMediaDescr.getLength();
622 8 : aMediaDescr.realloc( nOldLen + 1 );
623 8 : aMediaDescr[nOldLen].Name = "FilterName";
624 8 : aMediaDescr[ nOldLen ].Value = aTypes[nInd].Value;
625 8 : break;
626 : }
627 : }
628 8 : }
629 8 : }
630 : }
631 :
632 76 : 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 1918 : OUString MimeConfigurationHelper::GetDefaultFilterFromServiceName( const OUString& aServiceName, sal_Int32 nVersion )
716 : {
717 1918 : OUString aResult;
718 :
719 1918 : if ( !aServiceName.isEmpty() && nVersion )
720 : try
721 : {
722 : uno::Reference< container::XContainerQuery > xFilterQuery(
723 : GetFilterFactory(),
724 1918 : uno::UNO_QUERY_THROW );
725 :
726 3836 : uno::Sequence< beans::NamedValue > aSearchRequest( 2 );
727 1918 : aSearchRequest[0].Name = "DocumentService";
728 1918 : aSearchRequest[0].Value <<= aServiceName;
729 1918 : aSearchRequest[1].Name = "FileFormatVersion";
730 1918 : aSearchRequest[1].Value <<= nVersion;
731 :
732 : uno::Reference< container::XEnumeration > xFilterEnum =
733 3836 : xFilterQuery->createSubSetEnumerationByProperties( aSearchRequest );
734 :
735 : // use the first filter that is found
736 1918 : if ( xFilterEnum.is() )
737 5758 : while ( xFilterEnum->hasMoreElements() )
738 : {
739 2714 : uno::Sequence< beans::PropertyValue > aProps;
740 2714 : if ( xFilterEnum->nextElement() >>= aProps )
741 : {
742 2714 : SequenceAsHashMap aPropsHM( aProps );
743 2714 : 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 : sal_Int32 const nRequired = (SFX_FILTER_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 2714 : | (SOFFICE_FILEFORMAT_60 == nVersion ? 0 : SFX_FILTER_EXPORT)
751 2714 : | SFX_FILTER_IMPORT );
752 2714 : if ( ( ( nFlags & nRequired ) == nRequired ) && !( nFlags & SFX_FILTER_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 2694 : if ( aResult.isEmpty() || ( nFlags & SFX_FILTER_PREFERED ) )
757 2694 : aResult = aPropsHM.getUnpackedValueOrDefault( "Name", OUString() );
758 2694 : if ( nFlags & SFX_FILTER_PREFERED )
759 792 : break; // the preferred filter was found
760 1922 : }
761 : }
762 3840 : }
763 : }
764 0 : catch( uno::Exception& )
765 : {}
766 :
767 1918 : 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 : sal_Int32 nFlags = aImpFilterHM.getUnpackedValueOrDefault( "Flags", (sal_Int32)0 );
789 :
790 0 : if ( !( nFlags & SFX_FILTER_IMPORT ) )
791 : {
792 : OSL_FAIL( "This is no import filter!" );
793 0 : throw uno::Exception();
794 : }
795 :
796 0 : if ( nFlags & SFX_FILTER_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 : SFX_FILTER_EXPORT,
818 0 : SFX_FILTER_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 : sal_Int32 nMustFlags,
842 : sal_Int32 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 : sal_Int32 nFlags = aPropsHM.getUnpackedValueOrDefault("Flags",
859 0 : (sal_Int32)0 );
860 0 : if ( ( ( nFlags & nMustFlags ) == nMustFlags ) && !( nFlags & nDontFlags ) )
861 : {
862 0 : if ( ( nFlags & SFX_FILTER_DEFAULT ) == SFX_FILTER_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 1002 : bool MimeConfigurationHelper::ClassIDsEqual( const uno::Sequence< sal_Int8 >& aClassID1, const uno::Sequence< sal_Int8 >& aClassID2 )
880 : {
881 1002 : if ( aClassID1.getLength() != aClassID2.getLength() )
882 100 : return false;
883 :
884 1094 : for ( sal_Int32 nInd = 0; nInd < aClassID1.getLength(); nInd++ )
885 1082 : if ( aClassID1[nInd] != aClassID2[nInd] )
886 890 : return false;
887 :
888 12 : return true;
889 : }
890 :
891 :
892 1002 : 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 1002 : uno::Sequence< sal_Int8 > aResult( 16 );
897 1002 : aResult[0] = (sal_Int8)( n1 >> 24 );
898 1002 : aResult[1] = (sal_Int8)( ( n1 << 8 ) >> 24 );
899 1002 : aResult[2] = (sal_Int8)( ( n1 << 16 ) >> 24 );
900 1002 : aResult[3] = (sal_Int8)( ( n1 << 24 ) >> 24 );
901 1002 : aResult[4] = (sal_Int8)( n2 >> 8 );
902 1002 : aResult[5] = (sal_Int8)( ( n2 << 8 ) >> 8 );
903 1002 : aResult[6] = (sal_Int8)( n3 >> 8 );
904 1002 : aResult[7] = (sal_Int8)( ( n3 << 8 ) >> 8 );
905 1002 : aResult[8] = b8;
906 1002 : aResult[9] = b9;
907 1002 : aResult[10] = b10;
908 1002 : aResult[11] = b11;
909 1002 : aResult[12] = b12;
910 1002 : aResult[13] = b13;
911 1002 : aResult[14] = b14;
912 1002 : aResult[15] = b15;
913 :
914 1002 : return aResult;
915 : }
916 :
917 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|