mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 08:12:05 +00:00
891 lines
32 KiB
C++
891 lines
32 KiB
C++
/* -*- Mode: C++; tab-width: 4; 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.
|
|
*/
|
|
|
|
// npwplat.cpp
|
|
#include "stdafx.h"
|
|
#include <afxole.h>
|
|
#include <afxpriv.h>
|
|
#include <afxwin.h>
|
|
#include <errno.h>
|
|
#include <direct.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#ifdef WIN32
|
|
#include <io.h>
|
|
#include <winver.h>
|
|
#else
|
|
#include <dos.h>
|
|
#include <ver.h>
|
|
#endif
|
|
#include "npwplat.h"
|
|
#include "nppg.h"
|
|
#include "plgindll.h"
|
|
#include "np.h"
|
|
#include "helper.h"
|
|
#if defined(OJI)
|
|
#include "jvmmgr.h"
|
|
#elif defined(JAVA)
|
|
#include "java.h"
|
|
#endif
|
|
#include "edt.h"
|
|
#include "npglue.h"
|
|
|
|
NPPMgtBlk* g_pRegisteredPluginList = NULL;
|
|
|
|
// Tests that the directory specified by "dir" exists.
|
|
// Returns true if it does.
|
|
|
|
static XP_Bool wfe_CheckDir(const char * dir)
|
|
{
|
|
int ret;
|
|
XP_StatStruct statinfo;
|
|
|
|
ret = _stat((char *) dir, &statinfo);
|
|
if(ret == -1)
|
|
return(FALSE);
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
// Get the name of the directory where plugins live. "csDirname" is where the
|
|
// name of the dir is written to, and the trailing slash is removed.
|
|
// It always returns NPERR_NO_ERROR, since the Nav had to be started to get
|
|
// here, and the plugin dir is under where Nav started from.
|
|
NPError wfe_GetPluginsDirectory(CString& csDirname)
|
|
{
|
|
char ca_default[_MAX_PATH];
|
|
::GetModuleFileName(AfxGetApp()->m_hInstance, ca_default, _MAX_PATH);
|
|
char *cp_lastslash = ::strrchr(ca_default, '\\');
|
|
*cp_lastslash = NULL;
|
|
csDirname = ca_default;
|
|
csDirname += "\\plugins";
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
NPError wfe_GetJavaDirectory(CString& csDirname)
|
|
{
|
|
char ca_default[_MAX_PATH];
|
|
::GetModuleFileName(AfxGetApp()->m_hInstance, ca_default, _MAX_PATH);
|
|
char *cp_lastslash = ::strrchr(ca_default, '\\');
|
|
*cp_lastslash = NULL;
|
|
csDirname = ca_default;
|
|
csDirname += "\\java\\classes";
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
// Fetches the "MIME type" string from the DLL VERSIONINFO structure.
|
|
// "pVersionInfo" is ptr to the VERSIONINFO data, and "pNPMgtBlk" is a handle
|
|
// to a plugin management data structure created during fe_RegisterPlugin().
|
|
// The string is copied from the VERSIONINFO data into the
|
|
// "pNPMgtBlk->szMIMEType" member.
|
|
// An error is returned if out of memory. The MIME type string IS
|
|
// required, so an error is returned if the string does not exist.
|
|
NPError wfe_GetPluginMIMEType(VS_FIXEDFILEINFO* pVersionInfo,
|
|
NPPMgtBlk* pNPMgtBlk)
|
|
{
|
|
// get the mime type of this plugin
|
|
static char szMimeTypeBlock[] = "StringFileInfo\\040904E4\\MIMEType";
|
|
void* lpBuffer = NULL;
|
|
UINT uValueSize = 0;
|
|
if(::VerQueryValue(pVersionInfo, szMimeTypeBlock,
|
|
&lpBuffer, &uValueSize) == 0) // couldn't find MIME type
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
pNPMgtBlk->szMIMEType = new char[uValueSize];
|
|
if(pNPMgtBlk->szMIMEType == NULL)
|
|
return NPERR_OUT_OF_MEMORY_ERROR;
|
|
|
|
strcpy(pNPMgtBlk->szMIMEType, (const char*)lpBuffer);
|
|
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
// Fetches the "File Extents" string from the DLL VERSIONINFO structure.
|
|
// "pVersionInfo" is ptr to the VERSIONINFO data, and "pNPMgtBlk" is a handle
|
|
// to a plugin management data structure created during fe_RegisterPlugin().
|
|
// The string is copied from the VERSIONINFO data into the
|
|
// "pNPMgtBlk->szFileExtents" member.
|
|
// An error is returned if out of memory, but the extents string is not
|
|
// required, so it is not an error if the string does not exist.
|
|
NPError wfe_GetPluginExtents(VS_FIXEDFILEINFO* pVersionInfo,
|
|
NPPMgtBlk* pNPMgtBlk)
|
|
{ // get the file extent list of this plugin
|
|
pNPMgtBlk->szFileExtents = NULL;
|
|
|
|
static char szFileExtentsBlock[] = "StringFileInfo\\040904E4\\FileExtents";
|
|
void* lpBuffer = NULL;
|
|
UINT uValueSize = 0;
|
|
|
|
if(::VerQueryValue(pVersionInfo, szFileExtentsBlock,
|
|
&lpBuffer, &uValueSize) == 0)
|
|
// couldn't find file extent
|
|
return NPERR_NO_ERROR;
|
|
|
|
if((*((char*)lpBuffer) == '\0') || (uValueSize == 0)) // no extents
|
|
return NPERR_NO_ERROR;
|
|
|
|
// alloc char array
|
|
pNPMgtBlk->szFileExtents = new char[uValueSize];
|
|
if(pNPMgtBlk->szFileExtents == NULL)
|
|
return NPERR_OUT_OF_MEMORY_ERROR;
|
|
strcpy(pNPMgtBlk->szFileExtents, (const char*)lpBuffer);
|
|
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
// Fetches the "File Open Template" string from the DLL VERSIONINFO structure.
|
|
// "pVersionInfo" is ptr to the VERSIONINFO data, and "pNPMgtBlk" is a handle
|
|
// to a plugin management data structure created during fe_RegisterPlugin().
|
|
// The string is copied from the VERSIONINFO data into the
|
|
// "pNPMgtBlk->szFileOpenName" member.
|
|
// An error is returned if out of memory, but the template string is not
|
|
// required, so it is not an error if the string does not exist.
|
|
NPError wfe_GetPluginFileOpenTemplate(VS_FIXEDFILEINFO* pVersionInfo,
|
|
NPPMgtBlk* pNPMgtBlk)
|
|
{ // get the file open template this plugin
|
|
pNPMgtBlk->szFileOpenName = NULL;
|
|
|
|
static char szFileOpenBlock[] = "StringFileInfo\\040904E4\\FileOpenName";
|
|
void* lpBuffer = NULL;
|
|
UINT uValueSize = 0;
|
|
|
|
if(::VerQueryValue(pVersionInfo, szFileOpenBlock,
|
|
&lpBuffer, &uValueSize) == 0)
|
|
// couldn't find file extent
|
|
return NPERR_NO_ERROR;
|
|
|
|
if((*((char*)lpBuffer) == '\0') || (uValueSize == 0)) // no extents
|
|
return NPERR_NO_ERROR;
|
|
|
|
// alloc char array
|
|
pNPMgtBlk->szFileOpenName = new char[uValueSize];
|
|
if(pNPMgtBlk->szFileOpenName == NULL)
|
|
return NPERR_OUT_OF_MEMORY_ERROR;
|
|
strcpy(pNPMgtBlk->szFileOpenName, (const char*)lpBuffer);
|
|
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
// Fetches the plugin name and description from the resource info.
|
|
// Uses predefined version information strings
|
|
NPError wfe_GetPluginNameAndDescription(VS_FIXEDFILEINFO* pVersionInfo,
|
|
CString& strName,
|
|
CString& strDescription)
|
|
{
|
|
static char szNameBlock[] = "StringFileInfo\\040904E4\\ProductName";
|
|
static char szDescBlock[] = "StringFileInfo\\040904E4\\FileDescription";
|
|
void* lpBuffer = NULL;
|
|
UINT uValueSize = 0;
|
|
|
|
// Get the product name
|
|
if(::VerQueryValue(pVersionInfo, szNameBlock, &lpBuffer, &uValueSize) > 0)
|
|
strName = (LPSTR)lpBuffer;
|
|
|
|
// Get the file description
|
|
if(::VerQueryValue(pVersionInfo, szDescBlock, &lpBuffer, &uValueSize) > 0)
|
|
strDescription = (LPSTR)lpBuffer;
|
|
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
// Loads plugin properties from the DLL VERSIONINFO data structure.
|
|
// MIME type and version are required, but file extents and string
|
|
// file open templates are optional. "pPluginFilespec" is a string
|
|
// containing the file name of a DLL. "pNPMgtBlk" is a handle to a
|
|
// plugin management data structure created during fe_RegisterPlugin().
|
|
// Returns an error if "pPluginFilespec" did not have the required MIME
|
|
// type and version fields.
|
|
//
|
|
// Also returns the plugin name and description
|
|
NPError wfe_GetPluginProperties(char* pPluginFilespec,
|
|
NPPMgtBlk* pNPMgtBlk,
|
|
CString& strPluginName,
|
|
CString& strPluginDescription)
|
|
{
|
|
// prepare to read the version info tags
|
|
DWORD dwHandle = NULL;
|
|
DWORD dwVerInfoSize = ::GetFileVersionInfoSize(pPluginFilespec, &dwHandle);
|
|
if(dwVerInfoSize == NULL)
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
VS_FIXEDFILEINFO* pVersionInfo =
|
|
(VS_FIXEDFILEINFO*)new char[dwVerInfoSize];
|
|
if(pVersionInfo == NULL)
|
|
return NPERR_OUT_OF_MEMORY_ERROR;
|
|
|
|
if(::GetFileVersionInfo(pPluginFilespec, dwHandle,
|
|
dwVerInfoSize, pVersionInfo) == 0)
|
|
{
|
|
delete [] (char*)pVersionInfo;
|
|
return NPERR_GENERIC_ERROR;
|
|
}
|
|
|
|
NPError result;
|
|
// get the mime type of this plugin
|
|
if((result = wfe_GetPluginMIMEType(pVersionInfo, pNPMgtBlk))
|
|
!= NPERR_NO_ERROR)
|
|
{
|
|
delete [] (char*)pVersionInfo;
|
|
return result;
|
|
}
|
|
|
|
// get the file extent list of this plugin
|
|
if((result = wfe_GetPluginExtents(pVersionInfo, pNPMgtBlk))
|
|
!= NPERR_NO_ERROR)
|
|
|
|
{
|
|
delete [] pNPMgtBlk->szMIMEType;
|
|
delete [] (char*)pVersionInfo;
|
|
return result;
|
|
}
|
|
|
|
// get the file type template string of this plugin
|
|
if((result = wfe_GetPluginFileOpenTemplate(pVersionInfo, pNPMgtBlk))
|
|
!= NPERR_NO_ERROR)
|
|
|
|
{
|
|
delete [] pNPMgtBlk->szFileExtents;
|
|
delete [] pNPMgtBlk->szMIMEType;
|
|
delete [] (char*)pVersionInfo;
|
|
return result;
|
|
}
|
|
|
|
// get the version of this plugin
|
|
void* lpBuffer = NULL;
|
|
UINT uValueSize = 0;
|
|
if(::VerQueryValue(pVersionInfo, "\\", &lpBuffer, &uValueSize) == 0)
|
|
{ // couldn't find versioninfo
|
|
delete [] pNPMgtBlk->szFileExtents;
|
|
delete [] pNPMgtBlk->szMIMEType;
|
|
delete [] (char*)pVersionInfo;
|
|
return NPERR_GENERIC_ERROR;
|
|
}
|
|
pNPMgtBlk->versionMS = ((VS_FIXEDFILEINFO*)lpBuffer)->dwProductVersionMS;
|
|
pNPMgtBlk->versionLS = ((VS_FIXEDFILEINFO*)lpBuffer)->dwProductVersionLS;
|
|
|
|
// get the plugin name and description. It's not fatal if these fail
|
|
wfe_GetPluginNameAndDescription(pVersionInfo, strPluginName, strPluginDescription);
|
|
|
|
delete [] (char*)pVersionInfo;
|
|
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
// Given a file open filter, e.g. Text Documents(*.txt), extracts the
|
|
// description and returns a copy of it
|
|
static LPSTR
|
|
ExtractDescription(LPCSTR lpszFileOpenFilter)
|
|
{
|
|
ASSERT(lpszFileOpenFilter);
|
|
|
|
LPSTR lpszDescription = XP_STRDUP(lpszFileOpenFilter);
|
|
|
|
// Strip off an filter pattern at the end
|
|
LPSTR lpszPattern = strrchr(lpszDescription, '(');
|
|
|
|
if (lpszPattern)
|
|
*lpszPattern = '\0';
|
|
|
|
return lpszDescription;
|
|
}
|
|
|
|
// Registers one plugin. "pPluginFilespec" is a string containing the file
|
|
// name of a DLL.
|
|
// This function can be called more than once so a plugin which has copied
|
|
// into the plugins subdir AFTER the Nav has started can be registered
|
|
// and loaded.
|
|
// The DLL is a plugin candidate, and is qualified during
|
|
// this function, by checking the DLL VERSIONINFO data structure for a
|
|
// MIME type string. If this string is found successfully, the handle
|
|
// of the management block is used to register the plugin for its MIME type.
|
|
// The extents which are to be associated with this MIME type are also grokked
|
|
// from the VERSIONINFO data structure, once the candidate is accepted.
|
|
// This function also takes the opportunity to overrided any helper app, by
|
|
// setting a helper app data structure member to allow the plugin to handle
|
|
// the MIME type instead of the helper, (pApp->how_handle = HANDLE_VIA_PLUGIN).
|
|
// Returns an error if "pPluginFilespec" was not registered.
|
|
NPError fe_RegisterPlugin(char* pPluginFilespec)
|
|
{
|
|
CString strName, strDescription;
|
|
|
|
// initialize a new plugin list mgt block
|
|
NPPMgtBlk* pNPMgtBlk = new NPPMgtBlk;
|
|
if(pNPMgtBlk == NULL) // fatal, can't continue
|
|
return NPERR_OUT_OF_MEMORY_ERROR;
|
|
|
|
pNPMgtBlk->pPluginFuncs = NULL;
|
|
pNPMgtBlk->pLibrary = NULL;
|
|
pNPMgtBlk->uRefCount = 0;
|
|
pNPMgtBlk->next = NULL;
|
|
|
|
// determine the MIME type and version of this plugin
|
|
if(wfe_GetPluginProperties(pPluginFilespec, pNPMgtBlk, strName, strDescription) != NPERR_NO_ERROR)
|
|
{
|
|
delete pNPMgtBlk;
|
|
return NPERR_GENERIC_ERROR;
|
|
}
|
|
|
|
// if a plugin is already registered for this MIME type, return. this
|
|
// allows downloading and registering new plugins without exiting the nav
|
|
for(NPPMgtBlk* pListBlk = g_pRegisteredPluginList; pListBlk != NULL;
|
|
pListBlk = pListBlk->next) {
|
|
BOOL bSameFile =
|
|
(strcmp(pListBlk->pPluginFilename, pPluginFilespec) == 0);
|
|
BOOL bSameMIMEtype =
|
|
(strstr(pNPMgtBlk->szMIMEType, pListBlk->szMIMEType) != NULL);
|
|
if(bSameFile && bSameMIMEtype) {
|
|
// the plugin DLL's filename and the MIME type it's registering for
|
|
// are the same, don't reregister
|
|
delete pNPMgtBlk;
|
|
return NPERR_GENERIC_ERROR;
|
|
}
|
|
}
|
|
|
|
pNPMgtBlk->pPluginFilename = XP_STRDUP(pPluginFilespec);
|
|
if(pNPMgtBlk->pPluginFilename == NULL) // fatal, can't continue
|
|
{
|
|
delete pNPMgtBlk;
|
|
return NPERR_OUT_OF_MEMORY_ERROR;
|
|
}
|
|
|
|
// Register the plugin file with the XP plugin code
|
|
NPL_RegisterPluginFile(strName, pNPMgtBlk->pPluginFilename, strDescription,
|
|
pNPMgtBlk);
|
|
|
|
// Iterate through the filename extensions. These are a list which are
|
|
// delimited via the '|' character. The list of MIME Types,File Extents,
|
|
// and Open Names must all coordinate
|
|
char *pStartMIME, *pEndMIME, *pStartExt, *pEndExt, *pStartName, *pEndName;
|
|
|
|
pStartMIME = pNPMgtBlk->szMIMEType;
|
|
pStartExt = pNPMgtBlk->szFileExtents;
|
|
pStartName = pNPMgtBlk->szFileOpenName;
|
|
|
|
pEndMIME = strchr(pStartMIME ,'|');
|
|
while (pEndMIME) {
|
|
pEndExt = strchr(pStartExt,'|');
|
|
pEndName = strchr(pStartName,'|');
|
|
if (pEndMIME) *pEndMIME = 0;
|
|
else return NPERR_GENERIC_ERROR;
|
|
if (pEndExt) *pEndExt = 0;
|
|
else return NPERR_GENERIC_ERROR;
|
|
if (pEndName) *pEndName = 0;
|
|
else return NPERR_GENERIC_ERROR;
|
|
|
|
// Register the MIME type with the XP plugin code. We need to pass in
|
|
// a description. If there's a file open template specified, then use the
|
|
// description from there. Otherwise use the MIME type
|
|
LPSTR lpszDescription = NULL;
|
|
|
|
if (pStartName)
|
|
lpszDescription = ExtractDescription(pStartName);
|
|
|
|
NPL_RegisterPluginType(pStartMIME, (LPCSTR)pStartExt, lpszDescription ?
|
|
lpszDescription : pStartMIME, (void *)pStartName, pNPMgtBlk, TRUE);
|
|
|
|
if (lpszDescription)
|
|
XP_FREE(lpszDescription);
|
|
|
|
CHelperApp *pApp;
|
|
if(theApp.m_HelperListByType.Lookup(pStartMIME, (CObject *&)pApp)) {
|
|
// We've a match.
|
|
// Make sure the app is marked to handle the load
|
|
// via a plugin
|
|
pApp->how_handle = HANDLE_VIA_PLUGIN;
|
|
}
|
|
|
|
if ((pEndMIME+1) && (pEndExt+1) && (pEndName+1)) {
|
|
pStartMIME = pEndMIME+1;
|
|
pStartExt = pEndExt+1;
|
|
pStartName = pEndName+1;
|
|
}
|
|
pEndMIME = strchr(pStartMIME ,'|');
|
|
}
|
|
|
|
// Register the MIME type with the XP plugin code. We need to pass in
|
|
// a description. If there's a file open template specified, then use the
|
|
// description from there. Otherwise use the MIME type
|
|
LPSTR lpszDescription = NULL;
|
|
|
|
if (pStartName)
|
|
lpszDescription = ExtractDescription(pStartName);
|
|
|
|
NPL_RegisterPluginType(pStartMIME, (LPCSTR)pStartExt, lpszDescription ?
|
|
lpszDescription : pStartMIME, (void *)pStartName, pNPMgtBlk, TRUE);
|
|
|
|
if (lpszDescription)
|
|
XP_FREE(lpszDescription);
|
|
|
|
CHelperApp *pApp;
|
|
if(theApp.m_HelperListByType.Lookup(pStartMIME, (CObject *&)pApp)) {
|
|
// We've a match.
|
|
// Make sure the app is marked to handle the load
|
|
// via a plugin
|
|
pApp->how_handle = HANDLE_VIA_PLUGIN;
|
|
}
|
|
|
|
// insert the plugin mgt blk at the head of the list of registered plugins.
|
|
// this means they are listed in the reverse order from which they were
|
|
// created, which doesn't matter.
|
|
pNPMgtBlk->next = g_pRegisteredPluginList;
|
|
g_pRegisteredPluginList = pNPMgtBlk;
|
|
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
// FE_RegisterPlugins is called from navigator main via npglue's NP_Init(). Finds all
|
|
// plugins and begins tracking them using a NPPMgtBlk. Uses the NPPMgtBlk
|
|
// block handle to register the plugin with the xp plugin glue. Looks
|
|
// in the directory under the netscape.exe dir, named "plugins" and all
|
|
// subdirectories in recursive way (see fe_RegisterPlugins). If the
|
|
// directory doesn't exist, no warning dialog is shown.
|
|
// There are no input or return vals.
|
|
void fe_RegisterPlugins(char* pszPluginDir)
|
|
{
|
|
CString csPluginSpec;
|
|
csPluginSpec = pszPluginDir;
|
|
|
|
#if defined(JAVA)
|
|
// add directory to the java path no matter what
|
|
LJ_AddToClassPath(pszPluginDir);
|
|
#endif
|
|
|
|
if (thePluginManager == NULL) {
|
|
static NS_DEFINE_IID(kIPluginManagerIID, NS_IPLUGINMANAGER_IID);
|
|
nsresult rslt = nsPluginManager::Create(NULL, kIPluginManagerIID, (void**)&thePluginManager);
|
|
// XXX Out of memory already? This function should return an error code!
|
|
PR_ASSERT(rslt == NS_OK);
|
|
// keep going anyway...
|
|
}
|
|
|
|
csPluginSpec += "\\*.*";
|
|
|
|
#ifndef _WIN32
|
|
_find_t fileinfo;
|
|
unsigned result = _dos_findfirst((LPSTR)((LPCSTR)csPluginSpec), _A_NORMAL | _A_SUBDIR, &fileinfo );
|
|
|
|
if (result == 0) {
|
|
|
|
result = _dos_findnext(&fileinfo); // skip "."
|
|
result = _dos_findnext(&fileinfo); // skip ".."
|
|
|
|
CString csFileSpec;
|
|
|
|
while(result == 0)
|
|
{
|
|
csFileSpec = pszPluginDir;
|
|
csFileSpec += "\\";
|
|
csFileSpec += fileinfo.name;
|
|
|
|
// we got a subdir, call recursively this function to load plugin
|
|
if (fileinfo.attrib & _A_SUBDIR ) {
|
|
fe_RegisterPlugins((LPSTR)(LPCSTR)csFileSpec);
|
|
}
|
|
else {
|
|
size_t len = strlen(fileinfo.name);
|
|
|
|
// it's a file, see if it can be a plugin file
|
|
if ( len > 6 && // at least "np.dll"
|
|
(fileinfo.name[0] == 'n' || fileinfo.name[0] == 'N') &&
|
|
(fileinfo.name[1] == 'p' || fileinfo.name[1] == 'P') &&
|
|
!_stricmp(fileinfo.name + len - 4, ".dll"))
|
|
fe_RegisterPlugin((LPSTR)((LPCSTR)csFileSpec));
|
|
#ifdef EDITOR
|
|
// If it's a cpXXX.zip file,register it as a composer plugin.
|
|
else if ( len > 6 && // at least cp.zip
|
|
(fileinfo.name[0] == 'c' || fileinfo.name[0] == 'C') &&
|
|
(fileinfo.name[1] == 'p' || fileinfo.name[1] == 'P') &&
|
|
(!_stricmp(fileinfo.name + len - 4, ".zip")
|
|
|| !_stricmp(fileinfo.name + len - 4, ".jar"))
|
|
)
|
|
EDT_RegisterPlugin((LPSTR)((LPCSTR)csFileSpec));
|
|
#endif /* EDITOR */
|
|
}
|
|
result = _dos_findnext(&fileinfo);
|
|
}
|
|
}
|
|
#else /* _WIN32 */
|
|
_finddata_t fileinfo;
|
|
unsigned handle = _findfirst((LPSTR)((LPCSTR)csPluginSpec), &fileinfo );
|
|
unsigned result = 0;
|
|
|
|
if (handle != -1) {
|
|
result = _findnext(handle, &fileinfo); // skip "."
|
|
result = _findnext(handle, &fileinfo); // skip ".."
|
|
|
|
|
|
CString csFileSpec;
|
|
|
|
while((result != -1) && (handle != -1))
|
|
{
|
|
csFileSpec = pszPluginDir;
|
|
csFileSpec += "\\";
|
|
csFileSpec += fileinfo.name;
|
|
|
|
// we got a subdir, call recursively this function to load plugin
|
|
if (fileinfo.attrib & _A_SUBDIR ) {
|
|
fe_RegisterPlugins((LPSTR)(LPCSTR)csFileSpec);
|
|
}
|
|
else {
|
|
size_t len = strlen(fileinfo.name);
|
|
|
|
// it's a file, see if it can be a plugin file
|
|
if ( len > 6 && // at least "np.dll"
|
|
(fileinfo.name[0] == 'n' || fileinfo.name[0] == 'N') &&
|
|
(fileinfo.name[1] == 'p' || fileinfo.name[1] == 'P') &&
|
|
!_stricmp(fileinfo.name + len - 4, ".dll"))
|
|
fe_RegisterPlugin((LPSTR)((LPCSTR)csFileSpec));
|
|
#ifdef EDITOR
|
|
// If it's a cpXXX.zip file, add it to the java class path.
|
|
else if ( len > 6 && // at least cp.zip
|
|
(fileinfo.name[0] == 'c' || fileinfo.name[0] == 'C') &&
|
|
(fileinfo.name[1] == 'p' || fileinfo.name[1] == 'P') &&
|
|
(!_stricmp(fileinfo.name + len - 4, ".zip")
|
|
|| !_stricmp(fileinfo.name + len - 4, ".jar"))
|
|
)
|
|
EDT_RegisterPlugin((LPSTR)((LPCSTR)csFileSpec));
|
|
#endif
|
|
}
|
|
result = _findnext(handle, &fileinfo);
|
|
}
|
|
_findclose(handle);
|
|
}
|
|
#endif /* _WIN32 */
|
|
}
|
|
|
|
// called from the navigator main, dispatch to the previous function
|
|
void FE_RegisterPlugins()
|
|
{
|
|
CString csPluginDir;
|
|
// get the main plugins directory and start the process
|
|
wfe_GetPluginsDirectory(csPluginDir);
|
|
fe_RegisterPlugins((LPSTR)(LPCSTR)csPluginDir);
|
|
CString csJavaDir;
|
|
wfe_GetJavaDirectory(csJavaDir);
|
|
JVM_AddToClassPath(csJavaDir);
|
|
}
|
|
|
|
// saves the current path in the variable passed. ppPathSave is the
|
|
// address of the ptr which stores the path string. returns out of memory
|
|
// error if allocation for the string returned by _getcwd() fails. returns
|
|
// generic error if the "one deep" stack is already full.
|
|
NPError wfe_PushPath(LPSTR *ppPathSave)
|
|
{
|
|
// only allow "one deep" stack
|
|
if(*ppPathSave != NULL)
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
// save the CWD
|
|
*ppPathSave = _getcwd(NULL, 0);
|
|
if(*ppPathSave == NULL)
|
|
return NPERR_OUT_OF_MEMORY_ERROR;
|
|
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
// calculate the drive letter value for _chdrive(). ascii in, int out
|
|
int wfe_MapAsciiToDriveNum(char cAsciiNum)
|
|
{
|
|
int iDriveLetter = cAsciiNum;
|
|
if(islower(cAsciiNum))
|
|
iDriveLetter = _toupper(cAsciiNum);
|
|
// plus one because for _chdrive(), A = 1, B = 2, etc
|
|
return iDriveLetter - 'A' + 1;
|
|
}
|
|
|
|
// restores the path from the variable passed. pDirSave stores the pointer
|
|
// to the path string. returns an error if a path has never been pushed.
|
|
NPError wfe_PopPath(LPSTR pPathSave)
|
|
{
|
|
// only allows "one deep" stack
|
|
if(pPathSave == NULL)
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
// restore the drive
|
|
int chdriveErr = _chdrive(wfe_MapAsciiToDriveNum(pPathSave[0]));
|
|
|
|
// restore the CWD
|
|
int chdirErr = _chdir(pPathSave);
|
|
free(pPathSave);
|
|
|
|
return NPERR_NO_ERROR;
|
|
}
|
|
|
|
// Load a plugin dll. "pluginType" is a handle to a plugin management data
|
|
// structure created during FE_RegisterPlugins(). "pNavigatorFuncs" is
|
|
// a table of entry points into Navigator, which are the services provided
|
|
// by Navigator to plugins, such as requestread() and GetUrl(). These entry
|
|
// points are stored and called by the plugin when services are needed.
|
|
// The return val is a table of functions which are entry points to the
|
|
// newly loaded plugin, such as NewStream() and Write().
|
|
NPPluginFuncs* FE_LoadPlugin(void* pluginType, NPNetscapeFuncs* pNavigatorFuncs, np_handle* handle)
|
|
{
|
|
if(pluginType == NULL)
|
|
return NULL;
|
|
|
|
NPPMgtBlk* pNPMgtBlock = (NPPMgtBlk*)pluginType;
|
|
|
|
CString csPluginDir;
|
|
#ifdef OJI
|
|
char* szExplicitDLL = strrchr(pNPMgtBlock->pPluginFilename, '\\');
|
|
if( szExplicitDLL ) {
|
|
csPluginDir = pNPMgtBlock->pPluginFilename; // MFC copies the string
|
|
csPluginDir.SetAt( szExplicitDLL - pNPMgtBlock->pPluginFilename, '\0');
|
|
} else {
|
|
wfe_GetPluginsDirectory(csPluginDir);
|
|
}
|
|
#else
|
|
wfe_GetPluginsDirectory(csPluginDir);
|
|
#endif /* OJI */
|
|
|
|
LPSTR pPathSave = NULL; // storage for one dir spec
|
|
|
|
wfe_PushPath(&pPathSave); // save the current drive and dir
|
|
|
|
// change the default dir so that implib'd plugins won't fail
|
|
if(_chdir(csPluginDir) != 0) {
|
|
wfe_PopPath(pPathSave); // restore the path
|
|
return NULL;
|
|
}
|
|
|
|
// must change the drive as well as the dir path
|
|
if(isalpha(csPluginDir[0]) && csPluginDir[1] == ':') {
|
|
if(_chdrive(wfe_MapAsciiToDriveNum(csPluginDir[0])) != 0) {
|
|
wfe_PopPath(pPathSave); // restore the path
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
pNPMgtBlock->pLibrary = PR_LoadLibrary(pNPMgtBlock->pPluginFilename);
|
|
|
|
// the cross platform code should take care of the 16/32 bit issues
|
|
if(pNPMgtBlock->pLibrary == NULL)
|
|
return NULL;
|
|
|
|
nsFactoryProc nsGetFactory = (nsFactoryProc)
|
|
PR_FindSymbol(pNPMgtBlock->pLibrary, "NSGetFactory");
|
|
if (nsGetFactory != NULL) {
|
|
static NS_DEFINE_IID(kIPluginIID, NS_IPLUGIN_IID);
|
|
nsIPlugin* plugin = NULL;
|
|
nsresult res = nsGetFactory(kIPluginIID, (nsIFactory**)&plugin);
|
|
PR_ASSERT(thePluginManager != NULL);
|
|
if (res == NS_OK && plugin != NULL
|
|
&& plugin->Initialize((nsIPluginManager*)thePluginManager) == NS_OK) {
|
|
|
|
handle->userPlugin = plugin;
|
|
pNPMgtBlock->pPluginFuncs = (NPPluginFuncs*)-1; // something to say it's loaded, but != 0
|
|
#ifdef LATER // XXX coming soon...
|
|
// add the plugin directory if successful
|
|
JVM_AddToClassPathRecursively(csPluginDir);
|
|
#endif
|
|
}
|
|
else {
|
|
PR_UnloadLibrary(pNPMgtBlock->pLibrary);
|
|
wfe_PopPath(pPathSave); // restore the path
|
|
return NULL;
|
|
}
|
|
}
|
|
else {
|
|
|
|
NP_GETENTRYPOINTS getentrypoints =
|
|
(NP_GETENTRYPOINTS)PR_FindSymbol(pNPMgtBlock->pLibrary, "NP_GetEntryPoints");
|
|
if(getentrypoints == NULL)
|
|
{
|
|
PR_UnloadLibrary(pNPMgtBlock->pLibrary);
|
|
wfe_PopPath(pPathSave); // restore the path
|
|
return NULL;
|
|
}
|
|
|
|
if(pNPMgtBlock->pPluginFuncs == NULL)
|
|
{
|
|
pNPMgtBlock->pPluginFuncs = new NPPluginFuncs;
|
|
pNPMgtBlock->pPluginFuncs->size = sizeof NPPluginFuncs;
|
|
pNPMgtBlock->pPluginFuncs->javaClass = NULL;
|
|
if(pNPMgtBlock->pPluginFuncs == NULL) // fatal, can't continue
|
|
{
|
|
PR_UnloadLibrary(pNPMgtBlock->pLibrary);
|
|
wfe_PopPath(pPathSave); // restore the path
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if(getentrypoints(pNPMgtBlock->pPluginFuncs) != NPERR_NO_ERROR)
|
|
{
|
|
PR_UnloadLibrary(pNPMgtBlock->pLibrary);
|
|
delete pNPMgtBlock->pPluginFuncs;
|
|
pNPMgtBlock->pPluginFuncs = NULL;
|
|
wfe_PopPath(pPathSave); // restore the path
|
|
return NULL;
|
|
}
|
|
|
|
// if the plugin's major ver level is lower than the Navigator's,
|
|
// then they are incompatible, and should return an error
|
|
if(HIBYTE(pNPMgtBlock->pPluginFuncs->version) < NP_VERSION_MAJOR)
|
|
{
|
|
PR_UnloadLibrary(pNPMgtBlock->pLibrary);
|
|
delete pNPMgtBlock->pPluginFuncs;
|
|
pNPMgtBlock->pPluginFuncs = NULL;
|
|
wfe_PopPath(pPathSave); // restore the path
|
|
return NULL;
|
|
}
|
|
|
|
NP_PLUGININIT npinit = NULL;
|
|
|
|
// if this DLL is not already loaded, call its initialization entry point
|
|
if(pNPMgtBlock->uRefCount == 0) {
|
|
// the NP_Initialize entry point was misnamed as NP_PluginInit, early
|
|
// in plugin project development. Its correct name is documented
|
|
// now, and new developers expect it to work. However, I don't want
|
|
// to break the plugins already in the field, so I'll accept either
|
|
// name
|
|
npinit =
|
|
(NP_PLUGININIT)PR_FindSymbol(pNPMgtBlock->pLibrary, "NP_Initialize");
|
|
if(!npinit) {
|
|
npinit =
|
|
(NP_PLUGININIT)PR_FindSymbol(pNPMgtBlock->pLibrary, "NP_PluginInit");
|
|
}
|
|
}
|
|
|
|
if(npinit == NULL) {
|
|
PR_UnloadLibrary(pNPMgtBlock->pLibrary);
|
|
delete pNPMgtBlock->pPluginFuncs;
|
|
pNPMgtBlock->pPluginFuncs = NULL;
|
|
wfe_PopPath(pPathSave); // restore the path
|
|
return NULL;
|
|
}
|
|
|
|
if (npinit(pNavigatorFuncs) != NPERR_NO_ERROR) {
|
|
PR_UnloadLibrary(pNPMgtBlock->pLibrary);
|
|
delete pNPMgtBlock->pPluginFuncs;
|
|
pNPMgtBlock->pPluginFuncs = NULL;
|
|
wfe_PopPath(pPathSave); // restore the path
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
pNPMgtBlock->uRefCount++; // all is well, remember it was loaded
|
|
|
|
// can't pop the path until plugins have been completely loaded/init'd
|
|
wfe_PopPath(pPathSave); // restore the path
|
|
return pNPMgtBlock->pPluginFuncs;
|
|
}
|
|
|
|
// Unloads a plugin DLL. "pluginType" is a handle to a plugin management data
|
|
// structure created during FE_RegisterPlugins(). There is no return val.
|
|
void FE_UnloadPlugin(void* pluginType, struct _np_handle* handle)
|
|
{
|
|
NPPMgtBlk* pNPMgtBlk = (NPPMgtBlk*)pluginType;
|
|
if (pNPMgtBlk == NULL)
|
|
return;
|
|
|
|
// XXX Note that we're double refcounting here. If we were rewriting this
|
|
// from scratch, we could eliminate this pNPMgtBlk and its refcount and just
|
|
// rely on the one in the userPlugin.
|
|
|
|
pNPMgtBlk->uRefCount--; // another one bites the dust
|
|
|
|
// if this DLL is the last one, call its shutdown entry point
|
|
if (pNPMgtBlk->uRefCount == 0) {
|
|
if (handle->userPlugin) {
|
|
nsrefcnt cnt = handle->userPlugin->Release();
|
|
PR_ASSERT(cnt == 0);
|
|
|
|
#if 0 // XXX later...
|
|
// remove the plugin directory if successful
|
|
JVM_RemoveFromClassPathRecursively(csPluginDir);
|
|
#endif
|
|
}
|
|
else {
|
|
// the NP_Shutdown entry point was misnamed as NP_PluginShutdown, early
|
|
// in plugin project development. Its correct name is documented
|
|
// now, and new developers expect it to work. However, I don't want
|
|
// to break the plugins already in the field, so I'll accept either
|
|
// name
|
|
NP_PLUGINSHUTDOWN npshutdown =
|
|
(NP_PLUGINSHUTDOWN)PR_FindSymbol(pNPMgtBlk->pLibrary, "NP_Shutdown");
|
|
if (!npshutdown) {
|
|
npshutdown =
|
|
(NP_PLUGINSHUTDOWN)PR_FindSymbol(pNPMgtBlk->pLibrary, "NP_PluginShutdown");
|
|
}
|
|
|
|
if (npshutdown != NULL) {
|
|
NPError result = npshutdown();
|
|
}
|
|
}
|
|
}
|
|
|
|
PR_UnloadLibrary(pNPMgtBlk->pLibrary);
|
|
pNPMgtBlk->pLibrary = NULL;
|
|
|
|
if (handle->userPlugin) {
|
|
PR_ASSERT(pNPMgtBlk->pPluginFuncs == (NPPluginFuncs*)-1); // set in FE_LoadPlugin
|
|
handle->userPlugin = NULL;
|
|
}
|
|
else {
|
|
delete pNPMgtBlk->pPluginFuncs;
|
|
}
|
|
pNPMgtBlk->pPluginFuncs = NULL;
|
|
}
|
|
|
|
// Removes a plugin DLL from memory, and frees its NPPMgtBlk management block.
|
|
// "pluginType" is a handle to the plugin management data structure created
|
|
// during FE_RegisterPlugins(). There is no return val.
|
|
void FE_UnregisterPlugin(void* pluginType)
|
|
{
|
|
NPPMgtBlk* pNPMgtBlk = (NPPMgtBlk*)pluginType;
|
|
if(pNPMgtBlk == NULL)
|
|
return;
|
|
|
|
if(pNPMgtBlk->pLibrary != NULL)
|
|
PR_UnloadLibrary(pNPMgtBlk->pLibrary);
|
|
|
|
delete [] (char*)*pNPMgtBlk->pPluginFilename;
|
|
delete [] pNPMgtBlk->pPluginFilename;
|
|
delete [] pNPMgtBlk->szMIMEType;
|
|
delete pNPMgtBlk->pPluginFuncs;
|
|
delete pNPMgtBlk;
|
|
}
|
|
|
|
// Provides the entry point used by xp plugin code, (NPGLUE.C), to control
|
|
// scroll bars. The inputs are obvious, and there is no return val.
|
|
void FE_ShowScrollBars(MWContext* pContext, XP_Bool show)
|
|
{
|
|
if(ABSTRACTCX(pContext)->IsWindowContext()) {
|
|
CPaneCX *pPaneCX = PANECX(pContext);
|
|
|
|
pPaneCX->ShowScrollBars(SB_BOTH, show);
|
|
}
|
|
}
|
|
|
|
#ifdef XP_WIN32
|
|
void*
|
|
WFE_BeginSetModuleState()
|
|
{
|
|
return AfxSetModuleState(AfxGetAppModuleState());
|
|
}
|
|
|
|
void
|
|
WFE_EndSetModuleState(void* pPrevState)
|
|
{
|
|
AfxSetModuleState((AFX_MODULE_STATE*)pPrevState);
|
|
}
|
|
#endif
|
|
|
|
|