Fix test for bug #32625
[gnash.git] / libbase / extension.cpp
blob877c598f04da28e95fe51a7c3fa4ffe4ad8e74cf
1 // extension.cpp: Read and enable plug-in extensions to Flash, for Gnash.
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
4 // Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifdef HAVE_CONFIG_H
22 #include "gnashconfig.h"
23 #endif
25 #if defined(WIN32) || defined(_WIN32)
26 #define LIBLTDL_DLL_IMPORT 1
27 #endif
28 #include <cstring>
29 #include <iostream>
30 #include <sys/types.h>
32 #include "log.h"
33 #include "ltdl.h"
34 #include "sharedlib.h"
35 #include "extension.h"
37 namespace gnash {
38 class as_object;
41 #if defined(WIN32) || defined(_WIN32)
42 int lt_dlsetsearchpath (const char *search_path);
43 int lt_dlinit (void);
44 void * lt_dlsym (lt_dlhandle handle, const char *name);
45 const char *lt_dlerror (void);
46 int lt_dlclose (lt_dlhandle handle);
47 int lt_dlmakeresident (lt_dlhandle handle);
48 lt_dlhandle lt_dlopenext (const char *filename);
49 #endif
51 #if HAVE_DIRENT_H || WIN32==1 // win32 hack
52 # include <dirent.h>
53 # define NAMLEN(dirent) std::strlen((dirent)->d_name)
54 #else
55 # define dirent direct
56 # define NAMLEN(dirent) (dirent)->d_namlen
57 # if HAVE_SYS_NDIR_H
58 # include <sys/ndir.h>
59 # endif
60 # if HAVE_SYS_DIR_H
61 # include <sys/dir.h>
62 # endif
63 # if HAVE_NDIR_H
64 # include <ndir.h>
65 # endif
66 #endif
68 namespace gnash {
70 Extension::Extension()
72 // GNASH_REPORT_FUNCTION;
73 #ifdef LT_DLMUTEX
74 // return lt_dlmutex_register (gnash_mutex_lock, gnash_mutex_unlock,
75 // gnash_mutex_seterror, gnash_mutex_geterror);
76 #endif
77 char *env = std::getenv("GNASH_PLUGINS");
78 if (!env) {
79 _pluginsdir = PLUGINSDIR;
81 else {
82 _pluginsdir = env;
85 log_debug("Plugins path: %s", _pluginsdir);
86 #ifdef HAVE_LTDL
87 lt_dlsetsearchpath(_pluginsdir.c_str());
88 #endif
91 Extension::Extension(const std::string& dir)
93 // GNASH_REPORT_FUNCTION;
94 #ifdef LT_DLMUTEX
95 // return lt_dlmutex_register (gnash_mutex_lock, gnash_mutex_unlock,
96 // gnash_mutex_seterror, gnash_mutex_geterror);
97 #endif
98 _pluginsdir = dir;
99 #ifdef HAVE_LTDL
100 lt_dlsetsearchpath(_pluginsdir.c_str());
101 #endif
104 Extension::~Extension()
106 // GNASH_REPORT_FUNCTION;
109 bool
110 Extension::scanAndLoad(const std::string& dir, as_object &obj)
112 // GNASH_REPORT_FUNCTION;
114 #ifdef HAVE_LTDL
115 lt_dlsetsearchpath(_pluginsdir.c_str());
116 #endif
117 _pluginsdir = dir;
119 return scanAndLoad(obj);
122 bool
123 Extension::scanAndLoad(as_object& where)
125 // GNASH_REPORT_FUNCTION;
127 if (_modules.empty()) {
128 scanDir(_pluginsdir);
131 std::vector<std::string>::iterator it;
132 for (it = _modules.begin(); it != _modules.end(); it++) {
133 const std::string& mod = *it;
134 log_security(_("Loading module: %s from %s"), mod, _pluginsdir);
135 initModule(mod, where);
137 return true;
140 bool
141 Extension::initModule(const std::string& module, as_object &where)
144 SharedLib *sl;
145 std::string symbol(module);
147 log_security(_("Initializing module: \"%s\" from %s"), symbol, _pluginsdir);
149 if (_plugins[module] == 0) {
150 sl = new SharedLib(_pluginsdir + "/" + module, "GNASH_PLUGINS");
151 sl->openLib();
152 _plugins[module] = sl;
153 } else {
154 sl = _plugins[module];
157 symbol.append("_class_init");
159 SharedLib::initentry *symptr = sl->getInitEntry(symbol);
161 if (symptr) {
162 symptr(where);
163 } else {
164 log_error(_("Couldn't get class_init symbol"));
167 return true;
170 bool
171 Extension::initModuleWithFunc(const std::string& module,
172 const std::string& func, as_object &obj)
174 GNASH_REPORT_FUNCTION;
176 SharedLib *sl;
178 log_security(_("Initializing module: \"%s\""), module);
180 if (_plugins[module] == 0) {
181 sl = new SharedLib(module);
182 sl->openLib();
183 _plugins[module] = sl;
184 } else {
185 sl = _plugins[module];
188 SharedLib::initentry *symptr = sl->getInitEntry(func);
190 if (symptr) {
191 symptr(obj);
192 } else {
193 log_error(_("Couldn't get class_init symbol: \"%s\""), func);
196 return true;
199 bool
200 Extension::scanDir()
202 // GNASH_REPORT_FUNCTION;
203 scanDir(_pluginsdir);
204 return true;
207 bool
208 Extension::scanDir(const std::string& dirlist)
210 GNASH_REPORT_FUNCTION;
212 Tok t(dirlist, Sep(":"));
213 for (Tok::iterator i = t.begin(), e = t.end(); i != e; ++i) {
215 const std::string& dir = *i;
217 log_debug(_("Scanning directory \"%s\" for plugins"), dir);
218 DIR *libdir = opendir(dir.c_str());
220 if (!libdir) {
221 log_error(_("Can't open directory %s"), dir);
222 return false;
225 struct dirent *entry;
227 while ((entry = readdir(libdir)) != NULL) {
228 // We only want shared libraries that end with the suffix, otherwise
229 // we get all the duplicates.
230 std::string name(entry->d_name);
232 // Hidden files.
233 if (name.at(0) == '.') {
234 continue;
237 const std::string::size_type pos = name.find_last_of('.');
239 if (pos == std::string::npos) continue;
241 const std::string suffix = name.substr(pos);
242 name.erase(pos);
244 if (suffix == ".so") {
245 log_debug(_("Gnash Plugin name: %s"), name);
246 _modules.push_back(name);
248 else {
249 continue;
253 if (closedir(libdir) != 0) {
254 return false;
257 return true;
260 void
261 Extension::dumpModules()
263 GNASH_REPORT_FUNCTION;
265 std::cerr << _modules.size() << " plugin(s) for Gnash installed" << std::endl;
266 std::vector<std::string>::iterator it;
267 for (it = _modules.begin(); it != _modules.end(); it++) {
268 std::cerr << "Module name is: \"" << *(it) << "\"" << std::endl;
272 } // end of gnash namespace