/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ /* * plugin.cpp * * Xfe implementation of unix plugins. * * dp Suresh */ #include "mozilla.h" #include "xfe.h" #include #include #include #include #include #include #include #include "np.h" #include "nppg.h" #include "prlink.h" #include "prthread.h" #include "prlog.h" #ifdef NSPR20 #include "prerror.h" #endif /* NSPR20 */ #include "pref_helpers.h" #include "edt.h" #ifdef JAVA #include "java.h" #endif #include "obsolete/probslet.h" #include "npglue.h" EXTERN void fe_GetProgramDirectory(char *path, int len); /* for XP_GetString() */ #include extern int XFE_PLUGIN_NO_PLUGIN; extern int XFE_PLUGIN_CANT_LOAD; #ifdef SCO_SV #include "mcom_db.h" /* for MAXPATHLEN */ #endif /* extern from commands.c */ EXTERN NET_StreamClass *fe_MakeSaveAsStream (int format_out, void *data_obj, URL_Struct *url_struct, MWContext *context); #define DEFAULT_LEGACY_PLUGIN_PATH "/usr/local/lib/netscape/plugins" /* Things that are written to the "plugin-list" file */ #define PLUGIN_NAME_PARAM "pluginName=" #define PLUGIN_DESC_PARAM "pluginDescription=" #ifdef X_PLUGINS typedef struct NPX_MimeInfo { char *name; char *extensions; char *description; } NPX_MimeInfo; typedef struct NPX_PlugIn { char *filename; char *pluginName; char *pluginDesc; time_t modifyTime; char found; char Delete; int numberOfOpens; PRLibrary *dlopen_obj; NPError(*load)(NPNetscapeFuncs *, NPPluginFuncs *); NPError(*shutdown)(); NPError(*getvalue)(void *, NPPVariable variable, void *value); NPPluginFuncs fctns; int numMimeEntries; NPX_MimeInfo *mimeEntries; np_handle* handle; } NPX_PlugIn; typedef struct NPX_PlugInList { int num; int max; NPX_PlugIn *plugins; } NPX_PlugInList; static NPX_PlugInList *pluginList; /* Forward declarations */ static NPX_PlugIn *findPluginInfoFromName(NPX_PlugInList *list, char *pluginName); /*---------------------- Mailcap handling functions -------------------- */ static void fe_AddCinfo(char *mimeType) { NET_cdataStruct *cd; cd = NET_cdataCreate(); cd->ci.type = 0; cd->is_external = 1; cd->is_local = 0; /* This is internal; only for user to view */ StrAllocCopy(cd->ci.type, mimeType); NET_cdataAdd(cd); } static NET_cdataStruct * fe_GetCinfo(char *mimeType) { NET_cdataStruct *cd_item = NULL; XP_List *infoList = cinfo_MasterListPointer(); while ((cd_item = (NET_cdataStruct *) XP_ListNextObject(infoList))) { if (cd_item->ci.type && !strcmp(mimeType, cd_item->ci.type)) /* Found */ break; } return(cd_item); } static NET_mdataStruct * fe_GetMailcapEntry(char *mimeType) { return(fe_helpers_get_mailcap_from_type(mimeType)); } static char * fe_MakePluginXmodeEntry(char *pluginName) { return (PR_smprintf("%s%s", NET_COMMAND_PLUGIN, pluginName)); } static void fe_AddPluginMailcapEntry(char *mimeType, char *pluginName) { char *buf = NULL; buf = fe_MakePluginXmodeEntry(pluginName); if (!buf) return; fe_helpers_add_new_mailcap_data(mimeType, NULL, NULL, buf, 1); if (buf) XP_FREE(buf); } #endif /* X_PLUGINS */ XP_Bool fe_IsMailcapEntryPlugin(NET_mdataStruct *md_item) { if (!md_item || !md_item->xmode) return(False); return (!strncmp(md_item->xmode, NET_COMMAND_PLUGIN, strlen(NET_COMMAND_PLUGIN))); } char * fe_GetPluginNameFromMailcapEntry(NET_mdataStruct *md_item) { if (!fe_IsMailcapEntryPlugin(md_item)) return(NULL); return (md_item->xmode+strlen(NET_COMMAND_PLUGIN)); } /* * fe_GetMimetypeInfoFromPlugin: * Given a plugin name and a mime type that this plugin supports, return * a pointer to the description text and the extensions text. * WARNING: Caller should not modify or free the returned description * or extension string. */ int fe_GetMimetypeInfoFromPlugin(char *pluginName, char *mimetype, char **r_desc, char **r_ext) { int ret = -1; #ifdef X_PLUGINS int i; NPX_PlugIn *p = NULL; NPX_MimeInfo *m = NULL; if (!mimetype || !*mimetype || !pluginName || !*pluginName) return(ret); p = findPluginInfoFromName(pluginList, pluginName); if (!p) return(ret); i = p->numMimeEntries; m = p->mimeEntries; while (i > 0) { if (!strcmp(mimetype, m->name)) break; i--; m++; } if (i > 0) { /* Found the mimetype for plugin */ if (r_desc) *r_desc = m->description; if (r_ext) *r_ext = m->extensions; ret = 0; } #endif /* X_PLUGINS */ return(ret); } #ifdef X_PLUGINS /*---------------------------------------------------------------------- */ static char *skipSpaces(char *str) { while (*str != '\0' && isspace(*str)) { str++; } return str; } static char *scanToken(char *str, char *buf, int len, char *stopChars, Bool noSpacesOnOutput) { int pos = 0; str = skipSpaces(str); while (*str != '\0') { while (*str != '\0' && ! isspace(*str) && (stopChars == NULL || strchr(stopChars, *str) == NULL)) { buf[pos++] = *str++; } str = skipSpaces(str); if (*str == '\0' || stopChars == NULL || strchr(stopChars, *str) != NULL) { break; } if (! noSpacesOnOutput) { buf[pos++] = ' '; } } buf[pos] = '\0'; return str; } static NPX_PlugIn *findPluginInfo(NPX_PlugInList *list, char *filename) { int i; if (!list) return (NULL); for (i = 0; i < list->num; i++) { if (strcmp(list->plugins[i].filename, filename) == 0) { return(&list->plugins[i]); } } return(NULL); } static NPX_PlugIn * findPluginInfoFromName(NPX_PlugInList *list, char *pluginName) { int i; if (!list) return (NULL); for (i = 0; i < list->num; i++) { if (strcmp(list->plugins[i].pluginName, pluginName) == 0) { return(&list->plugins[i]); } } return(NULL); } static NPX_PlugIn *getNewPluginInfo(NPX_PlugInList *list, char *filename) { NPX_PlugIn *info; if (list->num == list->max) { list->max *= 2; list->plugins = (NPX_PlugIn *) realloc(list->plugins, list->max * sizeof(NPX_PlugIn)); } info = &list->plugins[list->num++]; info->filename = strdup(filename); info->mimeEntries = NULL; info->found = 0; info->Delete = 0; info->numMimeEntries = 0; info->numberOfOpens = 0; info->pluginName = NULL; info->pluginDesc = NULL; info->dlopen_obj = NULL; info->handle = NULL; info->fctns.size = sizeof(NPPluginFuncs); return info; } static void clearPluginInfo(NPX_PlugIn *info) { int i; NPX_MimeInfo *pMime; pMime = info->mimeEntries; for (i = 0; i < info->numMimeEntries; i++) { free(pMime->name); free(pMime->extensions); if (pMime->description) free(pMime->description); pMime++; } free(info->mimeEntries); if (info->pluginName) free(info->pluginName); if (info->pluginDesc) free(info->pluginDesc); info->found = 0; info->Delete = 0; info->numMimeEntries = 0; info->numberOfOpens = 0; info->dlopen_obj = NULL; info->mimeEntries = NULL; info->pluginName = 0; info->pluginDesc = 0; } static int parsePluginDescription(NPX_PlugIn *currentInfo, char *str) { char buf[1000]; int maxMimeEntries; NPX_MimeInfo *mimeEntry; maxMimeEntries = 2; currentInfo->mimeEntries = (NPX_MimeInfo *) malloc(2 * sizeof(NPX_MimeInfo)); currentInfo->numMimeEntries = 0; while (1) { str = scanToken(str, buf, sizeof(buf), ":", FALSE); if (buf[0] == '\0' || *str != ':') { break; } str++; if (currentInfo->numMimeEntries == maxMimeEntries) { maxMimeEntries *= 2; currentInfo->mimeEntries = (NPX_MimeInfo *) realloc(currentInfo->mimeEntries, maxMimeEntries * sizeof(NPX_MimeInfo)); } mimeEntry = ¤tInfo->mimeEntries[currentInfo->numMimeEntries++]; mimeEntry->name = strdup(buf); mimeEntry->description = NULL; mimeEntry->extensions = NULL; str = scanToken(str, buf, sizeof(buf), ";:", TRUE); mimeEntry->extensions = strdup(buf); if (*str == ':') { str++; str = scanToken(str, buf, sizeof(buf), ";", FALSE); mimeEntry->description = strdup(buf); } #if 0 else { /* Use mimetype for mime description */ mimeEntry->description = strdup(mimeEntry->name); } #endif /* 0 */ if (*str != ';') { break; } str++; } return (currentInfo->numMimeEntries == 0); } static void updateMimeInfo(NPX_PlugIn *plugin) { int i; NPX_MimeInfo *pMime = plugin->mimeEntries; if (!plugin->pluginName) plugin->pluginName = fe_Basename(XP_STRDUP(plugin->filename)); NPL_RegisterPluginFile(plugin->pluginName, plugin->filename, plugin->pluginDesc, (void *)plugin); for (i = 0; i < plugin->numMimeEntries; i++) { NPL_RegisterPluginType(pMime->name, pMime->extensions, pMime->description?pMime->description:pMime->name, NULL, (void *)plugin, FALSE); pMime++; } } static NPX_PlugIn *readPluginInfo(NPX_PlugInList *list, char *filename) { struct stat buf; NPX_PlugIn *currentInfo; char *(*fct)(void); NPError (*getvalue)(void *, int, void *); char *newInfo; PRLibrary *obj; if (stat(filename, &buf) != 0 || (buf.st_mode & S_IFREG) != S_IFREG) { return NULL; } currentInfo = findPluginInfo(list, filename); if (currentInfo != NULL) { /* currentInfo could have been filled in here because of * 1. The plugin was in the plugin-list. (currentInfo->found == 0) * 2. This is caused by a re-scan of the plugins directory. * (currentInfo->found == 1). * In this case, we can do a lot of things smart but since we * already have registered the plugin, we need to change the backed * too. That isn't supported yet like unregistering a plugin. * So we will let it go along as far it can and let fate decide... */ if (currentInfo->found) return(currentInfo); currentInfo->Delete = 0; if (currentInfo->modifyTime == buf.st_mtime) { currentInfo->found = 1; updateMimeInfo(currentInfo); return currentInfo; } clearPluginInfo(currentInfo); } if ((obj = PR_LoadLibrary(filename)) != NULL) { #ifndef NSPR20 fct = (char *(*)())PR_FindSymbol("NP_GetMIMEDescription", obj); #else fct = (char *(*)())PR_FindSymbol(obj, "NP_GetMIMEDescription"); #endif /* NSPR20 */ if (fct == NULL || (newInfo = (*fct)()) == NULL) { int err = PR_UnloadLibrary(obj); PR_ASSERT(err == 0); return NULL; } if (currentInfo == NULL) { currentInfo = getNewPluginInfo(list, filename); } if (parsePluginDescription(currentInfo, newInfo)) { int err = PR_UnloadLibrary(obj); PR_ASSERT(err == 0); currentInfo->Delete = 1; return NULL; } #ifndef NSPR20 getvalue = (NPError (*)(void *, int, void *)) PR_FindSymbol("NP_GetValue", obj); #else getvalue = (NPError (*)(void *, int, void *)) PR_FindSymbol(obj, "NP_GetValue"); #endif /* NSPR20 */ if (getvalue != NULL) { char *value; NPError err; err = (*getvalue)(NULL, NPPVpluginNameString, (void *) &value); if (err == NPERR_NO_ERROR) currentInfo->pluginName = strdup(value); else currentInfo->pluginName = fe_Basename(strdup(currentInfo->filename)); err = (*getvalue)(NULL, NPPVpluginDescriptionString, (void *) &value); if (err == NPERR_NO_ERROR) currentInfo->pluginDesc = strdup(value); } currentInfo->modifyTime = buf.st_mtime; currentInfo->found = 1; updateMimeInfo(currentInfo); { int err = PR_UnloadLibrary(obj); PR_ASSERT(err == 0); } return currentInfo; } else { fprintf (stderr, XP_GetString(XFE_PLUGIN_CANT_LOAD), PR_GetErrorString(), filename); } return NULL; } static int readPluginList(NPX_PlugInList *list, char *filename) { FILE *in; int versionNumber; char buf[10000]; char fileNameBuf[MAXPATHLEN]; char timeBuf[20]; NPX_PlugIn *pInfo = NULL; char *str; if ((in = fopen(filename, "r")) != NULL) { if (fgets(buf, sizeof(buf), in) != NULL && strlen(buf) >= 20 && strncmp(buf, "PluginList Version ", 19) == 0) { /* looking for header, which contains id, version, number of elements */ versionNumber = atoi(&buf[19]); if (versionNumber != 1) { fclose(in); return 1; } while (fgets(buf, sizeof(buf), in) != NULL) { if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; if (!strncmp(buf, PLUGIN_NAME_PARAM, strlen(PLUGIN_NAME_PARAM))) { if (pInfo) pInfo->pluginName = strdup(&buf[strlen(PLUGIN_NAME_PARAM)]); continue; } if (!strncmp(buf, PLUGIN_DESC_PARAM, strlen(PLUGIN_DESC_PARAM))) { if (pInfo) pInfo->pluginDesc = strdup(&buf[strlen(PLUGIN_DESC_PARAM)]); continue; } str = scanToken(buf, fileNameBuf, sizeof(fileNameBuf), NULL, FALSE); if (fileNameBuf == '\0') { continue; } pInfo = findPluginInfo(list, fileNameBuf); if (pInfo == NULL) { pInfo = getNewPluginInfo(list, fileNameBuf); } else { clearPluginInfo(pInfo); } str = scanToken(str, timeBuf, sizeof(timeBuf), NULL, FALSE); if (timeBuf[0] == '\0') { continue; } pInfo->modifyTime = atoi(timeBuf); parsePluginDescription(pInfo, str); } } fclose(in); } return 1; } static int writePluginList(NPX_PlugInList *list, char *filename) { FILE *out; int i; int j; NPX_PlugIn *pInfo; NPX_MimeInfo *pMime; if ((out = fopen(filename, "w")) != NULL) { fputs("PluginList Version 1\n", out); pInfo = list->plugins; for (i = 0; i < list->num; i++) { if (pInfo->found && ! pInfo->Delete && pInfo->numMimeEntries > 0) { fprintf(out, "%s %d", pInfo->filename, pInfo->modifyTime); pMime = pInfo->mimeEntries; for (j = 0; j < pInfo->numMimeEntries; j++) { fprintf(out, " %s: %s", pMime->name, pMime->extensions); if (pMime->description) fprintf(out, ":%s", pMime->description); fputs(";", out); pMime++; } fputs("\n", out); if (pInfo->pluginName && *pInfo->pluginName) fprintf(out, "%s%s\n", PLUGIN_NAME_PARAM, pInfo->pluginName); if (pInfo->pluginDesc && *pInfo->pluginDesc) fprintf(out, "%s%s\n", PLUGIN_DESC_PARAM, pInfo->pluginDesc); } pInfo++; } fclose(out); return 0; } return 1; } static void getPluginsFromDirectory(NPX_PlugInList *list, char *directoryName) { DIR *dir; char filename[MAXPATHLEN]; char *nameptr; struct dirent *dp; #ifdef JAVA /* Add directory to the java backend so that it can find java plugins */ LJ_AddToClassPath(directoryName); #endif /* JAVA */ if ((dir = opendir(directoryName)) != NULL) { strcpy(filename, directoryName); nameptr = &filename[strlen(filename)]; *nameptr++ = '/'; while ((dp = readdir(dir)) != NULL) { if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; strcpy(nameptr, dp->d_name); if (fe_isDir(filename)) getPluginsFromDirectory(list, filename); if (!strcmp(dp->d_name, "libc.so.1")) continue; /* * Look for Composer (Editor) plugins: * the local filename has form: cp.[zip|jar] */ if (strncmp(dp->d_name, "cp", 2) == 0 && (fe_StrEndsWith(dp->d_name, ".zip") || fe_StrEndsWith(dp->d_name, ".jar")) ) { #ifdef EDITOR #ifdef DEBUG_mcafee printf(" Found editor plugin \"%s\" in %s.\n", filename, directoryName); #endif EDT_RegisterPlugin(filename); #endif continue; } /* Ignore .class and .zip files */ if (fe_StrEndsWith(dp->d_name, ".class") || fe_StrEndsWith(dp->d_name, ".zip")) continue; readPluginInfo(list, filename); #ifdef DEBUG_mcafee printf(" Found plugin \"%s\" in %s.\n", filename, directoryName); #endif } closedir(dir); } } static void getPluginsFromPath(NPX_PlugInList *list, char *path) { char *str = path; char directoryName[MAXPATHLEN]; while (*str != '\0') { str = scanToken(str, directoryName, sizeof(directoryName), ":", FALSE); if (directoryName[0] != '\0') { #ifdef DEBUG_mcafee printf("Searching in %s.\n", directoryName); #endif getPluginsFromDirectory(list, directoryName); } if (*str == ':') { str++; } } } static NPX_PlugInList *getPluginList(int numFiles) { NPX_PlugInList *list; list = (NPX_PlugInList *) malloc(sizeof(NPX_PlugInList)); list->num = 0; list->max = numFiles; list->plugins = (NPX_PlugIn *) malloc(numFiles * sizeof(NPX_PlugIn)); return list; } #ifdef DEBUG_dp static void dumpPluginInfo(NPX_PlugIn *info) { int i; printf("filename: %s time: %d\n", info->filename, info->modifyTime); for (i = 0; i < info->numMimeEntries; i++) { printf(" mimetype: %s extensions: %s\n", info->mimeEntries[i].name, info->mimeEntries[i].extensions); } printf("\n"); } #endif #endif /* X_PLUGINS */ void FE_RegisterPlugins() { #ifdef X_PLUGINS char filename[MAXPATHLEN]; char newFilename[MAXPATHLEN]; char oldFilename[MAXPATHLEN]; char *npxPluginPath = getenv("NPX_PLUGIN_PATH"); char *mozHome = getenv("MOZILLA_HOME"); char *pluginPath = NULL; char *home = getenv ("HOME"); if (!home) home = ""; else if (!strcmp (home, "/")) home = ""; /* Algorithm for searching for plugins is: if $NPX_PLUGIN_PATH Use that else Build up a colon-delimited search string like /usr/local/lib/netscape/plugins:$MOZILLA_HOME/plugins: $HOME/.netscape/plugins with last directory overriding other directories, since they all get searched. */ if(npxPluginPath) { pluginPath = npxPluginPath; } else { /* Stuff in $MOZILLA_HOME if it's defined. */ if(mozHome) { pluginPath = PR_smprintf("%s:%s/plugins:%.900s/.netscape/plugins", DEFAULT_LEGACY_PLUGIN_PATH, mozHome, home); } else { /* Try to stuff argv[0] into the path */ char buf[MAXPATHLEN]; buf[0] = '\0'; fe_GetProgramDirectory(buf, sizeof(buf)-1); strncat(buf, "plugins", sizeof(buf)-1 - strlen(buf)); buf[sizeof(buf)-1] = '\0'; pluginPath = PR_smprintf("%s:%s:%.900s/.netscape/plugins", DEFAULT_LEGACY_PLUGIN_PATH, buf, home); } } PR_snprintf(filename, sizeof(filename), "%.900s/.netscape/plugin-list", home); PR_snprintf(newFilename, sizeof(newFilename), "%.900s/.netscape/plugin-list.new", home); PR_snprintf(oldFilename, sizeof(oldFilename), "%.900s/.netscape/plugin-list.BAK", home); if (pluginList == NULL) { pluginList = getPluginList(32); readPluginList(pluginList, filename); } getPluginsFromPath(pluginList, pluginPath); if (writePluginList(pluginList, newFilename) == 0) { rename(filename, oldFilename); rename(newFilename, filename); } if (!npxPluginPath) XP_FREE(pluginPath); /* Free if we used PR_smprintf(). */ fe_RegisterPluginConverters(); #endif /* X_PLUGINS */ } /* * The purpose of this function is * 1. Add md and cinfo list entries for new mimetypes that plugins handle * 2. Enable plugins for the new mimetype that we handle * 3. Change the converter for which there is no plugin to save as. */ void fe_RegisterPluginConverters(void) { NET_cdataStruct *cd_item = NULL; NET_mdataStruct *md_item = NULL; XP_List *infoList = cinfo_MasterListPointer(); #ifdef X_PLUGINS NPX_PlugInList *list = pluginList; int i, n; if (!list) return; /* Register all default plugin converters */ NPL_RegisterDefaultConverters(); /* 1. Add md and cinfo list entries for new mimetypes that plugins handle * 2. Enable plugins for the new mimetype that we handle * */ for (n=0; nnum; n++) { NPX_PlugIn *plugin = &list->plugins[n]; NPX_MimeInfo *pMime = plugin->mimeEntries; for (i = 0; i < plugin->numMimeEntries; i++) { XP_Bool enable = TRUE; cd_item = fe_GetCinfo(pMime->name); md_item = NULL; if (cd_item) { md_item = fe_GetMailcapEntry(cd_item->ci.type); if (md_item) { if (!fe_IsMailcapEntryPlugin(md_item) || (strcmp(fe_GetPluginNameFromMailcapEntry(md_item), plugin->pluginName))) enable = FALSE; /* Eventhough the mailcap entry is not a plugin, if we had changed it to save to Disk because a plugin suddenly was not found, we will change it back to plugin once it was found. */ if (md_item->xmode && !XP_STRCASECMP(md_item->xmode, NET_COMMAND_SAVE_BY_NETSCAPE)) { char *newxmode = fe_MakePluginXmodeEntry(plugin->pluginName); /* Enable the plugin for this mimetype */ enable = TRUE; /* Change the mailcap entry back to plugin */ if (newxmode) { fe_helpers_update_mailcap_entry(md_item->contenttype, md_item, newxmode); if (newxmode) XP_FREE(newxmode); } } } } if (enable) { if (!cd_item) { fe_AddCinfo(pMime->name); } if (!md_item) { fe_AddPluginMailcapEntry(pMime->name, plugin->pluginName); } if (NPL_EnablePlugin(pMime->name, plugin->pluginName, TRUE) != NPERR_NO_ERROR) { #ifdef DEBUG fprintf (stderr, "Cannot enable plugin %s for type %s.\n", plugin->pluginName, pMime->name); #endif /* DEBUG */ } } /* enabled */ pMime++; } } #endif /* X_PLUGINS */ /* 3. Change the converter for which there is no plugin to save as. */ while ((cd_item = (NET_cdataStruct *) XP_ListNextObject(infoList))) { md_item = fe_helpers_get_mailcap_from_type(cd_item->ci.type); if (fe_IsMailcapEntryPlugin(md_item)) { char *pname = fe_GetPluginNameFromMailcapEntry(md_item); if ( #ifdef X_PLUGINS !findPluginInfoFromName(pluginList, pname) #else /* X_PLUGINS */ True /* Plugin info is always not found for NO PLUGIN */ #endif /* X_PLUGINS */ ) { /* We have a plugin entry but no plugin */ fprintf (stderr, XP_GetString(XFE_PLUGIN_NO_PLUGIN), pname, cd_item->ci.type); NET_RegisterContentTypeConverter(cd_item->ci.type, FO_PRESENT, NULL, fe_MakeSaveAsStream ); fe_helpers_update_mailcap_entry(md_item->contenttype, md_item, NET_COMMAND_SAVE_BY_NETSCAPE); } } } } NPPluginFuncs * FE_LoadPlugin(void *pdesc, NPNetscapeFuncs *funcs, np_handle* handle) { #ifdef X_PLUGINS NPX_PlugIn *plugin = (NPX_PlugIn *) pdesc; NPError (*f)(NPNetscapeFuncs *, NPPluginFuncs *); NPError err; if (plugin->dlopen_obj == NULL) { plugin->dlopen_obj = PR_LoadLibrary(plugin->filename); if (plugin->dlopen_obj == NULL) { fprintf(stderr, XP_GetString(XFE_PLUGIN_CANT_LOAD), PR_GetErrorString(), plugin->filename); return NULL; } nsFactoryProc nsGetFactory = (nsFactoryProc)PR_FindSymbol(plugin->dlopen_obj, "NSGetFactory"); if (nsGetFactory != NULL) { // XXX Figure out where this should go: this seems a // little late in the game to be creating the plugin // manager... if (thePluginManager == NULL) { static NS_DEFINE_IID(kIPluginManagerIID, NS_IPLUGINMANAGER_IID); if (nsPluginManager::Create(NULL, kIPluginManagerIID, (void**)&thePluginManager) != NS_OK) return NULL; } PR_ASSERT(thePluginManager != NULL); static NS_DEFINE_IID(kIPluginIID, NS_IPLUGIN_IID); nsIPlugin* userPlugin = NULL; nsresult err = nsGetFactory(kIPluginIID, (nsIFactory**)&userPlugin); handle->userPlugin = userPlugin; plugin->handle = handle; if ((err != NS_OK) || (userPlugin == NULL) || (userPlugin->Initialize((nsIPluginManager*)thePluginManager) != NS_OK)) { PR_UnloadLibrary(plugin->dlopen_obj); plugin->dlopen_obj = NULL; return NULL; } #ifdef LATER // XXX coming soon... // add the plugin directory if successful JVM_AddToClassPathRecursively(csPluginDir); #endif } else { #ifndef NSPR20 f = (NPError(*)(NPNetscapeFuncs *, NPPluginFuncs *)) PR_FindSymbol("NP_Initialize", plugin->dlopen_obj); #else f = (NPError(*)(NPNetscapeFuncs *, NPPluginFuncs *)) PR_FindSymbol(plugin->dlopen_obj, "NP_Initialize"); #endif /* NSPR20 */ if (f == NULL) { int err = PR_UnloadLibrary(plugin->dlopen_obj); PR_ASSERT(err == 0); plugin->dlopen_obj = NULL; return NULL; } plugin->load = f; err = (*f)(funcs, &plugin->fctns); if (err != NPERR_NO_ERROR) { int err = PR_UnloadLibrary(plugin->dlopen_obj); PR_ASSERT(err == 0); plugin->dlopen_obj = NULL; return NULL; } #ifndef NSPR20 plugin->shutdown = (NPError(*)(void)) PR_FindSymbol("NP_Shutdown", plugin->dlopen_obj); #else plugin->shutdown = (NPError(*)(void)) PR_FindSymbol(plugin->dlopen_obj, "NP_Shutdown"); #endif /* NSPR20 */ } } plugin->numberOfOpens++; return &plugin->fctns; #else /* X_PLUGINS */ return (NULL); #endif /* X_PLUGINS */ } void FE_UnloadPlugin(void *pdesc, struct _np_handle* handle) { #ifdef X_PLUGINS NPX_PlugIn *plugin = (NPX_PlugIn *) pdesc; NPError (*f)(void); NPError err; if (plugin->handle) { if (plugin->handle->userPlugin) { nsIPlugin* userPlugin = (nsIPlugin*)plugin->handle->userPlugin; // XXX We should be calling userPlugin->Shutdown() here, // and then we should ping the lib's NSCanUnload() // function before actually unloading the library. XP_VERIFY(userPlugin->Release() == 0); plugin->handle = NULL; } } else { f = plugin->shutdown; if (f) { err = (*f)(); if (err != NPERR_NO_ERROR) { /* XXX There was a error while unloading this plugin. What can we * do. Ignore it for now. */ } } } plugin->numberOfOpens--; if (plugin->numberOfOpens == 0) { int err = PR_UnloadLibrary(plugin->dlopen_obj); PR_ASSERT(err == 0); plugin->dlopen_obj = NULL; } else if (plugin->numberOfOpens < 0) { plugin->numberOfOpens = 0; } #endif /* X_PLUGINS */ } void FE_EmbedURLExit(URL_Struct *urls, int status, MWContext *cx) { } NPError FE_PluginGetValue(void *pdesc, NPNVariable variable, void *r_value) { #ifdef X_PLUGINS NPError ret = NPERR_NO_ERROR; switch (variable) { case NPNVxDisplay: if (r_value) (*(Display **)r_value) = fe_display; break; case NPNVxtAppContext: if (r_value) (*(XtAppContext *)r_value) = fe_XtAppContext; break; default: ret = NPERR_INVALID_PARAM; } return ret; #else /* X_PLUGINS */ return(NPERR_INVALID_PARAM); #endif /* X_PLUGINS */ }