home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-04-08 | 30.2 KB | 1,063 lines |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * 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.
- */
-
- // umimemap.cp
- // CMimeMapper class and CMimeList
- // Created by atotic, June 6th, 1994
- // ===========================================================================
-
- // Front End
- #include "umimemap.h"
- #include "macutil.h"
- #include "resae.h"
- #include "uapp.h"
- #include "CAppleEventHandler.h"
- #include "ulaunch.h"
- #include "ufilemgr.h"
- #include "uprefd.h"
- #include "resgui.h"
- #include "BufferStream.h"
-
- // Netscape
- #include "client.h"
- #include "net.h"
- // stdc
- #include <String.h>
-
- #include "uerrmgr.h"
- #include "prefapi.h"
-
- //----------------------------------------------------------------------
- // class CMimeMapper
- //----------------------------------------------------------------------
-
- // ÑÑ Constructors/destructors
-
- // Initialize all the variables to defaults
- // Every initializer calls it
- void CMimeMapper::InitMapper()
- {
- fTemporary = false; // This is only a temporary mapper
- fRegisteredViewer = false; // This is a registered viewer, use all the special codes
- fTempAppSig = '????'; // Application
- fTempFileType = '????'; // File signature
- fFromOldPrefs = false; // Was this mapper from pre-plugin prefs?
- fLatentPlugin = false; // Was the plug-in disabled because it╒s missing?
- fLoadAction = CMimeMapper::Unknown;
- fBasePref = nil; // Corresponding XP pref branch name
- }
-
-
- Boolean
- CMimeMapper::NetscapeCanHandle(CStr255& mimeType)
- {
- return ((mimeType == IMAGE_GIF) ||
- (mimeType == IMAGE_JPG) ||
- (mimeType == IMAGE_XBM) ||
- (mimeType == APPLICATION_BINHEX) ||
- (mimeType == HTML_VIEWER_APPLICATION_MIME_TYPE) ||
- (mimeType == TEXT_PLAIN));
- }
-
-
- // ÑÑ XP Prefs
- //
- // CMimeMapper is technically now redundant because all the information
- // it contains is also reflected in xp prefs. Keeping duplicate
- // structures is not ideal but it's minimal-impact.
- //
- // The xp pref routines are:
- // - CreateMapperFor: creates a mapper corresponding to a specific
- // xp mime pref (e.g. mime.image_gif)
- // - ReadMimePref: converts an xp pref to a mapper (called from
- // CreateMapperFor, and when xp prefs are updated by auto-config).
- // - WriteMimePref: converts a mapper to its xp pref representation
- // (called when initializing 3.0-format preferences, after editing
- // a mime type from its pref UI, and when registering plug-ins).
-
- static const char* Pref_MimeType = ".mimetype";
- static const char* Pref_AppName = ".mac_appname";
- static const char* Pref_AppSig = ".mac_appsig";
- static const char* Pref_FileType = ".mac_filetype";
- static const char* Pref_Extension = ".extension";
- static const char* Pref_PluginName = ".mac_plugin_name";
- static const char* Pref_Description = ".description";
- static const char* Pref_LoadAction = ".load_action";
- static const char* Pref_LatentPlugin = ".latent_plug_in";
-
- // CreateMapperFor converts an xp pref name into a mimetype mapper.
- // Finds an existing mapper or creates a new one, and
- // populates its fields from user pref values.
- CMimeMapper* CMimeMapper::CreateMapperFor( const char* basepref, Boolean newPrefFormat )
- {
- CMimeMapper* mapper = CPrefs::sMimeTypes.FindBasePref(basepref);
-
- if (mapper) {
- mapper->ReadMimePrefs();
- return NULL; // already exists; caller doesn't use it.
- }
- else {
- mapper = new CMimeMapper(basepref);
- // FromOldPrefs triggers plug-ins to install themselves as preferred viewers
- mapper->fFromOldPrefs = !newPrefFormat;
- return mapper;
- }
- }
-
- // CreateMapperForRes converts a 3.0-format mime resource
- // into both a mimetype mapper and xp prefs.
- CMimeMapper* CMimeMapper::CreateMapperForRes(Handle res)
- {
- SInt8 flags = ::HGetState(res);
- ::HNoPurge(res);
-
- CMimeMapper* mapper = new CMimeMapper( res );
- ::HSetState(res, flags);
-
- if (mapper->fMimeType == HTML_VIEWER_APPLICATION_MIME_TYPE) {
- mapper->SetLoadAction(CPrefs::sViewSourceInline ? Internal : Launch);
- }
-
- mapper->WriteMimePrefs(false); // convert to xp format
-
- mapper->SetDefaultDescription();
-
- return mapper;
- }
-
-
- // Constructor to build mapper from xp prefs
- CMimeMapper::CMimeMapper( const char* basepref )
- {
- InitMapper();
-
- fBasePref = XP_STRDUP(basepref);
- if (strlen(fBasePref) > 200)
- fBasePref[200] = '\0';
- ReadMimePrefs();
-
- SetDefaultDescription();
- }
-
- // Copies an xp mimetype pref into the mapper
- void CMimeMapper::ReadMimePrefs()
- {
- int err;
- int size = 256,
- actualSize;
- char value[256];
-
- fAppSig = 0;
- err = PREF_GetCharPref( CPrefs::Concat(fBasePref, Pref_AppSig), value, &size );
- if (PREF_NOERROR == err)
- {
- // values stored as binary (Base64) will always be longer than 4 bytes
- // so if the string is 4 bytes long (or shorter), it's a straight character string
- actualSize = strlen(value);
- if (actualSize <= sizeof(OSType))
- ::BlockMoveData(value, (Ptr) &fAppSig, actualSize );
- else
- {
- err = PREF_GetBinaryPref ( CPrefs::Concat( fBasePref, Pref_AppSig ), value, &size);
- if (PREF_NOERROR == err)
- ::BlockMoveData( value, (Ptr) &fAppSig, sizeof(OSType) );
- }
- }
-
- fFileType = 0;
- err = PREF_GetCharPref( CPrefs::Concat(fBasePref, Pref_FileType), value, &size );
- if (PREF_NOERROR == err)
- {
- // see notes above for fAppSig
- actualSize = strlen(value);
- if (actualSize <= sizeof(OSType))
- ::BlockMoveData( value, (Ptr) &fFileType, actualSize );
- else
- {
- err = PREF_GetBinaryPref ( CPrefs::Concat( fBasePref, Pref_FileType ), value, &size);
- if (PREF_NOERROR == err)
- ::BlockMoveData( value, (Ptr) &fFileType, sizeof(OSType) );
- }
- }
-
- err = PREF_GetCharPref( CPrefs::Concat(fBasePref, Pref_AppName), value, &size );
- if (PREF_NOERROR == err)
- fAppName = value;
-
- err = PREF_GetCharPref( CPrefs::Concat(fBasePref, Pref_MimeType), value, &size );
- if (PREF_NOERROR == err)
- fMimeType = value;
-
- err = PREF_GetCharPref( CPrefs::Concat(fBasePref, Pref_Extension), value, &size );
- if (PREF_NOERROR == err)
- fExtensions = value;
-
- err = PREF_GetCharPref( CPrefs::Concat(fBasePref, Pref_PluginName), value, &size );
- if (PREF_NOERROR == err)
- fPluginName = value;
-
- err = PREF_GetCharPref( CPrefs::Concat(fBasePref, Pref_Description), value, &size );
- if (PREF_NOERROR == err)
- fDescription = value;
-
- int32 intvalue;
- err = PREF_GetIntPref( CPrefs::Concat(fBasePref, Pref_LoadAction), &intvalue );
- if (PREF_NOERROR == err)
- fLoadAction = (LoadAction) intvalue;
-
- XP_Bool boolvalue;
- err = PREF_GetBoolPref( CPrefs::Concat(fBasePref, Pref_LatentPlugin), &boolvalue );
- if (PREF_NOERROR == err)
- fLatentPlugin = (Boolean) boolvalue;
- }
-
- // -- For 3.0 format compatability --
- // Initializes off a resource handle of one of the mime types.
- // See pref.r for resource definition
- // The memory layout of the resource is very important.
- #define NAME_LENGTH_OFFSET 9
- CMimeMapper::CMimeMapper( Handle resRecord )
- {
- ThrowIfNil_(resRecord);
- Size size = ::GetHandleSize(resRecord);
- InitMapper();
-
- char temp[256];
- Ptr resPtr = *resRecord;
- Byte lengthByte = 0;
- long offset = 0;
-
- ThrowIf_(size < 9);
- ::BlockMoveData( resPtr, (Ptr)&fAppSig, 4 );
- ::BlockMoveData( resPtr + 4, (Ptr)&fFileType, 4 );
- uint32 loadAction = *((unsigned char*) (resPtr + 8));
- fLoadAction = (LoadAction) loadAction;
-
- offset = NAME_LENGTH_OFFSET;
- ThrowIf_(offset > size);
- // Ñ read the application name
- lengthByte = resPtr[ offset ];
- ThrowIf_(lengthByte > 255);
- ::BlockMoveData( &resPtr[ offset + 1 ], (Ptr)temp, lengthByte );
-
- temp[ lengthByte ] = 0;
-
- fAppName = temp;
-
- // Ñ read in the MIME type
- offset += ( lengthByte + 1 );
- ThrowIf_(offset > size);
- lengthByte = resPtr[ offset ];
- ::BlockMoveData( &resPtr[ offset + 1 ], temp, lengthByte );
-
- temp[ lengthByte ] = 0;
-
- fMimeType = temp;
-
- // Ñ read in the extensions string
- offset += ( lengthByte + 1 );
- ThrowIf_(offset > size);
- lengthByte = resPtr[ offset ];
- ThrowIf_(lengthByte > 255);
- ::BlockMove ( &resPtr[ offset + 1 ], temp, lengthByte );
-
- temp[ lengthByte ] = 0;
-
- fExtensions = temp;
-
- // Ñ read in the plug-in name string
- // Since the plug-in name doesn't exist in 2.0-vintage prefs resources, make
- // sure to check that there is still data left in the handle before proceeding.
- offset += ( lengthByte + 1 );
- if (offset < size)
- {
- lengthByte = resPtr[ offset ];
- ThrowIf_(lengthByte > 255);
- ::BlockMove ( &resPtr[ offset + 1 ], temp, lengthByte );
- temp[ lengthByte ] = 0;
- fPluginName = temp;
-
- // Now read the description string (it too could be non-existant)
- offset += ( lengthByte + 1 );
- if (offset < size)
- {
- lengthByte = resPtr[ offset ];
- ThrowIf_(lengthByte > 255);
- ::BlockMove ( &resPtr[ offset + 1 ], temp, lengthByte );
- temp[ lengthByte ] = 0;
- fDescription = temp;
-
- // Last, read the "latent plug-in" flag (if it exists)
- offset += ( lengthByte + 1 );
- if (offset < size)
- {
- Boolean latentPlugin = *((unsigned char*) (resPtr + offset));
- XP_ASSERT(latentPlugin == 0 || latentPlugin == 1);
- fLatentPlugin = latentPlugin;
- }
- }
- }
- else
- {
- fPluginName = "";
- fFromOldPrefs = true; // No plug-in info in these prefs
- }
- }
-
- //
- // For old prefs that don't have a description stored in the handle,
- // look up the default description in netlib, defaulting to just the
- // MIME type itself if it can't be found. This description will then
- // get written out to the prefs so it can be edited and saved by the user.
- //
- void CMimeMapper::SetDefaultDescription()
- {
- if (fMimeType == HTML_VIEWER_APPLICATION_MIME_TYPE)
- return;
-
- CStr255 description;
- char* mimetype = (char*) fMimeType;
- NET_cdataStruct* cdata = NULL;
- XP_List* list_ptr = cinfo_MasterListPointer();
- while ((cdata = (NET_cdataStruct*) XP_ListNextObject(list_ptr)) != NULL)
- if (strcasecomp(mimetype, cdata->ci.type) == 0)
- break;
-
- if (cdata && cdata->ci.desc)
- description = cdata->ci.desc;
- else
- description = fMimeType;
-
- if (fDescription == CStr255::sEmptyString) {
- fDescription = description;
- CPrefs::SetModified();
- }
-
- PREF_SetDefaultCharPref( CPrefs::Concat(fBasePref, Pref_Description), description );
- }
-
-
- // Duplicate
- CMimeMapper::CMimeMapper( const CMimeMapper& clone )
- {
- InitMapper();
- fMimeType = clone.fMimeType;
- fAppName = clone.fAppName;
- fAppSig = clone.fAppSig;
- fFileType = clone.fFileType;
- fLoadAction = clone.fLoadAction;
- fExtensions = clone.fExtensions;
-
- fTemporary = clone.fTemporary;
- fRegisteredViewer = clone.fRegisteredViewer;
- fTempAppSig = clone.fTempAppSig; // Application
- fTempFileType = clone.fTempFileType; // File signature
-
- fPluginName = clone.fPluginName;
- fFromOldPrefs = clone.fFromOldPrefs;
- fDescription = clone.fDescription;
- fLatentPlugin = clone.fLatentPlugin;
-
- fBasePref = clone.fBasePref ? XP_STRDUP(clone.fBasePref) : nil;
- }
-
- // Copies values from the mapper to xp user pref tree.
- void CMimeMapper::WriteMimePrefs( Boolean )
- {
- if (fBasePref == nil) {
- // Convert mime type to a pref-name string with
- // non-alpha chars replaced with underscores
- char typecopy[256];
- strcpy(typecopy, "mime.");
- int start = strlen(typecopy);
- strncat(typecopy, (char*) fMimeType, 200);
- for (int i = start; i < strlen(typecopy); i++)
- if (!isalnum(typecopy[i]))
- typecopy[i] = '_';
-
- // Mimetype may be blank, so pick an arbitrary name
- if (fMimeType.Length() == 0)
- strcat(typecopy, "unknown_type_999");
-
- fBasePref = XP_STRDUP(typecopy);
- }
-
- char appsig[sizeof(OSType)+1], filetype[sizeof(OSType)+1];
- appsig[sizeof(OSType)] = '\0';
- ::BlockMoveData( (Ptr) &fAppSig, appsig, sizeof(OSType) );
- filetype[sizeof(OSType)] = '\0';
- ::BlockMoveData( (Ptr) &fFileType, filetype, sizeof(OSType) );
-
- PREF_SetCharPref( CPrefs::Concat(fBasePref, Pref_Extension), fExtensions );
- if (fDescription.Length() > 0)
- PREF_SetCharPref( CPrefs::Concat(fBasePref, Pref_Description), fDescription );
- PREF_SetCharPref( CPrefs::Concat(fBasePref, Pref_MimeType), fMimeType );
- PREF_SetCharPref( CPrefs::Concat(fBasePref, Pref_AppName), fAppName );
- PREF_SetCharPref( CPrefs::Concat(fBasePref, Pref_PluginName), fPluginName );
- // store appsig and filetype as 4-byte character strings, if possible.
- // otherwise, store as binary.
- if (PrintableChars( &appsig, sizeof(OSType)))
- PREF_SetCharPref( CPrefs::Concat(fBasePref, Pref_AppSig), appsig );
- else
- PREF_SetBinaryPref( CPrefs::Concat(fBasePref, Pref_AppSig), appsig, sizeof(OSType));
- if (PrintableChars( &filetype, sizeof(OSType)))
- PREF_SetCharPref( CPrefs::Concat(fBasePref, Pref_FileType), filetype );
- else
- PREF_SetBinaryPref( CPrefs::Concat(fBasePref, Pref_FileType), filetype, sizeof(OSType));
- PREF_SetIntPref( CPrefs::Concat(fBasePref, Pref_LoadAction), fLoadAction );
- PREF_SetBoolPref( CPrefs::Concat(fBasePref, Pref_LatentPlugin), (XP_Bool) fLatentPlugin );
- }
-
- CMimeMapper::CMimeMapper(
- LoadAction loadAction,
- const CStr255& mimeType,
- const CStr255& appName,
- const CStr255& extensions,
- OSType appSignature,
- OSType fileType )
- {
- fLoadAction = loadAction;
- fMimeType = mimeType;
- fAppName = appName;
- fAppSig = appSignature;
- fFileType = fileType;
- fExtensions = extensions;
-
- fTemporary = false;
- fRegisteredViewer = false;
- fPluginName = "";
- fDescription = "";
- fLatentPlugin = false;
- fBasePref = nil;
- }
-
- // Disposes of all allocated structures
- CMimeMapper::~CMimeMapper()
- {
- if (fBasePref)
- free (fBasePref);
- }
-
- CMimeMapper & CMimeMapper::operator= (const CMimeMapper& mapper)
- {
- fMimeType = mapper.fMimeType;
- fAppName = mapper.fAppName;
- fAppSig = mapper.fAppSig;
- fFileType = mapper.fFileType;
- fLoadAction = mapper.fLoadAction;
- fPluginName = mapper.fPluginName;
- fFromOldPrefs = mapper.fFromOldPrefs;
- fDescription = mapper.fDescription;
- fLatentPlugin = mapper.fLatentPlugin;
- return *this;
- }
-
- void CMimeMapper::SetAppName(const CStr255& newName)
- {
- fAppName = newName;
- }
-
- void CMimeMapper::SetMimeType(const CStr255& newType)
- {
- fMimeType = newType;
- }
-
- void CMimeMapper::SetAppSig(OSType newSig)
- {
- fAppSig = newSig;
- }
-
- void CMimeMapper::SetAppSig(FSSpec& appSpec)
- {
- FInfo finderInfo;
- OSErr err = FSpGetFInfo(&appSpec, &finderInfo );
- ThrowIfOSErr_(err);
- fAppSig = finderInfo.fdCreator;
- }
-
- void CMimeMapper::SetExtensions(const CStr255& newExtensions)
- {
- fExtensions = newExtensions;
- SyncNetlib();
- }
-
- void CMimeMapper::SetDocType(OSType newType)
- {
- fFileType = newType;
- }
-
- void CMimeMapper::SetLoadAction(LoadAction newAction)
- {
- //
- // If the user explicitly changed the load action,
- // cancel the latent plug-in setting so their choice
- // is maintained persistently.
- //
- fLatentPlugin = false;
-
- //
- // If the user explicitly changed the load action,
- // cancel the registration of an external viewer.
- //
- fRegisteredViewer = false;
-
- fLoadAction = newAction;
- SyncNetlib();
- }
-
- void CMimeMapper::SetLatentPlugin()
- {
- fLatentPlugin = true;
- fLoadAction = CMimeMapper::Unknown;
- }
-
-
- void CMimeMapper::RegisterViewer(OSType tempAppSig, OSType tempFileType)
- {
- fTempAppSig = tempAppSig; // Application
- fTempFileType = tempFileType; // File signature
- fRegisteredViewer = TRUE;
- CFrontApp::RegisterMimeType(this);
- }
-
- void CMimeMapper::UnregisterViewer()
- {
- fRegisteredViewer = FALSE;
- CFrontApp::RegisterMimeType(this);
- }
-
- // Typical Spy apple event creation routine.
- // It creates the event, with two arguments, URL and the MIME type.
- // URL type is stored as attribute urlAttribute, MIME type as AE_spy_viewDocFile_mime
- OSErr CMimeMapper::MakeSpyEvent(AppleEvent & event,
- URL_Struct * request,
- AEEventID id,
- AEKeyword urlAttribute)
- {
- OSErr err;
- Try_
- {
- AEAddressDesc targetApp;
-
- // Specify the application, and create the event
- {
- err = ::AECreateDesc(typeApplSignature, &fTempAppSig,
- sizeof(fTempAppSig), &targetApp);
- ThrowIfOSErr_(err);
- OSErr err = ::AECreateAppleEvent(AE_spy_send_suite, id,
- &targetApp,
- kAutoGenerateReturnID,
- kAnyTransactionID,
- &event);
- ::AEDisposeDesc(&targetApp);
- }
- // URL
- {
- AEDesc urlDesc;
- err = ::AECreateDesc(typeChar, request->address, strlen(request->address), &urlDesc);
- ThrowIfOSErr_(err);
-
- err = ::AEPutParamDesc(&event, urlAttribute, &urlDesc);
- ThrowIfOSErr_(err);
- ::AEDisposeDesc(&urlDesc);
- }
- // MIME type
- if (request->content_type)
- {
- AEDesc mimeDesc;
- err = ::AECreateDesc(typeChar, request->content_type, strlen(request->content_type), &mimeDesc);
- ThrowIfOSErr_(err);
- err = ::AEPutParamDesc(&event, AE_spy_queryViewer_mime, &mimeDesc);
- ::AEDisposeDesc(&mimeDesc);
- }
- }
- Catch_(inErr)
- { return inErr;
- }
- EndCatch_
- return noErr;
- }
-
- /* Returns whether the contents of inBuffer are all visible, printable characters.
- Actually, that's a misnomer ... it returns whether the contents are printable
- on a Macintosh, which we define to be "not control characters." This is intended
- for determining whether a binary buffer can be stored as a text string, or needs
- to be encoded. */
- Boolean CMimeMapper::PrintableChars(const void *inBuffer, Int32 inLength)
- {
- unsigned char *buffer = (unsigned char *) inBuffer,
- *bufferEnd = buffer + inLength;
-
- while (buffer < bufferEnd)
- {
- if (*buffer <= 0x20)
- break;
- buffer++;
- }
- return buffer == bufferEnd;
- }
-
- // if we have a registered viewer, query it for a file spec
- OSErr CMimeMapper::GetFileSpec(URL_Struct * request,
- FSSpec & destination)
- {
- OSErr err = noErr;
- if (!fRegisteredViewer)
- return fnfErr;
- else
- Try_
- {
- AppleEvent queryViewerEvent;
-
- err = MakeSpyEvent(queryViewerEvent, request,AE_spy_queryViewer,
- keyDirectObject); // URL is the direct object
- // Send the event
- AppleEvent reply;
- err = ::AESend(&queryViewerEvent,&reply,kAEWaitReply,kAEHighPriority,600,nil, nil);
- ThrowIfOSErr_(err);
- // Handle the reply. We want to get out the transaction ID
- {
- DescType realType;
- Size actualSize;
- if (!MoreExtractFromAEDesc::DisplayErrorReply(reply))
- {
- err = ::AEGetParamPtr(&reply, keyAEResult, typeFSS,
- &realType, &destination, sizeof(destination),
- &actualSize);
- ThrowIfOSErr_(err);
- }
- else
- Throw_(fnfErr);
- ::AEDisposeDesc(&reply);
- }
- }
- Catch_(inErr)
- {
- return inErr;
- } EndCatch_
- return noErr;
- }
-
- // If we have a registered viewer, use ViewDocFile
- // if anything fails, or we have no viewer, use ordinary launch sequence
- OSErr CMimeMapper::LaunchFile(LFileBufferStream * inFile, URL_Struct * request, Int32 windowID)
- {
- OSErr err;
- if (fRegisteredViewer)
- {
- Try_
- {
- AppleEvent viewDocEvent;
- // AppleEvent(fileSpec, URL, MIME, windowID)
- // Create the event, with MIME and URL arguments
- err = MakeSpyEvent(viewDocEvent, request,AE_spy_viewDocFile,
- AE_spy_viewDocFile_url); // URL is the direct object
- ThrowIfOSErr_(err);
- // Make the file spec
- FSSpec fileSpec;
- inFile->GetSpecifier(fileSpec);
- err = ::AEPutParamPtr(&viewDocEvent,keyDirectObject,typeFSS,&fileSpec,sizeof(fileSpec));
- ThrowIfOSErr_(err);
- // URL
- if (request->address)
- {
- err = ::AEPutParamPtr(&viewDocEvent,AE_spy_viewDocFile_url, typeChar, request->address,strlen(request->address));
- ThrowIfOSErr_(err);
- }
- // MIME type
- {
- StAEDescriptor mimeDesc((StringPtr)fMimeType);
- err = ::AEPutParamDesc(&viewDocEvent,AE_spy_viewDocFile_mime,&mimeDesc.mDesc);
- ThrowIfOSErr_(err);
- }
- // WindowID
- {
- StAEDescriptor windowDesc(windowID);
- err = ::AEPutParamDesc(&viewDocEvent,AE_spy_viewDocFile_wind, &windowDesc.mDesc);
- ThrowIfOSErr_(err);
- }
- // Send the event
- AppleEvent reply;
- err = ::AESend(&viewDocEvent,&reply,kAEWaitReply,kAEHighPriority,60,nil, nil);
- if (err != errAETimeout)
- ThrowIfOSErr_(err);
- // If we got an error code back, launch as usual
- if (reply.descriptorType != typeNull)
- {
- DescType realType;
- Size actualSize;
- long errNumber;
- err = ::AEGetParamPtr(&reply, keyErrorNumber, typeLongInteger,
- &realType, &errNumber, sizeof(errNumber),
- &actualSize);
- if ((err == noErr) && (errNumber != noErr))
- Throw_(errNumber);
- }
- }
- Catch_(inErr)
- {
- // Launch through ViewDoc failed, use our original creator and launch as usual
- FSSpec fileSpec;
- inFile->GetSpecifier(fileSpec);
- err = CFileMgr::SetFileTypeCreator(fAppSig, fFileType, &fileSpec);
- ::LaunchFile(inFile);
- }
- EndCatch_
- }
- else
- ::LaunchFile(inFile);
- return noErr;
- }
-
-
- void CMimeMapper::SyncNetlib()
- {
- CFrontApp::RegisterMimeType(this);
- }
-
- //----------------------------------------------------------------------
- // class CMimeList
- //----------------------------------------------------------------------
-
- // ÑÑ Constructors/destructors
-
- CMimeList::CMimeList() : LArray()
- {
- }
-
- CMimeList::~CMimeList()
- {
- }
-
- // ÑÑ╩Utility functions
- // Overrode this on the assumption that every time you add a MIME mapper
- // to this list, you want to sync up the netlib
- ArrayIndexT CMimeList::InsertItemsAt(
- Uint32 inCount,
- ArrayIndexT inAtIndex,
- const void *inItem,
- Uint32 inItemSize)
-
- {
- ArrayIndexT result = LArray::InsertItemsAt(inCount,inAtIndex,inItem, inItemSize);
- CMimeMapper ** mapperPtr = (CMimeMapper **)inItem;
- (*mapperPtr)->SyncNetlib();
- return result;
- }
-
- // Deletes all the items in the list
- void CMimeList::DeleteAll(Boolean)
- {
- CMimeMapper* oldMap;
- for ( short i = 1; i <= mItemCount; i++ )
- {
- FetchItemAt( i, &oldMap );
- delete oldMap;
- }
- RemoveItemsAt( mItemCount,1);
- }
-
- // Finds a CMimeMapper with a given XP pref branch name.
- CMimeMapper* CMimeList::FindBasePref( const char* basepref )
- {
- CMimeMapper* foundMap = NULL;
- for ( Int32 i = mItemCount; i >= 1; i-- )
- {
- CMimeMapper* oldMap;
- FetchItemAt( i, &oldMap );
- if ( oldMap->GetBasePref() != NULL &&
- XP_STRCMP(oldMap->GetBasePref(), basepref) == 0 )
- {
- foundMap = oldMap;
- break;
- }
- }
- return foundMap;
- }
-
-
- // Finds a CMimeMapper with a given mimeType. NULL if none
- // Search is linear. Might want to make it faster
- CMimeMapper* CMimeList::FindMimeType( char* mimeType )
- {
- if ( mimeType == NULL )
- return NULL;
-
- CMimeMapper* foundMap = NULL;
- for ( Int32 i = 1; i <= mItemCount; i++ )
- {
- CMimeMapper* oldMap;
- FetchItemAt( i, &oldMap );
- if ( XP_STRCMP(oldMap->GetMimeName(), mimeType) == 0 )
- {
- foundMap = oldMap;
- break;
- }
- }
- return foundMap;
- }
-
- // Find a "built-in" mime type, which were separate in 3.0
- // but are integrated into the 4.0 mimetype list.
- CMimeMapper* CMimeList::FindMimeType(BuiltIn mimeBuiltin)
- {
- char* mimetype = nil;
- switch (mimeBuiltin) {
- case HTMLViewer:
- mimetype = HTML_VIEWER_APPLICATION_MIME_TYPE;
- break;
- case Telnet:
- mimetype = TELNET_APPLICATION_MIME_TYPE;
- break;
- case Tn3270:
- mimetype = TN3270_VIEWER_APPLICATION_MIME_TYPE;
- break;
- }
- return FindMimeType(mimetype);
- }
-
-
- // FindMimeType finds a Mime mapper that
- // matches this file's type and creator
- // Algorithm is inexact
- // TEXT files are not typed because netlib figures out the
- // HTML files, and hqx ones have the extension
- // Look for exact match.
- // If not found, look for inexact one
-
- // I don't like the above algorithm. There is no way of telling what type of match occured. In
- // cases other than exact or FileType match the results are unsatisfactory.
- // New behavoir is to return NULL and let the caller call CMimeList::FindCreatorFindCreator if
- // needed. Provides a way to hand off to IC if needed.
- CMimeMapper* CMimeList::FindMimeType(const FSSpec& inFileSpec)
- {
- FInfo fndrInfo;
-
- OSErr err = FSpGetFInfo( &inFileSpec, &fndrInfo );
- if ((err != noErr) || (fndrInfo.fdType == 'TEXT'))
- return NULL;
-
- CMimeMapper* fileTypeMatch = NULL;
-
- // Find the cinfo (which gives us the MIME type) for this file name
- NET_cinfo* cinfo = NET_cinfo_find_type((CStr255)inFileSpec.name);
-
- for (Int32 i = 1; i <= mItemCount; i++)
- {
- CMimeMapper* map;
- FetchItemAt(i, &map);
-
- //
- // If this MIME type is configured for a plug-in, see if it matches
- // the MIME type of the file (based on the file extension -> MIME
- // type mapping). If not, try for an exact or partial match based
- // on type and/or creator. bing: If we decide to support Mac file
- // types for plug-ins, we should check the file type here.
- //
- if (map->GetLoadAction() == CMimeMapper::Plugin)
- {
- if (cinfo && (map->GetMimeName() == cinfo->type))
- return map;
- }
- else if ((map->GetAppSig() == fndrInfo.fdCreator) &&
- (map->GetDocType() == fndrInfo.fdType))
- return map;
- else
- {
- #if 0
- if (map->GetAppSig() == fndrInfo.fdCreator)
- creatorMatch = map;
- #endif
- if (map->GetDocType() == fndrInfo.fdType)
- fileTypeMatch = map;
- }
- }
-
- return fileTypeMatch;
- }
-
-
- // FindCreator finds a CMimeMapper whose application signature
- // matches appSig
- CMimeMapper* CMimeList::FindCreator(OSType appSig)
- {
- CMimeMapper * foundMap = NULL;
- for (Int32 i = 1; i <= mItemCount; i++)
- {
- CMimeMapper* oldMap;
- FetchItemAt(i, &oldMap);
- if (oldMap->GetAppSig() == appSig)
- {
- foundMap = oldMap;
- break;
- }
- }
- return foundMap;
- }
-
- // ------------------------- Apple Event handling -------------------------------
-
- // HandleRegisterViewerEvent
- // registers a viewer.
- // If the MIME type does not exist, we create one on the fly
- void CMimeList::HandleRegisterViewerEvent(const AppleEvent &inAppleEvent,
- AppleEvent &outAEReply,
- AEDesc &/*outResult*/,
- long /*inAENumber*/)
- {
- OSType appSign; // app signature
- OSType fileType = 'TEXT'; // file type to be created
- volatile char * mimeType = NULL; // MIME type
- OSType realType;
- Size realSize;
- CMimeMapper * mapper;
- OSErr err;
- Try_ {
- { // Get the application signature. Required
- err = ::AEGetParamPtr(&inAppleEvent,keyDirectObject,typeApplSignature,
- &realType, &appSign, sizeof(appSign), &realSize);
- ThrowIfOSErr_(err);
- }
- { // Get the MIME type. Required
- AEDesc mimeDesc;
- err = ::AEGetParamDesc(&inAppleEvent,AE_spy_registerViewer_mime,typeWildCard,&mimeDesc);
- ThrowIfOSErr_(err);
- MoreExtractFromAEDesc::TheCString(mimeDesc, mimeType);
- ::AEDisposeDesc(&mimeDesc);
- if (mimeType == nil)
- ThrowOSErr_(errAEWrongDataType);
- }
-
- mapper = FindMimeType(mimeType);
- if (mapper)
- fileType = mapper->GetDocType();
- { // Get the file type. If none is specified, it defaults to already registered type, or 'TEXT'
- AEDesc fileTypeDesc;
- err = ::AEGetParamDesc(&inAppleEvent,AE_spy_registerViewer_ftyp,typeWildCard,&fileTypeDesc);
- if (err == noErr)
- {
- Try_ {
- UExtractFromAEDesc::TheType(fileTypeDesc, fileType);
- } Catch_(inErr)
- {} EndCatch_
- }
- ::AEDisposeDesc(&fileTypeDesc);
- }
- // We have all the arguments, set up the new mapper if necessary
- if (mapper == NULL)
- {
- mapper = new CMimeMapper(CMimeMapper::Launch,
- mimeType,
- "-", // I10L - this string is never seen by a user
- CStr255::sEmptyString,
- appSign,
- fileType);
- ThrowIfNil_(mapper);
- mapper->SetTemporary(TRUE);
- InsertItemsAt( 1, LArray::index_Last, &mapper);
- }
-
- // If the type is being handled by a plug-in, don╒t let the AE override
- Boolean result = false;
- if (mapper->GetLoadAction() != CMimeMapper::Plugin)
- {
- mapper->RegisterViewer(appSign, fileType);
- result = true;
- }
-
- // Reply success
- // Create the reply, it will automatically be stuck into the outgoing AE by PP
- {
- StAEDescriptor booleanDesc(result);
- err = ::AEPutKeyDesc(&outAEReply,keyAEResult,&booleanDesc.mDesc); /* IM VI chap. 6 pg 91 */
- }
- }
- Catch_(inErr)
- {
- MoreExtractFromAEDesc::MakeErrorReturn(outAEReply,
- (unsigned char *)GetCString(REG_EVENT_ERR_RESID) , inErr);
- } EndCatch_
- // Dispose
- if (mimeType) XP_FREE(mimeType);
- }
-
- void CMimeList::HandleUnregisterViewerEvent(const AppleEvent &inAppleEvent,
- AppleEvent &outAEReply,
- AEDesc &/*outResult*/,
- long /*inAENumber*/)
- {
- OSType appSign; // app signature
- OSType fileType = 'TEXT'; // file type to be created
- volatile char* mimeType = NULL; // MIME type
-
- CMimeMapper * mapper = NULL;
- OSErr err;
- Try_
- {
- { // Get the application signature. Required
- AEDesc appSignDesc;
- err = ::AEGetParamDesc(&inAppleEvent,keyDirectObject,typeWildCard,&appSignDesc);
- ThrowIfOSErr_(err);
- UExtractFromAEDesc::TheType(appSignDesc, appSign);
- ::AEDisposeDesc(&appSignDesc);
- }
- { // Get the MIME type. Required
- AEDesc mimeDesc;
- err = ::AEGetParamDesc(&inAppleEvent,AE_spy_unregisterViewer_mime,typeWildCard,&mimeDesc);
- ThrowIfOSErr_(err);
- MoreExtractFromAEDesc::TheCString(mimeDesc, mimeType);
- ::AEDisposeDesc(&mimeDesc);
- if (mimeType == nil)
- ThrowOSErr_(errAEWrongDataType);
- }
-
- mapper = FindMimeType(mimeType);
-
- if (mapper == NULL || mapper->IsViewerRegistered() == false)
- {
- //
- // If the type isn╒t found, or wasn╒t registered
- // to an external viewer, return an error.
- //
- MoreExtractFromAEDesc::MakeErrorReturn(outAEReply,
- (unsigned char *)GetCString(APP_NOT_REG_RESID), errAEDescNotFound);
- }
- else
- {
- //
- // Otherwise unregister the viewer and remove the
- // temporary mapper if necessary.
- //
- mapper->UnregisterViewer();
- if (mapper->IsTemporary())
- {
- Remove(&mapper);
- delete mapper;
- }
- }
- }
- Catch_(inErr)
- {
- MoreExtractFromAEDesc::MakeErrorReturn(outAEReply,
- (unsigned char *)GetCString(UNREG_EVENT_ERR_RESID), inErr);
- }
- EndCatch_
- if (mimeType) XP_FREE(mimeType);
- }
-
-