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