Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

544 lines
17 KiB

//*********************************************************************
//* Microsoft Windows **
//* Copyright(c) Microsoft Corp., 1995 **
//*********************************************************************
/*Included Files------------------------------------------------------------*/
#include "all.h"
#include "safestrm.h"
#include "decoder.h"
#include "history.h"
#include "midi.h"
#include "mci.h"
#include "wc_html.h"
#include "blob.h"
#ifdef FEATURE_VRML
#include "vrml.h"
#endif
/*Structures----------------------------------------------------------------*/
/*
This is the internal structure that will eventually get passed
to the blob callback
*/
PBGBLOBPARAMS BGBLOBPARAMSConstruct(){
PBGBLOBPARAMS pBGBlobParams;
pBGBlobParams = GTR_MALLOC(sizeof(*pBGBlobParams));
if (pBGBlobParams){
memset(pBGBlobParams, 0, sizeof(*pBGBlobParams));
}
return pBGBlobParams;
}
static void BGBLOBPARAMSDestruct(PBGBLOBPARAMS pBGBlobParams){
/*nore any of this*/
if (pBGBlobParams) {
if (pBGBlobParams->pszFilePath) {
GTR_FREE(pBGBlobParams->pszFilePath);
}
if (pBGBlobParams->szRequestedURL) {
GTR_FREE(pBGBlobParams->szRequestedURL);
}
GTR_FREE(pBGBlobParams);
}
}
static void BackgroundBlob_Callback(void *param, const char *pszURL, BOOL bAbort, const char *pszFileHREF, BOOL fDCache, DCACHETIME dctExpires, DCACHETIME dctLastModif)
{
BGBLOBPARAMS * pBGBlobParams = (BGBLOBPARAMS *) param;
ELEMENT *pel;
int z;
BOOL fResetDCacheCurDoc=FALSE;
/*Did everything go as planned?*/
if (!bAbort && pBGBlobParams && pBGBlobParams->pszFilePath) {
/*Cache this file*/
if (fDCache && gPrefs.bEnableDiskCache) {
FUpdateBuiltinDCache(pBGBlobParams->OriginalFormat,
pszURL, &pBGBlobParams->pszFilePath,
dctExpires, dctLastModif, TRUE, pBGBlobParams->tw);
fResetDCacheCurDoc=TRUE;
}
/*Start everyone that requested a fixup*/
if (pBGBlobParams->tw && pBGBlobParams->tw->w3doc){
pel = pBGBlobParams->tw->w3doc->aElements;
for (z=0;z>=0;z=pel[z].next){
if ( (pel[z].pblob)
&& (pel[z].pblob->dwFlags & BLOB_FLAGS_FIXUP)
&& (0 == _stricmp(pel[z].pblob->szURL, pel[pBGBlobParams->iIndex].pblob->szURL))
){
ASSERT(!(pel[z].pblob->dwFlags & BLOB_FLAGS_LOADED));
/*reset state flags*/
pel[z].pblob->dwFlags &= ~(BLOB_FLAGS_LOADING|BLOB_FLAGS_FIXUP);
pel[z].pblob->dwFlags |= BLOB_FLAGS_LOADED;
/*fill in blob structure with newly resolved local file name*/
if (BlobStoreFileName(pel[z].pblob, (char*) pBGBlobParams->pszFilePath)){
/*callback to start execution*/
(*pBGBlobParams->pCallback)(pBGBlobParams->tw, pel+z);
}
}
}
}
}
if (fResetDCacheCurDoc)
ResetCIFEntryCurDoc(pszURL);
/*clean up callback data*/
BGBLOBPARAMSDestruct(pBGBlobParams);
}
/*
Called from within Image_LoadAll_Async in imgcache.c, this lightweight
thread is responsible for loading the pel/blob combo that was passed in.
*/
#define STATE_BLOB_LOADED STATE_OTHER
int LoadBackgroundBlobs_Async(struct Mwin *tw, int nState, void **ppInfo){
struct Params_LoadBackgroundBlobs *pParams;
struct Params_LoadAsync *pLoadParams;
PBGBLOBPARAMS pBGBlobParams;
ELEMENT *pel;
char *pFileName;
BOOL fWire;
int output_format;
int z;
int iStatusBarTextID;
BOOL bAutoLoadVideos = gPrefs.bAutoLoadVideos;
if (ppInfo){
pParams = *ppInfo;
switch (nState) {
case STATE_INIT:
if (!tw || !tw->w3doc) return STATE_ABORT;
pel = pParams->twDoc->w3doc->aElements;
#ifdef FEATURE_VRML
// If we're on a full pane VRML page, pretend gprefs.bAutoLoadVideos is TRUE
if ( (tw->w3doc->flags & W3DOC_FLAG_FULL_PANE_VRML) &&
(pel[pParams->iIndex].lFlags & ELEFLAG_FULL_PANE_VRML_FIRST_LOAD ) &&
!(pel[pParams->iIndex].lFlags & ELEFLAG_HIDDEN )
)
{
// Clear the first load flag, so that reconnects to page will load
pel[pParams->iIndex].lFlags &= ~ELEFLAG_FULL_PANE_VRML_FIRST_LOAD;
bAutoLoadVideos = TRUE;
// we bail out since we're downloading it from another place
goto LoadBackgroundBlobs_Async_Exit;
}
#endif
/*Is another instance of us loading?*/
ASSERT(pel[pParams->iIndex].pblob);
for (z=0;z>=0;z=pel[z].next){
if ((z!=pParams->iIndex)
&& (pel[z].pblob)
&& (0 == _stricmp(pel[z].pblob->szURL, pel[pParams->iIndex].pblob->szURL))
){
if (pel[z].pblob->dwFlags & BLOB_FLAGS_LOADING){
pel[pParams->iIndex].pblob->dwFlags |= BLOB_FLAGS_FIXUP;
goto LoadBackgroundBlobs_Async_Exit;
}
}
}
pel = pParams->twDoc->w3doc->aElements + pParams->iIndex;
// making the assertion that this loop above is going
// to find a pel with a pblob
ASSERT(pel);
ASSERT(pel->pblob);
// clear any error that may be set
pel->pblob->dwFlags &= ~BLOB_FLAGS_ERROR;
/*do we get this from the wire, or is the local version ok?!?!?*/
if (PROT_FILE == ProtocolIdentify(pel->pblob->szURL))
{
fWire = FALSE;
pFileName = pel->pblob->szURL+5;
}
else {
fWire = TRUE;
pFileName = NULL;
}
if (pFileName && !BlobStoreFileName(pel->pblob, (char*) pFileName)){
goto LoadBackgroundBlobs_Async_Exit;
}
if (pParams->bLocalOnly){
// if our autoload images are off, but our play bk sounds
// are on, then we need to do a download for the sounds.
// otherwise we'll end up not loading sounds just because
// we're not showing images, B#391
if ( !gPrefs.bAutoLoadImages && gPrefs.bPlayBackgroundSounds &&
pel->type == ELE_BGSOUND )
{
pParams->bLocalOnly = FALSE;
} else if ( !gPrefs.bAutoLoadImages && bAutoLoadVideos &&
pel->type == ELE_IMAGE )
{
pParams->bLocalOnly = FALSE;
}
else
{
// otherwise do the normal stuff for bLocalOnly
if (!pFileName) goto LoadBackgroundBlobs_Async_Exit;
else fWire = FALSE;
}
}
// default
iStatusBarTextID = RES_STRING_BLOB_MCI;
/*determine what we are getting anyway. restart if local version ok*/
switch(pel->type){
case ELE_BGSOUND:
iStatusBarTextID = RES_STRING_BLOB_BGSOUND;
if (gPrefs.bPlayBackgroundSounds){
// if we don't have a sound card
// or MIDI device, then there is no need
// to download this file, B#539
if ( waveOutGetNumDevs() == 0 &&
midiOutGetNumDevs() == 0 )
goto LoadBackgroundBlobs_Async_Exit;
if (!fWire){
pel->pblob->dwFlags |= BLOB_FLAGS_LOADED;
BackgroundSoundFile_Callback(pParams->twDoc, pel);
goto LoadBackgroundBlobs_Async_Exit;
}
else{
/* This is a hack to figure out if we have a
* valid sound file. We basically just check for
* the filename (url in this case) to have the
* correct extension. Refer to DwValidSoundFile
* for details. (Bug 318)
*/
if (DwValidSoundFile(pel->pblob->szURL))
output_format = WWW_BGSOUND;
else goto LoadBackgroundBlobs_Async_Exit;
}
}
else goto LoadBackgroundBlobs_Async_Exit;
break;
case ELE_IMAGE:
#ifdef FEATURE_VRML
ASSERT(pel->pmo || pel->pVrml);
// if we're forcing a download then we need
// to download this guy even though we're not
// supposed to show the images
if (pel->pVrml)
iStatusBarTextID = RES_STRING_BLOB_VRML;
else
iStatusBarTextID = RES_STRING_BLOB_MCI;
if (bAutoLoadVideos || pParams->bJustOne)
{
if (!fWire)
{
pel->pblob->dwFlags |= BLOB_FLAGS_LOADED;
if (pel->pmo)
BackgroundMciFile_Callback(pParams->twDoc, pel);
else if (pel->pVrml)
BackgroundVRMLFile_Callback(pParams->twDoc, pel);
goto LoadBackgroundBlobs_Async_Exit;
}
else
{
if (pel->pmo)
output_format = WWW_MCI;
else if (pel->pVrml)
output_format = WWW_VRML;
}
}
else
{
// if we're not in an image download mode
// then lets stop this download process.
if (!gPrefs.bAutoLoadImages && !bAutoLoadVideos && pel->myImage)
{
pel->myImage->flags = IMG_NOTLOADED;
pel->myImage->flags |= IMG_LOADSUP;
pel->myImage->height = pel->myImage->width = 0;
}
goto LoadBackgroundBlobs_Async_Exit;
}
break;
#else
ASSERT(pel->pmo);
if (bAutoLoadVideos || pParams->bJustOne){
if (!fWire){
pel->pblob->dwFlags |= BLOB_FLAGS_LOADED;
BackgroundMciFile_Callback(pParams->twDoc, pel);
goto LoadBackgroundBlobs_Async_Exit;
}
else output_format = WWW_MCI;
}
break;
#endif
default:
ASSERT(0);
break;
}
/*we have a valid thing we are grabbing from the wire*/
pParams->pDest = Dest_CreateDest(pel->pblob->szURL);
if (NULL == pParams->pDest) return STATE_ABORT;
pLoadParams = GTR_MALLOC(sizeof(*pLoadParams));
if (pLoadParams == NULL) return STATE_ABORT;
memset(pLoadParams,0,sizeof(*pLoadParams));
pParams->status = 0;
pLoadParams->pStatus = &(pParams->status);
// By default, we say that it's not ok to load from dcache.
// This will kick in the If-Modified-since code if this
// blob is in dcache. Else it will fetch from wire anyway.
pLoadParams->fLoadFromDCacheOK = FALSE;
/* Set up the request structure */
pParams->pRequest = pLoadParams->request = HTRequest_new();
if (pLoadParams->request) {
/*force the output format so that we get called back*/
HTFormatInit(pLoadParams->request->conversions);
pLoadParams->request->output_format = output_format;
/*create our user defined data and place it in a spot that will be passsed along*/
pBGBlobParams = BGBLOBPARAMSConstruct();
if (pBGBlobParams){
char szBuf[MAX_URL_STRING+1]; // scratch buffer for rendering Status Bar
char *pszMallocBuf;
pBGBlobParams->iIndex = pParams->iIndex;
pBGBlobParams->tw = pParams->twDoc;
pLoadParams->request->context = (void *) pBGBlobParams;
pLoadParams->request->destination = pParams->pDest;
pLoadParams->request->referer = pParams->twDoc->w3doc->szActualURL;
pel->pblob->dwFlags |= (BLOB_FLAGS_LOADING|BLOB_FLAGS_FIXUP);
// if we're downloading a bunch of blobs ie we're doing
// a complete download of a page, then don't complain on
// each and every failure. Just show the error placeholder
if ( ! pParams->bJustOne )
pLoadParams->request->iFlags |= HTREQ_STOP_WHINING;
pLoadParams->request->fNotFromCache = pParams->bNoImageCache;
pLoadParams->request->iFlags &= ~HTREQ_RECORD;
pLoadParams->request->iFlags |= HTREQ_IF_IN_CACHE_DONT_READ_DATA;
pszMallocBuf = GTR_MALLOC( MAX_URL_STRING );
if ( pszMallocBuf )
{
GTR_strncpy(szBuf, pel->pblob->szURL, MAX_URL_STRING );
make_URL_HumanReadable(szBuf, NULL, FALSE );
GTR_formatmsg(iStatusBarTextID,pszMallocBuf, MAX_URL_STRING,szBuf);
WAIT_Push(tw, -1, pszMallocBuf);
WAIT_Lock( TRUE ) ;
GTR_FREE(pszMallocBuf);
}
else
{
// worst case is we won't have our status bar text
WAIT_Push(tw, -1, NULL);
}
Async_DoCall(HTLoadDocument_Async, pLoadParams);
return STATE_BLOB_LOADED;
}
}
/*fallthrough to abort*/
case STATE_ABORT:
case STATE_BLOB_LOADED:
if (pParams){
if (pParams->twDoc && pParams->twDoc->w3doc){
WAIT_Lock( FALSE ) ;
WAIT_Pop(tw);
pel = pParams->twDoc->w3doc->aElements + pParams->iIndex;
if (pel && pel->pblob)
{
pel->pblob->dwFlags &= ~BLOB_FLAGS_LOADING;
if ( pParams->pRequest && (pParams->pRequest->iFlags & HTREQ_HAD_ERROR))
{
pel->pblob->dwFlags |= BLOB_FLAGS_ERROR;
#ifdef FEATURE_VRML
// If we encountered an error when downloading a blob for the VRML hidden
// element, we need to notify the VRML viewer.
//
if (pel->pVrml && (pel->pVrml->dwFlags & VRMLF_INLINE)) {
BackgroundVRMLFile_Callback(pParams->twDoc, pel);
}
#endif
// if we don't have an Image, then mark the image as
// well as errored out
if ( pel->myImage && !pel->myImage->actualURL)
pel->myImage->flags = IMG_ERROR | (pel->myImage->flags & ~(IMG_ERROR|IMG_MISSING|IMG_NOTLOADED));
}
}
if (pParams->pDest) Dest_DestroyDest(pParams->pDest);
}
if (pParams->pRequest) HTRequest_delete(pParams->pRequest);
}
break;
}
/*
sometimes you feel like a nut, sometimes you don't
but really, quick exit so flag won't move as much on a revisit to a page
where everything is cached
*/
LoadBackgroundBlobs_Async_Exit:
/*reduce outstanding thread count so flag functions properly*/
if (pParams->pImgThreads){
pParams->pImgThreads = pSafeFree(pParams->pImgThreads);
if (pParams->pImgThreads) Async_UnblockThread(pParams->thidParent);
}
if (pParams->pDecoder) makeAvailable((PDECODER)pParams->pDecoder);
}
return STATE_DONE;
}
/*******************************************************************
NAME: GTR_DownloadBackgroundBlob
SYNOPSIS: Called when we are about to start downloading a
background sound file
********************************************************************/
HTStream *GTR_DownloadBackgroundBlob(struct Mwin *tw, HTRequest *request, void *param, HTFormat input_format, HTFormat output_format, HTStream *output_stream){
PBGBLOBPARAMS pBGBlobParams;
BOOL bWasSilent;
HTStream *me;
request = HTRequest_validate(request);
if (!request) return NULL;
pBGBlobParams = (PBGBLOBPARAMS) request->context;
if (request->szLocalFileName){
request->savefile = GTR_strdup(request->szLocalFileName);
}
else{
if (!request->fImgFromDCache)
{
// generate a temporary file name. This will be in the DCache
// directory but have some random .TMP name. This will get renamed
// by the caching code later on so it arrives at its proper name
// in the cache. A little weird, huh?
if (!(request->savefile = (char *) GTR_MALLOC(_MAX_PATH + 1))) {
BGBLOBPARAMSDestruct(pBGBlobParams);
return NULL;
}
// Get a temporary file name
if ( GetTempFileName(gPrefs.szCacheLocation, "A", 0, request->savefile) == 0 ) {
char path[_MAX_PATH + 1] = "";
PREF_GetTempPath(_MAX_PATH, path);
GetTempFileName(path, "A", 0, request->savefile);
}
}
}
pBGBlobParams->szRequestedURL = GTR_strdup(request->destination->szRequestedURL);
if (pBGBlobParams->szRequestedURL){
pBGBlobParams->OriginalFormat = input_format;
pBGBlobParams->pszFilePath = request->savefile;
request->nosavedlg = TRUE;
/*
get state of stuff downloading in background
we do this because HTSaveWithCallback puts up that annoying message
when we are downloading and want to switch pages.
we supress this behavior if a BLOB was the cause
*/
bWasSilent = tw->bSilent;
if (WWW_BGSOUND == request->output_format) pBGBlobParams->pCallback = BackgroundSoundFile_Callback;
else if (WWW_MCI == request->output_format) pBGBlobParams->pCallback = BackgroundMciFile_Callback;
#ifdef FEATURE_VRML
else if (WWW_VRML == request->output_format) pBGBlobParams->pCallback = BackgroundVRMLFile_Callback;
#endif
else if (WWW_PRESENT == request->output_format) pBGBlobParams->pCallback = BackgroundVRMLFile_Callback;
else ASSERT(0);
me = HTSaveWithCallback(tw, request,pBGBlobParams, input_format, BackgroundBlob_Callback);
tw->bSilent = bWasSilent;
}
else me = NULL;
return me;
}
/*Helper Functions for external structures----------------------------------*/
PBLOBstuff BlobConstruct(){
PBLOBstuff pblob;
pblob = GTR_MALLOC(sizeof(*pblob));
memset(pblob, 0, sizeof(*pblob));
return pblob;
}
void BlobDestruct(PBLOBstuff pblob){
if (pblob){
if (pblob->szURL) GTR_FREE(pblob->szURL);
if (pblob->szFileName) GTR_FREE(pblob->szFileName);
GTR_FREE(pblob);
}
}
BOOL BlobStoreUrl(PBLOBstuff pblob, char *pURL){
ASSERT(pblob);
if (pblob->szURL) GTR_FREE(pblob->szURL);
pblob->szURL = GTR_strdup(pURL);
return pblob->szURL?TRUE:FALSE;
}
BOOL BlobStoreFileName(PBLOBstuff pblob, char *pFileName){
ASSERT(pblob);
if (pblob->szFileName) GTR_FREE(pblob->szFileName);
pblob->szFileName = GTR_strdup(pFileName);
return pblob->szFileName?TRUE:FALSE;
}
/* Remove all blobs in a document
* Sort of replicated from Image_NukeImages && blob part of Image_Nuke
*/
BOOL FNukeBlobs(struct _www *pW3doc, BOOL bNukeDCache)
{
int i;
BOOL fSomethingNuked = FALSE;
for (i = 0; i < pW3doc->elementCount; i++)
{
if (pW3doc->aElements[i].pblob)
{
if (bNukeDCache && pW3doc->aElements[i].pblob->szURL )
{
pW3doc->aElements[i].pblob->dwFlags &= ~( BLOB_FLAGS_LOADING | BLOB_FLAGS_FIXUP | BLOB_FLAGS_LOADED );
FlushDCacheEntry(pW3doc->aElements[i].pblob->szURL);
fSomethingNuked = TRUE;
}
}
}
return fSomethingNuked;
}