/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "npapi.h" #include #include #include #include #include #define PLUGINFINDER_COMMAND_BEGINNING "javascript:window.open(\"" #define PLUGINFINDER_COMMAND_END "\",\"plugin\",\"toolbar=no,status=no,resizable=no,scrollbars=no,height=252,width=626\");" #define PLUGINFINDER_COMMAND_END2 "\",\"plugin\",\"toolbar=no,status=no,resizable=yes,scrollbars=yes,height=252,width=626\");" // // Instance state information about the plugin. // class CPlugin { public: enum HiliteState { kUnhilited = 0, kHilited = 1 }; static NPError Initialize(); static void Shutdown(); // no ctor because CPlugin is allocated and constructed by hand. // ideally, this should use placement |new|. void Constructor(NPP instance, NPMIMEType type, uint16 mode, int16 argc, char* argn[], char* argv[]); void Destructor(); void SetWindow(NPWindow* window); void Print(NPPrint* printInfo); Boolean HandleEvent(EventRecord*); protected: void Draw(HiliteState hilite); void DrawString(const unsigned char* text, short width, short height, short centerX, Rect drawRect); void MouseDown(); Boolean FocusDraw(); void RestoreDraw(); void DetermineURL(int16 argc, char* argn[], char* argv[]); char * MakeDefaultURL(void); void AddMimeTypeToList(StringPtr cTypeString); Boolean CheckMimeTypes(); void AskAndLoadURL(); void RefreshPluginPage(); Ptr New(UInt32 size); void Delete(Ptr ptr); Boolean IsPluginHidden(int16 argc, char* argn[], char* argv[]); private: static CIconHandle sIconHandle; static CursHandle sHandCursor; static char* sAltText; static char* sInstallCommand; static char* sDefaultPage; static char* sRefreshText; static char* sJavaScriptPage; static FSSpec sDataFileSpec; // only used for Mac OS 9 static Boolean sRunningOnOSX; NPP fInstance; NPWindow* fWindow; uint16 fMode; NPMIMEType fType; char* fPageURL; char* fFileURL; NPBool m_bOffline; NPBool m_bJavaScript; GrafPtr fSavePort; RgnHandle fSaveClip; Rect fRevealedRect; short fSavePortTop; short fSavePortLeft; Boolean fUserInstalledPlugin; Boolean fHiddenPlugin; Boolean fAskedLoadURL; }; CIconHandle CPlugin::sIconHandle = NULL; CursHandle CPlugin::sHandCursor = NULL; char* CPlugin::sAltText = NULL; char* CPlugin::sInstallCommand = NULL; char* CPlugin::sDefaultPage = NULL; char* CPlugin::sRefreshText = NULL; char* CPlugin::sJavaScriptPage = NULL; FSSpec CPlugin::sDataFileSpec; Boolean CPlugin::sRunningOnOSX = false; extern short gResFile; // 'cicn' const short rBrokenPluginIcon = 326; // 'CURS' const short rHandCursor = 128; // 'STR ' const short rDefaultPluginURL = 128; const short rAltTextString = 129; const short rJavaScriptInstallCommand = 130; const short rRefreshTextString = 131; const short rJavaScriptPageURL = 132; // 'STR#' const short rTypeListStrings = 129; static const char szPluginFinderCommandBeginning[] = PLUGINFINDER_COMMAND_BEGINNING; static const char szPluginFinderCommandEnd[] = PLUGINFINDER_COMMAND_END; //------------------------------------------------------------------------------------ // NPP_Initialize: //------------------------------------------------------------------------------------ NPError NPP_Initialize(void) { return CPlugin::Initialize(); } //------------------------------------------------------------------------------------ // NPP_Shutdown: //------------------------------------------------------------------------------------ void NPP_Shutdown(void) { CPlugin::Shutdown(); } //------------------------------------------------------------------------------------ // NPP_New: //------------------------------------------------------------------------------------ NPError NPP_New(NPMIMEType type, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData*) { if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; CPlugin* This = (CPlugin*) (char*)NPN_MemAlloc(sizeof(CPlugin)); instance->pdata = This; if (This != NULL) { This->Constructor(instance, type, mode, argc, argn, argv); return NPERR_NO_ERROR; } else return NPERR_OUT_OF_MEMORY_ERROR; } //------------------------------------------------------------------------------------ // NPP_Destroy: //------------------------------------------------------------------------------------ NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** /*save*/) { if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; CPlugin* This = (CPlugin*) instance->pdata; if (This != NULL) { This->Destructor(); NPN_MemFree(This); instance->pdata = NULL; } return NPERR_NO_ERROR; } //------------------------------------------------------------------------------------ // NPP_SetWindow: //------------------------------------------------------------------------------------ NPError NPP_SetWindow(NPP instance, NPWindow* window) { if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; CPlugin* This = (CPlugin*) instance->pdata; if (This != NULL) This->SetWindow(window); return NPERR_NO_ERROR; } //------------------------------------------------------------------------------------ // NPP_NewStream: //------------------------------------------------------------------------------------ NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType /*type*/, NPStream* /*stream*/, NPBool /*seekable*/, uint16* /*stype*/) { if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; return NPERR_NO_ERROR; } int32 STREAMBUFSIZE = 0X0FFFFFFF; // If we are reading from a file in NPAsFile // mode so we can take any size stream in our // write call (since we ignore it) //------------------------------------------------------------------------------------ // NPP_WriteReady: //------------------------------------------------------------------------------------ int32 NP_LOADDS NPP_WriteReady(NPP /*instance*/, NPStream* /*stream*/) { return STREAMBUFSIZE; // Number of bytes ready to accept in NPP_Write() } //------------------------------------------------------------------------------------ // NPP_Write: //------------------------------------------------------------------------------------ int32 NP_LOADDS NPP_Write(NPP /*instance*/, NPStream* /*stream*/, int32 /*offset*/, int32 len, void* /*buffer*/) { return len; // The number of bytes accepted } //------------------------------------------------------------------------------------ // NPP_DestroyStream: //------------------------------------------------------------------------------------ NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* /*stream*/, NPError /*reason*/) { if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; return NPERR_NO_ERROR; } //------------------------------------------------------------------------------------ // NPP_StreamAsFile: //------------------------------------------------------------------------------------ void NP_LOADDS NPP_StreamAsFile(NPP /*instance*/, NPStream */*stream*/, const char* /*fname*/) { } //------------------------------------------------------------------------------------ // NPP_Print: //------------------------------------------------------------------------------------ void NP_LOADDS NPP_Print(NPP instance, NPPrint* printInfo) { if (printInfo == NULL) return; if (instance != NULL) { if (printInfo->mode == NP_FULL) printInfo->print.fullPrint.pluginPrinted = FALSE; // Do the default else // If not fullscreen, we must be embedded { CPlugin* This = (CPlugin*) instance->pdata; if (This != NULL) This->Print(printInfo); } } } //------------------------------------------------------------------------------------ // NPP_HandleEvent: // Mac-only. //------------------------------------------------------------------------------------ int16 NPP_HandleEvent(NPP instance, void* event) { if (instance != NULL) { CPlugin* This = (CPlugin*) instance->pdata; if (This != NULL && event != NULL) return This->HandleEvent((EventRecord*) event); } return FALSE; } //------------------------------------------------------------------------------------ // NPP_URLNotify: //------------------------------------------------------------------------------------ void NPP_URLNotify(NPP /*instance*/, const char* /*url*/, NPReason /*reason*/, void* /*notifyData*/) { } #ifdef OJI //------------------------------------------------------------------------------------ // NPP_GetJavaClass: //------------------------------------------------------------------------------------ jref NPP_GetJavaClass(void) { return NULL; } #endif /* OJI */ #pragma mark - //------------------------------------------------------------------------------------ // CPlugin::Initialize: //------------------------------------------------------------------------------------ NPError CPlugin::Initialize() { Handle string; short saveResFile = CurResFile(); UseResFile(gResFile); long systemVersion; OSErr err = ::Gestalt(gestaltSystemVersion, &systemVersion); sRunningOnOSX = (err == noErr) && (systemVersion >= 0x00001000); // Get Resources CPlugin::sIconHandle = GetCIcon(rBrokenPluginIcon); CPlugin::sHandCursor = GetCursor(rHandCursor); // Get "alt text" string string = Get1Resource('STR ', rAltTextString); if (string && *string) { short stringLen = (*string)[0]; CPlugin::sAltText = (char*)NPN_MemAlloc(stringLen +1); if (CPlugin::sAltText != NULL) { short src = 1; short dest = 0; while (src <= stringLen) CPlugin::sAltText[dest++] = (*string)[src++]; CPlugin::sAltText[dest++] = 0; } } ReleaseResource(string); // Get "refresh text" string string = Get1Resource('STR ', rRefreshTextString); if (string && *string) { short stringLen = (*string)[0]; CPlugin::sRefreshText = (char*)NPN_MemAlloc(stringLen + 1); if (CPlugin::sRefreshText != NULL) { short src = 1; short dest = 0; while (src <= stringLen) CPlugin::sRefreshText[dest++] = (*string)[src++]; CPlugin::sRefreshText[dest++] = 0; } } ReleaseResource(string); // Get JavaScript install command string string = Get1Resource('STR ', rJavaScriptInstallCommand); if (string && *string) { short stringLen = (*string)[0]; CPlugin::sInstallCommand = (char*)NPN_MemAlloc(stringLen + 1); if (CPlugin::sInstallCommand != NULL) { short src = 1; short dest = 0; while (src <= stringLen) CPlugin::sInstallCommand[dest++] = (*string)[src++]; CPlugin::sInstallCommand[dest++] = 0; } } ReleaseResource(string); // Get default plug-in page URL string = Get1Resource('STR ', rDefaultPluginURL); if (string && *string) { short stringLen = (*string)[0]; CPlugin::sDefaultPage = (char*)NPN_MemAlloc(stringLen + 1); if (CPlugin::sDefaultPage != NULL) { short src = 1; short dest = 0; while (src <= stringLen) CPlugin::sDefaultPage[dest++] = (*string)[src++]; CPlugin::sDefaultPage[dest++] = 0; } } ReleaseResource(string); // Get javascript plug-in page URL string = Get1Resource('STR ', rJavaScriptPageURL); if (string && *string) { short stringLen = (*string)[0]; CPlugin::sJavaScriptPage = (char*)NPN_MemAlloc(stringLen + 1); if (CPlugin::sJavaScriptPage != NULL) { short src = 1; short dest = 0; while (src <= stringLen) CPlugin::sJavaScriptPage[dest++] = (*string)[src++]; CPlugin::sJavaScriptPage[dest++] = 0; } } ReleaseResource(string); UseResFile(saveResFile); if (!sRunningOnOSX) // We'll make some CFPreferences the first time we have to on OS X { ProcessSerialNumber psn; ProcessInfoRec info; FSSpec fsTheApp; SInt16 wResFile; OSErr wErr; psn.highLongOfPSN = 0; psn.lowLongOfPSN = kCurrentProcess; info.processInfoLength = sizeof(ProcessInfoRec); info.processName = nil; info.processAppSpec = &fsTheApp; wErr = ::GetProcessInformation(&psn, &info); if (wErr == noErr) { wErr = FSMakeFSSpec(fsTheApp.vRefNum, fsTheApp.parID, "\p:Plug-ins:Default Plug-in Data", &sDataFileSpec); if (wErr == fnfErr) { FSpCreateResFile(&sDataFileSpec, 'MOSS', 'BINA', smSystemScript); wResFile = FSpOpenResFile(&CPlugin::sDataFileSpec, fsRdWrPerm); if (wResFile != -1) { // create a STR# with 0 entires (i.e. only a count) string = NewHandleClear(sizeof(SInt16)); AddResource(string, 'STR#', rTypeListStrings, "\p"); UpdateResFile(wResFile); ReleaseResource(string); } FSClose(wResFile); } } } return NPERR_NO_ERROR; } //------------------------------------------------------------------------------------ // CPlugin::Shutdown: //------------------------------------------------------------------------------------ void CPlugin::Shutdown() { if (CPlugin::sIconHandle != NULL) ::ReleaseResource((Handle) CPlugin::sIconHandle); if (CPlugin::sHandCursor != NULL) ::ReleaseResource((Handle) CPlugin::sHandCursor); if (CPlugin::sAltText != NULL) NPN_MemFree(CPlugin::sAltText); if (CPlugin::sInstallCommand != NULL) NPN_MemFree(CPlugin::sInstallCommand); if (CPlugin::sDefaultPage != NULL) NPN_MemFree(CPlugin::sDefaultPage); if(CPlugin::sRefreshText != NULL) NPN_MemFree(CPlugin::sRefreshText); } //------------------------------------------------------------------------------------ // CPlugin::Constructor: //------------------------------------------------------------------------------------ void CPlugin::Constructor(NPP instance, NPMIMEType type, uint16 mode, int16 argc, char* argn[], char* argv[]) { fWindow = NULL; fPageURL = NULL; fFileURL = NULL; fInstance = instance; fMode = mode; // Mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h) fAskedLoadURL = false; fUserInstalledPlugin = false; // Save a copy of our mime type string short typeLength = strlen(type); fType = (char*)NPN_MemAlloc(typeLength+1); if (fType != NULL) strcpy(fType, type); // Make a handy region for use in FocusDraw fSaveClip = NewRgn(); // determine if the plugin is specified as HIDDEN if(IsPluginHidden(argc, argn, argv)) fHiddenPlugin = true; else fHiddenPlugin = false; // Get some information about our environment NPN_GetValue(fInstance, NPNVisOfflineBool, (void *)&m_bOffline); NPN_GetValue(fInstance, NPNVjavascriptEnabledBool, (void *)&m_bJavaScript); // Figure out what URL we will go to DetermineURL(argc, argn, argv); } //------------------------------------------------------------------------------------ // CPlugin::Destructor: //------------------------------------------------------------------------------------ void CPlugin::Destructor() { if (fSaveClip != NULL) DisposeRgn(fSaveClip); if (fType != NULL) NPN_MemFree(fType); if (fFileURL != NULL) NPN_MemFree(fFileURL); if (fPageURL != NULL) NPN_MemFree(fPageURL); } //------------------------------------------------------------------------------------ // CPlugin::SetWindow: //------------------------------------------------------------------------------------ void CPlugin::SetWindow(NPWindow* window) { fWindow = window; } //------------------------------------------------------------------------------------ // CPlugin::Print: // // To print, we need to retrieve the printing window from the printInfo, // temporarily make it our window, draw into it, and restore the window. // //------------------------------------------------------------------------------------ void CPlugin::Print(NPPrint* printInfo) { NPWindow* printWindow = &(printInfo->print.embedPrint.window); NPWindow* oldWindow = fWindow; fWindow = printWindow; if (FocusDraw()) { Draw(kUnhilited); RestoreDraw(); } fWindow = oldWindow; } //------------------------------------------------------------------------------------ // CPlugin::HandleEvent: //------------------------------------------------------------------------------------ Boolean CPlugin::HandleEvent(EventRecord* ev) { Boolean eventHandled = false; switch (ev->what) { case mouseDown: MouseDown(); eventHandled = true; break; case updateEvt: if (FocusDraw()) { Draw(kUnhilited); RestoreDraw(); } eventHandled = true; break; case NPEventType_AdjustCursorEvent: if (CPlugin::sHandCursor != NULL) SetCursor(*CPlugin::sHandCursor); if (fUserInstalledPlugin) { if (CPlugin::sRefreshText != NULL) NPN_Status(fInstance, CPlugin::sRefreshText); } else { if (CPlugin::sAltText != NULL) NPN_Status(fInstance, CPlugin::sAltText); } eventHandled = true; break; case nullEvent: // // NOTE: We have to wait until idle time // to ask the user if they want to visit // the URL to avoid reentering XP code. // if (!fAskedLoadURL) { if (CheckMimeTypes()) AskAndLoadURL(); fAskedLoadURL = true; } break; default: break; } return eventHandled; } //------------------------------------------------------------------------------------ // CPlugin::Draw: //------------------------------------------------------------------------------------ void CPlugin::Draw(HiliteState hilite) { UInt8 *pTheText; SInt32 height = fWindow->height; SInt32 width = fWindow->width; SInt32 centerX = (width) >> 1; SInt32 centerY = (height) >> 1; Rect drawRect; RGBColor black = { 0x0000, 0x0000, 0x0000 }; RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF }; RGBColor hiliteColor = { 0x0000, 0x0000, 0x0000 }; short transform; drawRect.top = 0; drawRect.left = 0; drawRect.bottom = height; drawRect.right = width; if (height < 4 && width < 4) return; PenNormal(); RGBForeColor(&black); RGBBackColor(&white); Pattern qdWhite; FillRect(&drawRect, GetQDGlobalsWhite(&qdWhite)); if (hilite == kHilited) { hiliteColor.red = 0xFFFF; transform = ttSelected; } else { hiliteColor.blue = 0xFFFF; transform = ttNone; } RGBForeColor(&hiliteColor); FrameRect(&drawRect); if (height > 32 && width > 32 && CPlugin::sIconHandle != NULL) { drawRect.top = centerY - 16; drawRect.bottom = centerY + 16; drawRect.left = centerX - 16; drawRect.right = centerX + 16; PlotCIconHandle(&drawRect, atAbsoluteCenter, transform, CPlugin::sIconHandle); } if (fUserInstalledPlugin) { pTheText = (unsigned char*)CPlugin::sRefreshText; } else { pTheText = (unsigned char*)CPlugin::sAltText; } DrawString(pTheText, width, height, centerX, drawRect); } //------------------------------------------------------------------------------------ // CPlugin::MouseDown: // // Track the click in our plugin by drawing the icon enabled or disabled // as the user moves the mouse in and out with the button held down. If // they let up the mouse while still inside, get the URL. // //------------------------------------------------------------------------------------ void CPlugin::MouseDown() { if (FocusDraw()) { Draw(kHilited); Boolean inside = true; // evil CPU-hogging loop on Mac OS X! while (StillDown()) { Point localMouse; GetMouse(&localMouse); Boolean insideNow = ::PtInRect(localMouse, &fRevealedRect); if (insideNow != inside) { Draw(insideNow ? kHilited : kUnhilited); inside = insideNow; } } if (inside) { Draw(kUnhilited); if (!fUserInstalledPlugin) AskAndLoadURL(); else RefreshPluginPage(); } RestoreDraw(); } } //------------------------------------------------------------------------------------ // CPlugin::FocusDraw: //------------------------------------------------------------------------------------ Boolean CPlugin::FocusDraw() { if (fWindow == NULL) return false; NP_Port* npport = (NP_Port*) fWindow->window; CGrafPtr ourPort = npport->port; if (fWindow->clipRect.left < fWindow->clipRect.right) { GetPort(&fSavePort); SetPort((GrafPtr) ourPort); Rect portRect; GetPortBounds(ourPort, &portRect); fSavePortTop = portRect.top; fSavePortLeft = portRect.left; GetClip(fSaveClip); fRevealedRect.top = fWindow->clipRect.top + npport->porty; fRevealedRect.left = fWindow->clipRect.left + npport->portx; fRevealedRect.bottom = fWindow->clipRect.bottom + npport->porty; fRevealedRect.right = fWindow->clipRect.right + npport->portx; SetOrigin(npport->portx, npport->porty); ClipRect(&fRevealedRect); return true; } else return false; } //------------------------------------------------------------------------------------ // CPlugin::RestoreDraw: //------------------------------------------------------------------------------------ void CPlugin::RestoreDraw() { SetOrigin(fSavePortLeft, fSavePortTop); SetClip(fSaveClip); SetPort(fSavePort); } //------------------------------------------------------------------------------------ // CPlugin::DetermineURL: // // Get a URL from either the parameters passed from the EMBED. // Append "?" and our mime type and save for later use. // //------------------------------------------------------------------------------------ void CPlugin::DetermineURL(int16 argc, char* argn[], char* argv[]) { char* url; SInt32 additionalLength = 0; SInt32 i; // Appended to the URL will be a "?" and the mime type of this instance. This lets the server // do something intelligent with a CGI script. if (fType != NULL) additionalLength += (strlen(fType) + 1); // Add 1 for '?' // The page designer can specify a URL where the plugin for this type can be downloaded. Here // we scan the arguments for this attribute and save it away if we // find it for later use by LoadPluginURL(). // for (i = 0; i < argc; i++) { if ((strcasecmp(argn[i], "PLUGINSPAGE") == 0) || (strcasecmp(argn[i], "CODEBASE") == 0)) { url = argv[i]; fPageURL = (char*)NPN_MemAlloc(strlen(url) + 1 + additionalLength); // Add 1 for '\0' if (fPageURL != NULL) { if (additionalLength > 0) { sprintf(fPageURL, "%s?%s", url, fType); } else { strcpy(fPageURL, url); } } break; } else if ((strcasecmp(argn[i], "PLUGINURL") == 0) || (strcasecmp(argn[i], "CLASSID") == 0)) { url = argv[i]; if (CPlugin::sInstallCommand != NULL) { // Allocate a new string fFileURL = (char*)NPN_MemAlloc(strlen(CPlugin::sInstallCommand) + 1 + strlen(url)); if (fFileURL != NULL) sprintf(fFileURL, CPlugin::sInstallCommand, url); } break; } } } //------------------------------------------------------------------------------------ // CPlugin::MakeDefaultURL: // // Get a URL from our resources. Append "?" and our mime type and save for later use. // //------------------------------------------------------------------------------------ char *CPlugin::MakeDefaultURL(void) { char *pDefURL = NULL; SInt32 additionalLength = 0; // Appended to the URL will be a "?" and the mime type of this instance. This lets the server // do something intelligent with a CGI script. if (fType != NULL) additionalLength += (strlen(fType) + 1); // Add 1 for '?' if (!m_bJavaScript) { if (CPlugin::sDefaultPage != NULL) { pDefURL = (char*)NPN_MemAlloc(strlen(CPlugin::sDefaultPage) + 1 + additionalLength); if (pDefURL != NULL) { if (additionalLength > 0) { sprintf(pDefURL, "%s?%s", CPlugin::sDefaultPage, fType); } else { strcpy(pDefURL, CPlugin::sDefaultPage); } } } } else { if (CPlugin::sJavaScriptPage != NULL) { pDefURL = (char*)NPN_MemAlloc(strlen(szPluginFinderCommandBeginning) + strlen(CPlugin::sJavaScriptPage) + additionalLength + strlen(szPluginFinderCommandEnd) + 1); if (pDefURL != NULL) { sprintf(pDefURL, "%s%s%s%s", szPluginFinderCommandBeginning, CPlugin::sJavaScriptPage, fType, szPluginFinderCommandEnd); } } } return(pDefURL); } //------------------------------------------------------------------------------------ // CPlugin::AddMimeTypeToList: // // Check the mime type of this instance against our list // of types weÕve seen before. If we find our type in the // list, return false; otherwise, return true. // // type 'STR#' { // integer = $$Countof(StringArray); // array StringArray { // pstring; // }; // //------------------------------------------------------------------------------------ void CPlugin::AddMimeTypeToList(StringPtr cTypeString) { if (sRunningOnOSX) { CFStringRef pluginKey = CFSTR("DefaultPluginSeenTypes"); // don't release this CFStringRef mimeType = ::CFStringCreateWithPascalString(kCFAllocatorDefault, cTypeString, kCFStringEncodingASCII); CFArrayRef prefsList = (CFArrayRef)::CFPreferencesCopyAppValue(pluginKey, kCFPreferencesCurrentApplication); Boolean foundType = false; if (prefsList == NULL) { CFStringRef stringArray[1]; stringArray[0] = mimeType; prefsList = ::CFArrayCreate(kCFAllocatorDefault, (const void **)stringArray, 1, &kCFTypeArrayCallBacks); if (prefsList) { ::CFPreferencesSetAppValue(pluginKey, prefsList, kCFPreferencesCurrentApplication); ::CFRelease(prefsList); } } else { if (::CFGetTypeID(prefsList) == ::CFArrayGetTypeID()) { // first make sure it's not in the list CFIndex count = ::CFArrayGetCount(prefsList); for (CFIndex i = 0; i < count; i ++) { CFStringRef item = (CFStringRef)::CFArrayGetValueAtIndex(prefsList, i); // does not retain if (item && (::CFGetTypeID(item) == ::CFStringGetTypeID()) && (::CFStringCompareWithOptions(item, mimeType, CFRangeMake(0, ::CFStringGetLength(item)), kCFCompareCaseInsensitive) == kCFCompareEqualTo)) { foundType = true; break; } } if (!foundType && !fHiddenPlugin) { CFMutableArrayRef typesArray = ::CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, (CFArrayRef)prefsList); if (typesArray) { ::CFArrayAppendValue(typesArray, mimeType); ::CFPreferencesSetAppValue(pluginKey, typesArray, kCFPreferencesCurrentApplication); } } } ::CFRelease(prefsList); } ::CFRelease(mimeType); } else { Handle hTypeList; SInt32 dwCount; SInt32 index; Str255 oldType; SInt16 wResFile; Boolean failedToFind = true; wResFile = FSpOpenResFile(&CPlugin::sDataFileSpec, fsRdWrPerm); if (wResFile != -1) { hTypeList = Get1Resource('STR#', rTypeListStrings); if (hTypeList != NULL) { dwCount = **((short **)hTypeList); // First make sure it's not already in the list. for (index = 1; index <= dwCount; index++) { GetIndString(oldType, rTypeListStrings, index); // if the mimetype already exists in our list, or the plugin is NOT hidden, // don't bring up the dialog box if (EqualString(cTypeString, oldType, true, true) && !fHiddenPlugin) { failedToFind = false; break; // Found a match, so bail out! } } if (failedToFind) { // Grow the string list handle Size itsSize = GetHandleSize(hTypeList); Size typeSize = cTypeString[0] + 1; SetHandleSize(hTypeList, itsSize + typeSize); // Increment the count of strings in the list (**((short**)hTypeList)) = (short)(++dwCount); // Copy the data from our string into the handle long dwCount = Munger(hTypeList, itsSize, NULL, typeSize, cTypeString, typeSize); // Mark the resource as changed so it will be written out if (dwCount > 0) { ChangedResource(hTypeList); UpdateResFile(wResFile); } } ReleaseResource(hTypeList); } FSClose(wResFile); } } } //------------------------------------------------------------------------------------ // CPlugin::CheckMimeTypes: // // Check the mime type of this instance against our list // of types weÕve seen before. If we find our type in the // list, return false; otherwise, return true. // // type 'STR#' { // integer = $$Countof(StringArray); // array StringArray { // pstring; // }; // //------------------------------------------------------------------------------------ Boolean CPlugin::CheckMimeTypes() { Boolean failedToFind = true; if (sRunningOnOSX) { CFStringRef pluginKey = CFSTR("DefaultPluginSeenTypes"); // don't release this CFStringRef mimeType = ::CFStringCreateWithCString(kCFAllocatorDefault, fType, kCFStringEncodingASCII); CFArrayRef prefsList = (CFArrayRef)::CFPreferencesCopyAppValue(pluginKey, kCFPreferencesCurrentApplication); if (prefsList) { if (::CFGetTypeID(prefsList) == ::CFArrayGetTypeID()) { CFIndex count = ::CFArrayGetCount(prefsList); for (CFIndex i = 0; i < count; i ++) { CFStringRef item = (CFStringRef)::CFArrayGetValueAtIndex(prefsList, i); // does not retain if (item && (::CFGetTypeID(item) == ::CFStringGetTypeID()) && (::CFStringCompareWithOptions(item, mimeType, CFRangeMake(0, ::CFStringGetLength(item)), kCFCompareCaseInsensitive) == kCFCompareEqualTo)) { failedToFind = false; break; } } } ::CFRelease(prefsList); } ::CFRelease(mimeType); } else { Handle hTypeList; SInt32 index; Str255 oldType; Str255 ourType; SInt16 wResFile; wResFile = FSpOpenResFile(&CPlugin::sDataFileSpec, fsRdPerm); if (wResFile != -1) { hTypeList = Get1Resource('STR#', rTypeListStrings); if (hTypeList != NULL) { // Convert the mime-type C string to a Pascal string. index = strlen(fType); if (index > 255) { // don't blow out the Str255 index = 255; } BlockMoveData(fType, &ourType[1], index); ourType[0] = index; short count = **((short **)hTypeList); // Iterate through all the strings in the list. for (index = 1; index <= count; index++) { GetIndString(oldType, rTypeListStrings, index); // if the mimetype already exists in our list, or the plugin is NOT hidden, // don't bring up the dialog box if (EqualString(ourType, oldType, true, true) && !fHiddenPlugin) { failedToFind = false; break; // Found a match, so bail out! } } ReleaseResource(hTypeList); } FSClose(wResFile); } } return(failedToFind); } //------------------------------------------------------------------------------------ // CPlugin::AskAndLoadURL: //------------------------------------------------------------------------------------ void CPlugin::AskAndLoadURL() { char *pTheURL; SInt32 dwLen; Str255 ourType; if (!m_bOffline) { // Convert the mime-type C string to a Pascal string. dwLen = strlen(fType); if (dwLen > 255) { // don't blow out the Str255 dwLen = 255; } BlockMoveData(fType, &ourType[1], dwLen); ourType[0] = dwLen; // NOTE: We need to set the cursor because almost always we will have set it to the // hand cursor before we get here. Cursor qdArrow; SetCursor(GetQDGlobalsArrow(&qdArrow)); // Now that weÕve queried the user about this mime type, // add it to our list so we wonÕt bug them again. AddMimeTypeToList(ourType); // // If the user clicked "Get the Plug-in", either execute the // JavaScript file-installation URL, or ask Netscape to open // a new window with the page URL. The title of the window // is arbitrary since it has nothing to do with the actual // window title shown to the user (itÕs only used internally). // NPN_PushPopupsEnabledState(fInstance, true); if (fFileURL != NULL) { (void) NPN_GetURL(fInstance, fFileURL, "_current"); } else if (fPageURL != NULL) { NPN_GetURL(fInstance, fPageURL, "_blank"); } else { pTheURL = MakeDefaultURL(); if (!m_bJavaScript) { NPN_GetURL(fInstance, pTheURL, "_blank"); } else { NPN_GetURL(fInstance, pTheURL, NULL); } NPN_MemFree(pTheURL); } NPN_PopPopupsEnabledState(fInstance); fUserInstalledPlugin = true; if (FocusDraw()) { Draw(kUnhilited); RestoreDraw(); } } } void CPlugin::RefreshPluginPage() { (void) NPN_GetURL(fInstance, "javascript:navigator.plugins.refresh(true);", "_self"); } void CPlugin::DrawString(const unsigned char* text, short width, short height, short centerX, Rect drawRect) { short length, textHeight, textWidth; if(text == NULL) return; length = strlen((char*)text); TextFont(20); TextFace(underline); TextMode(srcCopy); TextSize(10); FontInfo fontInfo; GetFontInfo(&fontInfo); textHeight = fontInfo.ascent + fontInfo.descent + fontInfo.leading; textWidth = TextWidth(text, 0, length); if (width > textWidth && height > textHeight + 32) { MoveTo(centerX - (textWidth >> 1), drawRect.bottom + textHeight); DrawText(text, 0, length); } } Boolean CPlugin::IsPluginHidden(int16 argc, char* argn[], char* argv[]) { int i; for(i=0; i