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