/* -*- 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. */ #include "stdafx.h" #include "wfedde.h" #include "ddectc.h" #include "cxsave.h" #include "extgen.h" extern "C" int MK_DISK_FULL; // defined in allxpstr.h CDDEStreamData::CDDEStreamData(const char *pServer, const char *pMimeType, DWORD dwSDIFlags, BOOL bQueryViewer) : CStreamData(CStreamData::m_DDE) { // Purpose: Construct the data stream object. // Arguments: pServer The name of the server that we should contact // in our data stream. // pMimeType The mime type fo the stream. // dwSDIFlags How we should contact the server. This will // converted into an internal type. // bQueryViewer Wether or not we should query a remote applciation // for the file in which we should save our data. // Returns: none // Comments: Note that we initialize the base class to know we are a DDE // viewer. // Revision History: // 01-06-95 created GAB // // Simply assign the members over for now. m_csServerName = pServer; m_csMimeType = pMimeType; m_bQueryViewer = bQueryViewer; switch(dwSDIFlags) { case 0x1L: m_dwHowHandle = m_OpenDocument; break; case 0x4L: m_dwHowHandle = m_ViewDocFile; break; case 0x8L: m_dwHowHandle = m_ViewDocData; break; } } CDDEDownloadData::CDDEDownloadData(CDDEStreamData *pCData, const char *pAddress, DWORD dwFrameID) { // Purpose: Create an instance of the download data. // Arguments: pCData A global object representing our DDE registered // viewer. // pAddress The URL we're loading, we'll use this to // construct a file name, and open it. // dwFrameID The frame performing the download. // Returns: none // Comments: Download instance specific member. // Revision History: // 01-06-95 created GAB // // Assign over our data. m_pCData = pCData; // Mark so that we know to delete any files that we create at // exit. m_bDelete = TRUE; // Save the URL/address m_csURL = pAddress; // Save the frame performing the download. m_dwFrameID = dwFrameID; // Create the file name. // Attempt to save as much of the file name as possible. char *cpFullName = ::fe_URLtoLocalName(pAddress, NULL); char *cpTempDir = theApp.m_pTempDir; if(cpFullName != NULL && cpTempDir != NULL) { char caNameBuffer[_MAX_PATH]; ::sprintf(caNameBuffer, "%s\\%s", cpTempDir, cpFullName); if(::_access(caNameBuffer, 0) == -1) { m_csFileName = caNameBuffer; } } if(cpFullName != NULL) { ::free(cpFullName); } // If our file name is still empty, then we must create it another // way, by using only the extension and some random name. // We leave as dot three, as we may be 32 bits yet talking to a 16 // bit DDE app. if(m_csFileName.IsEmpty()) { char caExt[_MAX_EXT]; DWORD dwFlags = EXT_DOT_THREE; size_t stExt = 0; caExt[0] = '\0'; stExt = EXT_Invent(caExt, sizeof(caExt), dwFlags, pAddress, NULL); { char* filename = WH_TempFileName(xpTemporary, "M", caExt); if (filename) { m_csFileName = filename; XP_FREE(filename); } } } // Okay, we've got the file name that will suite our needs. TRY { // Leave as shared readable for DDE apps looking into the file early. m_pStream = new CFile(m_csFileName, CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite); } CATCH(CFileException, e) { THROW_LAST(); } END_CATCH } extern "C" { NET_StreamClass *dde_stream(int iFormatOut, void *vpDataObj, URL_Struct *pURL, MWContext *pContext) { // Purpose: Return the stream class for our DDE stream. // Arguments: iFormatOut The representation we are outputting. // vpDataObj Our CDDEStreamData structure. // pURL The URL we're loading. // pContext The current context we're loading in. // Returns: NET_StreamClass A group of functions that will handle // the details of the download. // Comments: Set up the data stream. // The stream will be lost on completion if the app failed // to unregister itself with us and exited. // Can't really handle. // Revision History: // 01-06-95 created GAB // 10-20-95 Hacked it up to use a secondary stream through CSaveCX if possible. // NET_StreamClass *pRetval = NULL; // Convert our data object. CDDEStreamData *pCData = (CDDEStreamData *)vpDataObj; // Let's not be romantic about this, create our download data // and then the stream class. TRY { CDDEDownloadData *pDData = new CDDEDownloadData(pCData, pURL->address, FE_GetContextID(pContext)); pRetval = NET_NewStream("PaperbackWriter", dde_StreamWrite, dde_StreamComplete, dde_StreamAbort, dde_StreamReady, (void *)pDData, pContext); } CATCH(CException, e) { // Any exception will do pRetval = NULL; } END_CATCH if(pRetval != NULL) { // Attempt to go beyond, and get a secondary stream going // to split this off into a new context. // I know this says OLE, but it will work anyhow.... NET_StreamClass *pShunt = CSaveCX::OleStreamObject(pRetval, pURL, pCData->m_csServerName); if(pShunt != NULL) { pRetval = pShunt; } } return(pRetval); } int dde_StreamWrite(NET_StreamClass *stream, const char *cpWriteData, int32 lLength) { // Purpose: Write data out to the stream. // Arguments: vpDataObj Our download instance object. // cpWriteData The data to write. // lLength The amount of data to write. // Returns: int Return one of the infamous MK_* codes. // Comments: Hacking for a return value, it would seem. // Revision History: // 01-06-95 created GAB // // Obtain our data object. CDDEDownloadData *pDData = (CDDEDownloadData *)stream->data_object; TRY { ASSERT(lLength < 0x0000FFFFL); pDData->m_pStream->Write((const void *)cpWriteData, CASTINT(lLength)); } CATCH(CException, e) { // Just return out of disk space, any exception. return(MK_DISK_FULL); } END_CATCH return(MK_DATA_LOADED); } void dde_StreamComplete(NET_StreamClass *stream) { // Purpose: Called when a stream comes to its successful completion. // Arguments: vpDataObj Our download instance object // Returns: void // Comments: Just unitialize mainly. // Revision History: // 01-06-95 created // // Get our object. CDDEDownloadData *pDData = (CDDEDownloadData *)stream->data_object; // First off, close and free our file object. delete(pDData->m_pStream); pDData->m_pStream = NULL; // Now, see what we're supposed to do with this closed file. if(pDData->m_pCData->m_bQueryViewer == TRUE) { // We're to move the file to a new locale, and then // send whatever open message.... CDDEWrapper::QueryViewer(pDData); } // Okay, see if we're supposed to delete this file on exit. if(pDData->m_bDelete == TRUE) { FE_DeleteFileOnExit(pDData->m_csFileName, pDData->m_csURL); } // Switch on how to open. switch(pDData->m_pCData->m_dwHowHandle) { case CDDEStreamData::m_OpenDocument: // We're to use a platform specific open, this means // Shell Open to windows. CDDEWrapper::OpenDocument(pDData); break; case CDDEStreamData::m_ViewDocFile: // We're to simply tell the viewer what file to take a // look at. // Have our DDE member handle all the contingencies. CDDEWrapper::ViewDocFile(pDData); break; case CDDEStreamData::m_ViewDocData: default: // Not supported. ASSERT(0); break; } // We're basically done. // Free off the download specific data. delete(pDData); } void dde_StreamAbort(NET_StreamClass *stream, int iStatus) { // Purpose: Abort a streaming download. // Arguments: vpDataObj Our download instance information. // iStatus Our abort status. // Returns: void // Comments: Abort the stream, just as we close a connection. // We should send any streaming DDE clients a special // message. // Revision History: // 01-06-95 created GAB // // Get our object. CDDEDownloadData *pDData = (CDDEDownloadData *)stream->data_object; // Handle just like a normal file close. dde_StreamComplete(stream); } unsigned int dde_StreamReady(NET_StreamClass *stream) { // Purpose: Tell the nework library how much data every one is // ready to receive. // Arguments: vpDataObj Our download instance informational fucntion. // Returns: int The amount of data the stream is ready for. // Comments: On files, like what we are normally handline, simply // return the maximum amount. // On streaming clients, just ask them how much they can // now take. // Revision History: // 01-06-95 created GAB // // Get our object. CDDEDownloadData *pDData = (CDDEDownloadData *)stream->data_object; // Return our maximum write value for local files. return((unsigned int)MAX_WRITE_READY); } };