/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #include "net.h" #include "mktrace.h" #include "structs.h" #include "ctxtfunc.h" #include "xp_list.h" #include "plstr.h" #include "nsString.h" #include "nsIStreamListener.h" #include "nsINetSupport.h" #include "nsNetStream.h" /****************************************************************************/ /* Beginning of MWContext Evil!!! */ /* ------------------------------- */ /* */ /* Define a dummy MWContext where all of the upcalls are stubbed out. */ /* */ /****************************************************************************/ PRIVATE int stub_noop(int x, ...) { #ifdef XP_MAC #pragma unused (x) #endif /* DebugBreak(); */ return 0; } static nsIStreamListener *getStreamListener(URL_Struct *URL_s) { nsIStreamListener *res = NULL; if (URL_s && URL_s->fe_data) { /* * Retrieve the nsConnectionInfo object from the fe_data field * of the URL_Struct... */ nsConnectionInfo *pConn = (nsConnectionInfo *)URL_s->fe_data; if (pConn) { res = pConn->pConsumer; } } NS_IF_ADDREF(res); return res; } static NS_DEFINE_IID(kINetSupportIID, NS_INETSUPPORT_IID); static nsINetSupport *getNetSupport(URL_Struct *URL_s) { nsINetSupport *netSupport = nsnull; /* Access the nsConnectionInfo object off of the URL Struct fe_data */ if ((nsnull != URL_s) && (nsnull != URL_s->fe_data)) { nsConnectionInfo *pConn = (nsConnectionInfo *)URL_s->fe_data; /* Now get the nsIURL held by the nsConnectionInfo... */ if ((nsnull != pConn) && (nsnull != pConn->pURL)) { nsISupports *container; /* The nsINetSupport interface will be implemented by the container */ container = pConn->pURL->GetContainer(); if (nsnull != container) { container->QueryInterface(kINetSupportIID, (void **) &netSupport); NS_RELEASE(container); } } } return netSupport; } void stub_Alert(MWContext *context, const char *msg) { nsINetSupport *ins; if (nsnull != (ins = getNetSupport(context->modular_data))) { nsAutoString str(msg); ins->Alert(str); NS_RELEASE(ins);; } /* No nsINetSupport interface... */ else { printf("%cAlert: %s", '\007', msg); } } extern "C" void FE_Alert(MWContext *context, const char *msg) { stub_Alert(context, msg); } #if defined (WIN32) extern "C" char * FE_GetProgramDirectory(char *buffer, int length) { printf("XXX: returning c:\\temp\\ for the FE_GetProgramDirectory!\n"); strcpy(buffer, "c:\\temp\\"); return buffer; } #elif defined (XP_UNIX) extern "C" char * fe_GetProgramDirectory(char *buffer, int length) { printf("XXX: returning /tmp for the fe_GetProgramDirectory!\n"); strcpy(buffer, "/tmp/"); return buffer; } #endif XP_Bool stub_Confirm(MWContext *context, const char *msg) { nsINetSupport *ins; XP_Bool bResult = FALSE; if (nsnull != (ins = getNetSupport(context->modular_data))) { nsAutoString str(msg); bResult = ins->Confirm(str); NS_RELEASE(ins); } /* No nsINetSupport interface... */ else { printf("%cConfirm: %s (y/n)? ", '\007', msg); char c; for (;;) { c = getchar(); if (tolower(c) == 'y') { bResult = TRUE; } if (tolower(c) == 'n') { bResult = FALSE; } } } return bResult; } char *stub_Prompt(MWContext *context, const char *msg, const char *def) { nsINetSupport *ins; char *result = nsnull; if (nsnull != (ins = getNetSupport(context->modular_data))) { nsAutoString str(msg); nsAutoString defStr(def); nsAutoString res; if (ins->Prompt(msg, defStr, res)) { NS_RELEASE(ins); result = res.ToNewCString(); } NS_RELEASE(ins); } /* No nsINetSupport interface... */ else { char buf[256]; printf("%s\n", msg); printf("%cPrompt (default=%s): ", '\007', def); gets(buf); if (PL_strlen(buf)) { result = PL_strdup(buf); } else { result = PL_strdup(def); } } return result; } PRIVATE XP_Bool stub_PromptUsernameAndPassword(MWContext *context, const char *msg, char **username, char **password) { nsINetSupport *ins; XP_Bool bResult = FALSE; if (nsnull != (ins = getNetSupport(context->modular_data))) { nsAutoString str(msg); nsAutoString userStr(*username); nsAutoString pwdStr(*password); if (ins->PromptUserAndPassword(msg, userStr, pwdStr)) { *username = userStr.ToNewCString(); *password = pwdStr.ToNewCString(); bResult = TRUE; } NS_RELEASE(ins); } /* No nsINetSupport interface... */ else { char buf[256]; printf("%s\n", msg); printf("%cUser (default=%s): ", '\007', *username); gets(buf); if (strlen(buf)) { *username = PL_strdup(buf); } printf("%cPassword (default=%s): ", '\007', *password); gets(buf); if (strlen(buf)) { *password = PL_strdup(buf); } if (**username) { bResult = TRUE; } else { PR_FREEIF(*username); PR_FREEIF(*password); } } return bResult; } char *stub_PromptPassword(MWContext *context, const char *msg) { nsINetSupport *ins; char *result = nsnull; if (nsnull != (ins = getNetSupport(context->modular_data))) { nsAutoString str(msg); nsAutoString res; if (ins->PromptPassword(msg, res)) { result = res.ToNewCString(); } NS_RELEASE(ins); } /* No nsINetSupport interface... */ else { char buf[256]; printf("%s\n", msg); printf("%cPassword: ", '\007'); gets(buf); if (PL_strlen(buf)) { result = PL_strdup(buf); } } return result; } PRIVATE void stub_GraphProgressInit(MWContext *context, URL_Struct *URL_s, int32 content_length) { nsIStreamListener *pListener; if (URL_s->load_background) return; if (nsnull != (pListener = getStreamListener(URL_s))) { nsConnectionInfo *pConn = (nsConnectionInfo *) URL_s->fe_data; pListener->OnProgress(pConn->pURL, 0, content_length); NS_RELEASE(pListener); } } PRIVATE void stub_GraphProgress(MWContext *context, URL_Struct *URL_s, int32 bytes_received, int32 bytes_since_last_time, int32 content_length) { nsIStreamListener *pListener; if (URL_s->load_background) return; if (nsnull != (pListener = getStreamListener(URL_s))) { nsConnectionInfo *pConn = (nsConnectionInfo *) URL_s->fe_data; pListener->OnProgress(pConn->pURL, bytes_received, content_length); NS_RELEASE(pListener); } } PRIVATE void stub_GraphProgressDestroy(MWContext *context, URL_Struct *URL_s, int32 content_length, int32 total_bytes_read) { /* * XXX: Currently this function never calls OnProgress(...) because * netlib calls FE_GraphProgressDestroy(...) after closing the * stream... So, OnStopBinding(...) has already been called and * the nsConnectionInfo->pConsumer has been released and NULLed... */ nsIStreamListener *pListener; if (URL_s->load_background) return; if (nsnull != (pListener = getStreamListener(URL_s))) { nsConnectionInfo *pConn = (nsConnectionInfo *) URL_s->fe_data; pListener->OnProgress(pConn->pURL, total_bytes_read, content_length); // XXX The comment above no longer applies, and this function does // get called... NS_RELEASE(pListener); } } PRIVATE void stub_Progress(MWContext *context, const char *msg) { nsIStreamListener *pListener; if (nsnull != (pListener = getStreamListener(context->modular_data))) { nsConnectionInfo *pConn = (nsConnectionInfo *) context->modular_data->fe_data; nsAutoString status(msg); pListener->OnStatus(pConn->pURL, status); NS_RELEASE(pListener); } else { printf("%s\n", msg); } } PRIVATE void stub_AllConnectionsComplete(MWContext *context) { } #define MAKE_FE_TYPES_PREFIX(func) func##_t #define MAKE_FE_FUNCS_TYPES #include "mk_cx_fn.h" #undef MAKE_FE_FUNCS_TYPES #define stub_CreateNewDocWindow (CreateNewDocWindow_t)stub_noop #define stub_LayoutNewDocument (LayoutNewDocument_t)stub_noop #define stub_SetDocTitle (SetDocTitle_t)stub_noop #define stub_FinishedLayout (FinishedLayout_t)stub_noop #define stub_TranslateISOText (TranslateISOText_t)stub_noop #define stub_GetTextInfo (GetTextInfo_t)stub_noop #define stub_MeasureText (MeasureText_t)stub_noop #define stub_GetEmbedSize (GetEmbedSize_t)stub_noop #define stub_GetJavaAppSize (GetJavaAppSize_t)stub_noop #define stub_GetFormElementInfo (GetFormElementInfo_t)stub_noop #define stub_GetFormElementValue (GetFormElementValue_t)stub_noop #define stub_ResetFormElement (ResetFormElement_t)stub_noop #define stub_SetFormElementToggle (SetFormElementToggle_t)stub_noop #define stub_FreeFormElement (FreeFormElement_t)stub_noop #define stub_FreeImageElement (FreeImageElement_t)stub_noop #define stub_FreeEmbedElement (FreeEmbedElement_t)stub_noop #define stub_FreeBuiltinElement (FreeBuiltinElement_t)stub_noop #define stub_FreeJavaAppElement (FreeJavaAppElement_t)stub_noop #define stub_CreateEmbedWindow (CreateEmbedWindow_t)stub_noop #define stub_SaveEmbedWindow (SaveEmbedWindow_t)stub_noop #define stub_RestoreEmbedWindow (RestoreEmbedWindow_t)stub_noop #define stub_DestroyEmbedWindow (DestroyEmbedWindow_t)stub_noop #define stub_HideJavaAppElement (HideJavaAppElement_t)stub_noop #define stub_FreeEdgeElement (FreeEdgeElement_t)stub_noop #define stub_FormTextIsSubmit (FormTextIsSubmit_t)stub_noop #define stub_DisplaySubtext (DisplaySubtext_t)stub_noop #define stub_DisplayText (DisplayText_t)stub_noop #define stub_DisplayImage (DisplayImage_t)stub_noop #define stub_DisplayEmbed (DisplayEmbed_t)stub_noop #define stub_DisplayBuiltin (DisplayBuiltin_t)stub_noop #define stub_DisplayJavaApp (DisplayJavaApp_t)stub_noop #define stub_DisplaySubImage (DisplaySubImage_t)stub_noop #define stub_DisplayEdge (DisplayEdge_t)stub_noop #define stub_DisplayTable (DisplayTable_t)stub_noop #define stub_DisplayCell (DisplayCell_t)stub_noop #define stub_InvalidateEntireTableOrCell (InvalidateEntireTableOrCell_t)stub_noop #define stub_DisplayAddRowOrColBorder (DisplayAddRowOrColBorder_t)stub_noop #define stub_DisplaySubDoc (DisplaySubDoc_t)stub_noop #define stub_DisplayLineFeed (DisplayLineFeed_t)stub_noop #define stub_DisplayHR (DisplayHR_t)stub_noop #define stub_DisplayBullet (DisplayBullet_t)stub_noop #define stub_DisplayFormElement (DisplayFormElement_t)stub_noop #define stub_DisplayBorder (DisplayBorder_t)stub_noop #define stub_UpdateEnableStates (UpdateEnableStates_t)stub_noop #define stub_DisplayFeedback (DisplayFeedback_t)stub_noop #define stub_ClearView (ClearView_t)stub_noop #define stub_SetDocDimension (SetDocDimension_t)stub_noop #define stub_SetDocPosition (SetDocPosition_t)stub_noop #define stub_GetDocPosition (GetDocPosition_t)stub_noop #define stub_BeginPreSection (BeginPreSection_t)stub_noop #define stub_EndPreSection (EndPreSection_t)stub_noop #define stub_SetProgressBarPercent (SetProgressBarPercent_t)stub_noop #define stub_SetBackgroundColor (SetBackgroundColor_t)stub_noop #define stub_Progress (Progress_t)stub_Progress #define stub_Alert (Alert_t)stub_Alert #define stub_SetCallNetlibAllTheTime (SetCallNetlibAllTheTime_t)stub_noop #define stub_ClearCallNetlibAllTheTime (ClearCallNetlibAllTheTime_t)stub_noop #define stub_GraphProgressInit (GraphProgressInit_t)stub_GraphProgressInit #define stub_GraphProgressDestroy (GraphProgressDestroy_t)stub_GraphProgressDestroy #define stub_GraphProgress (GraphProgress_t)stub_GraphProgress #define stub_UseFancyFTP (UseFancyFTP_t)stub_noop #define stub_UseFancyNewsgroupListing (UseFancyNewsgroupListing_t)stub_noop #define stub_FileSortMethod (FileSortMethod_t)stub_noop #define stub_ShowAllNewsArticles (ShowAllNewsArticles_t)stub_noop #define stub_Confirm (Confirm_t)stub_Confirm #define stub_CheckConfirm (CheckConfirm_t)stub_noop #define stub_SelectDialog (SelectDialog_t)stub_noop #define stub_Prompt (Prompt_t)stub_Prompt #define stub_PromptWithCaption (PromptWithCaption_t)stub_noop #define stub_PromptUsernameAndPassword (PromptUsernameAndPassword_t)stub_PromptUsernameAndPassword #define stub_PromptPassword (PromptPassword_t)stub_PromptPassword #define stub_EnableClicking (EnableClicking_t)stub_noop #define stub_AllConnectionsComplete (AllConnectionsComplete_t)stub_AllConnectionsComplete #define stub_ImageSize (ImageSize_t)stub_noop #define stub_ImageData (ImageData_t)stub_noop #define stub_ImageIcon (ImageIcon_t)stub_noop #define stub_ImageOnScreen (ImageOnScreen_t)stub_noop #define stub_SetColormap (SetColormap_t)stub_noop #ifdef LAYERS #define stub_EraseBackground (EraseBackground_t)stub_noop #define stub_SetDrawable (SetDrawable_t)stub_noop #define stub_GetTextFrame (GetTextFrame_t)stub_noop #define stub_SetClipRegion (SetClipRegion_t)stub_noop #define stub_SetOrigin (SetOrigin_t)stub_noop #define stub_GetOrigin (GetOrigin_t)stub_noop #define stub_GetTextFrame (GetTextFrame_t)stub_noop #endif #define stub_GetDefaultBackgroundColor (GetDefaultBackgroundColor_t)stub_noop #define stub_LoadFontResource (LoadFontResource_t)stub_noop #define stub_DrawJavaApp (DrawJavaApp_t)stub_noop #define stub_HandleClippingView (HandleClippingView_t)stub_noop /* Just reuse the same set of context functions: */ ContextFuncs stub_context_funcs; XP_List *stub_context_list = NULL; MWContext *new_stub_context(URL_Struct *URL_s) { static int funcsInitialized = 0; MWContext *context; if (!funcsInitialized) { #define MAKE_FE_FUNCS_PREFIX(f) stub_##f #define MAKE_FE_FUNCS_ASSIGN stub_context_funcs. #include "mk_cx_fn.h" funcsInitialized = 1; stub_context_list = XP_ListNew(); } context = (MWContext *)calloc(sizeof(struct MWContext_), 1); if (nsnull != context) { context->funcs = &stub_context_funcs; context->type = MWContextBrowser; context->modular_data = URL_s; context->ref_count = 0; if (nsnull != stub_context_list) { XP_ListAddObjectToEnd(stub_context_list, context); } } return context; } void free_stub_context(MWContext *window_id) { TRACEMSG(("Freeing stub context...\n")); if (window_id) { if (stub_context_list) { PRBool result; result = XP_ListRemoveObject(stub_context_list, window_id); PR_ASSERT(PR_TRUE == result); } free(window_id); } } extern "C" MWContext * XP_FindContextOfType (MWContext * context, MWContextType type) { MWContext *window_id; /* * Return the context that was passed in if it is the correct type */ if (nsnull != context) { if (context->type == type) { window_id = context; } } /* * Otherwise, the type MUST be a MWBrowserContext, since that is the * only type of context that is created... * * Return the first stub context, since it is as good as any... :-) */ else if (MWContextBrowser == type) { window_id = (MWContext *)XP_ListTopObject(stub_context_list); } return window_id; } /****************************************************************************/ /* End of MWContext Evil!!! */ /****************************************************************************/ nsConnectionInfo *GetConnectionInfoFromStream(NET_StreamClass *stream) { URL_Struct *URL_s = (URL_Struct *)stream->data_object; return (URL_s) ? (nsConnectionInfo *)URL_s->fe_data : NULL; } /* * Define a NET_StreamClass which pushes its data into an nsIStream * and fires off notifications through the nsIStreamListener interface */ void stub_complete(NET_StreamClass *stream) { URL_Struct *URL_s = (URL_Struct *)stream->data_object; nsConnectionInfo *pConn = GetConnectionInfoFromStream(stream); TRACEMSG(("+++ stream complete.\n")); /* Close the stream and remove it from the ConnectionInfo... */ pConn->pNetStream->Close(); NS_RELEASE(pConn->pNetStream); /* Notify the Data Consumer that the Binding has completed... */ if (pConn->pConsumer) { nsAutoString status; pConn->pConsumer->OnStopBinding(pConn->pURL, NS_BINDING_SUCCEEDED, status); pConn->mStatus = nsConnectionSucceeded; } /* Release the URL_Struct hanging off of the data_object */ stream->data_object = NULL; NET_DropURLStruct(URL_s); } void stub_abort(NET_StreamClass *stream, int status) { URL_Struct *URL_s = (URL_Struct *)stream->data_object; nsConnectionInfo *pConn = GetConnectionInfoFromStream(stream); TRACEMSG(("+++ stream abort. Status = %d\n", status)); /* Close the stream and remove it from the ConnectionInfo... */ pConn->pNetStream->Close(); NS_RELEASE(pConn->pNetStream); /* Notify the Data Consumer that the Binding has completed... */ /* * XXX: Currently, there is no difference between complete and * abort... */ if (pConn->pConsumer) { nsAutoString status; pConn->pConsumer->OnStopBinding(pConn->pURL, NS_BINDING_ABORTED, status); pConn->mStatus = nsConnectionAborted; } /* Release the URL_Struct hanging off of the data_object */ stream->data_object = NULL; NET_DropURLStruct(URL_s); } int stub_put_block(NET_StreamClass *stream, const char *buffer, int32 length) { PRInt32 bytesWritten; nsresult errorCode; nsConnectionInfo *pConn = GetConnectionInfoFromStream(stream); TRACEMSG(("+++ stream put_block. Length = %d\n", length)); /* * XXX: Sometimes put_block(...) will be called without having * called is_write_ready(...) first. One case is when a stream * is interrupted... In this case, Netlib will call put_block(...) * with the string "Transfer Interrupted!" */ errorCode = pConn->pNetStream->Write(buffer, 0, length, &bytesWritten); /* Abort the connection... */ if (NS_BASE_STREAM_EOF == errorCode) { return -1; } if (pConn->pConsumer && (0 < bytesWritten)) { errorCode = pConn->pConsumer->OnDataAvailable(pConn->pURL, pConn->pNetStream, bytesWritten); } /* Abort the connection if an error occurred... */ if (NS_FAILED(errorCode) || (bytesWritten != length)) { return -1; } return 1; } unsigned int stub_is_write_ready(NET_StreamClass *stream) { PRInt32 errorCode; unsigned int free_space = 0; URL_Struct *URL_s = (URL_Struct *)stream->data_object; nsConnectionInfo *pConn = GetConnectionInfoFromStream(stream); free_space = (unsigned int)pConn->pNetStream->GetAvailableSpace(&errorCode); /* * If the InputStream has been closed... Return 1 byte available so * Netlib will call put_block(...) one more time... */ if (NS_BASE_STREAM_EOF == errorCode) { free_space = 1; } TRACEMSG(("+++ stream is_write_ready. Returning %d\n", free_space)); return free_space; } extern "C" { /* *Find a converter routine to create a stream and return the stream struct */ PUBLIC NET_StreamClass * NET_NGLayoutConverter(FO_Present_Types format_out, void *converter_obj, URL_Struct *URL_s, MWContext *context) { NET_StreamClass *stream = NULL; PRBool bSuccess = PR_TRUE; /* * Only create a stream if an nsConnectionInfo object is * available from the fe_data... */ if (NULL != URL_s->fe_data) { stream = (NET_StreamClass *)calloc(sizeof(NET_StreamClass), 1); if (NULL != stream) { nsConnectionInfo *pConn; /* * Initialize the NET_StreamClass instance... */ stream->name = "Stub Stream"; stream->window_id = context; stream->complete = stub_complete; stream->abort = stub_abort; stream->put_block = stub_put_block; stream->is_write_ready = stub_is_write_ready; /* * Retrieve the nsConnectionInfo object from the fe_data field * of the URL_Struct... */ pConn = (nsConnectionInfo *)URL_s->fe_data; /* Mark the connection as active... */ pConn->mStatus = nsConnectionActive; /* * If the URL address has been rewritten by netlib then update * the cached info in the URL object... */ if ((URL_s->address_modified) && (NULL != pConn->pURL)) { pConn->pURL->Set(URL_s->address); } /* * Create an Async stream unless a blocking stream is already * available in the ConnectionInfo... */ if (NULL == pConn->pNetStream) { pConn->pNetStream = new nsAsyncStream(8192); if (NULL == pConn->pNetStream) { free(stream); return NULL; } NS_ADDREF(pConn->pNetStream); } /* Hang the URL_Struct off of the NET_StreamClass */ NET_HoldURLStruct(URL_s); stream->data_object = URL_s; #ifdef NOISY printf("+++ Created a stream for %s\n", URL_s->address); #endif /* Notify the data consumer that Binding is beginning...*/ if (nsnull != pConn->pConsumer) { nsresult rv; rv = pConn->pConsumer->OnStartBinding(pConn->pURL, URL_s->content_type); /* * If OnStartBinding fails, then tear down the NET_StreamClass * and release all references... */ if (NS_OK != rv) { NET_DropURLStruct(URL_s); free(stream); stream = NULL; /* * The NET_GetURL(...) exit_routine will clean up the * nsConnectionInfo and associated objects. */ } } } } return stream; } }; /* extern "C" */