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.
 
 
 
 
 
 

545 lines
14 KiB

/*
Enhanced NCSA Mosaic from Spyglass
"Guitar"
Copyright 1994 Spyglass, Inc.
All Rights Reserved
Author(s):
Eric W. Sink [email protected]
Jim Seidman [email protected]
*/
#include "all.h"
#include "safestrm.h"
#include "decoder.h"
#include "stdio.h"
// FEATURE_IMG_THREADS
/* Stream Object
** ------------
*/
struct _HTStream
{
CONST HTStreamClass *isa;
HTRequest *request;
#ifdef FEATURE_JPEG
enum {TYPE_GIF, TYPE_JPEG} type;
#endif
PDECODER pDecoder;
PSAFESTREAM pSSInput;
struct Mwin *tw;
#ifdef XX_DEBUG
int count;
#endif
FILE *fpDc;
char *pszDcFile;
HTFormat format_inDc;
BOOL fDCache;
PIMGCBINFO pImgCBInfo;
};
/* Image streams
*/
PRIVATE enum GuitErrs imgComplete(PDECODER pdecoder,void *isa);
PRIVATE enum GuitErrs imgAbort(PDECODER pdecoder);
PRIVATE enum GuitErrs imgGifComplete(PDECODER pdecoder);
#ifdef FEATURE_JPEG
PRIVATE enum GuitErrs imgJPEGComplete(PDECODER pdecoder);
#endif
enum GuitErrs imgGifDecode(PDECODER pdecoder);
#ifdef FEATURE_JPEG
enum GuitErrs imgJPEGDecode(PDECODER pdecoder);
#endif
PRIVATE int HTIMAGE_init(struct Mwin *tw, int nState, void **ppInfo);
PRIVATE void HTIMAGE_write_dcache(HTStream * me, CONST char *s, int cb);
PRIVATE void HTIMAGE_free(HTStream * me, DCACHETIME dctExpires, DCACHETIME dctLastModif);
PRIVATE void HTIMAGE_abort(HTStream * me, HTError e);
PRIVATE BOOL HTIMAGE_put_character(HTStream * me, char c);
PRIVATE BOOL HTIMAGE_put_string(HTStream * me, CONST char *s);
PRIVATE BOOL HTIMAGE_write(HTStream * me, CONST char *s, int l, BOOL fDCache);
PRIVATE HTStreamClass HTGIFClass =
{
"GIF",
NULL,
NULL,
HTIMAGE_init,
HTIMAGE_free,
HTIMAGE_abort,
HTIMAGE_put_character, HTIMAGE_put_string,
HTIMAGE_write,
NULL,
HTIMAGE_write_dcache
};
#ifdef FEATURE_JPEG
PRIVATE HTStreamClass HTJPEGClass =
{
"JPEG",
NULL,
NULL,
HTIMAGE_init,
HTIMAGE_free,
HTIMAGE_abort,
HTIMAGE_put_character, HTIMAGE_put_string,
HTIMAGE_write,
NULL,
HTIMAGE_write_dcache
};
#endif
PRIVATE BOOL HTIMAGE_put_character(HTStream * me, char c)
{
#ifdef XX_DEBUG
me->count++;
#endif
if (me->pImgCBInfo == NULL)
return TRUE;
else
return bSS_Write(me->pSSInput,(unsigned char *)&c,1);
}
PRIVATE BOOL HTIMAGE_put_string(HTStream * me, CONST char *s)
{
/* This never gets called */
return FALSE;
}
PRIVATE BOOL HTIMAGE_write(HTStream * me, CONST char *s, int l, BOOL fDCache)
{
if (fDCache && me->isa->write_dcache)
(me->isa->write_dcache)(me, s, l);
#ifdef XX_DEBUG
me->count += l;
#endif
if (me->pImgCBInfo == NULL)
return TRUE;
else
return bSS_Write(me->pSSInput,(unsigned char *)s,l);
}
PRIVATE void HTIMAGE_free(HTStream * me, DCACHETIME dctExpires, DCACHETIME dctLastModif)
{
#ifdef XX_DEBUG
#ifdef FEATURE_JPEG
if (me->isa != &HTGIFClass)
XX_DMsg(DBG_IMAGE, ("JPEG: received %d bytes\n", me->count));
else
#endif
XX_DMsg(DBG_IMAGE, ("GIF: received %d bytes\n", me->count));
#endif /* XX_DEBUG */
if (me->fDCache)
UpdateStreamDCache(me, dctExpires, dctLastModif, /*fAbort=*/FALSE, me->tw);
if (me->pImgCBInfo != NULL)
{
SS_EOF(me->pSSInput,cbSS_ErrorCode(me->pSSInput));
me->pImgCBInfo->ppRef = NULL;
}
GTR_FREE(me);
}
PRIVATE void HTIMAGE_abort(HTStream * me, HTError e)
{
DCACHETIME dct={0,0};
#ifdef XX_DEBUG
XX_DMsg(DBG_IMAGE, ("Aborting transfer of %s, e = %d\n", me->request->destination->szRequestedURL, e));
#endif
if (me->fDCache)
UpdateStreamDCache(me, dct, dct, /*fAbort=*/TRUE, me->tw);
// Fix me: does it matter what error we return here?
DC_SetCompletion(me->pDecoder,NULL);
if (me->pImgCBInfo != NULL)
{
SS_EOF(me->pSSInput,(e != HTERROR_CANCELLED) ? errUnknown:errUserAbort);
me->pImgCBInfo->ppRef = NULL;
}
Image_SetImageData(me->request->destination->szRequestedURL, NULL, NULL, 0, (e != HTERROR_CANCELLED) ? IMG_ERROR : IMG_NOTLOADED, NULL, -1, 0, 0);
GTR_FREE(me);
}
/* Image creation
*/
PUBLIC HTStream *Image_GIF(struct Mwin *tw, HTRequest * request, void *param, HTFormat input_format, HTFormat output_format, HTStream * output_stream)
{
HTStream *me = NULL;
PIMGCBINFO pImgCBInfo = NULL;
PDECODER pDecoder = Image_GetDecoder(request->destination->szRequestedURL);
char *srcURL = NULL;
char *actualURL = NULL;
#ifdef XX_DEBUG
XX_Assert((pDecoder != NULL), ("pDecoder NULL in HTGIF\n"));
#endif
if (pDecoder == NULL ||
cbDC_GetStatus(pDecoder) != DC_Reserved ||
request->cbRequestID != cbDC_GetRequestID(pDecoder))
{
#ifdef XX_DEBUG
XX_DMsg(DBG_IMAGE, ("decoder not reserved for %s\n!", request->destination->szRequestedURL));
#endif
goto errExit1;
}
#ifdef XX_DEBUG
XX_DMsg(DBG_IMAGE, ("Creating new GIF stream for %s\n", request->destination->szRequestedURL));
#endif
me = (HTStream *) GTR_MALLOC(sizeof(*me));
pImgCBInfo = GTR_CALLOC(1,sizeof(IMGCBINFO));
srcURL = GTR_strdup(request->destination->szRequestedURL);
actualURL = GTR_strdup(request->destination->szActualURL);
HTLoadStatusStrings(&HTGIFClass,RES_STRING_HTGIF_NO,RES_STRING_HTGIF_YES);
if ((!me) || (!pImgCBInfo) || (!srcURL) || (!actualURL)) goto errExit;
pImgCBInfo->ppRef = &me->pImgCBInfo;
pImgCBInfo->srcURL = srcURL;
pImgCBInfo->actualURL = actualURL;
me->pImgCBInfo = pImgCBInfo;
me->isa = &HTGIFClass;
me->request = request;
me->pDecoder = pDecoder;
#ifdef XX_DEBUG
me->count = 0;
#endif
me->tw = tw;
me->pSSInput = pDC_GetStream(me->pDecoder);
SS_Reset(me->pSSInput);
DC_SetCompletion(me->pDecoder,imgGifComplete);
DC_SetAbort(me->pDecoder,imgAbort);
DC_SetOutput(me->pDecoder,pImgCBInfo);
DC_SetImgUpdate(me->pDecoder,GifImgUpdateRect);
DC_SetUpdate(me->pDecoder,GifUpdateRect);
DC_SetStretch(me->pDecoder,GifStretchDIBits);
if (cbDC_Start(me->pDecoder,imgGifDecode) != errNoError) goto errExit;
return me;
errExit:
Image_SetImageData(me->request->destination->szRequestedURL, NULL, NULL, 0, IMG_NOTLOADED, NULL, -1, 0, 0);
if (me) GTR_FREE(me);
if (pImgCBInfo) GTR_FREE(pImgCBInfo);
if (srcURL) GTR_FREE(srcURL);
if (actualURL) GTR_FREE(actualURL);
DC_SetOutput(pDecoder,NULL);
errExit1:
return NULL;
}
#ifdef FEATURE_JPEG
PUBLIC HTStream *Image_JPEG(struct Mwin *tw, HTRequest * request, void *param, HTFormat input_format, HTFormat output_format, HTStream * output_stream)
{
HTStream *me = NULL;
PIMGCBINFO pImgCBInfo = NULL;
PDECODER pDecoder = Image_GetDecoder(request->destination->szRequestedURL);
char *srcURL = NULL;
char *actualURL = NULL;
#ifdef XX_DEBUG
XX_Assert((pDecoder != NULL), ("pDecoder NULL in HTGIF\n"));
#endif
if (pDecoder == NULL ||
cbDC_GetStatus(pDecoder) != DC_Reserved ||
request->cbRequestID != cbDC_GetRequestID(pDecoder))
{
#ifdef XX_DEBUG
XX_DMsg(DBG_IMAGE, ("decoder not reserved for %s\n!", request->destination->szRequestedURL));
#endif
goto errExit1;
}
me = (HTStream *) GTR_MALLOC(sizeof(*me));
pImgCBInfo = GTR_CALLOC(1,sizeof(IMGCBINFO));
srcURL = GTR_strdup(request->destination->szRequestedURL);
actualURL = GTR_strdup(request->destination->szActualURL);
XX_DMsg(DBG_IMAGE, ("Creating new GIF stream for %s\n", request->destination->szRequestedURL));
HTLoadStatusStrings(&HTJPEGClass,RES_STRING_HTGIF_NO,RES_STRING_HTGIF_YES);
if ((!me) || (!pImgCBInfo) || (!srcURL) || (!actualURL)) goto errExit;
pImgCBInfo->ppRef = &me->pImgCBInfo;
pImgCBInfo->srcURL = srcURL;
pImgCBInfo->actualURL = actualURL;
me->pImgCBInfo = pImgCBInfo;
me->isa = &HTJPEGClass;
me->request = request;
#ifdef XX_DEBUG
me->count = 0;
#endif
me->tw = tw;
me->pDecoder = pDecoder;
me->pSSInput = pDC_GetStream(me->pDecoder);
SS_Reset(me->pSSInput);
DC_SetCompletion(me->pDecoder,imgJPEGComplete);
DC_SetAbort(me->pDecoder,imgAbort);
DC_SetOutput(me->pDecoder,pImgCBInfo);
DC_SetImgUpdate(me->pDecoder,GifImgUpdateRect);
DC_SetUpdate(me->pDecoder,GifUpdateRect);
DC_SetStretch(me->pDecoder,JPEGStretchDIBits);
if (cbDC_Start(me->pDecoder,imgJPEGDecode) != errNoError) goto errExit;
return me;
errExit:
Image_SetImageData(me->request->destination->szRequestedURL, NULL, NULL, 0, IMG_NOTLOADED, NULL, -1, 0, 0);
if (me) GTR_FREE(me);
if (pImgCBInfo) GTR_FREE(pImgCBInfo);
if (srcURL) GTR_FREE(srcURL);
if (actualURL) GTR_FREE(actualURL);
DC_SetOutput(pDecoder,NULL);
errExit1:
return NULL;
}
#endif
PRIVATE enum GuitErrs imgComplete(PDECODER pdecoder,const void *isa)
{
HPALETTE hPalette = NULL;
LOGPALETTE *lp;
PIMGCBINFO pImgCBInfo = pDC_GetOutput(pdecoder);
unsigned char *data = pImgCBInfo->data;
enum GuitErrs errorCode = cbDC_GetResult(pdecoder);
unsigned long cbCheckSum;
unsigned long cbBytesRead;
PSAFESTREAM pSStream;
pSStream = pDC_GetStream(pdecoder);
cbCheckSum = cbSS_CheckSum(pSStream);
cbBytesRead = cbSS_BytesRead(pSStream);
#ifdef XX_DEBUG
#ifdef FEATURE_JPEG
if (isa != &HTGIFClass)
XX_DMsg(DBG_IMAGE, ("JPEG: received %d bytes read sum = %d\n", cbBytesRead, cbCheckSum));
else
#endif
XX_DMsg(DBG_IMAGE, ("GIF: received %d bytes read sum = %d\n", cbBytesRead, cbCheckSum));
#endif /* XX_DEBUG */
SS_Reset(pSStream);
if (data)
{
if (isa == &HTGIFClass)
{
int i;
hPalette = pImgCBInfo->hPalette;
if (hPalette == NULL)
{
lp = (LOGPALETTE *) GTR_MALLOC(sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256);
if (lp == NULL)
{
errorCode = errOUTOFMEM;
GTR_FREE(data);
data = NULL;
goto exitPoint;
}
lp->palVersion = 0x300;
lp->palNumEntries = 256;
for (i = 0; i < 256; i++)
{
lp->palPalEntry[i] = pImgCBInfo->colors[i];
}
hPalette = CreatePalette(lp);
GTR_FREE(lp);
}
if (pImgCBInfo->ditherRow)
{
if (pImgCBInfo->ditherRow < pImgCBInfo->height && wg.eColorMode == 8)
{
x_DitherRelative(pImgCBInfo->data, pImgCBInfo->colors, pImgCBInfo->width, pImgCBInfo->height, pImgCBInfo->transparent, pImgCBInfo->ditherData, pImgCBInfo->ditherRow, pImgCBInfo->height-1);
pImgCBInfo->ditherRow = pImgCBInfo->height;
}
pImgCBInfo->flags |= IMG_PREMATCHED;
}
}
Image_SetImageData(pImgCBInfo->srcURL,
pImgCBInfo->actualURL,
data,
pImgCBInfo->width,
pImgCBInfo->height,
hPalette,
pImgCBInfo->transparent,
pImgCBInfo->flags,
cbCheckSum);
}
exitPoint:
if (data == NULL)
{
Image_SetImageData(pImgCBInfo->srcURL, NULL, NULL, 0, IMG_ERROR, NULL, -1, 0, 0);
}
if (pImgCBInfo->ditherData)
GTR_FREE(pImgCBInfo->ditherData);
if (pImgCBInfo->pbmi)
GTR_FREE(pImgCBInfo->pbmi);
if (pImgCBInfo->pRow)
GTR_FREE(pImgCBInfo->pRow);
if (pImgCBInfo->ppRef)
*pImgCBInfo->ppRef = NULL;
if (pImgCBInfo->srcURL)
GTR_FREE(pImgCBInfo->srcURL);
if (pImgCBInfo->actualURL)
GTR_FREE(pImgCBInfo->actualURL);
GTR_FREE(pImgCBInfo);
DC_SetOutput(pdecoder,NULL);
return errorCode;
}
PRIVATE enum GuitErrs imgAbort(PDECODER pdecoder)
{
PIMGCBINFO pImgCBInfo = pDC_GetOutput(pdecoder);
#ifdef XX_DEBUG
XX_DMsg(DBG_IMAGE, ("img abort of %d\n",pdecoder->cbRequestID));
#endif
SS_Reset(pDC_GetStream(pdecoder));
if (pImgCBInfo->data)
GTR_FREE(pImgCBInfo->data);
if (pImgCBInfo->ditherData)
GTR_FREE(pImgCBInfo->ditherData);
if (pImgCBInfo->pbmi)
GTR_FREE(pImgCBInfo->pbmi);
if (pImgCBInfo->pRow)
GTR_FREE(pImgCBInfo->pRow);
if (pImgCBInfo->hPalette)
DeleteObject(pImgCBInfo->hPalette);
if (pImgCBInfo->srcURL)
GTR_FREE(pImgCBInfo->srcURL);
if (pImgCBInfo->actualURL)
GTR_FREE(pImgCBInfo->actualURL);
if (pImgCBInfo->ppRef) *pImgCBInfo->ppRef = NULL;
GTR_FREE(pImgCBInfo);
return errNoError;
}
PRIVATE enum GuitErrs imgGifComplete(PDECODER pdecoder)
{
return imgComplete(pdecoder,&HTGIFClass);
}
#ifdef FEATURE_JPEG
PRIVATE enum GuitErrs imgJPEGComplete(PDECODER pdecoder)
{
return imgComplete(pdecoder,&HTJPEGClass);
}
#endif
// Request Routine called from decode win32 thread
enum GuitErrs imgGifDecode(PDECODER pdecoder)
{
PIMGCBINFO pImgCBInfo = pDC_GetOutput(pdecoder);
pImgCBInfo->flags = IMG_WHKNOWN;
pImgCBInfo->bProgSeen = TRUE;
pImgCBInfo->data = ReadGIFObject(pdecoder,
&pImgCBInfo->width,
&pImgCBInfo->height,
pImgCBInfo->colors,
&pImgCBInfo->transparent);
return cbDC_GetResult(pdecoder);
}
#ifdef FEATURE_JPEG
// Request Routine called from decode win32 thread
enum GuitErrs imgJPEGDecode(PDECODER pdecoder)
{
PIMGCBINFO pImgCBInfo = pDC_GetOutput(pdecoder);
/*
setImageData expects to be called with a DIB-padded-string of
pseudocolor bytes, width, height, a palette, -1 for transparent,
and IMG_JPEG.
Therefore, we have to do the dithering now, rather than later.
*/
pImgCBInfo->transparent = -1;
pImgCBInfo->flags = IMG_JPEG|IMG_WHKNOWN;
pImgCBInfo->bProgSeen = TRUE;
if (wg.eColorMode == 8)
{
pImgCBInfo->data = ReadJPEG_Dithered(pdecoder,NULL,0,&pImgCBInfo->width,&pImgCBInfo->height);
}
else if (wg.eColorMode == 4)
{
/* 16 color screen */
pImgCBInfo->data = ReadJPEG_Dithered_VGA(pdecoder,NULL,0,&pImgCBInfo->width,&pImgCBInfo->height);
}
else
{
/* true color screen */
pImgCBInfo->data = ReadJPEG_RGB(pdecoder,NULL,0,&pImgCBInfo->width,&pImgCBInfo->height);
}
return cbDC_GetResult(pdecoder);
}
#endif
PRIVATE int HTIMAGE_init(struct Mwin *tw, int nState, void **ppInfo)
{
struct Params_InitStream *pParams;
pParams = (struct Params_InitStream *) *ppInfo;
switch (nState)
{
case STATE_INIT:
pParams->request = HTRequest_validate(pParams->request);
if (pParams->request == NULL)
{
*pParams->pResult = -1;
return STATE_DONE;
}
pParams->me->fDCache = pParams->fDCache;
if (pParams->fDCache)
{
#ifdef FEATURE_INTL
SetFileDCache(tw->w3doc,
pParams->request->destination->szActualURL,
pParams->request->content_encoding,
&pParams->me->fpDc,
&pParams->me->pszDcFile,
pParams->atomMIMEType);
#else
SetFileDCache(pParams->request->destination->szActualURL,
pParams->request->content_encoding,
&pParams->me->fpDc,
&pParams->me->pszDcFile,
pParams->atomMIMEType);
#endif
pParams->me->format_inDc = pParams->atomMIMEType;
}
else
{
pParams->me->fpDc = NULL;
pParams->me->pszDcFile = NULL;
pParams->me->format_inDc = 0;
}
*pParams->pResult = 1;
return STATE_DONE;
case STATE_ABORT:
pParams->request = HTRequest_validate(pParams->request);
if (pParams->fDCache)
{
AbortFileDCache(&pParams->me->fpDc, &pParams->me->pszDcFile);
pParams->me->fDCache = FALSE; // So HTIMAGE_free knows.
}
*pParams->pResult = -1;
return STATE_DONE;
}
}
PRIVATE void HTIMAGE_write_dcache(HTStream * me, CONST char *s, int cb)
{
AssertDiskCacheEnabled();
if (me->fpDc)
CbWriteDCache(s, 1, cb, &me->fpDc, &me->pszDcFile, NULL, 0, me->tw);
}