mirror of https://github.com/lianthony/NT4.0
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.
1613 lines
41 KiB
1613 lines
41 KiB
/*
|
|
Enhanced NCSA Mosaic from Spyglass
|
|
"Guitar"
|
|
|
|
Copyright 1994 Spyglass, Inc.
|
|
All Rights Reserved
|
|
|
|
Author(s):
|
|
Jim Seidman [email protected]
|
|
*/
|
|
|
|
#include "all.h"
|
|
#include "history.h"
|
|
#include "htmlutil.h"
|
|
#include "wc_html.h"
|
|
#include "blob.h"
|
|
#define TIMER_PULL 1022
|
|
#ifdef FEATURE_IAPI
|
|
#include "w32dde.h"
|
|
#endif
|
|
#ifdef FEATURE_INTL
|
|
#define IEXPLORE
|
|
#include <fechrcnv.h>
|
|
#endif
|
|
|
|
#ifdef FEATURE_TESTHOOK
|
|
// defined in dumpanch.c
|
|
extern void TestDumpAnchors(struct _www*);
|
|
extern void TestSignalLoadDone(WORD);
|
|
#endif
|
|
|
|
#ifdef FEATURE_KEEPALIVE
|
|
#define KEEPALIVE_TIME 60000
|
|
#endif
|
|
|
|
static void x_DoLoadDocument(struct Mwin *tw, struct DestInfo *pDest,
|
|
BOOL bRecord, BOOL bPost, BOOL bNoDocCache,
|
|
BOOL bNoImageCache, BOOL bAuthFailCacheOK,
|
|
CONST char * szPostData, CONST char *szReferer,
|
|
BOOL fLoadFromDCacheOK);
|
|
|
|
/* DDE result information structure passed to IssueURLResult() */
|
|
|
|
typedef struct dderesultinfo
|
|
{
|
|
/* DDE transaction ID */
|
|
|
|
LONG lTransID;
|
|
|
|
/* window ID */
|
|
|
|
LONG lSerialID;
|
|
|
|
/* transaction result */
|
|
|
|
BOOL bResult;
|
|
|
|
/* referent's URL */
|
|
|
|
PSTR pszURL;
|
|
|
|
/* referent's MIME type */
|
|
|
|
HTAtom htaMIMEType;
|
|
}
|
|
DDERESULTINFO;
|
|
DECLARE_STANDARD_TYPES(DDERESULTINFO);
|
|
|
|
#ifdef DEBUG
|
|
|
|
PRIVATE_CODE BOOL IsValidPCDDERESULTINFO(PCDDERESULTINFO pcdderi)
|
|
{
|
|
/* bResult may be any value. */
|
|
|
|
/* BUGBUG: Beef up validation for lTransID and lSerialID. */
|
|
|
|
return ( IS_VALID_READ_PTR(pcdderi, CDDERESULTINFO)
|
|
&& ( !pcdderi->pszURL
|
|
|| IS_VALID_STRING_PTR(pcdderi->pszURL, STR))
|
|
&& ( !pcdderi->htaMIMEType
|
|
|| EVAL(IsValidHTAtom(pcdderi->htaMIMEType))));
|
|
}
|
|
|
|
#endif /* DEBUG */
|
|
|
|
/* Ensure that an http URL has a slash after the system name. This function is suitable
|
|
for "fixing" both URLs and proxy server specifications */
|
|
static void x_EnforceHostSlash(char *url)
|
|
{
|
|
char * p = url;
|
|
|
|
while (*p && *p!=':')
|
|
{
|
|
if (isupper(*p))
|
|
*p = tolower(*p);
|
|
p++;
|
|
}
|
|
|
|
if (!strncmp(url, "http://", 7))
|
|
{
|
|
if (!strchr(url + 7, '/'))
|
|
strcat(url, "/");
|
|
}
|
|
#ifdef HTTPS_ACCESS_TYPE
|
|
if (!strncmp(url, "https://", 8))
|
|
{
|
|
if (!strchr(url + 8, '/'))
|
|
strcat(url, "/");
|
|
}
|
|
#endif
|
|
|
|
#ifdef SHTTP_ACCESS_TYPE
|
|
if (!strncmp(url, "shttp://", 8))
|
|
{
|
|
if (!strchr(url + 8, '/'))
|
|
strcat(url, "/");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/* Find the element index for a local anchor */
|
|
int TW_FindLocalAnchor(struct _www *pdoc, char *name)
|
|
{
|
|
int i;
|
|
int nameLen;
|
|
|
|
nameLen = strlen(name);
|
|
|
|
if (pdoc->elementCount)
|
|
{
|
|
for (i = 0; i >= 0; i = pdoc->aElements[i].next)
|
|
{
|
|
if (pdoc->aElements[i].lFlags & ELEFLAG_NAME)
|
|
{
|
|
if (pdoc->aElements[i].nameLen == nameLen)
|
|
{
|
|
if (0 == strncmp(name, &(pdoc->pool[pdoc->aElements[i].nameOffset]), nameLen))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return i;
|
|
}
|
|
|
|
int TW_AddToHistory(struct Mwin *tw, char *url)
|
|
{
|
|
char *mycopy;
|
|
char *last;
|
|
|
|
XX_DMsg(DBG_HIST, ("Adding to window history: %s\n", url));
|
|
|
|
while (tw->history_index--)
|
|
{
|
|
mycopy = HTList_removeLastObject(tw->history);
|
|
GTR_FREE(mycopy);
|
|
#ifdef FEATURE_INTL
|
|
HTList_removeLastObject(tw->MimeHistory);
|
|
#endif
|
|
}
|
|
|
|
last = HTList_objectAt(tw->history, 0);
|
|
if (!last || strcmp(url, last))
|
|
{
|
|
mycopy = GTR_strdup(url);
|
|
|
|
HTList_addObject(tw->history, mycopy);
|
|
tw->history_index = HTList_indexOf(tw->history, mycopy);
|
|
#ifdef FEATURE_INTL
|
|
HTList_addObject(tw->MimeHistory, (tw->w3doc)? (void *)tw->w3doc->iMimeCharSet: (void *)tw->iMimeCharSet);
|
|
#endif
|
|
}
|
|
else
|
|
tw->history_index = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* This is meant to be a convenient interlude function which both reads in the images
|
|
and then reformats the document if necessary. It doesn't use ppInfo at all. */
|
|
int GDOC_LoadImages_Async(struct Mwin *tw, int nState, void **ppInfo)
|
|
{
|
|
struct Params_GDOC_LoadImages *pparams = NULL;
|
|
|
|
if (ppInfo)
|
|
{
|
|
pparams = *ppInfo;
|
|
}
|
|
|
|
if (tw == NULL) return STATE_DONE;
|
|
|
|
switch (nState)
|
|
{
|
|
case STATE_INIT:
|
|
{
|
|
struct Params_Image_LoadAll *pil;
|
|
|
|
pil = GTR_MALLOC(sizeof(*pil));
|
|
pil->tw = tw;
|
|
if (pparams)
|
|
{
|
|
pil->bLocalOnly = pparams->bLocalOnly;
|
|
}
|
|
else
|
|
{
|
|
pil->bLocalOnly = !gPrefs.bAutoLoadImages;
|
|
}
|
|
#ifdef FEATURE_IMG_THREADS
|
|
pil->bNoImageCache = FALSE;
|
|
pil->decoderObject = NULL;
|
|
pil->parentThread = NULL;
|
|
pil->bJustOne = FALSE;
|
|
|
|
// Image_LoadAll_Async tolerates pil->tw not being GIMGMASTER
|
|
#endif
|
|
Async_DoCall(Image_LoadAll_Async, pil);
|
|
return STATE_OTHER;
|
|
}
|
|
|
|
case STATE_OTHER:
|
|
case STATE_ABORT:
|
|
{
|
|
if (W3Doc_CheckForImageLoad(tw->w3doc))
|
|
{
|
|
TW_Reformat(tw, NULL);
|
|
/* TODO: Go back to correct place in document */
|
|
}
|
|
TW_UpdateTBar(tw);
|
|
return STATE_DONE;
|
|
}
|
|
}
|
|
XX_Assert((0), ("Function called with illegal state: %d", nState));
|
|
return STATE_DONE;
|
|
}
|
|
|
|
static void x_HandleCurrentDocument(struct Mwin *tw, struct DestInfo *pDest, BOOL bNoImageCache)
|
|
{
|
|
int ndx;
|
|
|
|
#if defined(FEATURE_IAPI) && defined(WIN32)
|
|
tw->transID = 0; /* special ID - Requested URL is already loaded in the window */
|
|
#endif
|
|
|
|
#if 0
|
|
/* TODO: Make this case work */
|
|
if (bNoImageCache)
|
|
{
|
|
w3doc->bIsShowPlaceholders = FALSE;
|
|
Image_NukeImages(tw->w3doc, TRUE, /*fNukeDCache=*/TRUE);
|
|
if (!g_bAbort)
|
|
Image_LoadAllImages(tw, !gPrefs.bAutoLoadImages);
|
|
}
|
|
#endif
|
|
|
|
W3Doc_CheckAnchorVisitations(tw->w3doc, NULL);
|
|
|
|
/* TW_InvalidateDocument( tw ); */
|
|
|
|
if (pDest->szActualLocal)
|
|
{
|
|
ndx = TW_FindLocalAnchor(tw->w3doc, pDest->szActualLocal);
|
|
if (ndx < 0)
|
|
ndx = 0;
|
|
TW_ScrollToElement(tw, ndx);
|
|
}
|
|
else
|
|
{
|
|
TW_ScrollToElement(tw, tw->w3doc->iFirstVisibleElement);
|
|
}
|
|
}
|
|
|
|
static void RevertToPrevious(struct Mwin *tw, struct _www *w3doc)
|
|
{
|
|
W3Doc_ConnectToWindow(w3doc, tw);
|
|
W3Doc_CheckAnchorVisitations(w3doc, NULL);
|
|
|
|
if (tw->win)
|
|
{
|
|
TW_InvalidateDocument(tw);
|
|
TW_SetWindowName(tw);
|
|
TW_Reformat(tw, NULL);
|
|
TW_ScrollToElement(tw, w3doc->iFirstVisibleElement);
|
|
}
|
|
}
|
|
|
|
static void x_HandleCacheHit(struct Mwin *tw, struct DestInfo *pDest, int doc_index, BOOL bNoImageCache, BOOL bRecord)
|
|
{
|
|
struct _www *w3doc;
|
|
int ndx;
|
|
|
|
/*
|
|
Move the w3doc to the end of the cache list
|
|
*/
|
|
Hash_GetIndexedEntry(&tw->doc_cache, doc_index, NULL, NULL, (void **) &w3doc);
|
|
Hash_DeleteIndexedEntry(&tw->doc_cache, doc_index);
|
|
Hash_Add(&tw->doc_cache, pDest->szActualURL, NULL, (void *) w3doc);
|
|
W3Doc_DisconnectFromWindow(tw->w3doc, tw);
|
|
w3doc->bIsShowPlaceholders = FALSE;
|
|
W3Doc_ConnectToWindow(w3doc, tw);
|
|
W3Doc_CheckAnchorVisitations(w3doc, NULL);
|
|
tw->bLoading = FALSE;
|
|
|
|
if (bNoImageCache)
|
|
{
|
|
Image_NukeImages(tw->w3doc, TRUE, /*fNukeDCache=*/TRUE);
|
|
FNukeBlobs(tw->w3doc, /*fNukeDCache=*/TRUE);
|
|
}
|
|
|
|
if (tw->win)
|
|
{
|
|
TW_SetWindowName(tw);
|
|
TW_Reformat(tw, NULL);
|
|
}
|
|
|
|
if (pDest->szActualLocal)
|
|
{
|
|
ndx = TW_FindLocalAnchor(tw->w3doc, pDest->szActualLocal);
|
|
if (ndx < 0)
|
|
ndx = 0;
|
|
TW_ScrollToElement(tw, ndx);
|
|
}
|
|
else
|
|
{
|
|
TW_ScrollToElement(tw, w3doc->iFirstVisibleElement);
|
|
}
|
|
|
|
if (bRecord)
|
|
{
|
|
TW_AddToHistory(tw, pDest->szActualURL);
|
|
GHist_Add(pDest->szActualURL, tw->w3doc->title, time(NULL),/*fCreateShortcut=*/TRUE);
|
|
UpdateHistoryMenus(tw);
|
|
}
|
|
|
|
/* TW_InvalidateDocument(tw); */
|
|
|
|
{
|
|
struct Params_GDOC_LoadImages *pparams;
|
|
|
|
pparams = GTR_MALLOC(sizeof(*pparams));
|
|
if (pparams)
|
|
{
|
|
pparams->tw = tw;
|
|
pparams->bLocalOnly = !gPrefs.bAutoLoadImages;
|
|
Async_StartThread(GDOC_LoadImages_Async, pparams, tw);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// ClientPullTimerProc - timer proc for Client Pull operations.
|
|
// After we complete a download, we SetTimer on that Mwin,
|
|
// when the time has elapsed we get called to go to the new URL..
|
|
//
|
|
// hWnd : handle to our current window that is getting Pulled ...
|
|
// idEvent: TIMER_PULL, our timer id.
|
|
// ....
|
|
VOID CALLBACK ClientPullTimerProc(
|
|
HWND hWnd, // handle of window for timer messages
|
|
UINT uMsg, // WM_TIMER message
|
|
UINT idEvent, // timer identifier
|
|
DWORD dwTime // current system time
|
|
)
|
|
{
|
|
struct Mwin * tw = GetPrivateData(hWnd);
|
|
|
|
// this is a one-shot timer, so lets kill it
|
|
KillTimer(hWnd, idEvent );
|
|
|
|
// make sure we don't party on with destroyed stuff
|
|
if ( tw == NULL || tw->w3doc == NULL || tw->w3doc->pMeta == NULL )
|
|
return;
|
|
|
|
tw->w3doc->pMeta->uiTimer = 0;
|
|
|
|
// if we have the URL lets go right to it..
|
|
// we may not need to call CreateOrLoad.. perhaps we could call
|
|
// lower in the call stack? perhaps a TW_ func?
|
|
if ( tw->w3doc->pMeta->szURL )
|
|
TW_LoadDocument(tw, tw->w3doc->pMeta->szURL, TW_LD_FL_NO_DOC_CACHE, NULL, NULL);
|
|
else
|
|
{
|
|
// reload by synthing a message WM_COMMAND message...
|
|
// could this be done better?
|
|
if ( tw->win )
|
|
{
|
|
XX_DMsg(DBG_MENU,
|
|
("CC_Forward: forwarding message 0x%x to window 0x%x.\n",
|
|
RES_MENU_ITEM_RELOAD, tw->win));
|
|
(void) SendMessage(tw->win, WM_COMMAND, (WPARAM) RES_MENU_ITEM_RELOAD, 0L);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
PRIVATE_CODE void FreeDDEResultInfo(PDDERESULTINFO pdderi)
|
|
{
|
|
ASSERT(IS_VALID_STRUCT_PTR(pdderi, CDDERESULTINFO));
|
|
|
|
if (pdderi->pszURL)
|
|
{
|
|
FreeMemory(pdderi->pszURL);
|
|
pdderi->pszURL = NULL;
|
|
}
|
|
|
|
FreeMemory(pdderi);
|
|
pdderi = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
** IssueURLResult()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: Frees pv as PDDERESULTINFO.
|
|
*/
|
|
PRIVATE_CODE void IssueURLResult(PVOID pv)
|
|
{
|
|
PDDERESULTINFO pdderi;
|
|
|
|
ASSERT(IS_VALID_STRUCT_PTR(pv, CDDERESULTINFO));
|
|
|
|
pdderi = pv;
|
|
|
|
if (pdderi->lTransID)
|
|
DDE_Issue_Result(pdderi->lTransID, pdderi->lSerialID, pdderi->bResult);
|
|
|
|
DDE_Issue_URLEcho(pdderi->lSerialID, pdderi->pszURL, pdderi->htaMIMEType);
|
|
|
|
FreeDDEResultInfo(pdderi);
|
|
pdderi = NULL;
|
|
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
PRIVATE_CODE BOOL IssueURLResult_Async(PMWIN pmwin, BOOL bURLResult)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
PSTR pszURLCopy = NULL;
|
|
PDDERESULTINFO pdderi = NULL;
|
|
struct Params_mdft *pmdft = NULL;
|
|
|
|
/* bURLResult may be any value. */
|
|
ASSERT(IS_VALID_STRUCT_PTR(pmwin, CMWIN));
|
|
|
|
if (! pmwin->w3doc ||
|
|
! pmwin->w3doc->szActualURL ||
|
|
StringCopy(pmwin->w3doc->szActualURL, &pszURLCopy))
|
|
{
|
|
if (AllocateMemory(sizeof(*pdderi), &pdderi))
|
|
{
|
|
if (AllocateMemory(sizeof(*pmdft), &pmdft))
|
|
{
|
|
/* Fill in DDERESULTINFO. */
|
|
|
|
pdderi->lTransID = pmwin->transID;
|
|
pdderi->lSerialID = pmwin->serialID;
|
|
pdderi->bResult = bURLResult;
|
|
pdderi->pszURL = pszURLCopy;
|
|
pdderi->htaMIMEType = pmwin->mimeType;
|
|
|
|
|
|
/* Fill in Params_mdft. */
|
|
|
|
ZeroMemory(pmdft, sizeof(*pmdft));
|
|
|
|
pmdft->tw = pmwin;
|
|
pmdft->fn = &IssueURLResult;
|
|
pmdft->args = pdderi;
|
|
pmdft->fDontDisable = TRUE;
|
|
|
|
/* IssueURLResult() frees pdderi. */
|
|
|
|
Async_DoCall(MDFT_RunModalDialog_Async, pmdft);
|
|
|
|
bResult = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Free allocated objects on failure. */
|
|
|
|
if (! bResult)
|
|
{
|
|
if (pszURLCopy)
|
|
{
|
|
FreeMemory(pszURLCopy);
|
|
pszURLCopy = NULL;
|
|
}
|
|
|
|
if (pdderi)
|
|
{
|
|
FreeMemory(pdderi);
|
|
pdderi = NULL;
|
|
}
|
|
|
|
if (pmdft)
|
|
{
|
|
FreeMemory(pmdft);
|
|
pmdft = NULL;
|
|
}
|
|
}
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
struct Params_HandleLoadDocument {
|
|
/* To be filled in by caller */
|
|
struct DestInfo *pDest;
|
|
BOOL bRecord;
|
|
BOOL bPost;
|
|
BOOL bNoDocCache;
|
|
BOOL bNoImageCache;
|
|
char * szPostData; /* This is GTR_FREE'd by this function! */
|
|
CONST char * szReferer;
|
|
|
|
/* Used internally by routine */
|
|
HTRequest * request;
|
|
struct _www * prev_w3doc;
|
|
int status;
|
|
#ifdef FEATURE_IMG_THREADS
|
|
struct Mwin *twMaster;
|
|
#endif
|
|
BOOL fLoadFromDCacheOK; //OK to load from dcache,
|
|
//no need to check header response
|
|
//for Last-Modified tag
|
|
};
|
|
|
|
#ifdef FEATURE_KEEPALIVE
|
|
static int cbDownLoads = 0;
|
|
static UINT uiKATimer = 0;
|
|
|
|
// KeepAliveTimerProc - timer proc for Keep Alive reaping operations.
|
|
// After we complete all downloads, we SetTimer, when the time has
|
|
// elapsed we attempt to close keep alive sockets. if we are now
|
|
// in the midst of another download, we let the last x_HandleLoadDocument_Async
|
|
// instance do it for us.
|
|
//
|
|
// ....
|
|
VOID CALLBACK KeepAliveTimerProc(
|
|
HWND hWnd, // handle of window for timer messages
|
|
UINT uMsg, // WM_TIMER message
|
|
UINT idEvent, // timer identifier
|
|
DWORD dwTime // current system time
|
|
)
|
|
{
|
|
|
|
// this is a one-shot timer, so lets kill it
|
|
KillTimer(NULL, uiKATimer );
|
|
// force all free sockets closed
|
|
if (cbDownLoads == 0) Net_CloseUnusedKeepAlive(TRUE);
|
|
}
|
|
#endif
|
|
|
|
|
|
#define STATE_HLD_TRIEDLOAD (STATE_OTHER)
|
|
#define STATE_HLD_GOTIMAGES (STATE_OTHER+1)
|
|
|
|
/* Handle loading an (ostensibly) new document. This could result in an HTTP redirection to a new
|
|
document which is actually present in the cache, in which case we'll call x_DoLoadDocument()
|
|
recursively. */
|
|
static int x_HandleLoadDocument_Async(struct Mwin *tw, int nState, void **ppInfo)
|
|
{
|
|
struct Params_HandleLoadDocument *pParams;
|
|
char buf[MAX_URL_STRING + 32 + 1];
|
|
char *p;
|
|
static BOOL success;
|
|
|
|
#ifdef FEATURE_IMG_THREADS
|
|
struct Params_Image_LoadAll *pil = NULL;
|
|
#endif
|
|
|
|
pParams = *ppInfo;
|
|
|
|
switch (nState)
|
|
{
|
|
case STATE_INIT:
|
|
#ifdef FEATURE_KEEPALIVE
|
|
cbDownLoads++;
|
|
#endif
|
|
if (tw == NULL) goto done;
|
|
#ifdef USE_MEMMANAGE
|
|
GTR_RestoreCushion();
|
|
#endif
|
|
#ifdef FEATURE_IMG_THREADS
|
|
pParams->twMaster = NewMwin(GIMGMASTER);
|
|
pil = GTR_MALLOC(sizeof(*pil));
|
|
if (pParams->twMaster == NULL || pil == NULL)
|
|
{
|
|
if (pParams->twMaster) Plan_close(pParams->twMaster);
|
|
if (pil) GTR_FREE(pil);
|
|
ERR_SimpleError(tw, errLowMemory, RES_STRING_LOADDOC1);
|
|
goto done;
|
|
}
|
|
#endif
|
|
GTR_formatmsg(RES_STRING_LOADDOC2,buf,sizeof(buf));
|
|
// save a pointer where URL will be, to allow humanizing in place
|
|
p = buf + strlen( buf );
|
|
GTR_strncat(buf, pParams->pDest->szActualURL, MAX_URL_STRING);
|
|
make_URL_HumanReadable( p, NULL, FALSE );
|
|
WAIT_Push(tw, waitPartialInteract, buf); // was: waitNoInteract
|
|
WAIT_SetStatusBarIcon( tw, SBI_FindingIcon );
|
|
|
|
tw->bLoading = TRUE;
|
|
|
|
#ifdef FEATURE_IMG_THREADS
|
|
// Launch Image_LoadAll_Async in the blocked state for TW_PARSEBLOCKED
|
|
// When LOADALL completes it clears TW_LOADALLDONE
|
|
pil->bJustOne = FALSE;
|
|
pil->tw = pParams->twMaster;
|
|
pil->bLocalOnly = !gPrefs.bAutoLoadImages;
|
|
pil->bNoImageCache = pParams->bNoImageCache ;
|
|
TW_SETBLOCKED(pParams->twMaster,TW_PARSEBLOCKED);
|
|
TW_SETFLAG(tw,TW_LOADALLACTIVE);
|
|
pil->tw->twParent = tw;
|
|
pil->parentThread = Async_GetCurrentThread();
|
|
Async_BlockThread(Async_StartThread(Image_LoadAll_Async,pil,pParams->twMaster));
|
|
#endif
|
|
/*
|
|
we must check here because we overloaded the bPost field to contain
|
|
information as to whether any data had been sent from a form
|
|
*/
|
|
if (IS_FLAG_SET(pParams->bPost, TW_LD_FL_POST))
|
|
{
|
|
pParams->request = tw->post_request;
|
|
|
|
XX_Assert((pParams->szPostData),
|
|
("x_HandleLoadDocument: bPost set when szPostData NULL."));
|
|
|
|
pParams->request->szPostData = pParams->szPostData;
|
|
|
|
XX_Assert((strcmp(HTAtom_name(pParams->request->content_type),
|
|
"application/x-www-form-urlencoded")==0),
|
|
("x_handleLoadDocument: request content-type not as expected [%s].",
|
|
HTAtom_name(pParams->request->content_type)));
|
|
}
|
|
else
|
|
{
|
|
pParams->request = tw->request;
|
|
|
|
/*
|
|
We need to initialize a few things here to make sure we're not
|
|
getting values left over from previous uses of this request struct.
|
|
TODO We should not be re-using these request structs. We should
|
|
allocate a new one for each request.
|
|
*/
|
|
pParams->request->content_encoding = 0;
|
|
pParams->request->content_length = 0;
|
|
pParams->request->content_type = 0;
|
|
pParams->request->content_language = 0;
|
|
pParams->request->callback = NULL;
|
|
pParams->request->iFlags = 0;
|
|
pParams->request->output_stream = NULL;
|
|
pParams->request->szLocalFileName = NULL;
|
|
#ifdef FEATURE_IAPI
|
|
pParams->request->savefile = NULL;
|
|
#endif
|
|
pParams->request->dctLastModified.dwDCacheTime1 =
|
|
pParams->request->dctLastModified.dwDCacheTime2 = 0;
|
|
}
|
|
|
|
/*
|
|
we overloaded the bPost field
|
|
*/
|
|
if (IS_FLAG_SET(pParams->bPost, TW_LD_FL_SENDING_FROM_FORM))
|
|
pParams->request->iFlags |= HTREQ_SENDING_FROM_FORM;
|
|
|
|
if (IS_FLAG_SET(pParams->bPost, TW_LD_FL_REALLY_SENDING_FROM_FORM))
|
|
pParams->request->iFlags |= HTREQ_REALLY_SENDING_FROM_FORM;
|
|
|
|
pParams->request->pMeta = NULL;
|
|
pParams->request->destination = pParams->pDest;
|
|
pParams->request->referer = pParams->szReferer;
|
|
if ( tw->w3doc && tw->w3doc->pMeta && tw->w3doc->pMeta->bInherit )
|
|
{
|
|
// we've got a redirection, that needs to be born again
|
|
// in a new life .. i mean a new w3doc.
|
|
//
|
|
// to get it over the great barrier to the new world
|
|
// we slide it into a request struct..
|
|
// it shouldn't get touched there ????
|
|
pParams->request->pMeta = tw->w3doc->pMeta;
|
|
// make sure it doesn't come back to haunt us after this one..
|
|
tw->w3doc->pMeta->bInherit = FALSE;
|
|
tw->w3doc->pMeta = NULL;
|
|
}
|
|
|
|
|
|
pParams->prev_w3doc = tw->w3doc;
|
|
pParams->request->fNotFromCache = pParams->bNoDocCache;
|
|
|
|
// indicate to the loader that this is a page that
|
|
// is being downloaded!
|
|
pParams->request->iFlags |= HTREQ_HTML_PAGE_DOWNLOAD;
|
|
|
|
if (pParams->bRecord)
|
|
{
|
|
pParams->request->iFlags |= HTREQ_RECORD;
|
|
}
|
|
else
|
|
{
|
|
pParams->request->iFlags &= (~HTREQ_RECORD);
|
|
}
|
|
pParams->request->bReload = pParams->bNoDocCache;
|
|
|
|
|
|
#ifdef FEATURE_SPM
|
|
#ifdef DISABLED_BY_JIM
|
|
tw->HACK_security_redirect = NULL;
|
|
#endif
|
|
#endif
|
|
/* Call load routines asynchronously. */
|
|
{
|
|
struct Params_LoadAsync *pLoadParams;
|
|
|
|
pLoadParams = GTR_MALLOC(sizeof(*pLoadParams));
|
|
pLoadParams->request = pParams->request;
|
|
pLoadParams->pStatus = &pParams->status;
|
|
pLoadParams->fLoadFromDCacheOK = pParams->fLoadFromDCacheOK;
|
|
Async_DoCall(HTLoadSpecial_Async, pLoadParams);
|
|
}
|
|
return STATE_HLD_TRIEDLOAD;
|
|
|
|
case STATE_HLD_TRIEDLOAD:
|
|
if (pParams->request->szLocalFileName)
|
|
{
|
|
GTR_FREE(pParams->request->szLocalFileName);
|
|
pParams->request->szLocalFileName = NULL;
|
|
}
|
|
|
|
pParams->request->referer = NULL;
|
|
pParams->request->iFlags &= (~HTREQ_RECORD);
|
|
|
|
/* We don't want to do a WAIT_Pop() here because that would bring us back to
|
|
the base state, resetting the globe position. */
|
|
WAIT_Update(tw, waitSameInteract,"");
|
|
|
|
if (pParams->szPostData)
|
|
{
|
|
GTR_FREE(pParams->szPostData);
|
|
pParams->szPostData = NULL;
|
|
}
|
|
|
|
if ( tw && tw->w3doc )
|
|
{
|
|
// hack for WellsFargo, they depend on a weird Netscape
|
|
// feature where class 500 errors always reload even
|
|
// when in memory cache
|
|
|
|
if ( pParams->request->iFlags & HTREQ_NO_MEM_CACHE_ON_PAGE )
|
|
tw->w3doc->flags |= W3DOC_FLAG_NO_MEM_CACHE_ON_PAGE;
|
|
}
|
|
|
|
if ( pParams->request->pMeta && tw->w3doc )
|
|
{
|
|
// watch out..
|
|
// what if we already grabed a W3 for this
|
|
// doc.?
|
|
//
|
|
// OK snatch the Meta struc from the HTTP Request Header..
|
|
// Assuming we found a "Refresh: " in the header.
|
|
//
|
|
if ( !tw->w3doc->pMeta || pParams->request->pMeta->bInherit )
|
|
{
|
|
|
|
// if we hit a redirected, Refresh Tag we need to propagage
|
|
// his idea upward.. an idea that no w3doc should be born
|
|
// without the inalienable right to inherit its refresh tag.
|
|
|
|
tw->w3doc->pMeta = pParams->request->pMeta;
|
|
pParams->request->pMeta = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef FEATURE_SPM
|
|
#ifdef DISABLED_BY_JIM
|
|
if (tw->HACK_security_redirect)
|
|
{
|
|
tw->bLoading = FALSE;
|
|
if (pParams->status == HT_LOADED)
|
|
{
|
|
tw->w3doc->my_anchor = (HTParentAnchor *) tw->HACK_security_redirect;
|
|
pParams->anc = (HTAnchor *) tw->w3doc->my_anchor;
|
|
pParams->adult = (HTParentAnchor *) pParams->anc;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
#endif /* FEATURE_SPM */
|
|
if ( pParams->status == HT_REDIRECTION_ON_FLY
|
|
|| pParams->status == HT_REDIRECTION_DCACHE
|
|
|| pParams->status == HT_REDIRECTION_DCACHE_TIMEOUT)
|
|
{
|
|
BOOL fLoadFromDCacheOK = FALSE;
|
|
|
|
#ifdef FEATURE_IMG_THREADS
|
|
Async_TerminateByWindow(pParams->twMaster);
|
|
#endif
|
|
if (pParams->status == HT_REDIRECTION_ON_FLY)
|
|
{
|
|
/* If we got here, our destination has already been updated to
|
|
reflect the redirection. */
|
|
|
|
/* This isn't useful in the history, but it allows us to properly
|
|
change the link color on redirected links */
|
|
GHist_Add(pParams->pDest->szRequestedURL, "Document moved", time(NULL),/*fCreateShortcut=*/TRUE);
|
|
}
|
|
else
|
|
{
|
|
fLoadFromDCacheOK = TRUE;
|
|
#ifdef XX_DEBUG
|
|
XX_Assert( pParams->status == HT_REDIRECTION_DCACHE
|
|
|| pParams->status == HT_REDIRECTION_DCACHE_TIMEOUT, (""));
|
|
#ifdef NEVER
|
|
if (pParams->status == HT_REDIRECTION_DCACHE_TIMEOUT)
|
|
{
|
|
PSTR psz;
|
|
XX_Assert(psz = PszGetDCachePath(pParams->pDest->szActualURL, NULL, NULL), (""));
|
|
if (psz)
|
|
GTR_FREE(psz);
|
|
}
|
|
#endif /* NEVER */
|
|
#endif
|
|
}
|
|
|
|
|
|
/* Call recursively so that we can check the image cache, etc. Note that we
|
|
never set bPost after a redirection. */
|
|
/* TODO: Should we reset bNoDocCache if bPost is true, so that a form request
|
|
can lead us to a cached document? */
|
|
/* NOTE: since we force bPost false, we don't send szPostData to the call. */
|
|
|
|
x_DoLoadDocument(tw, pParams->pDest, pParams->bRecord, FALSE,
|
|
pParams->bNoDocCache, pParams->bNoImageCache,
|
|
FALSE, NULL, pParams->szReferer,
|
|
fLoadFromDCacheOK);
|
|
|
|
/* tw->bLoading won't get reset if we wind up with a cache hit. */
|
|
|
|
tw->bLoading = FALSE;
|
|
#ifdef FEATURE_IMG_THREADS
|
|
Image_UnblockMaster(tw);
|
|
#endif
|
|
WAIT_Pop(tw);
|
|
/* Note that this is the one instance in this function where
|
|
we return without destroying the destination. This is
|
|
because we passed it to x_DoLoadDocument, so that function
|
|
will free it. */
|
|
success = TRUE;
|
|
goto finish_up;
|
|
}
|
|
else if (pParams->status == HT_LOADED)
|
|
{
|
|
if (tw->w3doc && (pParams->prev_w3doc != tw->w3doc))
|
|
{
|
|
|
|
#ifndef FEATURE_IMG_THREADS
|
|
if (pParams->bNoImageCache)
|
|
{
|
|
Image_NukeImages(tw->w3doc, FALSE, /*fNukeDCache=*/TRUE);
|
|
FNukeBlobs(tw->w3doc, /*fNukeDCache=*/TRUE);
|
|
}
|
|
#endif
|
|
FORM_ShowAllChildWindows(tw->w3doc, SW_SHOW);
|
|
}
|
|
|
|
tw->bLoading = FALSE;
|
|
|
|
if (tw->win && tw->w3doc && (pParams->prev_w3doc != tw->w3doc))
|
|
{
|
|
TW_SetWindowName(tw);
|
|
#ifdef FEATURE_INTL
|
|
if (IsFECodePage(GETMIMECP(tw->w3doc)))
|
|
TW_ForceReformat(tw);
|
|
else
|
|
#endif
|
|
TW_Reformat(tw, NULL);
|
|
|
|
#ifdef FEATURE_TESTHOOK
|
|
TestDumpAnchors(tw->w3doc);
|
|
#endif
|
|
|
|
#ifdef FEATURE_IMG_THREADS
|
|
Image_UnblockMaster(tw);
|
|
if (TW_GETFLAG(tw,TW_LOADALLACTIVE))
|
|
{
|
|
Async_BlockThread(Async_GetCurrentThread());
|
|
TW_SETBLOCKED(tw,TW_LOADALLBLOCKED);
|
|
}
|
|
#else
|
|
/* Load in images for this document */
|
|
{
|
|
struct Params_Image_LoadAll *pil;
|
|
pil = GTR_MALLOC(sizeof(*pil));
|
|
pil->tw = tw;
|
|
pil->bLocalOnly = !gPrefs.bAutoLoadImages;
|
|
Async_DoCall(Image_LoadAll_Async, pil);
|
|
}
|
|
#endif
|
|
|
|
return STATE_HLD_GOTIMAGES;
|
|
}
|
|
else
|
|
{
|
|
/* Even though the load succeeded we didn't get a new document.
|
|
That means we're done. */
|
|
WAIT_Pop(tw);
|
|
#ifdef FEATURE_IMG_THREADS
|
|
Async_TerminateByWindow(pParams->twMaster);
|
|
#endif
|
|
Dest_DestroyDest(pParams->pDest);
|
|
success = FALSE;
|
|
|
|
goto finish_up;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
!bOK : the load failed
|
|
*/
|
|
#if defined(FEATURE_IAPI) && defined(WIN32)
|
|
/* If the request is from an IAPI application, do not show the error box */
|
|
|
|
if (tw->transID == 0)
|
|
#endif
|
|
{
|
|
TBar_LoadFailed( tw, pParams->pDest->szRequestedURL );
|
|
/*
|
|
We deliberately do not display the errDocLoadFailed if the interlude dialog
|
|
was cancelled.
|
|
*/
|
|
if (!(pParams->request->iFlags & HTREQ_USERCANCEL))
|
|
{
|
|
ERR_ReportError(tw, errDocLoadFailed, pParams->pDest->szRequestedURL, NULL);
|
|
}
|
|
}
|
|
|
|
tw->bLoading = FALSE;
|
|
#ifdef FEATURE_IMG_THREADS
|
|
Async_TerminateByWindow(pParams->twMaster);
|
|
#endif
|
|
TW_InvalidateDocument(tw);
|
|
|
|
WAIT_Pop(tw);
|
|
Dest_DestroyDest(pParams->pDest);
|
|
success = FALSE;
|
|
|
|
#ifdef HTTPS_ACCESS_TYPE
|
|
/*
|
|
We cancelled this load. So reinstall flags from previous page. We do this
|
|
since we may not have completed the last load.
|
|
*/
|
|
tw->dwSslPageFlagsWorking &= SSL_PAGE_LAST_SECURE_PROTOCOL;
|
|
if (tw->w3doc && IsURLSecure(tw->w3doc->szActualURL)){
|
|
tw->dwSslPageFlagsWorking |= SSL_PAGE_CURRENT_SECURE_PROTOCOL;
|
|
}
|
|
#endif
|
|
|
|
|
|
goto finish_up;
|
|
}
|
|
XX_Assert((0), ("Fell through case improperly!"));
|
|
|
|
case STATE_HLD_GOTIMAGES:
|
|
if (W3Doc_CheckForImageLoad(tw->w3doc))
|
|
{
|
|
TW_Reformat(tw, NULL);
|
|
/* TODO: Go back to correct place in document */
|
|
}
|
|
WAIT_Pop(tw);
|
|
Dest_DestroyDest(pParams->pDest);
|
|
success = TRUE;
|
|
|
|
goto finish_up;
|
|
|
|
case STATE_ABORT:
|
|
if (tw == NULL) goto done;
|
|
if (tw->w3doc)
|
|
{
|
|
if (W3Doc_CheckForImageLoad(tw->w3doc))
|
|
{
|
|
TW_Reformat(tw, NULL);
|
|
/* TODO: Go back to correct place in document ? */
|
|
}
|
|
FORM_ShowAllChildWindows(tw->w3doc, SW_SHOW);
|
|
}
|
|
WAIT_Pop(tw);
|
|
#ifdef FEATURE_IMG_THREADS
|
|
TW_CLEARBLOCKED(tw,TW_LOADALLBLOCKED);
|
|
Async_TerminateByWindow(pParams->twMaster);
|
|
#endif
|
|
if (pParams->szPostData)
|
|
{
|
|
GTR_FREE(pParams->szPostData);
|
|
}
|
|
Dest_DestroyDest(pParams->pDest);
|
|
tw->bLoading = FALSE;
|
|
success = TRUE;
|
|
goto finish_up;
|
|
|
|
finish_up:
|
|
|
|
#ifdef FEATURE_IMG_THREADS
|
|
TW_CLEARFLAG(tw,TW_LOADALLACTIVE);
|
|
#endif
|
|
if ( (success) && nState != STATE_ABORT && !TW_GETFLAG(tw,TW_LOADALLBLOCKED))
|
|
{
|
|
// check to see if we have a meta - refresh tag
|
|
// BUGBUG if we add meta tags in the future
|
|
// that have nothing to do with refresh this could
|
|
// be a problem... for now we only have one type.
|
|
|
|
if (tw->w3doc && tw->w3doc->pMeta && !tw->w3doc->pMeta->bInherit)
|
|
{
|
|
if ( tw->w3doc->pMeta->uiTimer )
|
|
KillTimer(tw->win, tw->w3doc->pMeta->uiTimer);
|
|
|
|
tw->w3doc->pMeta->uiTimer =
|
|
SetTimer(tw->win, TIMER_PULL, tw->w3doc->pMeta->iDelay*1000,
|
|
(TIMERPROC) ClientPullTimerProc );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if ( success )
|
|
{
|
|
if ( nState != STATE_ABORT ) // was this load a real success?
|
|
{
|
|
TBar_LoadSucceeded( tw );
|
|
}
|
|
SelectFirstControl(tw);
|
|
}
|
|
#ifdef FEATURE_TESTHOOK
|
|
TestSignalLoadDone(success);
|
|
#endif
|
|
|
|
|
|
#ifdef HTTPS_ACCESS_TYPE
|
|
/*main page is done loading, can play with dwSslPageFlagsWorking here*/
|
|
#endif
|
|
|
|
TW_UpdateTBar(tw);
|
|
#if defined(FEATURE_IAPI) && defined(WIN32)
|
|
/* Ignore return value. */
|
|
IssueURLResult_Async(tw, success);
|
|
#endif
|
|
|
|
if ((!success) || (tw->w3doc && tw->w3doc->bIsJustMessage))
|
|
{
|
|
if (tw->wintype == GHTML && (tw->w3doc == NULL || tw->w3doc->bIsJustMessage))
|
|
{
|
|
if (pParams->prev_w3doc)
|
|
{
|
|
RevertToPrevious(tw, pParams->prev_w3doc);
|
|
}
|
|
else if (!TW_ExistsModalChild(tw))
|
|
{
|
|
tw->bKillMe = TRUE;
|
|
(void) PostMessage(wg.hWndHidden, WM_DO_KILLME, 0, 0L);
|
|
}
|
|
else if ( tw->w3doc != NULL )
|
|
{
|
|
tw->bKillMe = TRUE;
|
|
}
|
|
}
|
|
} else {
|
|
// we're now finished downloading page. If there are any
|
|
// fetches to be done, send a message to our window saying
|
|
// we should do the fetch now
|
|
if (tw->iIndexForNextFetch >= 0) {
|
|
SendMessage(tw->hWndFrame,WM_DO_FETCH,0,0);
|
|
}
|
|
|
|
}
|
|
goto done;
|
|
}
|
|
XX_Assert((0), ("Function called with illegal state: %d", nState));
|
|
done:
|
|
#ifdef FEATURE_KEEPALIVE
|
|
if (--cbDownLoads == 0)
|
|
{
|
|
if (uiKATimer) KillTimer(NULL, uiKATimer);
|
|
uiKATimer = SetTimer(NULL, 0, KEEPALIVE_TIME, (TIMERPROC) KeepAliveTimerProc );
|
|
// If SetTimer failed, force all free sockets closed
|
|
Net_CloseUnusedKeepAlive(uiKATimer == 0);
|
|
}
|
|
#endif
|
|
return STATE_DONE;
|
|
}
|
|
|
|
static int nNumUnsuccesfulTimeouts=0;
|
|
#define MAX_NUM_UNSUCCESFUL_TIMEOUTS 20
|
|
|
|
VOID CALLBACK AutoPlaceHolderTimerHandler(
|
|
HWND hWnd,
|
|
UINT uMsg,
|
|
UINT idEvent,
|
|
DWORD dwTime)
|
|
{
|
|
struct Mwin *tw;
|
|
struct _www *w3doc;
|
|
RECT rUpdate;
|
|
|
|
tw = GetPrivateData(hWnd);
|
|
|
|
if((!tw )|| (tw != (struct Mwin *)(idEvent))){
|
|
ASSERT(0);
|
|
goto exitPoint; // This is an error !
|
|
}
|
|
|
|
w3doc = tw->w3doc;
|
|
|
|
// Has the HTML text been downloaded -- If not leave and wait for the timer to go off again.
|
|
if((tw->bLoading) || (w3doc == NULL)){
|
|
nNumUnsuccesfulTimeouts++;
|
|
if(nNumUnsuccesfulTimeouts > MAX_NUM_UNSUCCESFUL_TIMEOUTS)
|
|
goto exitPoint;
|
|
//Otherwise -- Just let the timer go off again
|
|
return;
|
|
}
|
|
|
|
|
|
// Are there any images left ?
|
|
if (!(w3doc->frame.pLineInfo && w3doc->frame.nLineCount && w3doc->frame.nLastFormattedLine >= 0 &&w3doc->frame.nLastLineButForImg >= 0))
|
|
goto exitPoint;
|
|
|
|
if(tw->w3doc->bIsShowPlaceholders)
|
|
goto exitPoint;
|
|
|
|
tw->w3doc->bIsShowPlaceholders = TRUE;
|
|
if(w3doc->frame.nLineCount > w3doc->frame.nLastLineButForImg){ // Paranoia
|
|
rUpdate.top = w3doc->frame.pLineInfo[w3doc->frame.nLastLineButForImg].nYStart - tw->offt;
|
|
}else{
|
|
rUpdate.top = 0;
|
|
}
|
|
rUpdate.bottom = w3doc->frame.rWindow.bottom;
|
|
rUpdate.left = w3doc->frame.rWindow.left;
|
|
rUpdate.right = w3doc->frame.rWindow.right;
|
|
InvalidateRect(tw->win, &rUpdate, TRUE);
|
|
(void) UpdateWindow(tw->win);
|
|
|
|
|
|
exitPoint:
|
|
nNumUnsuccesfulTimeouts = 0;
|
|
KillTimer(hWnd, idEvent);
|
|
return;
|
|
}
|
|
|
|
static void x_DoLoadDocument(struct Mwin *tw, struct DestInfo *pDest,
|
|
BOOL bRecord, BOOL bPost, BOOL bNoDocCache,
|
|
BOOL bNoImageCache, BOOL bAuthFailCacheOK,
|
|
CONST char * szPostData, CONST char *szReferer,
|
|
BOOL fLoadFromDCacheOK)
|
|
{
|
|
int ndx;
|
|
struct _www *w3doc;
|
|
BOOL bDestroyDest;
|
|
char *szMyReferer;
|
|
|
|
|
|
bDestroyDest = TRUE;
|
|
|
|
/*
|
|
We make our own copy of the referer, since it could be freed indirectly
|
|
by the cache removal below.
|
|
*/
|
|
if (szReferer)
|
|
{
|
|
szMyReferer = GTR_strdup(szReferer);
|
|
}
|
|
else
|
|
{
|
|
szMyReferer = NULL;
|
|
}
|
|
|
|
w3doc = NULL;
|
|
ndx = Hash_Find(&tw->doc_cache, pDest->szActualURL, NULL, (void **)&w3doc);
|
|
if ( ndx >= 0
|
|
&& ( bNoDocCache
|
|
|| (w3doc->flags & W3DOC_FLAG_NO_MEM_CACHE_ON_PAGE)
|
|
|| !w3doc->bIsComplete
|
|
|| (w3doc->bAuthFailCache && !bAuthFailCacheOK)
|
|
|| FFreshnessCheckNeeded(pDest->szActualURL)
|
|
|| FExpired(w3doc->dctExpires)
|
|
|| LocalPageLastWriteTimeChanged(tw, w3doc, FALSE)
|
|
)
|
|
)
|
|
{
|
|
/* Note: the only time (for now) that FFreshnessCheckNeeded could
|
|
* return true is
|
|
* a) user started out with UpdateFrequency=NEVER
|
|
* b) Loaded a doc from the dcache and moved to another page
|
|
* c) Changed UpdateFrequency to ONCE_PER_SESSION
|
|
* d) Navigated back to this doc.
|
|
*/
|
|
/* Delete this item from the cache */
|
|
if (tw->w3doc == w3doc)
|
|
W3Doc_DisconnectFromWindow(w3doc, tw);
|
|
|
|
if (bNoImageCache)
|
|
{
|
|
Image_NukeImages(w3doc, TRUE, /*fNukeDCache=*/TRUE);
|
|
FNukeBlobs(w3doc, /*fNukeDCache=*/TRUE);
|
|
}
|
|
|
|
W3Doc_FreeContents(tw, w3doc);
|
|
GTR_FREE(w3doc);
|
|
|
|
/*
|
|
We need to re-do the search here to make sure that the document is still
|
|
in the cache. It is possible that it was removed in the call to
|
|
W3Doc_DisconnectFromWindow().
|
|
*/
|
|
ndx = Hash_Find(&tw->doc_cache, pDest->szActualURL, NULL, (void **)&w3doc);
|
|
if (ndx >= 0)
|
|
{
|
|
Hash_DeleteIndexedEntry(&tw->doc_cache, ndx);
|
|
}
|
|
w3doc = NULL;
|
|
}
|
|
|
|
if (bNoDocCache && gPrefs.bEnableDiskCache)
|
|
FlushDCacheEntry(pDest->szActualURL);
|
|
|
|
/* See if this is the currently loaded document */
|
|
if (w3doc)
|
|
{
|
|
if (tw->w3doc == w3doc)
|
|
{
|
|
x_HandleCurrentDocument(tw, pDest, bNoImageCache);
|
|
}
|
|
else
|
|
{
|
|
x_HandleCacheHit(tw, pDest, ndx, bNoImageCache, bRecord);
|
|
}
|
|
if (szPostData)
|
|
{
|
|
GTR_FREE((char *) szPostData);
|
|
}
|
|
SelectFirstControl(tw);
|
|
}
|
|
#ifdef FEATURE_IMAGE_VIEWER
|
|
#ifndef FEATURE_IMG_INLINE
|
|
else if (!bNoDocCache && (Viewer_ShowCachedFile(pDest->szActualURL)))
|
|
{
|
|
/* We used the existing copy on disk */
|
|
if (szPostData)
|
|
{
|
|
GTR_FREE((char *) szPostData);
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
#ifdef FEATURE_SOUND_PLAYER
|
|
else if (!bNoDocCache && (SoundPlayer_ShowCachedFile(pDest->szActualURL)))
|
|
{
|
|
/* We used the existing copy on disk */
|
|
if (szPostData)
|
|
{
|
|
GTR_FREE((char *) szPostData);
|
|
}
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
/*
|
|
** This is the situation where we actually have to load a document, either because
|
|
** it's not in the cache or because we are forcing a reload.
|
|
*/
|
|
struct Params_HandleLoadDocument *pHLDParams;
|
|
|
|
pHLDParams = GTR_MALLOC(sizeof(*pHLDParams));
|
|
pHLDParams->pDest = pDest;
|
|
pHLDParams->bRecord = bRecord;
|
|
/*the bPost field has been overloaded, no longer a bool*/
|
|
pHLDParams->bPost = bPost;
|
|
pHLDParams->bNoDocCache = bNoDocCache;
|
|
pHLDParams->bNoImageCache = bNoImageCache;
|
|
pHLDParams->szPostData = (char *) szPostData;
|
|
pHLDParams->szReferer = szMyReferer;
|
|
pHLDParams->fLoadFromDCacheOK = fLoadFromDCacheOK;
|
|
ASSERT(tw != 0);
|
|
|
|
// A way of disabling the timer by issuing a .reg file as a patch
|
|
if((tw) && (gPrefs.nPlaceHolderTimeOut < PLACEHOLDER_TIMEOUT_MAXIMUM)){
|
|
nNumUnsuccesfulTimeouts = 0;
|
|
SetTimer(tw->win, (UINT)(tw), gPrefs.nPlaceHolderTimeOut, AutoPlaceHolderTimerHandler);
|
|
}
|
|
|
|
Async_StartThread(x_HandleLoadDocument_Async, pHLDParams, tw);
|
|
|
|
/* The load function will destroy the destination for us when it
|
|
completes. */
|
|
bDestroyDest = FALSE;
|
|
}
|
|
|
|
if ( bDestroyDest ) {
|
|
Dest_DestroyDest( pDest );
|
|
TBar_LoadSucceeded( tw );
|
|
|
|
// check to see if we have a meta - refresh tag
|
|
// BUGBUG if we add meta tags in the future
|
|
// that have nothing to do with refresh this could
|
|
// be a problem... for now we only have one type.
|
|
|
|
if (tw->w3doc && tw->w3doc->pMeta && !tw->w3doc->pMeta->bInherit)
|
|
{
|
|
if ( tw->w3doc->pMeta->uiTimer )
|
|
KillTimer(tw->win, tw->w3doc->pMeta->uiTimer);
|
|
|
|
tw->w3doc->pMeta->uiTimer =
|
|
SetTimer(tw->win, TIMER_PULL, tw->w3doc->pMeta->iDelay*1000,
|
|
(TIMERPROC) ClientPullTimerProc );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* This function will free szPostData when done */
|
|
int TW_LoadDocument(PMWIN tw, PCSTR url, DWORD dwFlags, PSTR szPostData,
|
|
PCSTR szReferer)
|
|
{
|
|
char buf[MAX_URL_STRING + 32 + 1];
|
|
struct DestInfo *pDest;
|
|
|
|
|
|
bTBar_URLComboProtected = FALSE;
|
|
|
|
ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_TW_LD_FLAGS));
|
|
|
|
if (!url || !*url)
|
|
{
|
|
ERR_ReportError(tw, errNoURL, NULL, NULL);
|
|
if (szPostData)
|
|
{
|
|
GTR_FREE(szPostData);
|
|
}
|
|
TW_UpdateTBar(tw);
|
|
return -1;
|
|
}
|
|
XX_Assert((strlen(url) <= MAX_URL_STRING), ("TW_LoadDocument received a URL longer than %d characters. Actual length was %d\n", MAX_URL_STRING, strlen(url)));
|
|
|
|
/* If this is a relative anchor, make a full URL */
|
|
if (*url == '#')
|
|
{
|
|
if (!tw->w3doc)
|
|
{
|
|
/* Shouldn't happen */
|
|
ERR_ReportError(tw, errNoURL, NULL, NULL);
|
|
if (szPostData)
|
|
{
|
|
GTR_FREE(szPostData);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
GTR_strncpy(buf, tw->w3doc->szActualURL, MAX_URL_STRING);
|
|
strcat(buf, url);
|
|
}
|
|
else // Put URL in cannonical form - ie, lower case access and hostname
|
|
{
|
|
char *pURL = HTParse(url, "", PARSE_ALL);
|
|
|
|
if (!pURL) return -1;
|
|
GTR_strncpy(buf, pURL, MAX_URL_STRING);
|
|
GTR_FREE(pURL);
|
|
}
|
|
|
|
#ifdef HTTPS_ACCESS_TYPE
|
|
/*base warnings for this page*/
|
|
tw->dwSslPageFlagsWorking &= SSL_PAGE_LAST_SECURE_PROTOCOL;
|
|
if (buf && IsURLSecure(buf)){
|
|
tw->dwSslPageFlagsWorking |= SSL_PAGE_CURRENT_SECURE_PROTOCOL;
|
|
}
|
|
if (NULL == tw->w3doc)
|
|
{
|
|
BOOL at_home;
|
|
|
|
/*first page, and subsequent ones of same type should never get warnings*/
|
|
at_home = strcmp( gPrefs.szHomeURL, buf ) == 0;
|
|
if (at_home) tw->dwSslPageFlagsWorking |= SSL_PAGE_LAST_SPECIAL_PAGE;
|
|
}
|
|
|
|
tw->nCertWorking = 0;
|
|
tw->pCertWorking = NULL;
|
|
#endif
|
|
|
|
if ((!tw->bDDECandidate) && tw->bSilent && Async_GetThreadForWindow(tw) != 0)
|
|
{
|
|
if (resourceMessageBox(tw->hWndFrame, RES_STRING_SILENT, RES_STRING_SILENT_TITLE, MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION) != IDYES)
|
|
{
|
|
if (resourceMessageBox(tw->hWndFrame, RES_STRING_OPENNEW, RES_STRING_SILENT_TITLE, MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION) != IDYES)
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwNWDocFlags = 0;
|
|
int content_length_hint;
|
|
|
|
content_length_hint = (tw->request ? tw->request->content_length_hint : 0);
|
|
if (IS_FLAG_SET(dwFlags, TW_LD_FL_NO_DOC_CACHE))
|
|
SET_FLAG(dwNWDocFlags, GTR_NW_FL_NO_DOC_CACHE);
|
|
|
|
if (IS_FLAG_SET(dwFlags, TW_LD_FL_NO_IMAGE_CACHE))
|
|
SET_FLAG(dwNWDocFlags, GTR_NW_FL_NO_IMAGE_CACHE);
|
|
return GTR_NewWindow((PSTR)url, szReferer, content_length_hint, 0, dwNWDocFlags, szPostData, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Terminate any other threads currently running on this window. */
|
|
Async_TerminateByWindow(tw);
|
|
|
|
tw->bSilent = FALSE;
|
|
tw->bDDECandidate = FALSE;
|
|
tw->bKillMe = FALSE;
|
|
|
|
/* If the URL is of the form "http://system", append a slash at the end */
|
|
x_EnforceHostSlash(buf);
|
|
|
|
pDest = Dest_CreateDest(buf);
|
|
if (pDest)
|
|
#ifdef FEATURE_INTL
|
|
// Before load document, we initialize status of FECHRCNV.DLL.
|
|
// BUGBUG:I have to revisit this to make sure every case is covered here.
|
|
// _BUGBUG Perf: should load fechrcnv.dll on demand. (JCordell)
|
|
{
|
|
|
|
|
|
if ((tw->request != NULL && tw->request->iMimeCharSet != -1 && aMimeCharSet[tw->request->iMimeCharSet].iChrCnv)
|
|
|| (tw != NULL && aMimeCharSet[tw->iMimeCharSet].iChrCnv))
|
|
FCC_Init();
|
|
#endif
|
|
x_DoLoadDocument(tw, pDest, IS_FLAG_SET(dwFlags, TW_LD_FL_RECORD),
|
|
/*we overload the bPost field so we can get to the
|
|
TW_LD_FL_POST and TW_LD_FL_SENDING_FROM_FORM info
|
|
down the road
|
|
*/
|
|
dwFlags&(TW_LD_FL_SENDING_FROM_FORM|TW_LD_FL_POST|TW_LD_FL_REALLY_SENDING_FROM_FORM),//IS_FLAG_SET(dwFlags, TW_LD_FL_POST),
|
|
IS_FLAG_SET(dwFlags, TW_LD_FL_NO_DOC_CACHE),
|
|
IS_FLAG_SET(dwFlags, TW_LD_FL_NO_IMAGE_CACHE),
|
|
IS_FLAG_SET(dwFlags, TW_LD_FL_AUTH_FAIL_CACHE_OK),
|
|
szPostData, szReferer, /*fLoadFromDCacheOK=*/FALSE);
|
|
#ifdef FEATURE_INTL
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
if (szPostData)
|
|
GTR_FREE(szPostData);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
struct Params_Download {
|
|
char *url; /* Freed by function */
|
|
char *szReferer; /* Freed by function */
|
|
HTFormat output_format; // optional output format to force
|
|
|
|
/* Used internally */
|
|
HTRequest *request;
|
|
struct DestInfo *pDest;
|
|
int status;
|
|
};
|
|
static int x_DownLoad_Async(struct Mwin *tw, int nState, void **ppInfo)
|
|
{
|
|
struct Params_Download *pParams;
|
|
char buf[MAX_URL_STRING + 32 + 1];
|
|
struct Params_LoadAsync *pla;
|
|
static BOOL success;
|
|
|
|
pParams = *ppInfo;
|
|
|
|
switch (nState)
|
|
{
|
|
case STATE_INIT:
|
|
if (tw == NULL) return STATE_DONE;
|
|
pParams->pDest = Dest_CreateDest(pParams->url);
|
|
if (!pParams->pDest)
|
|
{
|
|
GTR_FREE(pParams->url);
|
|
if (pParams->szReferer)
|
|
GTR_FREE(pParams->szReferer);
|
|
success = FALSE;
|
|
goto finish_up;
|
|
}
|
|
|
|
/* Set up the request structure */
|
|
pParams->request = HTRequest_new();
|
|
HTFormatInit(pParams->request->conversions);
|
|
// if caller specified an output format to force, use it,
|
|
// otherwise set to WWW_UNKNOWN
|
|
if (pParams->output_format)
|
|
pParams->request->output_format = pParams->output_format;
|
|
else
|
|
pParams->request->output_format = WWW_UNKNOWN;
|
|
pParams->request->referer = pParams->szReferer;
|
|
pParams->request->destination = pParams->pDest;
|
|
pParams->request->iFlags |= HTREQ_BINARY;
|
|
|
|
GTR_formatmsg(RES_STRING_LOADDOC3,buf,sizeof(buf));
|
|
GTR_strncat(buf, pParams->pDest->szActualURL, MAX_URL_STRING);
|
|
WAIT_Push(tw, waitNoInteract, buf);
|
|
|
|
pla = GTR_MALLOC(sizeof(*pla));
|
|
pla->request = pParams->request;
|
|
pla->pStatus = &pParams->status;
|
|
pla->fLoadFromDCacheOK = FALSE;
|
|
Async_DoCall(HTLoadDocument_Async, pla);
|
|
return STATE_OTHER;
|
|
|
|
case STATE_OTHER:
|
|
WAIT_Pop(tw);
|
|
if (!pParams->status && !(pParams->request->iFlags & HTREQ_USERCANCEL))
|
|
{
|
|
TBar_LoadFailed( tw, pParams->pDest->szRequestedURL );
|
|
ERR_ReportError(tw, errDocLoadFailed, pParams->url, NULL);
|
|
}
|
|
Dest_DestroyDest(pParams->pDest);
|
|
HTRequest_delete(pParams->request);
|
|
GTR_FREE(pParams->url);
|
|
if (pParams->szReferer)
|
|
{
|
|
GTR_FREE(pParams->szReferer);
|
|
}
|
|
success = TRUE;
|
|
goto finish_up;
|
|
|
|
case STATE_ABORT:
|
|
if (tw == NULL) return STATE_DONE;
|
|
WAIT_Pop(tw);
|
|
Dest_DestroyDest(pParams->pDest);
|
|
HTRequest_delete(pParams->request);
|
|
GTR_FREE(pParams->url);
|
|
if (pParams->szReferer)
|
|
{
|
|
GTR_FREE(pParams->szReferer);
|
|
}
|
|
success = TRUE;
|
|
goto finish_up;
|
|
|
|
finish_up:
|
|
TW_UpdateTBar(tw);
|
|
#if defined(FEATURE_IAPI) && defined(WIN32)
|
|
/* Ignore return value. */
|
|
IssueURLResult_Async(tw, success);
|
|
#endif
|
|
return STATE_DONE;
|
|
}
|
|
XX_Assert((0), ("Function called with illegal state: %d", nState));
|
|
return STATE_DONE;
|
|
}
|
|
|
|
void GTR_DownLoad(struct Mwin *tw, char *url, CONST char *szReferer,
|
|
HTFormat output_format)
|
|
{
|
|
char buf[MAX_URL_STRING + 32 + 1];
|
|
struct Params_Download *pdl;
|
|
|
|
if (!url || !*url)
|
|
{
|
|
ERR_ReportError(tw, errNoURL, NULL, NULL);
|
|
TW_UpdateTBar(tw);
|
|
return;
|
|
}
|
|
|
|
tw->bSilent = TRUE;
|
|
tw->bDDECandidate = FALSE;
|
|
|
|
// Put URL in cannonical form - ie, lower case access and hostname
|
|
{
|
|
char *pURL = HTParse(url, "", PARSE_ALL);
|
|
|
|
if (!pURL) return;
|
|
GTR_strncpy(buf, pURL, MAX_URL_STRING);
|
|
GTR_FREE(pURL);
|
|
}
|
|
/* If the URL is of the form "http://system", append a slash at the end */
|
|
x_EnforceHostSlash(buf);
|
|
|
|
pdl = GTR_MALLOC(sizeof(*pdl));
|
|
|
|
/* Make copies of the URL and referer that we know won't be freed */
|
|
pdl->url = GTR_strdup(buf);
|
|
if (szReferer)
|
|
{
|
|
pdl->szReferer = GTR_strdup(szReferer);
|
|
}
|
|
else
|
|
{
|
|
pdl->szReferer = NULL;
|
|
}
|
|
|
|
pdl->output_format = output_format;
|
|
|
|
Async_StartThread(x_DownLoad_Async, pdl, tw);
|
|
}
|