00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 # include <config.h>
00024 #endif
00025
00026 #include "intl.h"
00027 #ifdef __MINGW32__
00028 typedef long __off32_t;
00029 #endif
00030 #include <sys/types.h>
00031 #include <dirent.h>
00032 #include <string.h>
00033 #include <stdlib.h>
00034 #include "globals.h"
00035 #include "defaults.h"
00036 #include "service.h"
00037 #include "plugin.h"
00038 #include "nomodule.h"
00039 #include "value_pair.h"
00040
00041 char *PLUGIN_TYPE_TXT[]={"SERVICE", "UTILITY", "SOUND", "LOG", "GUI", "UNKNOWN"};
00042 char *PLUGIN_STATUS_TXT[]={"Not Loaded",
00043 "Loaded",
00044 "Cannot Load"};
00045
00046 PLUGIN_INFO Plugin_Cannot_Load = {PLUGIN_UNKNOWN,
00047 "Unknown",
00048 "Unknown",
00049 "Unknown",
00050 "Unknown", NULL, NULL, NULL, NULL};
00051
00052 gint compare_plugin_loaded_service(gconstpointer a, gconstpointer b) {
00053 const eb_PLUGIN_INFO *epi=a;
00054 if(epi->service && epi->status==PLUGIN_LOADED && !strcmp( epi->service, (char *)b))
00055 return(0);
00056 return(1);
00057 }
00058
00059 gint compare_plugin_name(gconstpointer a, gconstpointer b) {
00060 const eb_PLUGIN_INFO *epi=a;
00061 if(epi->name && !strcmp( epi->name, (char *)b))
00062 return(0);
00063 return(1);
00064 }
00065
00066 gint compare_plugin_handle(gconstpointer a, gconstpointer b) {
00067 const eb_PLUGIN_INFO *epi=a;
00068 if( epi->Module && epi->Module == (lt_dlhandle )b)
00069 return(0);
00070 return(1);
00071 }
00072
00073
00074 eb_PLUGIN_INFO *FindLoadedPluginByService(char *service)
00075 {
00076 GList *plugins=GetPref(EB_PLUGIN_LIST);
00077 GList *PluginData = g_list_find_custom(plugins, service, compare_plugin_loaded_service);
00078 if(PluginData)
00079 return(PluginData->data);
00080 return(NULL);
00081 }
00082
00083 eb_PLUGIN_INFO *FindPluginByName(char *name)
00084 {
00085 GList *plugins=GetPref(EB_PLUGIN_LIST);
00086 GList *PluginData = g_list_find_custom(plugins, name, compare_plugin_name);
00087 if(PluginData)
00088 return(PluginData->data);
00089 return(NULL);
00090 }
00091
00092 eb_PLUGIN_INFO *FindPluginByHandle(lt_dlhandle *Module)
00093 {
00094 GList *plugins=GetPref(EB_PLUGIN_LIST);
00095 GList *PluginData = g_list_find_custom(plugins, Module, compare_plugin_handle);
00096 if(PluginData)
00097 return(PluginData->data);
00098 return(NULL);
00099 }
00100
00101
00102 void SetPluginInfo(PLUGIN_INFO *pi, char *name, lt_dlhandle Module, PLUGIN_STATUS status, const char *status_desc, char *service, gboolean force)
00103 {
00104 GList *plugins=NULL;
00105 eb_PLUGIN_INFO *epi=NULL;
00106
00107 epi=FindPluginByName(name);
00108 if(!epi) {
00109 epi=g_new0(eb_PLUGIN_INFO, 1);
00110 plugins=GetPref(EB_PLUGIN_LIST);
00111 plugins=g_list_append(plugins, epi);
00112 SetPref(EB_PLUGIN_LIST, plugins);
00113 }
00114 else if(force==TRUE || epi->status!=PLUGIN_LOADED) {
00115 if(epi->service)
00116 free(epi->service);
00117 free(epi->name);
00118 free(epi->pi.brief_desc);
00119 free(epi->pi.full_desc);
00120 free(epi->pi.version);
00121 free(epi->pi.date);
00122 }
00123 else
00124 return;
00125 epi->status=status;
00126 epi->status_desc=status_desc;
00127 if(!pi)
00128 pi=&Plugin_Cannot_Load;
00129 epi->pi.type=pi->type;
00130 epi->pi.brief_desc=strdup(pi->brief_desc);
00131 epi->pi.full_desc=strdup(pi->full_desc);
00132 epi->pi.version=strdup(pi->version);
00133 epi->pi.date=strdup(pi->date);
00134 epi->pi.init=pi->init;
00135 epi->pi.finish=pi->finish;
00136 epi->pi.prefs=pi->prefs;
00137 epi->name=strdup(name);
00138 if(service)
00139 epi->service=strdup(service);
00140 epi->Module=Module;
00141 }
00142
00143
00144 int select_module_entry(const struct dirent *dent) {
00145 int len=0;
00146 char *ext;
00147
00148 len=strlen(dent->d_name);
00149 if(len<4)
00150 return(0);
00151 ext=(char *)dent->d_name;
00152 ext+=(len-3);
00153 eb_debug(DBG_CORE, "select_module_entry: %s[%s]\n", dent->d_name, ext);
00154 if(!strncmp(ext, ".la", 3))
00155 return(1);
00156 return(0);
00157 }
00158
00159 int unload_module(eb_PLUGIN_INFO *epi)
00160 {
00161 int error=0;
00162 char buf[1024];
00163
00164 eb_debug(DBG_CORE, ">Unloading plugin %s\n", epi->name);
00165
00166 if(epi->pi.finish) {
00167 eb_debug(DBG_CORE, "Calling plugins finish function\n");
00168 error=epi->pi.finish();
00169 if(error) {
00170 sprintf(buf, _("Unable to unload plugin %s, still in use?\n"), epi->name);
00171 do_error_dialog(buf, _("Error"));
00172 eb_debug(DBG_CORE, "<Plugin failed to unload\n");
00173 return(-1);
00174 }
00175 }
00176 if(epi->service) {
00177 struct service SERVICE_INFO = { strdup(epi->service), -1, FALSE, FALSE, FALSE, FALSE, NULL };
00178
00179 SERVICE_INFO.sc=eb_nomodule_query_callbacks();
00180 add_service(&SERVICE_INFO);
00181 }
00182 epi->status=PLUGIN_NOT_LOADED;
00183 epi->pi.prefs=NULL;
00184 eb_debug(DBG_CORE, "Closing plugin\n");
00185 if(lt_dlclose(epi->Module)) {
00186 fprintf(stderr, "Error closing plugin: %s\n", lt_dlerror());
00187 }
00188 eb_debug(DBG_CORE, "<Plugin unloaded\n");
00189 return(0);
00190
00191 }
00192
00193 void unload_modules(void) {
00194 GList *plugins=GetPref(EB_PLUGIN_LIST);
00195 for(plugins=GetPref(EB_PLUGIN_LIST); plugins; plugins=plugins->next) {
00196 unload_module(plugins->data);
00197 }
00198 }
00199
00200 int load_module(char *path, char *name)
00201 {
00202 char full_path[1024];
00203 lt_dlhandle Module;
00204 PLUGIN_INFO *plugin_info=NULL;
00205 eb_PLUGIN_INFO *epi=NULL;
00206
00207 sprintf(full_path, "%s/%s", path, name);
00208 eb_debug(DBG_CORE, "Opening module: %s\n", full_path);
00209 Module = lt_dlopen(full_path);
00210 eb_debug(DBG_CORE, "Module: %p\n", Module);
00211
00212
00213 if(!Module) {
00214
00215 SetPluginInfo(NULL, full_path, NULL, PLUGIN_CANNOT_LOAD, lt_dlerror(), NULL, FALSE);
00216 return(-1);
00217 }
00218 plugin_info = (PLUGIN_INFO *)lt_dlsym(Module, "plugin_info");
00219 if(!plugin_info) {
00220 lt_dlclose(Module);
00221
00222 SetPluginInfo(NULL, full_path, NULL, PLUGIN_CANNOT_LOAD, _("Cannot resolve symbol plugin_info"), NULL, FALSE);
00223 return(-1);
00224 }
00225 epi=FindPluginByName(full_path);
00226 if(epi && epi->status==PLUGIN_LOADED) {
00227 lt_dlclose(Module);
00228 eb_debug(DBG_CORE, "Not loading already loaded module %s\n", name);
00229 return(-1);
00230 }
00231 switch(plugin_info->type) {
00232 case PLUGIN_SERVICE:
00233 load_service_plugin(Module, plugin_info, full_path);
00234 break;
00235 case PLUGIN_UTILITY:
00236 load_utility_plugin(Module, plugin_info, full_path);
00237 break;
00238 case PLUGIN_SOUND:
00239 load_sound_plugin(Module, plugin_info, full_path);
00240 break;
00241 case PLUGIN_LOG:
00242 load_log_plugin(Module, plugin_info, full_path);
00243 break;
00244 case PLUGIN_GUI:
00245 load_gui_plugin(Module, plugin_info, full_path);
00246 break;
00247 default:
00248 break;
00249 }
00250 return(0);
00251 }
00252
00253
00254 void load_modules()
00255 {
00256
00257 char buf[1024], *modules_path=NULL, *cur_path=NULL;
00258 char *tok_buf=NULL, *tok_buf_old=NULL;
00259 int n=0, success=0;
00260 struct dirent *dp;
00261 DIR *dirp;
00262
00263 eb_debug(DBG_CORE, ">Entering\n");
00264 modules_path=g_strdup(cGetLocalPref("modules_path"));
00265 tok_buf = g_new0(char, strlen(modules_path)+1);
00266
00267 tok_buf_old=tok_buf;
00268 lt_dlinit();
00269 lt_dlsetsearchpath(modules_path);
00270
00271
00272 #ifdef HAVE_STRTOK_R
00273 cur_path=strtok_r(modules_path, ":", &tok_buf);
00274 #else
00275 cur_path=strtok(modules_path, ":");
00276 #endif
00277 if(!cur_path)
00278 cur_path=MODULE_DIR;
00279 do {
00280 if((dirp = opendir(cur_path)) == NULL)
00281 {
00282 sprintf(buf, _("Cannot open module directory \"%s\""), cur_path);
00283 do_error_dialog(buf, _("Warning"));
00284 buf[0] = '\0';
00285 break;
00286 }
00287 n = 0;
00288 while((dp = readdir(dirp)) != NULL)
00289 {
00290 if( dp == NULL )
00291 {
00292 sprintf(buf, _("Looking for modules in %s"), cur_path);
00293 perror(buf);
00294 continue;
00295 }
00296 else if( select_module_entry( dp ) )
00297 {
00298 n++;
00299 success = load_module(cur_path, dp->d_name);
00300 }
00301 }
00302 if( n == 0 )
00303 {
00304 eb_debug(DBG_CORE, "<No modules found in %s, returning.\n", cur_path);
00305 }
00306 else
00307 {
00308 eb_debug(DBG_CORE, "Loaded %d modules from %s.\n", n, cur_path);
00309 }
00310 closedir(dirp);
00311 #ifdef HAVE_STRTOK_R
00312 } while((cur_path=strtok_r(NULL, ":", &tok_buf)));
00313 #else
00314 } while((cur_path=strtok(NULL, ":")));
00315 #endif
00316
00317 g_free(modules_path);
00318 g_free(tok_buf_old);
00319 eb_debug(DBG_CORE, "Adding idle_check\n");
00320 add_idle_check();
00321 eb_debug(DBG_CORE, "<End services_init\n");
00322 }
00323
00324 int load_service_plugin(lt_dlhandle Module, PLUGIN_INFO *info, char *name)
00325 {
00326 struct service *Service_Info=NULL;
00327 struct service_callbacks *(*query_callbacks)();
00328 int service_id=-1;
00329 eb_PLUGIN_INFO *epi=NULL;
00330 GList *user_prefs=NULL;
00331
00332 Service_Info = lt_dlsym(Module, "SERVICE_INFO");
00333 eb_debug(DBG_CORE, "SERVICE_INFO: %p\n", Service_Info);
00334 if(!Service_Info) {
00335 SetPluginInfo(info, name, NULL, PLUGIN_CANNOT_LOAD, _("Unable to resolve symbol SERVICE_INFO"), NULL, FALSE);
00336 lt_dlclose(Module);
00337 return(-1);
00338 }
00339
00340 epi=FindLoadedPluginByService(Service_Info->name);
00341 if(epi && epi->status==PLUGIN_LOADED) {
00342 fprintf(stderr, _("Not loading module %s, a module for that service is already loaded!\n"), name);
00343 SetPluginInfo(info, name, NULL, PLUGIN_CANNOT_LOAD, _("Service provided by an already loaded plugin"), Service_Info->name, FALSE);
00344 lt_dlclose(Module);
00345 return(-1);
00346 }
00347
00348 query_callbacks = lt_dlsym(Module, "query_callbacks");
00349 if(!query_callbacks) {
00350 SetPluginInfo(info, name, NULL, PLUGIN_CANNOT_LOAD, "Unable to resolve symbol query_callbacks", Service_Info->name, FALSE);
00351 lt_dlclose(Module);
00352 return(-1);
00353 }
00354 if(info->init) {
00355 eb_debug(DBG_CORE, "Executing init for %s\n", info->brief_desc);
00356 info->init();
00357 }
00358 if(info->prefs) {
00359 user_prefs=GetPref(name);
00360 if(user_prefs) {
00361 eb_update_from_value_pair(info->prefs, user_prefs);
00362 }
00363 eb_debug(DBG_MOD, "prefs name: %s\n", info->prefs->widget.entry.name);
00364 }
00365 Service_Info->sc=query_callbacks();
00366
00367 service_id = add_service(Service_Info);
00368 SetPluginInfo(info, name, Module, PLUGIN_LOADED, "", Service_Info->name, TRUE);
00369 eb_debug(DBG_CORE, "Added module:%s, service: %s\n", name, eb_services[service_id].name);
00370 eb_debug(DBG_CORE, "eb_services[%i].sc->read_local_account_config: %p\n", service_id, eb_services[service_id].sc->read_local_account_config);
00371 return(0);
00372 }
00373
00374 int load_utility_plugin(lt_dlhandle Module, PLUGIN_INFO *info, char *name)
00375 {
00376 char buf[1024];
00377 GList *user_prefs=NULL;
00378
00379 eb_debug(DBG_CORE, ">\n");
00380 if(!info->init) {
00381 SetPluginInfo(info, name, NULL, PLUGIN_CANNOT_LOAD, _("No init function defined"), NULL, FALSE);
00382 lt_dlclose(Module);
00383 sprintf(buf, _("init function not defined for utility module %s, unloading module\n"), name);
00384 do_error_dialog(buf, _("Warning"));
00385 return(-1);
00386 }
00387 eb_debug(DBG_CORE, "Executing init for %s\n", info->brief_desc);
00388 info->init();
00389 if(info->prefs) {
00390 user_prefs=GetPref(name);
00391 if(user_prefs) {
00392 eb_update_from_value_pair(info->prefs, user_prefs);
00393 }
00394 eb_debug(DBG_MOD, "prefs name: %s\n", info->prefs->widget.entry.name);
00395 }
00396 SetPluginInfo(info, name, Module, PLUGIN_LOADED, "", NULL, TRUE);
00397 eb_debug(DBG_CORE, "<\n");
00398 return(0);
00399 }
00400
00401 int load_log_plugin(lt_dlhandle Module, PLUGIN_INFO *info, char *name)
00402 {
00403 return(1);
00404 }
00405
00406 int load_sound_plugin(lt_dlhandle Module, PLUGIN_INFO *info, char *name)
00407 {
00408 return(1);
00409 }
00410
00411 int load_gui_plugin(lt_dlhandle Module, PLUGIN_INFO *info, char *name)
00412 {
00413 return(1);
00414 }
00415
00416
00417 int init_menu(char *menu_name, menu_func redraw_menu, ebmType type)
00418 {
00419 menu_data *md=NULL;
00420
00421 md=g_new0(menu_data, 1);
00422 md->menu_items=NULL;
00423 md->redraw_menu=redraw_menu;
00424 md->type=type;
00425 SetPref(menu_name, md);
00426 return(0);
00427 }
00428
00429
00430 int init_menus()
00431 {
00432 init_menu(EB_PROFILE_MENU, rebuild_profile_menu, ebmPROFILEDATA);
00433 init_menu(EB_IMPORT_MENU, rebuild_import_menu, ebmIMPORTDATA);
00434
00435 init_menu(EB_CHAT_WINDOW_MENU, NULL, ebmCONTACTDATA);
00436 init_menu(EB_CONTACT_MENU, NULL, ebmCONTACTDATA);
00437 return(0);
00438 }