home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / plugin.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  27.2 KB  |  1,055 lines

  1. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20.  * plugin.c
  21.  *
  22.  * Xfe implementation of unix plugins.
  23.  *
  24.  * dp Suresh <dp@netscape.com>
  25.  */
  26.  
  27. #include "mozilla.h"
  28. #include "xfe.h"
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <ctype.h>
  32. #include <string.h>
  33. #include <sys/types.h>
  34. #include <sys/param.h>
  35. #include <sys/stat.h>
  36. #include "np.h"
  37. #include "nppg.h"
  38. #include "prlink.h"
  39. #include "prthread.h"
  40. #include "prlog.h"
  41. #ifdef NSPR20
  42. #include "prerror.h"
  43. #endif /* NSPR20 */
  44. #include "pref_helpers.h"
  45. #include "edt.h"
  46. #include "java.h"
  47. #include "obsolete/probslet.h"
  48. #include "npglue.h"
  49.  
  50. EXTERN void fe_GetProgramDirectory(char *path, int len);
  51.  
  52. /* for XP_GetString() */
  53. #include <xpgetstr.h>
  54. extern int XFE_PLUGIN_NO_PLUGIN;
  55. extern int XFE_PLUGIN_CANT_LOAD;
  56.  
  57. #ifdef SCO_SV
  58. #include "mcom_db.h"    /* for MAXPATHLEN */
  59. #endif
  60.  
  61. /* extern from commands.c */
  62. EXTERN NET_StreamClass *fe_MakeSaveAsStream (int format_out, void *data_obj,
  63.                          URL_Struct *url_struct,
  64.                          MWContext *context);
  65.  
  66. #define DEFAULT_LEGACY_PLUGIN_PATH "/usr/local/lib/netscape/plugins"
  67.  
  68. /* Things that are written to the "plugin-list" file */
  69. #define PLUGIN_NAME_PARAM    "pluginName="
  70. #define PLUGIN_DESC_PARAM    "pluginDescription="
  71.  
  72. #ifdef X_PLUGINS
  73. typedef struct NPX_MimeInfo {
  74.     char *name;
  75.     char *extensions;
  76.     char *description;
  77. } NPX_MimeInfo;
  78.  
  79. typedef struct NPX_PlugIn {
  80.     char *filename;
  81.     char *pluginName;
  82.     char *pluginDesc;
  83.     time_t modifyTime;
  84.     char found;
  85.     char Delete;
  86.     int numberOfOpens;
  87.     PRLibrary *dlopen_obj;
  88.     NPError(*load)(NPNetscapeFuncs *, NPPluginFuncs *);
  89.     NPError(*shutdown)();
  90.     NPError(*getvalue)(void *, NPPVariable variable, void *value);
  91.     NPPluginFuncs fctns;
  92.     int numMimeEntries;
  93.     NPX_MimeInfo *mimeEntries;
  94.     np_handle* handle;
  95. } NPX_PlugIn;
  96.  
  97. typedef struct NPX_PlugInList {
  98.     int num;
  99.     int max;
  100.     NPX_PlugIn *plugins;
  101. } NPX_PlugInList;
  102.  
  103. static NPX_PlugInList *pluginList;
  104.  
  105.  
  106. /* Forward declarations */
  107. static NPX_PlugIn *findPluginInfoFromName(NPX_PlugInList *list,
  108.                       char *pluginName);
  109.  
  110.  
  111. /*---------------------- Mailcap handling functions -------------------- */
  112. static void
  113. fe_AddCinfo(char *mimeType)
  114. {
  115.   NET_cdataStruct *cd;
  116.   
  117.   cd = NET_cdataCreate();
  118.   cd->ci.type = 0;
  119.   cd->is_external = 1;
  120.   cd->is_local = 0; /* This is internal; only for user to view */
  121.   StrAllocCopy(cd->ci.type, mimeType);
  122.   NET_cdataAdd(cd);
  123. }
  124.  
  125. static NET_cdataStruct *
  126. fe_GetCinfo(char *mimeType)
  127. {
  128.     NET_cdataStruct *cd_item = NULL;
  129.     XP_List *infoList = cinfo_MasterListPointer();
  130.     
  131.     while ((cd_item = (NET_cdataStruct *) XP_ListNextObject(infoList))) {
  132.     if (cd_item->ci.type &&
  133.         !strcmp(mimeType, cd_item->ci.type)) /* Found */
  134.         break;
  135.     }
  136.  
  137.     return(cd_item);
  138. }
  139.  
  140. static NET_mdataStruct *
  141. fe_GetMailcapEntry(char *mimeType)
  142. {
  143.     return(fe_helpers_get_mailcap_from_type(mimeType));
  144. }
  145.  
  146. static char *
  147. fe_MakePluginXmodeEntry(char *pluginName)
  148. {
  149.   return (PR_smprintf("%s%s", NET_COMMAND_PLUGIN, pluginName));
  150. }
  151.  
  152. static void
  153. fe_AddPluginMailcapEntry(char *mimeType, char *pluginName)
  154. {
  155.     char *buf = NULL;
  156.     buf = fe_MakePluginXmodeEntry(pluginName);
  157.     if (!buf) return;
  158.     fe_helpers_add_new_mailcap_data(mimeType, NULL, NULL, buf, 1);
  159.     if (buf) XP_FREE(buf);
  160. }
  161. #endif /* X_PLUGINS */
  162.  
  163. XP_Bool
  164. fe_IsMailcapEntryPlugin(NET_mdataStruct *md_item)
  165. {
  166.     if (!md_item || !md_item->xmode) return(False);
  167.     return (!strncmp(md_item->xmode, NET_COMMAND_PLUGIN,
  168.              strlen(NET_COMMAND_PLUGIN)));
  169. }
  170.  
  171. char *
  172. fe_GetPluginNameFromMailcapEntry(NET_mdataStruct *md_item)
  173. {
  174.     if (!fe_IsMailcapEntryPlugin(md_item)) return(NULL);
  175.     return (md_item->xmode+strlen(NET_COMMAND_PLUGIN));
  176. }
  177.  
  178. /*
  179.  * fe_GetMimetypeInfoFromPlugin:
  180.  * Given a plugin name and a mime type that this plugin supports, return
  181.  * a pointer to the description text and the extensions text.
  182.  * WARNING: Caller should not modify or free the returned description
  183.  *        or extension string.
  184.  */
  185. int
  186. fe_GetMimetypeInfoFromPlugin(char *pluginName, char *mimetype,
  187.                  char **r_desc, char **r_ext)
  188. {
  189.   int ret = -1;
  190. #ifdef X_PLUGINS
  191.   int i;
  192.   NPX_PlugIn *p = NULL;
  193.   NPX_MimeInfo *m = NULL;
  194.  
  195.   if (!mimetype || !*mimetype || !pluginName || !*pluginName) return(ret);
  196.  
  197.   p = findPluginInfoFromName(pluginList, pluginName);
  198.   if (!p) return(ret);
  199.  
  200.   i = p->numMimeEntries;
  201.   m = p->mimeEntries;
  202.   while (i > 0) {
  203.     if (!strcmp(mimetype, m->name))
  204.       break;
  205.     i--; m++;
  206.   }
  207.   if (i > 0) {
  208.     /* Found the mimetype for plugin */
  209.     if (r_desc) *r_desc = m->description;
  210.     if (r_ext) *r_ext = m->extensions;
  211.     ret = 0;
  212.   }
  213. #endif /* X_PLUGINS */
  214.   return(ret);
  215. }
  216.  
  217. #ifdef X_PLUGINS
  218. /*---------------------------------------------------------------------- */
  219.  
  220. static char *skipSpaces(char *str)
  221. {
  222.     while (*str != '\0' && isspace(*str)) {
  223.     str++;
  224.     }
  225.     return str;
  226. }
  227.  
  228. static char *scanToken(char *str, char *buf, int len, char *stopChars, Bool noSpacesOnOutput)
  229. {
  230.     int pos = 0;
  231.     
  232.     str = skipSpaces(str);
  233.  
  234.     while (*str != '\0') {
  235.     while (*str != '\0' &&
  236.            ! isspace(*str) &&
  237.            (stopChars == NULL ||
  238.         strchr(stopChars, *str) == NULL)) {
  239.         buf[pos++] = *str++;
  240.     }
  241.  
  242.     str = skipSpaces(str);
  243.     if (*str == '\0' ||
  244.         stopChars == NULL ||
  245.         strchr(stopChars, *str) != NULL) {
  246.         break;
  247.     }
  248.     if (! noSpacesOnOutput) {
  249.         buf[pos++] = ' ';
  250.     }
  251.     }
  252.     buf[pos] = '\0';
  253.     return str;
  254. }
  255.  
  256. static NPX_PlugIn *findPluginInfo(NPX_PlugInList *list, char *filename)
  257. {
  258.     int i;
  259.  
  260.     if (!list) return (NULL);
  261.  
  262.     for (i = 0; i < list->num; i++) {
  263.     if (strcmp(list->plugins[i].filename, filename) == 0) {
  264.         return(&list->plugins[i]);
  265.     }
  266.     }
  267.     return(NULL);
  268. }
  269.  
  270. static NPX_PlugIn *
  271. findPluginInfoFromName(NPX_PlugInList *list, char *pluginName)
  272. {
  273.     int i;
  274.  
  275.     if (!list) return (NULL);
  276.  
  277.     for (i = 0; i < list->num; i++) {
  278.     if (strcmp(list->plugins[i].pluginName, pluginName) == 0) {
  279.         return(&list->plugins[i]);
  280.     }
  281.     }
  282.     return(NULL);
  283. }
  284.  
  285. static NPX_PlugIn *getNewPluginInfo(NPX_PlugInList *list, char *filename)
  286. {
  287.     NPX_PlugIn *info;
  288.  
  289.     if (list->num == list->max) {
  290.     list->max *= 2;
  291.     list->plugins = (NPX_PlugIn *) realloc(list->plugins, list->max * sizeof(NPX_PlugIn));
  292.     }
  293.  
  294.     info = &list->plugins[list->num++];
  295.     info->filename = strdup(filename);
  296.     info->mimeEntries = NULL;
  297.     info->found = 0;
  298.     info->Delete = 0;
  299.     info->numMimeEntries = 0;
  300.     info->numberOfOpens = 0;
  301.     info->pluginName = NULL;
  302.     info->pluginDesc = NULL;
  303.     info->dlopen_obj = NULL;
  304.     info->handle = NULL;
  305.  
  306.     info->fctns.size = sizeof(NPPluginFuncs);
  307.  
  308.  
  309.     return info;
  310. }
  311.  
  312.  
  313. static void clearPluginInfo(NPX_PlugIn *info)
  314. {
  315.     int i;
  316.     NPX_MimeInfo *pMime;
  317.  
  318.     pMime = info->mimeEntries;
  319.     for (i = 0; i < info->numMimeEntries; i++) {
  320.     free(pMime->name);
  321.     free(pMime->extensions);
  322.     if (pMime->description)
  323.           free(pMime->description);
  324.     pMime++;
  325.     }
  326.     free(info->mimeEntries);
  327.     if (info->pluginName)
  328.     free(info->pluginName);
  329.     if (info->pluginDesc)
  330.     free(info->pluginDesc);
  331.     info->found = 0;
  332.     info->Delete = 0;
  333.     info->numMimeEntries = 0;
  334.     info->numberOfOpens = 0;
  335.     info->dlopen_obj = NULL;
  336.     info->mimeEntries = NULL;
  337.     info->pluginName = 0;
  338.     info->pluginDesc = 0;
  339. }
  340.  
  341. static int parsePluginDescription(NPX_PlugIn *currentInfo, char *str)
  342. {
  343.     char buf[1000];
  344.     int maxMimeEntries;
  345.     NPX_MimeInfo *mimeEntry;
  346.  
  347.     maxMimeEntries = 2;
  348.     currentInfo->mimeEntries = (NPX_MimeInfo *) malloc(2 * sizeof(NPX_MimeInfo));
  349.     currentInfo->numMimeEntries = 0;
  350.     
  351.     while (1) {
  352.     str = scanToken(str, buf, sizeof(buf), ":", FALSE);
  353.     if (buf[0] == '\0' || *str != ':') {
  354.         break;
  355.     }
  356.     str++;
  357.     if (currentInfo->numMimeEntries == maxMimeEntries) {
  358.         maxMimeEntries *= 2;
  359.         currentInfo->mimeEntries = (NPX_MimeInfo *) realloc(currentInfo->mimeEntries, maxMimeEntries * sizeof(NPX_MimeInfo));
  360.     }
  361.     
  362.     mimeEntry = ¤tInfo->mimeEntries[currentInfo->numMimeEntries++];
  363.     mimeEntry->name = strdup(buf);
  364.     mimeEntry->description = NULL;
  365.     mimeEntry->extensions = NULL;
  366.     
  367.     str = scanToken(str, buf, sizeof(buf), ";:", TRUE);
  368.     mimeEntry->extensions = strdup(buf);
  369.     if (*str == ':') {
  370.         str++;
  371.         str = scanToken(str, buf, sizeof(buf), ";", FALSE);
  372.         mimeEntry->description = strdup(buf);
  373.     }
  374. #if 0
  375.     else {
  376.         /* Use mimetype for mime description */
  377.         mimeEntry->description = strdup(mimeEntry->name);
  378.     }
  379. #endif /* 0 */
  380.  
  381.     if (*str != ';') {
  382.         break;
  383.     }
  384.     str++;
  385.     }
  386.  
  387.     return (currentInfo->numMimeEntries == 0);
  388. }
  389.  
  390.  
  391. static void updateMimeInfo(NPX_PlugIn *plugin)
  392. {
  393.     int i;
  394.     NPX_MimeInfo *pMime = plugin->mimeEntries;
  395.  
  396.     if (!plugin->pluginName)
  397.     plugin->pluginName = fe_Basename(XP_STRDUP(plugin->filename));
  398.  
  399.     NPL_RegisterPluginFile(plugin->pluginName, plugin->filename,
  400.                 plugin->pluginDesc,
  401.                 (void *)plugin);
  402.     
  403.     for (i = 0; i < plugin->numMimeEntries; i++) {
  404.       NPL_RegisterPluginType(pMime->name, pMime->extensions,
  405.                  pMime->description?pMime->description:pMime->name,
  406.                  NULL, (void *)plugin,
  407.                  FALSE);
  408.       pMime++;
  409.     }
  410. }
  411.  
  412. static NPX_PlugIn *readPluginInfo(NPX_PlugInList *list, char *filename)
  413. {
  414.     struct stat buf;
  415.     NPX_PlugIn *currentInfo;
  416.     char *(*fct)(void);
  417.     NPError (*getvalue)(void *, int, void *);
  418.     char *newInfo;
  419.     PRLibrary *obj;
  420.  
  421.     if (stat(filename, &buf) != 0 || (buf.st_mode & S_IFREG) != S_IFREG) {
  422.     return NULL;
  423.     }
  424.  
  425.     currentInfo = findPluginInfo(list, filename);
  426.     
  427.     if (currentInfo != NULL) {
  428.     /* currentInfo could have been filled in here because of
  429.      * 1. The plugin was in the plugin-list. (currentInfo->found == 0)
  430.      * 2. This is caused by a re-scan of the plugins directory.
  431.      *    (currentInfo->found == 1).
  432.      *    In this case, we can do a lot of things smart but since we
  433.      *    already have registered the plugin, we need to change the backed
  434.      *    too. That isn't supported yet like unregistering a plugin.
  435.      *    So we will let it go along as far it can and let fate decide...
  436.      */
  437.     if (currentInfo->found)
  438.         return(currentInfo);
  439.  
  440.     currentInfo->Delete = 0;
  441.     if (currentInfo->modifyTime == buf.st_mtime) {
  442.         currentInfo->found = 1;
  443.           updateMimeInfo(currentInfo);
  444.         return currentInfo;
  445.     }
  446.     clearPluginInfo(currentInfo);
  447.     }
  448.     
  449.     if ((obj = PR_LoadLibrary(filename)) != NULL) {
  450.  
  451. #ifndef NSPR20
  452.     fct = (char *(*)())PR_FindSymbol("NP_GetMIMEDescription", obj);
  453. #else
  454.     fct = (char *(*)())PR_FindSymbol(obj, "NP_GetMIMEDescription");
  455. #endif /* NSPR20 */
  456.     if (fct == NULL ||
  457.         (newInfo = (*fct)()) == NULL) {
  458.         int err = PR_UnloadLibrary(obj);
  459.         PR_ASSERT(err == 0);
  460.         return NULL;
  461.     }
  462.  
  463.     if (currentInfo == NULL) {
  464.         currentInfo = getNewPluginInfo(list, filename);
  465.     }
  466.  
  467.     if (parsePluginDescription(currentInfo, newInfo)) {
  468.         int err = PR_UnloadLibrary(obj);
  469.         PR_ASSERT(err == 0);
  470.         currentInfo->Delete = 1;
  471.         return NULL;
  472.     }
  473.  
  474. #ifndef NSPR20
  475.     getvalue = (NPError (*)(void *, int, void *)) PR_FindSymbol("NP_GetValue", obj);
  476. #else
  477.     getvalue = (NPError (*)(void *, int, void *)) PR_FindSymbol(obj, "NP_GetValue");
  478. #endif /* NSPR20 */
  479.         if (getvalue != NULL) {
  480.         char *value;
  481.         NPError err;
  482.         err = (*getvalue)(NULL, NPPVpluginNameString, (void *) &value);
  483.         if (err == NPERR_NO_ERROR)
  484.         currentInfo->pluginName = strdup(value);
  485.         else
  486.             currentInfo->pluginName =
  487.           fe_Basename(strdup(currentInfo->filename));
  488.         err = (*getvalue)(NULL, NPPVpluginDescriptionString,
  489.                   (void *) &value);
  490.         if (err == NPERR_NO_ERROR)
  491.         currentInfo->pluginDesc = strdup(value);
  492.     }
  493.  
  494.     currentInfo->modifyTime = buf.st_mtime;
  495.     currentInfo->found = 1;
  496.  
  497.     updateMimeInfo(currentInfo);
  498.     {
  499.     int err = PR_UnloadLibrary(obj);
  500.     PR_ASSERT(err == 0);
  501.     }
  502.     return currentInfo;
  503.     }
  504.     else {
  505.     fprintf (stderr, XP_GetString(XFE_PLUGIN_CANT_LOAD),
  506.          PR_GetErrorString(), filename);
  507.     }
  508.  
  509.     return NULL;
  510. }
  511.  
  512.  
  513. static int readPluginList(NPX_PlugInList *list, char *filename)
  514. {
  515.     FILE *in;
  516.     int versionNumber;
  517.     char buf[10000];
  518.     char fileNameBuf[MAXPATHLEN];
  519.     char timeBuf[20];
  520.     NPX_PlugIn *pInfo = NULL;
  521.     char *str;
  522.  
  523.     if ((in = fopen(filename, "r")) != NULL) {
  524.     if (fgets(buf, sizeof(buf), in) != NULL &&
  525.         strlen(buf) >= 20 &&
  526.         strncmp(buf, "PluginList Version ", 19) == 0) {
  527.         /* looking for header, which contains id, version, number of elements */
  528.  
  529.         versionNumber = atoi(&buf[19]);
  530.  
  531.         if (versionNumber != 1) {
  532.         fclose(in);
  533.         return 1;
  534.         }
  535.  
  536.         while (fgets(buf, sizeof(buf), in) != NULL) {
  537.         if (buf[strlen(buf)-1] == '\n')
  538.             buf[strlen(buf)-1] = '\0';
  539.         if (!strncmp(buf, PLUGIN_NAME_PARAM,
  540.                  strlen(PLUGIN_NAME_PARAM))) {
  541.             if (pInfo)
  542.             pInfo->pluginName =
  543.               strdup(&buf[strlen(PLUGIN_NAME_PARAM)]);
  544.             continue;
  545.         }
  546.         if (!strncmp(buf, PLUGIN_DESC_PARAM,
  547.                  strlen(PLUGIN_DESC_PARAM))) {
  548.             if (pInfo)
  549.             pInfo->pluginDesc =
  550.               strdup(&buf[strlen(PLUGIN_DESC_PARAM)]);
  551.             continue;
  552.         }
  553.         str = scanToken(buf, fileNameBuf, sizeof(fileNameBuf), NULL, FALSE);
  554.         if (fileNameBuf == '\0') {
  555.             continue;
  556.         }
  557.         pInfo = findPluginInfo(list, fileNameBuf);
  558.         if (pInfo == NULL) {
  559.             pInfo = getNewPluginInfo(list, fileNameBuf);
  560.         }
  561.         else {
  562.             clearPluginInfo(pInfo);
  563.         }
  564.  
  565.         str = scanToken(str, timeBuf, sizeof(timeBuf), NULL, FALSE);
  566.  
  567.         if (timeBuf[0] == '\0') {
  568.             continue;
  569.         }
  570.  
  571.         pInfo->modifyTime = atoi(timeBuf);
  572.  
  573.         parsePluginDescription(pInfo, str);
  574.         }
  575.     }        
  576.     
  577.     fclose(in);
  578.     }
  579.     return 1;
  580. }
  581.  
  582. static int writePluginList(NPX_PlugInList *list, char *filename)
  583. {
  584.     FILE *out;
  585.     int i;
  586.     int j;
  587.     NPX_PlugIn *pInfo;
  588.     NPX_MimeInfo *pMime;
  589.  
  590.     if ((out = fopen(filename, "w")) != NULL) {
  591.     fputs("PluginList Version 1\n", out);
  592.     pInfo = list->plugins;
  593.     for (i = 0; i < list->num; i++) {
  594.         if (pInfo->found && ! pInfo->Delete && pInfo->numMimeEntries > 0) {
  595.         fprintf(out, "%s %d", pInfo->filename, pInfo->modifyTime);
  596.         pMime = pInfo->mimeEntries;
  597.         for (j = 0; j < pInfo->numMimeEntries; j++) {
  598.             fprintf(out, " %s: %s", pMime->name, pMime->extensions);
  599.             if (pMime->description)
  600.                 fprintf(out, ":%s", pMime->description);
  601.             fputs(";", out);
  602.             pMime++;
  603.         }
  604.         fputs("\n", out);
  605.         if (pInfo->pluginName && *pInfo->pluginName)
  606.             fprintf(out, "%s%s\n", PLUGIN_NAME_PARAM, pInfo->pluginName);
  607.         if (pInfo->pluginDesc && *pInfo->pluginDesc)
  608.             fprintf(out, "%s%s\n", PLUGIN_DESC_PARAM, pInfo->pluginDesc);
  609.         }
  610.         pInfo++;
  611.     }
  612.     fclose(out);
  613.     return 0;
  614.     }
  615.     return 1;
  616. }
  617.  
  618. static void getPluginsFromDirectory(NPX_PlugInList *list, char *directoryName)
  619. {
  620.     DIR *dir;
  621.     char filename[MAXPATHLEN];
  622.     char *nameptr;
  623.     struct dirent *dp;
  624.  
  625. #ifdef JAVA
  626.     /* Add directory to the java backend so that it can find java plugins */
  627.     LJ_AddToClassPath(directoryName);
  628. #endif /* JAVA */
  629.  
  630.     if ((dir = opendir(directoryName)) != NULL) {
  631.     strcpy(filename, directoryName);
  632.     nameptr = &filename[strlen(filename)];
  633.     *nameptr++ = '/';
  634.     while ((dp = readdir(dir)) != NULL) {
  635.         if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
  636.         continue;
  637.         strcpy(nameptr, dp->d_name);
  638.         if (fe_isDir(filename))
  639.         getPluginsFromDirectory(list, filename);
  640.         if (!strcmp(dp->d_name, "libc.so.1"))
  641.         continue;
  642.         /*
  643.          *    Look for Composer (Editor) plugins:
  644.          *    the local filename has form: cp<something>.[zip|jar]
  645.          */
  646.         if (strncmp(dp->d_name, "cp", 2) == 0
  647.             &&
  648.             (fe_StrEndsWith(dp->d_name, ".zip")
  649.              ||
  650.              fe_StrEndsWith(dp->d_name, ".jar"))
  651.             ) {
  652. #ifdef EDITOR
  653. #ifdef DEBUG_mcafee
  654.             printf("  Found editor plugin \"%s\" in %s.\n", filename, directoryName);
  655. #endif
  656.             EDT_RegisterPlugin(filename);
  657. #endif
  658.             continue;
  659.         }
  660.  
  661.         /* Ignore .class and .zip files */
  662.         if (fe_StrEndsWith(dp->d_name, ".class") ||
  663.         fe_StrEndsWith(dp->d_name, ".zip"))
  664.           continue;
  665.         readPluginInfo(list, filename);
  666. #ifdef DEBUG_mcafee
  667.         printf("  Found plugin \"%s\" in %s.\n", filename, directoryName);
  668. #endif
  669.     }
  670.     closedir(dir);
  671.     }
  672. }
  673.  
  674. static void getPluginsFromPath(NPX_PlugInList *list, char *path)
  675. {
  676.     char *str = path;
  677.     char directoryName[MAXPATHLEN];
  678.  
  679.     while (*str != '\0') {
  680.     str = scanToken(str, directoryName, sizeof(directoryName), ":", FALSE);
  681.  
  682.     if (directoryName[0] != '\0') {
  683. #ifdef DEBUG_mcafee
  684.             printf("Searching in %s.\n", directoryName);
  685. #endif
  686.  
  687.         getPluginsFromDirectory(list, directoryName);
  688.     }
  689.  
  690.     if (*str == ':') {
  691.         str++;
  692.     }
  693.     }
  694. }
  695.  
  696. static NPX_PlugInList *getPluginList(int numFiles)
  697. {
  698.     NPX_PlugInList *list;
  699.  
  700.     list = (NPX_PlugInList *) malloc(sizeof(NPX_PlugInList));
  701.     list->num = 0;
  702.     list->max = numFiles;
  703.     list->plugins = (NPX_PlugIn *) malloc(numFiles * sizeof(NPX_PlugIn));
  704.  
  705.     return list;
  706. }
  707.  
  708. #ifdef DEBUG_dp
  709. static void dumpPluginInfo(NPX_PlugIn *info)
  710. {
  711.     int i;
  712.  
  713.     printf("filename: %s time: %d\n",
  714.         info->filename, info->modifyTime);
  715.  
  716.     for (i = 0; i < info->numMimeEntries; i++) {
  717.     printf("    mimetype: %s extensions: %s\n", info->mimeEntries[i].name, info->mimeEntries[i].extensions);
  718.     }
  719.     printf("\n");
  720. }
  721. #endif
  722. #endif /* X_PLUGINS */
  723.  
  724. void FE_RegisterPlugins()
  725. {
  726. #ifdef X_PLUGINS
  727.     char filename[MAXPATHLEN];
  728.     char newFilename[MAXPATHLEN];
  729.     char oldFilename[MAXPATHLEN];
  730.     char *npxPluginPath  = getenv("NPX_PLUGIN_PATH");
  731.     char *mozHome        = getenv("MOZILLA_HOME");
  732.     char *pluginPath     = NULL;
  733.     char *home = getenv ("HOME");
  734.     
  735.     if (!home)
  736.         home = "";
  737.     else if (!strcmp (home, "/"))
  738.         home = "";
  739.  
  740.     /* Algorithm for searching for plugins is:
  741.        if $NPX_PLUGIN_PATH
  742.            Use that
  743.        else
  744.            Build up a colon-delimited search string like
  745.              /usr/local/lib/netscape/plugins:$MOZILLA_HOME/plugins:
  746.              $HOME/.netscape/plugins
  747.            with last directory overriding other directories, since
  748.            they all get searched. */
  749.     if(npxPluginPath) {
  750.         pluginPath = npxPluginPath;
  751.     } else {
  752.         /* Stuff in $MOZILLA_HOME if it's defined. */
  753.         if(mozHome) {
  754.             pluginPath = PR_smprintf("%s:%s/plugins:%.900s/.netscape/plugins",
  755.                                      DEFAULT_LEGACY_PLUGIN_PATH,
  756.                                      mozHome,
  757.                                      home);
  758.         } else {
  759.             /* Try to stuff argv[0] into the path */
  760.             char buf[MAXPATHLEN];
  761.  
  762.             buf[0] = '\0';
  763.             fe_GetProgramDirectory(buf, sizeof(buf)-1);
  764.             strncat(buf, "plugins", sizeof(buf)-1 - strlen(buf));
  765.             buf[sizeof(buf)-1] = '\0';
  766.  
  767.             pluginPath = PR_smprintf("%s:%s:%.900s/.netscape/plugins",
  768.                                      DEFAULT_LEGACY_PLUGIN_PATH,
  769.                                      buf,
  770.                                      home);            
  771.         }
  772.     }
  773.  
  774.     PR_snprintf(filename, sizeof(filename), "%.900s/.netscape/plugin-list", home);
  775.     PR_snprintf(newFilename, sizeof(newFilename), "%.900s/.netscape/plugin-list.new", home);
  776.     PR_snprintf(oldFilename, sizeof(oldFilename), "%.900s/.netscape/plugin-list.BAK", home);
  777.  
  778.     if (pluginList == NULL) {
  779.         pluginList = getPluginList(32);
  780.         readPluginList(pluginList, filename);
  781.     }
  782.  
  783.     getPluginsFromPath(pluginList, pluginPath);
  784.  
  785.     if (writePluginList(pluginList, newFilename) == 0) {
  786.         rename(filename, oldFilename);
  787.         rename(newFilename, filename);
  788.     }
  789.     
  790.     if (!npxPluginPath) 
  791.         XP_FREE(pluginPath);  /* Free if we used PR_smprintf(). */
  792.  
  793.     fe_RegisterPluginConverters();
  794.  
  795. #endif /* X_PLUGINS */
  796. }
  797.  
  798. /*
  799.  * The purpose of this function is
  800.  * 1. Add md and cinfo list entries for new mimetypes that plugins handle
  801.  * 2. Enable plugins for the new mimetype that we handle
  802.  * 3. Change the converter for which there is no plugin to save as.
  803.  */
  804. void
  805. fe_RegisterPluginConverters(void)
  806. {
  807.   NET_cdataStruct *cd_item = NULL;
  808.   NET_mdataStruct *md_item = NULL;
  809.   XP_List *infoList = cinfo_MasterListPointer();
  810. #ifdef X_PLUGINS
  811.   NPX_PlugInList *list = pluginList;
  812.   int i, n;
  813.  
  814.   if (!list) return;
  815.  
  816.   /* Register all default plugin converters */
  817.   NPL_RegisterDefaultConverters();
  818.  
  819.   /* 1. Add md and cinfo list entries for new mimetypes that plugins handle
  820.    * 2. Enable plugins for the new mimetype that we handle
  821.    *
  822.    */
  823.  
  824.   for (n=0; n<list->num; n++) {
  825.     NPX_PlugIn *plugin = &list->plugins[n];
  826.     NPX_MimeInfo *pMime = plugin->mimeEntries;
  827.     for (i = 0; i < plugin->numMimeEntries; i++) {
  828.       XP_Bool enable = TRUE;
  829.       cd_item = fe_GetCinfo(pMime->name);
  830.       md_item = NULL;
  831.  
  832.       if (cd_item) {
  833.     md_item = fe_GetMailcapEntry(cd_item->ci.type);
  834.     if (md_item) {
  835.       if (!fe_IsMailcapEntryPlugin(md_item) ||
  836.           (strcmp(fe_GetPluginNameFromMailcapEntry(md_item),
  837.               plugin->pluginName)))
  838.         enable = FALSE;
  839.  
  840.       /* Eventhough the mailcap entry is not a plugin, if we had changed
  841.          it to save to Disk because a plugin suddenly was not found, we
  842.          will change it back to plugin once it was found. */
  843.       if (md_item->xmode &&
  844.           !XP_STRCASECMP(md_item->xmode, NET_COMMAND_SAVE_BY_NETSCAPE)) {
  845.         char *newxmode = fe_MakePluginXmodeEntry(plugin->pluginName);
  846.         /* Enable the plugin for this mimetype */
  847.         enable = TRUE;
  848.         
  849.         /* Change the mailcap entry back to plugin */
  850.         if (newxmode) {
  851.           fe_helpers_update_mailcap_entry(md_item->contenttype, md_item,
  852.                           newxmode);
  853.           if (newxmode) XP_FREE(newxmode);
  854.         }
  855.       }
  856.     }
  857.       }
  858.  
  859.       if (enable) {
  860.     if (!cd_item) {
  861.       fe_AddCinfo(pMime->name);
  862.     }
  863.     if (!md_item) {
  864.       fe_AddPluginMailcapEntry(pMime->name, plugin->pluginName);
  865.     }
  866.  
  867.     if (NPL_EnablePlugin(pMime->name, plugin->pluginName, TRUE)
  868.         != NPERR_NO_ERROR) {
  869. #ifdef DEBUG
  870.       fprintf (stderr, "Cannot enable plugin %s for type %s.\n",
  871.            plugin->pluginName, pMime->name);
  872. #endif /* DEBUG */
  873.     }
  874.       } /* enabled */
  875.       pMime++;
  876.     }
  877.   }
  878. #endif /* X_PLUGINS */
  879.  
  880.   /* 3. Change the converter for which there is no plugin to save as. */
  881.   while ((cd_item = (NET_cdataStruct *) XP_ListNextObject(infoList))) {
  882.     md_item = fe_helpers_get_mailcap_from_type(cd_item->ci.type);
  883.  
  884.     if (fe_IsMailcapEntryPlugin(md_item)) {
  885.       char *pname = fe_GetPluginNameFromMailcapEntry(md_item);
  886.          
  887.       if (
  888. #ifdef X_PLUGINS
  889.       !findPluginInfoFromName(pluginList, pname)
  890. #else /* X_PLUGINS */
  891.       True /* Plugin info is always not found for NO PLUGIN */
  892. #endif /* X_PLUGINS */
  893.       ) {
  894.     /* We have a plugin entry but no plugin */
  895.     fprintf (stderr, XP_GetString(XFE_PLUGIN_NO_PLUGIN),
  896.          pname, cd_item->ci.type);
  897.     NET_RegisterContentTypeConverter(cd_item->ci.type,
  898.                      FO_PRESENT,
  899.                      NULL, fe_MakeSaveAsStream );
  900.     fe_helpers_update_mailcap_entry(md_item->contenttype, md_item,
  901.                           NET_COMMAND_SAVE_BY_NETSCAPE);
  902.       }
  903.     }
  904.   }
  905. }
  906.  
  907.     
  908. NPPluginFuncs *
  909. FE_LoadPlugin(void *pdesc, NPNetscapeFuncs *funcs, np_handle* handle)
  910. {
  911. #ifdef X_PLUGINS
  912.     NPX_PlugIn *plugin = (NPX_PlugIn *) pdesc;
  913.     NPError (*f)(NPNetscapeFuncs *, NPPluginFuncs *);
  914.  
  915.     NPError err;
  916.  
  917.     if (plugin->dlopen_obj == NULL) {
  918.         plugin->dlopen_obj = PR_LoadLibrary(plugin->filename);
  919.         if (plugin->dlopen_obj == NULL) {
  920.         fprintf(stderr, XP_GetString(XFE_PLUGIN_CANT_LOAD),
  921.             PR_GetErrorString(), plugin->filename);
  922.             return NULL;
  923.         }
  924.  
  925.     NP_CREATEPLUGIN npCreatePlugin =
  926. #ifndef NSPR20
  927.         (NP_CREATEPLUGIN)PR_FindSymbol("NP_CreatePlugin", plugin->dlopen_obj);
  928. #else
  929.             (NP_CREATEPLUGIN)PR_FindSymbol(plugin->dlopen_obj, "NP_CreatePlugin");
  930. #endif
  931.     if (npCreatePlugin != NULL) {
  932.         if (thePluginManager == NULL) {
  933.                 static NS_DEFINE_IID(kIPluginManagerIID, NP_IPLUGINMANAGER_IID);
  934.                 if (nsPluginManager::Create(NULL, kIPluginManagerIID, (void**)&thePluginManager) != NS_OK)
  935.                     return NULL;
  936.         }
  937.         NPIPlugin* userPlugin = NULL;
  938.         NPPluginError err = npCreatePlugin(thePluginManager, &userPlugin);
  939.         handle->userPlugin = userPlugin;
  940.         plugin->handle = handle;
  941.         if (err != NPPluginError_NoError || userPlugin == NULL) {
  942.         int err = PR_UnloadLibrary(plugin->dlopen_obj);
  943.         PR_ASSERT(err == 0);
  944.         plugin->dlopen_obj = NULL;
  945.         return NULL;
  946.         }
  947.     }
  948.     else {
  949. #ifndef NSPR20
  950.         f = (NPError(*)(NPNetscapeFuncs *, NPPluginFuncs *)) PR_FindSymbol("NP_Initialize", plugin->dlopen_obj);
  951. #else
  952.         f = (NPError(*)(NPNetscapeFuncs *, NPPluginFuncs *)) PR_FindSymbol(plugin->dlopen_obj, "NP_Initialize");
  953. #endif /* NSPR20 */
  954.  
  955.         if (f == NULL) {
  956.         int err = PR_UnloadLibrary(plugin->dlopen_obj);
  957.         PR_ASSERT(err == 0);
  958.         plugin->dlopen_obj = NULL;
  959.         return NULL;
  960.         }
  961.  
  962.         plugin->load = f;
  963.         err = (*f)(funcs, &plugin->fctns);
  964.  
  965.         if (err != NPERR_NO_ERROR) {
  966.         int err = PR_UnloadLibrary(plugin->dlopen_obj);
  967.         PR_ASSERT(err == 0);
  968.         plugin->dlopen_obj = NULL;
  969.         return NULL;
  970.         }
  971.  
  972. #ifndef NSPR20
  973.         plugin->shutdown = (NPError(*)(void)) PR_FindSymbol("NP_Shutdown", plugin->dlopen_obj);
  974. #else
  975.         plugin->shutdown = (NPError(*)(void)) PR_FindSymbol(plugin->dlopen_obj, "NP_Shutdown");
  976. #endif /* NSPR20 */
  977.  
  978.     }
  979.     }
  980.  
  981.     plugin->numberOfOpens++;
  982.     return &plugin->fctns;
  983. #else /* X_PLUGINS */
  984.     return (NULL);
  985. #endif /* X_PLUGINS */
  986. }
  987.  
  988.  
  989. void
  990. FE_UnloadPlugin(void *pdesc, struct _np_handle* handle)
  991. {
  992. #ifdef X_PLUGINS
  993.     NPX_PlugIn *plugin =  (NPX_PlugIn *) pdesc;
  994.     NPError (*f)(void);
  995.     NPError err;
  996.  
  997.     if (plugin->handle->userPlugin) {
  998.     NPIPlugin* userPlugin = (NPIPlugin*)plugin->handle->userPlugin;
  999.     XP_VERIFY(userPlugin->Release() == 0);
  1000.     plugin->handle = NULL;
  1001.     }
  1002.     else {
  1003.     f = plugin->shutdown;
  1004.     if (f) {
  1005.         err = (*f)();
  1006.         if (err != NPERR_NO_ERROR) {
  1007.         /* XXX There was a error while unloading this plugin. What can we
  1008.          *     do. Ignore it for now.
  1009.          */  
  1010.         }
  1011.     }
  1012.     }
  1013.     plugin->numberOfOpens--;
  1014.  
  1015.     if (plugin->numberOfOpens == 0) {
  1016.     int err = PR_UnloadLibrary(plugin->dlopen_obj);
  1017.     PR_ASSERT(err == 0);
  1018.     plugin->dlopen_obj = NULL;
  1019.     }
  1020.     else if (plugin->numberOfOpens < 0) {
  1021.         plugin->numberOfOpens = 0;
  1022.     }
  1023. #endif /* X_PLUGINS */
  1024. }
  1025.  
  1026. void
  1027. FE_EmbedURLExit(URL_Struct *urls, int status, MWContext *cx)
  1028. {
  1029. }
  1030.  
  1031. NPError
  1032. FE_PluginGetValue(void *pdesc, NPNVariable variable, void *r_value)
  1033. {
  1034. #ifdef X_PLUGINS
  1035.   NPError ret = NPERR_NO_ERROR;
  1036.  
  1037.   switch (variable) {
  1038.   case NPNVxDisplay:
  1039.     if (r_value)
  1040.       (*(Display **)r_value) = fe_display;
  1041.     break;
  1042.   case NPNVxtAppContext:
  1043.     if (r_value)
  1044.       (*(XtAppContext *)r_value) = fe_XtAppContext;
  1045.     break;
  1046.   default:
  1047.     ret = NPERR_INVALID_PARAM;
  1048.   }
  1049.   return ret;
  1050. #else /* X_PLUGINS */
  1051.   return(NPERR_INVALID_PARAM);
  1052. #endif /* X_PLUGINS */
  1053. }
  1054.  
  1055.