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