home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
- /*
- * state machine to speak HTTP
- *
- * Designed and implemented by Lou Montulli '94
- * Additions/Changes by Judson Valeski, Gagan Saksena 1997
- */
- #include "rosetta.h"
- #include "mkutils.h"
- #include "mkpadpac.h"
-
- #include "merrors.h"
-
- #include "mkgeturl.h"
- #include "mkhttp.h"
- #include "shist.h"
- #include "glhist.h"
- #include "mkparse.h"
- #include "mktcp.h"
- #include "mkstream.h"
- #include "mkformat.h"
- #include "mkaccess.h"
- #include "mkcache.h"
- #include "mkautocf.h"
- #include "secnav.h"
- #include "cert.h"
- #include "ssl.h"
- #include "jscookie.h"
- #include "prefapi.h"
- #include "xp_error.h"
- #include "libi18n.h"
- #include "prtime.h"
-
-
- /* for XP_GetString() */
- #include "xpgetstr.h"
- extern int MK_REDIRECT_ATTEMPT_NOT_ALLOWED;
- extern int MK_HTTP_TYPE_CONFLICT;
- extern int MK_OUT_OF_MEMORY;
- extern int MK_TCP_READ_ERROR;
- extern int MK_TCP_WRITE_ERROR;
- extern int MK_CONNECTION_REFUSED;
- extern int MK_CONNECTION_TIMED_OUT;
- extern int MK_UNABLE_TO_CONNECT;
- extern int MK_UNABLE_TO_CONNECT_TO_PROXY;
- extern int MK_UNABLE_TO_LOCATE_HOST;
- extern int MK_UNABLE_TO_LOCATE_FILE;
- extern int MK_UNABLE_TO_OPEN_FILE;
- extern int MK_ZERO_LENGTH_FILE;
- extern int MK_COMPUSERVE_AUTH_FAILED;
- extern int XP_ALERT_UNKNOWN_STATUS;
- extern int XP_ERRNO_EWOULDBLOCK;
- extern int XP_PROGRESS_TRANSFER_DATA;
- extern int XP_PROGRESS_TRYAGAIN;
- extern int XP_PROGRESS_WAIT_REPLY;
- extern int XP_HR_TRANSFER_INTERRUPTED;
- extern int XP_TRANSFER_INTERRUPTED;
- extern int XP_ERRNO_EIO;
-
-
- #ifdef PROFILE
- #pragma profile on
- #endif
-
- #define VERSION_STRING "HTTP/1.1"
-
- #define MAX_CACHED_HTTP_CONNECTIONS 4
-
- /* the maximum size of a HTTP servers first line of response
- */
- #define MAX_FIRST_LINE_SIZE 250
-
- /* temporary
- */
- #if defined(XP_WIN) || defined(XP_OS2) /* IBM-SAH */
- PUBLIC char *XP_AppName = 0;
- PUBLIC char *XP_AppCodeName = 0;
- PUBLIC char *XP_AppVersion = 0;
- PUBLIC char *XP_AppLanguage = 0;
- PUBLIC char *XP_AppPlatform = 0;
- #else
- PUBLIC CONST char *XP_AppName = 0;
- PUBLIC CONST char *XP_AppCodeName = 0;
- PUBLIC CONST char *XP_AppVersion = 0;
- PUBLIC CONST char *XP_AppLanguage = 0;
- PUBLIC CONST char *XP_AppPlatform = 0;
- #endif
-
- PUBLIC char * FE_UsersFromField=0; /* User's name/email address not used yet */
-
- PRIVATE XP_List * http_connection_list=0;
- PRIVATE IdentifyMeEnum http_identification_method = DoNotIdentifyMe;
- PRIVATE Bool sendRefererHeader=TRUE;
-
- /* definitions of state for the state machine design
- */
- typedef enum {
- HTTP_START_CONNECT,
- HTTP_FINISH_CONNECT,
- HTTP_SEND_SSL_PROXY_REQUEST,
- HTTP_BEGIN_UPLOAD_FILE,
- HTTP_SEND_REQUEST,
- HTTP_SEND_POST_DATA,
- HTTP_PARSE_FIRST_LINE,
- HTTP_PARSE_MIME_HEADERS,
- HTTP_SETUP_STREAM,
- HTTP_BEGIN_PUSH_PARTIAL_CACHE_FILE,
- HTTP_PUSH_PARTIAL_CACHE_FILE,
- HTTP_PULL_DATA,
- HTTP_DONE,
- HTTP_ERROR_DONE,
- HG93634
- HTTP_FREE
- } StatesEnum;
-
- /* structure to hold data about a tcp connection
- * to a news host
- */
- typedef struct _HTTPConnection {
- char *hostname; /* hostname string (may contain :port) */
- PRFileDesc *sock; /* socket */
- XP_Bool busy; /* is the connection in use already? */
- XP_Bool prev_cache; /* did this connection come from the cache? */
- XP_Bool secure; /* is it a secure connection? */
- } HTTPConnection;
-
- typedef enum {
- POINT_NINE,
- ONE_POINT_O,
- ONE_POINT_ONE
- } HTTP_Version;
-
- /* structure to hold data pertaining to the active state of
- * a transfer in progress.
- *
- */
- typedef struct _HTTPConData {
- StatesEnum next_state; /* the next state or action to be taken */
- char * proxy_server; /* name of proxy server if any */
- char * proxy_conf; /* proxy config ptr from proxy autoconfig */
- char * line_buffer; /* temporary string storage */
- char * server_headers; /* headers from the server for
- * the proxy client
- */
- char * orig_host; /* if the host gets modified
- * for my "netscape" -> "www.netscape.com"
- * hack, the original host gets put here
- */
- XP_File partial_cache_fp;
- int32 partial_needed; /* the part missing from the cache */
-
- int32 total_size_of_files_to_post;
- int32 total_amt_written;
-
- int32 line_buffer_size; /* current size of the line buffer */
-
- HTTPConnection *connection; /* struct to hold info about connection */
-
- NET_StreamClass * stream; /* The output stream */
- Bool pause_for_read; /* Pause now for next read? */
- Bool send_http1; /* should we send http/1.1? */
- Bool acting_as_proxy; /* are we acting as a proxy? */
- Bool server_busy_retry; /* should we retry the get? */
- Bool posting; /* are we posting? */
- Bool doing_redirect; /* are we redirecting? */
- Bool save_redirect_method; /* don't change METHOD when redirecting */
- Bool sent_authorization; /* did we send auth with the request? */
- Bool sent_proxy_auth; /* did we send proxy auth with the req? */
- Bool authorization_required; /* did we get a 401 auth return code? */
- Bool proxy_auth_required; /* did we get a 407 auth return code? */
- Bool destroy_graph_progress; /* destroy graph progress? */
- Bool destroy_file_upload_progress_dialog;
- HTTP_Version protocol_version; /* .9 1.0 or 1.1 */
- int32 original_content_length; /* the content length at the time of
- * calling graph progress
- */
- TCP_ConData *tcp_con_data; /* Data pointer for tcp connect state machine */
- Bool use_ssl_proxy; /* should we use the SSL proxy? */
- Bool ssl_proxy_setup_done; /* is setup done */
- Bool use_copy_from_cache; /* did we get a 304? */
- Bool displayed_some_data; /* have we displayed any data? */
- Bool save_connection; /* save this connection for reuse? */
- Bool partial_cache_file;
- Bool reuse_stream;
- Bool connection_is_valid;
- #ifdef XP_WIN
- Bool calling_netlib_all_the_time; /* is SetCallNetlibAllTheTime set? */
- #endif
- void *write_post_data_data; /* a data object
- * for the WritePostData function
- */
- } HTTPConData;
-
- /* macro's to simplify variable names */
- #define CD_NEXT_STATE cd->next_state
- #define CD_PROXY_SERVER cd->proxy_server
- #define CD_PROXY_CONF cd->proxy_conf
- #define CD_LINE_BUFFER cd->line_buffer
- #define CD_SERVER_HEADERS cd->server_headers
- #define CD_LINE_BUFFER_SIZE cd->line_buffer_size
- #define CD_STREAM cd->stream
- #define CD_SEND_HTTP1 cd->send_http1
- #define CD_PAUSE_FOR_READ cd->pause_for_read
- #define CD_ACTING_AS_PROXY cd->acting_as_proxy
- #define CD_SERVER_BUSY_RETRY cd->server_busy_retry
- #define CD_POSTING cd->posting
- #define CD_DOING_REDIRECT cd->doing_redirect
- #define CD_SENT_AUTHORIZATION cd->sent_authorization
- #define CD_SENT_PROXY_AUTH cd->sent_proxy_auth
- #define CD_AUTH_REQUIRED cd->authorization_required
- #define CD_PROXY_AUTH_REQUIRED cd->proxy_auth_required
- #define CD_DESTROY_GRAPH_PROGRESS cd->destroy_graph_progress
- #define CD_ORIGINAL_CONTENT_LENGTH cd->original_content_length
- #define CD_TCP_CON_DATA cd->tcp_con_data
- #define CD_USE_SSL_PROXY cd->use_ssl_proxy
- #define CD_SSL_PROXY_SETUP_DONE cd->ssl_proxy_setup_done
- #define CD_USE_COPY_FROM_CACHE cd->use_copy_from_cache
- #define CD_DISPLAYED_SOME_DATA cd->displayed_some_data
-
- #define CE_URL_S ce->URL_s
- #define CE_SOCK ce->socket
- #define CE_CON_SOCK ce->con_sock
- #define CE_STATUS ce->status
- #define CE_WINDOW_ID ce->window_id
- #define CE_BYTES_RECEIVED ce->bytes_received
- #define CE_FORMAT_OUT ce->format_out
-
- /* forward decl */
- PRIVATE int32 net_ProcessHTTP (ActiveEntry *ce);
-
- /*
- * replace
- * return(CE_STATUS)
- * with
- * RETURN_CE_STATUS
- */
- PRIVATE
- int ReturnErrorStatus (int status)
- {
- if (status < 0)
- status |= status; /* set a breakpoint HERE to find errors */
- return status;
- }
- #define STATUS(Status) ReturnErrorStatus (Status)
-
- #define PUTBLOCK(b, l) (*cd->stream->put_block) \
- (cd->stream, b, l)
- #define PUTSTRING(s) (*cd->stream->put_block) \
- (cd->stream, s, XP_STRLEN(s))
- #define COMPLETE_STREAM (*cd->stream->complete) \
- (cd->stream)
- #define ABORT_STREAM(s) (*cd->stream->abort) \
- (cd->stream, s)
- PUBLIC void
- NET_SetSendRefererHeader(Bool b)
- {
- sendRefererHeader=b;
- }
-
- /* set the method that the user wishes to identify themselves
- * with.
- * Default is DoNotIdentify unless this is called at startup
- */
- PUBLIC void
- NET_SetIdentifyMeType(IdentifyMeEnum method)
- {
- http_identification_method = method;
- }
-
- /* look for names like "ford" and "netscape"
- * and turn them into "www.ford.com" and "www.netscape.com"
- * If goBrowsing is enabled, this feature is turned off and the browser
- * asks the search provider to resolve the word into a url. This is
- * is prevent a kid typing in bambi (looking for the deer) from being
- * taken to a porn site.
- * returns 0 if found and replaced
- */
-
- PRIVATE int
- net_check_for_company_hostname(ActiveEntry *ce)
- {
- HTTPConData * cd = (HTTPConData *)ce->con_data;
- Bool add_www = FALSE;
- Bool add_com = FALSE;
- Bool goBrowsing = FALSE;
-
- if (PREF_GetBoolPref("browser.goBrowsingEnabled", &goBrowsing) != PREF_OK) goBrowsing = 0;
-
- if(!cd->orig_host)
- {
- char *dot=NULL;
-
- /* if the hostname doesn't have any
- * dots in it, then assume it's of
- * the form "netscape" or "ford".
- * If we add www. and .com to the front
- * and end we will get www.netscape.com :)
- */
- char * host = NET_ParseURL(CE_URL_S->address, GET_HOST_PART);
-
- if(host && *host && !(dot = XP_STRCHR(host, '.')))
- {
- add_www = add_com = TRUE;
- }
- else if(dot && !XP_STRCHR(dot+1, '.'))
- {
- /* there is only one dot in the host name
- * so it's probably of the form of "netscape.com"
- * or "ukans.edu". Add a "www." on the front
- * and try again.
- */
- add_www = TRUE;
- }
-
- if(add_www) {
- /* no dots in hostname */
- if (goBrowsing && !XP_STRCHR(CE_URL_S->address, '/')) {
- char *pUrl;
- PREF_CopyCharPref("network.search.url",&pUrl);
- if (pUrl) {
- char *tmp = NET_ParseURL(CE_URL_S->address, GET_HOST_PART);
- char* new_address = PR_smprintf("%sgo+%s", pUrl, tmp);
- XP_FREE(pUrl);
- FREE(CE_URL_S->address);
- FREEIF(tmp);
- CE_URL_S->address = new_address;
-
- if(cd->connection->sock != NULL)
- NET_TotalNumberOfOpenConnections--;
- return (0);
- } else return (-1);
- } else {
-
- char *new_address = NET_ParseURL(CE_URL_S->address,
- GET_PROTOCOL_PART);
- char *tmp = NET_ParseURL(CE_URL_S->address, GET_HOST_PART);
-
- /* save the host for error messages
- */
- cd->orig_host = tmp;
-
- StrAllocCat(new_address, "//www.");
- StrAllocCat(new_address, tmp);
-
- if(add_com)
- StrAllocCat(new_address, ".com");
-
- tmp = NET_ParseURL(CE_URL_S->address,
- GET_PATH_PART | GET_SEARCH_PART | GET_HASH_PART);
-
- StrAllocCat(new_address, tmp);
- FREEIF(tmp);
-
- FREE(CE_URL_S->address);
- CE_URL_S->address = new_address;
-
- if(cd->connection->sock != NULL)
- NET_TotalNumberOfOpenConnections--;
-
- return(0); /* will repeat this step */
- }
- }
- }
- else
- {
- /* the host mapping trick has already been applied and failed
- * redo the error message and fail
- */
- CE_URL_S->error_msg = NET_ExplainErrorDetails(
- MK_UNABLE_TO_LOCATE_HOST,
- cd->orig_host);
- /* fall through for failure case */
- }
-
- return(-1);
- }
-
- /* begins the connect process
- *
- * returns the TCP status code
- */
- PRIVATE int
- net_start_http_connect(ActiveEntry * ce)
- {
- HTTPConData * cd = (HTTPConData *)ce->con_data;
- Bool use_security=FALSE;
- int def_port;
-
- def_port = DEF_HTTP_PORT;
- if(ce->protocol == SECURE_HTTP_TYPE_URL)
- {
-
- if(CD_PROXY_SERVER)
- {
- CD_USE_SSL_PROXY = TRUE;
- CD_SSL_PROXY_SETUP_DONE = FALSE;
-
- TRACEMSG(("HTTP: Using SSL proxy"));
-
- /* put in code to check for using SSL to a proxy
- * if we need to use ssl set the options
- * on the next two lines
- *
- * use_security = TRUE;
- * def_port = DEF_HTTPS_PORT;
- *
- * @@@@@
- */
- }
- else
- {
- use_security = TRUE;
- def_port = DEF_HTTPS_PORT;
- }
- }
-
- /* if proxy_server is non NULL then use the string as a host:port
- * when a proxy server is used a connection is made to the proxy
- * host and port and the entire URL is sent instead of just
- * the path part.
- */
- if(CD_PROXY_SERVER)
- {
- /* MKConnect can take a URL or a host name as it's first
- * argument
- */
- CE_STATUS = NET_BeginConnect (CD_PROXY_SERVER,
- NULL,
- "HTTP",
- def_port,
- &cd->connection->sock,
- use_security,
- &CD_TCP_CON_DATA,
- CE_WINDOW_ID,
- &CE_URL_S->error_msg,
- ce->socks_host,
- ce->socks_port);
- }
- else
- {
- CE_STATUS = NET_BeginConnect (CE_URL_S->address,
- CE_URL_S->IPAddressString,
- "HTTP",
- def_port,
- &cd->connection->sock,
- use_security,
- &CD_TCP_CON_DATA,
- CE_WINDOW_ID,
- &CE_URL_S->error_msg,
- ce->socks_host,
- ce->socks_port);
- }
-
- /* set this so mkgeturl can select on it */
- CE_SOCK = cd->connection->sock;
-
- if(cd->connection->sock != NULL)
- NET_TotalNumberOfOpenConnections++;
-
- if (CE_STATUS < 0)
- {
- if(CE_STATUS == MK_UNABLE_TO_LOCATE_HOST
- && 0 == net_check_for_company_hostname(ce))
- {
- /* no need to set the state since this
- * is the state we want again
- */
- if(cd->connection->sock != NULL)
- {
- PR_Close(cd->connection->sock);
- cd->connection->sock = NULL;
- CE_SOCK = NULL;
- }
- return(0);
- }
-
- TRACEMSG(("HTTP: Unable to connect to host for `%s' (errno = %d).",
- CE_URL_S->address, SOCKET_ERRNO));
- /*
- * Proxy failover
- */
- if (CD_PROXY_CONF && CD_PROXY_SERVER &&
- (CE_STATUS == MK_UNABLE_TO_CONNECT ||
- CE_STATUS == MK_CONNECTION_TIMED_OUT ||
- CE_STATUS == MK_CONNECTION_REFUSED ||
- CE_STATUS == MK_UNABLE_TO_LOCATE_HOST))
- {
- #ifdef MOZILLA_CLIENT
- if (pacf_get_proxy_addr(CE_WINDOW_ID, CD_PROXY_CONF,
- &ce->proxy_addr,
- &ce->socks_host,
- &ce->socks_port))
- {
- CD_PROXY_SERVER = ce->proxy_addr;
- return net_start_http_connect(ce);
- }
- #endif /* MOZILLA_CLIENT */
- }
-
- if(CE_STATUS == MK_UNABLE_TO_CONNECT && CD_PROXY_SERVER)
- {
- StrAllocCopy (CE_URL_S->error_msg,
- XP_GetString(MK_UNABLE_TO_CONNECT_TO_PROXY));
- CE_STATUS = MK_UNABLE_TO_CONNECT_TO_PROXY;
- }
-
- CD_NEXT_STATE = HTTP_ERROR_DONE;
- return STATUS(CE_STATUS);
- }
-
- if(CE_STATUS == MK_CONNECTED)
- {
- if(CD_USE_SSL_PROXY)
- CD_NEXT_STATE = HTTP_SEND_SSL_PROXY_REQUEST;
- else if(ce->URL_s->files_to_post)
- CD_NEXT_STATE = HTTP_BEGIN_UPLOAD_FILE;
- else
- {
- HG56817
- CD_NEXT_STATE = HTTP_SEND_REQUEST;
- }
- TRACEMSG(("Connected to HTTP server on sock #%d",cd->connection->sock));
- NET_SetReadSelect(CE_WINDOW_ID, cd->connection->sock);
- }
- else
- {
- CD_NEXT_STATE = HTTP_FINISH_CONNECT;
- CD_PAUSE_FOR_READ = TRUE;
- CE_CON_SOCK = cd->connection->sock; /* set the socket for select */
- NET_SetConnectSelect(CE_WINDOW_ID, CE_CON_SOCK);
- }
-
- return STATUS(CE_STATUS);
- }
-
- /* begins the connect process
- *
- * returns the TCP status code
- */
- PRIVATE int
- net_finish_http_connect(ActiveEntry * ce)
- {
- HTTPConData * cd = (HTTPConData *)ce->con_data;
- int def_port;
-
- def_port = DEF_HTTP_PORT;
- if(ce->protocol == SECURE_HTTP_TYPE_URL)
- {
- def_port = DEF_HTTPS_PORT;
- }
-
- /* if proxy_server is non NULL then use the string as a host:port
- * when a proxy server is used a connection is made to the proxy
- * host and port and the entire URL is sent instead of just
- * the path part.
- */
- if(CD_PROXY_SERVER)
- {
- /* MKConnect can take a URL or a host name as it's first
- * argument
- */
- CE_STATUS = NET_FinishConnect(CD_PROXY_SERVER,
- "HTTP",
- def_port,
- &cd->connection->sock,
- &CD_TCP_CON_DATA,
- CE_WINDOW_ID,
- &CE_URL_S->error_msg);
- }
- else
- {
- CE_STATUS = NET_FinishConnect(CE_URL_S->address,
- "HTTP",
- def_port,
- &cd->connection->sock,
- &CD_TCP_CON_DATA,
- CE_WINDOW_ID,
- &CE_URL_S->error_msg);
- }
-
-
- if (CE_STATUS < 0)
- {
- if(CE_STATUS == MK_UNABLE_TO_LOCATE_HOST
- && 0 == net_check_for_company_hostname(ce))
- {
- if(cd->connection->sock != NULL)
- {
- NET_ClearConnectSelect(CE_WINDOW_ID, cd->connection->sock);
- PR_Close(cd->connection->sock);
- cd->connection->sock = NULL;
- CE_SOCK = NULL;
- CE_CON_SOCK = NULL;
- }
- cd->next_state = HTTP_START_CONNECT;
- return(0);
- }
-
- NET_ClearConnectSelect(CE_WINDOW_ID, CE_CON_SOCK);
- TRACEMSG(("HTTP: Unable to connect to host for `%s' (errno = %d).",
- CE_URL_S->address, SOCKET_ERRNO));
-
- /*
- * Proxy failover
- */
- if (CD_PROXY_CONF && CD_PROXY_SERVER &&
- (CE_STATUS == MK_UNABLE_TO_CONNECT ||
- CE_STATUS == MK_CONNECTION_TIMED_OUT ||
- CE_STATUS == MK_CONNECTION_REFUSED ||
- CE_STATUS == MK_UNABLE_TO_LOCATE_HOST))
- {
- #ifdef MOZILLA_CLIENT
- if (pacf_get_proxy_addr(CE_WINDOW_ID, CD_PROXY_CONF,
- &ce->proxy_addr,
- &ce->socks_host,
- &ce->socks_port))
- {
- CD_PROXY_SERVER = ce->proxy_addr;
- return net_start_http_connect(ce);
- }
- #endif /* MOZILLA_CLIENT */
- }
-
- /* proxy autodiscovery failover needs to be silent. If we were trying to
- * connect to a pad server and failed, don't report errors, just go on
- * about your business. */
- if(NET_LoadingPac() && NET_UsingPadPac() ) {
- /* Don't try to use the pad pac again. */
- net_UsePadPac(FALSE);
- CD_NEXT_STATE=HTTP_DONE;
- CE_STATUS=0;
- return STATUS(CE_STATUS);
- }
-
- if(CE_STATUS == MK_UNABLE_TO_CONNECT && CD_PROXY_SERVER)
- {
- StrAllocCopy (CE_URL_S->error_msg,
- XP_GetString(MK_UNABLE_TO_CONNECT_TO_PROXY));
- CE_STATUS = MK_UNABLE_TO_CONNECT_TO_PROXY;
- }
-
- CD_NEXT_STATE = HTTP_ERROR_DONE;
- return STATUS(CE_STATUS);
- }
-
- if(CE_STATUS == MK_CONNECTED)
- {
- NET_ClearConnectSelect(CE_WINDOW_ID, CE_CON_SOCK);
- CE_CON_SOCK = NULL; /* reset the socket so we don't select on it */
- /* set this so mkgeturl can select on it */
- CE_SOCK = cd->connection->sock;
- if(CD_USE_SSL_PROXY)
- CD_NEXT_STATE = HTTP_SEND_SSL_PROXY_REQUEST;
- else if(ce->URL_s->files_to_post)
- CD_NEXT_STATE = HTTP_BEGIN_UPLOAD_FILE;
- else
- {
- HG43241
- CD_NEXT_STATE = HTTP_SEND_REQUEST;
- }
- NET_SetReadSelect(CE_WINDOW_ID, cd->connection->sock);
- TRACEMSG(("Connected to HTTP server on sock #%d",cd->connection->sock));
-
- }
- else
- {
- /* unregister the old CE_SOCK from the select list
- * and register the new value in the case that it changes
- */
- if(ce->con_sock != cd->connection->sock)
- {
- NET_ClearConnectSelect(ce->window_id, ce->con_sock);
- ce->con_sock = cd->connection->sock;
- NET_SetConnectSelect(ce->window_id, ce->con_sock);
- }
-
- CD_PAUSE_FOR_READ = TRUE;
- }
-
- return STATUS(CE_STATUS);
- }
-
- PRIVATE int
- net_send_ssl_proxy_request (ActiveEntry *ce)
- {
- HTTPConData * cd = (HTTPConData *)ce->con_data;
- char *host = NET_ParseURL(CE_URL_S->address, GET_HOST_PART);
- char *command=0;
- char *auth = NULL;
-
- StrAllocCopy(command, "CONNECT ");
- StrAllocCat(command, host);
-
- if(!XP_STRCHR(host, ':'))
- {
- char small_buf[20];
- XP_SPRINTF(small_buf, ":%d", DEF_HTTPS_PORT);
- StrAllocCat(command, small_buf);
- }
-
- StrAllocCat(command, " "VERSION_STRING"\n");
-
- /*
- * Check if proxy is requiring authorization.
- * If NULL, not necessary, or the proxy will return 407 to
- * require authorization.
- *
- */
- if (NULL != (auth=NET_BuildProxyAuthString(CE_WINDOW_ID,
- CE_URL_S,
- CD_PROXY_SERVER)))
- {
- char *line = (char *)XP_ALLOC(strlen(auth) + 30);
- if (line) {
- XP_SPRINTF(line, "Proxy-authorization: %s%c%c", auth, CR, LF);
- StrAllocCat(command, line);
- XP_FREE(line);
- }
- CD_SENT_PROXY_AUTH = TRUE;
- TRACEMSG(("HTTP: Sending proxy-authorization: %s", auth));
- }
- else
- {
- TRACEMSG(("HTTP: Not sending proxy authorization (yet)"));
- }
-
- {
- char line[200];
- XP_SPRINTF(line, "User-Agent: %.100s/%.90s" CRLF CRLF,
- XP_AppCodeName, XP_AppVersion);
- StrAllocCat(command, line);
- }
-
- TRACEMSG(("Tx: %s", command));
-
- SSL_SetSockPeerID(cd->connection->sock, command);
- CE_STATUS = NET_HTTPNetWrite(cd->connection->sock, command, XP_STRLEN(command));
-
- FREE(command);
-
- CD_PAUSE_FOR_READ = TRUE;
-
- CD_NEXT_STATE = HTTP_PARSE_FIRST_LINE;
-
- return(CE_STATUS);
- }
-
- #define POST_DATA_BUFFER_SIZE 2048
-
- PRIVATE int32
- net_get_size_with_crlf( char *filename, XP_FileType file_type, XP_Bool add_crlf )
- {
- XP_File xpfileptr;
- uint32 return_value = 0;
- int line_length;
- char *line;
- char *buffer;
-
- if (!add_crlf)
- {
- /* Don't need to make any cr/lf adjustment, just stat the file and
- return the size. */
-
- XP_StatStruct stat_entry;
- if(-1 == XP_Stat(filename, &stat_entry, file_type))
- return -1;
- else
- return stat_entry.st_size;
- }
-
- xpfileptr = XP_FileOpen( filename, file_type, XP_FILE_READ );
- if (!xpfileptr)
- return -1;
-
- buffer = (char *) XP_ALLOC(POST_DATA_BUFFER_SIZE);
- if (!buffer)
- return -1;
-
- do {
- line = XP_FileReadLine(buffer, POST_DATA_BUFFER_SIZE-5, xpfileptr);
- if (!line)
- break;
-
- line_length = XP_STRLEN(line);
-
- if (line_length > 1 && line[line_length-2] == CR && line[line_length-1] == LF)
- {
- /* already ok */
- }
- else if(line_length > 0 && (line[line_length-1] == LF || line[line_length-1] == CR))
- {
- /* increment to account for missing CR or missing LF */
- line_length++;
- }
-
- return_value += line_length;
- } while (line);
-
- XP_FREE( buffer );
-
- return return_value;
- }
-
- /* begin sending a file
- */
- PRIVATE int
- net_begin_upload_file (ActiveEntry *ce)
- {
- HTTPConData * cd = (HTTPConData *) ce->con_data;
- char * filename;
- char * file_to_post;
- char * header=0;
- char * last_slash;
- char * status_msg;
- int i;
- int32 adjusted_file_size = -1;
-
- if(ce->URL_s->server_status == 401)
- {
- /* retrying with auth, don't change the filename */
- cd->next_state = HTTP_SEND_REQUEST;
- return(0);
- }
-
- XP_ASSERT(ce->URL_s->files_to_post && ce->URL_s->files_to_post[0]);
- if(!ce->URL_s->files_to_post || !ce->URL_s->files_to_post[0])
- return MK_UNABLE_TO_LOCATE_FILE;
-
- /* get a filename from the files_to_post array
- */
- for(i=0; ce->URL_s->files_to_post[i]; i++)
- ; /* find the end */
-
- XP_ASSERT(i>0);
-
- file_to_post = ce->URL_s->files_to_post[i-1];
-
- /* zero the file now so that we don't upload it again. */
- ce->URL_s->files_to_post[i-1] = NULL;
-
- #ifdef XP_MAC
- filename = XP_STRRCHR(file_to_post, '/');
- #elif defined(XP_WIN)
- filename = XP_STRRCHR(file_to_post, '\\');
- #else
- filename = XP_STRRCHR(file_to_post, '/');
- #endif
-
- if(!filename)
- filename = file_to_post;
- else
- filename++; /* go past delimiter */
-
- /* get the size of the file adjusting for crlf conversion */
- adjusted_file_size = net_get_size_with_crlf(file_to_post, xpFileToPost, ce->URL_s->add_crlf ? ce->URL_s->add_crlf[i-1] : FALSE);
- if (-1 == adjusted_file_size)
- {
- ce->URL_s->error_msg = NET_ExplainErrorDetails(MK_UNABLE_TO_LOCATE_FILE, file_to_post);
- FREE(file_to_post);
- return MK_UNABLE_TO_LOCATE_FILE;
- }
-
- status_msg = PR_smprintf("Uploading file %s", filename);
- if(status_msg)
- {
- NET_Progress(ce->window_id, status_msg);
- FREE(status_msg);
- }
-
- /*#ifdef EDITOR
- FE_SaveDialogSetFilename(ce->window_id, filename);
- #endif */ /* EDITOR */
-
- header = PR_smprintf("Content-Length: %ld" CRLF CRLF, adjusted_file_size);
-
-
- FREEIF(ce->URL_s->post_headers);
- /* if header is null this won't crash */
- ce->URL_s->post_headers = header;
-
- /* If the destination URL is explicitly specified in the post_to array, use it, otherwise
- * generate destination from URL_s->address and filename. hardts */
- if (ce->URL_s->post_to && ce->URL_s->post_to[i - 1]) {
- XP_FREE(ce->URL_s->address); /* We don't use it at all. */
- ce->URL_s->address = ce->URL_s->post_to[i - 1];
- ce->URL_s->post_to[i - 1] = NULL; /* zero the element */
- }
- else {
- /* strip the filename from the last slash and append the
- * new filename to the URL
- */
- last_slash = XP_STRRCHR(ce->URL_s->address, '/');
- if(last_slash)
- *last_slash = '\0';
- StrAllocCat(ce->URL_s->address, "/");
- StrAllocCat(ce->URL_s->address, filename);
- }
-
- #ifdef EDITOR
- {
- /* Strip out username and password. from address */
- char *pLocation = NULL;
- if (!NET_ParseUploadURL( ce->URL_s->address, &pLocation, NULL,NULL )) {
- XP_ASSERT(0);
- }
- if (CLEAR_CACHE_BIT(ce->format_out) != FO_LOCATION_INDEPENDENCE)
- FE_SaveDialogSetFilename(ce->window_id, pLocation);
- XP_FREE(pLocation);
- }
- #endif /* EDITOR */
-
- /* make the method PUT */
- ce->URL_s->method = URL_PUT_METHOD;
-
- /* specify the file to be uploaded */
- StrAllocCopy(ce->URL_s->post_data, file_to_post);
-
- /* specify that the post data is a file */
- ce->URL_s->post_data_is_file = TRUE;
-
- /* do the request */
- cd->next_state = HTTP_SEND_REQUEST;
-
- FREE(file_to_post);
-
- return(0);
- }
-
- /* build the HTTP request.
- *
- * mallocs a big string that must be free'd
- * returns the string
- */
- PRIVATE unsigned int
- net_build_http_request (URL_Struct * URL_s,
- FO_Present_Types format_out,
- Bool http1,
- char * proxy_server,
- Bool posting,
- MWContext * window_id,
- char ** command,
- Bool * sent_authorization,
- Bool * sent_proxy_auth)
- {
- char line_buffer[4096]; /* buffer */
- char *auth; /* authorization header string */
- size_t csize; /* size of command */
- const char *tempURL=NULL;
- char *proxyServer=NULL;
-
- /* begin the request
- */
- switch(URL_s->method)
- {
- case URL_MKDIR_METHOD:
- #define MKDIR_WORD "MKDIR "
- BlockAllocCopy(*command, MKDIR_WORD, 5);
- csize = sizeof(MKDIR_WORD)-1;
- break;
-
- case URL_DELETE_METHOD:
- #define DELETE_WORD "DELETE "
- #define RMDIR_WORD "RMDIR "
- if(URL_s->is_directory)
- {
- BlockAllocCopy(*command, RMDIR_WORD, 6);
- csize = sizeof(RMDIR_WORD)-1;
- }
- else
- {
- BlockAllocCopy(*command, DELETE_WORD, 7);
- csize = sizeof(DELETE_WORD)-1;
- }
- break;
-
- case URL_POST_METHOD:
- #define POST_WORD "POST "
- BlockAllocCopy(*command, POST_WORD, 5);
- csize = sizeof(POST_WORD)-1;
- break;
-
- case URL_PUT_METHOD:
- #define PUT_WORD "PUT "
- BlockAllocCopy(*command, PUT_WORD, 4);
- csize = sizeof(PUT_WORD)-1;
- break;
-
- case URL_HEAD_METHOD:
- #define HEAD_WORD "HEAD "
- BlockAllocCopy(*command, HEAD_WORD, 5);
- csize = sizeof(HEAD_WORD)-1;
- break;
-
- case URL_INDEX_METHOD:
- #define INDEX_WORD "INDEX "
- BlockAllocCopy(*command, INDEX_WORD, 6);
- csize = sizeof(INDEX_WORD)-1;
- break;
-
- case URL_MOVE_METHOD:
- #define MOVE_WORD "MOVE "
- BlockAllocCopy(*command, MOVE_WORD, 5);
- csize = sizeof(MOVE_WORD)-1;
- break;
-
- case URL_COPY_METHOD:
- #define COPY_WORD "COPY "
- BlockAllocCopy(*command, COPY_WORD, 5);
- csize = sizeof(COPY_WORD)-1;
- break;
-
- default:
- XP_ASSERT(0);
- /* fall through to GET */
-
- case URL_GET_METHOD:
- #define GET_WORD "GET "
- BlockAllocCopy(*command, GET_WORD, 4);
- csize = sizeof(GET_WORD)-1;
- break;
-
- case URL_GETPROPERTIES_METHOD:
- #define GETPROPERTIES_WORD "GETPROPERTIES "
- BlockAllocCopy(*command, GETPROPERTIES_WORD, 14);
- csize = sizeof(GETPROPERTIES_WORD)-1;
- break;
- }
-
-
- /* if we are using a proxy gateway copy in the entire URL
- * minus the hash mark
- */
- if(proxy_server)
- {
-
- char *url_minus_hash = NET_ParseURL(URL_s->address,
- GET_PROTOCOL_PART
- | GET_USERNAME_PART
- | GET_PASSWORD_PART
- | GET_HOST_PART
- | GET_PATH_PART
- | GET_SEARCH_PART);
- if(url_minus_hash)
- {
- BlockAllocCat(*command, (size_t) csize, url_minus_hash, XP_STRLEN(url_minus_hash));
- csize += XP_STRLEN(url_minus_hash);
- XP_FREE(url_minus_hash);
- }
-
- }
- else
- {
- /* else use just the path and search stuff
- */
- char *path = NET_ParseURL(URL_s->address,
- GET_PATH_PART | GET_SEARCH_PART);
- BlockAllocCat(*command, csize, path, XP_STRLEN(path));
- csize += XP_STRLEN(path);
-
- XP_FREE(path);
- }
-
- if(http1)
- {
- BlockAllocCat(*command, csize, " ", 1);
- csize += 1;
- BlockAllocCat(*command, csize,
- VERSION_STRING,
- XP_STRLEN(VERSION_STRING));
- csize += XP_STRLEN(VERSION_STRING);
- /* finish the line */
- BlockAllocCat(*command, csize, CRLF, 2); /* CR LF, as in rfc 977 */
- csize += 2;
-
- if ((URL_s->etag) && (URL_s->force_reload != NET_SUPER_RELOAD))
- {
- /* add the If-None-Match header */
- XP_STRCPY(line_buffer, "If-None-Match: \"");
- BlockAllocCat(*command, csize,
- line_buffer, XP_STRLEN(line_buffer));
- csize += XP_STRLEN(line_buffer);
- BlockAllocCat(*command, csize,
- URL_s->etag,
- XP_STRLEN(URL_s->etag));
- csize += XP_STRLEN(URL_s->etag);
- /* Closing " */
- BlockAllocCat(*command, csize,
- "\"",
- 1);
- csize += 1;
- BlockAllocCat(*command, csize, CRLF, 2);
- csize += 2;
- }
-
- if(URL_s->last_modified && URL_s->force_reload != NET_SUPER_RELOAD)
- {
- /* add if modified since
- *
- * right now this is being added even if the server sent pragma: no-cache
- * I'm not sure if this is the right thing to do but it seems
- * very efficient since we can still use the cache.
- */
-
- /* add tmp character storage for strings in order for assert
- * to work properly in debug compile.
- * IBM compiler does not put "\" to make " work properly.
- */
- #ifndef AIX
- char *tmp_str = "http";
- #endif
- {
- /* A conversion from time_t to NSPR's int64 is needed in order to
- * use the NSPR time functions. URL_Struct should really be changed
- * to use the NSPR time type instead of time_t.
- */
- #ifndef NSPR20
- uint64 timeInSec;
- uint64 timeInUSec;
- uint64 secToUSec;
- PRTime expandedTime;
- #else
- PRTime timeInSec;
- PRTime timeInUSec;
- PRTime secToUSec;
- PRExplodedTime expandedTime;
- #endif /* NSPR20 */
-
- LL_I2L(timeInSec, URL_s->last_modified);
- LL_I2L(secToUSec, PR_USEC_PER_SEC);
- LL_MUL(timeInUSec, timeInSec, secToUSec);
- #ifndef NSPR20
- #ifndef XP_MAC
- timeInUSec = PR_ToGMT(timeInUSec);
- #endif /* XP_MAC */
- PR_ExplodeTime(&expandedTime, timeInUSec);
- #else
- PR_ExplodeTime(timeInUSec, PR_GMTParameters, &expandedTime);
- #endif /* NSPR20 */
- PR_FormatTimeUSEnglish(line_buffer, 400,
- "If-Modified-Since: %a, %d %b %Y %H:%M:%S GMT",
- &expandedTime);
- }
-
- /* must not be zero for http URL's
- * or else I screwed up the cache logic
- */
- #ifndef AIX
- XP_ASSERT(strncasecomp(URL_s->address, tmp_str, 4)
- || URL_s->real_content_length > 0);
- #endif
-
- if(URL_s->real_content_length)
- XP_SPRINTF(&line_buffer[XP_STRLEN(line_buffer)],
- "; length=%ld" CRLF,
- URL_s->real_content_length);
- BlockAllocCat(*command, csize, line_buffer, XP_STRLEN(line_buffer));
- csize += XP_STRLEN(line_buffer);
-
- /* reset the expires since we will want to
- * either get a new one from the server or
- * set it to zero
- */
- URL_s->expires = 0;
- }
-
- if(URL_s->http_headers) /* use headers that were passed in */
- {
-
- BlockAllocCat(*command, csize, URL_s->http_headers, XP_STRLEN(URL_s->http_headers));
- csize += XP_STRLEN(URL_s->http_headers);
- }
- else
- {
- /* For MOVE method. This contains the destination uri name */
- int meth=URL_s->method;
- if(URL_s->destination
- && (*(URL_s->destination) != '\0')
- && ( (meth == URL_MOVE_METHOD)
- || (meth == URL_COPY_METHOD) )
- ){
- int len=0;
- if(meth == URL_MOVE_METHOD) {
- XP_SPRINTF(line_buffer, "New-uri: %s", URL_s->destination);
- len=XP_STRLEN(line_buffer);
- BlockAllocCat(*command, csize, line_buffer, len);
- csize+=len;
- }
- else if(meth == URL_COPY_METHOD) {
- ;/* some http copy syntax */
- }
-
- BlockAllocCat(*command, csize, CRLF, XP_STRLEN(CRLF));
- csize += XP_STRLEN(CRLF);
- }
- /* sendRefererHeader is set in NET_SetSendRefererHeaderPref in mkhttp.c.
- This condition is set via a javascript pref and was implemented to
- settle some privacy/security issue */
- if(sendRefererHeader)
- {
- int url_type = NET_URL_Type(URL_s->referer);
- if(URL_s->referer
- && url_type != MAILBOX_TYPE_URL
- && url_type != IMAP_TYPE_URL
- && url_type != FILE_TYPE_URL)
- {
- TRACEMSG(("Sending referer field"));
- XP_STRCPY(line_buffer, "Referer: ");
- BlockAllocCat(*command, csize, line_buffer, XP_STRLEN(line_buffer));
- csize += XP_STRLEN(line_buffer);
- BlockAllocCat(*command, csize, URL_s->referer,
- XP_STRLEN(URL_s->referer));
- csize += XP_STRLEN(URL_s->referer);
- BlockAllocCat(*command, csize, CRLF, 2);
- csize += 2;
- }
- }
-
- assert (XP_AppCodeName);
- assert (XP_AppVersion);
-
- if(proxy_server)
- XP_STRCPY(line_buffer, "Proxy-Connection: Keep-Alive" CRLF);
- else
- XP_STRCPY(line_buffer, "Connection: Keep-Alive" CRLF);
-
- XP_SPRINTF (&line_buffer[XP_STRLEN(line_buffer)],
- "User-Agent: %.100s/%.90s" CRLF,
- XP_AppCodeName, XP_AppVersion);
- BlockAllocCat(*command, csize, line_buffer, XP_STRLEN(line_buffer));
- csize += XP_STRLEN(line_buffer);
-
- if(URL_s->force_reload)
- {
- BlockAllocCat(*command, csize, "Pragma: no-cache" CRLF, 18);
- csize += 18;
- }
-
- if(URL_s->range_header)
- {
- #ifndef AIX
- char *tmp_str = CRLF;
- XP_ASSERT(!XP_STRSTR(URL_s->range_header, tmp_str));
- #endif
- #define REQUEST_RANGE_HEADER "Range: "
- BlockAllocCat(*command, csize,
- REQUEST_RANGE_HEADER,
- XP_STRLEN(REQUEST_RANGE_HEADER));
- csize += XP_STRLEN(REQUEST_RANGE_HEADER);
- BlockAllocCat(*command, csize,
- URL_s->range_header,
- XP_STRLEN(URL_s->range_header));
- csize += XP_STRLEN(URL_s->range_header);
- BlockAllocCat(*command, csize,
- CRLF, XP_STRLEN(CRLF));
- csize += XP_STRLEN(CRLF);
- }
-
- #define OLD_RANGE_SUPPORT
- #ifdef OLD_RANGE_SUPPORT
- /* this is here for backwards compatibility with
- * the old range spec
- * It should be removed before final beta 2
- */
- if(URL_s->range_header)
- {
- #ifndef AIX
- char *tmp_str = CRLF;
- XP_ASSERT(!XP_STRSTR(URL_s->range_header, tmp_str));
- #endif
- #undef REQUEST_RANGE_HEADER
- #define REQUEST_RANGE_HEADER "Request-Range: "
- BlockAllocCat(*command, csize,
- REQUEST_RANGE_HEADER,
- XP_STRLEN(REQUEST_RANGE_HEADER));
- csize += XP_STRLEN(REQUEST_RANGE_HEADER);
- BlockAllocCat(*command, csize,
- URL_s->range_header,
- XP_STRLEN(URL_s->range_header));
- csize += XP_STRLEN(URL_s->range_header);
- BlockAllocCat(*command, csize,
- CRLF, XP_STRLEN(CRLF));
- csize += XP_STRLEN(CRLF);
- }
- #endif
-
- if(1)
- {
- char * host = NET_ParseURL(URL_s->address, GET_HOST_PART);
-
- if(host)
- {
- int len;
-
- #define HOST_HEADER "Host: "
- BlockAllocCat(*command,
- csize,
- HOST_HEADER,
- sizeof(HOST_HEADER)-1);
- csize += sizeof(HOST_HEADER)-1;
- len = XP_STRLEN(host);
- BlockAllocCat(*command, csize, host, len);
-
- csize += len;
-
- FREE(host);
-
- BlockAllocCat(*command, csize, CRLF, 2);
- csize += 2;
- }
- }
-
- #ifdef SEND_FROM_FIELD
- XP_SPRINTF(line_buffer, "From: %.256s%c%c",
- FE_UsersMailAddress() ? FE_UsersMailAddress() : "unregistered", CR,LF);
- BlockAllocCat(*command, csize, line_buffer, XP_STRLEN(line_buffer));
- csize += XP_STRLEN(line_buffer);
- #endif /* SEND_FROM_FIELD */
-
-
- if(CLEAR_CACHE_BIT(format_out) != FO_INTERNAL_IMAGE)
- {
- /* send Accept: *(slash)* as well as the others
- */
- XP_SPRINTF(line_buffer, "Accept: %s, %s, %s, %s, %s, */*" CRLF,
- IMAGE_GIF, IMAGE_XBM, IMAGE_JPG, IMAGE_PJPG, IMAGE_PNG);
- }
- else
- {
- XP_SPRINTF(line_buffer, "Accept: %s, %s, %s, %s, %s" CRLF,
- IMAGE_GIF, IMAGE_XBM, IMAGE_JPG, IMAGE_PJPG, IMAGE_PNG);
- }
-
- BlockAllocCat(*command, csize, line_buffer, XP_STRLEN(line_buffer));
- csize += XP_STRLEN(line_buffer);
-
- /* add Accept-Encoding Header */
- XP_SPRINTF(line_buffer, "Accept-Encoding: %s" CRLF, ENCODING_GZIP2);
- BlockAllocCat(*command, csize, line_buffer, XP_STRLEN(line_buffer));
- csize += XP_STRLEN(line_buffer);
-
- #ifdef MOZILLA_CLIENT
- #define SEND_ACCEPT_LANGUAGE 1
- #ifdef SEND_ACCEPT_LANGUAGE /* Added by ftang */
- {
- char *acceptlang = INTL_GetAcceptLanguage();
- if((acceptlang != NULL) && ( *acceptlang != '\0') )
- {
- XP_SPRINTF(line_buffer, "Accept-Language: %s" CRLF,
- acceptlang );
- BlockAllocCat(*command, csize, line_buffer, XP_STRLEN(line_buffer));
- csize += XP_STRLEN(line_buffer);
- }
- }
- #endif /* SEND_ACCEPT_LANGUAGE */
-
- #define SEND_ACCEPT_CHARSET 1
- #ifdef SEND_ACCEPT_CHARSET /* Added by bstell */
- {
- char *acceptCharset = INTL_GetAcceptCharset();
- if((acceptCharset != NULL) && ( *acceptCharset != '\0') )
- {
- XP_SPRINTF(line_buffer, "Accept-Charset: %s" CRLF,
- acceptCharset );
- BlockAllocCat(*command, csize, line_buffer, XP_STRLEN(line_buffer));
- csize += XP_STRLEN(line_buffer);
- }
- }
- #endif /* SEND_ACCEPT_CHARSET */
- #endif /* MOZILLA_CLIENT */
-
- /*
- * Check if proxy is requiring authorization.
- * If NULL, not necessary, or the proxy will return 407 to
- * require authorization.
- *
- */
- /* This was hacked in because proxy auth can be required when the Auto-config url
- * itself requires authorization. We used to ask for proxy auth only when the proxy was
- * input directly into the prefs. Now we check to see if there's a pacurl (if there
- * is, there can't be a proxy url simultaneously) use it, otherwise we're using a
- * proxy from the prefs.
- */
-
- /* Figure out which kind of proxy we're using: PAC or straight proxy.
- * DON'T FREE tempURL!!!
- */
- if ( (tempURL = net_GetPACUrl()) && (*tempURL) )
- proxyServer = NET_ParseURL(tempURL, GET_HOST_PART | GET_PATH_PART | GET_USERNAME_PART | GET_PASSWORD_PART);
- else
- proxyServer = proxy_server;
-
- if (proxyServer &&
- NULL != (auth=NET_BuildProxyAuthString(window_id,
- URL_s,
- proxyServer)))
- {
- if (tempURL)
- XP_FREE(proxyServer);
- *sent_proxy_auth = TRUE;
- XP_SPRINTF(line_buffer, "Proxy-authorization: %.3840s%c%c", auth, CR, LF);
- BlockAllocCat(*command, csize, line_buffer, XP_STRLEN(line_buffer));
- csize += XP_STRLEN(line_buffer);
- TRACEMSG(("HTTP: Sending proxy-authorization: %s", auth));
- }
- else
- {
- TRACEMSG(("HTTP: Not sending proxy authorization (yet)"));
- }
-
- /* NET_BuildAuthString will return non-NULL if authorization is
- * known to be required for this document.
- *
- * If NULL is returned authorization is not required or is
- * not known to be required yet so we will look for a 401
- * return code later on to see if authorization will be
- * neccessary
- */
- if (NULL!=(auth=NET_BuildAuthString(window_id, URL_s)))
- {
- *sent_authorization = TRUE;
- BlockAllocCat(*command, csize, auth, XP_STRLEN(auth));
- csize += XP_STRLEN(auth);
- TRACEMSG(("HTTP: Sending authorization: %s", auth));
- }
- else
- {
- TRACEMSG(("HTTP: Not sending authorization (yet)"));
- }
-
- if (NULL!=(auth=NET_GetCookie(window_id, URL_s->address)))
- {
- int len;
- XP_STRCPY(line_buffer, "Cookie: ");
- BlockAllocCat(*command, csize,
- line_buffer, XP_STRLEN(line_buffer));
-
- csize += XP_STRLEN(line_buffer);
- len = XP_STRLEN(auth);
- BlockAllocCat(*command, csize, auth, len);
- csize += len;
- BlockAllocCat(*command, csize, CRLF, XP_STRLEN(CRLF));
- csize += XP_STRLEN(CRLF);
- TRACEMSG(("HTTP: Sending Cookie: %s", auth));
- XP_FREE(auth);
- }
- else
- {
- TRACEMSG(("HTTP: Not sending cookie"));
- }
-
- } /* end of if passed in headers */
- } /* end of if(http1) */
-
- /* end of Get/Post request */
-
- /* Blank line means "end" of headers
- * If we are posting WritePostData will
- * add the extra line feed for us
- */
- if(!posting)
- {
- BlockAllocCat(*command, csize, CRLF, 2);
- csize += 2;
- }
-
- return((unsigned int) csize);
- }
-
- HG12515
-
- /* send_http_request makes a connection to the http server
- * and sends a request (ethier http1 or http/.9) to the server
- *
- * returns the TCP status code
- */
- #define SOCK_CHUNK_SIZE 1024
- PRIVATE int
- net_send_http_request (ActiveEntry *ce)
- {
- /* assign it so that we have a typed structure pointer */
- HTTPConData * cd = (HTTPConData *)ce->con_data;
- char * command=0;
- unsigned int command_size;
-
- /* we make the assumption that we are always acting as a proxy
- * server if we get http_headers passed in the URL structure.
- *
- * when acting as a proxy_server the clients headers are sent
- * to the server instead of being generated here and the headers
- * from the server are unparsed and sent on the the client.
- */
- if(ce->format_out == FO_OUT_TO_PROXY_CLIENT ||
- ce->format_out == FO_CACHE_AND_OUT_TO_PROXY_CLIENT)
- CD_ACTING_AS_PROXY=YES;
-
- TRACEMSG(("Entered \"send_http_request\""));
-
- /* we make the assumption that we will always use the POST
- * method if there is post data in the URL structure
- * Is that a bad assumption?
- */
- if(CE_URL_S->method == URL_POST_METHOD
- || CE_URL_S->method == URL_PUT_METHOD) {
- CD_POSTING = YES;
- #ifdef MOZILLA_CLIENT
- SECNAV_Posting(cd->connection->sock);
- #endif /* MOZILLA_CLIENT */
- } else if (CE_URL_S->method == URL_HEAD_METHOD) {
- #ifdef MOZILLA_CLIENT
- SECNAV_HTTPHead(cd->connection->sock);
- #endif /* MOZILLA_CLIENT */
- }
-
- /* zero out associated mime fields in URL structure
- *
- * all except content_length since that may be passed in
- */
- CE_URL_S->protection_template = 0;
- FREE_AND_CLEAR(CE_URL_S->redirecting_url);
- FREE_AND_CLEAR(CE_URL_S->authenticate);
- FREE_AND_CLEAR(CE_URL_S->proxy_authenticate);
-
- /* Build the request command. (It must be free'd!!!)
- *
- * build_http_request will assemble a string containing
- * the main request line, HTTP/1.0 MIME headers and
- * the post data (if it exits)
- */
- command_size = net_build_http_request(CE_URL_S,
- CE_FORMAT_OUT,
- CD_SEND_HTTP1,
- (CD_USE_SSL_PROXY ? NULL : CD_PROXY_SERVER),
- CD_POSTING,
- CE_WINDOW_ID,
- &command,
- &CD_SENT_AUTHORIZATION,
- &CD_SENT_PROXY_AUTH);
-
- TRACEMSG(("Sending HTTP Request:\n---------------------------------"));
-
- CE_STATUS = (int) NET_BlockingWrite(cd->connection->sock, command, command_size);
-
- #if defined(JAVA)
- #if defined(DEBUG)
- if(MKLib_trace_flag)
- {
- NET_NTrace("Tx: ", 4);
- NET_NTrace(command, command_size);
- }
- #endif /* DEBUG */
- #endif /* JAVA */
- XP_FREE (command); /* freeing the request */
-
- if (CE_STATUS < 0)
- {
- int err = PR_GetError();
-
- if(err == PR_WOULD_BLOCK_ERROR)
- return(1); /* continue */
-
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_TCP_WRITE_ERROR, err);
-
- CD_NEXT_STATE= HTTP_ERROR_DONE;
-
- return(MK_TCP_WRITE_ERROR);
- }
-
-
- /* make sure these are empty
- */
- FREE_AND_CLEAR(CD_LINE_BUFFER); /* reset */
- CD_LINE_BUFFER_SIZE=0; /* reset */
-
- if(CD_POSTING
- && CE_URL_S->post_data)
- {
- NET_ClearReadSelect(CE_WINDOW_ID, cd->connection->sock);
- NET_SetConnectSelect(CE_WINDOW_ID, cd->connection->sock);
- #ifdef XP_WIN
- cd->calling_netlib_all_the_time = TRUE;
- NET_SetCallNetlibAllTheTime(CE_WINDOW_ID, "mkhttp");
- #endif /* XP_WIN */
- CE_CON_SOCK = cd->connection->sock;
- CD_NEXT_STATE = HTTP_SEND_POST_DATA;
- return(0);
- }
-
- CD_NEXT_STATE = HTTP_PARSE_FIRST_LINE;
-
- /* Don't pause for read any more because we need to do
- * at least a single read right away to detect if the
- * connection is bad. Apparently windows will queue a
- * write and not return a failure, but in fact the
- * connection has already been closed by the server.
- * Windows select will not even detect the exception
- * so we end up deadlocked. By doing one read we
- * can detect errors immediately
- *
- * CD_PAUSE_FOR_READ = TRUE;
- */
-
- {
- char * nonProxyHost = NET_ParseURL(CE_URL_S->address, GET_HOST_PART);
- if (nonProxyHost) {
- char* msg = PR_smprintf(XP_GetString(XP_PROGRESS_WAIT_REPLY),
- nonProxyHost);
- if (msg) {
- NET_Progress(CE_WINDOW_ID, msg);
- XP_FREE(msg);
- }
- XP_FREE(nonProxyHost);
- }
- }
-
- return STATUS(CE_STATUS);
-
- } /* end of net_send_http_request */
-
- PRIVATE int
- net_http_send_post_data (ActiveEntry *ce)
- {
- HTTPConData * cd = (HTTPConData *)ce->con_data;
- /* Default to not add_crlf_to_line_endings for HTTP. */
- XP_Bool add_crlf = FALSE;
-
-
- /* make sure the line buffer is large enough
- * for us to use as a buffer
- */
- if(cd->line_buffer_size < 200)
- {
- FREEIF(cd->line_buffer);
- cd->line_buffer = (char*)XP_ALLOC(256);
- cd->line_buffer_size = 256;
- }
-
- /* If the add_crlf field is set in the URL struct, find the
- entry corresponding to the current file being posted. */
- if (CE_URL_S->files_to_post && CE_URL_S->add_crlf) {
- int n = 0;
- while (CE_URL_S->files_to_post[n]) {
- n++;
- }
- /* n should now point after the last entry in files_to_post,
- which is the current file being uploaded. */
- add_crlf = CE_URL_S->add_crlf[n];
- }
-
- /* returns 0 on done and negative on error
- * positive if it needs to continue.
- */
- CE_STATUS = NET_WritePostData(CE_WINDOW_ID, CE_URL_S,
- cd->connection->sock,
- &cd->write_post_data_data,
- add_crlf);
-
- cd->pause_for_read = TRUE;
-
- if(CE_STATUS == 0)
- {
- /* normal done
- */
- TRACEMSG(("End of post data data"));
-
- /* make sure these are empty
- */
- FREE_AND_CLEAR(cd->line_buffer); /* reset */
- cd->line_buffer_size=0; /* reset */
-
- NET_ClearConnectSelect(CE_WINDOW_ID, cd->connection->sock);
- NET_SetReadSelect(CE_WINDOW_ID, cd->connection->sock);
- CE_CON_SOCK = NULL;
-
- {
- char * nonProxyHost = NET_ParseURL(CE_URL_S->address, GET_HOST_PART);
- if (nonProxyHost) {
- char* msg = PR_smprintf(XP_GetString(XP_PROGRESS_WAIT_REPLY),
- nonProxyHost);
- if (msg) {
- NET_Progress(CE_WINDOW_ID, msg);
- XP_FREE(msg);
- }
- XP_FREE(nonProxyHost);
- }
- }
-
- cd->next_state = HTTP_PARSE_FIRST_LINE;
- return(0);
- }
- else if(cd->total_size_of_files_to_post && ce->status > 0)
- {
- cd->total_amt_written += ce->status;
-
- FE_GraphProgress(ce->window_id,
- ce->URL_s,
- cd->total_amt_written,
- ce->status,
- cd->total_size_of_files_to_post);
- FE_SetProgressBarPercent(ce->window_id,
- cd->total_amt_written*100/cd->total_size_of_files_to_post);
- }
-
-
-
- return(CE_STATUS);
- }
-
- /* parse_http_mime_headers
- *
- * parses the mime headers as they are received from the
- * HTTP server.
- *
- * Returns the TCP status code
- *
- */
-
- PRIVATE int
- net_parse_http_mime_headers (ActiveEntry *ce)
- {
- HTTPConData * cd = (HTTPConData *)ce->con_data;
- char *line;
- char *value;
-
- CE_STATUS = NET_BufferedReadLine(cd->connection->sock, &line, &CD_LINE_BUFFER,
- &CD_LINE_BUFFER_SIZE, &CD_PAUSE_FOR_READ);
-
- if(CE_STATUS < 0)
- {
- NET_ExplainErrorDetails(MK_TCP_READ_ERROR, SOCKET_ERRNO);
-
- /* return TCP error
- */
- return MK_TCP_READ_ERROR;
- }
-
- if(CE_STATUS == 0)
- {
- /* if this is set just return so we can use
- * the cached copythat
- */
- if(CD_USE_COPY_FROM_CACHE)
- {
- /* clear the URL content fields so that
- * the 304 object doesn't effect the actual
- * cache file
- */
- if(!CE_URL_S->preset_content_type)
- FREE_AND_CLEAR(CE_URL_S->content_type);
- CE_URL_S->content_length = 0;
- CE_URL_S->real_content_length = 0;
- CE_URL_S->last_modified = 0;
- FREE_AND_CLEAR(CE_URL_S->content_encoding);
- FREE_AND_CLEAR(CE_URL_S->content_name);
- CD_NEXT_STATE = HTTP_DONE;
- CD_PAUSE_FOR_READ = FALSE;
- return(MK_USE_COPY_FROM_CACHE);
- }
-
- /* no mo data */
- if(CD_USE_SSL_PROXY && !CD_SSL_PROXY_SETUP_DONE)
- {
- /* we have now successfully initiated a ssl proxy
- * connection to a remote ssl host
- *
- * now we need to give the file descriptor
- * to the ssl library and let it initiate
- * a secure connection
- * after that we need to send a normal
- * http request
- *
- * ADD STUFF HERE KIPP!!!!
- *
- * fd is cd->connection->sock
- */
- if(ce->URL_s->files_to_post)
- CD_NEXT_STATE = HTTP_BEGIN_UPLOAD_FILE;
- else
- CD_NEXT_STATE = HTTP_SEND_REQUEST;
- CD_SSL_PROXY_SETUP_DONE = TRUE;
- }
- else if(ce->URL_s->files_to_post)
- {
- if(ce->URL_s->files_to_post[0]
- && ce->URL_s->server_status/100 == 2)
- {
- if(ce->URL_s->can_reuse_connection)
- {
- CD_NEXT_STATE = HTTP_BEGIN_UPLOAD_FILE;
- }
- else
- {
- NET_ClearReadSelect(CE_WINDOW_ID, cd->connection->sock);
- NET_TotalNumberOfOpenConnections--;
-
- /* close the old connection
- */
- PR_Close(cd->connection->sock);
- cd->connection->sock = NULL;
-
- CD_NEXT_STATE = HTTP_START_CONNECT;
- }
- }
- else
- {
- CD_NEXT_STATE = HTTP_DONE;
- }
- }
- else
- {
- CD_NEXT_STATE = HTTP_SETUP_STREAM;
- }
- CD_PAUSE_FOR_READ = FALSE;
- return(0);
- }
-
- if(!line)
- return(0); /* wait for next line */
-
- TRACEMSG(("parse_http_mime_headers: Parsing headers, got line: %s",line));
-
- if(CD_ACTING_AS_PROXY)
- {
- /* save all the headers so we can pass them to the client
- * when neccessary
- */
- StrAllocCat(CD_SERVER_HEADERS, line);
- StrAllocCat(CD_SERVER_HEADERS, "\r\n"); /* add the \n back on */
- }
-
- /* check for end of MIME headers */
- if(*line == '\0' || *line == '\r')
- {
- TRACEMSG(("Finished parsing MIME headers"));
-
- CD_PAUSE_FOR_READ = FALSE;
-
- HG07606
- if(ce->URL_s->files_to_post
- && ce->URL_s->server_status/100 == 2)
- {
- if(ce->URL_s->files_to_post[0])
- {
- if(ce->URL_s->can_reuse_connection)
- {
- CD_NEXT_STATE = HTTP_BEGIN_UPLOAD_FILE;
- }
- else
- {
- NET_ClearReadSelect(CE_WINDOW_ID, cd->connection->sock);
- NET_TotalNumberOfOpenConnections--;
-
- /* close the old connection
- */
- PR_Close(cd->connection->sock);
- cd->connection->sock = NULL;
-
- CD_NEXT_STATE = HTTP_START_CONNECT;
- }
- }
- else
- {
- CD_NEXT_STATE = HTTP_DONE;
- }
- }
- else
- {
- CD_NEXT_STATE = HTTP_SETUP_STREAM;
- }
-
- return(0);
- }
-
- value = XP_STRCHR(line, ':');
- if(value)
- value++;
- NET_ParseMimeHeader(CE_FORMAT_OUT, CE_WINDOW_ID, CE_URL_S, line, value, TRUE);
-
- return(1);
- }
-
- /* setup HTTP/1.1 specific protocol defaults */
- PRIVATE void
- net_setup_http11_defaults(ActiveEntry *ce)
- {
- HTTPConData * cd = (HTTPConData *)ce->con_data;
-
- ce->URL_s->can_reuse_connection = TRUE;
-
- return;
- }
-
- /* parses the first line of the http server's response
- * and determines if it is an http1 or http/.9 server
- *
- * returns the tcp status code
- */
- PRIVATE int
- net_parse_first_http_line (ActiveEntry *ce)
- {
- char *line_feed=0;
- char *ptr;
- int line_size;
- int num_fields;
- char server_version[36];
- HTTPConData * cd = (HTTPConData *)ce->con_data;
- char small_buf[MAX_FIRST_LINE_SIZE+16];
- Bool do_redirect = TRUE;
-
- TRACEMSG(("Entered: net_parse_first_http_line"));
-
- CE_STATUS = PR_Read(cd->connection->sock, small_buf, MAX_FIRST_LINE_SIZE+10);
-
- if(CE_STATUS == 0)
- {
- /* the server dropped the connection? */
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_ZERO_LENGTH_FILE);
- CD_NEXT_STATE = HTTP_ERROR_DONE;
- CD_PAUSE_FOR_READ = FALSE;
- return(MK_ZERO_LENGTH_FILE);
- }
- else if(CE_STATUS < 0)
- {
- int s_error = PR_GetError();
- if (s_error == PR_WOULD_BLOCK_ERROR)
- {
- CD_PAUSE_FOR_READ = TRUE;
- return(0);
- }
- else
- {
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_TCP_READ_ERROR, s_error);
-
- /* return TCP error
- */
- return MK_TCP_READ_ERROR;
- }
- }
-
- /* this is where kipp says that I can finally query
- * for the security data. We can't do it after the
- * connect since the handshake isn't done yet...
- */
- /* clear existing data
- */
- FREEIF(CE_URL_S->key_cipher);
- FREEIF(CE_URL_S->key_issuer);
- FREEIF(CE_URL_S->key_subject);
- if ( CE_URL_S->certificate ) {
- CERT_DestroyCertificate(CE_URL_S->certificate);
- }
-
- SSL_SecurityStatus(cd->connection->sock,
- &CE_URL_S->security_on,
- &CE_URL_S->key_cipher,
- &CE_URL_S->key_size,
- &CE_URL_S->key_secret_size,
- &CE_URL_S->key_issuer,
- &CE_URL_S->key_subject);
- CE_URL_S->certificate = SSL_PeerCertificate(cd->connection->sock);
-
- #ifdef MOZILLA_CLIENT
- if ( ce->URL_s->redirecting_cert &&
- ( ! (CD_USE_SSL_PROXY && !CD_SSL_PROXY_SETUP_DONE) ) ) {
- /* don't do the redirect check when talking to the proxy,
- * wait for it to come through here a second time, when
- * we are really using SSL to talk to the real server.
- */
-
- PRBool compare;
-
- compare = CERT_CompareCertsForRedirection(ce->URL_s->certificate,
- ce->URL_s->redirecting_cert);
-
- /* now that we are done with the redirecting cert destroy it */
- CERT_DestroyCertificate(ce->URL_s->redirecting_cert);
- ce->URL_s->redirecting_cert = NULL;
-
- if ( compare != PR_TRUE ) {
- /* certs are different */
-
- do_redirect = (Bool)SECNAV_SecurityDialog(CE_WINDOW_ID,
- SD_REDIRECTION_TO_SECURE_SITE);
- if ( !do_redirect ) {
- /* stop connection here!! */
- CE_URL_S->error_msg = 0; /* XXX - is this right? */
-
- /* return TCP error
- */
- return MK_TCP_READ_ERROR;
- }
- }
- }
- #endif /* MOZILLA_CLIENT */
-
- /* CE_STATUS greater than 0
- */
- BlockAllocCat(CD_LINE_BUFFER, CD_LINE_BUFFER_SIZE, small_buf, CE_STATUS);
- CD_LINE_BUFFER_SIZE += CE_STATUS;
-
- for(ptr = CD_LINE_BUFFER, line_size=0; line_size < CD_LINE_BUFFER_SIZE; ptr++, line_size++)
- if(*ptr == LF)
- {
- line_feed = ptr;
- break;
- }
-
- /* assume HTTP/.9 until we know better
- */
- cd->protocol_version = POINT_NINE;
-
- if(line_feed)
- {
- *server_version = 0;
-
- *line_feed = '\0';
-
- num_fields = sscanf(CD_LINE_BUFFER, "%20s %d", server_version, &CE_URL_S->server_status);
-
- TRACEMSG(("HTTP: Scanned %d fields from first_line: %s", num_fields, CD_LINE_BUFFER));
-
- /* Try and make sure this is an HTTP/1.0 reply
- */
- if (num_fields == 2 || !XP_STRNCMP("HTTP/", server_version, 5))
- {
- double ver = atof(server_version+5);
-
- if(ver > 1.0)
- {
- /* HTTP1.1 */
- cd->protocol_version = ONE_POINT_ONE;
-
- net_setup_http11_defaults(ce);
-
- XP_ASSERT(ver == 1.1);
- }
- else
- {
- /* HTTP1 */
- cd->protocol_version = ONE_POINT_O;
-
- XP_ASSERT(ver == 1.0 || ver == 0.0); /* allow 0 bug */
- }
- }
-
- /* put the line back the way it should be
- */
- *line_feed = LF;
- }
- else if(CD_LINE_BUFFER_SIZE < MAX_FIRST_LINE_SIZE)
- {
- return(0); /* not ready to process */
- }
-
- if(cd->connection->prev_cache && cd->protocol_version == POINT_NINE)
- {
- /* got a non HTTP/1.0 or above response from
- * server that must support HTTP/1.0 since it
- * supports keep-alive. The connection
- * must be in a bad state now so
- * restart the whole thang by going to the ERROR state
- */
- CD_NEXT_STATE = HTTP_ERROR_DONE;
- }
-
- /* if we are getting a successful read here
- * then the connection is valid
- */
- cd->connection_is_valid = TRUE;
-
- if(cd->protocol_version == POINT_NINE)
- { /* HTTP/0.9 */
- NET_cinfo * ctype;
-
- TRACEMSG(("Receiving HTTP/0.9"));
-
- CE_URL_S->content_length = 0;
- CE_URL_S->real_content_length = 0;
- FREE_AND_CLEAR(CE_URL_S->content_encoding);
- FREE_AND_CLEAR(CE_URL_S->content_name);
-
- if(!CE_URL_S->preset_content_type)
- {
- FREE_AND_CLEAR(CE_URL_S->content_type);
-
- /* fake the content_type since we can't get it */
- ctype = NET_cinfo_find_type(CE_URL_S->address);
-
- /* treat unknown types as HTML
- */
- if(ctype->is_default)
- StrAllocCopy(CE_URL_S->content_type, TEXT_HTML);
- else
- StrAllocCopy(CE_URL_S->content_type, ctype->type);
-
- /* fake the content_encoding since we can't get it */
- StrAllocCopy(CE_URL_S->content_encoding,
- (NET_cinfo_find_enc(CE_URL_S->address))->encoding);
- }
-
- CD_NEXT_STATE = HTTP_SETUP_STREAM;
-
- }
- else
- {
- /* Decode full HTTP/1.0 or 1.1 response */
-
- TRACEMSG(("Receiving HTTP1 reply, status: %d", CE_URL_S->server_status));
-
- if(CE_URL_S->server_status != 304
- && (!CD_USE_SSL_PROXY || CD_SSL_PROXY_SETUP_DONE))
- {
- /* if we don't have a 304, zero all
- * the content headers so that they
- * don't interfere with the
- * incoming object
- *
- * don't zero these in the case of a SSL proxy
- * since this isn't the real request this
- * is just the connection open request response
- */
- if(!CE_URL_S->preset_content_type)
- FREE_AND_CLEAR(CE_URL_S->content_type);
- CE_URL_S->content_length = 0;
- CE_URL_S->real_content_length = 0;
- FREE_AND_CLEAR(CE_URL_S->content_encoding);
- FREE_AND_CLEAR(CE_URL_S->content_name);
- }
-
- switch (CE_URL_S->server_status / 100)
- {
- case 1:
- if(CE_URL_S->server_status == 100)
- {
- char * end_of_line;
- int cur_line_size;
-
- /* 100 continue. Ignore line and continue looking
- * for first line
- */
-
- /* strip the "HTTP/1.1 100 Continue" from the line buffer */
- end_of_line = line_feed;
- cur_line_size = (end_of_line - cd->line_buffer)+1;
-
- /* absorb any blank lines after the 100 continue */
- while(cd->line_buffer_size > cur_line_size)
- {
- if(line_feed[1] == CR || line_feed[1] == LF)
- {
- cur_line_size++;
- end_of_line++;
- }
- else
- {
- /* anything else stop */
- break;
- }
- }
-
- cd->line_buffer_size -= cur_line_size;
- if(cd->line_buffer_size)
- XP_MEMMOVE(cd->line_buffer, end_of_line+1, cd->line_buffer_size);
-
- /* by not setting CD_NEXT_STATE to something different
- * we will come back to this function and look for another
- * first line.
- */
- return(0);
-
- }
- break;
-
- case 2: /* Succesful reply */
-
- /* Since we
- * are getting a new copy, delete the old one
- * from the cache
- */
- #ifdef MOZILLA_CLIENT
- NET_RemoveURLFromCache(CE_URL_S);
- #endif
-
- if((CE_URL_S->server_status == 204
- || CE_URL_S->server_status == 201)
- && !CD_ACTING_AS_PROXY)
- {
- if(ce->URL_s->files_to_post && ce->URL_s->files_to_post[0])
- {
- /* fall through since we need to get
- * the headers to complete the
- * file transfer
- */
- }
- else
- {
- CE_STATUS = MK_NO_ACTION;
- CD_NEXT_STATE = HTTP_ERROR_DONE;
- return STATUS(CE_STATUS);
- }
- }
- else if(cd->partial_cache_file
- && ce->URL_s->range_header
- && CE_URL_S->server_status != 206)
- {
- /* we asked for a range and got back
- * the whole document. Something
- * went wrong, error out.
- */
- CE_STATUS = MK_TCP_READ_ERROR;
- ce->URL_s->error_msg = NET_ExplainErrorDetails(
- MK_TCP_READ_ERROR,
- XP_ERRNO_EIO);
- CD_NEXT_STATE = HTTP_ERROR_DONE;
- return(CE_STATUS);
- }
-
- break;
-
- case 3: /* redirection and other such stuff */
-
- if(!CD_ACTING_AS_PROXY
- && (CE_URL_S->server_status == 301 || CE_URL_S->server_status == 302))
- {
- /* Redirect with GET only (change POST to get)
- *
- * Supported within the HTTP module.
- * Will retry after mime parsing
- */
- TRACEMSG(("Got Redirect code"));
- CD_DOING_REDIRECT = TRUE;
- }
- if(!CD_ACTING_AS_PROXY && CE_URL_S->server_status == 307)
- {
- /* Redirect without changing METHOD
- *
- * Supported within the HTTP module.
- * Will retry after mime parsing
- */
- TRACEMSG(("Got Redirect code"));
- CD_DOING_REDIRECT = TRUE;
- cd->save_redirect_method = TRUE;
- }
- else if(CE_URL_S->server_status == 304)
- {
- /* use the copy from the cache since it wasn't modified
- *
- * note: this will work with proxy clients too
- */
- if(CE_URL_S->last_modified)
- {
- #ifdef MOZILLA_CLIENT
- /* check to see if we just now entered a secure space
- *
- * don't do if this is coming from history
- * don't do this if about to redirect
- */
- if(CE_URL_S->security_on
- && (CE_FORMAT_OUT == FO_CACHE_AND_PRESENT
- || CE_FORMAT_OUT == FO_PRESENT)
- && !CE_URL_S->history_num)
- {
- History_entry * h = SHIST_GetCurrent(&CE_WINDOW_ID->hist);
-
- if(!h || !h->security_on)
- SECNAV_SecurityDialog(CE_WINDOW_ID,
- SD_ENTERING_SECURE_SPACE);
- }
- #endif /* MOZILLA_CLIENT */
-
- CD_USE_COPY_FROM_CACHE = TRUE;
- /* no longer return since we need to parse
- * headers from the server
- *
- * return(MK_USE_COPY_FROM_CACHE);
- */
- }
-
- /* else continue since the server messed up
- * and sent us a 304 even without us having sent
- * it an if-modified-since header
- */
- }
- break;
-
- case 4: /* client error */
-
- CE_URL_S->preset_content_type = FALSE;
-
- if(CE_URL_S->server_status == 401 && !CD_ACTING_AS_PROXY)
- {
- /* never do this if acting as a proxy
- * If we are a proxy then just pass on
- * the headers and the document.
- *
- * if authorization_required is set we will check
- * below after parsing the MIME headers to see
- * if we should redo the request with an authorization
- * string
- */
- CD_AUTH_REQUIRED = TRUE;
-
- /* Since we
- * are getting a new copy, delete the old one
- * from the cache
- */
- #ifdef MOZILLA_CLIENT
- NET_RemoveURLFromCache(CE_URL_S);
- #endif
-
- /* we probably want to cache this unless
- * the user chooses not to authorize himself
- */
- }
- else if (CE_URL_S->server_status == 407 && !CD_ACTING_AS_PROXY)
- {
- /* This happens only if acting as a client */
- CD_PROXY_AUTH_REQUIRED = TRUE;
-
- /* we probably want to cache this unless
- * the user chooses not to authorize himself
- */
- }
- else
- {
- /* don't cache unless we have a succesful reply
- */
- TRACEMSG(("Server did not return success: NOT CACHEING!!"));
- CE_URL_S->dont_cache = TRUE;
-
- /* all other codes should be displayed */
- }
- break;
-
- case 5: /* server error code */
- TRACEMSG(("Server did not return success: NOT CACHEING!!!"));
- CE_URL_S->dont_cache = TRUE;
- CE_URL_S->preset_content_type = FALSE;
- #ifdef DO_503
- if(CE_URL_S->server_status == 503 && !CD_ACTING_AS_PROXY)
- {
- CD_SERVER_BUSY_RETRY = TRUE;
- }
- #endif /* DO_503 */
-
- /* display the error results */
- break;
-
- default: /* unexpected reply code */
- {
- char message_buffer[256];
- XP_SPRINTF(message_buffer,
- XP_GetString(XP_ALERT_UNKNOWN_STATUS),
- CE_URL_S->server_status);
- FE_Alert(CE_WINDOW_ID, message_buffer);
-
- /* don't cache unless we have a succesful reply
- */
- TRACEMSG(("Server did not return 200: NOT CACHEING!!!"));
- CE_URL_S->dont_cache = TRUE;
- }
- break;
- } /* Switch on server_status/100 */
-
- CD_NEXT_STATE = HTTP_PARSE_MIME_HEADERS;
-
- } /* Full HTTP reply */
-
- return(0); /* good */
-
- }
-
- /* if we were posting a file and received an error put the
- * current file we were posting back on the end of the list
- * so that our state is correctly reset
- */
- PRIVATE void
- net_revert_post_data(ActiveEntry * ce)
- {
- if(ce->URL_s->files_to_post && ce->URL_s->post_data)
- {
- /* find the end of the files to post array */
- int index=0;
-
- for(; ce->URL_s->files_to_post[index]; index++)
- ; /* null body */
-
- /* this will not explode even if the malloc fails */
- ce->URL_s->files_to_post[index] = XP_STRDUP(ce->URL_s->post_data);
-
- ce->URL_s->files_to_post[index+1] = NULL;
-
- if(ce->URL_s->post_to)
- {
- ce->URL_s->post_to[index] = XP_STRDUP(ce->URL_s->address);
-
- ce->URL_s->post_to[index+1] = NULL;
- }
- }
- }
-
- /* sets up the stream and performs special actions like redirect and
- * retry on authorization
- *
- * returns the tcp status code
- */
- PRIVATE int
- net_setup_http_stream(ActiveEntry * ce)
- {
- HTTPConData * cd = (HTTPConData *)ce->con_data;
- XP_Bool need_to_do_again = FALSE;
- MWContext * stream_context;
-
- TRACEMSG(("NET_ProcessHTTP: setting up stream"));
-
- /* save this since it can be changed in lots
- * of places. This will be used for graph progress
- * and to terminate the tranfer
- */
- if(!ce->URL_s->high_range)
- cd->original_content_length = CE_URL_S->content_length;
- else
- cd->original_content_length = ce->URL_s->high_range
- - ce->URL_s->low_range
- + 1;
-
- if ((ce->URL_s->method == URL_HEAD_METHOD) &&
- ( CD_AUTH_REQUIRED == FALSE))
- {
- /* We only wanted the head, so we should stop doing anything else. */
- CD_NEXT_STATE = HTTP_DONE;
- return 0;
- }
-
- /* if this is set just return so that we can use
- * the cached copy
- */
- if(CD_USE_COPY_FROM_CACHE)
- {
- /* if this is a partial cache file situation
- * then we will keep going and switch later
- * on in this file.
- *
- * If it's not a partial cache file then
- * leave the HTTP module and go to the
- * file module to display the file
- */
- if(!cd->partial_cache_file)
- {
- /* clear the URL content fields so that
- * the 304 object doesn't effect the actual
- * cache file
- */
- if(!CE_URL_S->preset_content_type)
- FREE_AND_CLEAR(CE_URL_S->content_type);
- CE_URL_S->content_length = 0;
- CE_URL_S->real_content_length = 0;
- FREE_AND_CLEAR(CE_URL_S->content_encoding);
- FREE_AND_CLEAR(CE_URL_S->content_name);
- CD_NEXT_STATE = HTTP_DONE;
- CD_PAUSE_FOR_READ = FALSE;
- return(MK_USE_COPY_FROM_CACHE);
- }
- else
- {
- /* set the correct content length so that
- * the cache gets it right
- */
- ce->URL_s->content_length = ce->URL_s->real_content_length;
- }
- }
-
- /* do we need to start the tranfer over with authorization?
- */
- if(CD_AUTH_REQUIRED)
- {
- /* clear to prevent tight loop */
- int status;
- NET_ClearReadSelect(CE_WINDOW_ID, cd->connection->sock);
- status = NET_AskForAuthString(CE_WINDOW_ID,
- CE_URL_S,
- CE_URL_S->authenticate,
- CE_URL_S->protection_template,
- CD_SENT_AUTHORIZATION);
-
- if(status == NET_RETRY_WITH_AUTH)
- need_to_do_again = TRUE;
- else
- CE_URL_S->dont_cache = TRUE;
-
- NET_SetReadSelect(CE_WINDOW_ID, cd->connection->sock);
- }
- #if defined(XP_WIN) && defined(MOZILLA_CLIENT)
-
- #define COMPUSERVE_HEADER_NAME "Remote-Passphrase"
-
- else if(CE_URL_S->authenticate && !strncasecomp(CE_URL_S->authenticate,
- COMPUSERVE_HEADER_NAME,
- sizeof(COMPUSERVE_HEADER_NAME) - 1))
- {
- /* compuserve auth requires us to send all authenticate
- * headers into their code to verify the authentication
- */
- int status = WFE_DoCompuserveAuthenticate(CE_WINDOW_ID,
- CE_URL_S,
- CE_URL_S->authenticate);
-
- if(status == NET_AUTH_FAILED_DONT_DISPLAY)
- {
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_COMPUSERVE_AUTH_FAILED);
-
- return(MK_COMPUSERVE_AUTH_FAILED);
- }
- }
- #endif /* XP_WIN and MOZILLA_CLIENT */
-
- if(CD_PROXY_AUTH_REQUIRED)
- {
- /* This was hacked in because proxy auth can be required when the Auto-config url
- * itself requires authorization. We used to ask for proxy auth only when the proxy was
- * input directly into the prefs. Now we check to see if there's a pacurl (if there
- * is, there can't be a proxy url simultaneously) use it, otherwise we're using a
- * proxy from the prefs.
- */
- const char *tempURL=NULL;
- char *proxyServer=NULL;
-
- /* Figure out which kind of proxy we're using: PAC or straight proxy.
- * DON'T FREE tempURL!!!
- */
- if ( (tempURL = net_GetPACUrl()) && (*tempURL) )
- proxyServer = NET_ParseURL(tempURL, GET_HOST_PART | GET_PATH_PART | GET_USERNAME_PART | GET_PASSWORD_PART);
- else
- proxyServer = CD_PROXY_SERVER;
-
- if(NET_AskForProxyAuth(CE_WINDOW_ID,
- proxyServer,
- CE_URL_S->proxy_authenticate,
- CD_SENT_PROXY_AUTH))
- need_to_do_again = TRUE;
- else
- CE_URL_S->dont_cache = TRUE;
- /* Only free the our temp proxy server if it's not pointing to CD_PROXY_SERVER.
- * We don't want to be freeing someone elses memory, we were just temporarily
- * pointing to it.
- */
- if (tempURL)
- XP_FREEIF(proxyServer);
- }
-
- if (need_to_do_again)
- {
- NET_ClearReadSelect(CE_WINDOW_ID, cd->connection->sock);
- PR_Close(cd->connection->sock);
- NET_TotalNumberOfOpenConnections--;
- cd->connection->sock = NULL;
- CD_SEND_HTTP1 = TRUE;
- CD_AUTH_REQUIRED = FALSE;
- CD_PROXY_AUTH_REQUIRED = FALSE;
- CD_NEXT_STATE = HTTP_START_CONNECT;
- CE_URL_S->last_modified = 0; /* clear this so we don't get 304 loopage */
-
- /* we don't know if the connection is valid anymore */
- cd->connection_is_valid = FALSE;
-
- /* clear the buffer
- */
- FREE_AND_CLEAR(CD_LINE_BUFFER);
- CD_LINE_BUFFER_SIZE = 0;
-
- /* if necessary */
- FREE_AND_CLEAR(CD_SERVER_HEADERS);
-
- return(0); /* continue */
- }
- else if (CD_DOING_REDIRECT && CE_URL_S->redirecting_url &&
- /* try and prevent a circular loop. wont work for dual doc loop
- */
- XP_STRCMP(CE_URL_S->redirecting_url, CE_URL_S->address))
- {
- Bool do_redirect=TRUE;
- char *curURLHost, *redirectURLHost;
- char *curPort, *redirectPort;
-
- #ifdef MOZILLA_CLIENT
- /* update the global history since we wont have the same
- * url later
- */
- GH_UpdateGlobalHistory(CE_URL_S);
- #endif /* MOZILLA_CLIENT */
-
- /* Inserted for security reasons. Ie. java applets being told to redirect to places they shouldn't be.*/
- if(CE_URL_S->dontAllowDiffHostRedirect) {
-
- if( !(curURLHost = NET_ParseURL(CE_URL_S->address, GET_HOST_PART)) )
- return MK_INTERRUPTED;
- if( !(redirectURLHost = NET_ParseURL(CE_URL_S->redirecting_url, GET_HOST_PART)) ) {
- XP_FREE(curURLHost);
- return MK_INTERRUPTED;
- }
-
- if ( (curPort = XP_STRCHR(curURLHost, ':')) != NULL)
- *curPort='\0';
- if ( (redirectPort = XP_STRCHR(redirectURLHost, ':')) != NULL)
- *redirectPort='\0';
-
- if(strcasecomp(curURLHost, redirectURLHost)) {
- XP_FREE(curURLHost);
- XP_FREE(redirectURLHost);
- FREE_AND_CLEAR(CE_URL_S->redirecting_url);
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_REDIRECT_ATTEMPT_NOT_ALLOWED);
- return MK_REDIRECT_ATTEMPT_NOT_ALLOWED;
- }
-
- XP_FREE(curURLHost);
- XP_FREE(redirectURLHost);
-
- } /* End URL_s->dontAllowDiffHostRedirect */
-
- if(CE_FORMAT_OUT == FO_CACHE_AND_PRESENT) {
- if(NET_IsURLSecure(CE_URL_S->address)) { /* current URL is secure*/
- if(NET_IsURLSecure(CE_URL_S->redirecting_url)) {
- /* new URL is secure */
- /* save the cert of the guy doing the redirect */
- ce->URL_s->redirecting_cert =
- CERT_DupCertificate(ce->URL_s->certificate);
- } else { /* new URL is not secure */
- /* ask the user to confirm */
- do_redirect = (Bool)SECNAV_SecurityDialog(CE_WINDOW_ID,
- SD_REDIRECTION_TO_INSECURE_DOC);
- }
- }
- }
-
- /* OK, now we've got the redirection URL stored
- * in redirecting_url.
- * Now change the URL in the URL structure and do the whole
- * thing again
- */
- StrAllocCopy(CE_URL_S->address, CE_URL_S->redirecting_url);
-
- /* if we were posting a file and received an error put the
- * current file we were posting back on the end of the list
- * so that our state is correctly reset
- */
- net_revert_post_data(ce);
-
- if(!cd->save_redirect_method)
- {
- FREE_AND_CLEAR(CE_URL_S->post_data);
- FREE_AND_CLEAR(CE_URL_S->post_headers);
- CE_URL_S->post_data_size = 0;
- CE_URL_S->method = URL_GET_METHOD;
- }
-
- /* clear these */
- if(!CE_URL_S->preset_content_type)
- FREE_AND_CLEAR(CE_URL_S->content_type);
- FREE_AND_CLEAR(CE_URL_S->content_encoding);
- CE_URL_S->content_length = 0; /* reset */
- CE_URL_S->real_content_length = 0; /* reset */
- CE_URL_S->last_modified = 0; /* reset */
-
- CD_POSTING = FALSE;
-
- CE_URL_S->address_modified = TRUE;
-
- if(do_redirect)
- return(MK_DO_REDIRECT); /*fall out of HTTP and load the redirecting url */
- else
- return(MK_INTERRUPTED);
- }
- else if(CD_SERVER_BUSY_RETRY)
- {
- /* the redirecting mechanism works well for the retry
- * since it is really the same thing except the url stays
- * the same
- */
- return(MK_DO_REDIRECT); /* fall out of HTTP and reload the url */
- }
-
- #ifdef MOZILLA_CLIENT
- /* check to see if we just now entered a secure space
- *
- * don't do if this is coming from history
- * don't do this if about to redirect
- */
- if(CE_URL_S->security_on
- && (CE_FORMAT_OUT == FO_CACHE_AND_PRESENT || CE_FORMAT_OUT == FO_PRESENT)
- && !CE_URL_S->history_num)
- {
- History_entry * h = SHIST_GetCurrent(&CE_WINDOW_ID->hist);
- XP_Bool warn = FALSE;
-
- if (h == NULL) {
- /* Deal with frames. If the window doesn't have history,
- * then it is a new window or a new frame cell.
- */
- if ( ce->window_id->grid_parent != NULL ) {
- h = SHIST_GetCurrent(&ce->window_id->grid_parent->hist);
- if ( !h->security_on ) {
- /* parent frame is not secure */
- warn = TRUE;
- }
- } else {
- /* no parent frame - this is a top level window */
- warn = TRUE;
- }
- } else if ( !h->security_on ) {
- warn = TRUE;
- }
- if ( warn ) {
- SECNAV_SecurityDialog(CE_WINDOW_ID, SD_ENTERING_SECURE_SPACE);
- }
- }
- #endif /* MOZILLA_CLIENT */
-
- /* set a default content type if one wasn't given
- */
- if(!CE_URL_S->content_type
- || !*CE_URL_S->content_type)
- StrAllocCopy(CE_URL_S->content_type, TEXT_HTML);
-
- /* If a stream previously exists from a partial cache
- * situation, reuse it
- */
- if(!CD_STREAM)
- {
- /* clear to prevent tight loop */
- NET_ClearReadSelect(ce->window_id, cd->connection->sock);
-
- #ifdef MOZILLA_CLIENT
- /* if the context can't handle HTML then we
- * need to generate an HTML dialog to handle
- * the message
- */
- if(ce->URL_s->files_to_post && EDT_IS_EDITOR(ce->window_id))
- {
- Chrome chrome_struct;
-
- XP_MEMSET(&chrome_struct, 0, sizeof(Chrome));
-
-
- chrome_struct.is_modal = TRUE;
- chrome_struct.allow_close = TRUE;
- chrome_struct.allow_resize = TRUE;
- chrome_struct.show_scrollbar = TRUE;
- chrome_struct.w_hint = 400;
- chrome_struct.h_hint = 300;
- #ifdef XP_MAC
- /* on Mac, topmost windows are floating windows not dialogs */
- chrome_struct.topmost = FALSE;
- /* disable commands to change to minimal menu bar; */
- /* avoids confusion about which commands are present */
- chrome_struct.disable_commands = TRUE;
- #else
- chrome_struct.topmost = TRUE;
- #endif
-
-
- stream_context = FE_MakeNewWindow(ce->window_id,
- NULL,
- NULL,
- &chrome_struct);
- if(!stream_context)
- return (MK_OUT_OF_MEMORY);
-
- /* zero out the post_data field so that it doesn't get
- * pushed onto the history stack. Otherwise it can
- * get deleted when the history gets cleared
- */
- FREE_AND_CLEAR(ce->URL_s->post_data);
- ce->URL_s->post_data_is_file = FALSE;
- }
- else
- #endif /* MOZILLA_CLIENT */
- {
- stream_context = CE_WINDOW_ID;
- }
-
- /* we can get here on server or proxy errors
- * if we proceed to build the stream with post_data
- * set then the file could get deleted by history
- * cleanup code. Make sure we zero the field
- */
- if(ce->URL_s->files_to_post && ce->URL_s->post_data)
- {
- /* we shoved the file to post into the post data.
- * remove it so the history doesn't get confused
- * and try and delete the file.
- */
- FREE_AND_CLEAR(ce->URL_s->post_data);
- ce->URL_s->post_data_is_file = FALSE;
- }
-
- /* Set up the stream stack to handle the body of the message */
- CD_STREAM = NET_StreamBuilder(CE_FORMAT_OUT,
- CE_URL_S,
- stream_context);
-
- if (!CD_STREAM)
- {
- CE_STATUS = MK_UNABLE_TO_CONVERT;
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_UNABLE_TO_CONVERT);
- return STATUS(CE_STATUS);
- }
- HG94794
- NET_SetReadSelect(CE_WINDOW_ID, cd->connection->sock);
-
- if(ce->URL_s->files_to_post)
- {
- char * tmp_string = XP_STRDUP("<h2>Error uploading files</h2><b>The server responded:<b><hr><p>\n");
-
- if(tmp_string)
- PUTSTRING(tmp_string);
- }
- }
- else
- {
- /* check to see if it's a multipart respose.
- * if it is then we need to do some magic to
- * strip the multipart
- */
- if(!strncasecomp(ce->URL_s->content_type, "multipart", 9))
- {
- /* reset the state to parse_mime_headers to strip
- * the multipart headers off
- */
- CD_NEXT_STATE = HTTP_PARSE_MIME_HEADERS;
- return STATUS(CE_STATUS);
- }
- }
-
- if(CD_USE_COPY_FROM_CACHE)
- {
- /* we can only get here if it's a partial cache file */
- CD_NEXT_STATE = HTTP_BEGIN_PUSH_PARTIAL_CACHE_FILE;
- CD_USE_COPY_FROM_CACHE = FALSE;
- }
- else
- {
- /* start the graph progress indicator
- */
- FE_GraphProgressInit(CE_WINDOW_ID,
- CE_URL_S,
- cd->original_content_length);
- CD_DESTROY_GRAPH_PROGRESS = TRUE; /* we will need to destroy it */
-
- CD_NEXT_STATE = HTTP_PULL_DATA;
-
- if(CD_ACTING_AS_PROXY && CD_SERVER_HEADERS)
- {
- CE_STATUS = PUTBLOCK(CD_SERVER_HEADERS,
- XP_STRLEN(CD_SERVER_HEADERS));
- CD_DISPLAYED_SOME_DATA = TRUE;
- }
-
- {
- char * nonProxyHost = NET_ParseURL(CE_URL_S->address, GET_HOST_PART);
- if (nonProxyHost) {
- char* msg = PR_smprintf(XP_GetString(XP_PROGRESS_TRANSFER_DATA),
- nonProxyHost);
- if (msg) {
- NET_Progress(CE_WINDOW_ID, msg);
- XP_FREE(msg);
- }
- XP_FREE(nonProxyHost);
- }
- }
-
- /* Push though buffered data */
- if(CD_LINE_BUFFER_SIZE)
- {
- /* @@@ bug, check return status and only send
- * up to the return value
- */
- (*CD_STREAM->is_write_ready)(CD_STREAM);
- CE_STATUS = PUTBLOCK(CD_LINE_BUFFER, CD_LINE_BUFFER_SIZE);
- CE_BYTES_RECEIVED = CD_LINE_BUFFER_SIZE;
- FE_GraphProgress(CE_WINDOW_ID,
- CE_URL_S,
- CE_BYTES_RECEIVED,
- CD_LINE_BUFFER_SIZE,
- CD_ORIGINAL_CONTENT_LENGTH);
- CD_DISPLAYED_SOME_DATA = TRUE;
- }
- }
-
- FREE_AND_CLEAR(CD_LINE_BUFFER);
- CD_LINE_BUFFER_SIZE=0;
-
- /* check to see if we have read the whole object,
- * and finish the transfer if so.
- */
- if(CE_STATUS > -1
- && CD_ORIGINAL_CONTENT_LENGTH
- && CE_BYTES_RECEIVED >= CD_ORIGINAL_CONTENT_LENGTH)
- {
- /* normal end of transfer */
- CE_STATUS = MK_DATA_LOADED;
- CD_NEXT_STATE = HTTP_DONE;
- CD_PAUSE_FOR_READ = FALSE;
- }
-
- return STATUS(CE_STATUS);
- }
-
- /* begin pushing a partial cache file down the stream
- */
- PRIVATE int
- net_http_push_partial_cache_file(ActiveEntry *ce)
- {
- HTTPConData * cd = (HTTPConData *)ce->con_data;
- int32 write_ready, status;
-
- write_ready = (*cd->stream->is_write_ready)(cd->stream);
-
- write_ready = MIN(write_ready, NET_Socket_Buffer_Size);
-
- status = XP_FileRead(NET_Socket_Buffer, write_ready, cd->partial_cache_fp);
-
- if(status < 0)
- {
- /* @@@ This is the wrong error code
- */
- ce->URL_s->error_msg = NET_ExplainErrorDetails(MK_TCP_READ_ERROR,
- SOCKET_ERRNO);
- return(MK_TCP_READ_ERROR);
- }
- else if(status == 0)
- {
- /* all done with reading this file
- */
- NET_ClearFileReadSelect(ce->window_id, XP_Fileno(cd->partial_cache_fp));
- XP_FileClose(cd->partial_cache_fp);
- cd->partial_cache_fp = NULL;
-
- /* set these back in preperation for
- * using the http connection again
- */
- ce->socket = cd->connection->sock;
- ce->local_file = FALSE;
-
- /* add a request-range header
- */
- XP_ASSERT(!ce->URL_s->range_header);
- ce->URL_s->range_header = PR_smprintf("bytes=%ld-",
- cd->partial_needed);
-
- /* the byterange part has not been gotten yet */
- ce->URL_s->last_modified = 0;
-
- /* we don't know if the connection is valid anymore
- * because we are going to try it again
- */
- cd->connection_is_valid = FALSE;
-
- if(ce->URL_s->can_reuse_connection)
- {
- NET_SetReadSelect(ce->window_id, cd->connection->sock);
- cd->next_state = HTTP_SEND_REQUEST;
-
- /* set the connection to be from the connection cache
- * since we have used it once
- */
- cd->connection->prev_cache = TRUE;
- }
- else
- {
- NET_ClearReadSelect(CE_WINDOW_ID, cd->connection->sock);
- NET_ClearConnectSelect(CE_WINDOW_ID, cd->connection->sock);
- PR_Close(cd->connection->sock);
- NET_TotalNumberOfOpenConnections--;
- cd->connection->sock = NULL;
- cd->next_state = HTTP_START_CONNECT;
- }
-
- cd->reuse_stream = TRUE;
-
- return(0);
- }
-
- /* else, push the data read up the stream
- */
- status = (*cd->stream->put_block)(cd->stream,
- NET_Socket_Buffer,
- status);
-
- cd->pause_for_read = TRUE;
-
- return(status);
- }
-
- /* begin pushing a partial cache file down the stream
- */
- PRIVATE int
- net_http_begin_push_partial_cache_file(ActiveEntry *ce)
- {
- HTTPConData * cd = (HTTPConData *)ce->con_data;
- char *cache_file = ce->URL_s->cache_file;
- XP_File fp;
-
- if(!cache_file
- || NULL == (fp = XP_FileOpen(cache_file, xpCache, XP_FILE_READ_BIN)))
- {
- ce->URL_s->error_msg = NET_ExplainErrorDetails(MK_UNABLE_TO_OPEN_FILE,
- cache_file);
- return(MK_UNABLE_TO_OPEN_FILE);
- }
-
- /* set up read select on the file instead of the socket
- */
- NET_ClearReadSelect(ce->window_id, cd->connection->sock);
- NET_SetFileReadSelect(ce->window_id, XP_Fileno(fp));
- ce->socket = NULL;
- ce->local_file = TRUE;
-
- cd->next_state = HTTP_PUSH_PARTIAL_CACHE_FILE;
-
- cd->partial_cache_fp = fp;
-
- return(net_http_push_partial_cache_file(ce));
- }
-
- /* pulls down all the data
- *
- * returns the tcp status code
- */
- PRIVATE int
- net_pull_http_data(ActiveEntry * ce)
- {
- HTTPConData * cd = (HTTPConData *)ce->con_data;
- unsigned int write_ready, read_size;
-
- TRACEMSG(("NET_ProcessHTTP: pulling data"));
-
- /* check to see if the stream is ready for writing
- */
- write_ready = (*CD_STREAM->is_write_ready)(CD_STREAM);
-
- if(!write_ready)
- {
- CD_PAUSE_FOR_READ = TRUE;
- return(0); /* wait until we are ready to write */
- }
- else if(write_ready < (unsigned int) NET_Socket_Buffer_Size)
- {
- read_size = write_ready;
- }
- else
- {
- read_size = NET_Socket_Buffer_Size;
- }
-
- CE_STATUS = PR_Read(cd->connection->sock, NET_Socket_Buffer, read_size);
-
- CD_PAUSE_FOR_READ = TRUE; /* pause for the next read */
-
- if(CE_STATUS > 0)
- {
- CE_BYTES_RECEIVED += CE_STATUS;
- FE_GraphProgress(CE_WINDOW_ID,
- CE_URL_S,
- CE_BYTES_RECEIVED,
- CE_STATUS,
- CD_ORIGINAL_CONTENT_LENGTH);
-
- CE_STATUS = PUTBLOCK(NET_Socket_Buffer, CE_STATUS); /* ALEKS */
- CD_DISPLAYED_SOME_DATA = TRUE;
-
- if(CD_ORIGINAL_CONTENT_LENGTH
- && CE_BYTES_RECEIVED >= CD_ORIGINAL_CONTENT_LENGTH)
- {
- /* normal end of transfer */
- CE_STATUS = MK_DATA_LOADED;
- CD_NEXT_STATE = HTTP_DONE;
- CD_PAUSE_FOR_READ = FALSE;
- }
-
- }
- else if(CE_STATUS == 0)
- {
- /* transfer finished
- */
- TRACEMSG(("MKHTTP.c: Caught TCP EOF ending stream"));
-
- if(!CD_DISPLAYED_SOME_DATA)
- {
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_ZERO_LENGTH_FILE);
- CD_NEXT_STATE = HTTP_ERROR_DONE;
- CD_PAUSE_FOR_READ = FALSE;
- return(MK_ZERO_LENGTH_FILE);
- }
-
- /* return the server status instead of data loaded
- */
- CE_STATUS = MK_DATA_LOADED;
- CD_NEXT_STATE = HTTP_DONE;
- CD_PAUSE_FOR_READ = FALSE;
- }
- else /* error */
- {
- int err = PR_GetError();
-
- TRACEMSG(("TCP Error: %d", err));
-
- if (err == PR_WOULD_BLOCK_ERROR)
- {
- CD_PAUSE_FOR_READ = TRUE;
- return (0);
- }
-
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_TCP_READ_ERROR, err);
-
- /* return TCP error
- */
- return MK_TCP_READ_ERROR;
- }
-
- return STATUS(CE_STATUS);
-
- }
-
- /* begin loading an object from an http host
- *
- * proxy_server If not empty, the name of a host and/or port that will
- * act as a proxy server for the request. If proxy_server
- * is NULL then no proxy server is used
- *
- */
- PRIVATE int32
- net_HTTPLoad (ActiveEntry * ce)
- {
- /* get memory for Connection Data */
- HTTPConData * cd = XP_NEW(HTTPConData);
- XP_Bool url_is_secure = FALSE;
- char *use_host;
-
- ce->con_data = cd;
- if(!ce->con_data)
- {
- CE_STATUS = MK_OUT_OF_MEMORY;
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_OUT_OF_MEMORY);
- return STATUS(CE_STATUS);
- }
-
- /* kill any returns in the URL */
- XP_STRTOK(ce->URL_s->address, "\r");
- XP_STRTOK(ce->URL_s->address, "\n");
-
- /* init */
- XP_MEMSET(cd, 0, sizeof(HTTPConData));
- CD_PROXY_SERVER = ce->proxy_addr;
- CD_PROXY_CONF = ce->proxy_conf;
- CD_SEND_HTTP1 = TRUE;
-
- /* set partial_cache_file if the whole file is not
- * cached
- */
- if(ce->URL_s->content_length < ce->URL_s->real_content_length)
- {
- cd->partial_cache_file = TRUE;
- cd->partial_needed = ce->URL_s->content_length;
-
- #ifdef MOZILLA_CLIENT
- /* if this isn't true then partial cacheing is screwed */
- XP_ASSERT(NET_IsPartialCacheFile(ce->URL_s));
- #else
- XP_ASSERT(0);
- #endif /* MOZILLA_CLIENT */
- }
-
- if(CD_PROXY_SERVER)
- {
- use_host = XP_STRDUP(CD_PROXY_SERVER);
- }
- else
- {
- use_host = NET_ParseURL(ce->URL_s->address, GET_HOST_PART);
- if(!strncasecomp(ce->URL_s->address, "https:", 6))
- url_is_secure = TRUE;
- }
-
- if(!use_host)
- {
- FREE(ce->con_data);
- CE_STATUS = MK_OUT_OF_MEMORY;
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_OUT_OF_MEMORY);
- return STATUS(CE_STATUS);
- }
-
- /* if we are useing the files_to_post method
- * make sure that the directory specified in the
- * URL contains a slash at the end, otherwise
- * it wont work
- */
- if(ce->URL_s->files_to_post)
- {
- int32 end = XP_STRLEN(ce->URL_s->address)-1;
- XP_StatStruct stat_entry;
- int i;
-
- if(ce->URL_s->address[end] != '/')
- StrAllocCat(ce->URL_s->address, "/");
-
- /* run through the list of files and
- * gather the total size
- */
- for(i=0; ce->URL_s->files_to_post[i]; i++)
- if(-1 != XP_Stat(ce->URL_s->files_to_post[i],
- &stat_entry,
- xpFileToPost))
- cd->total_size_of_files_to_post += stat_entry.st_size;
-
- /* start the graph progress indicator
- */
- FE_GraphProgressInit(ce->window_id,
- ce->URL_s,
- cd->total_size_of_files_to_post);
-
- CD_DESTROY_GRAPH_PROGRESS = TRUE; /* we will need to destroy it */
-
- #ifdef EDITOR
- /* Don't show the dialog if the data is being delivered to a plug-in */
- if ( (CLEAR_CACHE_BIT(ce->format_out) != FO_PLUGIN)
- && (CLEAR_CACHE_BIT(ce->format_out) != FO_LOCATION_INDEPENDENCE))
- {
- FE_SaveDialogCreate(ce->window_id, i, ED_SAVE_DLG_PUBLISH);
- cd->destroy_file_upload_progress_dialog = TRUE;
- }
- #endif /* EDITOR */
- }
-
- /* check for established connection and use it if available
- */
- if(http_connection_list)
- {
- HTTPConnection * tmp_con;
- XP_List * list_entry = http_connection_list;
-
- /* If the url is secure and we are using a proxy server
- * then never use a cached connection
- */
- if(!cd->use_ssl_proxy)
- {
-
- while((tmp_con = (HTTPConnection *)XP_ListNextObject(list_entry))
- != NULL)
- {
- /* if the hostnames match up exactly
- * and security matches up.
- * and the connection
- * is not busy at the moment then reuse this connection.
- */
- if(!XP_STRCMP(tmp_con->hostname, use_host)
- && url_is_secure == tmp_con->secure
- && !tmp_con->busy)
- {
- cd->connection = tmp_con;
- cd->connection->sock = cd->connection->sock;
- NET_SetReadSelect(CE_WINDOW_ID, cd->connection->sock);
- CE_SOCK = cd->connection->sock;
- cd->connection->prev_cache = TRUE; /* this was from the cache */
- TRACEMSG(("Found cached HTTP connection: %d", cd->connection->sock));
-
- /* reorder the connection in the list to keep most recently
- * used connections at the end
- */
- XP_ListRemoveObject(http_connection_list, tmp_con);
- XP_ListAddObjectToEnd(http_connection_list, tmp_con);
-
- break;
- }
- }
- }
- }
- else
- {
- /* initialize the connection list
- */
- http_connection_list = XP_ListNew();
- }
-
- if(cd->connection)
- {
- if(CD_USE_SSL_PROXY)
- CD_NEXT_STATE = HTTP_SEND_SSL_PROXY_REQUEST;
- else if(ce->URL_s->files_to_post)
- CD_NEXT_STATE = HTTP_BEGIN_UPLOAD_FILE;
- else
- CD_NEXT_STATE = HTTP_SEND_REQUEST;
-
- /* set the connection busy
- */
- cd->connection->busy = TRUE;
- NET_TotalNumberOfOpenConnections++;
- }
- else
- {
- /* build a control connection structure so we
- * can store the data as we go along
- */
- cd->connection = XP_NEW(HTTPConnection);
- if(!cd->connection)
- {
- CE_STATUS = MK_OUT_OF_MEMORY;
- CE_URL_S->error_msg = NET_ExplainErrorDetails(MK_OUT_OF_MEMORY);
- FREE(use_host);
- FREE(ce->con_data);
- return(-1);
- }
- XP_MEMSET(cd->connection, 0, sizeof(HTTPConnection));
-
- StrAllocCopy(cd->connection->hostname, use_host);
-
- cd->connection->secure = url_is_secure;
-
- cd->connection->prev_cache = FALSE; /* this wasn't from the cache */
-
- cd->connection->sock = NULL;
-
- /* add this structure to the connection list even
- * though it's not really valid yet.
- * we will fill it in as we go and if
- * an error occurs will will remove it from the
- * list. No one else will be able to use it since
- * we will mark it busy.
- */
- XP_ListAddObject(http_connection_list, cd->connection);
-
- /* set the connection busy
- */
- cd->connection->busy = TRUE;
-
- /* if the connection list is larger than MAX_CACHED_HTTP_CONNECTIONS
- * trim it down
- */
- if(XP_ListCount(http_connection_list) > MAX_CACHED_HTTP_CONNECTIONS)
- {
- HTTPConnection *tmp_con;
- XP_List * list_entry = http_connection_list;
-
- TRACEMSG(("More than %d cached connections. Deleteing one...",
- MAX_CACHED_HTTP_CONNECTIONS));
-
- while((tmp_con = (HTTPConnection *)XP_ListNextObject(list_entry)) != NULL)
- {
- if(!tmp_con->busy)
- {
-
- if(!strncasecomp(tmp_con->hostname, "rl.", 3)
- && strcasestr(tmp_con->hostname+2, ".netscape.com"))
- {
- /* if there is max plus one we are done, else
- * continue on and remove one
- */
- if(XP_ListCount(http_connection_list)
- == MAX_CACHED_HTTP_CONNECTIONS+1)
- {
- break; /* from while */
- }
-
- }
- else
- {
- /* remove the object */
- XP_ListRemoveObject(http_connection_list, tmp_con);
- PR_Close(tmp_con->sock);
- FREE(tmp_con->hostname);
- FREE(tmp_con);
- break; /* from while */
- }
- }
- }
- }
-
- CD_NEXT_STATE = HTTP_START_CONNECT;
-
- }
-
- FREE(use_host);
-
- return STATUS (net_ProcessHTTP(ce));
- }
-
-
- /* NET_process_HTTP will control the state machine that
- * loads an HTTP document
- *
- * returns negative if the transfer is finished or error'd out
- *
- * returns zero or more if the transfer needs to be continued.
- */
- PRIVATE int32
- net_ProcessHTTP (ActiveEntry *ce)
- {
- HTTPConData * cd = (HTTPConData *)ce->con_data;
-
- TRACEMSG(("Entering NET_ProcessHTTP"));
-
- CD_PAUSE_FOR_READ = FALSE; /* already paused; reset */
-
- while(!CD_PAUSE_FOR_READ)
- {
-
- switch(CD_NEXT_STATE)
- {
- case HTTP_START_CONNECT:
- CE_STATUS = net_start_http_connect(ce);
- break;
-
- case HTTP_FINISH_CONNECT:
- CE_STATUS = net_finish_http_connect(ce);
- break;
-
- case HTTP_SEND_SSL_PROXY_REQUEST:
- /* send ssl proxy init stuff
- */
- CE_STATUS = net_send_ssl_proxy_request(ce);
- break;
-
- case HTTP_BEGIN_UPLOAD_FILE:
- /* form a put request */
- ce->status = net_begin_upload_file (ce);
- break;
- HG51096
- case HTTP_SEND_REQUEST:
- /* send HTTP request */
- CE_STATUS = net_send_http_request(ce);
- break;
-
- case HTTP_SEND_POST_DATA:
- CE_STATUS = net_http_send_post_data(ce);
- break;
-
- case HTTP_PARSE_FIRST_LINE:
- CE_STATUS = net_parse_first_http_line(ce);
- break;
-
- case HTTP_PARSE_MIME_HEADERS:
- CE_STATUS = net_parse_http_mime_headers(ce);
- break;
-
- case HTTP_SETUP_STREAM:
- CE_STATUS = net_setup_http_stream(ce);
- break;
-
- case HTTP_BEGIN_PUSH_PARTIAL_CACHE_FILE:
- ce->status = net_http_begin_push_partial_cache_file(ce);
- break;
-
- case HTTP_PUSH_PARTIAL_CACHE_FILE:
- ce->status = net_http_push_partial_cache_file(ce);
- break;
-
- case HTTP_PULL_DATA:
- CE_STATUS = net_pull_http_data(ce);
- break;
-
- case HTTP_DONE:
- NET_ClearReadSelect(CE_WINDOW_ID, cd->connection->sock);
- NET_TotalNumberOfOpenConnections--;
-
- if(ce->URL_s->can_reuse_connection && !CD_USE_SSL_PROXY)
- {
- cd->connection->busy = FALSE;
- }
- else
- {
- PR_Close(cd->connection->sock);
-
- /* remove the connection from the cache list
- * and free the data
- */
- XP_ListRemoveObject(http_connection_list, cd->connection);
- if(cd->connection)
- {
- FREEIF(cd->connection->hostname);
- FREE(cd->connection);
- }
- }
-
- #ifdef MOZILLA_CLIENT
- /* make any meta tag changes take effect
- */
- NET_RefreshCacheFileExpiration(CE_URL_S);
- #endif /* MOZILLA_CLIENT */
-
- if(CD_STREAM)
- {
- COMPLETE_STREAM;
- FREE(CD_STREAM);
- CD_STREAM = 0;
- }
- CD_NEXT_STATE = HTTP_FREE;
- break;
-
- case HTTP_ERROR_DONE:
- if(cd->connection->sock != NULL)
- {
- NET_ClearDNSSelect(CE_WINDOW_ID, cd->connection->sock);
- NET_ClearReadSelect(CE_WINDOW_ID, cd->connection->sock);
- NET_ClearConnectSelect(CE_WINDOW_ID, cd->connection->sock);
- PR_Close(cd->connection->sock);
- NET_TotalNumberOfOpenConnections--;
- cd->connection->sock = NULL;
- }
-
- if(cd->partial_cache_fp)
- {
- NET_ClearFileReadSelect(ce->window_id,
- XP_Fileno(cd->partial_cache_fp));
- XP_FileClose(cd->partial_cache_fp);
- cd->partial_cache_fp = 0;
- }
-
-
- if(cd->connection->prev_cache
- && !cd->connection_is_valid
- && ce->status != MK_INTERRUPTED)
- {
- if(CD_STREAM && !cd->reuse_stream)
- {
- ABORT_STREAM(CE_STATUS);
- FREE(CD_STREAM);
- CD_STREAM = 0;
- }
-
- /* the connection came from the cache and
- * may have been stale. Try it again
- */
- /* clear any error message */
- if(ce->URL_s->error_msg)
- {
- FREE(ce->URL_s->error_msg);
- ce->URL_s->error_msg = NULL;
- }
- cd->next_state = HTTP_START_CONNECT;
- ce->status = 0;
-
- /* we don't know if the connection is valid anymore
- * because we are going to try it again
- */
- cd->connection_is_valid = FALSE;
-
- cd->connection->prev_cache = FALSE;
-
- /* if we were posting a file and received an error put the
- * current file we were posting back on the end of the list
- * so that our state is correctly reset
- */
- net_revert_post_data(ce);
-
- }
- else
- {
- CD_NEXT_STATE = HTTP_FREE;
-
- if(CD_STREAM)
- {
- ABORT_STREAM(CE_STATUS);
- FREE(CD_STREAM);
- CD_STREAM = 0;
- }
-
- /* remove the connection from the cache list
- * and free the data
- */
- XP_ListRemoveObject(http_connection_list, cd->connection);
- FREEIF(cd->connection->hostname);
- FREE(cd->connection);
- }
-
- break;
-
- case HTTP_FREE:
-
- /* close the file upload progress. If a stream was created
- * then some sort of HTTP error occured. Send in an error
- * code
- */
- #ifdef EDITOR
- if(cd->destroy_file_upload_progress_dialog) {
- /* Convert from netlib errors to editor errors. */
- ED_FileError error = ED_ERROR_NONE;
- if ( (ce->URL_s->server_status != 204 && ce->URL_s->server_status != 201 )
- || ce->status < 0 )
- error = ED_ERROR_PUBLISHING;
- FE_SaveDialogDestroy(ce->window_id, error, ce->URL_s->post_data);
- /* FE_SaveDialogDestroy(ce->window_id, ce->URL_s->server_status != 204 ? -1 : ce->status, ce->URL_s->post_data); */
- }
- #endif /* EDITOR */
-
- if(ce->URL_s->files_to_post && ce->URL_s->post_data)
- {
- /* we shoved the file to post into the post data.
- * remove it so the history doesn't get confused
- * and try and delete the file.
- */
- FREE_AND_CLEAR(ce->URL_s->post_data);
- ce->URL_s->post_data_is_file = FALSE;
- }
-
- if(CD_DESTROY_GRAPH_PROGRESS)
- FE_GraphProgressDestroy(CE_WINDOW_ID,
- CE_URL_S,
- CD_ORIGINAL_CONTENT_LENGTH,
- CE_BYTES_RECEIVED);
-
- FREEIF(CD_LINE_BUFFER);
- FREEIF(CD_STREAM); /* don't forget the stream */
- FREEIF(CD_SERVER_HEADERS);
- FREEIF(cd->orig_host);
- if(CD_TCP_CON_DATA)
- NET_FreeTCPConData(CD_TCP_CON_DATA);
- FREEIF(cd);
- JSCF_Cleanup();
- return STATUS (-1); /* final end */
-
- default: /* should never happen !!! */
- TRACEMSG(("HTTP: BAD STATE!"));
- CD_NEXT_STATE = HTTP_ERROR_DONE;
- break;
- }
-
- /* check for errors during load and call error
- * state if found
- */
- if(CE_STATUS < 0
- && CE_STATUS != MK_USE_COPY_FROM_CACHE
- && CD_NEXT_STATE != HTTP_FREE)
- {
-
- if (CE_STATUS == MK_MULTIPART_MESSAGE_COMPLETED)
- {
- /* We found the end of a multipart/mixed response
- * from a CGI script in a http keep-alive response
- * That signifies the end of a message.
- */
- TRACEMSG(("mkhttp.c: End of multipart keep-alive response"));
-
- CE_STATUS = MK_DATA_LOADED;
- CD_NEXT_STATE = HTTP_DONE;
-
- }
- else if (CE_STATUS == MK_HTTP_TYPE_CONFLICT
- /* Don't retry if were HTTP/.9 */
- && !CD_SEND_HTTP1
- /* Don't retry if we're posting. */
- && !CD_POSTING)
- {
- /* Could be a HTTP 0/1 compability problem. */
- TRACEMSG(("HTTP: Read error trying again with HTTP0 request."));
- NET_Progress (CE_WINDOW_ID, XP_GetString(XP_PROGRESS_TRYAGAIN));
-
- NET_ClearReadSelect(CE_WINDOW_ID, cd->connection->sock);
- NET_ClearConnectSelect(CE_WINDOW_ID, cd->connection->sock);
- #ifdef XP_WIN
- if(cd->calling_netlib_all_the_time)
- {
- NET_ClearCallNetlibAllTheTime(CE_WINDOW_ID, "mkhttp");
- }
- #endif /* XP_WIN */
- NET_ClearDNSSelect(CE_WINDOW_ID, cd->connection->sock);
- PR_Close(cd->connection->sock);
- NET_TotalNumberOfOpenConnections--;
- cd->connection->sock = NULL;
-
- if(CD_STREAM)
- (*CD_STREAM->abort) (CD_STREAM, CE_STATUS);
- CD_SEND_HTTP1 = FALSE;
- /* go back and send an HTTP0 request */
- CD_NEXT_STATE = HTTP_START_CONNECT;
- }
- else
- {
- CD_NEXT_STATE = HTTP_ERROR_DONE;
- }
- /* don't exit! loop around again and do the free case */
- CD_PAUSE_FOR_READ = FALSE;
- }
- } /* while(!CD_PAUSE_FOR_READ) */
-
- return STATUS(CE_STATUS);
- }
-
-
- /* abort the connection in progress
- */
- PRIVATE int32
- net_InterruptHTTP(ActiveEntry * ce)
- {
- HTTPConData * cd = (HTTPConData *)ce->con_data;
-
- /* if we are currently pulling data and the data is
- * Textual then truncate the file, leave notification and
- * end normally
- */
- if(CD_NEXT_STATE == HTTP_PULL_DATA
- && CE_URL_S->content_type
- && !strcasecomp(CE_URL_S->content_type, TEXT_HTML))
- {
- char buffer[127];
-
- if(!strcasecomp(CE_URL_S->content_type, TEXT_HTML))
- PR_snprintf(buffer, sizeof(buffer),
- XP_GetString(XP_HR_TRANSFER_INTERRUPTED));
- else
- PR_snprintf(buffer, sizeof(buffer),
- XP_GetString(XP_TRANSFER_INTERRUPTED));
-
- PUTSTRING(buffer);
-
- /* steps from HTTP_DONE duplicated, with the addition of
- * NET_RefreshCacheFileExpiration
- */
- NET_ClearReadSelect(CE_WINDOW_ID, cd->connection->sock);
- PR_Close(cd->connection->sock);
- NET_TotalNumberOfOpenConnections--;
- ABORT_STREAM(MK_INTERRUPTED);
- FREE(CD_STREAM);
- CD_STREAM = 0;
-
- CE_URL_S->last_modified = 0;
- #ifdef MOZILLA_CLIENT
- /* to make the last_modified change take effect
- */
- NET_RefreshCacheFileExpiration(CE_URL_S);
- #endif /* MOZILLA_CLIENT */
-
- CD_NEXT_STATE = HTTP_FREE;
-
- CE_STATUS = MK_DATA_LOADED;
- }
- else
- {
- CD_NEXT_STATE = HTTP_ERROR_DONE;
- CE_STATUS = MK_INTERRUPTED;
- }
-
- return STATUS (net_ProcessHTTP(ce));
- }
-
- /* Free any memory that might be used in caching etc.
- */
- PRIVATE void
- net_CleanupHTTP(void)
- {
- /* nothing so far needs freeing */
- return;
- }
-
- MODULE_PRIVATE void
- NET_InitHTTPProtocol(void)
- {
- static NET_ProtoImpl http_proto_impl;
-
- http_proto_impl.init = net_HTTPLoad;
- http_proto_impl.process = net_ProcessHTTP;
- http_proto_impl.interrupt = net_InterruptHTTP;
- http_proto_impl.cleanup = net_CleanupHTTP;
-
- NET_RegisterProtocolImplementation(&http_proto_impl, HTTP_TYPE_URL);
- NET_RegisterProtocolImplementation(&http_proto_impl, SECURE_HTTP_TYPE_URL);
- }
-
- #ifdef PROFILE
- #pragma profile off
- #endif
-