/* -*- Mode: C; tab-width: 4 -*-
*/
#include "mkutils.h"
#include "mkgeturl.h"
#include "shist.h"
#include "mkparse.h"
#include "mkformat.h"
#include "mkhttp.h"
#include "mkftp.h"
#include "mkgopher.h"
#include "mkremote.h"
#include "mknews.h"
#include "mkpop3.h"
#include "mkfile.h"
#include "mksmtp.h"
#include "mkcache.h"
#include "mkmemcac.h"
#include "glhist.h"
#include "mkaccess.h"
#include "mkmailbx.h"
#include "mkautocf.h"
#include "ssl.h"
#include "mktcp.h" /* for NET_InGetHostByName semaphore */
#include "cert.h"
#ifdef MOZILLA_CLIENT
#include "secnav.h"
#ifdef MOCHA
#include "libmocha.h"
#endif
#endif
#include "il.h"
#include "libi18n.h"
#include "xp_sec.h"
#include "mkmocha.h"
#include "htmldlgs.h"
#include "np.h"
#include "prefapi.h"
#include "sslerr.h"
#include "xp_error.h"
#include "merrors.h"
#ifdef EDITOR
#include "edt.h"
#endif
#ifdef MOCHA
#include "libmocha.h"
#endif
#ifdef XP_UNIX
#include "prnetdb.h"
#else
#define PRHostEnt struct hostent
#endif
#include "xplocale.h"
/* for XP_GetString() */
#include "xpgetstr.h"
extern int MK_CONNECTION_REFUSED;
extern int MK_CONNECTION_TIMED_OUT;
extern int MK_MALFORMED_URL_ERROR;
extern int MK_NO_WAIS_PROXY;
extern int MK_OUT_OF_MEMORY;
extern int MK_TIMEBOMB_MESSAGE;
extern int MK_TIMEBOMB_URL_PROHIBIT;
extern int MK_TIMEBOMB_WARNING_MESSAGE;
extern int MK_UNABLE_TO_CONNECT;
extern int MK_UNABLE_TO_CREATE_SOCKET;
extern int MK_UNABLE_TO_LOCATE_HOST;
extern int MK_UNABLE_TO_LOCATE_PROXY;
#ifndef NO_SSL /* added by jwz */
extern int SSL_ERROR_BAD_CERTIFICATE;
#endif /* NO_SSL -- added by jwz */
extern int XP_ALERT_CONNECTION_LESSZERO;
extern int XP_ALERT_INTERRUPT_WINDOW;
extern int XP_ALERT_URLS_LESSZERO;
extern int XP_ALERT_URN_USEHTTP;
extern int XP_CONFIRM_REPOST_FORMDATA;
extern int XP_CONSULT_SYS_ADMIN;
extern int XP_HTML_MISSING_REPLYDATA;
extern int XP_SOCKS_NS_ENV_VAR;
extern int XP_SOME_HOSTS_UNREACHABLE;
extern int XP_THIS_IS_DNS_VERSION;
extern int XP_THIS_IS_YP_VERSION;
extern int XP_UNKNOWN_HOST;
extern int XP_UNKNOWN_HOSTS;
extern int XP_UNKNOWN_HTTP_PROXY;
extern int XP_UNKNOWN_SOCKS_HOST;
extern int XP_URLS_WAITING_FOR_AN_OPEN_SOCKET;
extern int XP_URLS_WAITING_FOR_FEWER_ACTIVE_URLS;
extern int XP_CONNECTIONS_OPEN;
extern int XP_ACTIVE_URLS;
extern int XP_USING_PREVIOUSLY_CACHED_COPY_INSTEAD;
extern int XP_BAD_AUTOCONFIG_NO_FAILOVER;
extern int XP_SOCK_CON_SOCK_PROTOCOL;
extern int XP_URL_NOT_FOUND_IN_CACHE;
extern int XP_PARTIAL_CACHE_ENTRY;
extern int XP_CHECKING_SERVER__FORCE_RELOAD;
extern int XP_OBJECT_HAS_EXPIRED;
extern int XP_CHECKING_SERVER_CACHE_ENTRY;
extern int XP_CHECKING_SERVER__LASTMOD_MISS;
extern int XP_NETSITE_ ;
extern int XP_LOCATION_ ;
extern int XP_FILE_MIME_TYPE_ ;
extern int XP_CURRENTLY_UNKNOWN;
extern int XP_SOURCE_ ;
extern int XP_CURRENTLY_IN_DISK_CACHE ;
extern int XP_CURRENTLY_IN_MEM_CACHE;
extern int XP_CURRENTLY_NO_CACHE ;
extern int XP_LOCAL_CACHE_FILE_ ;
extern int XP_NONE ;
extern int XP_LOCAL_TIME_FMT ;
extern int XP_LAST_MODIFIED ;
extern int XP_GMT_TIME_FMT ;
extern int XP_CONTENT_LENGTH_ ;
extern int XP_NO_DATE_GIVEN;
extern int XP_EXPIRES_ ;
extern int XP_MAC_TYPE_ ;
extern int XP_MAC_CREATOR_ ;
extern int XP_CHARSET_ ;
extern int XP_STATUS_UNKNOWN ;
extern int XP_SECURITY_ ;
extern int XP_CERTIFICATE_ ;
extern int XP_UNTITLED_DOCUMENT ;
extern int XP_HAS_THE_FOLLOWING_STRUCT ;
extern int XP_DOCUMENT_INFO ;
extern int XP_THE_WINDOW_IS_NOW_INACTIVE ;
extern int XP_MSG_UNKNOWN ;
extern int XP_EDIT_NEW_DOC_NAME;
extern int XP_CONFIRM_MAILTO_POST_1;
extern int XP_CONFIRM_MAILTO_POST_2;
extern int XP_CONFIRM_MAILTO_POST_3;
#if defined(JAVA)
#include "nslocks.h"
#include "prlog.h"
#include <stdarg.h>
PRMonitor* libnet_asyncIO;
#if defined(SOLARIS)
extern int gethostname(char *, int);
#endif /* SOLARIS */
/*
** Map netlib trace messages into nspr logger so that they are
** thread safe.
*/
#if defined(DEBUG)
PR_LOG_DEFINE(NETLIB);
PRIVATE
void net_Trace(char *msg)
{
#ifdef XP_WIN32
if(MKLib_trace_flag)
XP_Trace(msg);
#endif
PR_LOG(NETLIB, out, ("libnet: %s", msg));
}
void NET_NTrace(char *msg, int32 length)
{
char * new_string = XP_ALLOC(length+1);
if(!new_string)
return;
strncpy(new_string, msg, length);
new_string[length] = '\0';
net_Trace(new_string);
FREE(new_string);
}
void _MK_TraceMsg(char *fmt, ...)
{
va_list ap;
char buf[200];
va_start(ap, fmt);
PR_vsnprintf(buf, sizeof(buf), fmt, ap);
PR_LOG(NETLIB, out, ("libnet: %s", buf));
}
#endif /* DEBUG */
#endif /* JAVA */
#define LIBNET_UNLOCK_AND_RETURN(value) \
do { int rv = (value); LIBNET_UNLOCK(); return rv; } while (0)
/*
** Don't ever forget about this!!!
**
** Define TIMEBOMB_ON for beta builds.
** Undef TIMEBOMB_ON for release builds.
*/
/* #define TIMEBOMB_ON */
#undef TIMEBOMB_ON
/*
** After this date all hell breaks loose
*/
#define TIME_BOMB_TIME 848131203 /* 11/16/96 + 3 secs */
#define TIME_BOMB_WARNING_TIME 846835203 /* 11/01/96 + 3 secs */
#ifndef XP_UNIX
#ifdef NADA_VERSION
static char *https_security = "SECURITY_VERSION: -https";
#else
static char *https_security = "SECURITY_VERSION: +https";
#endif
#endif
#ifdef EDITOR
/*
* Strings used for new, empty document creation
* Kluge we use to load a new document is resource with one space.
* These strings are loaded from XP_MSG.I on first GetURL call
* (this allows changing "Untitled" for other languages)
*/
PUBLIC char *XP_NEW_DOC_URL = NULL; /* "about:editfilenew" */
/*
* This is the name we want to appear as the URL address
* You can load a new doc using this - it will be changed
* to XP_NEW_DOC_URL.
* When done, XP_NEW_DOC_URL will be changed to XP_NEW_DOC_NAME
*/
PUBLIC char *XP_NEW_DOC_NAME = NULL; /* "Untitled" */
#endif
#ifdef PROFILE
#pragma profile on
#endif
PRIVATE void add_slash_to_URL (URL_Struct *URL_s);
PRIVATE Bool override_proxy (CONST char * URL);
PRIVATE int net_output_about_url(ActiveEntry * this_entry);
PRIVATE int net_output_security_url(ActiveEntry * this_entry, MWContext *cx);
PRIVATE Bool net_about_kludge(URL_Struct *URL_s);
PRIVATE void net_FreeURLAllHeaders(URL_Struct * URL_s);
PRIVATE NET_TimeBombActive = FALSE;
typedef struct _WaitingURLStruct {
int type;
URL_Struct *URL_s;
FO_Present_Types format_out;
MWContext *window_id;
Net_GetUrlExitFunc *exit_routine;
} WaitingURLStruct;
/* Pointers to proxy servers
* They are pointers to a host if
* a proxy environment variable
* was found or they are zero if not.
*/
PRIVATE char * MKftp_proxy=0;
PRIVATE char * MKgopher_proxy=0;
PRIVATE char * MKhttp_proxy=0;
PRIVATE char * MKhttps_proxy=0;
PRIVATE char * MKwais_proxy=0;
PRIVATE char * MKnews_proxy=0;
PRIVATE char * MKno_proxy=0;
PRIVATE char * MKproxy_ac_url=0;
PRIVATE NET_ProxyStyle MKproxy_style = PROXY_STYLE_UNSET;
PRIVATE XP_List * net_EntryList=0;
MODULE_PRIVATE CacheUseEnum NET_CacheUseMethod=CU_CHECK_PER_SESSION;
#define MAX_NUMBER_OF_PROCESSING_URLS 15
#define INITIAL_MAX_ALL_HEADERS 10
#define MULT_ALL_HEADER_COUNT 2
#define MAX_ALL_HEADER_COUNT 16000
MODULE_PRIVATE time_t NET_StartupTime=0;
MODULE_PRIVATE XP_Bool NET_ProxyAcLoaded = FALSE;
MODULE_PRIVATE int NET_TotalNumberOfOpenConnections=0;
MODULE_PRIVATE int NET_MaxNumberOfOpenConnections=100;
MODULE_PRIVATE int NET_MaxNumberOfOpenConnectionsPerContext=4;
MODULE_PRIVATE int NET_TotalNumberOfProcessingURLs=0;
PRIVATE XP_List * net_waiting_for_actives_url_list=0;
PRIVATE XP_List * net_waiting_for_connection_url_list=0;
typedef struct NETExitCallbackNode {
struct NETExitCallbackNode *next;
void *arg;
void (* func)(void *arg);
} NETExitCallbackNode;
PRIVATE NETExitCallbackNode *NETExitCallbackHead = NULL;
PUBLIC void
NET_AddExitCallback( void (* func)(void *arg), void *arg)
{
NETExitCallbackNode *node;
/* alloc node */
node = XP_ALLOC(sizeof(NETExitCallbackNode));
if ( node != NULL ) {
/* fill it in */
node->func = func;
node->arg = arg;
/* link it into the list */
node->next = NETExitCallbackHead;
NETExitCallbackHead = node;
}
return;
}
PRIVATE void
NET_ProcessExitCallbacks(void)
{
NETExitCallbackNode *node, *freenode;
node = NETExitCallbackHead;
while ( node != NULL ) {
(* node->func)(node->arg);
freenode = node;
node = node->next;
XP_FREE(freenode);
}
NETExitCallbackHead = NULL;
return;
}
/* initialize the netlibrary and set the socket buffer size
*/
PUBLIC int
NET_InitNetLib(int socket_buffer_size, int max_number_of_connections)
{
int status;
TRACEMSG(("Initializing Network library"));
NET_StartupTime = time(NULL);
/* seed the random generator
*/
XP_SRANDOM((unsigned int) time(NULL));
if(max_number_of_connections < 1)
max_number_of_connections = 1;
#ifdef XP_UNIX
signal(SIGPIPE, SIG_IGN);
#endif
status = NET_ChangeSocketBufferSize(socket_buffer_size);
NET_ChangeMaxNumberOfConnections(max_number_of_connections);
net_waiting_for_actives_url_list = XP_ListNew();
net_waiting_for_connection_url_list = XP_ListNew();
net_EntryList = XP_ListNew();
#ifdef MOZILLA_CLIENT
NET_ReadCacheFAT("", TRUE);
NET_ReadCookies("");
GH_InitGlobalHistory();
#endif /* MOZILLA_CLIENT */
NET_TotalNumberOfProcessingURLs=0; /* reset */
#ifdef XP_UNIX
{
char *ac_url = getenv("AUTOCONF_URL");
if (ac_url) {
NET_SetProxyServer(PROXY_AUTOCONF_URL, ac_url);
NET_SelectProxyStyle(PROXY_STYLE_AUTOMATIC);
}
}
#endif
#ifdef JAVA
libnet_asyncIO = PR_NewNamedMonitor(0, "libnet");
#endif
return(status);
}
/* set the maximum allowable number of open connections at any one
* time regardless of the context
*/
PUBLIC void
NET_ChangeMaxNumberOfConnections(int max_number_of_connections)
{
/* if already equal return */
if(NET_MaxNumberOfOpenConnections == max_number_of_connections)
return;
if(max_number_of_connections < 1)
max_number_of_connections = 1;
/* make sure that # conns per context is less than or equal
* to this Max
*/
if(NET_MaxNumberOfOpenConnectionsPerContext > max_number_of_connections)
NET_MaxNumberOfOpenConnectionsPerContext = max_number_of_connections;
NET_MaxNumberOfOpenConnections = max_number_of_connections;
/* close any open connections to prevent deadlock
*/
NET_CleanupFTP();
#ifdef MOZILLA_CLIENT
NET_CleanupNews();
#endif /* MOZILLA_CLIENT */
}
/* set the maximum allowable number of open connections at any one
* time Per context
*/
PUBLIC void
NET_ChangeMaxNumberOfConnectionsPerContext(int max_number_of_connections)
{
/* if already equal return */
if(NET_MaxNumberOfOpenConnectionsPerContext == max_number_of_connections)
return;
/* gate the number of max connections to be within 1 and 4
*/
if(max_number_of_connections < 1)
max_number_of_connections = 1;
if(max_number_of_connections > 6)
max_number_of_connections = 6;
NET_MaxNumberOfOpenConnectionsPerContext = max_number_of_connections;
/* close any open connections to prevent deadlock
*/
NET_CleanupFTP();
#ifdef MOZILLA_CLIENT
NET_CleanupNews();
#endif /* MOZILLA_CLIENT */
}
/* check the date and set off the timebomb if necessary
*
* Calls FE_Alert with a message and then disables
* all network calls to hosts not in our domains,
* except for FTP connects.
*/
PUBLIC Bool
NET_CheckForTimeBomb(MWContext *context)
{
#ifdef TIMEBOMB_ON
time_t cur_time;
static Bool done = FALSE;
time_t timebomb_time = TIME_BOMB_TIME;
#ifdef DEBUG
time_t timebomb_warning_time = TIME_BOMB_WARNING_TIME;
#endif
if(done)
return(NET_TimeBombActive);
done = TRUE;
cur_time = XP_TIME();
TRACEMSG(("Timebomb time is: %ld %s", timebomb_time,
ctime(&timebomb_time)));
#ifdef DEBUG
TRACEMSG(("Timebomb warning time is: %ld %s", timebomb_warning_time,
ctime(&timebomb_warning_time)));
#endif
TRACEMSG(("current time is: %ld %s", cur_time,
ctime(&cur_time)));
if(cur_time > TIME_BOMB_TIME)
{
char * alert = NET_ExplainErrorDetails(MK_TIMEBOMB_MESSAGE);
FE_Alert(context, alert);
FREE(alert);
NET_TimeBombActive = TRUE;
return(TRUE);
}
else if(cur_time > TIME_BOMB_WARNING_TIME)
{
char * alert = NET_ExplainErrorDetails( MK_TIMEBOMB_WARNING_MESSAGE,
INTL_ctime(context, &timebomb_time));
FE_Alert(context, alert);
FREE(alert);
NET_TimeBombActive = FALSE;
return(FALSE);
}
#endif /* TIMEBOMB_ON */
return(FALSE);
}
/* set the way the cache should be used
*/
PUBLIC void
NET_SetCacheUseMethod(CacheUseEnum method)
{
NET_CacheUseMethod = method;
}
PRIVATE void
net_CallExitRoutine(Net_GetUrlExitFunc *exit_routine,
URL_Struct *URL_s,
int status,
FO_Present_Types format_out,
MWContext *window_id)
{
#ifdef EDITOR
/* History_entry * his; */
/* Change all references to "about:editfilenew" into "file:///Untitled" */
/* Do this for both Browser and Editor windows */
if( /* EDT_IS_EDITOR(window_id) && */
URL_s && URL_s->address &&
0 == XP_STRCMP(URL_s->address, XP_NEW_DOC_URL) )
{
XP_FREE(URL_s->address);
URL_s->address = XP_STRDUP(XP_NEW_DOC_NAME);
/* Not sure if this is the best place to do this,
* but it needs to go someplace!
*/
LO_SetBaseURL(window_id, XP_NEW_DOC_NAME);
/* Setting context title to NULL will trigger
* Windows front end to use the URL address and set
* doc and window title to "Untitled"
* Do all front ends do this?
* If not, they will have to use EDT_IS_NEW_DOCUMENT
* to test for new doc and update title (in exit_routine)
*/
if ( window_id->title ) {
XP_FREE(window_id->title);
window_id->title = NULL;
}
/* Note: We replace "about:editfilenew" with "file:///Untitled"
* in SHIST_AddDocument(), so we don't need to mess with
* History data here.
*/
/* Set window_id->is_new_document flag appropriately
* This flag allows quicker response for often-called
* status queries at front end
*/
if ( EDT_IS_EDITOR(window_id) ) {
EDT_NEW_DOCUMENT(window_id, TRUE);
}
}
#endif /* EDITOR */
#if defined(XP_WIN) || defined (XP_MAC)
FE_URLEcho(URL_s, status, window_id);
#endif /* XP_WIN/MAC */
if (!URL_s->load_background)
FE_EnableClicking(window_id);
#ifdef MOZILLA_CLIENT
if(URL_s->refresh_url && status != MK_INTERRUPTED)
FE_SetRefreshURLTimer(window_id, URL_s->refresh, URL_s->refresh_url);
#endif /* MOZILLA_CLIENT */
if (URL_s->pre_exit_fn)
{
Net_GetUrlExitFunc *per = URL_s->pre_exit_fn;
URL_s->pre_exit_fn = 0;
(*per) (URL_s, status, window_id);
}
(*exit_routine) (URL_s, status, window_id);
#ifdef MOZILLA_CLIENT
#ifdef EDITOR
#ifdef XP_MAC
/* If URL is not loaded correctly at startup,
* there is no history entry to fall back on,
* so editor doesn't have a document, which is very very bad!
* Load our "new document" if this happens
*/
if( EDT_IS_EDITOR(window_id) &&
status < 0 )
{
History_entry * his = SHIST_GetCurrent(&window_id->hist);
if ( his == NULL || his->address == NULL ) {
URL_Struct *pNewDocURL = NET_CreateURLStruct (XP_NEW_DOC_URL, NET_NORMAL_RELOAD );
NET_GetURL (pNewDocURL, FO_CACHE_AND_PRESENT, window_id, exit_routine);
}
}
#endif /* XP_MAC */
#endif /* EDITOR */
#endif /* MOZILLA_CLIENT */
}
PRIVATE XP_Bool
net_does_url_require_socket_limit(int url_type)
{
if( url_type == HTTP_TYPE_URL
|| url_type == SECURE_HTTP_TYPE_URL
|| url_type == FTP_TYPE_URL
|| url_type == NEWS_TYPE_URL
|| url_type == GOPHER_TYPE_URL)
return TRUE;
return(FALSE);
}
PRIVATE XP_Bool
net_is_one_url_allowed_to_run(MWContext *context, int url_type)
{
/* put a limit on the total number of open connections
*/
if(NET_TotalNumberOfOpenConnections < NET_MaxNumberOfOpenConnectionsPerContext
|| !net_does_url_require_socket_limit(url_type))
{
return(TRUE);
}
else if(NET_TotalNumberOfOpenConnections >= NET_MaxNumberOfOpenConnections)
{
return(FALSE);
}
else
{
XP_List * list_ptr;
ActiveEntry * tmpEntry;
int32 cur_win_id = FE_GetContextID(context);
int real_number_of_connections = 0;
/* run through the list of running URLs and check
* for open connections only for this context.
* This will allow for the Total number of open
* connections to only apply to each window not
* to the whole program
*/
list_ptr = net_EntryList;
while((tmpEntry = (ActiveEntry *) XP_ListNextObject(list_ptr)) != NULL)
{
if(cur_win_id == FE_GetContextID(tmpEntry->window_id)
&& net_does_url_require_socket_limit(url_type))
{
real_number_of_connections++;
}
} /* end while */
/* pause it if the number of connections per context
* is higher than the per context limit or
*/
if(real_number_of_connections >= NET_MaxNumberOfOpenConnectionsPerContext)
{
return(FALSE);
}
}
return(TRUE);
}
static int
net_push_url_on_wait_queue(int url_type,
URL_Struct *URL_s,
FO_Present_Types format_out,
MWContext *context,
Net_GetUrlExitFunc exit_routine)
{
WaitingURLStruct * wus = XP_NEW(WaitingURLStruct);
TRACEMSG(("Pushing URL on wait queue with %d open connections",
NET_TotalNumberOfOpenConnections ));
if(!wus)
{
net_CallExitRoutine(exit_routine,
URL_s,
MK_OUT_OF_MEMORY,
format_out,
context);
return(MK_OUT_OF_MEMORY);
}
wus->type = url_type;
wus->URL_s = URL_s;
wus->format_out = format_out;
wus->window_id = context;
wus->exit_routine = exit_routine;
/* add "text/ *" to beginning of list so it gets processed first */
if (CLEAR_CACHE_BIT(format_out) == FO_INTERNAL_IMAGE)
/* low priority */
XP_ListAddObjectToEnd(net_waiting_for_connection_url_list, wus);
else
/* higher priority */
XP_ListAddObject(net_waiting_for_connection_url_list, wus);
return(0);
}
/* returns a malloc'd string that has a bunch of netlib
* status info in it.
*
* please free the pointer when done.
*/
PUBLIC char *
NET_PrintNetlibStatus()
{
char small_buf[128];
XP_List * list_ptr;
ActiveEntry *tmpEntry;
char *rv=0;
LIBNET_LOCK();
list_ptr = net_EntryList;
sprintf(small_buf, XP_GetString( XP_URLS_WAITING_FOR_AN_OPEN_SOCKET ),
XP_ListCount(net_waiting_for_connection_url_list),
NET_MaxNumberOfOpenConnectionsPerContext);
StrAllocCat(rv, small_buf);
sprintf(small_buf, XP_GetString( XP_URLS_WAITING_FOR_FEWER_ACTIVE_URLS ),
XP_ListCount(net_waiting_for_actives_url_list));
StrAllocCat(rv, small_buf);
sprintf(small_buf, XP_GetString( XP_CONNECTIONS_OPEN ),
NET_TotalNumberOfOpenConnections);
StrAllocCat(rv, small_buf);
sprintf(small_buf, XP_GetString( XP_ACTIVE_URLS ),
NET_TotalNumberOfProcessingURLs);
StrAllocCat(rv, small_buf);
while((tmpEntry = (ActiveEntry *)XP_ListNextObject(list_ptr)) != 0)
{
sprintf(small_buf, "------------------------------------\nURL:");
StrAllocCat(rv, small_buf);
StrAllocCat(rv, tmpEntry->URL_s->address);
StrAllocCat(rv, "\n");
sprintf(small_buf, XP_GetString(XP_SOCK_CON_SOCK_PROTOCOL),
tmpEntry->socket, tmpEntry->con_sock, tmpEntry->protocol);
StrAllocCat(rv, small_buf);
}
#if defined(DEBUG) && defined(JAVA)
{
static int loggingOn = 0;
NETLIBLog.level = (loggingOn ? PRLogLevel_none : PRLogLevel_debug);
NETLIBLog.depth = 0; /* keep it from auto-initializing */
loggingOn = !loggingOn;
}
#endif /* defined(DEBUG) && defined(JAVA) */
LIBNET_UNLOCK();
return(rv);
}
PRIVATE void
net_release_urls_for_processing(XP_Bool release_prefered)
{
XP_List * list_ptr = net_waiting_for_connection_url_list;
WaitingURLStruct * wus;
while((wus = (WaitingURLStruct *)
XP_ListNextObject(list_ptr)) != NULL)
{
if(!release_prefered
|| ( (wus->format_out != FO_INTERNAL_IMAGE
&& wus->format_out != FO_CACHE_AND_INTERNAL_IMAGE)
#ifdef MOZILLA_CLIENT
|| IL_PreferredStream(wus->URL_s) ) )
#else
) )
#endif /* MOZILLA_CLIENT */
{
XP_ListRemoveObject(net_waiting_for_connection_url_list, wus);
NET_GetURL(wus->URL_s,
wus->format_out,
wus->window_id,
wus->exit_routine);
FREE(wus);
break;
}
}
}
/*
* Must be called under the cover of the LIBNET_LOCK!
*
* The was_background parameter is used to determine when to call
* FE_AllConnectionsComplete. It should only be called if we've just
* completed processing a URL that's *not* a background loading URL.
* A background URL is one that loads without UI activity e.g. no
* status bar and thermo activity.
* This ensures that looping animations don't call
* FE_AllConnectionsComplete on every loop cycle.
*/
PRIVATE void
net_CheckForWaitingURL(MWContext * window_id, int protocol, Bool was_background)
{
#ifdef NSPR
XP_ASSERT(LIBNET_IS_LOCKED());
#endif
/* decrement here since this function is called
* after every exit_routine
*/
NET_TotalNumberOfProcessingURLs--;
if(NET_TotalNumberOfProcessingURLs < 0)
{
FE_Alert(window_id, XP_GetString(XP_ALERT_URLS_LESSZERO));
NET_TotalNumberOfProcessingURLs = 0;
}
if(NET_TotalNumberOfOpenConnections < 0)
{
FE_Alert(window_id, XP_GetString(XP_ALERT_CONNECTION_LESSZERO));
NET_TotalNumberOfOpenConnections = 0;
}
TRACEMSG(("In: net_CheckForWaitingURL with %d connection waiting URL's, %d active waiting URL's and %d open connections",
XP_ListCount(net_waiting_for_connection_url_list),
XP_ListCount(net_waiting_for_actives_url_list),
NET_TotalNumberOfOpenConnections));
/* release preferred streams first */
net_release_urls_for_processing(TRUE);
/* release non-prefered streams */
net_release_urls_for_processing(FALSE);
if(!NET_AreThereActiveConnectionsForWindow(window_id) &&
!was_background)
{
#ifdef MOCHA
LM_SendLoadEvent(window_id, LM_XFER_DONE);
#endif
FE_AllConnectionsComplete(window_id);
}
}
PRIVATE int
net_AbortWaitingURL(MWContext * window_id, Bool all, XP_List *list)
{
XP_List * list_ptr = list->next;
XP_List * prev_list_ptr = list;
XP_List * tmp_list_ptr;
WaitingURLStruct * wus;
int32 cur_win_id;
int number_killed = 0;
if(!all && window_id)
cur_win_id = FE_GetContextID(window_id);
while(list_ptr)
{
wus = (WaitingURLStruct *)list_ptr->object;
if(all || (window_id && cur_win_id == FE_GetContextID(wus->window_id)))
{
TRACEMSG(("killing waiting URL"));
/* call exit routine since we are done */
net_CallExitRoutine(wus->exit_routine,
wus->URL_s,
MK_INTERRUPTED,
wus->format_out,
wus->window_id);
number_killed += 1;
tmp_list_ptr = list_ptr;
list_ptr = list_ptr->next;
/* remove the element from the list
*
* we have to use the function since it does
* funky doubly linked list shit.
*/
XP_ListRemoveObject(list, wus);
FREE(wus);
}
else
{
prev_list_ptr = list_ptr;
list_ptr = list_ptr->next;
}
}
return(number_killed);
}
/* Helper function for NET_SanityCheckDNS() */
PRIVATE Bool
net_IsHostResolvable (CONST char *hostname, MWContext *context)
{
#ifdef XP_UNIX
int rv;
PRHostEnt hpbuf;
char dbbuf[PR_NETDB_BUF_SIZE];
rv = (PR_gethostbyname(hostname, &hpbuf, dbbuf, sizeof(dbbuf), 0)
? TRUE : FALSE);
return rv;
#else
return(FALSE);
#endif
}
#if defined(__sun) && !defined(__svr4__)
/* From xfe/dns-stub.o or xfe/nis-stub.o, depending. Gag. */
extern int fe_HaveDNS;
#endif
PUBLIC void
NET_SanityCheckDNS (MWContext *context)
{
#ifdef XP_UNIX
char *proxy = MKhttp_proxy;
char *socks = NET_SocksHostName;
char *test_host_1 = "home.netscape.com";
char *test_host_2 = "home6.netscape.com";
char *test_host_3 = "internic.net";
char *message;
#if defined(__sun) && !defined(__svr4__)
char temp[1000];
#endif
static Bool done;
if (done) return;
done = TRUE;
message = (char *) XP_ALLOC (3000);
if (! message)
return;
*message = 0;
if (proxy)
proxy = XP_STRDUP (proxy);
if (socks)
socks = XP_STRDUP (socks);
/* Strip off everything after last colon. */
{
char *s;
if (proxy && (s = XP_STRRCHR (proxy, ':')))
*s = 0;
if (socks && (s = XP_STRRCHR (socks, ':')))
*s = 0;
}
if (proxy)
proxy = XP_StripLine (proxy); /* in case it was "hostname: 80" */
if (socks)
socks = XP_StripLine (socks);
/* If the hosts are specified as IP numbers, don't try and resolve them.
(Yes, hostnames can't begin with digits.) */
if (proxy && proxy[0] >= '0' && proxy[0] <= '9')
XP_FREE (proxy), proxy = 0;
if (socks && socks[0] >= '0' && socks[0] <= '9')
XP_FREE (socks), socks = 0;
if (proxy && *proxy)
{
/* If there is an HTTP proxy, then we shouldn't try to resolve any
other hosts at all, because they might legitimately be unresolvable.
The HTTP proxy will do all lookups.
*/
if (!net_IsHostResolvable (proxy, context))
{
sprintf(message, XP_GetString(XP_UNKNOWN_HTTP_PROXY), proxy);
}
}
else
{
/* There is not an HTTP proxy specified. So check the other hosts.
*/
if (socks && *socks && !net_IsHostResolvable (socks, context))
{
sprintf(message, XP_GetString(XP_UNKNOWN_SOCKS_HOST), socks);
#ifdef XP_UNIX
XP_STRCAT (message, XP_GetString(XP_SOCKS_NS_ENV_VAR));
/* Only Unix has the $SOCKS_NS environment variable. */
#endif /* XP_UNIX */
XP_STRCAT (message, XP_GetString(XP_CONSULT_SYS_ADMIN));
}
else
{
/* At this point, we're not using a proxy, and either we're not
using a SOCKS host or we're using a resolvable SOCKS host.
So that means that all the usual host names should be resolvable,
and the world is broken if they're not.
*/
char *losers [10];
int loser_count = 0;
#ifdef XP_UNIX
char local [255], *local2;
PRHostEnt *hent, hpbuf;
char dbbuf[PR_NETDB_BUF_SIZE];
if (gethostname (local, sizeof (local) - 1))
local [0] = 0;
/* gethostname() and gethostbyname() often return different data -
on many systems, the former is basename, the latter is FQDN. */
if (local &&
(hent = PR_gethostbyname (local, &hpbuf, dbbuf, sizeof(dbbuf), 0)) &&
XP_STRCMP (local, hent->h_name))
local2 = XP_STRDUP (hent->h_name);
else
local2 = 0;
if (local && *local && !net_IsHostResolvable (local, context))
losers [loser_count++] = local;
if (local2 && *local2 && !net_IsHostResolvable (local2, context))
losers [loser_count++] = local2;
#endif /* XP_UNIX */
if (!net_IsHostResolvable (test_host_1, context))
losers [loser_count++] = test_host_1;
if (!net_IsHostResolvable (test_host_2, context))
losers [loser_count++] = test_host_2;
if (!net_IsHostResolvable (test_host_3, context))
losers [loser_count++] = test_host_3;
if (loser_count > 0)
{
if (loser_count > 1)
{
int i;
sprintf(message, XP_GetString(XP_UNKNOWN_HOSTS));
for (i = 0; i < loser_count; i++)
{
XP_STRCAT (message, " ");
XP_STRCAT (message, losers [i]);
XP_STRCAT (message, "\n");
}
}
else
{
sprintf(message, XP_GetString(XP_UNKNOWN_HOST), losers[0]);
}
XP_STRCAT (message, XP_GetString(XP_SOME_HOSTS_UNREACHABLE));
#ifdef XP_UNIX
# if defined(__sun) && !defined(__svr4__) /* compiled on SunOS 4.1.3 */
if (fe_HaveDNS)
/* Don't talk about $SOCKS_NS in the YP/NIS version. */
# endif
XP_STRCAT (message, XP_GetString(XP_SOCKS_NS_ENV_VAR));
#if defined(__sun) && !defined(__svr4__) /* compiled on SunOS 4.1.3 */
assert (XP_AppName);
if (fe_HaveDNS)
{
sprintf(temp, XP_GetString(XP_THIS_IS_DNS_VERSION),
XP_AppName);
}
else
{
sprintf(temp, XP_GetString(XP_THIS_IS_YP_VERSION),
XP_AppName);
}
XP_STRCAT(message, temp);
# endif /* SunOS 4.* */
#endif /* XP_UNIX */
XP_STRCAT (message, XP_GetString(XP_CONSULT_SYS_ADMIN));
}
#ifdef XP_UNIX
if (local2) XP_FREE (local2);
#endif /* XP_UNIX */
}
}
if (proxy) XP_FREE (proxy);
if (socks) XP_FREE (socks);
if (*message)
FE_Alert (context, message);
XP_FREE (message);
#endif /* XP_UNIX full function wrap */
}
/* shutdown the netlibrary, cancel all
* conections and free all
* memory
*/
PUBLIC void
NET_ShutdownNetLib(void)
{
ActiveEntry *tmpEntry;
#ifdef XP_WIN32
if (libnet_asyncIO) LIBNET_LOCK();
#else
LIBNET_LOCK();
#endif
if(net_waiting_for_actives_url_list) {
net_AbortWaitingURL(0, TRUE, net_waiting_for_actives_url_list);
XP_ListDestroy(net_waiting_for_actives_url_list);
net_waiting_for_actives_url_list = 0;
}
if(net_waiting_for_connection_url_list) {
net_AbortWaitingURL(0, TRUE, net_waiting_for_connection_url_list);
XP_ListDestroy(net_waiting_for_connection_url_list);
net_waiting_for_connection_url_list = 0;
}
/* run through list of
* connections
*/
while((tmpEntry = (ActiveEntry *)XP_ListRemoveTopObject(net_EntryList)) != 0)
{
switch(tmpEntry->protocol)
{
#ifdef MOZILLA_CLIENT
case MEMORY_CACHE_TYPE_URL:
NET_InterruptMemoryCache(tmpEntry);
break;
case MAILTO_TYPE_URL:
NET_InterruptMailto(tmpEntry);
break;
case POP3_TYPE_URL:
NET_InterruptPop3(tmpEntry);
break;
case MAILBOX_TYPE_URL:
NET_InterruptMailbox(tmpEntry);
break;
#endif /* MOZILLA_CLIENT */
case HTTP_TYPE_URL:
case SECURE_HTTP_TYPE_URL:
NET_InterruptHTTP(tmpEntry);
break;
case GOPHER_TYPE_URL:
NET_InterruptGopher(tmpEntry);
break;
case FTP_TYPE_URL:
NET_InterruptFTP(tmpEntry);
break;
#ifdef MOZILLA_CLIENT
case NEWS_TYPE_URL:
case INTERNAL_NEWS_TYPE_URL:
NET_InterruptNews(tmpEntry);
break;
case FILE_TYPE_URL:
case FILE_CACHE_TYPE_URL:
NET_InterruptFile(tmpEntry);
#endif /* MOZILLA_CLIENT */
} /* end switch */
TRACEMSG(("End of transfer, entry (soc=%d, con=%d) being removed from list with %d status: %s",
tmpEntry->socket, tmpEntry->con_sock, tmpEntry->status, tmpEntry->URL_s->address));
/* call exit routine since we know we are done */
net_CallExitRoutine(tmpEntry->exit_routine,
tmpEntry->URL_s,
tmpEntry->status,
tmpEntry->format_out,
tmpEntry->window_id);
XP_FREE(tmpEntry); /* free the no longer active entry */
}
XP_ListDestroy(net_EntryList);
net_EntryList = 0;
/* free any memory in the protocol modules
*/
NET_CleanupHTTP();
NET_CleanupGopher();
NET_CleanupFTP();
#ifdef MOZILLA_CLIENT
NET_CleanupNews();
NET_CleanupFile();
NET_CleanupMailto();
NET_SaveCookies("");
GH_SaveGlobalHistory();
#endif /* MOZILLA_CLIENT */
/* purge existing cache files */
/* free memory in the tcp routines
*/
NET_CleanupTCP();
#ifdef MOZILLA_CLIENT
NET_CleanupCache("");
NET_SetMemoryCacheSize(0); /* free memory cache */
#endif /* MOZILLA_CLIENT */
#ifdef XP_UNIX
NET_CleanupFileFormat(NULL);
#else
NET_CleanupFileFormat();
#endif
#ifdef XP_WIN32
if (libnet_asyncIO) LIBNET_UNLOCK();
#else
LIBNET_UNLOCK();
#endif
}
static PRBool warn_on_mailto_post = PR_TRUE;
extern void
NET_WarnOnMailtoPost(PRBool warn)
{
warn_on_mailto_post = warn;
return;
}
/* register and begin a transfer.
*
* returns negative if the transfer errored or finished during the call
* otherwise returns 0 or greater.
*
* A URL, an output format, a window context pointer, and a callback routine
* should be passed in.
*/
PUBLIC int
NET_GetURL (URL_Struct *URL_s,
FO_Present_Types output_format,
MWContext *window_id,
Net_GetUrlExitFunc* exit_routine)
{
int status=MK_MALFORMED_URL_ERROR;
int pacf_status=TRUE;
int type;
int cache_method=0;
ActiveEntry *this_entry=0; /* a new entry */
char *new_address;
char *colon;
int processcallbacks = 0;
Bool confirm;
Bool load_background;
char *confirmstring;
TRACEMSG(("Entering NET_GetURL"));
LIBNET_LOCK();
XP_ASSERT (URL_s && URL_s->address);
#ifdef MOZILLA_CLIENT
if ( URL_s->mailto_post && warn_on_mailto_post) {
confirmstring = NULL;
confirm = FALSE;
StrAllocCopy(confirmstring, XP_GetString(XP_CONFIRM_MAILTO_POST_1));
StrAllocCat(confirmstring, XP_GetString(XP_CONFIRM_MAILTO_POST_2));
StrAllocCat(confirmstring, XP_GetString(XP_CONFIRM_MAILTO_POST_3));
if ( confirmstring ) {
confirm = FE_Confirm(window_id, confirmstring);
XP_FREE(confirmstring);
}
if ( !confirm ) {
/* abort url
*/
net_CallExitRoutine(exit_routine,
URL_s,
MK_INTERRUPTED,
output_format,
window_id);
LIBNET_UNLOCK_AND_RETURN(MK_INTERRUPTED);
}
}
#endif /* MOZILLA_CLIENT */
#ifdef EDITOR
/* First time here - get our strings out of XP_MSG.I */
if (XP_NEW_DOC_URL == NULL) {
StrAllocCopy(XP_NEW_DOC_URL, "about:editfilenew");
/* Added strings to allxpstr.h and sllxpstr.rc,
but still get "undefined" WHERE ARE MSG IDs DEFINED? */
/* StrAllocCopy(XP_NEW_DOC_URL, XP_GetString(XP_EDIT_NEW_DOC_URL) ); */
}
if (XP_NEW_DOC_NAME == NULL) {
/* StrAllocCopy(XP_NEW_DOC_NAME, "file:///Untitled" ); */
StrAllocCopy(XP_NEW_DOC_NAME, XP_GetString(XP_EDIT_NEW_DOC_NAME) );
}
/* Test for "Untitled" URL */
if( 0 == XP_STRCMP(URL_s->address, XP_NEW_DOC_NAME) ) {
/* if ( EDT_IS_EDITOR(window_id) ) { */
/* Change request to load "file:///Untitled" into "about:editfilenew" */
XP_FREE(URL_s->address);
URL_s->address = XP_STRDUP(XP_NEW_DOC_URL);
/* Set flag so FE can quickly detect new doc */
window_id->is_new_document = TRUE;
/* } */
}
else if( 0 == XP_STRCMP(URL_s->address, XP_NEW_DOC_URL) ) {
window_id->is_new_document = TRUE;
}
#endif
#ifdef MOZILLA_CLIENT
if (MKproxy_ac_url && !NET_ProxyAcLoaded &&
(!MKproxy_style || MKproxy_style == PROXY_STYLE_AUTOMATIC) &&
(!(type = NET_URL_Type(URL_s->address))
|| type == HTTP_TYPE_URL
|| type == SECURE_HTTP_TYPE_URL
|| type == GOPHER_TYPE_URL
|| type == FTP_TYPE_URL
|| type == FILE_TYPE_URL
|| type == WAIS_TYPE_URL
|| type == URN_TYPE_URL
|| (type == NEWS_TYPE_URL && !strncasecomp(URL_s->address, "snews:", 6)))) {
int status;
NET_ProxyAcLoaded = TRUE;
status = NET_LoadProxyConfig(MKproxy_ac_url,
URL_s, output_format, window_id,
exit_routine);
if (status != -1) {
/*
* Proxy autoconf load started -- the originally
* requested URL will be loaded by the pre_exit_fn()
* in the proxy autoconf URL_Struct.
*
*/
LIBNET_UNLOCK_AND_RETURN(status);
}
/* else no proxy autoconfig -- continue normally */
}
#endif /* MOZILLA_CLIENT */
if(!URL_s || !URL_s->address || !*URL_s->address
#if defined MOZILLA_CLIENT && defined MOCHA
|| !LM_CheckGetURL(window_id, URL_s)
#endif
)
{
/* we need at least an address
* if we don't have it exit this routine
*/
net_CallExitRoutine(exit_routine,
URL_s,
MK_MALFORMED_URL_ERROR,
output_format,
window_id);
/* increment since it will get decremented */
NET_TotalNumberOfProcessingURLs++;
net_CheckForWaitingURL(window_id, 0, FALSE);
LIBNET_UNLOCK_AND_RETURN(MK_MALFORMED_URL_ERROR);
}
load_background = URL_s->load_background;
/* kill leading and trailing spaces in the URL address
*/
new_address = XP_StripLine(URL_s->address);
if(new_address != URL_s->address)
{
XP_MEMMOVE(URL_s->address, new_address, XP_STRLEN(new_address)+1);
}
/* get the protocol type
*/
type = NET_URL_Type(URL_s->address);
if (URL_s->method == URL_HEAD_METHOD &&
type != HTTP_TYPE_URL && type != SECURE_HTTP_TYPE_URL && type != FILE_TYPE_URL) {
/* We can only do HEAD on http connections. */
net_CallExitRoutine(exit_routine,
URL_s,
MK_MALFORMED_URL_ERROR, /* Is this right? ### */
output_format,
window_id);
/* increment since it will get decremented */
NET_TotalNumberOfProcessingURLs++;
net_CheckForWaitingURL(window_id, 0, load_background);
LIBNET_UNLOCK_AND_RETURN(MK_MALFORMED_URL_ERROR);
}
TRACEMSG(("Called NET_GetURL with FO: %d URL %.5000s ---------------------------", output_format, URL_s->address));
TRACEMSG(("with method: %d, and post headers: %s", URL_s->method,
URL_s->post_headers ? URL_s->post_headers : "none"));
/* put a limit on the total number of active urls
*/
if((NET_TotalNumberOfProcessingURLs >= MAX_NUMBER_OF_PROCESSING_URLS) &&
((output_format & FO_ONLY_FROM_CACHE) == 0))
{
LIBNET_UNLOCK_AND_RETURN(net_push_url_on_wait_queue(type,
URL_s,
output_format,
window_id,
exit_routine));
}
/* if we get this far then we should add the URL
* to the number of processing URL's
*/
NET_TotalNumberOfProcessingURLs++;
if(type == VIEW_SOURCE_TYPE_URL)
{
/* this is a view-source: URL
* strip off the front stuff
*/
char *new_address=0;
/* the colon is guarenteed to be there */
StrAllocCopy(new_address, XP_STRCHR(URL_s->address, ':')+1);
FREE(URL_s->address);
URL_s->address = new_address;
type = NET_URL_Type(URL_s->address);
/* remap the format out for the fo_present type
*/
if(CLEAR_CACHE_BIT(output_format) == FO_PRESENT)
output_format = FO_VIEW_SOURCE;
}
#ifdef MOZILLA_CLIENT
if(
#if defined(XP_WIN) || defined(XP_MAC)
FE_UseExternalProtocolModule(window_id, output_format, URL_s, exit_routine) ||
#endif
NPL_HandleURL(window_id, output_format, URL_s, exit_routine))
{
/* don't call the exit routine since the
* External protocol module will call it
*/
net_CheckForWaitingURL(window_id, 0, load_background);
LIBNET_UNLOCK_AND_RETURN(-1); /* all done */
}
if(NET_TimeBombActive)
{
/* Timebomb has gone off!!
*
* limit URL's to FTP and anything in our domains
*/
if(type != FTP_TYPE_URL
&& type != ABOUT_TYPE_URL
&& type != FILE_TYPE_URL
&& type != MAILBOX_TYPE_URL
&& type != POP3_TYPE_URL
&& type != MOCHA_TYPE_URL
&& !strcasestr(URL_s->address, "mcom.com")
&& !strcasestr(URL_s->address, "netscape.com"))
{
char * alert = NET_ExplainErrorDetails(MK_TIMEBOMB_URL_PROHIBIT);
FE_Alert(window_id, alert);
FREE(alert);
/* we need at least an address
* if we don't have it exit this routine
*/
net_CallExitRoutine(exit_routine,
URL_s,
MK_TIMEBOMB_URL_PROHIBIT,
output_format,
window_id);
net_CheckForWaitingURL(window_id, 0, load_background);
LIBNET_UNLOCK_AND_RETURN(MK_TIMEBOMB_URL_PROHIBIT);
}
}
/* put up security dialog boxes to tell the user
* about transitions
*
* only do this for FO_PRESENT objects and objects
* not coming out of history
* and also make sure that the object is not being asked
* for twice via the "304 use local copy" method
*/
if(output_format == FO_CACHE_AND_PRESENT
&& !URL_s->history_num
&& !URL_s->use_local_copy)
{
Bool continue_loading_url = TRUE;
History_entry * h = SHIST_GetCurrent(&window_id->hist);
/* this is some protection against the "mail document"
* feature popping up a dialog warning about an insecure
* post.
* If the type is MAILTO and the first post header
* begins with "Content-type" then it is a post from
* inside a form, otherwise it is just a normal MAILTO
*
* And, of course, anything not a MAILTO link will fall
* into the if as well.
*/
if(type != MAILTO_TYPE_URL
|| !URL_s->post_headers
|| !XP_STRNCMP("Content-type", URL_s->post_headers, 12))
{
#ifndef NO_SSL /* added by jwz */
if(h && h->security_on)
{
/* if this is not a secure transaction */
if(type != SECURE_HTTP_TYPE_URL
&& !(type == NEWS_TYPE_URL &&
toupper(*URL_s->address) == 'S') )
{
if(URL_s->method == URL_POST_METHOD)
{
continue_loading_url = (Bool)SECNAV_SecurityDialog(window_id,
SD_INSECURE_POST_FROM_SECURE_DOC);
}
else if(!URL_s->redirecting_url
&& type != MAILTO_TYPE_URL
&& type != ABOUT_TYPE_URL
&& type != MOCHA_TYPE_URL)
{
/* don't put up in case of redirect or mocha
*/
continue_loading_url = (Bool)SECNAV_SecurityDialog(window_id,
SD_LEAVING_SECURE_SPACE);
}
}
}
else
#endif /* NO_SSL -- added by jwz */
{
/* put up a dialog for all insecure posts
* except news and mail posts
*/
if(URL_s->method == URL_POST_METHOD
&& type != SECURE_HTTP_TYPE_URL
&& type != INTERNAL_NEWS_TYPE_URL
&& type != NEWS_TYPE_URL
&& type != HTML_DIALOG_HANDLER_TYPE_URL
&& type != HTML_PANEL_HANDLER_TYPE_URL
&& type != INTERNAL_SECLIB_TYPE_URL
&& type != MAILTO_TYPE_URL)
{
#ifndef NO_SSL /* added by jwz */
continue_loading_url = (Bool)SECNAV_SecurityDialog(window_id,
SD_INSECURE_POST_FROM_INSECURE_DOC);
#else
continue_loading_url = TRUE; /* #### ???? */
#endif /* NO_SSL -- added by jwz */
}
}
if(!continue_loading_url)
{
/* abort url
*/
net_CallExitRoutine(exit_routine,
URL_s,
MK_INTERRUPTED,
output_format,
window_id);
net_CheckForWaitingURL(window_id, 0, load_background);
LIBNET_UNLOCK_AND_RETURN(MK_INTERRUPTED);
}
}
}
#endif /* MOZILLA_CLIENT */
/*
* if the string is not a valid URL we are just going
* to punt, so we may as well try it as http
*
* if the address has a colon not followed by a digit then
* don't do this. This prevents things like Ftp://test
* from getting treated badly
*/
if(type==0 && URL_s->address &&
(!(colon = strrchr(URL_s->address, ':')) || isdigit(*(colon+1))) )
{
char *munged;
#define INT_SEARCH_URL "http://cgi.netscape.com/cgi-bin/url_search.cgi?search="
#define INT_SEARCH_URL_TYPE HTTP_TYPE_URL
if(!(munged = (char*) XP_ALLOC(XP_STRLEN(URL_s->address)+20)))
{
net_CallExitRoutine(exit_routine,
URL_s,
MK_OUT_OF_MEMORY,
output_format,
window_id);
LIBNET_UNLOCK_AND_RETURN(MK_OUT_OF_MEMORY);
}
#ifdef URL_SEARCH_FEATURE
if(XP_STRCHR(URL_s->address, ' '))
{
/* URL contains spaces. Treat it as search text. */
char *escaped = NET_Escape(URL_s->address, URL_XPALPHAS);
if(escaped)
{
FREE(munged);
munged = PR_smprintf("%s%s", INT_SEARCH_URL, escaped);
FREE(escaped);
type = INT_SEARCH_URL_TYPE;
}
}
else
#endif /* URL_SEARCH_FEATURE */
{
if(*URL_s->address == '/')
{
XP_STRCPY(munged, "file:");
type = FILE_TYPE_URL;
}
else if(!strncasecomp(URL_s->address, "ftp", 3))
{
XP_STRCPY(munged, "ftp://");
type = FTP_TYPE_URL;
}
else if(!strncasecomp(URL_s->address, "gopher", 6))
{
XP_STRCPY(munged, "gopher://");
type = GOPHER_TYPE_URL;
}
else if(!strncasecomp(URL_s->address, "news", 4)
|| !strncasecomp(URL_s->address, "nntp", 4))
{
XP_STRCPY(munged, "news://");
type = NEWS_TYPE_URL;
}
else
{
XP_STRCPY(munged, "http://");
type = HTTP_TYPE_URL;
}
XP_STRCAT(munged, URL_s->address);
}
XP_FREE(URL_s->address);
URL_s->address = munged;
#ifdef MOZILLA_CLIENT
/* Try the external protocol handlers again, since with the
* newly appended protocol, they might work this time.
*/
if(
#if defined(XP_WIN) || defined(XP_MAC)
FE_UseExternalProtocolModule(window_id, output_format, URL_s, exit_routine) ||
#endif
NPL_HandleURL(window_id, output_format, URL_s, exit_routine))
{
/* don't call the exit routine since the
* External protocol module will call it
*/
net_CheckForWaitingURL(window_id, 0, load_background);
LIBNET_UNLOCK_AND_RETURN(-1); /* all done */
}
#endif /* MOZILLA_CLIENT */
}
if(type == HTTP_TYPE_URL || type == FILE_TYPE_URL ||
type == SECURE_HTTP_TYPE_URL || type == GOPHER_TYPE_URL)
add_slash_to_URL(URL_s);
#ifdef MOZILLA_CLIENT
/*
* If this is a resize-reload OR a view-source URL, try to use the
* URL's wysiwyg: counterpart.
*/
URL_s->resize_reload = (URL_s->force_reload == NET_RESIZE_RELOAD);
if(URL_s->wysiwyg_url &&
(URL_s->resize_reload == TRUE ||
output_format == FO_VIEW_SOURCE))
{
StrAllocCopy(URL_s->address, URL_s->wysiwyg_url);
type = WYSIWYG_TYPE_URL;
}
/* the FE's were screwing up the use of force_reload
* to get around a bug in the scroll to named anchor
* code. So I gave them an enum NET_RESIZE_RELOAD
* that they could use instead. NET_RESIZE_RELOAD
* should be treated just like NET_DONT_RELOAD within
* the netlib
*/
if((URL_s->force_reload == NET_RESIZE_RELOAD) ||
(URL_s->force_reload == NET_CACHE_ONLY_RELOAD))
URL_s->force_reload = NET_DONT_RELOAD;
/* check for the url in the cache
*/
cache_method = NET_FindURLInCache(URL_s, window_id);
if (!cache_method)
{
/* cache testing stuff */
if(NET_CacheTraceOn)
{
char *buf = 0;
StrAllocCopy(buf, XP_GetString(XP_URL_NOT_FOUND_IN_CACHE));
StrAllocCat(buf, URL_s->address);
FE_Alert(window_id, buf);
FREE(buf);
}
/* cache miss: we must clear this flag so scripts rerun */
URL_s->resize_reload = FALSE;
#ifdef MOCHA /* added by jwz */
/* if wysiwyg, there must be a cache entry or we retry the real url */
if(type == WYSIWYG_TYPE_URL)
{
const char *real_url = LM_SkipWysiwygURLPrefix(URL_s->address);
/* XXX can't use StrAllocCopy because it frees dest first */
if (real_url && (new_address = XP_STRDUP(real_url)))
{
XP_FREE(URL_s->address);
URL_s->address = new_address;
FREE_AND_CLEAR(URL_s->wysiwyg_url);
LIBNET_UNLOCK_AND_RETURN(
NET_GetURL(URL_s, output_format, window_id, exit_routine)
);
}
}
#endif /* MOCHA -- added by jwz */
}
/* if cache_method is non zero then we have this URL cached. Use
* the bogus cache url type
*
* This nasty bit of logic figures out if we really
* need to reload it or if we can use the cached copy
*/
else
{
if(URL_s->use_local_copy || output_format & FO_ONLY_FROM_CACHE)
{
/* the cached file is valid so use it unilaterally
*/
type = cache_method;
}
else if(URL_s->real_content_length > URL_s->content_length)
{
/* cache testing stuff */
if(NET_CacheTraceOn)
{
char *buf = 0;
StrAllocCopy(buf, XP_GetString(XP_PARTIAL_CACHE_ENTRY));
StrAllocCat(buf, URL_s->address);
FE_Alert(window_id, buf);
FREE(buf);
}
URL_s->memory_copy = 0;
cache_method = 0;
TRACEMSG(("Getting the rest of a partial cache file"));
}
else if (URL_s->force_reload != NET_DONT_RELOAD)
{
TRACEMSG(("Force reload flag set. Checking server to see if modified"));
/* cache testing stuff */
if(NET_CacheTraceOn)
{
char *buf = 0;
StrAllocCopy(buf, XP_GetString(XP_CHECKING_SERVER__FORCE_RELOAD));
StrAllocCat(buf, URL_s->address);
FE_Alert(window_id, buf);
FREE(buf);
}
/* strip the cache file and
* memory pointer
*/
if (type == WYSIWYG_TYPE_URL)
type = cache_method;
else
{
FREE_AND_CLEAR(URL_s->cache_file);
URL_s->memory_copy = 0;
cache_method = 0;
}
}
else if(URL_s->expires)
{
time_t cur_time = time(NULL);
if(cur_time > URL_s->expires)
{
FREE_AND_CLEAR(URL_s->cache_file);
URL_s->memory_copy = 0;
URL_s->expires = 0; /* remove cache reference */
cache_method = 0;
/* cache testing stuff */
if(NET_CacheTraceOn)
{
char *buf = 0;
StrAllocCopy(buf, XP_GetString(XP_OBJECT_HAS_EXPIRED));
StrAllocCat(buf, URL_s->address);
FE_Alert(window_id, buf);
FREE(buf);
}
}
else
{
/* the cached file is valid so use it unilaterally
*/
type = cache_method;
}
}
else if((NET_CacheUseMethod == CU_NEVER_CHECK || URL_s->history_num)
&& !URL_s->expires)
{
type = cache_method;
}
else if(NET_CacheUseMethod == CU_CHECK_ALL_THE_TIME
&& CLEAR_CACHE_BIT(output_format) == FO_PRESENT
&& (type == HTTP_TYPE_URL || type == SECURE_HTTP_TYPE_URL)
&& !URL_s->expires)
{
/* cache testing stuff */
if(NET_CacheTraceOn)
{
char *buf = 0;
StrAllocCopy(buf, XP_GetString(XP_CHECKING_SERVER_CACHE_ENTRY));
StrAllocCat(buf, URL_s->address);
FE_Alert(window_id, buf);
FREE(buf);
}
/* if it's an HTTP URL and its not an Internal image
* and it's not being asked for with ONLY FROM CACHE
* and it's not coming out of the history
* and it doesn't have an expiration date...
* FORCE Reload it
*/
TRACEMSG(("Non history http file found. Force reloading it "));
/* strip the cache file and
* memory pointer
*/
FREE_AND_CLEAR(URL_s->cache_file);
URL_s->memory_copy = 0;
cache_method = 0;
}
else if(!URL_s->last_modified
&& CLEAR_CACHE_BIT(output_format) == FO_PRESENT
&& (type == HTTP_TYPE_URL || type == SECURE_HTTP_TYPE_URL))
{
TRACEMSG(("Non history cgi script found (probably)."
" Force reloading it "));
/* cache testing stuff */
if(NET_CacheTraceOn)
{
char *buf = 0;
StrAllocCopy(buf, XP_GetString(XP_CHECKING_SERVER__LASTMOD_MISS));
StrAllocCat(buf, URL_s->address);
FE_Alert(window_id, buf);
FREE(buf);
}
/* strip the cache file and
* memory pointer
*/
FREE_AND_CLEAR(URL_s->cache_file);
URL_s->memory_copy = 0;
URL_s->expires = 0; /* remove cache reference */
cache_method = 0;
}
else
{
/* the cached file is valid so use it unilaterally
*/
type = cache_method;
}
}
#endif /* MOZILLA_CLIENT */
/*
* If the object should only come out of the cache
* we should abort now if there is not a cache object
*/
if(output_format & FO_ONLY_FROM_CACHE)
{
TRACEMSG(("object called with ONLY_FROM_CACHE format out"));
if(!cache_method)
{
net_CallExitRoutine(exit_routine,
URL_s,
MK_OBJECT_NOT_IN_CACHE,
output_format,
window_id);
net_CheckForWaitingURL(window_id, type, load_background);
LIBNET_UNLOCK_AND_RETURN(MK_OBJECT_NOT_IN_CACHE);
}
else
{
/* remove the ONLY_FROM_CACHE designation and replace
* it with CACHE_AND.. so that we go through the cacheing
* module again so that we can memory cache disk objects
* and do the right thing in general
*/
output_format = CLEAR_PRESENT_BIT(output_format,FO_ONLY_FROM_CACHE);
output_format = SET_PRESENT_BIT(output_format,FO_CACHE_ONLY);
}
}
/* put a limit on the total number of open connections
*/
if(!net_is_one_url_allowed_to_run(window_id, type))
{
NET_TotalNumberOfProcessingURLs--; /* waiting not processing */
LIBNET_UNLOCK_AND_RETURN(net_push_url_on_wait_queue(type,
URL_s,
output_format,
window_id,
exit_routine));
}
/* start a new entry */
this_entry = XP_NEW(ActiveEntry);
if(!this_entry)
{
net_CallExitRoutine(exit_routine,
URL_s,
MK_OUT_OF_MEMORY,
output_format,
window_id);
LIBNET_UNLOCK_AND_RETURN(MK_OUT_OF_MEMORY);
}
/* init new entry */
XP_MEMSET(this_entry, 0, sizeof(ActiveEntry));
this_entry->URL_s = URL_s;
this_entry->socket = SOCKET_INVALID;
this_entry->con_sock = SOCKET_INVALID;
this_entry->exit_routine = exit_routine;
this_entry->window_id = window_id;
this_entry->protocol = type;
/* set the format out for the entry
*/
this_entry->format_out = output_format;
/* set it busy */
this_entry->busy = TRUE;
/* add it to the processing list now
*/
XP_ListAddObjectToEnd(net_EntryList, this_entry);
/* this will protect against multiple posts unknown to the
* user
*
* check if the method is post and it came from the
* history and it isn't coming from the cache
*/
if(URL_s->method == URL_POST_METHOD
&& !URL_s->expires
&& !cache_method
&& URL_s->history_num)
{
if(URL_s->force_reload != NET_DONT_RELOAD)
{
if(!FE_Confirm(window_id, XP_GetString(XP_CONFIRM_REPOST_FORMDATA)))
{
XP_ListRemoveObject(net_EntryList, this_entry);
net_CallExitRoutine(exit_routine,
URL_s,
MK_INTERRUPTED,
output_format,
window_id);
/* will get decremented */
net_CheckForWaitingURL(window_id, this_entry->protocol,
load_background);
XP_FREE(this_entry); /* not needed any more */
LIBNET_UNLOCK_AND_RETURN(MK_INTERRUPTED);
}
/* otherwise fall through and repost
*/
}
else
{
NET_StreamClass * stream;
char buffer[1000];
StrAllocCopy(URL_s->content_type, TEXT_HTML);
stream = NET_StreamBuilder(CLEAR_CACHE_BIT(output_format),
URL_s,
window_id);
if(stream)
{
XP_STRCPY(buffer, XP_GetString(XP_HTML_MISSING_REPLYDATA));
(*stream->put_block)(stream->data_object,
buffer,
XP_STRLEN(buffer));
(*stream->complete)(stream->data_object);
}
XP_ListRemoveObject(net_EntryList, this_entry);
net_CallExitRoutine(exit_routine,
URL_s,
MK_INTERRUPTED,
output_format,
window_id);
net_CheckForWaitingURL(window_id, this_entry->protocol,
load_background);
XP_FREE(this_entry); /* not needed any more */
LIBNET_UNLOCK_AND_RETURN(MK_INTERRUPTED);
}
}
redo_load_switch: /* come here on file/ftp retry */
ABOUT_KLUDGE:
#ifdef MOZILLA_CLIENT
pacf_status = TRUE;
if ((NET_ProxyAcLoaded) &&
(this_entry->protocol == HTTP_TYPE_URL
|| this_entry->protocol == SECURE_HTTP_TYPE_URL
|| this_entry->protocol == GOPHER_TYPE_URL
|| this_entry->protocol == FTP_TYPE_URL
|| this_entry->protocol == WAIS_TYPE_URL
|| this_entry->protocol == URN_TYPE_URL
|| (this_entry->protocol == NEWS_TYPE_URL
&& !strncasecomp(URL_s->address, "snews:", 6)
)
)
&& (this_entry->proxy_conf =
pacf_find_proxies_for_url(window_id, URL_s->address)) &&
(pacf_status = pacf_get_proxy_addr(window_id,
this_entry->proxy_conf,
&this_entry->proxy_addr,
&this_entry->socks_host,
&this_entry->socks_port)) &&
(this_entry->proxy_addr))
{
/* Secure protocols need to be kept in their own protocol
* to make SSL tunneling happen.
*/
if (this_entry->protocol != SECURE_HTTP_TYPE_URL &&
this_entry->protocol != NEWS_TYPE_URL)
{
this_entry->protocol = HTTP_TYPE_URL;
}
/* Everything else except SNEWS gets loaded by HTTP loader,
* including HTTPS.
*/
if (this_entry->protocol != NEWS_TYPE_URL)
{
status = NET_HTTPLoad(this_entry);
}
else
{
status = NET_NewsLoad(this_entry, this_entry->proxy_addr);
}
}
else
if ( pacf_status == FALSE && NET_GetNoProxyFailover() == TRUE ) {
status = MK_UNABLE_TO_LOCATE_PROXY;
FE_Alert(window_id, XP_GetString(XP_BAD_AUTOCONFIG_NO_FAILOVER));
} else
#endif /* ! MOZILLA_CLIENT */
switch(type) {
#ifdef MOZILLA_CLIENT
case MAILBOX_TYPE_URL:
status = NET_MailboxLoad(this_entry);
break;
case MEMORY_CACHE_TYPE_URL:
status = NET_MemoryCacheLoad(this_entry);
break;
#ifdef MOCHA
case MOCHA_TYPE_URL:
if (URL_s)
StrAllocCopy(URL_s->charset, INTL_ResourceCharSet());
status = net_OpenMochaURL(this_entry);
break;
#endif /* MOCHA */
#endif /* MOZILLA_CLIENT */
case FILE_TYPE_URL:
case FILE_CACHE_TYPE_URL:
status = NET_FileLoad(this_entry);
break;
case FTP_TYPE_URL:
if(MKftp_proxy && !override_proxy(this_entry->URL_s->address))
{
this_entry->protocol = HTTP_TYPE_URL;
this_entry->proxy_addr = MKftp_proxy;
status = NET_HTTPLoad(this_entry);
}
else
{
status = NET_FTPLoad(this_entry);
}
break;
case SECURE_HTTP_TYPE_URL:
#ifdef NADA_VERSION
/* change the url to point to our page that
* says security doesn't work in this version
*/
this_entry->protocol = HTTP_TYPE_URL;
StrAllocCopy(this_entry->URL_s->address,
"http://home.netscape.com/home/no-https.html");
#endif
if(MKhttps_proxy && !override_proxy(this_entry->URL_s->address))
{
this_entry->proxy_addr = MKhttps_proxy;
status = NET_HTTPLoad(this_entry);
}
else
{
status = NET_HTTPLoad(this_entry);
}
break;
case HTTP_TYPE_URL:
if(MKhttp_proxy && !override_proxy(this_entry->URL_s->address))
{
this_entry->protocol = HTTP_TYPE_URL;
this_entry->proxy_addr = MKhttp_proxy;
status = NET_HTTPLoad(this_entry);
}
else
{
status = NET_HTTPLoad(this_entry);
}
break;
case URN_TYPE_URL:
if(MKhttp_proxy)
{
this_entry->protocol = HTTP_TYPE_URL;
this_entry->proxy_addr = MKhttp_proxy;
status = NET_HTTPLoad(this_entry);
}
else
{
char buffer[256];
XP_STRCPY(buffer, XP_GetString(XP_ALERT_URN_USEHTTP));
XP_STRNCAT(buffer, this_entry->URL_s->address, 150);
buffer[255] = '\0'; /* in case strncat doesn't add one */
FE_Alert(window_id, buffer);
}
break;
case GOPHER_TYPE_URL:
if(MKgopher_proxy && !override_proxy(this_entry->URL_s->address))
{
this_entry->protocol = HTTP_TYPE_URL;
this_entry->proxy_addr = MKgopher_proxy;
status = NET_HTTPLoad(this_entry);
}
else
{
status = NET_GopherLoad(this_entry);
}
break;
#ifdef MOZILLA_CLIENT
case MAILTO_TYPE_URL:
status = NET_MailtoLoad(this_entry);
break;
case INTERNAL_NEWS_TYPE_URL:
if(!URL_s->internal_url)
goto invalid_url;
case NEWS_TYPE_URL:
if(MKnews_proxy && !override_proxy(this_entry->URL_s->address))
{
this_entry->protocol = HTTP_TYPE_URL;
this_entry->proxy_addr = MKnews_proxy;
status = NET_HTTPLoad(this_entry);
}
else
{
status = NET_NewsLoad(this_entry, MKhttps_proxy);
}
break;
#endif /* MOZILLA_CLIENT */
case ABOUT_TYPE_URL:
#ifdef MOZILLA_CLIENT
/* Force embedded textfile to be ResourceCharset if require translation */
if (URL_s && XP_STRCMP(URL_s->address, "about:license") == 0)
StrAllocCopy(URL_s->charset, INTL_ResourceCharSet());
#endif /* MOZILLA_CLIENT */
if (net_about_kludge (URL_s))
{
type = this_entry->protocol = NET_URL_Type (URL_s->address);
goto ABOUT_KLUDGE;
}
status = net_output_about_url(this_entry);
break;
#ifdef MOZILLA_CLIENT
case INTERNAL_IMAGE_TYPE_URL:
break;
case RLOGIN_TYPE_URL:
case TELNET_TYPE_URL:
case TN3270_TYPE_URL:
status = NET_RemoteHostLoad(this_entry);
break;
#endif /* MOZILLA_CLIENT */
case WAIS_TYPE_URL:
if(MKwais_proxy && !override_proxy(this_entry->URL_s->address))
{
this_entry->protocol = HTTP_TYPE_URL;
this_entry->proxy_addr = MKwais_proxy;
status = NET_HTTPLoad(this_entry);
}
else
{
char * alert = NET_ExplainErrorDetails(MK_NO_WAIS_PROXY);
FE_Alert(window_id, alert);
FREE(alert);
}
break;
#ifdef MOZILLA_CLIENT
case POP3_TYPE_URL:
if(URL_s->internal_url)
{
status = NET_Pop3Load(this_entry);
break;
}
else
{
goto invalid_url;
}
#ifdef HAVE_SECURITY /* added by jwz */
case SECURITY_TYPE_URL:
if (URL_s)
StrAllocCopy(URL_s->charset, INTL_ResourceCharSet());
status = net_output_security_url(this_entry, window_id);
if (this_entry->status == MK_MALFORMED_URL_ERROR)
/* uhh, is this right? Should we go there whenever negative? */
goto invalid_url;
break;
#endif /* !HAVE_SECURITY -- added by jwz */
#ifdef HAVE_SECURITY /* added by jwz */
case HTML_DIALOG_HANDLER_TYPE_URL:
if (URL_s)
StrAllocCopy(URL_s->charset, INTL_ResourceCharSet());
XP_HandleHTMLDialog(this_entry->URL_s);
processcallbacks = 1;
status = -1; /* XXX - why?? */
break;
case HTML_PANEL_HANDLER_TYPE_URL:
if (URL_s)
StrAllocCopy(URL_s->charset, INTL_ResourceCharSet());
XP_HandleHTMLPanel(this_entry->URL_s);
processcallbacks = 1;
status = -1; /* XXX - why?? */
break;
#endif /* !HAVE_SECURITY -- added by jwz */
#ifndef NO_SSL /* added by jwz */
case INTERNAL_SECLIB_TYPE_URL:
if (URL_s)
StrAllocCopy(URL_s->charset, INTL_ResourceCharSet());
SECNAV_HandleInternalSecURL(this_entry->URL_s, window_id);
processcallbacks = 1;
status = -1; /* XXX - why?? */
break;
#endif /* NO_SSL -- added by jwz */
#endif /* MOZILLA_CLIENT */
#ifdef MOCHA /* added by jwz */
case WYSIWYG_TYPE_URL:
{
const char *real_url = LM_SkipWysiwygURLPrefix(URL_s->address);
/* XXX can't use StrAllocCopy because it frees dest first */
if (real_url && (new_address = XP_STRDUP(real_url)) != NULL)
{
XP_FREE(URL_s->address);
URL_s->address = new_address;
FREE_AND_CLEAR(URL_s->wysiwyg_url);
XP_ListRemoveObject(net_EntryList, this_entry);
XP_FREE(this_entry);
LIBNET_UNLOCK_AND_RETURN(
NET_GetURL(URL_s, output_format, window_id, exit_routine)
);
}
}
#endif /* MOCHA -- added by jwz */
/* FALL THROUGH */
default:
invalid_url: /* goto jump point */
{
URL_s->error_msg =
NET_ExplainErrorDetails(MK_MALFORMED_URL_ERROR,
this_entry->URL_s->address);
status = MK_MALFORMED_URL_ERROR;
this_entry->status = MK_MALFORMED_URL_ERROR;
}
}
/* the entry is no longer busy
*/
this_entry->busy = FALSE;
#ifdef MOZILLA_CLIENT
/* OH NASTY A GOTO!
* If we went into load file and what we really wanted to do
* was use FTP, LoadFile will return MK_USE_FTP_INSTEAD so
* we will go back up to the beginning of the switch and
* use ftp instead
*/
if(status == MK_USE_FTP_INSTEAD)
{
type = FTP_TYPE_URL;
this_entry->protocol = type; /* change protocol designator */
this_entry->status = 0; /* reset */
goto redo_load_switch;
}
else
#endif /* MOZILLA_CLIENT */
if(this_entry->status == MK_USE_COPY_FROM_CACHE)
{
TRACEMSG(("304 Not modified recieved using cached entry\n"));
#ifdef MOZILLA_CLIENT
NET_RefreshCacheFileExpiration(this_entry->URL_s);
#endif /* MOZILLA_CLIENT */
/* turn off force reload by telling it to use local copy
*/
this_entry->URL_s->use_local_copy = TRUE;
/* restart the transfer
*/
XP_ListRemoveObject(net_EntryList, this_entry);
status = NET_GetURL(this_entry->URL_s,
this_entry->format_out,
this_entry->window_id,
this_entry->exit_routine);
net_CheckForWaitingURL(this_entry->window_id,
this_entry->protocol,
this_entry->URL_s->load_background);
XP_FREE(this_entry);
LIBNET_UNLOCK_AND_RETURN(0);
}
else
if(this_entry->status == MK_DO_REDIRECT)
{
/* this redirect should just call GetURL again
*/
int status;
XP_ListRemoveObject(net_EntryList, this_entry);
status =NET_GetURL(this_entry->URL_s,
this_entry->format_out,
this_entry->window_id,
this_entry->exit_routine);
net_CheckForWaitingURL(this_entry->window_id,
this_entry->protocol,
load_background);
XP_FREE(this_entry); /* not needed any more */
LIBNET_UNLOCK_AND_RETURN(0);
}
else if(this_entry->status == MK_TOO_MANY_OPEN_FILES)
{
/* Queue this URL so it gets tried again
*/
XP_ListRemoveObject(net_EntryList, this_entry);
status = net_push_url_on_wait_queue(
NET_URL_Type(this_entry->URL_s->address),
this_entry->URL_s,
this_entry->format_out,
this_entry->window_id,
this_entry->exit_routine);
NET_TotalNumberOfProcessingURLs--;
XP_FREE(this_entry);
LIBNET_UNLOCK_AND_RETURN(status);
}
if(status < 0) /* check for finished state */
{
TRACEMSG(("End of transfer, entry (soc=%d, con=%d) being removed from list with %d status: %s",
this_entry->socket, this_entry->con_sock, this_entry->status, this_entry->URL_s->address));
XP_ListRemoveObject(net_EntryList, this_entry);
net_CallExitRoutine(this_entry->exit_routine,
this_entry->URL_s,
this_entry->status,
this_entry->format_out,
this_entry->window_id);
net_CheckForWaitingURL(this_entry->window_id,
this_entry->protocol,
load_background);
XP_FREE(this_entry); /* not needed any more */
}
TRACEMSG(("Leaving GetURL with %d items in list",
XP_ListCount(net_EntryList)));
/* XXX - hack for chromeless windows - jsw 10/27/95 */
LIBNET_UNLOCK();
if ( processcallbacks ) {
NET_ProcessExitCallbacks();
}
return status;
#ifdef NOTDEF /* this is the real code here */
LIBNET_UNLOCK_AND_RETURN(status);
#endif
}
/* process_net is called from the client's main event loop and
* causes connections to be read and processed. Multiple
* connections can be processed simultaneously.
*/
PUBLIC int NET_ProcessNet (NETSOCK ready_fd, int fd_type)
{
ActiveEntry * tmpEntry;
XP_List * list_item;
int rv;
Bool load_background;
TRACEMSG(("Entering ProcessNet! ready_fd: %d", ready_fd));
LIBNET_LOCK();
if(XP_ListIsEmpty(net_EntryList))
{
TRACEMSG(("Invalid call to NET_ProcessNet with fd: %d - No active entries\n", ready_fd));
#ifdef MOZILLA_CLIENT
#ifdef XP_UNIX
# if 0 /* jwz */
XP_ASSERT(0);
# endif
#endif
if (ready_fd == -1)
{
MWContext *c = XP_FindContextOfType(0, MWContextBrowser);
if (!c) c = XP_FindContextOfType(0, MWContextMail);
if (!c) c = XP_FindContextOfType(0, MWContextNews);
if (!c) c = XP_FindContextOfType(0, MWContextMessageComposition);
if (c)
FE_ClearCallNetlibAllTheTime(c);
}
#endif /* MOZILLA_CLIENT */
LIBNET_UNLOCK_AND_RETURN(0); /* no entries to process */
}
if(NET_InGetHostByName)
{
TRACEMSG(("call to processnet while doing gethostbyname call"));
assert(0);
LIBNET_UNLOCK_AND_RETURN(1);
}
/*
* if -1 is passed into ProcessNet use select to
* figure out if a socket is ready
*/
if(ready_fd == -1)
{
/* try and find a socket ready for reading
*/
fd_set read_fds;
fd_set write_fds;
fd_set exps_fds;
unsigned int fd_set_size=0;
struct timeval timeout;
/* reorder the list so that we get a round robin effect */
XP_ListMoveTopToBottom(net_EntryList);
timeout.tv_sec = 0; /* polling */
timeout.tv_usec = 0; /* polling */
XP_MEMSET(&read_fds, 0, sizeof(fd_set));
XP_MEMSET(&write_fds, 0, sizeof(fd_set));
XP_MEMSET(&exps_fds, 0, sizeof(fd_set));
fd_type = NET_SOCKET_FD;
/* process one socket ready for reading */
list_item = net_EntryList;
while((tmpEntry = (ActiveEntry *) XP_ListNextObject(list_item)) != 0)
{
if(tmpEntry->busy)
continue;
if(!tmpEntry->local_file && !tmpEntry->memory_file)
{
if (tmpEntry->socket != SOCKET_INVALID)
{
/* check with SSL to see if it already
* had data pending. If it does
* then we will bypass select
*/
#ifndef NO_SSL /* added by jwz */
if(SSL_DataPending(tmpEntry->socket))
{
fd_type = NET_SOCKET_FD;
ready_fd = tmpEntry->socket;
break; /* exit while */
}
#endif /* NO_SSL -- added by jwz */
FD_SET(tmpEntry->socket, &read_fds);
if(tmpEntry->socket >= fd_set_size)
fd_set_size = tmpEntry->socket+1;
}
}
else if(tmpEntry ==
(ActiveEntry *) XP_ListGetObjectNum(net_EntryList, 1))
{
/* if this is the very first object in the list
* and it's a local file or a memory cache copy
* then use this one entry and skip the select call
* we won't deadlock because we reorder the list
* with every call to net process net.
*/
fd_type = NET_LOCAL_FILE_FD;
ready_fd = tmpEntry->socket; /* ugly */
break; /* exit while */
}
if(tmpEntry->con_sock != SOCKET_INVALID)
{
FD_SET(tmpEntry->con_sock, &write_fds);
FD_SET(tmpEntry->con_sock, &exps_fds);
if(tmpEntry->con_sock >= fd_set_size)
fd_set_size = tmpEntry->con_sock+1;
}
}
if(ready_fd == -1) /* in case we set it for the local file type above */
{
int ret = select(fd_set_size,
&read_fds,
&write_fds,
&exps_fds,
&timeout);
if(!ret)
{
TRACEMSG(("Select returned no active sockets! "
"WASTED CALL TO PROCESS NET"));
LIBNET_UNLOCK_AND_RETURN(XP_ListIsEmpty(net_EntryList) ? 0 : 1);
}
fd_type = NET_SOCKET_FD;
/* process one socket ready for reading,
* find the first one ready
*/
list_item = net_EntryList;
while((tmpEntry=(ActiveEntry *) XP_ListNextObject(list_item)) != 0)
{
if(tmpEntry->busy)
continue;
if(!tmpEntry->local_file && !tmpEntry->memory_file)
{
if(FD_ISSET(tmpEntry->socket, &read_fds)
|| FD_ISSET(tmpEntry->socket, &write_fds)
|| FD_ISSET(tmpEntry->socket, &exps_fds))
{
ready_fd = tmpEntry->socket;
break;
}
}
}
if(ready_fd == -1)
{
LIBNET_UNLOCK_AND_RETURN(XP_ListIsEmpty(net_EntryList) ? 0 : 1);
}
}
}
list_item = net_EntryList;
/* process one socket ready for reading
*
* find the ready socket in the active entry list
*/
while((tmpEntry = (ActiveEntry *) XP_ListNextObject(list_item)) != 0)
{
TRACEMSG(("Found item in Active Entry List. sock #%d con_sock #%d",
tmpEntry->socket, tmpEntry->con_sock));
if(tmpEntry->busy)
{
/* I guess this is alright since one of the streams
* (Play audio for instance) may put up a modal dialog
* box which causes the main event loop to get called
* from within the stream
*
* FE_Alert(tmpEntry->window_id, "reentrant call to Process Net");
*/
}
else if( ((tmpEntry->memory_file && fd_type == NET_UNKNOWN_FD) ||
/* always activate memory files */
(fd_type == NET_LOCAL_FILE_FD && tmpEntry->local_file && ready_fd == tmpEntry->socket) ||
(fd_type != NET_LOCAL_FILE_FD &&
(ready_fd == tmpEntry->socket || ready_fd == tmpEntry->con_sock) ) ) )
{
tmpEntry->busy = TRUE;
TRACEMSG(("Item has data ready for read"));
switch(tmpEntry->protocol)
{
#ifdef MOZILLA_CLIENT
case MAILBOX_TYPE_URL:
rv = NET_ProcessMailbox(tmpEntry);
break;
case MEMORY_CACHE_TYPE_URL:
rv = NET_ProcessMemoryCache(tmpEntry);
break;
case MOCHA_TYPE_URL:
XP_ASSERT(0);
break;
#endif /* MOZILLA_CLIENT */
case HTTP_TYPE_URL:
case SECURE_HTTP_TYPE_URL:
rv = NET_ProcessHTTP(tmpEntry);
break;
#ifdef MOZILLA_CLIENT
case MAILTO_TYPE_URL:
rv = NET_ProcessMailto(tmpEntry);
break;
case POP3_TYPE_URL:
rv = NET_ProcessPop3(tmpEntry);
break;
#endif /* MOZILLA_CLIENT */
case GOPHER_TYPE_URL:
rv = NET_ProcessGopher(tmpEntry);
break;
case FTP_TYPE_URL:
rv = NET_ProcessFTP(tmpEntry);
break;
#ifdef MOZILLA_CLIENT
case NEWS_TYPE_URL:
case INTERNAL_NEWS_TYPE_URL:
rv = NET_ProcessNews(tmpEntry);
break;
#endif /* MOZILLA_CLIENT */
case FILE_TYPE_URL:
case FILE_CACHE_TYPE_URL:
rv = NET_ProcessFile(tmpEntry);
} /* end switch */
tmpEntry->busy = FALSE;
/* check for done status on transfer and call
* exit routine if done.
*/
if(rv < 0)
{
XP_ListRemoveObject(net_EntryList, tmpEntry);
if(tmpEntry->status == MK_USE_COPY_FROM_CACHE)
{
TRACEMSG(("304 Not modified recieved using cached entry\n"));
#ifdef MOZILLA_CLIENT
NET_RefreshCacheFileExpiration(tmpEntry->URL_s);
#endif /* MOZILLA_CLIENT */
/* turn off force reload by telling it to use local copy
*/
tmpEntry->URL_s->use_local_copy = TRUE;
/* restart the transfer
*/
NET_GetURL(tmpEntry->URL_s,
tmpEntry->format_out,
tmpEntry->window_id,
tmpEntry->exit_routine);
net_CheckForWaitingURL(tmpEntry->window_id,
tmpEntry->protocol,
tmpEntry->URL_s->load_background);
}
else if(tmpEntry->status == MK_DO_REDIRECT)
{
TRACEMSG(("Doing redirect part in ProcessNet"));
/* restart the whole transfer */
NET_GetURL(tmpEntry->URL_s,
tmpEntry->format_out,
tmpEntry->window_id,
tmpEntry->exit_routine);
net_CheckForWaitingURL(tmpEntry->window_id,
tmpEntry->protocol,
tmpEntry->URL_s->load_background); }
else if(tmpEntry->status == MK_TOO_MANY_OPEN_FILES)
{
/* Queue this URL so it gets tried again
*/
LIBNET_UNLOCK_AND_RETURN(net_push_url_on_wait_queue(
NET_URL_Type(tmpEntry->URL_s->address),
tmpEntry->URL_s,
tmpEntry->format_out,
tmpEntry->window_id,
tmpEntry->exit_routine));
}
else if(tmpEntry->status < 0
&& tmpEntry->URL_s->last_modified
&& !tmpEntry->URL_s->use_local_copy
#ifndef NO_SSL /* added by jwz */
&& XP_GetError() != SSL_ERROR_BAD_CERTIFICATE
#endif /* NO_SSL -- added by jwz */
&& (tmpEntry->status == MK_CONNECTION_REFUSED
|| tmpEntry->status == MK_CONNECTION_TIMED_OUT
|| tmpEntry->status == MK_UNABLE_TO_CREATE_SOCKET
|| tmpEntry->status == MK_UNABLE_TO_LOCATE_HOST
|| tmpEntry->status == MK_UNABLE_TO_CONNECT))
{
/* if the status is negative something went wrong
* with the load. If last_modified is set
* then we probably have a cache file,
* but it might be a broken image so
* make sure "use_local_copy" is not
* set.
*
* Only do this when we can't connect to the
* server.
*/
/* if we had a cache file and got a load
* error, go ahead and use it anyways
*/
/* turn off force reload by telling it to use local copy
*/
tmpEntry->URL_s->use_local_copy = TRUE;
if(CLEAR_CACHE_BIT(tmpEntry->format_out) == FO_PRESENT)
{
StrAllocCat(tmpEntry->URL_s->error_msg,
XP_GetString( XP_USING_PREVIOUSLY_CACHED_COPY_INSTEAD ) );
FE_Alert(tmpEntry->window_id,
tmpEntry->URL_s->error_msg);
}
FREE_AND_CLEAR(tmpEntry->URL_s->error_msg);
/* restart the transfer
*/
NET_GetURL(tmpEntry->URL_s,
tmpEntry->format_out,
tmpEntry->window_id,
tmpEntry->exit_routine);
net_CheckForWaitingURL(tmpEntry->window_id,
tmpEntry->protocol,
tmpEntry->URL_s->load_background);
}
else
{
TRACEMSG(("End of transfer, entry (soc=%d, con=%d) being removed from list with %d status: %s",
tmpEntry->socket, tmpEntry->con_sock, tmpEntry->status,
(tmpEntry->URL_s->address ? tmpEntry->URL_s->address : "")));
/* catch out of memory errors at the lowest
* level since we don't do it at all the out
* of memory condition spots
*/
if(tmpEntry->status == MK_OUT_OF_MEMORY
&& !tmpEntry->URL_s->error_msg)
{
tmpEntry->URL_s->error_msg =
NET_ExplainErrorDetails(MK_OUT_OF_MEMORY);
}
load_background = tmpEntry->URL_s->load_background;
/* run the exit routine
*/
net_CallExitRoutine(tmpEntry->exit_routine,
tmpEntry->URL_s,
tmpEntry->status,
tmpEntry->format_out,
tmpEntry->window_id);
net_CheckForWaitingURL(tmpEntry->window_id,
tmpEntry->protocol,
load_background);
#ifdef MILAN
/* if the error was caused by a NETWORK DOWN
* then interrupt the window. This
* could still be a problem since another
* window may be active, but it should get
* the same error
*/
if(SOCKET_ERRNO == XP_ERRNO_ENETDOWN)
{
NET_SilentInterruptWindow(tmpEntry->window_id);
}
#endif /* MILAN */
}
XP_FREE(tmpEntry); /* free the now non active entry */
} /* end if */
TRACEMSG(("Leaving process net with %d items in list",
XP_ListCount(net_EntryList)));
LIBNET_UNLOCK_AND_RETURN(XP_ListIsEmpty(net_EntryList) ? 0 : 1); /* all done */
} /* end if FD_ISSET */
} /* end while */
/* the active socket wasn't found in the list :(
*/
TRACEMSG(("Invalid call to NET_ProcessNet: Active item with passed in fd: %d not found\n", ready_fd));
LIBNET_UNLOCK_AND_RETURN(XP_ListIsEmpty(net_EntryList) ? 0 : 1);
}
/*
* net_InterruptActiveStream
* Kills a single stream given its ActiveEntry*
* * FrontEndCancel -> NetInterruptWindow -> net_InterruptActiveStream
* * LayoutNewDoc -> KillOtherLayouts -> net_InterruptActiveStream
*
* Also removes the entry from the active list and frees it.
* Also allows waiting urls into the active list.
*/
PRIVATE int
net_InterruptActiveStream (ActiveEntry *entry)
{
TRACEMSG(("Terminating transfer on port #%d, proto: %d",
entry->socket, entry->protocol));
/* remove it from the active list first to prevent
* reentrant problem
*/
XP_ListRemoveObject(net_EntryList, entry);
switch(entry->protocol)
{
#ifdef MOZILLA_CLIENT
case MAILBOX_TYPE_URL:
NET_InterruptMailbox(entry);
break;
case MEMORY_CACHE_TYPE_URL:
NET_InterruptMemoryCache(entry);
break;
case MAILTO_TYPE_URL:
NET_InterruptMailto(entry);
break;
case POP3_TYPE_URL:
NET_InterruptPop3(entry);
break;
#ifdef MOCHA
case MOCHA_TYPE_URL:
net_InterruptMocha(entry);
break;
#endif /* MOCHA */
#endif /* MOZILLA_CLIENT */
case HTTP_TYPE_URL:
case SECURE_HTTP_TYPE_URL:
NET_InterruptHTTP(entry);
break;
case GOPHER_TYPE_URL:
NET_InterruptGopher(entry);
break;
case FTP_TYPE_URL:
NET_InterruptFTP(entry);
break;
#ifdef MOZILLA_CLIENT
case INTERNAL_NEWS_TYPE_URL:
case NEWS_TYPE_URL:
NET_InterruptNews(entry);
break;
case FILE_TYPE_URL:
case FILE_CACHE_TYPE_URL:
NET_InterruptFile(entry);
break;
#endif /* MOZILLA_CLIENT */
default:
XP_ASSERT(0);
} /* end switch */
TRACEMSG(("End of transfer, entry (soc=%d, con=%d) being removed from list with %d status: %s",
entry->socket, entry->con_sock, entry->status, entry->URL_s->address));
/* call exit routine since we know we are done */
net_CallExitRoutine(entry->exit_routine,
entry->URL_s,
entry->status,
entry->format_out,
entry->window_id);
/* decrement here since we don't call checkForWaitingURL's
*/
NET_TotalNumberOfProcessingURLs--;
if(!NET_AreThereActiveConnectionsForWindow(entry->window_id))
FE_AllConnectionsComplete(entry->window_id);
/* free the no longer active entry */
XP_FREE(entry);
return 0;
}
/*
* NET_InterruptStream kills just stream associated with an URL.
*/
PUBLIC int
NET_InterruptStream (URL_Struct *nurl)
{
/* Find the ActiveEntry structure for this URL */
ActiveEntry *tmpEntry = NULL, *entryToKill = NULL;
XP_List * iter;
int status;
TRACEMSG(("Entering NET_InterruptStream"));
LIBNET_LOCK();
iter = net_EntryList;
if(NET_InGetHostByName)
{
TRACEMSG(("call to InterrruptStream while doing gethostbyname call"));
LIBNET_UNLOCK_AND_RETURN(1);
}
while ((tmpEntry = (ActiveEntry *) XP_ListNextObject(iter)) != NULL) {
if (tmpEntry->URL_s == nurl) {
entryToKill = tmpEntry;
break;
}
}
/* assert (entryToKill);*/
/* Kill it & free it */
if (entryToKill)
status = net_InterruptActiveStream (entryToKill);
else
status = -1;
LIBNET_UNLOCK_AND_RETURN(status);
}
/* interrupt a LoadURL action by using a socket number as
* an index. NOTE: that this cannot interrupt non-socket
* based operations such as file or memory cache loads
*
* returns -1 on error.
*/
PUBLIC int
NET_InterruptSocket (NETSOCK socket)
{
/* Find the ActiveEntry structure for this URL */
ActiveEntry *tmpEntry = NULL, *entryToKill = NULL;
XP_List * iter;
int status;
TRACEMSG(("Entering NET_InterruptSocket"));
LIBNET_LOCK();
iter = net_EntryList;
if(NET_InGetHostByName)
{
TRACEMSG(("call to InterrruptStream while doing gethostbyname call"));
LIBNET_UNLOCK_AND_RETURN(1);
}
while ((tmpEntry = (ActiveEntry *) XP_ListNextObject(iter)) != NULL) {
if (tmpEntry->con_sock == socket || tmpEntry->socket == socket) {
entryToKill = tmpEntry;
break;
}
}
if (entryToKill)
status = net_InterruptActiveStream (entryToKill);
else
status = -1;
LIBNET_UNLOCK_AND_RETURN(status);
}
/*
* NET_SetNewContext changes the context associated with a URL Struct.
* can also change the url exit routine, which causes the old one to be
* called with a status of MK_CHANGING_CONTEXT
*/
PUBLIC int
NET_SetNewContext(URL_Struct *URL_s, MWContext * new_context, Net_GetUrlExitFunc *exit_routine)
{
/* Find the ActiveEntry structure for this URL */
ActiveEntry *tmpEntry = NULL;
XP_List * iter;
MWContext *old_window_id;
LIBNET_LOCK();
iter = net_EntryList;
while ((tmpEntry = (ActiveEntry *) XP_ListNextObject(iter)) != NULL)
{
if (tmpEntry->URL_s == URL_s)
{
/* call the old exit routine now with the old context */
/* call with MK_CHANGING_CONTEXT, FE shouldn't free URL_s */
net_CallExitRoutine(tmpEntry->exit_routine,
URL_s,
MK_CHANGING_CONTEXT,
0,
tmpEntry->window_id);
/* see if we're changing exit routines */
if(exit_routine != NULL) {
/* okay to change now. */
tmpEntry->exit_routine = exit_routine;
}
old_window_id = tmpEntry->window_id;
tmpEntry->window_id = new_context;
#ifdef XP_WIN
/*
* Windows needs a way to know when a URL switches contexts,
* so that it can keep the NCAPI progress messages
* specific to a URL loading and not specific to the
* context attempting to load.
* So sue me. GAB 10-16-95
*/
FE_UrlChangedContext(URL_s, old_window_id, new_context);
#endif /* XP_WIN */
/* if there are no more connections in the old context, we
* need to call AllConnectionsComplete
*/
if(!NET_AreThereActiveConnectionsForWindow(old_window_id))
FE_AllConnectionsComplete(old_window_id);
LIBNET_UNLOCK();
return(0);
}
}
/* couldn't find it :( */
XP_ASSERT (0);
LIBNET_UNLOCK();
return(-1);
}
/* returns true if the stream is safe for setting up a new
* context and using a separate window.
*
* This will return FALSE in multipart/mixed cases where
* it is impossible to use separate windows for the
* same stream.
*/
PUBLIC Bool
NET_IsSafeForNewContext(URL_Struct *URL_s)
{
if(!URL_s || URL_s->is_active)
return(FALSE);
return(TRUE);
}
/* NET_InterruptTransfer
*
* Interrupts all transfers in progress that have the same window id as
* the one passed in.
*/
PRIVATE int
net_InternalInterruptWindow(MWContext * window_id, Bool show_warning)
{
int starting_list_count;
ActiveEntry * tmpEntry;
ActiveEntry * tmpEntry2;
XP_List * list_item;
int32 cur_win_id = FE_GetContextID(window_id);
int number_killed=0;
XP_Bool call_all_connections_complete = TRUE;
TRACEMSG(("-------Interrupt Transfer called!"));
LIBNET_LOCK();
list_item = net_EntryList;
starting_list_count = XP_ListCount(net_EntryList);
#ifdef DEBUG
if(NET_InGetHostByName)
{
TRACEMSG(("call to InterrruptWindow while doing gethostbyname call"));
LIBNET_UNLOCK_AND_RETURN(1);
}
#endif /* DEBUG */
number_killed = net_AbortWaitingURL(window_id,
FALSE,
net_waiting_for_actives_url_list);
number_killed += net_AbortWaitingURL(window_id,
FALSE,
net_waiting_for_connection_url_list);
/* run through the whole list of connections and
* interrupt any of them that have a matching window
* id.
*/
tmpEntry = (ActiveEntry *) XP_ListNextObject(list_item);
while(tmpEntry)
{
/* advance to the next item NOW in case we free this one */
tmpEntry2 = (ActiveEntry *) XP_ListNextObject(list_item);
if(FE_GetContextID(tmpEntry->window_id) == cur_win_id)
{
if(tmpEntry->busy)
{
if(show_warning)
{
TRACEMSG(("AAAACK, reentrant protection kicking in.!!!"));
#ifdef DEBUG
FE_Alert(tmpEntry->window_id, XP_GetString(XP_ALERT_INTERRUPT_WINDOW));
#endif /* DEBUG */
}
}
else
{
FE_EnableClicking(window_id);
net_InterruptActiveStream (tmpEntry);
number_killed += 1;
/* unset call_all_connections_complete here
* since InterruptActiveStream will already
* call all_connections_complete when it detects
* that there are no more active connections
* going on for the window.
*/
call_all_connections_complete = FALSE;
}
} /* end if cur_win_id */
tmpEntry = tmpEntry2;
} /* end while */
/* If all_connection_complete was called, FE might have destroyed
* the context. So dont call FE_EnableClicking() if
* call_all_connections_complete was already called.
*/
if (call_all_connections_complete)
FE_EnableClicking(window_id);
/* we are sure that all connections are complete
* but only call it if we killed one.
*/
if(number_killed && call_all_connections_complete)
FE_AllConnectionsComplete(window_id);
TRACEMSG(("Leaving Interrupt transfer with %d items in list",
XP_ListCount(net_EntryList)));
LIBNET_UNLOCK_AND_RETURN(starting_list_count - XP_ListCount(net_EntryList));
}
/*
* Interrupts all transfers in progress that have the same window id as
* the one passed in.
*/
PUBLIC int
NET_InterruptWindow(MWContext * window_id)
{
return(net_InternalInterruptWindow(window_id, TRUE));
}
/*
* Silently Interrupts all transfers in progress that have the same
* window id as the one passed in.
*/
MODULE_PRIVATE int
NET_SilentInterruptWindow(MWContext * window_id)
{
return(net_InternalInterruptWindow(window_id, FALSE));
}
/* check for any active URL transfers in progress for the given
* window Id
*
* It is possible that there exist URL's on the wait queue that
* will not be returned by this function. It is recommended
* that you call NET_InterruptWindow(MWContext * window_id)
* when FALSE is returned to make sure that the wait queue is
* cleared as well.
*
* It is also possible that some URLs will be explicitly marked as
* "background" URLs that are not identified as active, even though
* they are.
*/
PUBLIC Bool
NET_AreThereActiveConnectionsForWindow(MWContext * window_id)
{
ActiveEntry * tmpEntry;
int32 cur_win_id = FE_GetContextID(window_id);
XP_List * list_ptr;
WaitingURLStruct * wus;
LIBNET_LOCK();
TRACEMSG(("-------NET_AreThereActiveConnectionsForWindow called!"));
/* check for connections in the wait queue
*/
list_ptr = net_waiting_for_actives_url_list;
while((wus = (WaitingURLStruct*) XP_ListNextObject(list_ptr)) != NULL)
{
if(cur_win_id == FE_GetContextID(wus->window_id) &&
!wus->URL_s->load_background)
{
LIBNET_UNLOCK();
return(TRUE);
}
}
/* check for connections in the connections wait queue
*/
list_ptr = net_waiting_for_connection_url_list;
while((wus = (WaitingURLStruct*) XP_ListNextObject(list_ptr)) != NULL)
{
if(cur_win_id == FE_GetContextID(wus->window_id) &&
!wus->URL_s->load_background)
{
LIBNET_UNLOCK();
return(TRUE);
}
}
/* run through the whole list of active connections and
* return true if any of them have the passed in window id
*/
list_ptr = net_EntryList;
while((tmpEntry = (ActiveEntry *) XP_ListNextObject(list_ptr)) != NULL)
{
if(cur_win_id == FE_GetContextID(tmpEntry->window_id) &&
!tmpEntry->URL_s->load_background)
{
LIBNET_UNLOCK();
return(TRUE);
}
} /* end while */
LIBNET_UNLOCK();
return(FALSE);
}
/*
* GAB 04-23-96
* We're interested in knowing if there are any operations which
* will cause activity of the said type, in the said context.
* This is in the interests of PE, where they desire a world of
* dial on demand (hanging up the phone when we're not doing dick
* on the network).
*
* Args:
* window_id The said context to check.
* If NULL, check them all (disregard).
* waiting Include waiting queues in check if TRUE.
* Note that waiting queues do not know thier type
* yet (local, cache, or net), thus type can not
* be correctly checked. I can only assume that
* we have the technology to mostly decide this
* before the fact, but I see no facility available.
* background Include background activity in the check if TRUE.
* Returns:
* Bool TRUE, there is chance of activity of said type.
* FALSE, that particular type of activity is not present.
*
*/
PUBLIC Bool
NET_HasNetworkActivity(MWContext * window_id, Bool waiting, Bool background)
{
ActiveEntry * tmpEntry;
XP_List * list_ptr;
WaitingURLStruct * wus;
LIBNET_LOCK();
TRACEMSG(("-------NET_HasNetworkActivity called!"));
/* check for connections in the wait queue
*/
if(waiting)
{
list_ptr = net_waiting_for_actives_url_list;
while((wus = (WaitingURLStruct*) XP_ListNextObject(list_ptr)) != NULL)
{
if((window_id == NULL ||
FE_GetContextID(window_id) ==
FE_GetContextID(wus->window_id)) &&
(background || !wus->URL_s->load_background))
{
LIBNET_UNLOCK();
return(TRUE);
}
}
/* check for connections in the connections wait queue
*/
list_ptr = net_waiting_for_connection_url_list;
while((wus = (WaitingURLStruct*) XP_ListNextObject(list_ptr)) != NULL)
{
if((window_id == NULL ||
FE_GetContextID(window_id) ==
FE_GetContextID(wus->window_id)) &&
(background || !wus->URL_s->load_background))
{
LIBNET_UNLOCK();
return(TRUE);
}
}
}
/* run through the whole list of active connections
*/
list_ptr = net_EntryList;
while((tmpEntry = (ActiveEntry *) XP_ListNextObject(list_ptr)) != NULL)
{
if((window_id == NULL ||
FE_GetContextID(window_id) ==
FE_GetContextID(tmpEntry->window_id)) &&
(background || !tmpEntry->URL_s->load_background) &&
!tmpEntry->memory_file &&
!tmpEntry->local_file)
{
LIBNET_UNLOCK();
return(TRUE);
}
} /* end while */
LIBNET_UNLOCK();
return(FALSE);
}
/* malloc, init, and set the URL structure used
* for the network library
*/
PUBLIC URL_Struct *
NET_CreateURLStruct (CONST char *url, NET_ReloadMethod force_reload)
{
uint32 all_headers_size;
URL_Struct * URL_s = XP_NEW(URL_Struct);
if(!URL_s)
{
return NULL;
}
/* zap the whole structure */
XP_MEMSET (URL_s, 0, sizeof (URL_Struct));
/* we haven't modified the address at all (since we are just creating it)*/
URL_s->address_modified=NO;
URL_s->method = URL_GET_METHOD;
URL_s->force_reload = force_reload;
URL_s->load_background = FALSE;
/* Allocate space for pointers to hold message (http, news etc) headers */
all_headers_size =
INITIAL_MAX_ALL_HEADERS * sizeof (URL_s->all_headers.key[0]);
URL_s->all_headers.key = (char **) XP_ALLOC(all_headers_size);
if(!URL_s->all_headers.key)
{
NET_FreeURLStruct(URL_s);
return NULL;
}
XP_MEMSET (URL_s->all_headers.key, 0, all_headers_size);
all_headers_size =
INITIAL_MAX_ALL_HEADERS * sizeof (URL_s->all_headers.value[0]);
URL_s->all_headers.value = (char **) XP_ALLOC(all_headers_size);
if(!URL_s->all_headers.value)
{
NET_FreeURLStruct(URL_s);
return NULL;
}
XP_MEMSET (URL_s->all_headers.value, 0, all_headers_size);
URL_s->all_headers.max_index = INITIAL_MAX_ALL_HEADERS;
/* set the passed in value */
StrAllocCopy(URL_s->address, url);
if (!URL_s->address) {
/* out of memory, clean up previously allocated objects */
NET_FreeURLStruct(URL_s);
URL_s = NULL;
}
return(URL_s);
}
/* Increase the size of AllHeaders in URL_struct
*/
PRIVATE Bool
net_EnlargeURLAllHeaders (URL_Struct * URL_s)
{
uint32 number_of_entries =
URL_s->all_headers.empty_index * MULT_ALL_HEADER_COUNT;
uint32 realloc_size =
number_of_entries * sizeof (URL_s->all_headers.key[0]);
char **temp;
if (number_of_entries < MAX_ALL_HEADER_COUNT) {
temp = (char **) XP_REALLOC(URL_s->all_headers.key, realloc_size);
if (URL_s->all_headers.key) {
URL_s->all_headers.key = temp;
temp = (char **) XP_REALLOC(URL_s->all_headers.value, realloc_size);
if (URL_s->all_headers.value) {
URL_s->all_headers.value = temp;
URL_s->all_headers.max_index = number_of_entries;
return(TRUE);
}
}
}
net_FreeURLAllHeaders(URL_s);
return(FALSE);
}
/* Append Key, Value pair into AllHeaders list of URL_struct
*/
PUBLIC Bool
NET_AddToAllHeaders(URL_Struct * URL_s, char *name, char *value)
{
char *key_ptr;
char *value_ptr;
XP_ASSERT(URL_s);
XP_ASSERT(name);
XP_ASSERT(value);
if ((URL_s->all_headers.empty_index >= URL_s->all_headers.max_index) &&
(!net_EnlargeURLAllHeaders(URL_s))) {
return(FALSE);
}
key_ptr = URL_s->all_headers.key[URL_s->all_headers.empty_index] =
XP_STRDUP(name);
if (!key_ptr) {
net_FreeURLAllHeaders(URL_s);
return(FALSE);
}
value_ptr = URL_s->all_headers.value[URL_s->all_headers.empty_index] =
XP_STRDUP(value);
if (!value_ptr) {
XP_FREE(key_ptr);
URL_s->all_headers.key[URL_s->all_headers.empty_index] = NULL;
net_FreeURLAllHeaders(URL_s);
return(FALSE);
}
URL_s->all_headers.empty_index++;
return(TRUE);
}
/* Set the option IPAddressString field
* This field overrides the hostname when doing the connect,
* and allows Java to specify a spelling of an IP number.
* Out of memory condition will cause the URL_struct to be destroyed.
*/
PUBLIC int
NET_SetURLIPAddressString (URL_Struct * URL_s, CONST char *ip_string)
{
XP_ASSERT(URL_s);
FREEIF(URL_s->IPAddressString);
URL_s->IPAddressString = NULL;
/* set the passed in value */
StrAllocCopy(URL_s->IPAddressString, ip_string);
return NULL == URL_s->IPAddressString;
}
/* free the contents and the URL structure when finished
*/
PUBLIC void
NET_FreeURLStruct (URL_Struct * URL_s)
{
#ifdef XP_WIN
/*
* Call the front end to have it free off any
* special data it has hanging off the
* structure. In specific, the ncapi stuff.
*/
FE_DeleteUrlData(URL_s);
#endif /* XP_WIN */
FREEIF(URL_s->address);
FREEIF(URL_s->username);
FREEIF(URL_s->password);
FREEIF(URL_s->IPAddressString);
FREEIF(URL_s->referer);
FREEIF(URL_s->post_data);
FREEIF(URL_s->post_headers);
FREEIF(URL_s->content_type);
FREEIF(URL_s->content_encoding);
FREEIF(URL_s->x_mac_type);
FREEIF(URL_s->x_mac_creator);
FREEIF(URL_s->charset);
FREEIF(URL_s->boundary);
FREEIF(URL_s->redirecting_url);
FREEIF(URL_s->authenticate);
FREEIF(URL_s->protection_template);
FREEIF(URL_s->http_headers);
FREEIF(URL_s->cache_file);
FREEIF(URL_s->window_target);
FREEIF(URL_s->window_chrome);
FREEIF(URL_s->refresh_url);
FREEIF(URL_s->wysiwyg_url);
FREEIF(URL_s->error_msg);
FREEIF(URL_s->key_cipher);
FREEIF(URL_s->key_issuer);
FREEIF(URL_s->key_subject);
#ifdef HAVE_SECURITY /* added by jwz */
if ( URL_s->certificate ) {
CERT_DestroyCertificate(URL_s->certificate);
}
if ( URL_s->redirecting_cert ) {
CERT_DestroyCertificate(URL_s->redirecting_cert);
}
#endif /* !HAVE_SECURITY -- added by jwz */
/* Free all memory associated with header information */
net_FreeURLAllHeaders(URL_s);
if(URL_s->files_to_post)
{
/* free a null terminated array of filenames
*/
int i=0;
for(i=0; URL_s->files_to_post[i] != NULL; i++)
{
FREE(URL_s->files_to_post[i]); /* free the filenames */
}
FREE(URL_s->files_to_post); /* free the array */
}
XP_FREE(URL_s);
}
/* free the contents of AllHeader structure that is part of URL_Struct
*/
PRIVATE void
net_FreeURLAllHeaders (URL_Struct * URL_s)
{
uint32 i=0;
/* Free all memory associated with header information */
for (i = 0; i < URL_s->all_headers.empty_index; i++) {
if (URL_s->all_headers.key) {
FREEIF(URL_s->all_headers.key[i]);
}
if (URL_s->all_headers.value) {
FREEIF(URL_s->all_headers.value[i]);
}
}
URL_s->all_headers.empty_index = URL_s->all_headers.max_index = 0;
FREEIF(URL_s->all_headers.key);
FREEIF(URL_s->all_headers.value);
URL_s->all_headers.key = URL_s->all_headers.value = NULL;
}
/* if there is no slash in a URL besides the two that specify a host
* then add one to the end.
*/
PRIVATE void add_slash_to_URL (URL_Struct *URL_s)
{
char *colon=XP_STRCHR(URL_s->address,':'); /* must find colon */
char *slash;
/* make sure there is a hostname
*/
if(*(colon+1) == '/' && *(colon+2) == '/')
slash = XP_STRCHR(colon+3,'/');
else
return;
if(slash==NULL)
{
TRACEMSG(("GetURL: URL %s changed to ",URL_s->address));
#ifdef MOZILLA_CLIENT
/* add it now to the Global history since we can't get this
* name back :( this is a bug because we are not sure
* that the link will actually work.
*/
GH_UpdateGlobalHistory(URL_s);
#endif /* MOZILLA_CLIENT */
StrAllocCat(URL_s->address, "/");
URL_s->address_modified = YES;
TRACEMSG(("%s",URL_s->address));
}
}
#ifdef MOZILLA_CLIENT
PRIVATE void
net_OutputURLDocInfo(MWContext *ctxt, char *which, char **data, int32 *length)
{
char *output=0;
URL_Struct *URL_s = NET_CreateURLStruct(which, NET_DONT_RELOAD);
struct tm *tm_struct_p;
char buf[64];
char *tmp=0;
char *sec_msg, *il_msg;
char *charset;
NET_FindURLInCache(URL_s, ctxt);
#define CELL_TOP \
StrAllocCat(output, \
"</A></TD>" \
"<TR><TD VALIGN=BASELINE ALIGN=RIGHT><B>");
#define CELL_TITLE(title) \
StrAllocCat(output, title);
#define CELL_MIDDLE \
StrAllocCat(output, \
"</B></TD>" \
"<TD>");
#define CELL_BODY(body) \
StrAllocCat(output, body);
#define CELL_END \
StrAllocCat(output, \
"</TD></TR>");
#define ADD_CELL(c_title, c_body) \
CELL_TOP; \
CELL_TITLE(c_title); \
CELL_MIDDLE; \
CELL_BODY(c_body); \
CELL_END;
StrAllocCopy(output, "<TABLE>");
StrAllocCopy(tmp, "<A HREF=\"");
StrAllocCat(tmp, URL_s->address);
StrAllocCat(tmp, "\">");
StrAllocCat(tmp, URL_s->address);
StrAllocCat(tmp, "</a>");
if(URL_s->is_netsite)
{
ADD_CELL(XP_GetString(XP_NETSITE_), tmp);
}
else
{
ADD_CELL(XP_GetString(XP_LOCATION_), tmp);
}
FREE(tmp);
ADD_CELL(XP_GetString(XP_FILE_MIME_TYPE_),
URL_s->content_type ? URL_s->content_type : XP_GetString(XP_CURRENTLY_UNKNOWN));
ADD_CELL(XP_GetString(XP_SOURCE_), URL_s->cache_file
? XP_GetString(XP_CURRENTLY_IN_DISK_CACHE)
: URL_s->memory_copy ?
XP_GetString(XP_CURRENTLY_IN_MEM_CACHE)
: XP_GetString(XP_CURRENTLY_NO_CACHE));
ADD_CELL(XP_GetString(XP_LOCAL_CACHE_FILE_), URL_s->cache_file
? URL_s->cache_file
: XP_GetString(XP_NONE));
tm_struct_p = localtime(&URL_s->last_modified);
if(tm_struct_p)
{
#ifdef XP_UNIX
strftime(buf, 64, XP_GetString(XP_LOCAL_TIME_FMT),
tm_struct_p);
#else
char tmpbuf[64];
XP_StrfTime(ctxt,tmpbuf,64,XP_LONG_DATE_TIME_FORMAT,
tm_struct_p);
/* NOTE: XP_LOCAL_TIME_FMT is different depend on platform */
PR_snprintf(buf, 64, XP_GetString(XP_LOCAL_TIME_FMT), tmpbuf);
#endif
}
else
{
buf[0] = 0;
}
ADD_CELL(XP_GetString(XP_LAST_MODIFIED), URL_s->last_modified ? buf : XP_GetString(XP_MSG_UNKNOWN));
tm_struct_p = gmtime(&URL_s->last_modified);
if(tm_struct_p)
{
#ifdef XP_UNIX
strftime(buf, 64, XP_GetString(XP_GMT_TIME_FMT),
tm_struct_p);
#else
char tmpbuf[64];
XP_StrfTime(ctxt,tmpbuf,64,XP_LONG_DATE_TIME_FORMAT,
tm_struct_p);
/* NOTE: XP_GMT_TIME_FMT is different depend on platform */
PR_snprintf(buf, 64, XP_GetString(XP_GMT_TIME_FMT), tmpbuf);
#endif
}
else
{
buf[0] = 0;
}
ADD_CELL(XP_GetString(XP_LAST_MODIFIED), URL_s->last_modified ? buf : XP_GetString(XP_MSG_UNKNOWN));
#ifdef DEBUG
PR_snprintf(buf, 64, "%lu seconds since 1-1-70 GMT", URL_s->last_modified);
ADD_CELL("Last Modified:", URL_s->last_modified ? buf : "Unknown");
#endif
XP_SPRINTF(buf, "%lu", URL_s->content_length);
ADD_CELL(XP_GetString(XP_CONTENT_LENGTH_), URL_s->content_length
? buf
: XP_GetString(XP_MSG_UNKNOWN));
ADD_CELL(XP_GetString(XP_EXPIRES_), URL_s->expires > 0
? INTL_ctime(ctxt, &URL_s->expires)
: XP_GetString(XP_NO_DATE_GIVEN));
if (URL_s->x_mac_type && *URL_s->x_mac_type)
{
ADD_CELL(XP_GetString(XP_MAC_TYPE_), URL_s->x_mac_type);
}
if (URL_s->x_mac_creator && *URL_s->x_mac_creator)
{
ADD_CELL(XP_GetString(XP_MAC_CREATOR_), URL_s->x_mac_creator);
}
if (URL_s->charset)
{
ADD_CELL(XP_GetString(XP_CHARSET_), URL_s->charset);
}
else
{
charset = INTL_CharSetDocInfo(ctxt);
ADD_CELL(XP_GetString(XP_CHARSET_), charset);
FREE(charset);
}
if(URL_s->cache_file || URL_s->memory_copy)
sec_msg = XP_PrettySecurityStatus(URL_s->security_on,
URL_s->key_cipher,
URL_s->key_size,
URL_s->key_secret_size);
else
sec_msg = XP_STRDUP(XP_GetString(XP_STATUS_UNKNOWN));
if(sec_msg)
{
ADD_CELL(XP_GetString(XP_SECURITY_), sec_msg);
FREE(sec_msg);
}
#ifdef HAVE_SECURITY /* added by jwz */
if(URL_s->certificate)
sec_msg = CERT_HTMLCertInfo(URL_s->certificate, PR_TRUE);
else
#endif /* !HAVE_SECURITY -- added by jwz */
sec_msg = 0;
#ifndef NO_SSL /* added by jwz */
if(sec_msg)
{
char *extstring;
extstring = SECNAV_MakeCertButtonString(URL_s->certificate);
if ( extstring ) {
StrAllocCat(sec_msg, extstring);
XP_FREE(extstring);
}
ADD_CELL(XP_GetString(XP_CERTIFICATE_), sec_msg);
FREE(sec_msg);
}
#endif /* NO_SSL -- added by jwz */
StrAllocCat(output, "</TABLE>");
if(URL_s->content_type
&& !strncasecomp(URL_s->content_type, "image", 5))
{
/* Have a seat. Lie down. Tell me about yourself. */
il_msg = IL_HTMLImageInfo(URL_s->address);
if (il_msg) {
StrAllocCat(output, "<HR>\n");
StrAllocCat(output, il_msg);
XP_FREE(il_msg);
}
}
*data = output;
*length = XP_STRLEN(output);
NET_FreeURLStruct(URL_s);
return;
}
/* prints information about a context usint HTML.
*
* The context passed in as arg2 is the context that
* we are printing info about and the context that
* is in the ActiveEntry is the window we are displaying
* within
*/
PRIVATE
int
net_PrintContextInfo(ActiveEntry *cur_entry, MWContext *context)
{
History_entry *his;
NET_StreamClass *stream;
char buf[64];
char *tmp;
/* get the current history entry and
* extract the URL from it. That has
* the top level document URL and the title
*/
his = SHIST_GetCurrent (&context->hist);
cur_entry->format_out = CLEAR_CACHE_BIT(cur_entry->format_out);
StrAllocCopy(cur_entry->URL_s->content_type, TEXT_HTML);
stream = NET_StreamBuilder(cur_entry->format_out,
cur_entry->URL_s, cur_entry->window_id);
if(!stream)
return(MK_UNABLE_TO_CONVERT);
XP_STRCPY(buf, "<FONT SIZE=+2><b>");
(*stream->put_block)(stream->data_object, buf, XP_STRLEN(buf));
if(his && his->title)
tmp = XP_STRDUP(his->title);
else
tmp = XP_STRDUP(XP_GetString(XP_UNTITLED_DOCUMENT));
(*stream->put_block)(stream->data_object, tmp, XP_STRLEN(tmp));
XP_STRCPY(buf, XP_GetString(XP_HAS_THE_FOLLOWING_STRUCT));
(*stream->put_block)(stream->data_object, buf, XP_STRLEN(buf));
LO_DocumentInfo(context, stream);
(*stream->complete)(stream->data_object);
cur_entry->status = MK_DATA_LOADED;
cur_entry->status = MK_DATA_LOADED;
return(-1);
}
#endif /* MOZILLA_CLIENT */
/* print out silly about type URL
*/
PRIVATE int net_output_about_url(ActiveEntry * cur_entry)
{
NET_StreamClass * stream;
char * data=0;
char * content_type=0;
int32 length;
char * which = cur_entry->URL_s->address;
char * colon = strchr (which, ':');
void * fe_data = NULL;
Bool uses_fe_data=FALSE;
if (colon)
which = colon + 1;
if(0)
{
/* placeholder to make ifdef's easier */
}
#ifdef MOZILLA_CLIENT
else if(NET_URL_Type(which))
{
/* this url is asking for document info about this
* URL.
* Call a NET function to generate the HTML block
*/
net_OutputURLDocInfo(cur_entry->window_id, which, &data, &length);
StrAllocCopy(content_type, TEXT_HTML);
}
else if(!strcasecomp(which, "cache"))
{
NET_DisplayCacheInfoAsHTML(cur_entry);
return(-1);
}
else if(!strcasecomp(which, "memory-cache"))
{
NET_DisplayMemCacheInfoAsHTML(cur_entry);
return(-1);
}
else if(!strcasecomp(which, "image-cache"))
{
IL_DisplayMemCacheInfoAsHTML(cur_entry->format_out, cur_entry->URL_s,
cur_entry->window_id);
return(-1);
}
else if(!strcasecomp(which, "document"))
{
char buf[64];
History_entry *his;
MWContext *context;
/* output a Grid here with the first grid
* cell containing an about: url with the
* context pointer as the argument.
*
* also put the context pointer in as the post data
* if it's not there already so that history will
* do the right thing.
*
* also output blank string for all FO's not view source
* and save
*/
/* if there is post data then a context ID is hiding
* in there. Get it and verify it
*/
if(cur_entry->URL_s->post_data)
{
#if defined(__sun) && !defined(SVR4) /* sun 4.1.3 */
sscanf(cur_entry->URL_s->post_data, "%lu", &context);
#else
sscanf(cur_entry->URL_s->post_data, "%p", &context);
#endif
if(!XP_IsContextInList(context))
context = cur_entry->window_id;
}
else
{
context = cur_entry->window_id;
}
/* get the current history entry and
* extract the URL from it. That has
* the top level document URL
*/
his = SHIST_GetCurrent (&context->hist);
StrAllocCat(data, "<TITLE>");
StrAllocCat(data, XP_GetString(XP_DOCUMENT_INFO));
StrAllocCat(data, "</TITLE>"
"<frameset rows=\"40%,60%\">"
"<frame src=about:");
StrAllocCopy(cur_entry->URL_s->window_target, "%DocInfoWindow");
/* add a Chrome Struct so that we can control the window */
cur_entry->URL_s->window_chrome = XP_NEW(Chrome);
if(cur_entry->URL_s->window_chrome)
{
XP_MEMSET(cur_entry->URL_s->window_chrome, 0, sizeof(Chrome));
/* it should be MWContextDialog
* but X isn't ready for it yet...
*/
#ifdef XP_UNIX
cur_entry->URL_s->window_chrome->type = MWContextBrowser;
#else
cur_entry->URL_s->window_chrome->type = MWContextDialog;
#endif
cur_entry->URL_s->window_chrome->show_scrollbar = TRUE;
cur_entry->URL_s->window_chrome->allow_resize = TRUE;
cur_entry->URL_s->window_chrome->allow_close = TRUE;
}
/* don't let people really view the source of this... */
if(FO_PRESENT != CLEAR_CACHE_BIT(cur_entry->format_out))
{
StrAllocCat(data, "blank");
}
else
{
StrAllocCat(data, "FeCoNtExT=");
if(!cur_entry->URL_s->post_data)
{
#if defined(__sun) && !defined(SVR4) /* sun 4.1.3 */
XP_SPRINTF(buf, "%lu", context);
#else
XP_SPRINTF(buf, "%p", context);
#endif
StrAllocCat(data, buf);
StrAllocCopy(cur_entry->URL_s->post_data, buf);
}
else
{
StrAllocCat(data, cur_entry->URL_s->post_data);
}
}
StrAllocCat(data, "><frame name=Internal_URL_Info src=about:");
if(his && his->address)
StrAllocCat(data, his->address);
else
StrAllocCat(data, "blank");
StrAllocCat(data, "></frameset>");
length = XP_STRLEN(data);
StrAllocCopy(content_type, TEXT_HTML);
}
else if(!strncasecomp(which, "Global", 6))
{
cur_entry->status = NET_DisplayGlobalHistoryInfoAsHTML(
cur_entry->window_id,
cur_entry->URL_s,
cur_entry->format_out);
return(-1);
}
else if(!XP_STRNCMP(which, "FeCoNtExT=", 10))
{
MWContext *old_ctxt;
#if defined(__sun) && !defined(SVR4) /* sun 4.1.3 */
sscanf(which+10, "%lu", &old_ctxt);
#else
sscanf(which+10, "%p", &old_ctxt);
#endif
/* verify that we have the right context
*
*/
if(!XP_IsContextInList(old_ctxt))
{
StrAllocCopy(data, XP_GetString(XP_THE_WINDOW_IS_NOW_INACTIVE));
}
else
{
return(net_PrintContextInfo(cur_entry, old_ctxt));
}
length = XP_STRLEN(data);
StrAllocCopy(content_type, TEXT_HTML);
}
#endif /* MOZILLA_CLIENT */
else if(!strncasecomp(which, "authors", 7))
{
static const char *d =
("<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html\" "
"CHARSET=\"iso-8859-1\"><TITLE>Mozilla Über Alles</TITLE>"
"<BODY BGCOLOR=\"#C0C0C0\" TEXT=\"#000000\">"
"<TABLE width=\"100%\" height=\"100%\"><TR><TD ALIGN=CENTER>"
"<FONT SIZE=5><FONT COLOR=\"#0000EE\">about:authors</FONT> "
"removed.</FONT></TD></TR></TABLE>");
data = XP_STRDUP(d);
length = (d ? XP_STRLEN(d) : 0);
content_type = XP_STRDUP(TEXT_HTML);
uses_fe_data = FALSE;
}
else
{
fe_data = FE_AboutData(which, &data, &length, &content_type);
uses_fe_data=TRUE;
}
if (!data || !content_type)
{
cur_entry->status = MK_MALFORMED_URL_ERROR;
}
else
{
int status;
StrAllocCopy(cur_entry->URL_s->content_type, content_type);
cur_entry->format_out = CLEAR_CACHE_BIT(cur_entry->format_out);
stream = NET_StreamBuilder(cur_entry->format_out,
cur_entry->URL_s, cur_entry->window_id);
if(!stream)
{
cur_entry->status = MK_UNABLE_TO_CONVERT;
return(MK_UNABLE_TO_CONVERT);
}
status = (*stream->put_block)(stream->data_object, data, length);
if (status >= 0)
(*stream->complete) (stream->data_object);
else
(*stream->abort) (stream->data_object, status);
cur_entry->status = status;
FREE(stream);
}
if(uses_fe_data)
{
#ifdef XP_MAC
FE_FreeAboutData (fe_data, which);
#endif /* XP_MAC */
}
else
{
FREE(data);
FREE(content_type);
}
return(-1);
}
#ifdef MOZILLA_CLIENT
#ifndef NO_SSL /* added by jwz */
/* print out security URL
*/
PRIVATE int net_output_security_url(ActiveEntry * cur_entry, MWContext *cx)
{
NET_StreamClass * stream;
char * content_type;
char * which = cur_entry->URL_s->address;
char * colon = XP_STRCHR (which, ':');
if (colon)
{
/* found the first colon; now find the question mark
(as in "about:security?certs"). */
which = colon + 1;
colon = XP_STRCHR (which, '?');
if (colon)
which = colon + 1;
else
which = which + XP_STRLEN (which); /* give it "" */
}
content_type = SECNAV_SecURLContentType(which);
if (!content_type) {
cur_entry->status = MK_MALFORMED_URL_ERROR;
} else if (!strcasecomp(content_type, "advisor")) {
cur_entry->status = SECNAV_SecHandleSecurityAdvisorURL(cx, which);
} else {
int status;
StrAllocCopy(cur_entry->URL_s->content_type, content_type);
cur_entry->format_out = CLEAR_CACHE_BIT(cur_entry->format_out);
stream = NET_StreamBuilder(cur_entry->format_out,
cur_entry->URL_s, cur_entry->window_id);
if (!stream)
return(MK_UNABLE_TO_CONVERT);
status = SECNAV_SecURLData(which, stream, cx);
if (status >= 0) {
(*stream->complete) (stream->data_object);
} else {
(*stream->abort) (stream->data_object, status);
}
cur_entry->status = status;
FREE(stream);
}
return(-1);
}
#endif /* NO_SSL -- added by jwz */
#endif /* MOZILLA_CLIENT */
PRIVATE Bool net_about_kludge(URL_Struct *URL_s)
{
unsigned char *url = (unsigned char *) URL_s->address;
unsigned char *user = (unsigned char *) XP_STRDUP ((char*)(url + 6));
unsigned char *tmp;
if (user == NULL)
return FALSE;
for (tmp = user; *tmp; tmp++) *tmp += 23;
if(!XP_STRCMP((char*)user, "\170\211\200") || /* ari */
!XP_STRCMP((char*)user, "\170\213\206\213\200\172") || /* atotic */
!XP_STRCMP((char*)user, "\171\203\220\213\177\174") || /* blythe */
!XP_STRCMP((char*)user, "\172\177\206\214\172\202") || /* chouck */
!XP_STRCMP((char*)user, "\172\204\170\205\212\202\174") || /* cmanske */
!XP_STRCMP((char*)user, "\173\202\170\211\203\213\206\205") || /* dkarlton */
!XP_STRCMP((char*)user, "\173\204\206\212\174") || /* dmose */
!XP_STRCMP((char*)user, "\173\207") || /* dp */
!XP_STRCMP((char*)user, "\174\171\200\205\170") || /* ebina */
!XP_STRCMP((char*)user, "\175\213\170\205\176") || /* ftang */
!XP_STRCMP((char*)user, "\174\211\200\202") || /* erik */
!XP_STRCMP((char*)user, "\172\217\214\174") || /* cxue */
!XP_STRCMP((char*)user, "\171\206\171\201") || /* bobj */
!XP_STRCMP((char*)user, "\175\214\171\200\205\200") || /* fubini */
!XP_STRCMP((char*)user, "\175\214\211") || /* fur */
!XP_STRCMP((char*)user, "\177\170\176\170\205") || /* hagan */
!XP_STRCMP((char*)user, "\201\170\211") || /* jar */
!XP_STRCMP((char*)user, "\201\174\175\175") || /* jeff */
!XP_STRCMP((char*)user, "\201\176") || /* jg */
!XP_STRCMP((char*)user, "\201\216\221") || /* jwz */
!XP_STRCMP((char*)user, "\201\212\216") || /* jsw */
!XP_STRCMP((char*)user, "\202\170\211\203\213\206\205") || /* karlton */
!XP_STRCMP((char*)user, "\202\200\207\207") || /* kipp */
!XP_STRCMP((char*)user, "\203\213\170\171\171") || /* ltabb */
!XP_STRCMP((char*)user, "\204\170\211\172\170") || /* marca */
!XP_STRCMP((char*)user, "\204\203\204") || /* mlm */
!XP_STRCMP((char*)user, "\204\206\205\213\214\203\203\200")|| /*montulli*/
!XP_STRCMP((char*)user, "\204\213\206\220") || /* mtoy */
!XP_STRCMP((char*)user, "\207\170\210\214\200\205") || /* paquin */
!XP_STRCMP((char*)user, "\207\170\203\174\215\200\172\177") || /* palevich */
!XP_STRCMP((char*)user, "\211\170\204\170\205") || /* raman */
!XP_STRCMP((char*)user, "\211\174\207\202\170") ||
/* repka */
!XP_STRCMP((char*)user, "\211\206\171\204") || /* robm */
!XP_STRCMP((char*)user, "\211\206\174\171\174\211") || /* roeber */
!XP_STRCMP((char*)user, "\212\177\170\211\206\205\200") || /* sharoni */
!XP_STRCMP((char*)user, "\204\170\203\204\174\211") || /* malmer */
!XP_STRCMP((char*)user, "\212\202") || /* sk */
!XP_STRCMP((char*)user, "\212\207\174\205\172\174") || /* spence */
!XP_STRCMP((char*)user, "\213\174\211\211\220") || /* terry */
!XP_STRCMP((char*)user, "\213\200\204\204")) /* timm */
{
char *head = ("\177\213\213\207\121\106\106\177\206\204\174\105\205"
"\174\213\212\172\170\207\174\105\172\206\204\106\207"
"\174\206\207\203\174\106"
/* "http://home.netscape.com/people/" */
);
unsigned char *location = (unsigned char *)
XP_ALLOC (XP_STRLEN ((char *) head) + XP_STRLEN ((char *) user) + 2);
if (! location)
{
XP_FREE (user);
return FALSE;
}
XP_STRCPY ((char *) location, (char *) head);
XP_STRCAT ((char *) location, (char *) user);
for (tmp = location; *tmp; tmp++) *tmp -= 23;
XP_STRCAT ((char *) location, "/");
XP_FREE (user);
XP_FREE (URL_s->address);
URL_s->address = (char *) location;
URL_s->address_modified = TRUE;
return TRUE;
}
else
{
XP_FREE (user);
return FALSE;
}
}
/*
* Check the no_proxy environment variable to get the list
* of hosts for which proxy server is not consulted.
*
* no_proxy is a comma- or space-separated list of machine
* or domain names, with optional :port part. If no :port
* part is present, it applies to all ports on that domain.
*
* Example: "netscape.com,some.domain:8001"
*
*/
PRIVATE Bool override_proxy (CONST char * URL)
{
char * p = NULL;
char * host = NULL;
int port = 0;
int h_len = 0;
char *no_proxy = MKno_proxy;
if(no_proxy==NULL)
return(FALSE);
if (!(host = NET_ParseURL(URL, GET_HOST_PART)))
return NO;
if (!*host)
{
XP_FREE(host);
return NO;
}
p = XP_STRCHR(host, ':');
if (p) /* Port specified */
{
*p++ = 0; /* Chop off port */
port = atoi(p);
}
else
{ /* Use default port */
char * access = NET_ParseURL(URL, GET_PROTOCOL_PART);
if (access) {
if (!XP_STRCMP(access,"http")) port = 80;
else if (!XP_STRCMP(access,"gopher")) port = 70;
else if (!XP_STRCMP(access,"ftp")) port = 21;
XP_FREE(access);
}
}
if (!port) port = 80; /* Default */
h_len = XP_STRLEN(host);
while (*no_proxy) {
char * end;
char * colon = NULL;
int templ_port = 0;
int t_len;
while (*no_proxy && (isspace(*no_proxy) || *no_proxy==','))
no_proxy++; /* Skip whitespace and separators */
end = no_proxy;
while (*end && !isspace(*end) && *end != ',') /* Find separator */
{
if (*end==':') colon = end; /* Port number given */
end++;
}
if (colon)
{
templ_port = atoi(colon+1);
t_len = colon - no_proxy;
}
else
{
t_len = end - no_proxy;
}
/* don't worry about case when comparing the requested host to the proxies in the
no proxy list, i.e. use XP_STRNCASECMP */
if ((!templ_port || templ_port == port) && (t_len > 0 && t_len <= h_len &&
!XP_STRNCASECMP(host + h_len - t_len, no_proxy, t_len)))
{
XP_FREE(host);
return YES;
}
if (*end)
no_proxy = end+1;
else
break;
}
XP_FREE(host);
return NO;
}
PUBLIC void
NET_SetProxyServer(NET_ProxyType type, const char * org_host_port)
{
char *host_port = 0;
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
if(org_host_port && *org_host_port) {
host_port = XP_STRDUP(org_host_port);
if(!host_port)
return;
/* limit the size of host_port to within MAXHOSTNAMELEN */
if(XP_STRLEN(host_port) > MAXHOSTNAMELEN)
host_port[MAXHOSTNAMELEN] = '\0';
}
TRACEMSG(("NET_SetProxyServer called with host: %s",
host_port ? host_port : "(null)"));
switch(type)
{
case PROXY_AUTOCONF_URL:
if (host_port) {
if (!MKproxy_ac_url || XP_STRCMP(MKproxy_ac_url, org_host_port)) {
StrAllocCopy(MKproxy_ac_url, org_host_port);
NET_ProxyAcLoaded = FALSE;
}
}
else {
if (MKproxy_ac_url) {
FREE_AND_CLEAR(MKproxy_ac_url);
NET_ProxyAcLoaded = FALSE;
}
}
break;
case FTP_PROXY:
if(host_port)
StrAllocCopy(MKftp_proxy, host_port);
else
FREE_AND_CLEAR(MKftp_proxy);
break;
case GOPHER_PROXY:
if(host_port)
StrAllocCopy(MKgopher_proxy, host_port);
else
FREE_AND_CLEAR(MKgopher_proxy);
break;
case HTTP_PROXY:
if(host_port)
StrAllocCopy(MKhttp_proxy, host_port);
else
FREE_AND_CLEAR(MKhttp_proxy);
break;
case HTTPS_PROXY:
if(host_port)
StrAllocCopy(MKhttps_proxy, host_port);
else
FREE_AND_CLEAR(MKhttps_proxy);
break;
case NEWS_PROXY:
if(host_port)
StrAllocCopy(MKnews_proxy, host_port);
else
FREE_AND_CLEAR(MKnews_proxy);
break;
case WAIS_PROXY:
if(host_port)
StrAllocCopy(MKwais_proxy, host_port);
else
FREE_AND_CLEAR(MKno_proxy);
break;
case NO_PROXY:
if(host_port)
StrAllocCopy(MKno_proxy, org_host_port);
break;
default:
/* ignore */
break;
}
FREEIF(host_port);
}
/*
* Select proxy style; one of:
* PROXY_STYLE_MANUAL -- old style proxies
* PROXY_STYLE_AUTOMATIC -- new style proxies
* PROXY_STYLE_NONE -- no proxies
*
*/
PUBLIC void
NET_SelectProxyStyle(NET_ProxyStyle style)
{
if (MKproxy_style != style) {
NET_ProxyAcLoaded = FALSE;
}
MKproxy_style = style;
if (MKproxy_style != PROXY_STYLE_AUTOMATIC) {
FREE_AND_CLEAR(MKproxy_ac_url);
NET_ProxyAcLoaded = FALSE;
}
if (MKproxy_style != PROXY_STYLE_MANUAL) {
FREE_AND_CLEAR(MKftp_proxy);
FREE_AND_CLEAR(MKgopher_proxy);
FREE_AND_CLEAR(MKhttp_proxy);
FREE_AND_CLEAR(MKhttps_proxy);
FREE_AND_CLEAR(MKwais_proxy);
FREE_AND_CLEAR(MKnews_proxy);
FREE_AND_CLEAR(MKno_proxy);
NET_SetSocksHost(NULL);
}
}
/*
* Force it to reload automatic proxy config.
*
*
*/
#ifdef MOZILLA_CLIENT
PUBLIC void
NET_ReloadProxyConfig(MWContext *window_id)
{
if (MKproxy_ac_url &&
(!MKproxy_style || MKproxy_style == PROXY_STYLE_AUTOMATIC))
{
NET_ProxyAcLoaded = FALSE;
}
}
#endif /* MOZILLA_CLIENT */
/* Debugging routine prints an URL (and string "header")
*/
#ifdef DEBUG
void TraceURL (URL_Struct *url, char *header)
{
TRACEMSG(("URL %s", header));
if (url->address) TRACEMSG((" address %s", url->address));
if (url->content_length) TRACEMSG((" content_length %i", url->content_length));
if (url->content_type) TRACEMSG((" content_type %s", url->content_type));
if (url->content_encoding) TRACEMSG((" content_encoding %s", url->content_encoding));
}
#endif
#if 0
/* This function's existance was prompted by the front end desiring the ability to put the
client in kiosk mode. The function removes any potentially sensitive information from the
background: passwords, caches, histories, cookies. */
PUBLIC void
NET_DestroyEvidence()
{
int32 oldSize = 0;
/* Handle authorizations */
NET_RemoveAllAuthorizations();
/* Handle global history */
GH_ClearGlobalHistory();
/* Handle Session History */
/* Handle cookies */
NET_RemoveAllCookies();
/* Handle disk cache */
oldSize = NET_GetDiskCacheSize();
NET_SetDiskCacheSize(0); /* zero it out */
NET_SetDiskCacheSize(oldSize); /* set it back up */
/* Handle memory cache */
oldSize = NET_GetMemoryCacheSize();
NET_SetMemoryCacheSize(0); /* zero it out */
NET_SetMemoryCacheSize(oldSize); /* set it back up */
}
#endif
#ifdef PROFILE
#pragma profile off
#endif