1 // =================================================================================================
2 // ADOBE SYSTEMS INCORPORATED
3 // Copyright 2011 Adobe Systems Incorporated
4 // All Rights Reserved
5 //
6 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
7 // of the Adobe license agreement accompanying it.
8 // =================================================================================================
9
10 #include "PluginManager.h"
11 #include "FileHandler.h"
12 #include <algorithm>
13 #include "XMPAtoms.h"
14 #include "XMPFiles/source/HandlerRegistry.h"
15 #include "FileHandlerInstance.h"
16 #include "HostAPI.h"
17
18 using namespace Common;
19 using namespace std;
20
21 // =================================================================================================
22
23 namespace XMP_PLUGIN
24 {
25
26 const char* kResourceName_UIDs = "XMPPLUGINUIDS";
27 const char* kLibraryExtensions[] = { "xpi" };
28
29 struct FileHandlerPair
30 {
31 FileHandlerSharedPtr mStandardHandler;
32 FileHandlerSharedPtr mReplacementHandler;
33 };
34
35 // =================================================================================================
36 #if 0 // unused
37 static XMP_FileFormat GetXMPFileFormatFromFilePath( XMP_StringPtr filePath )
38 {
39 XMP_StringPtr pathName = filePath + strlen(filePath);
40 for ( ; pathName > filePath; --pathName ) {
41 if ( *pathName == '.' ) break;
42 }
43
44 XMP_StringPtr fileExt = pathName + 1;
45 return HandlerRegistry::getInstance().getFileFormat ( fileExt );
46 }
47 #endif
48 // =================================================================================================
49
Plugin_MetaHandlerCTor(FileHandlerSharedPtr handler,XMPFiles * parent)50 static XMPFileHandler* Plugin_MetaHandlerCTor ( FileHandlerSharedPtr handler, XMPFiles* parent )
51 {
52 SessionRef object;
53 WXMP_Error error;
54
55 if( (handler == 0) || (! handler->load()) )
56 {
57 XMP_Throw ( "Plugin not loaded", kXMPErr_InternalFailure );
58 }
59
60 if( handler->getModule()->getPluginAPIs()->mInitializeSessionV2Proc )
61 handler->getModule()->getPluginAPIs()->mInitializeSessionV2Proc ( handler->getUID().c_str(), parent->GetFilePath().c_str(), (XMP_Uns32)parent->format, (XMP_Uns32)handler->getHandlerFlags(), (XMP_Uns32)parent->openFlags, &object, &error, ErrorCallbackBox( parent->errorCallback.wrapperProc, parent->errorCallback.clientProc, parent->errorCallback.context, parent->errorCallback.limit ), parent->progressTracker->GetCallbackInfo() );
62 else
63 handler->getModule()->getPluginAPIs()->mInitializeSessionProc ( handler->getUID().c_str(), parent->GetFilePath().c_str(), (XMP_Uns32)parent->format, (XMP_Uns32)handler->getHandlerFlags(), (XMP_Uns32)parent->openFlags, &object, &error );
64 CheckError ( error );
65
66 FileHandlerInstance* instance = new FileHandlerInstance ( object, handler, parent );
67 return instance;
68 }
69
Plugin_MetaHandlerCTor_Standard(XMPFiles * parent)70 static XMPFileHandler* Plugin_MetaHandlerCTor_Standard( XMPFiles * parent )
71 {
72 FileHandlerSharedPtr handler = PluginManager::getFileHandler( parent->format, PluginManager::kStandardHandler );
73
74 return Plugin_MetaHandlerCTor( handler, parent );
75 }
76
Plugin_MetaHandlerCTor_Replacement(XMPFiles * parent)77 static XMPFileHandler* Plugin_MetaHandlerCTor_Replacement( XMPFiles * parent )
78 {
79 FileHandlerSharedPtr handler = PluginManager::getFileHandler( parent->format, PluginManager::kReplacementHandler );
80
81 return Plugin_MetaHandlerCTor( handler, parent );
82 }
83
84 // =================================================================================================
85
Plugin_CheckFileFormat(FileHandlerSharedPtr handler,XMP_StringPtr filePath,XMP_IO * fileRef,XMPFiles *)86 static bool Plugin_CheckFileFormat ( FileHandlerSharedPtr handler, XMP_StringPtr filePath, XMP_IO * fileRef, XMPFiles * /*parent*/ )
87 {
88 if ( handler != 0 ) {
89
90 // call into plugin if owning handler or if manifest has no CheckFormat entry
91 if ( fileRef == 0 || handler->getCheckFormatSize() == 0) {
92
93 XMP_Bool ok;
94 WXMP_Error error;
95 CheckSessionFileFormatProc checkProc = handler->getModule()->getPluginAPIs()->mCheckFileFormatProc;
96 checkProc ( handler->getUID().c_str(), filePath, fileRef, &ok, &error );
97 CheckError ( error );
98 return ConvertXMP_BoolToBool( ok );
99
100 } else {
101
102 // all CheckFormat manifest entries must match
103 for ( XMP_Uns32 i=0; i < handler->getCheckFormatSize(); i++ ) {
104
105 CheckFormat checkFormat = handler->getCheckFormat ( i );
106
107 if ( checkFormat.empty() ) return false;
108
109 XMP_Uns8 buffer[1024];
110
111 if ( checkFormat.mLength > 1024 ) {
112 //Ideally check format string should not be that long.
113 //The check is here to handle only malicious data.
114 checkFormat.mLength = 1024;
115 }
116
117 fileRef->Seek ( checkFormat.mOffset, kXMP_SeekFromStart );
118 XMP_Uns32 len = fileRef->Read ( buffer, checkFormat.mLength );
119
120 if ( len != checkFormat.mLength ) {
121
122 // Not enough byte read from the file.
123 return false;
124
125 } else {
126
127 // Check if byteSeq is hexadecimal byte sequence, e.g 0x03045100
128
129 bool isHex = ( (checkFormat.mLength > 0 ) &&
130 (checkFormat.mByteSeq.size() == (2 + 2*checkFormat.mLength) &&
131 (checkFormat.mByteSeq[0] == '0') &&
132 (checkFormat.mByteSeq[1] == 'x') )
133 );
134
135 if ( ! isHex ) {
136
137 if ( memcmp ( buffer, checkFormat.mByteSeq.c_str(), checkFormat.mLength ) != 0 ) return false;
138
139 } else {
140
141 for ( XMP_Uns32 current = 0; current < checkFormat.mLength; current++ ) {
142
143 char oneByteBuffer[3];
144 oneByteBuffer[0] = checkFormat.mByteSeq [ 2 + 2*current ];
145 oneByteBuffer[1] = checkFormat.mByteSeq [ 2 + 2*current + 1 ];
146 oneByteBuffer[2] = '\0';
147
148 XMP_Uns8 oneByte = (XMP_Uns8) strtoul ( oneByteBuffer, 0, 16 );
149 if ( oneByte != buffer[current] ) return false;
150
151 }
152
153 }
154
155 }
156
157 }
158
159 return true; // The checkFormat string comparison passed.
160
161 }
162
163 }
164
165 return false; // Should never get here.
166 } // Plugin_CheckFileFormat
167
Plugin_CheckFileFormat_Standard(XMP_FileFormat format,XMP_StringPtr filePath,XMP_IO * fileRef,XMPFiles * parent)168 static bool Plugin_CheckFileFormat_Standard( XMP_FileFormat format, XMP_StringPtr filePath, XMP_IO* fileRef, XMPFiles* parent )
169 {
170 FileHandlerSharedPtr handler = PluginManager::getFileHandler( format, PluginManager::kStandardHandler );
171
172 return Plugin_CheckFileFormat( handler, filePath, fileRef, parent );
173 }
174
Plugin_CheckFileFormat_Replacement(XMP_FileFormat format,XMP_StringPtr filePath,XMP_IO * fileRef,XMPFiles * parent)175 static bool Plugin_CheckFileFormat_Replacement( XMP_FileFormat format, XMP_StringPtr filePath, XMP_IO* fileRef, XMPFiles* parent )
176 {
177 FileHandlerSharedPtr handler = PluginManager::getFileHandler( format, PluginManager::kReplacementHandler );
178
179 return Plugin_CheckFileFormat( handler, filePath, fileRef, parent );
180 }
181
182 // =================================================================================================
183
Plugin_CheckFolderFormat(FileHandlerSharedPtr handler,const std::string & rootPath,const std::string & gpName,const std::string & parentName,const std::string & leafName,XMPFiles *)184 static bool Plugin_CheckFolderFormat( FileHandlerSharedPtr handler,
185 const std::string & rootPath,
186 const std::string & gpName,
187 const std::string & parentName,
188 const std::string & leafName,
189 XMPFiles * /*parent*/ )
190 {
191 XMP_Bool result = false;
192
193 if ( handler != 0 )
194 {
195 WXMP_Error error;
196 CheckSessionFolderFormatProc checkProc = handler->getModule()->getPluginAPIs()->mCheckFolderFormatProc;
197 checkProc ( handler->getUID().c_str(), rootPath.c_str(), gpName.c_str(), parentName.c_str(), leafName.c_str(), &result, &error );
198 CheckError( error );
199 }
200
201 return ConvertXMP_BoolToBool( result );
202
203 }
204
Plugin_CheckFolderFormat_Standard(XMP_FileFormat format,const std::string & rootPath,const std::string & gpName,const std::string & parentName,const std::string & leafName,XMPFiles * parent)205 static bool Plugin_CheckFolderFormat_Standard( XMP_FileFormat format,
206 const std::string & rootPath,
207 const std::string & gpName,
208 const std::string & parentName,
209 const std::string & leafName,
210 XMPFiles * parent )
211 {
212 FileHandlerSharedPtr handler = PluginManager::getFileHandler( format, PluginManager::kStandardHandler );
213
214 return Plugin_CheckFolderFormat( handler, rootPath, gpName, parentName, leafName, parent );
215 }
216
Plugin_CheckFolderFormat_Replacement(XMP_FileFormat format,const std::string & rootPath,const std::string & gpName,const std::string & parentName,const std::string & leafName,XMPFiles * parent)217 static bool Plugin_CheckFolderFormat_Replacement( XMP_FileFormat format,
218 const std::string & rootPath,
219 const std::string & gpName,
220 const std::string & parentName,
221 const std::string & leafName,
222 XMPFiles * parent )
223 {
224 FileHandlerSharedPtr handler = PluginManager::getFileHandler( format, PluginManager::kReplacementHandler );
225
226 return Plugin_CheckFolderFormat( handler, rootPath, gpName, parentName, leafName, parent );
227 }
228
229 // =================================================================================================
230
231 PluginManager* PluginManager::msPluginManager = 0;
232
PluginManager(const std::string & pluginDir,const std::string & plugins)233 PluginManager::PluginManager( const std::string& pluginDir, const std::string& plugins )
234 : mPluginDir ( pluginDir )
235 {
236
237 const std::size_t count = sizeof(kLibraryExtensions) / sizeof(kLibraryExtensions[0]);
238
239 for ( std::size_t i = 0; i<count; ++i ) {
240 mExtensions.push_back ( std::string ( kLibraryExtensions[i] ) );
241 }
242
243 size_t pos1 = std::string::npos;
244
245 #if XMP_WinBuild
246 // convert to Win kDirChar
247 while ( (pos1 = mPluginDir.find ('/')) != string::npos ) {
248 mPluginDir.replace (pos1, 1, "\\");
249 }
250 #else
251 while ( (pos1 = mPluginDir.find ('\\')) != string::npos ) {
252 mPluginDir.replace (pos1, 1, "/");
253 }
254 #endif
255
256 if ( ! mPluginDir.empty() && Host_IO::Exists( mPluginDir.c_str() ) ) {
257
258 XMP_StringPtr strPtr = plugins.c_str();
259 size_t pos = 0;
260 size_t length = 0;
261
262 for ( ; ; ++strPtr, ++length ) {
263
264 if ( (*strPtr == ',') || (*strPtr == '\0') ) {
265
266 if ( length != 0 ) {
267
268 //Remove white spaces from front
269 while ( plugins[pos] == ' ' ) {
270 ++pos;
271 --length;
272 }
273
274 std::string pluginName;
275 pluginName.assign ( plugins, pos, length );
276
277 //Remove extension from the plugin name
278 size_t found = pluginName.find ( '.' );
279 if ( found != string::npos ) pluginName.erase ( found );
280
281 //Remove white spaces from the back
282 found = pluginName.find ( ' ' );
283 if ( found != string::npos ) pluginName.erase ( found );
284
285 MakeLowerCase ( &pluginName );
286 mPluginsNeeded.push_back ( pluginName );
287
288 //Reset for next plugin
289 pos = pos + length + 1;
290 length = 0;
291
292 }
293
294 if ( *strPtr == '\0' ) break;
295
296 }
297
298 }
299
300 }
301
302 } // PluginManager::PluginManager
303
304 // =================================================================================================
305
~PluginManager()306 PluginManager::~PluginManager()
307 {
308 mPluginDir.clear();
309 mExtensions.clear();
310 mPluginsNeeded.clear();
311 mHandlers.clear();
312 mSessions.clear();
313
314 terminateHostAPI();
315 }
316
317 // =================================================================================================
318
registerHandler(XMP_FileFormat format,FileHandlerSharedPtr handler)319 static bool registerHandler( XMP_FileFormat format, FileHandlerSharedPtr handler )
320 {
321 bool ret = false;
322
323 HandlerRegistry& hdlrReg = HandlerRegistry::getInstance();
324 /*FileHandlerType type =*/ handler->getHandlerType();
325 CheckFileFormatProc chkFileFormat = NULL;
326 CheckFolderFormatProc chkFolderFormat = NULL;
327 XMPFileHandlerCTor hdlCtor = NULL;
328
329 if ( handler->getHandlerFlags() & kXMPFiles_NeedsPreloading )
330 {
331 try
332 {
333 handler->load();
334 }
335 catch ( ... )
336 {
337 return false;
338 }
339 }
340
341 if( handler->getOverwriteHandler() )
342 {
343 //
344 // ctor, checkformat function pointers for replacement handler
345 //
346 hdlCtor = Plugin_MetaHandlerCTor_Replacement;
347 chkFileFormat = Plugin_CheckFileFormat_Replacement;
348 chkFolderFormat = Plugin_CheckFolderFormat_Replacement;
349 }
350 else
351 {
352 //
353 // ctor, checkformat function pointers for standard handler
354 //
355 hdlCtor = Plugin_MetaHandlerCTor_Standard;
356 chkFileFormat = Plugin_CheckFileFormat_Standard;
357 chkFolderFormat = Plugin_CheckFolderFormat_Standard;
358 }
359
360 //
361 // register handler according to its type
362 //
363 switch( handler->getHandlerType() )
364 {
365 case NormalHandler_K:
366 ret = hdlrReg.registerNormalHandler( format, handler->getHandlerFlags(), chkFileFormat,
367 hdlCtor, handler->getOverwriteHandler() );
368 break;
369
370 case OwningHandler_K:
371 ret = hdlrReg.registerOwningHandler( format, handler->getHandlerFlags(), chkFileFormat,
372 hdlCtor, handler->getOverwriteHandler() );
373 break;
374
375 case FolderHandler_K:
376 ret = hdlrReg.registerFolderHandler( format, handler->getHandlerFlags(), chkFolderFormat,
377 hdlCtor, handler->getOverwriteHandler() );
378 break;
379
380 default:
381 break;
382 }
383
384 return ret;
385 }
386
initialize(const std::string & pluginDir,const std::string & plugins)387 void PluginManager::initialize( const std::string& pluginDir, const std::string& plugins )
388 {
389 try
390 {
391 if( msPluginManager == 0 ) msPluginManager = new PluginManager( pluginDir, plugins );
392 msPluginManager->initializeHostAPI();
393
394 msPluginManager->doScan( 2 );
395
396 //
397 // Register all the found plugin based file handler
398 //
399 for( PluginHandlerMap::iterator it = msPluginManager->mHandlers.begin(); it != msPluginManager->mHandlers.end(); ++it )
400 {
401 XMP_FileFormat format = it->first;
402 FileHandlerPair handlers = it->second;
403
404 if( handlers.mStandardHandler != NULL )
405 {
406 registerHandler( format, handlers.mStandardHandler );
407 }
408
409 if( handlers.mReplacementHandler != NULL )
410 {
411 registerHandler( format, handlers.mReplacementHandler );
412 }
413 }
414 }
415 catch( ... )
416 {
417 // Absorb exceptions. This is the plugin-architecture entry point.
418 }
419
420 } // PluginManager::initialize
421
422 // =================================================================================================
423
terminate()424 void PluginManager::terminate()
425 {
426 delete msPluginManager;
427 msPluginManager = 0;
428 ResourceParser::terminate();
429 }
430
431 // =================================================================================================
432
addFileHandler(XMP_FileFormat format,FileHandlerSharedPtr handler)433 void PluginManager::addFileHandler( XMP_FileFormat format, FileHandlerSharedPtr handler )
434 {
435 if ( msPluginManager != 0 )
436 {
437 PluginHandlerMap & handlerMap = msPluginManager->mHandlers;
438
439 //
440 // Create placeholder in map for format
441 //
442 if ( handlerMap.find(format) == handlerMap.end() )
443 {
444 FileHandlerPair pair;
445 handlerMap.insert( handlerMap.end(), std::pair<XMP_FileFormat, FileHandlerPair>( format, pair) );
446 }
447
448 //
449 //
450 // if there is already a standard handler or a replacement handler for the file format
451 // then use the one with the highest version. If both versions are the same the first one wins.
452 //
453 FileHandlerSharedPtr& existingHandler =
454 handler->getOverwriteHandler() ? handlerMap[format].mReplacementHandler : handlerMap[format].mStandardHandler;
455
456 if( ! existingHandler )
457 {
458 existingHandler = handler;
459 }
460 else
461 {
462 if( existingHandler->getUID() == handler->getUID() )
463 {
464 if( existingHandler->getVersion() < handler->getVersion() )
465 {
466 existingHandler = handler; // replace older handler
467 }
468 }
469 else
470 {
471 // TODO: notify client that two plugin handlers try to handle the same file format
472 // -> need access to the global notification handler
473 }
474 }
475 }
476 }
477
478 // =================================================================================================
479
getFileHandler(XMP_FileFormat format,HandlerPriority priority)480 FileHandlerSharedPtr PluginManager::getFileHandler( XMP_FileFormat format, HandlerPriority priority /*= kStandardHandler*/ )
481 {
482 if ( msPluginManager != 0 )
483 {
484 PluginHandlerMap::iterator it = msPluginManager->mHandlers.find( format );
485
486 if( it != msPluginManager->mHandlers.end() )
487 {
488 if( priority == kStandardHandler )
489 {
490 return it->second.mStandardHandler;
491 }
492 else if( priority == kReplacementHandler )
493 {
494 return it->second.mReplacementHandler;
495 }
496 }
497 }
498
499 return FileHandlerSharedPtr();
500 }
501
502 // =================================================================================================
503
504 static XMP_ReadWriteLock sSessionMapPluginManagerRWLock;
505
addHandlerInstance(SessionRef session,FileHandlerInstancePtr handler)506 void PluginManager::addHandlerInstance( SessionRef session, FileHandlerInstancePtr handler )
507 {
508 if ( msPluginManager != 0 ) {
509 XMP_AutoLock lock(&sSessionMapPluginManagerRWLock, kXMP_WriteLock);
510 SessionMap & sessionMap = msPluginManager->mSessions;
511 if ( sessionMap.find(session) == sessionMap.end() ) {
512 sessionMap[session] = handler;
513 }
514 }
515 }
516
517 // =================================================================================================
518
removeHandlerInstance(SessionRef session)519 void PluginManager::removeHandlerInstance( SessionRef session )
520 {
521 if ( msPluginManager != 0 ) {
522 XMP_AutoLock lock(&sSessionMapPluginManagerRWLock, kXMP_WriteLock);
523 SessionMap & sessionMap = msPluginManager->mSessions;
524 sessionMap.erase ( session );
525 }
526 }
527
528 // =================================================================================================
529
getHandlerInstance(SessionRef session)530 FileHandlerInstancePtr PluginManager::getHandlerInstance( SessionRef session )
531 {
532 FileHandlerInstancePtr ret = 0;
533 if ( msPluginManager != 0 ) {
534 XMP_AutoLock lock(&sSessionMapPluginManagerRWLock, kXMP_ReadLock);
535 ret = msPluginManager->mSessions[session];
536 }
537 return ret;
538 }
539
540 // =================================================================================================
541
getHandlerPriority(FileHandlerInstancePtr handler)542 PluginManager::HandlerPriority PluginManager::getHandlerPriority( FileHandlerInstancePtr handler )
543 {
544 if( handler != NULL )
545 {
546 for( PluginHandlerMap::iterator it=msPluginManager->mHandlers.begin();
547 it != msPluginManager->mHandlers.end(); it++ )
548 {
549 if( it->second.mStandardHandler == handler->GetHandlerInfo() ) return kStandardHandler;
550 if( it->second.mReplacementHandler == handler->GetHandlerInfo() ) return kReplacementHandler;
551 }
552 }
553
554 return kUnknown;
555 }
556
557 // =================================================================================================
558
CheckPluginArchitecture(XMLParserAdapter * xmlParser)559 static bool CheckPluginArchitecture ( XMLParserAdapter * xmlParser ) {
560
561 #if XMP_MacBuild
562 bool okArchitecture = true; // Missing Architecture attribute means load on Mac.
563 #else
564 bool okArchitecture = false; // Missing Architecture attribute means do not load elsewhere.
565 #endif
566
567 #if XMP_64
568 const char * nativeArchitecture = "x64";
569 #else
570 const char * nativeArchitecture = "x86";
571 #endif
572
573 size_t i, limit;
574 XML_Node & xmlTree = xmlParser->tree;
575 XML_NodePtr rootElem = 0;
576
577 // Find the outermost XML element and see if it is PluginResource.
578 for ( i = 0, limit = xmlTree.content.size(); i < limit; ++i ) {
579 if ( xmlTree.content[i]->kind == kElemNode ) {
580 rootElem = xmlTree.content[i];
581 break;
582 }
583 }
584
585 if ( (rootElem == 0) || (rootElem->name != "PluginResource") ) return okArchitecture;
586
587 // Look for the Architecture attribute and see if it matches.
588
589 XML_NodePtr archAttr = 0;
590 for ( i = 0, limit = rootElem->attrs.size(); i < limit; ++i ) {
591 if ( rootElem->attrs[i]->name == "Architecture" ) {
592 archAttr = rootElem->attrs[i];
593 break;
594 }
595 }
596
597 if ( archAttr != 0 ) okArchitecture = (archAttr->value == nativeArchitecture);
598
599 return okArchitecture;
600
601 } // CheckPluginArchitecture
602
603 // =================================================================================================
604
loadResourceFile(ModuleSharedPtr module)605 void PluginManager::loadResourceFile( ModuleSharedPtr module )
606 {
607
608 OS_ModuleRef moduleRef = LoadModule ( module->getPath(), true );
609
610 if ( moduleRef != 0 ) {
611
612 XMLParserAdapter* parser = 0;
613
614 try {
615
616 std::string buffer;
617 if ( GetResourceDataFromModule ( moduleRef, kResourceName_UIDs, "txt", buffer ) ) {
618
619 ResourceParser::initialize(); // Initialize XMPAtoms before processing resource file.
620
621 parser = XMP_NewExpatAdapter ( ExpatAdapter::kUseGlobalNamespaces );
622 parser->ParseBuffer ( (XMP_Uns8*)buffer.c_str(), buffer.size(), true );
623
624 if ( CheckPluginArchitecture ( parser ) ) {
625 ResourceParser resource ( module );
626 resource.parseElementList ( &parser->tree, true );
627 }
628
629 delete parser;
630
631 }
632
633 } catch ( ... ) {
634
635 if ( parser != 0 ) delete parser;
636 // Otherwise ignore errors.
637
638 }
639
640 UnloadModule ( moduleRef, true );
641
642 }
643
644 } // PluginManager::loadResourceFile
645
646 // =================================================================================================
647
scanRecursive(const std::string & tempPath,std::vector<std::string> & ioFoundLibs,XMP_Int32 inLevel,XMP_Int32 inMaxNestingLevel)648 void PluginManager::scanRecursive( const std::string & tempPath, std::vector<std::string>& ioFoundLibs, XMP_Int32 inLevel, XMP_Int32 inMaxNestingLevel )
649 {
650 ++inLevel;
651 Host_IO::AutoFolder aFolder;
652 if ( Host_IO::GetFileMode( tempPath.c_str() ) != Host_IO::kFMode_IsFolder ) return;
653
654 aFolder.folder = Host_IO::OpenFolder( tempPath.c_str() );
655 std::string childPath, childName;
656
657 while ( Host_IO::GetNextChild ( aFolder.folder, &childName ) ) {
658
659 // Make sure the children of CONTENTS are legit.
660 childPath = tempPath;
661 childPath += kDirChar;
662 childPath += childName;
663 Host_IO::FileMode clientMode = Host_IO::GetFileMode ( childPath.c_str() );
664
665 bool okFolder = (clientMode == Host_IO::kFMode_IsFolder);
666 #if XMP_MacBuild
667 if ( okFolder ) okFolder = ( ! IsValidLibrary ( childPath ) );
668 #endif
669
670 // only step into non-packages (neither bundle nor framework) on Mac
671 if ( okFolder ) {
672
673 if ( inLevel < inMaxNestingLevel ) {
674 scanRecursive ( childPath + kDirChar, ioFoundLibs, inLevel, inMaxNestingLevel );
675 }
676
677 } else {
678
679 if ( childName[0] == '~' ) continue; // ignore plug-ins like "~PDFL.xpi"
680
681 std::string fileExt;
682 XMP_StringPtr extPos = childName.c_str() + childName.size();
683 for ( ; (extPos != childName.c_str()) && (*extPos != '.'); --extPos ) {}
684 if ( *extPos == '.' ) {
685 fileExt.assign ( extPos+1 );
686 MakeLowerCase ( &fileExt );
687 }
688
689 StringVec::const_iterator iterFound =
690 std::find_if ( mExtensions.begin(), mExtensions.end(),
691 [&fileExt](const std::string& file_ext){ return file_ext == fileExt; });
692
693 if ( iterFound != mExtensions.end() ) {
694
695 //Check if the found plugin is present in the user's demanding plugin list.
696 childName.erase ( extPos - childName.c_str() );
697 MakeLowerCase ( &childName );
698
699 StringVec::const_iterator pluginNeeded =
700 std::find_if ( mPluginsNeeded.begin(), mPluginsNeeded.end(),
701 [&childName](const std::string& child_name){ return child_name == childName; });
702
703 if ( (pluginNeeded != mPluginsNeeded.end()) || mPluginsNeeded.empty() ) {
704 ioFoundLibs.push_back ( childPath );
705 }
706
707 }
708
709 }
710
711 }
712
713 aFolder.Close();
714
715 } // PluginManager::scanRecursive
716
717 // =================================================================================================
718
doScan(const XMP_Int32 inMaxNumOfNestedFolder)719 void PluginManager::doScan( const XMP_Int32 inMaxNumOfNestedFolder )
720 {
721 XMP_Assert(inMaxNumOfNestedFolder > 0);
722 if ( inMaxNumOfNestedFolder < 1 ) return; // noop, wrong parameter
723
724 // scan directory
725 std::vector<std::string> foundLibs;
726 XMP_Int32 iteration = 0;
727 scanRecursive ( mPluginDir, foundLibs, iteration, inMaxNumOfNestedFolder );
728
729 // add found modules
730 std::vector<std::string>::const_iterator iter = foundLibs.begin();
731 std::vector<std::string>::const_iterator iterEnd = foundLibs.end();
732 for ( ; iter != iterEnd; ++iter ) {
733 std::string path ( *iter );
734 ModuleSharedPtr module ( new Module ( path ) );
735 loadResourceFile ( module );
736 }
737
738 } // PluginManager::doScan
739
740 // =================================================================================================
741
getHostAPI(XMP_Uns32 version)742 HostAPIRef PluginManager::getHostAPI( XMP_Uns32 version )
743 {
744 HostAPIRef hostAPI = NULL;
745
746 if( msPluginManager == NULL ) return NULL;
747 if( version < 1 ) return NULL;
748
749 HostAPIMap::iterator iter = msPluginManager->mHostAPIs.find( version );
750
751 if( iter != msPluginManager->mHostAPIs.end() )
752 {
753 hostAPI = iter->second;
754 }
755
756 return hostAPI;
757 }
758
759 // =================================================================================================
760
terminateHostAPI()761 void PluginManager::terminateHostAPI()
762 {
763 for( HostAPIMap::iterator it = msPluginManager->mHostAPIs.begin(); it != msPluginManager->mHostAPIs.end(); ++it )
764 {
765 XMP_Uns32 version = it->first;
766 HostAPIRef hostAPI = it->second;
767
768 switch( version )
769 {
770 case 1:
771 case 2:
772 case 3:
773 case 4:
774 {
775 delete hostAPI->mFileIOAPI;
776 delete hostAPI->mStrAPI;
777 delete hostAPI->mAbortAPI;
778 delete hostAPI->mStandardHandlerAPI;
779 delete hostAPI;
780 }
781 break;
782
783 default:
784 {
785 delete hostAPI;
786 }
787 }
788 }
789 }
790
initializeHostAPI()791 void PluginManager::initializeHostAPI()
792 {
793 HostAPIRef hostAPI = NULL;
794
795
796 for ( int i = 0; i < XMP_HOST_API_VERSION_4; i++ )
797 {
798 hostAPI = new HostAPI();
799 hostAPI->mSize = sizeof( HostAPI );
800 hostAPI->mVersion = i + 1;
801
802 switch( hostAPI->mVersion )
803 {
804 case 1:
805 SetupHostAPI_V1( hostAPI );
806 break;
807
808 case 2:
809 SetupHostAPI_V2( hostAPI );
810 break;
811
812 case 3:
813 SetupHostAPI_V3( hostAPI );
814 break;
815
816 default:
817 case 4:
818 SetupHostAPI_V4( hostAPI );
819 break;
820 }
821
822 msPluginManager->mHostAPIs[ hostAPI->mVersion ] = hostAPI;
823 }
824 }
825
826 } // namespace XMP_PLUGIN
827