home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / feembed.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  25.2 KB  |  750 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "stdafx.h"
  20.  
  21. #include "feembed.h"
  22.  
  23. #include "cntritem.h"
  24. #include "ngdwtrst.h"
  25. #include "cxdc.h"
  26. #include "npapi.h"
  27. #include "np.h"
  28. #include "presentm.h"
  29. #include "helper.h"
  30. #include "il_icons.h"
  31. #include "extgen.h"
  32. #include "libevent.h"
  33.  
  34. extern "C" int MK_DISK_FULL;   // defined in allxpstr.c
  35.  
  36. extern char *FE_FindFileExt(char * path);
  37.  
  38. extern "C"    {
  39.  
  40. BOOL wfe_IsTypePlugin(NPEmbeddedApp* pEmbeddedApp) 
  41. {
  42.     CNetscapeCntrItem *pItem = (CNetscapeCntrItem *)pEmbeddedApp->fe_data;
  43.     return (pEmbeddedApp->type == NP_Plugin) ? TRUE : FALSE;
  44. }
  45.  
  46. CNetscapeCntrItem *wfe_GetCntrPtr(void* pDataObj) // where pDataObj is an URL struct
  47. {
  48.     NPEmbeddedApp* pEmbeddedApp = (NPEmbeddedApp*)((URL_Struct*)pDataObj)->fe_data;
  49.     return (CNetscapeCntrItem *)pEmbeddedApp->fe_data;
  50. }
  51.  
  52. NPError FE_PluginGetValue(MWContext *pContext, NPEmbeddedApp *pApp, 
  53.                           NPNVariable variable, void *pRetVal)
  54. {
  55.     NPError ret = NPERR_NO_ERROR;
  56.     
  57.     switch (variable) {
  58.         case NPNVnetscapeWindow:
  59.         {
  60.             if (pContext->type != MWContextPrint)
  61.                 *(HWND *)pRetVal = PANECX(pContext)->GetPane();
  62.             else
  63.                 ret = NPERR_INVALID_PARAM;
  64.         }
  65.          break;
  66.         default:
  67.             *(void **)pRetVal = NULL;
  68.             break;
  69.     }
  70.  
  71.     return ret;
  72. }
  73.  
  74. // wrapper for plugin-related FE entry point invented after EmbedUrlExit()
  75. void FE_EmbedURLExit(URL_Struct *urls, int status, MWContext *cx)
  76. {
  77.     EmbedUrlExit(urls, status, cx);
  78. }
  79.  
  80. void EmbedUrlExit(URL_Struct *pUrl, int iStatus, MWContext *pContext)
  81. {
  82.     //  The embedded item is finished downloading, and possibly has an error and stuff.
  83.     NPEmbeddedApp* pEmbeddedApp = (NPEmbeddedApp*)pUrl->fe_data;
  84.  
  85.     if (!pEmbeddedApp) {
  86.         NET_FreeURLStruct(pUrl);
  87.         return;
  88.     }
  89.  
  90.     CNetscapeCntrItem *pItem = (CNetscapeCntrItem *)pEmbeddedApp->fe_data;
  91.  
  92.     // if an EMBED tag's SRC attribute is a LOCAL file which does not exist,
  93.     // pItem is NULL.  Bandaid against GPF for 2.0, but later we must fix the
  94.     // FE_GetEmbedSize() and NP_EmbedCreate() combo that cause this problem.
  95.     if(pItem != NULL) {
  96.         if(wfe_IsTypePlugin(pEmbeddedApp))
  97.         {
  98.             pItem->m_bLoading = FALSE;
  99.             NET_FreeURLStruct(pUrl);
  100.             return;
  101.         }
  102. #ifdef MOCHA
  103.         {
  104.             /* only wait on applets if onload flag */
  105.             lo_TopState *top_state = lo_FetchTopState(XP_DOCID(pContext));
  106.             if (top_state != NULL && top_state->mocha_loading_embeds_count)
  107.             {
  108.                 top_state->mocha_loading_embeds_count--;
  109.                 ET_SendLoadEvent(pContext, EVENT_XFER_DONE, NULL, NULL, 
  110.                                  LO_DOCUMENT_LAYER_ID, FALSE);
  111.             }
  112.         }
  113. #endif /* MOCHA */
  114.  
  115.         // else must be an OLE stream exit
  116.         if(iStatus != MK_DATA_LOADED)   {
  117.             //  Load error.
  118.             pItem->m_bBroken = TRUE;
  119.         }
  120.         else if(pUrl->server_status != 0 && pUrl->server_status / 100 != 2 && pUrl->server_status / 100 != 3 && iStatus == MK_DATA_LOADED)  {
  121.             //  Server error.
  122.             pItem->m_bBroken = TRUE;
  123.         }
  124.  
  125.         //  If the item isn't broken, we can load it up.
  126.         if(pItem->m_bBroken == FALSE)   {
  127.             SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));
  128.             if(FALSE == pItem->CreateFromFile(pItem->m_csFileName)) {
  129.                 //  Couldn't create for some reason!
  130.                 pItem->m_bBroken = TRUE;
  131.             }
  132.             SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  133.         }
  134.         pItem->m_bLoading = FALSE;
  135.  
  136.         //  Get the width and height out of our newly created item, if it isn't broken.
  137.         //    We need to do this two different ways, depending on what type of context we
  138.         //        are in.
  139.         CSize csExtents;
  140.         //    New way.
  141.         CDCCX *pCX = VOID2CX(pContext->fe.cx, CDCCX);
  142.         if(pItem->m_bBroken == FALSE)    {
  143.             pItem->GetExtent(&csExtents);
  144.             csExtents.cx = CASTINT(pCX->Metric2TwipsX(csExtents.cx));
  145.             csExtents.cy = CASTINT(pCX->Metric2TwipsY(csExtents.cy));
  146.         }
  147.         else    {
  148.             LTRB Rect;
  149.             int32 x, y;
  150. //            pCX->DisplayIcon(Rect.left, Rect.right, IL_IMAGE_BAD_DATA, &x, &y);
  151.             pCX->GetIconDimensions(&x, &y, IL_IMAGE_BAD_DATA);
  152.             csExtents.cx = CASTINT(x);
  153.             csExtents.cy = CASTINT(y);
  154.         }
  155.         //  Need to flush all delayed display, and blocked layout.
  156.         //  Do all blocks.
  157.         POSITION rIndex = pItem->m_cplUnblock.GetHeadPosition();
  158.         LO_EmbedStruct *pLayoutData = NULL;
  159.         while(rIndex != NULL && iStatus != MK_INTERRUPTED)   {
  160.             pLayoutData = (LO_EmbedStruct *)pItem->m_cplUnblock.GetNext(rIndex);
  161.             if ((pEmbeddedApp->type ==  NP_OLE) && pItem->m_lpObject) {
  162.                 if ( pLayoutData->width)
  163.                     csExtents.cx = pLayoutData->width; 
  164.                 if ( pLayoutData->height)
  165.                     csExtents.cy = pLayoutData->height; 
  166.                 pLayoutData->width = csExtents.cx;
  167.                 pLayoutData->height = csExtents.cy;
  168.  
  169.             }
  170.             LO_ClearEmbedBlock(ABSTRACTCX(pContext)->GetDocumentContext(), pLayoutData);        
  171.         }
  172.         pItem->m_cplUnblock.RemoveAll();
  173.  
  174. #ifdef LAYERS
  175.         rIndex = pItem->m_cplElements.GetHeadPosition();
  176.         while (rIndex != NULL) {
  177.             pLayoutData = (LO_EmbedStruct *)pItem->m_cplElements.GetNext(rIndex);
  178.             // An OLE container is windowless until it is activated.
  179.             LO_SetEmbedType(pLayoutData, PR_FALSE);
  180.         }
  181. #endif // LAYERS
  182.         
  183.         //  Do all needed display.
  184.         rIndex = pItem->m_cplDisplay.GetHeadPosition();
  185.         while(rIndex != NULL)   {
  186.             pLayoutData = (LO_EmbedStruct *)pItem->m_cplDisplay.GetNext(rIndex);
  187.  
  188.             if ((pEmbeddedApp->type ==  NP_OLE) && pItem->m_lpObject) {
  189.                 if ( pLayoutData->width )
  190.                     csExtents.cx = pLayoutData->width; 
  191.                 if ( pLayoutData->height)
  192.                     csExtents.cy = pLayoutData->height;
  193.                 pLayoutData->width = csExtents.cx;
  194.                 pLayoutData->height = csExtents.cy;
  195.             }
  196. #ifdef LAYERS
  197.             if (pContext->compositor) {
  198.                 XP_Rect rect;
  199.                 
  200.                 CL_GetLayerBbox(pLayoutData->layer, &rect);
  201.                 CL_UpdateLayerRect(CL_GetLayerCompositor(pLayoutData->layer),
  202.                                    pLayoutData->layer, &rect, PR_FALSE);
  203.             }
  204.             else
  205. #endif /* LAYERS */
  206.                 pContext->funcs->DisplayEmbed(pContext, FE_VIEW, pLayoutData);
  207.  
  208.         }
  209.         pItem->m_cplDisplay.RemoveAll();
  210.     }
  211.  
  212.     //  And well, hey, get rid of the url.
  213.     NET_FreeURLStruct(pUrl);
  214. }
  215.  
  216. static void wfe_PluginStream(URL_Struct *pUrlData, MWContext *pContext)
  217. {
  218.     NPEmbeddedApp* pEmbeddedApp = (NPEmbeddedApp*)pUrlData->fe_data;
  219.  
  220.     ASSERT(pEmbeddedApp);
  221.  
  222.     // Make sure the type is set properly
  223.     pEmbeddedApp->type = NP_Plugin;
  224.  
  225.     //  Need to flush all delayed display, and blocked layout.
  226.     CNetscapeCntrItem *pItem = (CNetscapeCntrItem *)pEmbeddedApp->fe_data;
  227.  
  228.     ASSERT(pItem);
  229.  
  230.     if (!pItem->m_cplUnblock.IsEmpty()) {
  231.         // There had better only be one item here
  232.         ASSERT(pItem->m_cplUnblock.GetCount() == 1);
  233.  
  234.         POSITION        rIndex = pItem->m_cplUnblock.GetHeadPosition();
  235.         LO_EmbedStruct*    pLayoutData = (LO_EmbedStruct *)pItem->m_cplUnblock.GetNext(rIndex);
  236.  
  237.         // Unblock layout
  238.         LO_ClearEmbedBlock(ABSTRACTCX(pContext)->GetDocumentContext(), pLayoutData);        
  239.         pItem->m_cplUnblock.RemoveAll();
  240.     }
  241.  
  242.     //  Display the plugin if necessarily
  243.     if (!pItem->m_cplDisplay.IsEmpty()) {
  244.         // There had better only be one item here
  245.         ASSERT(pItem->m_cplDisplay.GetCount() == 1);
  246.  
  247.         POSITION        rIndex = pItem->m_cplDisplay.GetHeadPosition();
  248.         LO_EmbedStruct*    pLayoutData = (LO_EmbedStruct *)pItem->m_cplDisplay.GetNext(rIndex);
  249.  
  250. #ifdef LAYERS
  251.         int32 lXSave, lYSave;
  252.         XP_Rect rect;
  253.         
  254.         // I don't like the fact that this code has to be here. At some
  255.         // level, it goes against the rule that all drawing has to be
  256.         // driven by the compositor through layout. The easy fix is that
  257.         // we do the same coordinate space conversion that's done in
  258.         // layout.  -- Vidur
  259.         if (pContext->compositor) {
  260.             /* Convert layer-relative coordinates for element to document
  261.                coordinates, since that's what the FE uses. */
  262.             rect.top = rect.left = rect.right = rect.bottom = 0;
  263.             CL_LayerToWindowRect(pContext->compositor, pLayoutData->layer, &rect);
  264.             CL_WindowToDocumentRect(pContext->compositor, &rect);
  265.             
  266.             /* Save old, layer-relative coordinates */
  267.             lXSave = pLayoutData->x;
  268.             lYSave = pLayoutData->y;
  269.             
  270.             /* Temporarily shift element to document coordinates */
  271.             pLayoutData->x = rect.left - pLayoutData->x_offset;
  272.             pLayoutData->y = rect.top - pLayoutData->y_offset;
  273.         }
  274. #endif /* LAYERS */
  275.  
  276.         // Display the plugin
  277.         pContext->funcs->DisplayEmbed(pContext, FE_VIEW, pLayoutData);
  278.  
  279. #ifdef LAYERS
  280.         if (pContext->compositor) {
  281.             pLayoutData->x = lXSave;
  282.             pLayoutData->y = lYSave;
  283.         }
  284. #endif /* LAYERS */
  285.  
  286.         pItem->m_cplDisplay.RemoveAll();
  287.     }
  288. }
  289.  
  290. BOOL WildMime(const char *pOne, const char *pTwo)    {
  291. //    Purpose:    Compare two mime types to see if they can be considered
  292. //                    equivalent.
  293. //    Arguments:    csOne    A fully qualified mime type, no wilds.
  294. //                csTwo    A mime type, can be wild, or subtype wild.
  295. //    Returns:    BOOL    TRUE    A match.
  296. //                        FALSE    No match.
  297. //    Comments:    Mime types are case insensitive.
  298. //    Revision History:
  299. //        01-04-95    created GAB
  300. //
  301.  
  302.     //    First, just get rid of any wilds right now.
  303.     if(*pTwo == '*')    {
  304.         return(TRUE);
  305.     }
  306.     
  307.     //    Okay, only have subtype wilds left, split the mime types up
  308.     //        into minor, major parts.
  309.     char *p1 = strdup(pOne);
  310.     char *pmin1 = strchr(p1, '/');
  311.     if(pmin1) {
  312.         *pmin1 = '\0';
  313.         pmin1++;
  314.     } else {
  315.         pmin1 = p1;
  316.     }
  317.     
  318.         
  319.     char *p2 = strdup(pTwo);
  320.     char *pmin2 = strchr(p2, '/');
  321.     if(pmin2) {
  322.         *pmin2 = '\0';
  323.         pmin2++;
  324.     } else {
  325.          pmin2 = p2;    
  326.     }               
  327.     
  328.     //    If majors don't match, there is no hope.
  329.     if(stricmp(p1, p2) != 0)    {
  330.         free(p1);
  331.         free(p2);
  332.         return(FALSE);
  333.     }
  334.     
  335.     //    Okay, let's get rid of sub type wilds right now.
  336.     if(*pmin2 == '*')    {
  337.         free(p1);
  338.         free(p2);
  339.         return(TRUE);
  340.     }
  341.     
  342.     //    See if the minors match up.
  343.     BOOL bRetVal = FALSE;
  344.     if(stricmp(pmin1, pmin2) == 0)    {
  345.         bRetVal = TRUE;
  346.     }
  347.     
  348.     free(p1);
  349.     free(p2);
  350.     return(bRetVal);
  351. }
  352.  
  353.  
  354. static BOOL wfe_IsRegisteredForPlugin(int iFormatOut, URL_Struct *pUrlStruct, MWContext *pContext)
  355. {
  356.     //    Find the callers mime/type in the iFormatOut registry list,
  357.     //  and return true if found.
  358.     CString csMimeType = pUrlStruct->content_type;
  359.     
  360.     //    Find the relevant mime type in our list.
  361.     //    There should always be a wild on the end of the list, but if not, duh.
  362.     XP_List *list = NET_GetRegConverterList(iFormatOut);
  363.     ContentTypeConverter *pConv;
  364.  
  365.     while(pConv = (ContentTypeConverter *)XP_ListNextObject(list))
  366.     {
  367.         
  368.         //    Do a wild compare on the mime types
  369.         if(WildMime(csMimeType, pConv->format_in))
  370.         {
  371.             //  May have found an appropriate converter.
  372.  
  373.             //  Only when the viewer is not automated,
  374.             //  and the mime types are a case insensitive
  375.             //  match, return TRUE.
  376.             // ZZZ: Make sure it's a plug-in and not an automated viewer.
  377.             // We're doing it this demented way because pConv->bAutomated is
  378.             // getting stomped and points to garbage
  379.             if ((pConv->bAutomated == FALSE) && NPL_FindPluginEnabledForType(pConv->format_in)) {
  380.                 // only check for can handle by OLE when there is no plugin register for
  381.                 // the mine type.
  382.                 // Find out can we handle by OLE.
  383.                 if (strcmp(pConv->format_in, "*") == 0) 
  384.                     /* there previously was a call to FE_FileType here, but it is clearly
  385.                     unnecessary given the check of fe_CanHandlebyOLE we've added.  byrd.
  386.                     reminder - we should overhaul/remove FE_FileType and it's other call.
  387.                     && 
  388.                     FE_FileType(pUrlStruct->address, pUrlStruct->content_type,
  389.                                     pUrlStruct->content_encoding))
  390.                                     */
  391.                 {
  392.                     if(iFormatOut == FO_EMBED){
  393.                         /* don't have to worry about FO_CACHE_AND_EMBED since cache bit cleared by NET_CacheConverter */
  394.                         /* also, don't want to interfere w/ full-page case... */
  395.                         char* ext[1];
  396.                         ext[0] = FE_FindFileExt(pUrlStruct->address);
  397.  
  398.                         if(ext[0] && fe_CanHandleByOLE(ext,1))
  399.                             return FALSE;
  400.                         else
  401.                             return TRUE;
  402.                     }
  403.  
  404.                     else return FALSE;
  405.                 }
  406.                 else
  407.                     return TRUE;
  408.             }
  409.             //  Only when the viewer is not automated,
  410.             //  and the handler is for wildcard MIME type,
  411.             //  and OLE doesn't want it, return TRUE.
  412.             // ZZZ: See above comment
  413.             if ((pConv->bAutomated == FALSE) && XP_STRCMP(pConv->format_in, "*") == 0 &&
  414.                 NPL_FindPluginEnabledForType("*")) {
  415.                 // the following code is copied from EmbedStream(), OLE related stuff
  416.                 // BUG: this code needs to be shared code!
  417.  
  418.                 // extract the extension of the file name
  419.                 char aExt[_MAX_EXT];
  420.                 size_t stExt = 0;
  421.                 DWORD dwFlags = EXT_NO_PERIOD;
  422.                 
  423. #ifdef XP_WIN16
  424.                 dwFlags |= EXT_DOT_THREE;
  425. #endif
  426.                 aExt[0] = '\0';
  427.                 stExt = EXT_Invent(aExt, sizeof(aExt), dwFlags, pUrlStruct->address, pUrlStruct->content_type);
  428.                 CString csFinalExtension = aExt;
  429.  
  430.                 //  Check to see if the embedded file matches any known extensions.
  431.                 //  If not, then consider the file of no use to the user.
  432.                 //    Use new way if we are in a different style of context.
  433.                 if(wfe_IsExtensionRegistrationValid(csFinalExtension, ABSTRACTCX(pContext)->GetDialogOwner(), FALSE) == FALSE) {
  434.                     return TRUE;
  435.                 }        
  436.             }
  437.         }
  438.     }
  439.     return FALSE;
  440. }
  441.  
  442. NET_StreamClass *EmbedStream(int iFormatOut, void *pDataObj, URL_Struct *pUrlData, MWContext *pContext)
  443. {
  444.     NPEmbeddedApp* pEmbeddedApp = NULL;
  445.     CNetscapeCntrItem* pItem = NULL;
  446.     NET_StreamClass * pStream = NULL;
  447.  
  448.     if(wfe_IsRegisteredForPlugin(iFormatOut, pUrlData, pContext)) {
  449.         if(!ABSTRACTCX(pContext)->IsPrintContext()) {
  450.             if (iFormatOut == FO_EMBED) {
  451.                 // NPL_NewEmbedStream() sets pUrlData->fe_data to NPEmbeddedApp*, so
  452.                 // it is not valid until NPL_NewEmbedStream() returns
  453.                 pStream = NPL_NewEmbedStream((FO_Present_Types)iFormatOut,
  454.                     pDataObj, pUrlData, pContext);
  455.                 
  456.             } else if (iFormatOut == FO_PRESENT) {
  457.                 // NPL_NewPresentStream() sets pUrlData->fe_data to NPEmbeddedApp*, so
  458.                 // it is not valid until NPL_NewPresentStream() returns
  459.                 pStream = NPL_NewPresentStream((FO_Present_Types)iFormatOut,
  460.                     pDataObj, pUrlData, pContext);
  461.                 
  462.             } else {
  463.                 ASSERT(FALSE);
  464.                 return NULL;
  465.             }
  466.  
  467.             // If we fail to load for some reason, show a broken icon.
  468.             if(!pStream) {
  469.                 if(pItem)
  470.                     pItem->m_bBroken = TRUE;
  471.                 return NULL;
  472.             }
  473.             pEmbeddedApp = (NPEmbeddedApp*)pUrlData->fe_data;
  474.             if(pEmbeddedApp)
  475.                 pItem = (CNetscapeCntrItem *)pEmbeddedApp->fe_data;
  476.         }
  477.  
  478.         // pDataObj gets its fe_data member written by libplugin in
  479.         // the full screen case
  480.         //
  481.         // It's possible that the context is different. This happens for full-page
  482.         // plug-ins when we decide to display the plugin in it's own window
  483.         if (pItem && pItem->GetDocument()) {
  484.             CDCCX*    pDC = pItem->GetDocument()->GetContext();
  485.  
  486.             if (pDC && pDC->GetContext() != pContext) {
  487.                 TRACE0("Context changed in EmbedStream()!\n");
  488.                 pContext = pDC->GetContext();
  489.             }
  490.         }
  491.  
  492.         wfe_PluginStream(pUrlData, pContext);
  493.         return pStream;
  494.     }
  495.  
  496.     // if the MIME type isn't registered to a plugin,
  497.     // assume it must be handled by OLE
  498.     pEmbeddedApp = (NPEmbeddedApp*)pUrlData->fe_data;
  499.     if(pEmbeddedApp == NULL) // our OLE support doesn't do full page
  500.         return NULL;
  501.  
  502.     // Explicitly type it as an embedded OLE object
  503.     pEmbeddedApp->type = NP_OLE;
  504.     pItem = (CNetscapeCntrItem *)pEmbeddedApp->fe_data;
  505.     pItem->m_bIsOleItem = TRUE;
  506.  
  507.     //  Formulate a file name that will suckle data from the net.
  508.     char *pFormulateName = fe_URLtoLocalName(pItem->m_csAddress, pUrlData ? pUrlData->content_type : NULL);
  509.     char *pLocalName = NULL;
  510.     if(((CNetscapeApp *)AfxGetApp())->m_pTempDir != NULL && pFormulateName != NULL) {
  511.         StrAllocCopy(pLocalName, ((CNetscapeApp *)AfxGetApp())->m_pTempDir);
  512.         StrAllocCat(pLocalName, "\\");
  513.         StrAllocCat(pLocalName, pFormulateName);
  514.  
  515.         //  If this file exists, then we must attempt another temp file.
  516.         if(-1 != _access(pLocalName, 0))    {
  517.             //  Retain the extension.
  518.             char aExt[_MAX_EXT];
  519.             size_t stExt = 0;
  520.             DWORD dwFlags = 0;
  521.             
  522. #ifdef XP_WIN16
  523.             dwFlags |= EXT_DOT_THREE;
  524. #endif
  525.             aExt[0] = '\0';
  526.             stExt = EXT_Invent(aExt, sizeof(aExt), dwFlags, pUrlData->address, pUrlData->content_type);
  527.  
  528.             if(pLocalName) {
  529.                 XP_FREE(pLocalName);
  530.                 pLocalName = NULL;
  531.             }
  532.             pLocalName = WH_TempFileName(xpTemporary, "E", aExt);
  533.         }
  534.     }
  535.     else    {
  536.         //  Retain the extension.
  537.         char aExt[_MAX_EXT];
  538.         size_t stExt = 0;
  539.         DWORD dwFlags = 0;
  540.         
  541. #ifdef XP_WIN16
  542.         dwFlags |= EXT_DOT_THREE;
  543. #endif
  544.         aExt[0] = '\0';
  545.         stExt = EXT_Invent(aExt, sizeof(aExt), dwFlags, pUrlData->address, pUrlData->content_type);
  546.  
  547.         if(pLocalName) {
  548.             XP_FREE(pLocalName);
  549.             pLocalName = NULL;
  550.         }
  551.         pLocalName = WH_TempFileName(xpTemporary, "E", aExt);
  552.     }
  553.  
  554.     if(pFormulateName != NULL)  {
  555.         XP_FREE(pFormulateName);
  556.         pFormulateName = NULL;
  557.     }
  558.  
  559.     //  Correctly extract the extension from the created file name.
  560.     char aExt[_MAX_EXT];
  561.     size_t stExt = 0;
  562.     DWORD dwFlags = EXT_NO_PERIOD;
  563.     
  564. #ifdef XP_WIN16
  565.     dwFlags |= EXT_DOT_THREE;
  566. #endif
  567.     aExt[0] = '\0';
  568.     stExt = EXT_Invent(aExt, sizeof(aExt), dwFlags, pLocalName, pUrlData->content_type);
  569.     CString csFinalExtension = aExt;
  570.  
  571.     //  Check to see if the embedded file matches any known extensions.
  572.     //  If not, then consider the file of no use to the user.
  573.     //    Use new way if we are in a different style of context.
  574.     if(pEmbeddedApp->type == NP_OLE && pItem->m_isFullPage) {
  575.         //; do nothing for full page OLE.  Because the security dialog already shown on external_viewer_disk_stream.
  576.     }
  577.     else {
  578.         if(wfe_IsExtensionRegistrationValid(csFinalExtension, ABSTRACTCX(pContext)->GetDialogOwner(), TRUE) == FALSE) {
  579.             //  Broken....
  580.             XP_FREE(pLocalName);
  581.             pItem->m_bBroken = TRUE;
  582.             return(NULL);
  583.         }
  584.     }
  585.     //  Open up the file for writing.
  586.     pItem->m_csFileName = pLocalName;
  587.     XP_FREE(pLocalName);
  588.  
  589.     CFileException cfe;
  590.     if(FALSE == pItem->m_cfOutput.Open(pItem->m_csFileName, CFile::modeCreate | CFile::modeWrite, &cfe))    {
  591.         //  Couldn't open.
  592.         pItem->m_bBroken = TRUE;
  593.         return(NULL);
  594.     }
  595.  
  596.     //  Create the stream class that will handle the download.
  597.     //  Send the embed along for the download.
  598.     pItem->m_bLoading = TRUE;
  599.     return(NET_NewStream("EmbeddedItemCheeseSpankDior",
  600.         EmbedWrite,
  601.         EmbedComplete,
  602.         EmbedAbort,
  603.         EmbedReady,
  604.         (void *)pUrlData,
  605.         pContext));
  606. }
  607.  
  608. unsigned int EmbedReady(NET_StreamClass *stream) {
  609.     void *pDataObj=stream->data_object;    
  610.     // pDataObj is an URL struct
  611.     if(wfe_IsTypePlugin((NPEmbeddedApp*)((URL_Struct*)pDataObj)->fe_data))
  612.         return NPL_WriteReady(stream);
  613.  
  614.     //  The the netowrk library how much we're willing to write to our new embedded item.
  615.     return(MAX_WRITE_READY);
  616. }
  617.  
  618. int EmbedWrite(NET_StreamClass *stream, const char *pWriteData, int32 lLength)   {
  619.     void *pDataObj=stream->data_object;    
  620.     // pDataObj is an URL struct
  621.     if(wfe_IsTypePlugin((NPEmbeddedApp*)((URL_Struct*)pDataObj)->fe_data))
  622.         return NPL_Write(stream, (unsigned char *)pWriteData, lLength);
  623.  
  624.     //  Serialize some more information for the embedded item.
  625.     CNetscapeCntrItem *pItem = wfe_GetCntrPtr(pDataObj);
  626.     TRY {   
  627.         pItem->m_cfOutput.Write(pWriteData, CASTUINT(lLength));
  628.     }
  629.     CATCH(CFileException, e)    {
  630.         //  Couldn't write for some reason.
  631.         pItem->m_bBroken = TRUE;
  632.         return(MK_DISK_FULL);
  633.     }
  634.     END_CATCH
  635.  
  636.     return(MK_DATA_LOADED);
  637. }
  638.  
  639. void EmbedComplete(NET_StreamClass *stream)  {
  640.     void *pDataObj=stream->data_object;    
  641.     // pDataObj is an URL struct
  642.     if(wfe_IsTypePlugin((NPEmbeddedApp*)((URL_Struct*)pDataObj)->fe_data))
  643.     {
  644.         NPL_Complete(stream);
  645.         return;
  646.     }
  647.     //  The load is complete.
  648.     //  Close our file.
  649.     CNetscapeCntrItem *pItem = wfe_GetCntrPtr(pDataObj);
  650.     TRY {
  651.         pItem->m_cfOutput.Close();
  652.     }
  653.     CATCH(CFileException, e)    {
  654.         //  Some error.
  655.         pItem->m_bBroken = TRUE;
  656.     }
  657.     END_CATCH
  658. }
  659.  
  660. void EmbedAbort(NET_StreamClass *stream, int iStatus)    {
  661.     void *pDataObj=stream->data_object;    
  662.     // pDataObj is an URL struct
  663.     if(wfe_IsTypePlugin((NPEmbeddedApp*)((URL_Struct*)pDataObj)->fe_data))
  664.     {
  665.         NPL_Abort(stream, iStatus);
  666.         return;
  667.     }
  668.     //  The load was aborted.
  669.     //  Do a normal close, then mark ourselves as broken.
  670.     EmbedComplete(stream);
  671.  
  672.     CNetscapeCntrItem *pItem = wfe_GetCntrPtr(pDataObj);
  673.     pItem->m_bBroken = TRUE;
  674. }
  675. };
  676.  
  677. BOOL wfe_IsExtensionRegistrationValid(CString& csExtension, CWnd *pWnd, BOOL bAskDialog) {
  678. //    Purpose:    Determine if an extension will present the user with a useful embedded item.
  679. //    Arguments:  csExtension The extension of the data file.
  680. //              pWnd        The calling window
  681. //    Returns:    BOOL    TRUE    The extension has an application present that can handle it.
  682. //                      FALSE   Either the extension is not presently registered,
  683. //                              the registered viewer is no longer present locally, or
  684. //                              the application isn't trusted (CanSpawn).
  685. //    Comments:   Troy's handywork.
  686. //    Revision History:
  687. //      02-07-95    created GAB
  688. //      04-10-95    modified to check and see if execution of the application has
  689. //                      been cleared by the user.
  690. //
  691.  
  692.     char szExt[_MAX_EXT], szValue[_MAX_PATH];
  693.     long cb;
  694.     OFSTRUCT of;
  695.  
  696.     //  First, try the system registry.
  697.     wsprintf(szExt, ".%s", (LPCSTR)csExtension);
  698.     cb = sizeof(szValue);
  699.     if(RegQueryValue(HKEY_CLASSES_ROOT, szExt, szValue, &cb) == ERROR_SUCCESS)  {
  700.         CString strKey = szValue;
  701.         strKey += "\\shell\\open\\command";
  702.         cb = sizeof(szValue);
  703.         if(RegQueryValue(HKEY_CLASSES_ROOT, strKey, szValue, &cb) == ERROR_SUCCESS) {
  704.             //  Just use the app name, ignore switches.
  705. //            char *pAppName = strtok(szValue, " ");
  706.  
  707.             // mwh this is becuase in Win 32 directory name can have space. 
  708.             // still need to fix the cause that the directory has '.'
  709.  
  710.             char *pAppName = strchr(szValue, '.');
  711.             if (pAppName) {
  712.                 char *next = strchr(pAppName, ' ');
  713.                 *next = '\0';  // NULL terminated the string.
  714.  
  715.                 // mhw to get around the problem, that some shell command have "".
  716.                 if (*(next-1) == '"') *(next-1) = 0; 
  717.                 if (szValue[0] == '"')
  718.                     pAppName = &szValue[1];
  719.                 else
  720.                     pAppName = szValue;
  721.                 if(pAppName)    {
  722.                     if(OpenFile(pAppName, &of, OF_EXIST) != HFILE_ERROR)    {
  723.                         //  See if we can spawn this app.
  724.                         if(bAskDialog == TRUE)
  725.                             return(((CNetscapeApp *)AfxGetApp())->m_pSpawn->CanSpawn(CString(pAppName), pWnd));
  726.                         else
  727.                             return TRUE;
  728.                     }
  729.                 }
  730.             }
  731.         }
  732.     }
  733.  
  734.     //  Second try win.ini win16 associations.
  735.     if(::GetProfileString("Extensions", csExtension, "", szValue, sizeof(szValue))) {
  736.         char *pAppName = strtok(szValue, " ");
  737.         if(pAppName != NULL)    {
  738.             if(OpenFile(pAppName, &of, OF_EXIST) != HFILE_ERROR)    {
  739.                 //  see if we can spawn this app.
  740.                 if(bAskDialog == TRUE)
  741.                     return(((CNetscapeApp *)AfxGetApp())->m_pSpawn->CanSpawn(CString(pAppName), pWnd));
  742.                 else
  743.                     return TRUE;
  744.             }
  745.         }
  746.     }
  747.     //  Neither will work, nothing will work.
  748.     return(FALSE);
  749. }
  750.