merged tag ooo/OOO330_m14
[LibreOffice.git] / extensions / source / plugin / aqua / macmgr.cxx
blobb66963e420fb41ca6e1f5020a1c13fc012e5e6ad
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 #include "rtl/ustrbuf.hxx"
29 #include "rtl/strbuf.hxx"
31 #include "plugin/impl.hxx"
32 #include "osl/file.h"
33 #include "osl/module.hxx"
35 using namespace rtl;
36 using namespace std;
37 using namespace com::sun::star::uno;
38 using namespace com::sun::star::plugin;
40 namespace plugstringhelper
43 rtl::OUString getString( CFStringRef i_xString )
45 rtl::OUStringBuffer aBuf;
46 if( i_xString )
48 CFIndex nChars = CFStringGetLength( i_xString );
49 CFRange aRange = { 0, nChars };
50 aBuf.setLength( nChars );
51 CFStringGetCharacters( i_xString, aRange, static_cast< UniChar* >(const_cast<sal_Unicode*>(aBuf.getStr())) );
53 return aBuf.makeStringAndClear();
56 rtl::OUString getString( CFURLRef i_xURL )
58 CFStringRef xString = CFURLGetString( i_xURL );
59 return getString( xString );
62 CFMutableStringRef createString( const rtl::OUString& i_rString )
64 CFMutableStringRef xString = CFStringCreateMutable( NULL, 0 );
65 if( xString )
66 CFStringAppendCharacters( xString, i_rString.getStr(), i_rString.getLength() );
67 return xString;
70 CFURLRef createURL( const rtl::OUString& i_rString )
73 CFMutableStringRef xMutableString = createString( i_rString );
74 CFURLRef xURL = CFURLCreateWithString( NULL, xMutableString, NULL );
75 CFRelease( xMutableString );
76 return xURL;
79 rtl::OUString getURLFromPath( const rtl::OUString& i_rPath )
81 CFMutableStringRef xMutableString = createString( i_rPath );
82 CFURLRef xURL = CFURLCreateWithFileSystemPath( NULL, xMutableString, kCFURLPOSIXPathStyle, true );
83 CFRelease( xMutableString );
84 CFStringRef xString = CFURLGetString( xURL );
85 rtl::OUString aRet = getString( xString );
86 CFRelease( xURL );
87 return aRet;
90 CFURLRef createURLFromPath( const rtl::OUString& i_rPath )
92 CFMutableStringRef xMutableString = createString( i_rPath );
93 CFURLRef xURL = CFURLCreateWithFileSystemPath( NULL, xMutableString, kCFURLPOSIXPathStyle, true );
94 return xURL;
97 rtl::OUString CFURLtoOSLURL( CFURLRef i_xURL )
99 // make URL absolute
100 CFURLRef xAbsURL = CFURLCopyAbsoluteURL( i_xURL );
101 // copy system path
102 CFStringRef xSysPath = CFURLCopyFileSystemPath( xAbsURL ? xAbsURL : i_xURL, kCFURLPOSIXPathStyle );
103 if( xAbsURL )
104 CFRelease( xAbsURL );
105 rtl::OUString aSysPath( getString( xSysPath ) );
106 CFRelease( xSysPath );
107 rtl::OUString aFileURL;
108 osl_getFileURLFromSystemPath( aSysPath.pData, &aFileURL.pData );
109 return aFileURL;
114 using namespace plugstringhelper;
116 static int parsePlist( CFBundleRef i_xBundle, const rtl::OUString& i_rBundleURL , list< PluginDescription* >& io_rDescriptions )
118 CFTypeRef xMimeDict = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("WebPluginMIMETypes"));
119 int nMimetypes = 0;
120 if( xMimeDict == 0 ||
121 CFGetTypeID(xMimeDict) != CFDictionaryGetTypeID() ||
122 (nMimetypes = CFDictionaryGetCount( static_cast<CFDictionaryRef>(xMimeDict))) <= 0 )
124 return 0;
127 // prepare an array of key and value refs
128 std::vector< CFTypeRef > aKeys( nMimetypes, CFTypeRef(NULL) );
129 std::vector< CFTypeRef > aValues( nMimetypes, CFTypeRef(NULL) );
130 CFDictionaryGetKeysAndValues(static_cast<CFDictionaryRef>(xMimeDict), &aKeys[0], &aValues[0] );
132 int nAdded = 0;
133 for( int i = 0; i < nMimetypes; i++ )
135 // get the mimetype
136 CFTypeRef xKey = aKeys[i];
137 if( ! xKey || CFGetTypeID(xKey) != CFStringGetTypeID() )
138 continue;
139 rtl::OUString aMimetype = getString( (CFStringRef)xKey );
141 // the correspoding value should be a dictionary
142 CFTypeRef xDict = aValues[i];
143 if( ! xDict || CFGetTypeID( xDict ) != CFDictionaryGetTypeID() )
144 continue;
146 // get the extension list
147 CFTypeRef xExtArray = CFDictionaryGetValue( (CFDictionaryRef)xDict, CFSTR("WebPluginExtensions" ) );
148 if( !xExtArray || CFGetTypeID( xExtArray ) != CFArrayGetTypeID() )
149 continue;
151 OUStringBuffer aExtBuf;
152 int nExtensions = CFArrayGetCount( (CFArrayRef)xExtArray );
153 for( int n = 0; n < nExtensions; n++ )
155 CFTypeRef xExt = CFArrayGetValueAtIndex( (CFArrayRef)xExtArray, n );
156 if( xExt && CFGetTypeID( xExt ) == CFStringGetTypeID() )
158 if( aExtBuf.getLength() > 0 )
159 aExtBuf.append( sal_Unicode(';') );
160 OUString aExt( getString( (CFStringRef)xExt ) );
161 if( aExt.indexOfAsciiL( "*.", 2 ) != 0 )
162 aExtBuf.appendAscii( "*." );
163 aExtBuf.append( aExt );
167 // get the description string
168 CFTypeRef xDescString = CFDictionaryGetValue( (CFDictionaryRef)xDict, CFSTR("WebPluginTypeDescription" ) );
169 if( !xDescString || CFGetTypeID( xDescString ) != CFStringGetTypeID() )
170 continue;
171 rtl::OUString aDescription = getString( (CFStringRef)xDescString );
173 PluginDescription* pNew = new PluginDescription;
174 // set plugin name (path to library)
175 pNew->PluginName = i_rBundleURL;
176 // set mimetype
177 pNew->Mimetype = aMimetype;
178 // set extension line
179 pNew->Extension = aExtBuf.makeStringAndClear();
180 // set description
181 pNew->Description= aDescription;
183 io_rDescriptions.push_back( pNew );
184 nAdded++;
186 #if OSL_DEBUG_LEVEL > 1
187 fprintf( stderr,
188 "Inserting from PList:\n"
189 " Mimetype: %s\n"
190 " Extension: %s\n"
191 " Description: %s\n",
192 OUStringToOString( pNew->Mimetype, RTL_TEXTENCODING_UTF8 ).getStr(),
193 OUStringToOString( pNew->Extension, RTL_TEXTENCODING_UTF8 ).getStr(),
194 OUStringToOString( pNew->Description, RTL_TEXTENCODING_UTF8 ).getStr()
196 #endif
200 return nAdded;
203 static int parseMimeString( const rtl::OUString& i_rBundleURL , list< PluginDescription* >& io_rDescriptions, const char* i_pMime )
205 if( ! i_pMime )
206 return 0;
208 rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
210 OStringBuffer aMIME;
211 aMIME.append( i_pMime );
213 if( aMIME.getLength() < 1 )
214 return 0;
216 OString aLine = aMIME.makeStringAndClear();
218 int nAdded = 0;
219 sal_Int32 nIndex = 0;
220 while( nIndex != -1 )
222 OString aType = aLine.getToken( 0, ';', nIndex );
224 sal_Int32 nTypeIndex = 0;
225 OString aMimetype = aType.getToken( 0, ':', nTypeIndex );
226 OString aExtLine = aType.getToken( 0, ':', nTypeIndex );
227 if( nTypeIndex < 0 ) // ensure at least three tokens
228 continue;
229 OString aDesc = aType.getToken( 0, ':', nTypeIndex );
231 // create extension list string
232 sal_Int32 nExtIndex = 0;
233 OStringBuffer aExtension;
234 while( nExtIndex != -1 )
236 OString aExt = aExtLine.getToken( 0, ',', nExtIndex);
237 if( aExt.indexOf( "*." ) != 0 )
238 aExtension.append( "*." );
239 aExtension.append( aExt );
240 if( nExtIndex != -1 )
241 aExtension.append( ';' );
244 PluginDescription* pNew = new PluginDescription;
245 // set plugin name (path to library)
246 pNew->PluginName = i_rBundleURL;
247 // set mimetype
248 pNew->Mimetype = OStringToOUString( aMimetype, aEncoding );
249 // set extension line
250 pNew->Extension = OStringToOUString( aExtension.makeStringAndClear(), aEncoding );
251 // set description
252 pNew->Description= OStringToOUString( aDesc, aEncoding );
253 io_rDescriptions.push_back( pNew );
254 nAdded++;
256 #if OSL_DEBUG_LEVEL > 1
257 fprintf( stderr,
258 "Inserting from mime string:\n"
259 " Mimetype: %s\n"
260 " Extension: %s\n"
261 " Description: %s\n",
262 OUStringToOString( pNew->Mimetype, aEncoding ).getStr(),
263 OUStringToOString( pNew->Extension, aEncoding ).getStr(),
264 OUStringToOString( pNew->Description, aEncoding ).getStr()
266 #endif
268 return nAdded;
271 // this is so ugly it you want to tear your eyes out
272 static rtl::OUString GetNextPluginStringFromHandle(Handle h, short *index)
274 char* pPascalBytes = (*h + *index);
275 sal_uInt32 nLen = (unsigned char)pPascalBytes[0];
276 rtl::OStringBuffer aBuf( nLen );
277 aBuf.append( pPascalBytes+1, nLen );
278 *index += nLen + 1;
279 return rtl::OStringToOUString( aBuf.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
282 static int parseMimeResource( CFBundleRef i_xBundle,
283 oslModule& i_rMod,
284 const rtl::OUString& i_rBundleURL,
285 list< PluginDescription* >& io_rDescriptions )
287 int nAdded = 0;
288 // just to hurt our eyes more there is an alternative mimetype function plus the possibility
289 // of a resource fork. Must be a case of think different.
290 #if __LP64__
292 #else
293 SInt16
294 #endif
295 xRes = 0;
296 BPSupportedMIMETypes aMIMETypesStrangeStruct = {kBPSupportedMIMETypesStructVers_1, NULL, NULL};
298 BP_GetSupportedMIMETypesUPP pBPGetSupp = (BP_GetSupportedMIMETypesUPP)osl_getAsciiFunctionSymbol( i_rMod, "BP_GetSupportedMIMETypes" );
299 if( pBPGetSupp &&
300 noErr == pBPGetSupp( &aMIMETypesStrangeStruct, 0 ) &&
301 aMIMETypesStrangeStruct.typeStrings )
303 HLock( aMIMETypesStrangeStruct.typeStrings );
304 if( aMIMETypesStrangeStruct.infoStrings ) // it's possible some plugins have infoStrings missing
305 HLock( aMIMETypesStrangeStruct.infoStrings );
307 else // Try to get data from the resource fork
309 xRes = CFBundleOpenBundleResourceMap( i_xBundle );
310 if( xRes > 0 )
312 aMIMETypesStrangeStruct.typeStrings = Get1Resource('STR#', 128);
313 if( aMIMETypesStrangeStruct.typeStrings )
315 DetachResource( aMIMETypesStrangeStruct.typeStrings );
316 HLock( aMIMETypesStrangeStruct.typeStrings );
317 aMIMETypesStrangeStruct.infoStrings = Get1Resource('STR#', 127);
318 if( aMIMETypesStrangeStruct.infoStrings )
320 DetachResource( aMIMETypesStrangeStruct.infoStrings );
321 HLock( aMIMETypesStrangeStruct.infoStrings );
327 if( aMIMETypesStrangeStruct.typeStrings && aMIMETypesStrangeStruct.infoStrings )
329 short nVariantCount = (**(short**)aMIMETypesStrangeStruct.typeStrings) / 2;
330 // Fill in the info struct based on the data in the BPSupportedMIMETypes struct
331 // this is an array of pascal string of unknown (!) encoding
332 // whoever thought of this deserves a fair beating
333 short mimeIndex = 2;
334 short descriptionIndex = 2;
335 for( int i = 0; i < nVariantCount; i++ )
337 rtl::OUString aMimetype = GetNextPluginStringFromHandle( aMIMETypesStrangeStruct.typeStrings, &mimeIndex );
338 rtl::OUString aExtLine = GetNextPluginStringFromHandle( aMIMETypesStrangeStruct.typeStrings, &mimeIndex );
339 rtl::OUString aDescription;
340 if( aMIMETypesStrangeStruct.infoStrings )
341 aDescription = GetNextPluginStringFromHandle( aMIMETypesStrangeStruct.infoStrings, &descriptionIndex );
343 // create extension list string
344 sal_Int32 nExtIndex = 0;
345 OUStringBuffer aExtension;
346 while( nExtIndex != -1 )
348 OUString aExt = aExtLine.getToken( 0, ',', nExtIndex);
349 if( aExt.indexOfAsciiL( "*.", 2 ) != 0 )
350 aExtension.appendAscii( "*." );
351 aExtension.append( aExt );
352 if( nExtIndex != -1 )
353 aExtension.append( sal_Unicode(';') );
356 PluginDescription* pNew = new PluginDescription;
357 // set plugin name (path to library)
358 pNew->PluginName = i_rBundleURL;
359 // set mimetype
360 pNew->Mimetype = aMimetype;
361 // set extension line
362 pNew->Extension = aExtension.makeStringAndClear();
363 // set description
364 pNew->Description= aDescription;
365 io_rDescriptions.push_back( pNew );
366 nAdded++;
368 #if OSL_DEBUG_LEVEL > 1
369 fprintf( stderr,
370 "Inserting from resource:\n"
371 " Mimetype: %s\n"
372 " Extension: %s\n"
373 " Description: %s\n",
374 OUStringToOString( pNew->Mimetype, RTL_TEXTENCODING_UTF8 ).getStr(),
375 OUStringToOString( pNew->Extension, RTL_TEXTENCODING_UTF8 ).getStr(),
376 OUStringToOString( pNew->Description, RTL_TEXTENCODING_UTF8 ).getStr()
378 #endif
383 // clean up
384 if( aMIMETypesStrangeStruct.typeStrings )
386 HUnlock( aMIMETypesStrangeStruct.typeStrings );
387 DisposeHandle( aMIMETypesStrangeStruct.typeStrings );
389 if( aMIMETypesStrangeStruct.infoStrings )
391 HUnlock( aMIMETypesStrangeStruct.infoStrings );
392 DisposeHandle( aMIMETypesStrangeStruct.infoStrings );
394 if( xRes )
395 CFBundleCloseBundleResourceMap( i_xBundle, xRes );
397 return nAdded;
400 // check some known bad plugins to avoid crashes
401 static bool checkBlackList( CFBundleRef i_xBundle )
403 rtl::OUString aBundleName;
404 CFTypeRef bundlename = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("CFBundleName"));
405 if( bundlename && CFGetTypeID(bundlename) == CFStringGetTypeID() )
406 aBundleName = getString( static_cast<CFStringRef>(bundlename) );
408 rtl::OUString aBundleVersion;
409 CFTypeRef bundleversion = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("CFBundleVersion"));
410 if( bundleversion && CFGetTypeID(bundleversion) == CFStringGetTypeID() )
411 aBundleVersion = getString( static_cast<CFStringRef>(bundleversion) );
413 bool bReject = false;
414 // #i102735# VLC plugin prior to 1.0 tends to crash
415 if( aBundleName.equalsAscii( "VLC Plug-in" ) )
417 sal_Int32 nIndex = 0;
418 rtl::OUString aMajor( aBundleVersion.getToken( 0, '.', nIndex ) );
419 if( aMajor.toInt32() < 1 )
421 bReject = true;
424 // #i103674# Garmin Communicator Plugin crashes
425 else if( aBundleName.equalsAscii( "Garmin Communicator Plugin" ) )
427 bReject = true;
430 #if OSL_DEBUG_LEVEL > 1
431 if( bReject )
432 fprintf( stderr, "rejecting plugin \"%s\" version %s\n",
433 rtl::OUStringToOString( aBundleName, RTL_TEXTENCODING_UTF8 ).getStr(),
434 rtl::OUStringToOString( aBundleVersion, RTL_TEXTENCODING_UTF8 ).getStr()
436 #endif
438 return bReject;
441 static int getPluginDescriptions( CFBundleRef i_xBundle , list< PluginDescription* >& io_rDescriptions )
443 int nDescriptions = 0;
444 if( ! i_xBundle )
445 return nDescriptions;
447 if( checkBlackList( i_xBundle ) )
448 return 0;
450 rtl::OUString aPlugURL;
451 CFURLRef xURL = CFBundleCopyBundleURL( i_xBundle );
452 aPlugURL = getString( xURL );
453 CFRelease( xURL );
455 #if OSL_DEBUG_LEVEL > 1
456 rtl::OUString aPlugName, aPlugDescription;
457 CFTypeRef name = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("WebPluginName"));
458 if( name && CFGetTypeID(name) == CFStringGetTypeID() )
459 aPlugName = getString( static_cast<CFStringRef>(name) );
461 CFTypeRef description = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("WebPluginDescription"));
462 if( description && CFGetTypeID(description) == CFStringGetTypeID() )
463 aPlugDescription = getString( static_cast<CFStringRef>(description) );
465 fprintf( stderr, "URL: %s\nname: %s\ndescription: %s\n",
466 rtl::OUStringToOString( aPlugURL, RTL_TEXTENCODING_UTF8 ).getStr(),
467 rtl::OUStringToOString( aPlugName, RTL_TEXTENCODING_UTF8 ).getStr(),
468 rtl::OUStringToOString( aPlugDescription, RTL_TEXTENCODING_UTF8 ).getStr()
470 #endif
473 // get location of plugin library
474 CFURLRef xLibURL = CFBundleCopyExecutableURL( i_xBundle );
475 if( ! xLibURL )
476 return 0;
477 // get the file system path
478 rtl::OUString aModuleURL( CFURLtoOSLURL( xLibURL ) );
479 CFRelease( xLibURL );
481 #if OSL_DEBUG_LEVEL > 1
482 fprintf( stderr, "exec URL = %s\n", rtl::OUStringToOString( aModuleURL, RTL_TEXTENCODING_UTF8 ).getStr() );
483 #endif
485 /* TODO: originally the C++ wrapper for oslModule was used here, but that led to
486 mysterious crashes in the event loop (pointing to heap corruption). Why using
487 the C style oslModule should fix this is completely unknown. It may be that
488 we have just hidden the heap corruption a little more.
490 oslModule aMod = osl_loadModule( aModuleURL.pData, SAL_LOADMODULE_DEFAULT );
491 if( ! aMod )
492 return 0;
494 // check for at least the init function of a plugin
495 if( ! osl_getAsciiFunctionSymbol( aMod, "NP_Initialize") &&
496 ! osl_getAsciiFunctionSymbol( aMod, "NP_GetEntryPoints" ) )
498 return 0;
501 // ask the plist of the bundle for mimetypes
502 nDescriptions = parsePlist( i_xBundle, aPlugURL, io_rDescriptions );
503 if( nDescriptions )
505 osl_unloadModule( aMod );
506 return nDescriptions;
509 // resolve the symbol that might get us the mimetypes
510 const char* (*pGetMimeDescription)() = (const char*(*)())osl_getAsciiFunctionSymbol( aMod, "_NP_GetMIMEDescription" );
511 if( pGetMimeDescription )
513 const char* pMime = pGetMimeDescription();
514 if( pMime )
516 nDescriptions = parseMimeString( aPlugURL, io_rDescriptions, pMime );
517 if( nDescriptions )
519 osl_unloadModule( aMod );
520 return nDescriptions;
525 // and as last resort check the resource of the bundle
526 nDescriptions = parseMimeResource( i_xBundle, aMod, aPlugURL, io_rDescriptions );
527 osl_unloadModule( aMod );
529 return nDescriptions;
532 // Unix specific implementation
533 static bool CheckPlugin( const rtl::OUString& rPath, list< PluginDescription* >& rDescriptions )
535 #if OSL_DEBUG_LEVEL > 1
536 fprintf( stderr, "Trying path %s ... ", rtl::OUStringToOString( rPath, RTL_TEXTENCODING_UTF8 ).getStr() );
537 #endif
538 CFURLRef xURL = createURL( rPath );
540 CFArrayRef xBundles = CFBundleCreateBundlesFromDirectory( NULL, xURL, CFSTR("plugin") );
541 if( ! xBundles )
542 return false;
544 CFIndex nBundles = CFArrayGetCount( xBundles );
546 #if OSL_DEBUG_LEVEL > 1
547 fprintf( stderr, "got %d bundles\n", (int)nBundles );
548 #endif
550 int nDescriptions = 0;
551 for( CFIndex i = 0; i < nBundles; i++ )
553 CFBundleRef xBundle = (CFBundleRef)CFArrayGetValueAtIndex( xBundles, i );
554 nDescriptions += getPluginDescriptions( xBundle, rDescriptions );
556 CFRelease( xBundle );
558 CFRelease( xBundles );
561 return nDescriptions > 0;
564 static rtl::OUString FindFolderURL( FSVolumeRefNum vRefNum, OSType folderType )
566 rtl::OUString aRet;
568 FSRef aFSRef;
569 OSErr err = FSFindFolder( vRefNum, folderType, kDontCreateFolder, &aFSRef );
570 if( err == noErr )
572 CFURLRef xURL = CFURLCreateFromFSRef( NULL, &aFSRef );
573 aRet = getString( xURL );
574 CFRelease( xURL );
577 return aRet;
580 Sequence<PluginDescription> XPluginManager_Impl::impl_getPluginDescriptions() throw()
582 static Sequence<PluginDescription> aDescriptions;
583 static BOOL bHavePlugins = FALSE;
584 if( ! bHavePlugins )
586 std::list<PluginDescription*> aPlugins;
588 static const char* pNPXPluginPath = getenv( "MOZ_PLUGIN_PATH" );
590 // get directories
591 std::list< rtl::OUString > aPaths;
592 if( pNPXPluginPath )
594 CFMutableStringRef xMutableString = CFStringCreateMutable( NULL, 0 );
595 CFStringAppendCString( xMutableString, pNPXPluginPath, kCFStringEncodingUTF8 );
596 CFURLRef xURL = CFURLCreateWithFileSystemPath( NULL, xMutableString, kCFURLPOSIXPathStyle, true );
597 CFRelease( xMutableString );
598 aPaths.push_back( getString( xURL ) );
599 CFRelease( xURL );
602 rtl::OUString aPath = FindFolderURL( kUserDomain, kInternetPlugInFolderType );
603 if( aPath.getLength() )
604 aPaths.push_back( aPath );
605 aPath = FindFolderURL( kLocalDomain, kInternetPlugInFolderType );
606 if( aPath.getLength() )
607 aPaths.push_back( aPath );
608 aPath = FindFolderURL( kOnAppropriateDisk, kInternetPlugInFolderType );
609 if( aPath.getLength() )
610 aPaths.push_back( aPath );
613 const Sequence< ::rtl::OUString >& rPaths( PluginManager::getAdditionalSearchPaths() );
614 for( sal_Int32 i = 0; i < rPaths.getLength(); i++ )
616 aPaths.push_back( getURLFromPath( rPaths.getConstArray()[i] ) );
619 for( std::list< rtl::OUString >::const_iterator it = aPaths.begin(); it != aPaths.end(); ++it )
621 rtl::OUString aPath( *it );
622 #if OSL_DEBUG_LEVEL > 1
623 fprintf( stderr, "check path %s\n", rtl::OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr() );
624 #endif
625 CheckPlugin( aPath, aPlugins );
629 // create return value
630 aDescriptions = Sequence<PluginDescription>( aPlugins.size() );
631 #if OSL_DEBUG_LEVEL > 1
632 fprintf( stderr, "found %d plugins\n", (int)aPlugins.size() );
633 #endif
634 list<PluginDescription*>::iterator iter;
635 sal_Int32 nPlug = 0;
636 for( iter = aPlugins.begin(); iter != aPlugins.end(); ++iter )
638 aDescriptions.getArray()[ nPlug++ ] = **iter;
639 delete *iter;
641 aPlugins.clear();
642 bHavePlugins = TRUE;
644 return aDescriptions;