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.
 
 
 
 
 
 

1497 lines
42 KiB

/*
Enhanced NCSA Mosaic from Spyglass
"Guitar"
Copyright 1994 Spyglass, Inc.
All Rights Reserved
Portions of this file were derived from
the CERN libwww, version 2.15.
moved back to shared by -dpg
*/
#include "all.h"
/*
** This file is now shared between Windows and UNIX
** (so please be nice)
*/
#if defined(WIN32) || defined (UNIX)
/******************************************************/
/* Intentional syntax error - this file is WIN32 only */
/******************************************************/
/* that doesn't work w/ gcc */
#ifdef WIN32
#include <process.h>
#include <io.h>
#endif
/*
This file contains the implementation of a stream used whenever the object
being retrieved needs to be saved to disk. The internal image viewers work
this way, as does the sound player. External viewers work this way, including
smart viewers (ones which use the SDI). Finally, this stream is used whenever
the object is simply being retrieved so that it can be saved to disk.
There are five different ways to create the stream, all of which work a little
differently. In any case, the stream struct is the same. Regardless of how
the stream was created, and for what purpose, the async init function
HTFWRITE_Async() will be called so that the stream can do any initialization
necessary.
Regardless of how this stream is created, me->fp must be set to an open file
for writing the data as it comes in. Some of the methods create this file as
the stream is created, because enough information is available at that time to
do so. Others wait for the init function to be called, so that more information
may be gathered (potentially from the user) before opening the file.
The five routines which create this stream are:
GTR_DoExternalViewer
This is used whenever there is already an external viewer configured for
the MIME type of the object being retrieved. This function opens the file
right away, so HTFWRITE_Async() doesn't need to do anything.
HTSaveWithCallback
This is used whenever we are receiving an object for which an internal
viewer exists. Specifically, this is used for JPEG, GIF, AU, and AIFF.
This function also set me->fp as the stream is created.
GTR_DoSmartViewer
This is used when there is already an SDI viewer registered and running for
the MIME type of the object being retrieved. This function also set me->fp
as the stream is created.
GTR_DoRegisterNow
This is used when there is a preconfigured SDI viewer for the MIME type,
but that viewer is not running and registered. The SDI RegisterNow verb
needs to be issued so that the viewer can register itself, ready for the
object to be transferred over. This function leaves me->fp NULL, thus
HTFWRITE_Async() will handle the SDI commands, then open the file.
GTR_DoDownLoad
This is used when we don't know what else to do with the object being
retrieved. It is also used when we deliberately want to skip any other
default handling for the object. It leaves me->fp NULL, and
HTFWRITE_Async() will bring up the "Unhandled File Format" dialog,
allowing the user to decide how to handle the file.
*/
struct _HTStream
{
CONST HTStreamClass *isa;
int expected_length;
int count;
BOOL bError;
FILE *fp;
HTRequest *request; /* saved for callback */
HTFormat mime_type;
struct Viewer_Info *pvi;
char *filename;
void (*callback)(void *param, const char *szURL, BOOL bAbort);
void *param;
struct Mwin *tw;
BOOL bRegisterNow; /* TRUE if in the middle of RegisterNow */
#ifdef UNIX
unsigned int flags;
char szURL[MAX_URL_STRING + 1];
#endif
BOOL bDoInterlude;
};
#define STATE_HTFWRITE_DID_INTERLUDE_DIALOG (STATE_OTHER + 1)
#define STATE_HTFWRITE_DID_REGISTER_NOW (STATE_OTHER + 2)
#define STATE_HTFWRITE_CHECK_HELPER_READY (STATE_OTHER + 3)
#define STATE_HTFWRITE_HELPER_IS_READY (STATE_OTHER + 4)
#ifdef _GIBRALTAR
#define STATE_HTFWRITE_DO_SAFEOPEN_DIALOG (STATE_OTHER + 5)
#define STATE_HTFWRITE_DID_SAFEOPEN_DIALOG (STATE_OTHER + 6)
#endif // _GIBRALTAR
PRIVATE int HTFWRITE_Async(struct Mwin *tw, int nState, void **ppInfo)
{
struct Params_InitStream *pParams;
ThreadID tid;
char tempFile[_MAX_PATH + 1];
char path[_MAX_PATH + 1];
BOOL bQueryViewerStatus;
pParams = (struct Params_InitStream *) *ppInfo;
tid = Async_GetCurrentThread();
switch (nState)
{
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case STATE_INIT:
/*
If we already have a file pointer, then we are really going
to write to a file. Return 1 (keep-going).
*/
if (pParams->me->fp)
{
*pParams->pResult = 1;
#ifdef UNIX
if (debug)
printf("STATEINIT already have a file pointer.\n");
#endif
return STATE_DONE;
}
#ifdef UNIX
strcpy(pParams->me->szURL, pParams->request->destination->szActualURL);
#endif
#ifdef FEATURE_IAPI
if (pParams->me->bRegisterNow)
{
/* Wait for the app to be ready to receive DDE. This is necessary
because some helpers may take a long time to initialize */
return STATE_HTFWRITE_CHECK_HELPER_READY;
}
#endif
/*
If we are actually accessing a local file, then we don't
really write a temp file at all. We lie and say we have
completed. The code in htfile.c and dcache.c knows how to
handle this situation. The next thing that happens is that
the _free method (below, HTFWriter_free()) will be called.
*/
if (pParams->request->szLocalFileName)
{
if (pParams->me->mime_type == WWW_BINARY)
{
#ifdef UNIX
if (debug)
printf("WWW_BINARY Local \n");
#endif
GTR_FREE(pParams->request->szLocalFileName);
pParams->request->szLocalFileName = NULL;
}
else if (!pParams->me->bDoInterlude)
{
/* if an app is configured, then just return and they
** will handle that file. Else lets pull up the
** interlude
*/
struct Viewer_Info *pvi;
pvi = PREF_GetViewerInfoBy_MIMEAtom(pParams->me->mime_type);
#ifdef UNIX
if (debug)
printf("Here in HTFWrite_Async.\n");
if (pvi && pvi->iHowToPresent != HTP_SAVE &&
pvi->iHowToPresent != HTP_UNKNOWN &&
pvi->iHowToPresent != HTP_SAVELAUNCH)
#else
if (pvi && pvi->iHowToPresent != HTP_SAVE &&
pvi->iHowToPresent != HTP_UNKNOWN)
#endif
{
*pParams->pResult = 0; /* all done! */
return STATE_DONE;
}
}
}
#ifdef UNIX
else
if (debug)
printf("WWW NOT local file.\n");
#endif
x_get_good_filename ( pParams->tempFile,
pParams->request->destination->szActualURL,
pParams->me->mime_type );
pParams->atomMIMEType = pParams->me->mime_type;
pParams->expected_length = pParams->me->expected_length;
/*
This routine is called whether we are downloading, or handling
an external viewer, or a smart viewer, or whatever. We only
want to block the thread and bring up the dialog if we got here
via GTR_DoDownLoad.
*/
#if defined (UNIX)
/* popup interlude dialog */
UseInterlude(tw, pParams, tid);
#elif defined (WIN32)
DlgUNK_RunDialog(tw, pParams, tid);
#endif
Async_BlockThread(tid);
return STATE_HTFWRITE_DID_INTERLUDE_DIALOG;
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifdef FEATURE_IAPI
case STATE_HTFWRITE_CHECK_HELPER_READY:
# ifdef WIN32
if (!GTR_IsHelperReady(pParams->me->pvi->szCurrentViewerServiceName))
return STATE_HTFWRITE_CHECK_HELPER_READY;
else
return STATE_HTFWRITE_HELPER_IS_READY;
# endif /* win32 */
# ifdef UNIX
/* UNIX: thread is blocked until app registers for
** this mimetype. On RegisterViewer, will walk through
** PVI list looking for mimetype and bRegisterNow flag set
** and if found will unblock this
*/
if (!GTR_HasHelperRegistered( pParams->me->pvi->atomMIMEType) )
{
pParams->me->pvi->RegisterTid = tid;
Async_BlockThread(tid);
return STATE_HTFWRITE_CHECK_HELPER_READY;
}
else
return STATE_HTFWRITE_HELPER_IS_READY;
# endif /* unix */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case STATE_HTFWRITE_HELPER_IS_READY:
#ifdef WIN32
if ( !SDI_Issue_RegisterNow(tw,
pParams->me->pvi->szCurrentViewerServiceName))
{
*pParams->pResult = -1;
return STATE_DONE;
}
Async_BlockThread(tid);
#endif
return STATE_HTFWRITE_DID_REGISTER_NOW;
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case STATE_HTFWRITE_DID_REGISTER_NOW:
/* Call a function which issues ViewDocCache to the registered
viewer. If this function returns TRUE, then the document
already exists and we are finished. */
#ifdef FEATURE_IAPI
if (SDI_Issue_ViewDocCache(tw, pParams->me->mime_type))
{
*pParams->pResult = -1;
return STATE_DONE;
}
#endif
/* Get the temporary file name to save the document to */
#ifdef UNIX
if (debug)
printf("Here in STATE_HTFWRITE_DID_REGISTER_NOW - build tmpfile.\n");
xgtr_build_tempfile ( (char *)NULL,
(char *)NULL, (char *)HTFileSuffix (pParams->me->mime_type),
tempFile);
#else
path[0] = 0;
PREF_GetTempPath(_MAX_PATH, path);
GetTempFileName(path, "A", 0, tempFile);
remove(tempFile);
#endif
/* See if the registered viewer wants to override the file name. */
#ifdef FEATURE_IAPI
bQueryViewerStatus = SDI_Issue_QueryViewer (tw,
pParams->me->mime_type, tempFile, sizeof(tempFile));
#endif
if (bQueryViewerStatus)
{
if (pParams->request->szLocalFileName)
{
/*
The SDI app chose to override the file name. We no
longer care if we are accessing a local file. It
asked for a temp file, so it will get it.
*/
GTR_FREE(pParams->request->szLocalFileName);
pParams->request->szLocalFileName = NULL;
/*
This falls through to below where we actually open a
temp file, which in this case the SDI app specified.
*/
}
}
else
{
/*
The SDI app did not choose to override the file name.
Therefore, any file we pass them is under our control.
If we want to pass them a non-temp file (because we are
accessing a local file), then that is our choice, and we
take responsibility for not deleting it.
*/
if (pParams->request->szLocalFileName)
{
*pParams->pResult = 0; /* all done! */
pParams->me->filename =
GTR_strdup (pParams->request->szLocalFileName);
return STATE_DONE;
}
}
/*
If we get here, we are going to write a temp file.
*/
if (!pParams->request->content_encoding)
{
pParams->request->content_encoding =
HTContentToEncoding (pParams->me->mime_type);
}
if (!(pParams->request->iFlags & HTREQ_BINARY) && (pParams->request->content_encoding == HTAtom_for("7bit") ||
pParams->request->content_encoding == HTAtom_for("8bit")))
{
pParams->me->fp = fopen(tempFile, "w");
}
else
{
pParams->me->fp = fopen(tempFile, "wb");
}
if (!pParams->me->fp)
{
*pParams->pResult = -1;
return STATE_DONE;
}
pParams->me->filename = GTR_strdup(tempFile); /* Will be freed */
/*
If the SDI app specifies the location of the temp file, it is
responsible for cleaning it up. Otherwise, it is our
responsibility, and we will delete it if it is a temp file,
and leave it untouched if it is not.
*/
#ifdef WIN32
if (!bQueryViewerStatus && !pParams->request->szLocalFileName)
{
TEMP_Add(tempFile);
}
#endif
*pParams->pResult = 1;
pParams->me->request = pParams->request; /* won't be freed */
pParams->me->tw = tw;
return STATE_DONE;
#endif /* FEATURE_IAPI
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case STATE_HTFWRITE_DID_INTERLUDE_DIALOG:
/*
After the dialog, it is possible that we are going to continue
on and do a SAVEAS, or we may CANCEL, or the user may have
configured a viewer.
*/
#ifdef UNIX
if (debug)
printf("HERE DID_INTERLUDE %d.\n", pParams->iUserChoice);
#endif
switch (pParams->iUserChoice)
{
case 1: /* save */
if (!(pParams->request->iFlags & HTREQ_BINARY) && ( pParams->request->content_encoding ==HTAtom_for("7bit") ||
pParams->request->content_encoding ==HTAtom_for("8bit") ))
{
pParams->me->fp = fopen(pParams->tempFile, "w");
}
else
{
pParams->me->fp = fopen(pParams->tempFile, "wb");
}
if (pParams->me->fp)
{
pParams->me->filename = GTR_strdup(pParams->tempFile);
*pParams->pResult = 1;
}
else
{
ERR_ReportError(tw, SID_ERR_COULD_NOT_SAVE_FILE_S, pParams->tempFile, NULL);
*pParams->pResult = -1;
}
return STATE_DONE;
case 2: /* abort download */
*pParams->pResult = -1;
pParams->request->iFlags |= HTREQ_USERCANCEL;
return STATE_DONE;
case 3:
{
struct Viewer_Info *pvi;
/* Viewer configured, possibly. If it is a smart
viewer, then invoke the smart viewer by returning
the correct state. */
pvi =
PREF_GetViewerInfoBy_MIMEAtom(pParams->me->mime_type);
pParams->me->pvi = pvi;
#ifdef WIN32
/*
This saves the viewer we just configured to the prefs file
*/
SaveViewersInfo();
#endif
#ifdef FEATURE_IAPI
#ifdef WIN32
if (pvi && pvi->szCurrentViewerServiceName[0])
{
/* See if the viewer is already up */
if (GTR_IsHelperReady(pvi->szSmartViewerServiceName))
{
strcpy (pvi->szCurrentViewerServiceName,
pvi->szSmartViewerServiceName);
pvi->iHowToPresent = HTP_SMARTVIEWER;
return STATE_HTFWRITE_CHECK_HELPER_READY;
}
/* Helper is not ready. Can we start it? */
if (pvi->szViewerApp[0] &&
GTR_StartApplication(pvi->szViewerApp))
{
strcpy(pvi->szCurrentViewerServiceName,
pvi->szSmartViewerServiceName);
return STATE_HTFWRITE_CHECK_HELPER_READY;
}
/* Fall through */
}
#endif
#ifdef UNIX
/* TODO UNIX SDI */
/* TODO UNIX SDI */
/* TODO UNIX SDI */
/* TODO UNIX SDI */
/* TODO UNIX SDI */
#endif
#endif /* FEATURE_IAPI */
#ifdef UNIX
if (debug)
printf("Build Tmp File.\n");
xgtr_build_tempfile ( (char *)NULL,
(char *)NULL, (char *)HTFileSuffix (pParams->me->mime_type),
pParams->tempFile);
/* TODO note the code below doesn't guarantee a unique name. */
#else
path[0] = 0;
PREF_GetTempPath(_MAX_PATH, path);
{
char baseFile[_MAX_PATH + 1];
x_get_good_filename (baseFile,
pParams->request->destination->szActualURL,
pParams->me->mime_type);
/* The name is now in baseFile */
sprintf(pParams->tempFile, "%s%s", path, baseFile);
}
#endif
if (!(pParams->request->iFlags & HTREQ_BINARY) && (pParams->request->content_encoding ==
HTAtom_for("7bit") ||
pParams->request->content_encoding ==
HTAtom_for("8bit")))
{
pParams->me->fp = fopen(pParams->tempFile, "w");
}
else
{
pParams->me->fp = fopen(pParams->tempFile, "wb");
}
if (pParams->me->fp)
{
/* Will be freed */
pParams->me->filename=GTR_strdup(pParams->tempFile);
*pParams->pResult = 1;
}
else
{
ERR_ReportError(tw, SID_ERR_COULD_NOT_SAVE_FILE_S, pParams->tempFile, NULL);
*pParams->pResult = -1;
}
return STATE_DONE;
}
break;
}
XX_Assert((0), ("This statement should not be reached\n"));
return STATE_ABORT;
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case STATE_ABORT:
*pParams->pResult = -1;
return STATE_DONE;
}
}
PRIVATE BOOL HTFWriter_put_character(HTStream * me, char c)
{
int result;
result = putc(c, me->fp);
me->count++;
if (me->expected_length > 0)
WAIT_SetTherm(me->tw, me->count);
if (result == EOF)
{
me->bError = TRUE;
}
return (!me->bError);
}
PRIVATE BOOL HTFWriter_put_string(HTStream * me, CONST char *s)
{
int len;
int result;
len = strlen(s);
result = fputs(s, me->fp);
me->count += len;
if (me->expected_length > 0)
WAIT_SetTherm(me->tw, me->count);
if (result <= 0)
{
me->bError = TRUE;
}
return (!me->bError);
}
PRIVATE BOOL HTFWriter_write(HTStream * me, CONST char *s, int len)
{
int result;
if ( !s || !me || !(me->fp))
{
me->bError = TRUE;
return (!me->bError);
}
result = fwrite(s, 1, len, me->fp);
me->count += len;
if (me->expected_length > 0)
WAIT_SetTherm(me->tw, me->count);
if (result != len)
{
me->bError = TRUE;
}
return (!me->bError);
}
PRIVATE void HTFWriter_free(HTStream * me)
{
char szFullURL[MAX_URL_STRING + 1];
/*
When we get here, we either have a me->fp valid or not. If we do,
then we have written a temporary file, and this routine is responsible
for taking action with it. That action may be launching an external
viewer, or perhaps passing the data to an SDI viewer, or perhaps
executing the callback function (to an internal viewer).
If we do not have a valid me->fp, then the URL being accessed was
retrieved from a local file, as indicated by
me->request->szLocalFileName being valid. This could have been due
to a disk cache hit (see dcache.c) or the URL may have simply been
a file: URL (see htfile.c).
*/
if (me->fp)
{
fclose(me->fp);
}
if (me->bError)
{
ERR_ReportError(me->tw, SID_ERR_COULD_NOT_SAVE_FILE_S, me->filename, NULL);
if (me->callback)
(*me->callback)(me->param, me->request->destination->szActualURL, TRUE);
#ifdef UNIX
if (me->filename && !me->request->szLocalFileName)
#else
if (me->filename)
#endif
{
remove(me->filename);
}
}
else
{
GHist_Add((char *) me->request->destination->szActualURL, NULL, time(NULL));
if (me->pvi)
{
switch (me->pvi->iHowToPresent)
{
#ifdef UNIX
case HTP_SAVE:
if (debug)
printf("Here in save from HTFWriter_free.\n");
break;
case HTP_SAVELAUNCH:
{
char *szCmd;
XX_Assert(me->filename, ("filename is NULL"));
szCmd = (char *) GTR_MALLOC(
(strlen(me->pvi->szViewerApp) + 10 +
3 * strlen(me->filename)) * sizeof(char));
if (szCmd)
{
sprintf (szCmd, me->pvi->szViewerApp,
me->filename, me->filename, me->filename);
ExecuteCommand(szCmd);
GTR_FREE(szCmd);
}
else
{
ERR_ReportError(me->tw, SID_ERR_OUT_OF_MEMORY, NULL, NULL);
}
}
break;
#endif
#ifdef _GIBRALTAR
case HTP_ASSOCIATION:
{
HINSTANCE hApp = ShellExecute(NULL, NULL, me->filename, NULL, NULL, SW_NORMAL);
if (hApp < (HINSTANCE)32)
{
char buf[_MAX_PATH + 512];
if (hApp == (HINSTANCE)SE_ERR_NOASSOC)
{
sprintf(buf, GTR_GetString(SID_ERR_NO_ASSOCIATION), me->filename, NULL);
}
else
{
sprintf(buf, GTR_GetString(SID_ERR_COULD_NOT_EXECUTE_COMMAND_D_S), hApp, me->filename);
}
ERR_ReportError(NULL, SID_ERR_SIMPLY_SHOW_ARGUMENTS_S_S, buf, NULL);
}
}
break;
#endif // _GIBRALTAR
case HTP_DUMBVIEWER:
{
char *szCmd;
XX_Assert(me->filename, ("filename is NULL"));
szCmd = (char *) GTR_MALLOC(
(strlen(me->pvi->szViewerApp) + 10 +
3 * strlen(me->filename)) * sizeof(char));
if (szCmd)
{
sprintf (szCmd, me->pvi->szViewerApp,
me->filename, me->filename, me->filename);
ExecuteCommand(szCmd);
GTR_FREE(szCmd);
}
else
{
ERR_ReportError(me->tw, SID_ERR_OUT_OF_MEMORY, NULL, NULL);
}
}
break;
case HTP_SMARTVIEWER:
XX_Assert(me->filename, ("filename is NULL"));
#ifdef FEATURE_IAPI
strcpy(szFullURL, me->request->destination->szRequestedURL);
if (me->request->destination->szRequestedLocal &&
me->request->destination->szRequestedLocal[0])
{
strcat(szFullURL, "#");
strcat(szFullURL, me->request->destination->szRequestedLocal);
}
SDI_Issue_ViewDocFile(me->filename, szFullURL,
HTAtom_name(me->mime_type), me->tw->serialID);
#endif
break;
default:
if (me->callback)
(*me->callback)(me->param, me->request->destination->szActualURL, FALSE);
break;
}
}
else
{
if (me->callback)
(*me->callback)(me->param, me->request->destination->szActualURL, FALSE);
}
}
if (me->filename)
GTR_FREE(me->filename);
GTR_FREE(me);
}
PRIVATE void HTFWriter_abort(HTStream * me, HTError e)
{
if (me->fp)
{
fclose(me->fp);
}
if (me->callback)
{
(*me->callback)(me->param, me->request->destination->szActualURL, TRUE);
}
#ifdef UNIX
if (me->filename && !me->request->szLocalFileName)
#else
if (me->filename)
#endif
{
remove(me->filename);
}
if (me->filename)
GTR_FREE(me->filename);
GTR_FREE(me);
}
PRIVATE CONST HTStreamClass HTFWriter = /* As opposed to print etc */
{
"FileWriter",
SID_HTFWRITE_TRANSFERRING_FILE_S,
SID_HTFWRITE_TRANSFERRING_FILE_S_S,
HTFWRITE_Async,
HTFWriter_free,
HTFWriter_abort,
HTFWriter_put_character, HTFWriter_put_string,
HTFWriter_write
};
HTStream *GTR_DoExternalViewer(struct Mwin *tw, HTRequest * request, void *param,
HTFormat input_format, HTFormat output_format,
HTStream * output_stream)
{
char tempFile[_MAX_PATH + 1];
HTStream *me;
char path[_MAX_PATH + 1];
me = (HTStream *) GTR_CALLOC(sizeof(*me), 1);
if (me == NULL)
{
return NULL;
}
me->isa = &HTFWriter;
me->expected_length = request->content_length;
me->count = 0;
me->mime_type = input_format;
me->bError = FALSE;
if (me->expected_length > 0)
{
WAIT_SetRange(tw, 0, 100, me->expected_length);
}
me->pvi = PREF_GetViewerInfoBy_MIMEAtom(input_format);
if (!request->content_encoding)
{
request->content_encoding = HTContentToEncoding(input_format);
}
if (request->szLocalFileName)
{
me->filename = GTR_strdup(request->szLocalFileName);
me->fp = NULL;
}
else
{
#ifdef UNIX
if (me->pvi && (me->pvi->iHowToPresent == HTP_SAVE ||
me->pvi->iHowToPresent == HTP_SAVELAUNCH))
{
me->request = request; /* won't be freed */
me->tw = tw;
return me;
}
else
{
xgtr_build_tempfile ((char *)NULL, (char *)NULL,
(char *)HTFileSuffix(me->mime_type), tempFile);
me->filename = GTR_strdup(tempFile); /* Will be freed */
}
#endif
#ifdef WIN32
path[0] = 0;
PREF_GetTempPath(_MAX_PATH, path);
{
/* Configured external viewer */
char baseFile[_MAX_PATH + 1];
x_get_good_filename(baseFile, request->destination->szActualURL, input_format);
/* The full temp file path is now in path */
/* We will not prompt for a filename - just create the temp file */
sprintf(tempFile, "%s%s", path, baseFile);
}
#endif /* WIN32 */
if (!(request->iFlags & HTREQ_BINARY) && ( request->content_encoding == HTAtom_for("7bit") ||
request->content_encoding == HTAtom_for("8bit") ))
{
me->fp = fopen(tempFile, "w");
}
else
{
me->fp = fopen(tempFile, "wb");
}
if (!me->fp)
{
ERR_ReportError(tw, SID_ERR_COULD_NOT_SAVE_FILE_S, tempFile, NULL);
GTR_FREE(me);
return NULL;
}
#ifdef WIN32
me->filename = GTR_strdup(tempFile); /* Will be freed */
TEMP_Add(me->filename); /* mark this to be deleted at program exit */
#endif
}
me->request = request; /* won't be freed */
me->tw = tw;
return me;
}
/* Save Locally */
HTStream *GTR_DoDownLoad(struct Mwin *tw, HTRequest * request, void *param,
HTFormat input_format, HTFormat output_format,
HTStream * output_stream)
{
HTStream *me;
me = (HTStream *) GTR_CALLOC(sizeof(*me), 1);
if (me == NULL)
{
return NULL;
}
me->isa = &HTFWriter;
me->expected_length = request->content_length;
me->count = 0;
me->mime_type = input_format;
me->bError = FALSE;
me->pvi = NULL;
if (me->expected_length > 0)
{
WAIT_SetRange(tw, 0, 100, me->expected_length);
}
if (!request->content_encoding)
{
request->content_encoding = HTContentToEncoding(input_format);
}
#ifdef FEATURE_IAPI
if (request->savefile)
{
if (!(request->iFlags & HTREQ_BINARY) && ( request->content_encoding == HTAtom_for("7bit") ||
request->content_encoding == HTAtom_for("8bit") ))
{
me->fp = fopen(request->savefile, "w");
}
else
{
me->fp = fopen(request->savefile, "wb");
}
if (!me->fp)
{
ERR_ReportError(tw, SID_ERR_COULD_NOT_SAVE_FILE_S, request->savefile, NULL);
GTR_FREE(me);
return NULL;
}
me->filename = GTR_strdup(request->savefile); /* Will be freed */
}
else
#endif
{
me->bDoInterlude = TRUE;
}
me->request = request; /* won't be freed */
me->tw = tw;
return me;
}
HTStream *HTSaveWithCallback(struct Mwin *tw, HTRequest *request, void *param, HTFormat input_format, void (*callback)(void *, const char *, BOOL))
{
char tempFile[_MAX_PATH + 1];
HTStream *me;
me = (HTStream *) GTR_CALLOC(sizeof(*me), 1);
if (me == NULL)
{
return NULL;
}
me->isa = &HTFWriter;
me->expected_length = request->content_length;
me->count = 0;
me->mime_type = input_format;
me->bError = FALSE;
if (me->expected_length > 0)
{
WAIT_SetRange(tw, 0, 100, me->expected_length);
}
if (!request->content_encoding)
{
request->content_encoding = HTContentToEncoding(input_format);
}
if (request->szLocalFileName)
{
me->fp = NULL;
me->filename = NULL;
/* we don't need to set a filename. The code in winview.c or au.c is taking care of it properly. */
}
else
{
strcpy(tempFile, request->savefile);
if (!(request->iFlags & HTREQ_BINARY) && (request->content_encoding == HTAtom_for("7bit") || request->content_encoding == HTAtom_for("8bit")))
me->fp = fopen(tempFile, "w");
else
me->fp = fopen(tempFile, "wb");
if (!me->fp)
{
ERR_ReportError(tw, SID_ERR_COULD_NOT_SAVE_FILE_S, tempFile, NULL);
GTR_FREE(me);
return NULL;
}
me->filename = GTR_strdup(tempFile); /* Will be freed */
/*
We don't call TEMP_Add() for this filename since the viewer/sound player code will
be responsible for deleting it.
*/
}
me->request = request; /* won't be freed */
me->tw = tw;
me->callback = callback;
me->param = param;
return me;
}
HTStream *GTR_DoSmartViewer(struct Mwin *tw, HTRequest * request, void *param,
HTFormat input_format, HTFormat output_format,
HTStream * output_stream)
{
#ifdef FEATURE_IAPI
char tempFile[_MAX_PATH + 1];
HTStream *me;
char path[_MAX_PATH + 1];
BOOL bQueryViewerStatus;
BOOL bDoTempFile;
me = (HTStream *) GTR_CALLOC(sizeof(*me), 1);
if (me == NULL)
{
return NULL;
}
me->isa = &HTFWriter;
me->expected_length = request->content_length;
me->count = 0;
me->mime_type = input_format;
me->bError = FALSE;
if (me->expected_length > 0)
{
WAIT_SetRange(tw, 0, 100, me->expected_length);
}
me->pvi = PREF_GetViewerInfoBy_MIMEAtom(input_format);
/* Call a function which issues ViewDocCache to the registered
viewer. If this function returns TRUE, then the document
already exists and we are finished. */
/* this would seem to be just a little redundant -dpg */
#ifdef FEATURE_IAPI
if (SDI_Issue_ViewDocCache(tw, input_format))
{
GTR_FREE(me);
return NULL;
}
#endif
if (!request->content_encoding)
{
request->content_encoding = HTContentToEncoding(input_format);
}
/* Get the temporary file name to save the document to */
#ifdef UNIX
if (debug)
printf("Here in Do Smart Viewer.\n");
xgtr_build_tempfile ( (char *)NULL, (char *)NULL,
(char *)HTFileSuffix (me->mime_type), tempFile);
#else
path[0] = 0;
PREF_GetTempPath(_MAX_PATH, path);
GetTempFileName(path, "A", 0, tempFile);
remove(tempFile);
#endif
/* See if the registered viewer wants to override the file name. */
#ifdef FEATURE_IAPI
bQueryViewerStatus = SDI_Issue_QueryViewer(tw, me->mime_type, tempFile, sizeof(tempFile));
#endif
bDoTempFile = TRUE;
if (bQueryViewerStatus)
{
/*
The SDI app chose to override the file name. We no longer
care if we are accessing a local file. It asked for a temp file,
so it will get it.
*/
if (request->szLocalFileName)
{
GTR_FREE(request->szLocalFileName);
request->szLocalFileName = NULL;
}
/*
This falls through to below where we actually open a temp file,
which in this case the SDI app specified.
*/
}
else
{
/*
The SDI app did not choose to override the file name. Therefore,
any file we pass them is under our control. If we want to pass
them a non-temp file (because we are accessing a local file), then
that is our choice, and we take responsibility for not deleting it.
*/
if (request->szLocalFileName)
{
me->fp = NULL;
me->filename = GTR_strdup(request->szLocalFileName);
bDoTempFile = FALSE;
}
}
if (bDoTempFile)
{
if (!(request->iFlags & HTREQ_BINARY) && (request->content_encoding == HTAtom_for("7bit") || request->content_encoding == HTAtom_for("8bit")))
me->fp = fopen(tempFile, "w");
else
me->fp = fopen(tempFile, "wb");
if (!me->fp)
{
/* ERR_ReportError(tw, SID_ERR_COULD_NOT_SAVE_FILE_S, tempFile, NULL); */
GTR_FREE(me);
return NULL;
}
me->filename = GTR_strdup(tempFile); /* Will be freed */
#ifdef WIN32
if (!bQueryViewerStatus)
{
/*
If the SDI app specifies the location of the temp file, it
is responsible for cleaning it up. Otherwise, it is our
responsibility, and we will delete it if it is a temp file,
and leave it untouched if it is not.
*/
TEMP_Add(tempFile);
}
#endif
}
me->request = request; /* won't be freed */
me->tw = tw;
return me;
#else
return NULL;
#endif
}
HTStream *GTR_DoRegisterNow(struct Mwin *tw, HTRequest * request, void *param,
HTFormat input_format, HTFormat output_format,
HTStream * output_stream)
{
#ifdef FEATURE_IAPI
HTStream *me;
me = (HTStream *) GTR_CALLOC(sizeof(*me), 1);
if (me == NULL)
{
return NULL;
}
me->isa = &HTFWriter;
me->expected_length = request->content_length;
me->count = 0;
me->mime_type = input_format;
me->bError = FALSE;
if (me->expected_length > 0)
{
WAIT_SetRange(tw, 0, 100, me->expected_length);
}
if (!request->content_encoding)
{
request->content_encoding = HTContentToEncoding(input_format);
}
/* Issue RegisterNow to the app */
me->pvi = PREF_GetViewerInfoBy_MIMEAtom(input_format);
me->request = request; /* won't be freed */
me->tw = tw;
me->bRegisterNow = TRUE;
return me;
#else
return NULL;
#endif
}
void x_get_good_filename(char *dest, char *url, HTFormat input_format)
#if defined (UNIX)
/* if it's good enough for a url, it's good enough for unix */
{
char *p1;
static int counter;
p1 = strrchr(url, '/');
if (p1)
{
p1++; /* skip the slash */
GTR_strncpy (dest, p1, 255);
}
else
{
/* we'll have to synthesize a basename */
sprintf (dest, "gtr%dx%d.tmp", _getpid(), counter++);
}
}
#elif defined (WIN32)
{
/*
This code and perhaps its callers should be modified
to NOT create short filenames under Win95 and NT.
*/
char *p1;
char *p2;
char *q;
char *pBase;
char szBase[255 + 1];
char szSuff[31 + 1];
int len;
#ifdef _GIBRALTAR
// convert back all slashes to uniform notation.
while (p1 = strchr(url, '\\'))
{
*p1++ = '/';
}
#endif // _GIBRALTAR
//
// Check if we are on Win95 or Windows NT.
// Both these systems support long file names (liberally), so
// we will not do custom munging of the names on these systems.
//
if ( wg.fWin95 || wg.fWindowsNT) {
//
// Bingo! We support long file names.
// Generate the good file name from the URL directly.
//
dest[0] = '\0';
p1 = strrchr(url, '/');
if (p1 != NULL) {
p1++; /* skip the slash */
GTR_strncpy (dest, p1, 255);
}
if ( dest[0] == '\0') {
// empty file name. fill in with a temporary name.
static int counter;
/* we'll have to synthesize a basename */
sprintf (dest, "gtr%dx%d.tmp",
GetCurrentProcessId(), counter++);
}
#ifdef _GIBRALTAR
//
// Get rid of CGI '?' char from the suffix
//
{
char *pch = strrchr(dest, '?');
if (pch)
{
*pch = '\0';;
}
}
#endif // _GIBRALTAR
return; // Get out of this function ...
}
//
// Process URLs for Win32s systems, that do not support long file names.
//
p1 = strrchr(url, '/');
if (p1)
{
p1++; /* skip the slash */
pBase = p1;
/*
Copy everything from p1 until the end
of the string, OR the first dot (we don't want
the suffix right now.
*/
q = szBase;
while (*p1 && (*p1 != '.') && ((q - szBase) < 255))
{
*q++ = *p1++;
}
*q = 0;
/*
szBase *might* still be empty
*/
}
else
{
szBase[0] = 0; /* we'll have to synthesize a basename */
p1 = url;
}
p2 = strrchr(url, '.');
if (p2 && (p2 > pBase))
{
/*
We have a suffix in the base of the URL. We'll see about
using it or not.
*/
p2++; /* skip the dot */
q = szSuff;
while (*p2 && ((q - szSuff) < 31))
{
*q++ = *p2++;
}
*q = 0;
#ifdef _GIBRALTAR
//
// Get rid of CGI '?' char from the suffix
//
{
char *pch = strrchr(szSuff, '?');
if (pch)
{
*pch = '\0';;
}
}
#endif // _GIBRALTAR
}
else
{
szSuff[0] = 0; /* we'll have to synthesize a suffix */
}
/*
OK, we've stripped everything out of the URL which might be
useful.
*/
if (szBase[0])
{
if (wg.fWindowsNT || (wg.iWindowsMajorVersion >= 4))
{
/* the base name is fine, or TODO should we fix to 31 chars?? */
}
else
{
len = strlen(szBase);
if (len > 8)
{
szBase[8] = 0;
}
}
}
else
{
static int counter;
/*
Let's synthesize a valid basename
*/
sprintf(szBase, "gtr%d", counter++);
}
if (szSuff[0])
{
/*
We have suffix, and the string does not include the dot.
Let's see if it's legal
*/
len = strlen(szSuff);
if ((len > 3) && !(wg.fWindowsNT || (wg.iWindowsMajorVersion >= 4)))
{
/*
We can't just null terminate a suffix.
Void the one we have entirely, and choose
a new one.
*/
szSuff[0] = 0;
}
else
{
/*
Length is OK, is it a valid suffix for our MIME type?
*/
HTFormat suffix_format;
char buf[_MAX_PATH+1];
sprintf(buf, "%s.%s", szBase, szSuff);
suffix_format = HTFileFormat(buf, NULL, NULL);
if (suffix_format != input_format)
{
/* no match, discard the suffix and trust the MIME type */
szSuff[0];
}
}
}
if (!szSuff[0])
{
char *suffix;
char *p;
/*
We have to synthesize a suffix
*/
suffix = (char *) HTFileSuffix(input_format);
if (suffix)
{
p = suffix;
if (p[0] == '.')
{
p++;
}
strcpy(szSuff, p);
/*
HTFileSuffix returns a <=3 char suffix when possible,
so the following line is just in case.
*/
szSuff[3] = 0;
}
else
{
/*
This only happens when there was no suffix, and we have
nothing in the MIME type to the help us.
*/
strcpy(szSuff, "tmp");
}
}
/*
OK, now we have a valid basename which is <=8 chars and a valid
suffix which is <=3 chars. Both were derived from the URL if
it was possible to do so.
*/
sprintf(dest, "%s.%s", szBase, szSuff);
}
#endif
#endif /* WIN32/UNIX */