dmose%mozilla.org ce50f7d151 updated license boilerplate to xPL 1.1, a=chofmann@netscape.com,r=endico@mozilla.org
git-svn-id: svn://10.0.0.236/trunk@52900 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-06 02:47:15 +00:00

5457 lines
147 KiB
C

/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
*
* Designed and Implemented by Lou Montulli '94
* Heavily modified by Judson Valeski '97
* Yada yada yada... Gagan Saksena '98
*
* This file implements HTTP access authorization
* and HTTP cookies
*/
#if defined(CookieManagement)
/* #define TRUST_LABELS */
#endif
#if defined(SingleSignon)
#define EDITOR 1
#endif
#define alphabetize 1
#include "rosetta.h"
#include "xp.h"
#include "mkprefs.h"
#include "netutils.h"
#include "mkselect.h"
#include "mktcp.h"
#include "mkgeturl.h"
#include "mkparse.h"
#include "mkaccess.h"
#include "net_xp_file.h"
/*#include "cookies.h" */
#include "httpauth.h"
#include "prefapi.h"
#include "shist.h"
#include "jscookie.h"
#include "prmon.h"
#include "edt.h" /* for EDT_SavePublishUsernameAndPassword */
#ifdef XP_MAC
#include "prpriv.h" /* for NewNamedMonitor */
#else
#include "private/prpriv.h"
#endif
#include "secnav.h"
#include "sechash.h"
#include "libevent.h"
#include "pwcacapi.h"
/* for XP_GetString() */
#include "xpgetstr.h"
extern int XP_CONFIRM_AUTHORIZATION_FAIL;
extern int XP_ACCESS_ENTER_USERNAME;
extern int XP_CONFIRM_PROXYAUTHOR_FAIL;
extern int XP_CONNECT_PLEASE_ENTER_PASSWORD_FOR_HOST;
extern int XP_PROXY_REQUIRES_UNSUPPORTED_AUTH_SCHEME;
extern int XP_LOOPING_OLD_NONCES;
extern int XP_UNIDENTIFIED_PROXY_SERVER;
extern int XP_PROXY_AUTH_REQUIRED_FOR;
extern int XP_CONNECT_PLEASE_ENTER_PASSWORD_FOR_PROXY;
extern int XP_FORTEZZA_PROXY_AUTH;
/*
extern int MK_ACCESS_COOKIES_THE_SERVER;
extern int MK_ACCESS_COOKIES_WISHES;
#if defined(CookieManagement)
extern int MK_ACCESS_COOKIES_WISHES0;
extern int MK_ACCESS_COOKIES_WISHES1;
extern int MK_ACCESS_COOKIES_WISHESN;
extern int MK_ACCESS_COOKIES_WISHES_MODIFY;
extern int MK_ACCESS_COOKIES_REMEMBER;
extern int MK_ACCESS_COOKIES_ACCEPTED;
extern int MK_ACCESS_SITE_COOKIES_ACCEPTED;
extern int MK_ACCESS_COOKIES_PERMISSION;
#else
extern int MK_ACCESS_COOKIES_TOANYSERV;
extern int MK_ACCESS_COOKIES_TOSELF;
extern int MK_ACCESS_COOKIES_NAME_AND_VAL;
extern int MK_ACCESS_COOKIES_COOKIE_WILL_PERSIST;
#endif
extern int MK_ACCESS_COOKIES_SET_IT;
extern int MK_ACCESS_YOUR_COOKIES;
extern int MK_ACCESS_NAME;
extern int MK_ACCESS_VALUE;
extern int MK_ACCESS_HOST;
extern int MK_ACCESS_DOMAIN;
extern int MK_ACCESS_PATH;
extern int MK_ACCESS_YES;
extern int MK_ACCESS_NO;
extern int MK_ACCESS_SECURE;
extern int MK_ACCESS_EXPIRES;
extern int MK_ACCESS_END_OF_SESSION;
extern int MK_ACCESS_VIEW_COOKIES;
extern int MK_ACCESS_VIEW_SITES;
#ifdef TRUST_LABELS
extern int MK_ACCESS_TL_PUR1;
extern int MK_ACCESS_TL_PUR2;
extern int MK_ACCESS_TL_PUR3;
extern int MK_ACCESS_TL_PUR4;
extern int MK_ACCESS_TL_PUR5;
extern int MK_ACCESS_TL_PUR6;
extern int MK_ACCESS_TL_PPH0;
extern int MK_ACCESS_TL_PPH1;
extern int MK_ACCESS_TL_PPH2;
extern int MK_ACCESS_TL_PPH3;
extern int MK_ACCESS_TL_PPH4;
extern int MK_ACCESS_TL_PPH5;
extern int MK_ACCESS_TL_ID1;
extern int MK_ACCESS_TL_ID0;
extern int MK_ACCESS_TL_BY;
extern int MK_ACCESS_TL_RECP1;
extern int MK_ACCESS_TL_RECP2;
extern int MK_ACCESS_TL_RECP3;
extern int MK_ACCESS_TL_RPH0;
extern int MK_ACCESS_TL_RPH1;
extern int MK_ACCESS_TL_RPH2;
extern int MK_ACCESS_TL_RPH3;
#endif
#define MAX_NUMBER_OF_COOKIES 300
#define MAX_COOKIES_PER_SERVER 20
#define MAX_BYTES_PER_COOKIE 4096 // must be at least 1
*/
/*
* Authentication information for servers and proxies is kept
* on separate lists, but both lists consist of net_AuthStruct's.
*/
HG73943
PRIVATE XP_List * net_auth_list = NULL;
PRIVATE XP_List * net_proxy_auth_list = NULL;
/*
PRIVATE Bool cookies_changed = FALSE;
#if defined(CookieManagement)
PRIVATE Bool cookie_permissions_changed = FALSE;
PRIVATE Bool cookie_remember_checked = FALSE;
#endif
PRIVATE NET_CookieBehaviorEnum net_CookieBehavior = NET_Accept;
PRIVATE Bool net_WarnAboutCookies = FALSE;
PRIVATE char *net_scriptName = (char *)0;
*/
/*
* Different schemes supported by the client.
* Order means the order of preference between authentication schemes.
*
*/
typedef enum _net_AuthType {
AUTH_INVALID = 0,
AUTH_BASIC = 1
#ifdef SIMPLE_MD5
HG72621
#endif /* SIMPLE_MD5 */
,AUTH_FORTEZZA = 3
} net_AuthType;
/*
* This struct describes both Basic authentication stuff,
* for both HTTP servers and proxies.
*
*/
HG10828
typedef struct _net_AuthStruct {
net_AuthType auth_type;
char * path; /* For normal authentication only */
char * proxy_addr; /* For proxy authentication only */
char * username; /* Obvious */
char * password; /* Not too cryptic either */
char * auth_string; /* Storage for latest Authorization str */
char * realm; /* For all auth schemes */
#ifdef SIMPLE_MD5
HG82727
#endif
char * challenge;
HG26250
char * signature;
char * clientRan;
PRBool oldChallenge;
int oldChallenge_retries;
} net_AuthStruct;
/*----------------- Normal client-server authentication ------------------ */
PRIVATE net_AuthStruct *
net_CheckForAuthorization(char * address, Bool exact_match)
{
char *atSign, *fSlash, *afterProto, *newAddress=NULL;
char tmp;
XP_List * list_ptr = net_auth_list;
net_AuthStruct * auth_s;
TRACEMSG(("net_CheckForAuthorization: checking for auth on: %s", address));
/* Auth struct->path doesn't contain username/password info (such as
* http://uname:pwd@host.com, so make sure we don't compare an address
* passed in with one with an auth struct->path until we remove/reduce the
* address passed in. */
if( (afterProto=PL_strstr(address, "://")) != 0 ) {
afterProto=afterProto+3;
tmp=*afterProto;
*afterProto='\0';
StrAllocCopy(newAddress, address);
*afterProto=tmp;
/* temporarily truncate after first slash, if any. */
if( (fSlash=PL_strchr(afterProto, '/')) != 0)
*fSlash='\0';
atSign=PL_strchr(afterProto, '@');
if(fSlash)
*fSlash='/';
if(atSign)
StrAllocCat(newAddress, atSign+1);
else
StrAllocCat(newAddress, afterProto);
}
while((auth_s = (net_AuthStruct *) XP_ListNextObject(list_ptr))!=0)
{
XP_ASSERT(newAddress);
if(!newAddress)
return NULL;
if(exact_match)
{
if(!PL_strcmp(address, auth_s->path)) {
XP_FREE(newAddress);
return(auth_s);
}
}
else
{
/* shorter strings always come last so there can be no
* ambiquity
*/
if(!PL_strncasecmp(address, auth_s->path, PL_strlen(auth_s->path))) {
XP_FREE(newAddress);
return(auth_s);
}
}
}
XP_FREE(newAddress);
HG25262
return(NULL);
}
/* returns TRUE if authorization is required
*/
PUBLIC Bool
NET_AuthorizationRequired(char * address)
{
net_AuthStruct * rv;
char * last_slash = PL_strrchr(address, '/');
if(last_slash)
*last_slash = '\0';
rv = net_CheckForAuthorization(address, FALSE);
HG17993
if(last_slash)
*last_slash = '/';
if(!rv)
return(FALSE);
else
return(TRUE);
}
/* returns a authorization string if one is required, otherwise
* returns NULL
*/
PUBLIC char *
NET_BuildAuthString(MWContext * context, URL_Struct *URL_s)
{
char * address = URL_s->address;
net_AuthStruct * auth_s = net_CheckForAuthorization(address, FALSE);
if(!auth_s)
#if defined(XP_WIN) && defined(MOZILLA_CLIENT)
return(WFE_BuildCompuserveAuthString(URL_s));
#else
return(NULL);
#endif
else
{
static char * auth_header = 0;
if(auth_header)
PR_Free(auth_header);
auth_header = PR_smprintf("Authorization: Basic %s"CRLF, auth_s->auth_string);
return(auth_header);
}
}
PRIVATE net_AuthStruct *
net_ScanForHostnameRealmMatch(char * address, char * realm)
{
char * proto_host = NET_ParseURL(address, GET_HOST_PART | GET_PROTOCOL_PART);
XP_List * list_ptr = net_auth_list;
net_AuthStruct * auth_s;
while((auth_s = (net_AuthStruct *) XP_ListNextObject(list_ptr))!=0)
{
/* shorter strings always come last so there can be no
* ambiquity
*/
if(!PL_strncasecmp(proto_host, auth_s->path, PL_strlen(proto_host))
&& !PL_strcasecmp(realm, auth_s->realm))
{
PR_Free(proto_host);
return(auth_s);
}
}
PR_Free(proto_host);
return(NULL);
}
PRIVATE void
net_free_auth_struct(net_AuthStruct *auth)
{
PR_Free(auth->path);
PR_Free(auth->proxy_addr);
PR_Free(auth->username);
PR_Free(auth->password);
PR_Free(auth->auth_string);
PR_Free(auth->realm);
/*FORTEZZA related stuff */
PR_FREEIF(auth->challenge);
HG26763
PR_FREEIF(auth->signature);
PR_FREEIF(auth->clientRan);
/*End FORTEZZA related stuff*/
PR_Free(auth);
}
/* blows away all authorization structs currently in the list, and the list itself.
* frees and nulls the list pointer itself (net_auth_list)
*/
PUBLIC void
NET_RemoveAllAuthorizations()
{
net_AuthStruct * victim;
if(XP_ListIsEmpty(net_auth_list)) /* XP_ListIsEmpty handles null list */
return;
while((victim = (net_AuthStruct *) XP_ListNextObject(net_auth_list)) != 0)
net_free_auth_struct(victim);
XP_ListDestroy(net_auth_list);
net_auth_list = NULL;
}
PRIVATE void
net_remove_exact_auth_match_on_cancel(net_AuthStruct *prev_auth, char *cur_path)
{
if(!prev_auth || !cur_path)
return;
if(!PL_strcmp(prev_auth->path, cur_path))
{
/* if the paths are exact and the user cancels
* remove the mapping
*/
XP_ListRemoveObject(net_auth_list, prev_auth);
net_free_auth_struct(prev_auth);
}
}
#define HTTP_PW_MODULE_NAME "http_pw"
#define HTTP_PW_NAME_TOKEN "name"
#define HTTP_PW_PASSWORD_TOKEN "pass"
PRIVATE char *
gen_http_key(char *address, char *realm)
{
char *rv=NULL;
StrAllocCopy(rv, address);
StrAllocCat(rv, "\t");
StrAllocCat(rv, realm);
return rv;
}
PRIVATE void
separate_http_key(char *key, char **address, char **realm)
{
char *tab;
HG72294
*address = NULL;
*realm = NULL;
if(!key)
return;
tab = PL_strchr(key, '\t');
if(!tab)
return;
*address = key;
*realm = tab+1;
}
PRIVATE void
net_store_http_password(char *address, char *realm, char *username, char *password)
{
char *key;
PCNameValueArray *array = PC_NewNameValueArray();
if(!array)
return;
PC_AddToNameValueArray(array, HTTP_PW_NAME_TOKEN, username);
PC_AddToNameValueArray(array, HTTP_PW_PASSWORD_TOKEN, password);
key = gen_http_key(address, realm);
if(!key)
return;
PC_StorePasswordNameValueArray(HTTP_PW_MODULE_NAME, key, array);
PR_Free(key);
}
PRIVATE void
net_remove_stored_http_password(char *url)
{
PC_DeleteStoredPassword(HTTP_PW_MODULE_NAME, url);
}
MODULE_PRIVATE void
net_http_password_data_interp(
char *module,
char *key,
char *data, int32 data_len,
char *type_buffer, int32 type_buffer_size,
char *url_buffer, int32 url_buffer_size,
char *username_buffer, int32 username_buffer_size,
char *password_buffer, int32 password_buffer_size)
{
PCNameValueArray * array;
char *username, *password;
char *address, *realm;
array = PC_CharToNameValueArray(data, data_len);
if(!array)
return;
username = PC_FindInNameValueArray(array, HTTP_PW_NAME_TOKEN);
password = PC_FindInNameValueArray(array, HTTP_PW_PASSWORD_TOKEN);
PL_strncpyz(type_buffer, "HTTP basic authorization", type_buffer_size);
separate_http_key(key, &address, &realm);
if(address)
{
PL_strncpyz(url_buffer, address, url_buffer_size);
}
if(username)
{
PL_strncpyz(username_buffer, username, username_buffer_size);
PR_Free(username);
}
if(password)
{
PL_strncpyz(password_buffer, password, password_buffer_size);
PR_Free(password);
}
}
PRIVATE void
net_initialize_http_access(void)
{
/* register PW cache interp function */
PC_RegisterDataInterpretFunc(HTTP_PW_MODULE_NAME,
net_http_password_data_interp);
HG21522
}
/* forward declaration */
PUBLIC XP_Bool
stub_PromptUsernameAndPassword(MWContext *context,
const char *msg,
char **username,
char **password,
void *closure);
/* returns false if the user wishes to cancel authorization
* and TRUE if the user wants to continue with a new authorization
* string
*/
/* HARDTS: I took a whack at fixing up some of the strings leaked in this
* function. All the PR_FREEIF()s are new.
*/
PUBLIC Bool
NET_AskForAuthString(MWContext *context,
URL_Struct * URL_s,
char * authenticate,
char * prot_template,
Bool already_sent_auth,
void *closure)
{
static PRBool first_time=TRUE;
net_AuthStruct *prev_auth;
char *address=URL_s->address;
char *host=NET_ParseURL(address, GET_HOST_PART);
char *new_address=NULL;
char *username=NULL,*colon=NULL,*password=NULL,*unamePwd=NULL;
char *u_pass_string=NULL;
char *auth_string=NULL;
char *realm;
char *slash;
char *authenticate_header_value;
char *buf=NULL;
int32 len=0;
int status;
PRBool re_authorize=FALSE;
TRACEMSG(("Entering NET_AskForAuthString"));
if(first_time)
{
net_initialize_http_access();
first_time = FALSE;
}
if(authenticate)
{
/* check for the compuserve Remote-Passphrase type of
* authentication
*/
authenticate_header_value = XP_StripLine(authenticate);
HG03937
#define COMPUSERVE_HEADER_NAME "Remote-Passphrase"
if(!PL_strncasecmp(authenticate_header_value,
COMPUSERVE_HEADER_NAME,
sizeof(COMPUSERVE_HEADER_NAME) - 1))
{
/* This is a compuserv style header
*/
PR_FREEIF(host);
#if defined(XP_WIN) && defined(MOZILLA_CLIENT)
return(WFE_DoCompuserveAuthenticate(context, URL_s, authenticate_header_value));
#else
return(NET_AUTH_FAILED_DISPLAY_DOCUMENT);
#endif
}
#define HTTP_BASIC_AUTH_TOKEN "BASIC"
else if(PL_strncasecmp(authenticate_header_value,
HTTP_BASIC_AUTH_TOKEN,
sizeof(HTTP_BASIC_AUTH_TOKEN) - 1))
{
HG21632
/* unsupported auth type */
return(NET_AUTH_FAILED_DISPLAY_DOCUMENT);
}
}
new_address = NET_ParseURL(address, GET_PROTOCOL_PART | GET_HOST_PART | GET_PATH_PART);
if(!new_address) {
PR_FREEIF(host);
return NET_AUTH_FAILED_DISPLAY_DOCUMENT;
}
/* get the username and password from the URL struct */
if( URL_s->password && *URL_s->password ) {
password = PL_strdup(URL_s->password);
}
if( URL_s->username && *URL_s->username ) {
username = PL_strdup(URL_s->username);
} else {
/* See if username and password are still in the address */
unamePwd=NET_ParseURL(address, GET_USERNAME_PART | GET_PASSWORD_PART);
/* get the username & password out of the combo string */
if( (colon = PL_strchr(unamePwd, ':')) != NULL ) {
*colon='\0';
username=PL_strdup(unamePwd);
/* Use password we found above? */
if( password == NULL ) {
password=PL_strdup(colon+1);
}
*colon=':';
PR_Free(unamePwd);
} else {
username=unamePwd;
}
}
/*if last char is not a slash then */
if (new_address[PL_strlen(new_address)-1] != '/')
{
/* remove everything after the last slash */
slash = PL_strrchr(new_address, '/');
if(++slash)
*slash = '\0';
}
if(!authenticate)
{
realm = "unknown";
}
else
{
realm = PL_strchr(authenticate, '"');
if(realm)
{
realm++;
/* terminate at next quote */
strtok(realm, "\"");
#define MAX_REALM_SIZE 128
if(PL_strlen(realm) > MAX_REALM_SIZE)
realm[MAX_REALM_SIZE] = '\0';
}
else
{
realm = "unknown";
}
}
/* no hostname/realm match search for exact match */
prev_auth = net_CheckForAuthorization(new_address, FALSE);
if(prev_auth && !already_sent_auth)
{
/* somehow the mapping changed since the time we sent
* the authorization.
* This happens sometimes because of the parrallel
* nature of the requests.
* In this case we want to just retry the connection
* since it will probably succede now.
*/
HG22220
PR_FREEIF(host);
PR_FREEIF(new_address);
PR_FREEIF(username);
PR_FREEIF(password);
return(NET_RETRY_WITH_AUTH);
}
else if(prev_auth)
{
/* we sent the authorization string and it was wrong
*/
if(!FE_Confirm(context, XP_GetString(XP_CONFIRM_AUTHORIZATION_FAIL)))
{
TRACEMSG(("User canceled login!!!"));
if(!PL_strcmp(prev_auth->path, new_address))
{
/* if the paths are exact and the user cancels
* remove the mapping
*/
net_remove_exact_auth_match_on_cancel(prev_auth, new_address);
PR_FREEIF(host);
PR_FREEIF(new_address);
PR_FREEIF(username);
PR_FREEIF(password);
return(NET_AUTH_FAILED_DISPLAY_DOCUMENT);
}
}
if (!username)
username = PL_strdup(prev_auth->username);
if (!password)
password = PL_strdup(prev_auth->password);
re_authorize = TRUE;
}
else
{
char *ptr1, *ptr2;
/* scan all the authorization strings to see if we
* can find a hostname and realm match. If we find
* a match then reduce the authorization path to include
* the current path as well.
*/
prev_auth = net_ScanForHostnameRealmMatch(address, realm);
if(prev_auth)
{
char *tmp;
int skipProtoHost;
net_remove_stored_http_password(prev_auth->path);
tmp = NET_ParseURL(prev_auth->path, GET_HOST_PART | GET_PROTOCOL_PART);
skipProtoHost = PL_strlen(tmp);
PR_ASSERT(!PL_strncasecmp(
tmp,
NET_ParseURL(new_address, GET_HOST_PART | GET_PROTOCOL_PART),
skipProtoHost));
PR_Free(tmp);
/* compare the two url paths until they deviate
* once they deviate truncate.
* skip ptr1, ptr2 past the host names
* which we have already compared
*/
for(ptr1 = prev_auth->path + skipProtoHost, ptr2 = new_address + skipProtoHost; *ptr1 && *ptr2; ptr1++, ptr2++)
{
if(*ptr1 != *ptr2)
{
break; /* end for */
}
}
/* truncate at *ptr1 now since the new address may
* be just a subpath of the original address and
* the compare above will not handle the subpath correctly
*/
*ptr1 = '\0'; /* truncate */
if(*(ptr1-1) == '/')
*(ptr1-1) = '\0'; /* strip a trailing slash */
/* make sure a path always has at least a slash
* at the end.
* If the slash isn't there then
* the password will be sent to ports on the
* same host since we use a first part match
*/
tmp = NET_ParseURL(prev_auth->path, GET_PATH_PART);
if(!*tmp)
StrAllocCat(prev_auth->path, "/");
PR_Free(tmp);
TRACEMSG(("Truncated new auth path to be: %s", prev_auth->path));
net_store_http_password(prev_auth->path, prev_auth->realm, prev_auth->username, prev_auth->password);
PR_Free(host);
PR_Free(new_address);
return(NET_RETRY_WITH_AUTH);
}
}
/* Use username and/or password specified in URL_struct if exists. */
if (!username && URL_s->username && *URL_s->username) {
username = PL_strdup(URL_s->username);
}
if (!password && URL_s->password && *URL_s->password) {
password = PL_strdup(URL_s->password);
}
if(!username && !password)
{
/* look for a previously stored password in the pw cache */
PCNameValueArray *array;
array = PC_CheckForStoredPasswordArray(HTTP_PW_MODULE_NAME, URL_s->address);
if(array)
{
username = PC_FindInNameValueArray(array, HTTP_PW_NAME_TOKEN);
password = PC_FindInNameValueArray(array, HTTP_PW_PASSWORD_TOKEN);
if(!username)
{
PR_FREEIF(password);
password = NULL;
}
}
}
/* if the password is filled in then the username must
* be filled in already.
*/
/* 4/6/99 -- with the new async dialogs, we will only enter this
statement the first time through; afterward, we will have the
user and pass via NET_ResumeWithAuth()
*/
if(!password || re_authorize)
{
XP_Bool remember_password = FALSE;
char *loginString=XP_GetString(XP_ACCESS_ENTER_USERNAME);
host = NET_ParseURL(address, GET_HOST_PART);
/* malloc memory here to prevent buffer overflow */
len = XP_STRLEN(loginString) + XP_STRLEN(realm) + XP_STRLEN(host) + 10;
buf = (char *)PR_Malloc(len*sizeof(char));
if(buf) {
PR_snprintf( buf, len*sizeof(char), loginString, realm, host);
NET_Progress(context, XP_GetString( XP_CONNECT_PLEASE_ENTER_PASSWORD_FOR_HOST) );
#if 0
#if defined(SingleSignon)
/* prefill prompt with previous username/passwords if any
* this returns 1 if user pressed OK, or 0 if they Canceled
*/
status = SI_PromptUsernameAndPassword
(context, buf, &username, &password, URL_s->address);
/* Tell the Editor the correct username */
if( status > 0 ) {
EDT_SavePublishUsername(context, address, username);
}
#else
status = PC_PromptUsernameAndPassword
(context, buf, &username, &password,
&remember_password, NET_IsURLSecure(URL_s->address));
#endif
#else
{
NET_AuthClosure * authclosure = (NET_AuthClosure *) closure;
/* the new multi-threaded case -- we return asynchronously */
authclosure->msg = PL_strdup (buf);
status = stub_PromptUsernameAndPassword
(context, buf, &username, &password, closure);
}
#endif
PR_Free(buf);
} else {
status = 0;
}
PR_Free(host);
if(!status) {
/* XXX now we have FALSE == WAIT_FOR_AUTH */
return(NET_WAIT_FOR_AUTH);
#ifdef notused /* with async dialogs, we never have a user/pass here */
TRACEMSG(("User canceled login!!!"));
/* if the paths are exact and the user cancels
* remove the mapping
*/
net_remove_exact_auth_match_on_cancel(prev_auth, new_address);
PR_FREEIF(username);
PR_FREEIF(password);
PR_FREEIF(new_address);
return(NET_AUTH_FAILED_DISPLAY_DOCUMENT);
#endif /* notused */
}
else if(!username || !password)
{
PR_FREEIF(username);
PR_FREEIF(password);
PR_FREEIF(new_address);
return(NET_AUTH_FAILED_DISPLAY_DOCUMENT);
}
else if(remember_password)
{
net_store_http_password(URL_s->address, realm, username, password);
}
}
StrAllocCopy(u_pass_string, username);
StrAllocCat(u_pass_string, ":");
StrAllocCat(u_pass_string, password);
len = PL_strlen(u_pass_string);
auth_string = (char*) PR_Malloc((((len+1)*4)/3)+10);
if(!auth_string)
{
PR_FREEIF(username);
PR_FREEIF(password);
PR_FREEIF(u_pass_string);
PR_Free(new_address);
return(NET_RETRY_WITH_AUTH);
}
HG38932
NET_UUEncode((unsigned char *)u_pass_string, (unsigned char*) auth_string, len);
PR_Free(u_pass_string);
if(prev_auth)
{
PR_FREEIF(prev_auth->auth_string);
prev_auth->auth_string = auth_string;
PR_FREEIF(prev_auth->username);
prev_auth->username = username;
PR_FREEIF(prev_auth->password);
prev_auth->password = password;
}
else
{
char *atSign, *host, *fSlash;
XP_List * list_ptr = net_auth_list;
net_AuthStruct * tmp_auth_ptr;
size_t new_len;
/* construct a new auth_struct
*/
prev_auth = PR_NEWZAP(net_AuthStruct);
if(!prev_auth)
{
PR_FREEIF(auth_string);
PR_FREEIF(username);
PR_FREEIF(password);
PR_Free(new_address);
return(NET_RETRY_WITH_AUTH);
}
prev_auth->auth_string = auth_string;
prev_auth->username = username;
prev_auth->password = password;
prev_auth->path = 0;
/* Don't save username/password info in the auth struct path. */
if( (atSign=PL_strchr(new_address, '@')) != 0) {
if( (host=PL_strstr(new_address, "://")) != 0) {
char tmp;
host+=3;
tmp=*host;
*host='\0';
StrAllocCopy(prev_auth->path, new_address);
*host=tmp;
fSlash=PL_strchr(host, '/');
if(fSlash)
*fSlash='\0';
/* Do the atSign check again so we're sure to get one between the
* protocol part and the first slash. */
atSign=PL_strchr(host, '@');
if(fSlash)
*fSlash='/';
if(atSign) {
StrAllocCat(prev_auth->path, atSign+1);
} else {
StrAllocCat(prev_auth->path, host);
}
}
} else {
StrAllocCopy(prev_auth->path, new_address);
}
prev_auth->realm = 0;
StrAllocCopy(prev_auth->realm, realm);
if(!net_auth_list)
{
net_auth_list = XP_ListNew();
if(!net_auth_list)
{
/* Maybe should free prev_auth here. */
PR_Free(new_address);
return(NET_RETRY_WITH_AUTH);
}
}
/* add it to the list so that it is before any strings of
* smaller length
*/
new_len = PL_strlen(prev_auth->path);
while((tmp_auth_ptr = (net_AuthStruct *) XP_ListNextObject(list_ptr))!=0)
{
if(new_len > PL_strlen(tmp_auth_ptr->path))
{
XP_ListInsertObject(net_auth_list, tmp_auth_ptr, prev_auth);
PR_Free(new_address);
return(NET_RETRY_WITH_AUTH);
}
}
/* no shorter strings found in list */
XP_ListAddObjectToEnd(net_auth_list, prev_auth);
}
PR_Free(new_address);
return(NET_RETRY_WITH_AUTH);
}
/*--------------------------------------------------
* The following routines support the
* Set-Cookie: / Cookie: headers
*/
/*
PRIVATE XP_List * net_cookie_list=0;
#if defined(CookieManagement)
PRIVATE XP_List * net_cookie_permission_list=0;
PRIVATE XP_List * net_defer_cookie_list=0;
#endif
typedef struct _net_CookieStruct {
char * path;
char * host;
char * name;
char * cookie;
time_t expires;
time_t last_accessed;
HG26237
Bool is_domain; // is it a domain instead of an absolute host?
} net_CookieStruct;
*/
/*
#if defined(CookieManagement)
typedef struct _net_CookiePermissionStruct {
char * host;
Bool permission;
#ifdef TRUST_LABELS
XP_List * TrustList; // a list of trust label entries
#endif
} net_CookiePermissionStruct;
*/
/*
typedef struct _net_DeferCookieStruct {
MWContext * context;
char * cur_url;
char * set_cookie_header;
time_t timeToExpire;
} net_DeferCookieStruct;
*/
/*
#ifdef TRUST_LABELS
void ParseTrustLabelInfo
(char *Buf, net_CookiePermissionStruct * cookie_permission);
void SaveTrustLabelData
( net_CookiePermissionStruct * cookie_permission, XP_File fp );
void DeleteCookieFromPermissions( char *CookieHost, char *CookieName );
void AddTrustLabelInfo( char *CookieName, TrustLabel *trustlabel );
typedef struct {
char * CookieName;
int purpose; // the purpose rating has a series of bits set
int recipient; // the recipient value
Bool bIdentifiable; // true if the related cookie puts to identifiable information
char * by; // the by field from the trust label
char * CookieSet; // when the cookie was set into cookies.txt
} TrustEntry;
#endif
#endif
*/
/* Routines and data to protect the cookie list so it
** can be accessed by mulitple threads
*/
/*
#include "prthread.h"
#include "prmon.h"
static PRMonitor * cookie_lock_monitor = NULL;
static PRThread * cookie_lock_owner = NULL;
static int cookie_lock_count = 0;
PRIVATE void
net_lock_cookie_list(void)
{
if(!cookie_lock_monitor)
cookie_lock_monitor = PR_NewNamedMonitor("cookie-lock");
PR_EnterMonitor(cookie_lock_monitor);
while(TRUE) {
// no current owner or owned by this thread
PRThread * t = PR_CurrentThread();
if(cookie_lock_owner == NULL || cookie_lock_owner == t) {
cookie_lock_owner = t;
cookie_lock_count++;
PR_ExitMonitor(cookie_lock_monitor);
return;
}
// owned by someone else -- wait till we can get it
PR_Wait(cookie_lock_monitor, PR_INTERVAL_NO_TIMEOUT);
}
}
*/
/*
PRIVATE void
net_unlock_cookie_list(void)
{
PR_EnterMonitor(cookie_lock_monitor);
#ifdef DEBUG
// make sure someone doesn't try to free a lock they don't own
PR_ASSERT(cookie_lock_owner == PR_CurrentThread());
#endif
cookie_lock_count--;
if(cookie_lock_count == 0) {
cookie_lock_owner = NULL;
PR_Notify(cookie_lock_monitor);
}
PR_ExitMonitor(cookie_lock_monitor);
}
*/
/*
#if defined(CookieManagement)
static PRMonitor * defer_cookie_lock_monitor = NULL;
static PRThread * defer_cookie_lock_owner = NULL;
static int defer_cookie_lock_count = 0;
PRIVATE void
net_lock_defer_cookie_list(void)
{
if(!defer_cookie_lock_monitor)
defer_cookie_lock_monitor =
PR_NewNamedMonitor("defer_cookie-lock");
PR_EnterMonitor(defer_cookie_lock_monitor);
while(TRUE) {
// no current owner or owned by this thread
PRThread * t = PR_CurrentThread();
if(defer_cookie_lock_owner == NULL || defer_cookie_lock_owner == t) {
defer_cookie_lock_owner = t;
defer_cookie_lock_count++;
PR_ExitMonitor(defer_cookie_lock_monitor);
return;
}
// owned by someone else -- wait till we can get it
PR_Wait(defer_cookie_lock_monitor, PR_INTERVAL_NO_TIMEOUT);
}
}
*/
/*
PRIVATE void
net_unlock_defer_cookie_list(void)
{
PR_EnterMonitor(defer_cookie_lock_monitor);
#ifdef DEBUG
// make sure someone doesn't try to free a lock they don't own
PR_ASSERT(defer_cookie_lock_owner == PR_CurrentThread());
#endif
defer_cookie_lock_count--;
if(defer_cookie_lock_count == 0) {
defer_cookie_lock_owner = NULL;
PR_Notify(defer_cookie_lock_monitor);
}
PR_ExitMonitor(defer_cookie_lock_monitor);
}
*/
/*
static PRMonitor * cookie_permission_lock_monitor = NULL;
static PRThread * cookie_permission_lock_owner = NULL;
static int cookie_permission_lock_count = 0;
PRIVATE void
net_lock_cookie_permission_list(void)
{
if(!cookie_permission_lock_monitor)
cookie_permission_lock_monitor =
PR_NewNamedMonitor("cookie_permission-lock");
PR_EnterMonitor(cookie_permission_lock_monitor);
while(TRUE) {
// no current owner or owned by this thread
PRThread * t = PR_CurrentThread();
if(cookie_permission_lock_owner == NULL || cookie_permission_lock_owner == t) {
cookie_permission_lock_owner = t;
cookie_permission_lock_count++;
PR_ExitMonitor(cookie_permission_lock_monitor);
return;
}
// owned by someone else -- wait till we can get it
PR_Wait(cookie_permission_lock_monitor, PR_INTERVAL_NO_TIMEOUT);
}
}
*/
/*
PRIVATE void
net_unlock_cookie_permission_list(void)
{
PR_EnterMonitor(cookie_permission_lock_monitor);
#ifdef DEBUG
// make sure someone doesn't try to free a lock they don't own
PR_ASSERT(cookie_permission_lock_owner == PR_CurrentThread());
#endif
cookie_permission_lock_count--;
if(cookie_permission_lock_count == 0) {
cookie_permission_lock_owner = NULL;
PR_Notify(cookie_permission_lock_monitor);
}
PR_ExitMonitor(cookie_permission_lock_monitor);
}
*/
/*
PRIVATE int
net_SaveCookiePermissions(char * filename);
PRIVATE void
net_FreeCookiePermission
(net_CookiePermissionStruct * cookie_permission, Bool save)
{
// This routine should only be called while holding the
// cookie permission list lock
if(!cookie_permission) {
return;
}
XP_ListRemoveObject(net_cookie_permission_list, cookie_permission);
PR_FREEIF(cookie_permission->host);
#ifdef TRUST_LABELS
// free the entries on the trust list
if ( cookie_permission->TrustList ) {
TrustEntry * TEntry;
XP_List *Tptr = cookie_permission->TrustList;
while( (TEntry = (TrustEntry *)XP_ListNextObject( Tptr )) ) {
PR_FREEIF(TEntry->CookieName);
PR_FREEIF(TEntry->by);
PR_FREEIF(TEntry->CookieSet);
// before removing the current entry get the ptr to the next one
Tptr = Tptr->prev;
XP_ListRemoveObject(cookie_permission->TrustList, TEntry);
}
XP_ListDestroy(cookie_permission->TrustList);
}
#endif
PR_Free(cookie_permission);
if (save) {
cookie_permissions_changed = TRUE;
net_SaveCookiePermissions(NULL);
}
}
*/
/* blows away all cookie permissions currently in the list */
/*
PRIVATE void
net_RemoveAllCookiePermissions()
{
net_CookiePermissionStruct * victim;
XP_List * cookiePermissionList;
// check for NULL or empty list
net_lock_cookie_permission_list();
cookiePermissionList = net_cookie_permission_list;
if(XP_ListIsEmpty(cookiePermissionList)) {
net_unlock_cookie_permission_list();
return;
}
while((victim =
(net_CookiePermissionStruct *)
XP_ListNextObject(cookiePermissionList)) != 0) {
net_FreeCookiePermission(victim, FALSE);
cookiePermissionList = net_cookie_permission_list;
}
XP_ListDestroy(net_cookie_permission_list);
net_cookie_permission_list = NULL;
net_unlock_cookie_permission_list();
}
#endif
*/
/* This should only get called while holding the cookie-lock
**
*/
/*
PRIVATE void
net_FreeCookie(net_CookieStruct * cookie)
{
if(!cookie)
return;
#ifdef TRUST_LABELS
// delete the reference to the cookie in the cookie permission list
//which contains the trust label for the cookie
DeleteCookieFromPermissions(cookie->host, cookie->name );
#endif
XP_ListRemoveObject(net_cookie_list, cookie);
PR_FREEIF(cookie->path);
PR_FREEIF(cookie->host);
PR_FREEIF(cookie->name);
PR_FREEIF(cookie->cookie);
PR_Free(cookie);
cookies_changed = TRUE;
}
*/
/*
PUBLIC void
NET_DeleteCookie(char* cookieURL)
{
net_CookieStruct * cookie;
XP_List * list_ptr;
char * cookieURL2 = 0;
net_lock_cookie_list();
list_ptr = net_cookie_list;
while((cookie = (net_CookieStruct *) XP_ListNextObject(list_ptr))!=0) {
StrAllocCopy(cookieURL2, "cookie:");
StrAllocCat(cookieURL2, cookie->host);
StrAllocCat(cookieURL2, "!");
StrAllocCat(cookieURL2, cookie->path);
StrAllocCat(cookieURL2, "!");
StrAllocCat(cookieURL2, cookie->name);
if (PL_strcmp(cookieURL, cookieURL2)==0) {
net_FreeCookie(cookie);
break;
}
}
PR_FREEIF(cookieURL2);
net_unlock_cookie_list();
}
*/
/* blows away all cookies currently in the list, then blows away the list itself
* nulling it after it's free'd
*/
/*
PRIVATE void
net_RemoveAllCookies()
{
net_CookieStruct * victim;
XP_List * cookieList;
// check for NULL or empty list
net_lock_cookie_list();
cookieList = net_cookie_list;
if(XP_ListIsEmpty(cookieList)) {
net_unlock_cookie_list();
return;
}
while((victim = (net_CookieStruct *) XP_ListNextObject(cookieList)) != 0) {
net_FreeCookie(victim);
cookieList=net_cookie_list;
}
XP_ListDestroy(net_cookie_list);
net_cookie_list = NULL;
net_unlock_cookie_list();
}
*/
/*
PUBLIC void
NET_RemoveAllCookies()
{
#if defined(CookieManagement)
net_RemoveAllCookiePermissions();
#endif
net_RemoveAllCookies();
}
PRIVATE void
net_remove_oldest_cookie(void)
{
XP_List * list_ptr;
net_CookieStruct * cookie_s;
net_CookieStruct * oldest_cookie;
net_lock_cookie_list();
list_ptr = net_cookie_list;
if(XP_ListIsEmpty(list_ptr)) {
net_unlock_cookie_list();
return;
}
oldest_cookie = (net_CookieStruct*) list_ptr->next->object;
while((cookie_s = (net_CookieStruct *) XP_ListNextObject(list_ptr))!=0)
{
if(cookie_s->last_accessed < oldest_cookie->last_accessed)
oldest_cookie = cookie_s;
}
if(oldest_cookie)
{
TRACEMSG(("Freeing cookie because global max cookies has been exceeded"));
net_FreeCookie(oldest_cookie);
}
net_unlock_cookie_list();
}
*/
/* Remove any expired cookies from memory
** This routine should only be called while holding the cookie list lock
*/
/*
PRIVATE void
net_remove_expired_cookies(void)
{
XP_List * list_ptr = net_cookie_list;
net_CookieStruct * cookie_s;
time_t cur_time = time(NULL);
if(XP_ListIsEmpty(list_ptr))
return;
while((cookie_s = (net_CookieStruct *) XP_ListNextObject(list_ptr))!=0)
{
// Don't get rid of expire time 0 because these need to last for
// the entire session. They'll get cleared on exit.
//
if( cookie_s->expires && (cookie_s->expires < cur_time) ) {
net_FreeCookie(cookie_s);
// Reset the list_ptr to the beginning of the list.
// Do this because list_ptr's object was just freed
// by the call to net_FreeCookie struct, even
// though it's inefficient.
list_ptr = net_cookie_list;
}
}
}
*/
/*
PRIVATE XP_List * net_dormant_cookie_list=0;
Bool net_anonymous = FALSE;
PUBLIC void
NET_AnonymizeCookies()
{
if (!net_anonymous) {
net_lock_cookie_list();
net_dormant_cookie_list = net_cookie_list;
net_cookie_list = XP_ListNew();
net_unlock_cookie_list();
net_anonymous = TRUE;
}
}
PUBLIC void
NET_UnanonymizeCookies()
{
if (net_anonymous) {
net_RemoveAllCookies();
net_lock_cookie_list();
net_cookie_list = net_dormant_cookie_list;
net_unlock_cookie_list();
net_dormant_cookie_list = 0;
net_anonymous = FALSE;
}
}
*/
/*
* Determine whether or not to suppress the referer field for anonymity.
* The first time this function is called on behalf of a given window
* after a mode change (into or out of anonymous mode), the returned value is
* true.
*/
PUBLIC Bool
NET_SupressRefererForAnonymity(MWContext *window_id) {
return FALSE;
}
/* checks to see if the maximum number of cookies per host
* is being exceeded and deletes the oldest one in that
* case
* This routine should only be called while holding the cookie lock
*/
/*
PRIVATE void
net_CheckForMaxCookiesFromHost(const char * cur_host)
{
XP_List * list_ptr = net_cookie_list;
net_CookieStruct * cookie_s;
net_CookieStruct * oldest_cookie = 0;
int cookie_count = 0;
if(XP_ListIsEmpty(list_ptr))
return;
while((cookie_s = (net_CookieStruct *) XP_ListNextObject(list_ptr))!=0)
{
if(!PL_strcasecmp(cookie_s->host, cur_host))
{
cookie_count++;
if(!oldest_cookie
|| oldest_cookie->last_accessed > cookie_s->last_accessed)
oldest_cookie = cookie_s;
}
}
if(cookie_count >= MAX_COOKIES_PER_SERVER && oldest_cookie)
{
TRACEMSG(("Freeing cookie because max cookies per server has been exceeded"));
net_FreeCookie(oldest_cookie);
}
}
*/
/* search for previous exact match
** This routine should only be called while holding the cookie lock
*/
/*
PRIVATE net_CookieStruct *
net_CheckForPrevCookie(char * path,
char * hostname,
char * name)
{
XP_List * list_ptr = net_cookie_list;
net_CookieStruct * cookie_s;
while((cookie_s = (net_CookieStruct *) XP_ListNextObject(list_ptr))!=0) {
if(path && hostname && cookie_s->path && cookie_s->host && cookie_s->name
&& !PL_strcmp(name, cookie_s->name)
&& !PL_strcmp(path, cookie_s->path)
&& !PL_strcasecmp(hostname, cookie_s->host))
return(cookie_s);
}
return(NULL);
}
*/
/* cookie utility functions */
/*
PRIVATE void
NET_SetCookieBehaviorPref(NET_CookieBehaviorEnum x)
{
net_CookieBehavior = x;
HG83330
if(net_CookieBehavior == NET_DontUse) {
NET_XP_FileRemove("", xpHTTPCookie);
#if defined(CookieManagement)
NET_XP_FileRemove("", xpHTTPCookiePermission);
#endif
}
}
*/
/*
PRIVATE void
NET_SetCookieWarningPref(Bool x)
{
net_WarnAboutCookies = x;
}
PRIVATE void
NET_SetCookieScriptPref(const char *name)
{
PR_FREEIF(net_scriptName);
if( name && *name )
net_scriptName=PL_strdup(name);
else
net_scriptName=NULL;
}
PRIVATE NET_CookieBehaviorEnum
NET_GetCookieBehaviorPref(void)
{
return net_CookieBehavior;
}
PRIVATE Bool
NET_GetCookieWarningPref(void)
{
return net_WarnAboutCookies;
}
PRIVATE const char *
NET_GetCookieScriptPref(void)
{
return (const char *)net_scriptName;
}
MODULE_PRIVATE int PR_CALLBACK
NET_CookieBehaviorPrefChanged(const char * newpref, void * data)
{
PRInt32 n;
if ( (PREF_OK != PREF_GetIntPref(pref_cookieBehavior, &n)) ) {
n = DEF_COOKIE_BEHAVIOR;
}
NET_SetCookieBehaviorPref((NET_CookieBehaviorEnum)n);
return PREF_NOERROR;
}
MODULE_PRIVATE int PR_CALLBACK
NET_CookieWarningPrefChanged(const char * newpref, void * data)
{
PRBool x;
if ( (PREF_OK != PREF_GetBoolPref(pref_warnAboutCookies, &x)) ) {
x = FALSE;
}
NET_SetCookieWarningPref(x);
return PREF_NOERROR;
}
MODULE_PRIVATE int PR_CALLBACK
NET_CookieScriptPrefChanged(const char * newpref, void * data)
{
char s[64];
int len = sizeof(s);
*s='\0';
PREF_GetCharPref(pref_scriptName, s, &len);
NET_SetCookieScriptPref(s);
return PREF_NOERROR;
}
*/
/*
#if defined(CookieManagement)
// search if permission already exists
PRIVATE net_CookiePermissionStruct *
net_CheckForCookiePermission(char * hostname) {
XP_List * list_ptr;
net_CookiePermissionStruct * cookie_s;
// ignore leading period in host name
while (hostname && (*hostname == '.')) {
hostname++;
}
net_lock_cookie_permission_list();
list_ptr = net_cookie_permission_list;
while((cookie_s = (net_CookiePermissionStruct *) XP_ListNextObject(list_ptr))!=0) {
if(hostname && cookie_s->host
&& !PL_strcasecmp(hostname, cookie_s->host)) {
net_unlock_cookie_permission_list();
return(cookie_s);
}
}
net_unlock_cookie_permission_list();
return(NULL);
}
*/
/*
* return:
* +1 if cookie permission exists for host and indicates host can set cookies
* 0 if cookie permission does not exist for host
* -1 if cookie permission exists for host and indicates host can't set cookies
*/
/*
PUBLIC int
NET_CookiePermission(char* URLName) {
net_CookiePermissionStruct * cookiePermission;
char * host;
char * colon;
if (!URLName || !(*URLName)) {
return 0;
}
// remove protocol from URL name
host = NET_ParseURL(URLName, GET_HOST_PART);
// remove port number from URL name
colon = PL_strchr(host, ':');
if(colon) {
*colon = '\0';
}
cookiePermission = net_CheckForCookiePermission(host);
if(colon) {
*colon = ':';
}
PR_Free(host);
if (cookiePermission == NULL) {
return 0;
}
if (cookiePermission->permission) {
return 1;
}
return -1;
}
#endif
*/
/* called from mkgeturl.c, NET_InitNetLib(). This sets the module local cookie pref variables
and registers the callbacks */
/*
PUBLIC void
NET_RegisterCookiePrefCallbacks(void)
{
PRInt32 n;
PRBool x;
char s[64];
int len = sizeof(s);
*s = '\0';
if ( (PREF_OK != PREF_GetIntPref(pref_cookieBehavior, &n)) ) {
n = DEF_COOKIE_BEHAVIOR;
}
NET_SetCookieBehaviorPref((NET_CookieBehaviorEnum)n);
PREF_RegisterCallback(pref_cookieBehavior, NET_CookieBehaviorPrefChanged, NULL);
if ( (PREF_OK != PREF_GetBoolPref(pref_warnAboutCookies, &x)) ) {
x = FALSE;
}
NET_SetCookieWarningPref(x);
PREF_RegisterCallback(pref_warnAboutCookies, NET_CookieWarningPrefChanged, NULL);
*s='\0';
PREF_GetCharPref(pref_scriptName, s, &len);
NET_SetCookieScriptPref(s);
PREF_RegisterCallback(pref_scriptName, NET_CookieScriptPrefChanged, NULL);
}
*/
/* returns TRUE if authorization is required
**
**
** IMPORTANT: Now that this routine is mutli-threaded it is up
** to the caller to free any returned string
*/
/*
PUBLIC char *
NET_GetCookie(MWContext * context, char * address)
{
char *name=0;
char *host = NET_ParseURL(address, GET_HOST_PART);
char *path = NET_ParseURL(address, GET_PATH_PART);
XP_List * list_ptr;
net_CookieStruct * cookie_s;
Bool first=TRUE;
HG26748
time_t cur_time = time(NULL);
int host_length;
int domain_length;
// return string to build
char * rv=0;
// disable cookie's if the user's prefs say so
if(NET_GetCookieBehaviorPref() == NET_DontUse)
return NULL;
HG98476
// search for all cookies
net_lock_cookie_list();
list_ptr = net_cookie_list;
while((cookie_s = (net_CookieStruct *) XP_ListNextObject(list_ptr))!=0)
{
if(!cookie_s->host)
continue;
// check the host or domain first
if(cookie_s->is_domain)
{
char *cp;
domain_length = PL_strlen(cookie_s->host);
// calculate the host length by looking at all characters up to
// a colon or '\0'. That way we won't include port numbers
//in domains
for(cp=host; *cp != '\0' && *cp != ':'; cp++)
; // null body
host_length = cp - host;
if(domain_length > host_length
|| PL_strncasecmp(cookie_s->host,
&host[host_length - domain_length],
domain_length))
{
HG20476
//no match. FAIL
continue;
}
}
else if(PL_strcasecmp(host, cookie_s->host))
{
//hostname matchup failed. FAIL
continue;
}
// shorter strings always come last so there can be no
// ambiquity
if(cookie_s->path && !PL_strncmp(path,
cookie_s->path,
PL_strlen(cookie_s->path)))
{
// if the cookie is secure and the path isn't
// dont send it
HG83764
// check for expired cookies
//
if( cookie_s->expires && (cookie_s->expires < cur_time) )
{
//expire and remove the cookie
net_FreeCookie(cookie_s);
// start the list parsing over :(
//we must also start the string over
PR_FREEIF(rv);
rv = NULL;
list_ptr = net_cookie_list;
first = TRUE; // reset first
continue;
}
if(first)
first = FALSE;
else
StrAllocCat(rv, "; ");
if(cookie_s->name && *cookie_s->name != '\0')
{
cookie_s->last_accessed = cur_time;
StrAllocCopy(name, cookie_s->name);
StrAllocCat(name, "=");
#ifdef PREVENT_DUPLICATE_NAMES
// make sure we don't have a previous
// name mapping already in the string
//
if(!rv || !PL_strstr(rv, name))
{
StrAllocCat(rv, name);
StrAllocCat(rv, cookie_s->cookie);
}
#else
StrAllocCat(rv, name);
StrAllocCat(rv, cookie_s->cookie);
#endif // PREVENT_DUPLICATE_NAMES
}
else
{
StrAllocCat(rv, cookie_s->cookie);
}
}
}
#if defined(MOZ_BRPROF)
// Okay, this is a horrible hack. It looks for a URL with
// 'iiop/BRPROF' in it (our little browsing profile reader), and
//if it finds it, it uploads the browsing profile cookie.
//
// The _real_ way to do this would be to
//
// 1) See if the user has enabled the preference to even allow us
// to send out the cookie to _anyone_.
//
// 2) See if the specific site has asked for and received
// permission to be sent the cookie.
//
if (PL_strstr(address, "iiop/BRPROF")) {
extern PRBool BP_GetProfile(char* *aProfileCookie);
char* profile;
if (BP_GetProfile(&profile)) {
if (! first)
StrAllocCat(rv, "; ");
StrAllocCat(rv, "BP=");
StrAllocCat(rv, profile);
PL_strfree(profile);
}
}
#endif
net_unlock_cookie_list();
PR_FREEIF(name);
PR_Free(path);
PR_Free(host);
// may be NULL
return(rv);
}
*/
/*
#if defined(CookieManagement)
void
net_AddCookiePermission
(net_CookiePermissionStruct * cookie_permission, Bool save ) {
// This routine should only be called while holding the
// cookie permission list lock
//
if (cookie_permission) {
XP_List * list_ptr = net_cookie_permission_list;
if(!net_cookie_permission_list) {
net_cookie_permission_list = XP_ListNew();
if(!net_cookie_permission_list) {
PR_Free(cookie_permission->host);
PR_Free(cookie_permission);
return;
}
list_ptr = net_cookie_permission_list;
}
#ifdef alphabetize
// add it to the list in alphabetical order
{
net_CookiePermissionStruct * tmp_cookie_permission;
Bool permissionAdded = FALSE;
while((tmp_cookie_permission = (net_CookiePermissionStruct *)
XP_ListNextObject(list_ptr))!=0) {
if (PL_strcasecmp
(cookie_permission->host,tmp_cookie_permission->host)<0) {
XP_ListInsertObject
(net_cookie_permission_list,
tmp_cookie_permission,
cookie_permission);
permissionAdded = TRUE;
break;
}
}
if (!permissionAdded) {
XP_ListAddObjectToEnd
(net_cookie_permission_list, cookie_permission);
}
}
#else
// add it to the end of the list
XP_ListAddObjectToEnd (net_cookie_permission_list, cookie_permission);
#endif
if (save) {
cookie_permissions_changed = TRUE;
net_SaveCookiePermissions(NULL);
}
}
}
*/
/*
MODULE_PRIVATE PRBool
net_CookieIsFromHost(net_CookieStruct *cookie_s, char *host) {
if (!cookie_s || !(cookie_s->host)) {
return FALSE;
}
if (cookie_s->is_domain) {
char *cp;
int domain_length, host_length;
domain_length = PL_strlen(cookie_s->host);
// calculate the host length by looking at all characters up to
// a colon or '\0'. That way we won't include port numbers
// in domains
//
for(cp=host; *cp != '\0' && *cp != ':'; cp++) {
; // null body
}
host_length = cp - host;
// compare the tail end of host to cook_s->host
return (domain_length <= host_length &&
PL_strncasecmp(cookie_s->host,
&host[host_length - domain_length],
domain_length) == 0);
} else {
return PL_strcasecmp(host, cookie_s->host) == 0;
}
}
*/
/* find out how many cookies this host has already set */
/*
PRIVATE int
net_CookieCount(char * host) {
int count = 0;
XP_List * list_ptr;
net_CookieStruct * cookie;
net_lock_cookie_list();
list_ptr = net_cookie_list;
while((cookie = (net_CookieStruct *) XP_ListNextObject(list_ptr))!=0) {
if (host && net_CookieIsFromHost(cookie, host)) {
count++;
}
}
net_unlock_cookie_list();
return count;
}
*/
/*
PUBLIC int
NET_CookieCount(char * URLName) {
char * host;
char * colon;
int count = 0;
if (!URLName || !(*URLName)) {
return 0;
}
// remove protocol from URL name
host = NET_ParseURL(URLName, GET_HOST_PART);
// remove port number from URL name
colon = PL_strchr(host, ':');
if(colon) {
*colon = '\0';
}
// get count
count = net_CookieCount(host);
// free up allocated string and return
if(colon) {
*colon = ':';
}
PR_Free(host);
return count;
}
*/
/*
PRBool net_IntSetCookieStringInUse = FALSE;
PRIVATE void
net_DeferCookie(
MWContext * context,
char * cur_url,
char * set_cookie_header,
time_t timeToExpire) {
net_DeferCookieStruct * defer_cookie = PR_NEW(net_DeferCookieStruct);
defer_cookie->context = context;
defer_cookie->cur_url = NULL;
StrAllocCopy(defer_cookie->cur_url, cur_url);
defer_cookie->set_cookie_header = NULL;
StrAllocCopy(defer_cookie->set_cookie_header, set_cookie_header);
defer_cookie->timeToExpire = timeToExpire;
net_lock_defer_cookie_list();
if (!net_defer_cookie_list) {
net_defer_cookie_list = XP_ListNew();
if (!net_cookie_list) {
PR_FREEIF(defer_cookie->cur_url);
PR_FREEIF(defer_cookie->set_cookie_header);
PR_Free(defer_cookie);
}
}
XP_ListAddObject(net_defer_cookie_list, defer_cookie);
net_unlock_defer_cookie_list();
}
*/
/*
PRIVATE void
net_IntSetCookieString(MWContext * context,
char * cur_url,
char * set_cookie_header,
time_t timeToExpire );
PRIVATE void
net_UndeferCookies() {
net_DeferCookieStruct * defer_cookie;
net_lock_defer_cookie_list();
if(XP_ListIsEmpty(net_defer_cookie_list)) {
net_unlock_defer_cookie_list();
return;
}
defer_cookie = XP_ListRemoveEndObject(net_defer_cookie_list);
net_unlock_defer_cookie_list();
net_IntSetCookieString (
defer_cookie->context,
defer_cookie->cur_url,
defer_cookie->set_cookie_header,
defer_cookie->timeToExpire);
PR_FREEIF(defer_cookie->cur_url);
PR_FREEIF(defer_cookie->set_cookie_header);
PR_Free(defer_cookie);
}
#endif
*/
/* Java script is calling NET_SetCookieString, netlib is calling
** this via NET_SetCookieStringFromHttp.
*/
/*
PRIVATE void
net_IntSetCookieString(MWContext * context,
char * cur_url,
char * set_cookie_header,
time_t timeToExpire )
{
net_CookieStruct * prev_cookie;
char *path_from_header=NULL, *host_from_header=NULL;
char *host_from_header2=NULL;
char *name_from_header=NULL, *cookie_from_header=NULL;
time_t expires=0;
char *cur_path = NET_ParseURL(cur_url, GET_PATH_PART);
char *cur_host = NET_ParseURL(cur_url, GET_HOST_PART);
char *semi_colon, *ptr, *equal;
const char *script_name;
PRBool HG83744 is_domain=FALSE, ask=FALSE, accept=FALSE;
MWContextType type;
Bool bCookieAdded;
if(!context) {
PR_Free(cur_path);
PR_Free(cur_host);
return;
}
// Only allow cookies to be set in the listed contexts. We
// don't want cookies being set in html mail.
type = context->type;
if(!( (type == MWContextBrowser)
|| (type == MWContextHTMLHelp)
|| (type == MWContextPane) )) {
PR_Free(cur_path);
PR_Free(cur_host);
return;
}
if(NET_GetCookieBehaviorPref() == NET_DontUse) {
PR_Free(cur_path);
PR_Free(cur_host);
return;
}
#if defined(CookieManagement)
// Don't enter this routine if it is already in use by another
// thread. Otherwise the "remember this decision" result of the
// other cookie (which came first) won't get applied to this cookie.
if (net_IntSetCookieStringInUse) {
PR_Free(cur_path);
PR_Free(cur_host);
net_DeferCookie(context, cur_url, set_cookie_header, timeToExpire);
return;
}
net_IntSetCookieStringInUse = TRUE;
#endif
HG87358
// terminate at any carriage return or linefeed
for(ptr=set_cookie_header; *ptr; ptr++)
if(*ptr == LF || *ptr == CR) {
*ptr = '\0';
break;
}
// parse path and expires attributes from header if
//present
//
semi_colon = PL_strchr(set_cookie_header, ';');
if(semi_colon)
{
// truncate at semi-colon and advance
//
*semi_colon++ = '\0';
// there must be some attributes. (hopefully)
//
HG83476
// look for the path attribute
//
ptr = PL_strcasestr(semi_colon, "path=");
if(ptr) {
// allocate more than we need
StrAllocCopy(path_from_header, XP_StripLine(ptr+5));
// terminate at first space or semi-colon
//
for(ptr=path_from_header; *ptr != '\0'; ptr++)
if(NET_IS_SPACE(*ptr) || *ptr == ';' || *ptr == ',') {
*ptr = '\0';
break;
}
}
// look for the URI or URL attribute
// This might be a security hole so I'm removing
// it for now.
// look for a domain
ptr = PL_strcasestr(semi_colon, "domain=");
if(ptr) {
char *domain_from_header=NULL;
char *dot, *colon;
int domain_length, cur_host_length;
// allocate more than we need
StrAllocCopy(domain_from_header, XP_StripLine(ptr+7));
// terminate at first space or semi-colon
//
for(ptr=domain_from_header; *ptr != '\0'; ptr++)
if(NET_IS_SPACE(*ptr) || *ptr == ';' || *ptr == ',') {
*ptr = '\0';
break;
}
// verify that this host has the authority to set for
// this domain. We do this by making sure that the
// host is in the domain
// We also require that a domain have at least two
// periods to prevent domains of the form ".com"
// and ".edu"
//
// Also make sure that there is more stuff after
// the second dot to prevent ".com."
dot = PL_strchr(domain_from_header, '.');
if(dot)
dot = PL_strchr(dot+1, '.');
if(!dot || *(dot+1) == '\0') {
// did not pass two dot test. FAIL
PR_Free(domain_from_header);
PR_Free(cur_path);
PR_Free(cur_host);
TRACEMSG(("DOMAIN failed two dot test"));
#if defined(CookieManagement)
net_IntSetCookieStringInUse = FALSE;
net_UndeferCookies();
#endif
return;
}
// strip port numbers from the current host
// for the domain test
colon = PL_strchr(cur_host, ':');
if(colon)
*colon = '\0';
domain_length = PL_strlen(domain_from_header);
cur_host_length = PL_strlen(cur_host);
// check to see if the host is in the domain
//
if(domain_length > cur_host_length
|| PL_strcasecmp(domain_from_header,
&cur_host[cur_host_length-domain_length]))
{
TRACEMSG(("DOMAIN failed host within domain test."
" Domain: %s, Host: %s", domain_from_header, cur_host));
PR_Free(domain_from_header);
PR_Free(cur_path);
PR_Free(cur_host);
#if defined(CookieManagement)
net_IntSetCookieStringInUse = FALSE;
net_UndeferCookies();
#endif
return;
}
// check that portion of host not in domain does not contain a dot
// This satisfies the fourth requirement in section 4.3.2 of the cookie
// spec rfc 2109 (see www.cis.ohio-state.edu/htbin/rfc/rfc2109.html).
// It prevents host of the form x.y.co.nz from setting cookies in the
// entire .co.nz domain. Note that this doesn't really solve the problem,
// it justs makes it more unlikely. Sites such as y.co.nz can still set
// cookies for the entire .co.nz domain.
//
cur_host[cur_host_length-domain_length] = '\0';
dot = XP_STRCHR(cur_host, '.');
cur_host[cur_host_length-domain_length] = '.';
if (dot) {
TRACEMSG(("host minus domain failed no-dot test."
" Domain: %s, Host: %s", domain_from_header, cur_host));
PR_Free(domain_from_header);
PR_Free(cur_path);
PR_Free(cur_host);
#if defined(CookieManagement)
net_IntSetCookieStringInUse = FALSE;
net_UndeferCookies();
#endif
return;
}
// all tests passed, copy in domain to hostname field
StrAllocCopy(host_from_header, domain_from_header);
is_domain = TRUE;
TRACEMSG(("Accepted domain: %s", host_from_header));
PR_Free(domain_from_header);
}
// now search for the expires header
// NOTE: that this part of the parsing
// destroys the original part of the string
//
ptr = PL_strcasestr(semi_colon, "expires=");
if(ptr) {
char *date = ptr+8;
// terminate the string at the next semi-colon
for(ptr=date; *ptr != '\0'; ptr++)
if(*ptr == ';') {
*ptr = '\0';
break;
}
if(timeToExpire)
expires = timeToExpire;
else
expires = NET_ParseDate(date);
TRACEMSG(("Have expires date: %ld", expires));
}
}
if(!path_from_header) {
// strip down everything after the last slash
// to get the path.
char * slash = PL_strrchr(cur_path, '/');
if(slash)
*slash = '\0';
path_from_header = cur_path;
} else {
PR_Free(cur_path);
}
if(!host_from_header)
host_from_header = cur_host;
else
PR_Free(cur_host);
// keep cookies under the max bytes limit
if(PL_strlen(set_cookie_header) > MAX_BYTES_PER_COOKIE)
set_cookie_header[MAX_BYTES_PER_COOKIE-1] = '\0';
// separate the name from the cookie
equal = PL_strchr(set_cookie_header, '=');
if(equal) {
*equal = '\0';
StrAllocCopy(name_from_header, XP_StripLine(set_cookie_header));
StrAllocCopy(cookie_from_header, XP_StripLine(equal+1));
} else {
TRACEMSG(("Warning: no name found for cookie"));
StrAllocCopy(cookie_from_header, XP_StripLine(set_cookie_header));
StrAllocCopy(name_from_header, "");
}
// If there's a script, call it now
script_name = NET_GetCookieScriptPref();
if( (const char *)0 != script_name ) {
JSCFCookieData *cd;
Bool changed = FALSE;
JSCFResult result;
cd = PR_NEWZAP(JSCFCookieData);
if( (JSCFCookieData *)0 == cd ) {
PR_FREEIF(path_from_header);
PR_FREEIF(host_from_header);
PR_FREEIF(name_from_header);
PR_FREEIF(cookie_from_header);
// FREEIF(cur_path);
// FREEIF(cur_host);
#if defined(CookieManagement)
net_IntSetCookieStringInUse = FALSE;
net_UndeferCookies();
#endif
return;
}
cd->path_from_header = path_from_header;
cd->host_from_header = host_from_header;
cd->name_from_header = name_from_header;
cd->cookie_from_header = cookie_from_header;
cd->expires = expires;
cd->url = cur_url;
HG84777
cd->domain = is_domain;
cd->prompt = NET_GetCookieWarningPref();
cd->preference = NET_GetCookieBehaviorPref();
//This is only safe to do from the mozilla thread
// since it might do file I/O and uses the preferences
// global context + objects.
//
// XXX: This is probably not correct, but it will fix the build for now...
result= JSCF_Execute(context, script_name, cd, &changed);
if( result != JSCF_error) {
if( changed ) {
if( cd->path_from_header != path_from_header ) {
PR_FREEIF(path_from_header);
path_from_header = PL_strdup(cd->path_from_header);
}
if( cd->host_from_header != host_from_header ) {
PR_FREEIF(host_from_header);
host_from_header = PL_strdup(cd->host_from_header);
}
if( cd->name_from_header != name_from_header ) {
PR_FREEIF(name_from_header);
name_from_header = PL_strdup(cd->name_from_header);
}
if( cd->cookie_from_header != cookie_from_header ) {
PR_FREEIF(cookie_from_header);
cookie_from_header = PL_strdup(cd->cookie_from_header);
}
if( cd->expires != expires )
expires = cd->expires;
if( cd->domain != is_domain )
//lets hope the luser remembered to change the domain field
is_domain = cd->domain;
HG27398
}
switch( result ) {
case JSCF_reject:
PR_FREEIF(path_from_header);
PR_FREEIF(host_from_header);
PR_FREEIF(name_from_header);
PR_FREEIF(cookie_from_header);
PR_Free(cd);
// FREEIF(cur_path);
// FREEIF(cur_host);
#if defined(CookieManagement)
net_IntSetCookieStringInUse = FALSE;
net_UndeferCookies();
#endif
return;
case JSCF_accept:
accept=TRUE;
case JSCF_error:
case JSCF_ask:
ask=TRUE;
case JSCF_whatever:
break;
}
}
PR_Free(cd);
#if defined(CookieManagement)
} else {
net_CookiePermissionStruct * cookie_permission;
cookie_permission = net_CheckForCookiePermission(host_from_header);
if (cookie_permission != NULL) {
if (cookie_permission->permission == FALSE) {
PR_FREEIF(path_from_header);
PR_FREEIF(host_from_header);
PR_FREEIF(name_from_header);
PR_FREEIF(cookie_from_header);
net_IntSetCookieStringInUse = FALSE;
net_UndeferCookies();
return;
} else {
accept = TRUE;
}
}
#endif
}
if( (NET_GetCookieWarningPref() || ask) && !accept ) {
// the user wants to know about cookies so let them
// know about every one that is set and give them
//the choice to accept it or not
//
char * new_string=0;
#if defined(CookieManagement)
int count;
char * remember_string = 0;
StrAllocCopy
(remember_string, XP_GetString(MK_ACCESS_COOKIES_REMEMBER));
// find out how many cookies this host has already set
count = net_CookieCount(host_from_header);
net_lock_cookie_list();
prev_cookie = net_CheckForPrevCookie
(path_from_header, host_from_header, name_from_header);
net_unlock_cookie_list();
if (prev_cookie) {
new_string = PR_smprintf(
XP_GetString(MK_ACCESS_COOKIES_WISHES_MODIFY),
host_from_header ? host_from_header : "");
} else if (count>1) {
new_string = PR_smprintf(
XP_GetString(MK_ACCESS_COOKIES_WISHESN),
host_from_header ? host_from_header : "",
count);
} else if (count==1){
new_string = PR_smprintf(
XP_GetString(MK_ACCESS_COOKIES_WISHES1),
host_from_header ? host_from_header : "");
} else {
new_string = PR_smprintf(
XP_GetString(MK_ACCESS_COOKIES_WISHES0),
host_from_header ? host_from_header : "");
}
#else
char * tmp_host = NET_ParseURL(cur_url, GET_HOST_PART);
StrAllocCopy(new_string, XP_GetString(MK_ACCESS_COOKIES_THE_SERVER));
StrAllocCat(new_string, tmp_host ? tmp_host : "");
StrAllocCat(new_string, XP_GetString(MK_ACCESS_COOKIES_WISHES));
PR_Free(tmp_host);
if(is_domain) {
StrAllocCat(new_string, XP_GetString(MK_ACCESS_COOKIES_TOANYSERV));
StrAllocCat(new_string, host_from_header);
} else {
StrAllocCat(new_string, XP_GetString(MK_ACCESS_COOKIES_TOSELF));
}
StrAllocCat(new_string, XP_GetString(MK_ACCESS_COOKIES_NAME_AND_VAL));
StrAllocCat(new_string, name_from_header);
StrAllocCat(new_string, "=");
StrAllocCat(new_string, cookie_from_header);
StrAllocCat(new_string, "\n");
if(expires) {
StrAllocCat(new_string, XP_GetString(MK_ACCESS_COOKIES_COOKIE_WILL_PERSIST));
StrAllocCat(new_string, ctime(&expires));
}
StrAllocCat(new_string, XP_GetString(MK_ACCESS_COOKIES_SET_IT));
#endif
//
// Who knows what thread we are on. Only the mozilla thread
// is allowed to post dialogs so, if need be, go over there
//
#if defined(CookieManagement)
{
Bool old_cookie_remember_checked = cookie_remember_checked;
XP_Bool userHasAccepted = ET_PostCheckConfirmBox
(context,
new_string,
remember_string,
0,0,
&cookie_remember_checked);
PR_FREEIF(new_string);
PR_FREEIF(remember_string);
if (cookie_remember_checked) {
net_CookiePermissionStruct * cookie_permission;
cookie_permission = PR_NEW(net_CookiePermissionStruct);
if (cookie_permission) {
net_lock_cookie_permission_list();
StrAllocCopy(host_from_header2, host_from_header);
//ignore leading periods in host name
while (host_from_header2 && (*host_from_header2 == '.')) {
host_from_header2++;
}
cookie_permission->host = host_from_header2; // set host string
cookie_permission->permission = userHasAccepted;
#ifdef TRUST_LABELS
cookie_permission->TrustList = NULL;
#endif
net_AddCookiePermission(cookie_permission, TRUE);
net_unlock_cookie_permission_list();
}
}
if (old_cookie_remember_checked != cookie_remember_checked) {
cookie_permissions_changed = TRUE;
net_SaveCookiePermissions(NULL);
}
if (!userHasAccepted) {
#if defined(CookieManagement)
net_IntSetCookieStringInUse = FALSE;
net_UndeferCookies();
#endif
return;
}
}
#else
if(!ET_PostMessageBox(context, new_string, TRUE)) {
PR_FREEIF(new_string);
return;
}
PR_FREEIF(new_string);
#endif
}
TRACEMSG(("mkaccess.c: Setting cookie: %s for host: %s for path: %s",
cookie_from_header, host_from_header, path_from_header));
// We have decided we are going to insert a cookie into the list
// Get the cookie lock so that we can munge on the list
//
net_lock_cookie_list();
// limit the number of cookies from a specific host or domain
net_CheckForMaxCookiesFromHost(host_from_header);
if(XP_ListCount(net_cookie_list) > MAX_NUMBER_OF_COOKIES-1)
net_remove_oldest_cookie();
prev_cookie = net_CheckForPrevCookie
(path_from_header, host_from_header, name_from_header);
if(prev_cookie) {
prev_cookie->expires = expires;
PR_FREEIF(prev_cookie->cookie);
PR_FREEIF(prev_cookie->path);
PR_FREEIF(prev_cookie->host);
PR_FREEIF(prev_cookie->name);
prev_cookie->cookie = cookie_from_header;
prev_cookie->path = path_from_header;
prev_cookie->host = host_from_header;
prev_cookie->name = name_from_header;
HG83263
prev_cookie->is_domain = is_domain;
prev_cookie->last_accessed = time(NULL);
} else {
XP_List * list_ptr = net_cookie_list;
net_CookieStruct * tmp_cookie_ptr;
size_t new_len;
// construct a new cookie_struct
//
prev_cookie = PR_NEW(net_CookieStruct);
if(!prev_cookie) {
PR_FREEIF(path_from_header);
PR_FREEIF(host_from_header);
PR_FREEIF(name_from_header);
PR_FREEIF(cookie_from_header);
net_unlock_cookie_list();
#if defined(CookieManagement)
net_IntSetCookieStringInUse = FALSE;
net_UndeferCookies();
#endif
return;
}
//copy
//
prev_cookie->cookie = cookie_from_header;
prev_cookie->name = name_from_header;
prev_cookie->path = path_from_header;
prev_cookie->host = host_from_header;
prev_cookie->expires = expires;
HG22730
prev_cookie->is_domain = is_domain;
prev_cookie->last_accessed = time(NULL);
if(!net_cookie_list) {
net_cookie_list = XP_ListNew();
if(!net_cookie_list) {
PR_FREEIF(path_from_header);
PR_FREEIF(name_from_header);
PR_FREEIF(host_from_header);
PR_FREEIF(cookie_from_header);
PR_Free(prev_cookie);
net_unlock_cookie_list();
#if defined(CookieManagement)
net_IntSetCookieStringInUse = FALSE;
net_UndeferCookies();
#endif
return;
}
}
// add it to the list so that it is before any strings of
// smaller length
//
bCookieAdded = FALSE;
new_len = PL_strlen(prev_cookie->path);
while((tmp_cookie_ptr = (net_CookieStruct *) XP_ListNextObject(list_ptr))!=0) {
if(new_len > PL_strlen(tmp_cookie_ptr->path)) {
XP_ListInsertObject(net_cookie_list, tmp_cookie_ptr, prev_cookie);
bCookieAdded = TRUE;
break;
}
}
if ( !bCookieAdded ) {
// no shorter strings found in list
XP_ListAddObjectToEnd(net_cookie_list, prev_cookie);
}
}
//At this point we know a cookie has changed. Write the cookies to file.
cookies_changed = TRUE;
NET_SaveCookies(NULL);
net_unlock_cookie_list();
#ifdef TRUST_LABELS
{
TrustLabel *trustlabel;
// At this point the cookie was added to
// the cookie list. So see if there is a trust label that
// matches the cookie and if so add the trust label to the
// cookie permission list. Existing trust label entries in
// the permission list replaced with this latest entry.
//
if ( MatchCookieToLabel2(
cur_url, prev_cookie->name,
prev_cookie->path, prev_cookie->host, &trustlabel ) ) {
// found a match - add the trust info to the proper
// entry in the cookie permission list
//
AddTrustLabelInfo( prev_cookie->name, trustlabel );
// update the disk file //
cookie_permissions_changed = TRUE;
net_SaveCookiePermissions(NULL);
}
}
#endif
#if defined(CookieManagement)
net_IntSetCookieStringInUse = FALSE;
net_UndeferCookies();
#endif
return;
}
*/
/*
PUBLIC void
NET_SetCookieString(MWContext * context,
char * cur_url,
char * set_cookie_header) {
net_IntSetCookieString(context, cur_url, set_cookie_header, 0);
}
*/
/* Determines whether the inlineHost is in the same domain as the currentHost. For use with rfc 2109
* compliance/non-compliance. */
/*
#ifdef TRUST_LABELS
PUBLIC int
#else
PRIVATE int
#endif
*/
/*
NET_SameDomain(char * currentHost, char * inlineHost)
{
char * dot = 0;
char * currentDomain = 0;
char * inlineDomain = 0;
if(!currentHost || !inlineHost)
return 0;
// case insensitive compare
if(PL_strcasecmp(currentHost, inlineHost) == 0)
return 1;
currentDomain = PL_strchr(currentHost, '.');
inlineDomain = PL_strchr(inlineHost, '.');
if(!currentDomain || !inlineDomain)
return 0;
// check for at least two dots before continuing, if there are
// not two dots we don't have enough information to determine
// whether or not the inlineDomain is within the currentDomain
dot = PL_strchr(inlineDomain, '.');
if(dot)
dot = PL_strchr(dot+1, '.');
else
return 0;
// handle .com. case
if(!dot || (*(dot+1) == '\0') )
return 0;
if(!PL_strcasecmp(inlineDomain, currentDomain))
return 1;
return 0;
}
*/
/* This function wrapper wraps NET_SetCookieString for the purposes of
** determining whether or not a cookie is inline (we need the URL struct,
** and outputFormat to do so). this is called from NET_ParseMimeHeaders
** in mkhttp.c
** This routine does not need to worry about the cookie lock since all of
** the work is handled by sub-routines
*/
/*
PUBLIC void
NET_SetCookieStringFromHttp(FO_Present_Types outputFormat,
URL_Struct * URL_s,
MWContext * context,
char * cur_url,
char * set_cookie_header)
{
// If the outputFormat is not PRESENT (the url is not going to the screen), and not
// SAVE AS (shift-click) then
// the cookie being set is defined as inline so we need to do what the user wants us
// to based on his preference to deal with foreign cookies. If it's not inline, just set
// the cookie.
char *ptr=NULL, *date=NULL;
time_t gmtCookieExpires=0, expires=0;
if(CLEAR_CACHE_BIT(outputFormat) != FO_PRESENT && CLEAR_CACHE_BIT(outputFormat) != FO_SAVE_AS)
{
if (NET_GetCookieBehaviorPref() == NET_DontAcceptForeign)
{
// the user doesn't want foreign cookies, check to see if its foreign
char * curSessionHistHost = 0;
char * theColon = 0;
char * curHost = NET_ParseURL(cur_url, GET_HOST_PART);
History_entry * shistEntry = SHIST_GetCurrent(&context->hist);
if (shistEntry) {
curSessionHistHost = NET_ParseURL(shistEntry->address, GET_HOST_PART);
}
if(!curHost || !curSessionHistHost)
{
PR_FREEIF(curHost);
PR_FREEIF(curSessionHistHost);
return;
}
// strip ports
theColon = PL_strchr(curHost, ':');
if(theColon)
*theColon = '\0';
theColon = PL_strchr(curSessionHistHost, ':');
if(theColon)
*theColon = '\0';
// if it's foreign, get out of here after a little clean up
if(!NET_SameDomain(curHost, curSessionHistHost))
{
PR_FREEIF(curHost);
PR_FREEIF(curSessionHistHost);
return;
}
PR_FREEIF(curHost);
PR_FREEIF(curSessionHistHost);
}
}
//Determine when the cookie should expire. This is done by taking the difference between
//the server time and the time the server wants the cookie to expire, and adding that
// difference to the client time. This localizes the client time regardless of whether or
// not the TZ environment variable was set on the client.
// Get the time the cookie is supposed to expire according to the attribute
ptr = PL_strcasestr(set_cookie_header, "expires=");
if(ptr)
{
char *date = ptr+8;
char origLast = '\0';
for(ptr=date; *ptr != '\0'; ptr++)
if(*ptr == ';')
{
origLast = ';';
*ptr = '\0';
break;
}
expires = NET_ParseDate(date);
*ptr=origLast;
}
if( URL_s->server_date && expires )
{
if( expires < URL_s->server_date )
{
gmtCookieExpires=1;
}
else
{
gmtCookieExpires = expires - URL_s->server_date + time(NULL);
// if overflow
if( gmtCookieExpires < time(NULL) )
gmtCookieExpires = (((unsigned) (~0) << 1) >> 1); // max int
}
}
net_IntSetCookieString(context, cur_url, set_cookie_header, gmtCookieExpires);
}
*/
#if defined(CookieManagement)
/* saves the HTTP cookies permissions to disk
* the parameter passed in on entry is ignored
* returns 0 on success -1 on failure.
*/
/*
PRIVATE int
net_SaveCookiePermissions(char * filename)
{
XP_List * list_ptr;
net_CookiePermissionStruct * cookie_permission_s;
XP_File fp;
int32 len = 0;
if(NET_GetCookieBehaviorPref() == NET_DontUse) {
return(-1);
}
if(!cookie_permissions_changed) {
return(-1);
}
net_lock_cookie_permission_list();
list_ptr = net_cookie_permission_list;
if(!(net_cookie_permission_list)) {
net_unlock_cookie_permission_list();
return(-1);
}
if(!(fp = NET_XP_FileOpen(filename, xpHTTPCookiePermission, XP_FILE_WRITE))) {
net_unlock_cookie_permission_list();
return(-1);
}
len = NET_XP_FileWrite("# Netscape HTTP Cookie Permission File" LINEBREAK
"# http://www.netscape.com/newsref/std/cookie_spec.html"
LINEBREAK "# This is a generated file! Do not edit."
LINEBREAK LINEBREAK, -1, fp);
if (len < 0) {
NET_XP_FileClose(fp);
net_unlock_cookie_permission_list();
return -1;
}
// format shall be:
// host \t permission <optional trust label information >
//
while((cookie_permission_s = (net_CookiePermissionStruct *)
XP_ListNextObject(list_ptr)) != NULL) {
len = NET_XP_FileWrite(cookie_permission_s->host, -1, fp);
if (len < 0) {
NET_XP_FileClose(fp);
net_unlock_cookie_permission_list();
return -1;
}
NET_XP_FileWrite("\t", 1, fp);
if(cookie_permission_s->permission) {
NET_XP_FileWrite("TRUE", -1, fp);
} else {
NET_XP_FileWrite("FALSE", -1, fp);
}
#ifdef TRUST_LABELS
// save the trust label information
SaveTrustLabelData( cookie_permission_s, fp );
#endif
len = NET_XP_FileWrite(LINEBREAK, -1, fp);
if (len < 0) {
NET_XP_FileClose(fp);
net_unlock_cookie_permission_list();
return -1;
}
}
// save current state of cookie nag-box's checkmark
NET_XP_FileWrite("@@@@", -1, fp);
NET_XP_FileWrite("\t", 1, fp);
if (cookie_remember_checked) {
NET_XP_FileWrite("TRUE", -1, fp);
} else {
NET_XP_FileWrite("FALSE", -1, fp);
}
NET_XP_FileWrite(LINEBREAK, -1, fp);
cookie_permissions_changed = FALSE;
NET_XP_FileClose(fp);
net_unlock_cookie_permission_list();
return(0);
}
*/
/* reads the HTTP cookies permission from disk
* the parameter passed in on entry is ignored
* returns 0 on success -1 on failure.
*
*/
/* #define PERMISSION_LINE_BUFFER_SIZE 4096 */
/*
PRIVATE int
net_ReadCookiePermissions(char * filename)
{
XP_File fp;
char buffer[PERMISSION_LINE_BUFFER_SIZE];
char *host, *p;
Bool permission_value;
net_CookiePermissionStruct * cookie_permission;
char *host_from_header2;
if(!(fp = NET_XP_FileOpen(filename, xpHTTPCookiePermission, XP_FILE_READ)))
return(-1);
// format is:
// host \t permission <optional trust label information>
// if this format isn't respected we move onto the next line in the file.
//
net_lock_cookie_permission_list();
while(NET_XP_FileReadLine(buffer, PERMISSION_LINE_BUFFER_SIZE, fp)) {
if (*buffer == '#' || *buffer == CR || *buffer == LF || *buffer == 0) {
continue;
}
XP_StripLine(buffer); // remove '\n' from end of the line
host = buffer;
// isolate the host field which is the first field on the line
if( !(p = PL_strchr(host, '\t')) ) {
continue; / * no permission field * /
}
*p++ = '\0';
if(*p == CR || *p == LF || *p == 0) {
continue; // no permission field
}
// ignore leading periods in host name
while (host && (*host == '.')) {
host++;
}
// the first part of the permission file is valid -
// allocate a new permission struct and fill it in
//
cookie_permission = PR_NEW(net_CookiePermissionStruct);
if (cookie_permission) {
host_from_header2 = PL_strdup(host);
cookie_permission->host = host_from_header2;
// Now handle the permission field.
// a host value of "@@@@" is a special code designating the
// state of the cookie nag-box's checkmark
//
permission_value = (!PL_strncmp(p, "TRUE", sizeof("TRUE")-1));
if (!PL_strcmp(host, "@@@@")) {
cookie_remember_checked = permission_value;
} else {
cookie_permission->permission = permission_value;
#ifdef TRUST_LABELS
// pick up the trust label information from the line
// and add it to the permission struct
//
cookie_permission->TrustList = NULL;
ParseTrustLabelInfo(p, cookie_permission);
#endif
// add the permission entry
net_AddCookiePermission( cookie_permission, FALSE );
}
} // end if (cookie_permission)
} // while(NET_XP_FileReadLine(
net_unlock_cookie_permission_list();
NET_XP_FileClose(fp);
cookie_permissions_changed = FALSE;
return(0);
}
*/
#endif
/* saves out the HTTP cookies to disk
*
* on entry pass in the name of the file to save
*
* returns 0 on success -1 on failure.
*
*/
/*
PUBLIC int
NET_SaveCookies(char * filename)
{
XP_List * list_ptr;
net_CookieStruct * cookie_s;
time_t cur_date = time(NULL);
XP_File fp;
int32 len = 0;
char date_string[36];
if(NET_GetCookieBehaviorPref() == NET_DontUse)
return(-1);
if(!cookies_changed)
return(-1);
if(net_anonymous) {
return(-1);
}
net_lock_cookie_list();
list_ptr = net_cookie_list;
if(!(list_ptr)) {
net_unlock_cookie_list();
return(-1);
}
if(!(fp = NET_XP_FileOpen(filename, xpHTTPCookie, XP_FILE_WRITE))) {
net_unlock_cookie_list();
return(-1);
}
len = NET_XP_FileWrite("# Netscape HTTP Cookie File" LINEBREAK
"# http://www.netscape.com/newsref/std/cookie_spec.html"
LINEBREAK "# This is a generated file! Do not edit."
LINEBREAK LINEBREAK,
-1, fp);
if (len < 0)
{
NET_XP_FileClose(fp);
net_unlock_cookie_list();
return -1;
}
// format shall be:
// host \t is_domain \t path \t secure \t expires \t name \t cookie
//is_domain is TRUE or FALSE
// secure is TRUE or FALSE
// expires is a time_t integer
// cookie can have tabs
//
while((cookie_s = (net_CookieStruct *) XP_ListNextObject(list_ptr)) != NULL)
{
if(cookie_s->expires < cur_date)
continue; // don't write entry if cookie has expired
// or has no expiration date
//
len = NET_XP_FileWrite(cookie_s->host, -1, fp);
if (len < 0)
{
NET_XP_FileClose(fp);
net_unlock_cookie_list();
return -1;
}
NET_XP_FileWrite("\t", 1, fp);
if(cookie_s->is_domain)
NET_XP_FileWrite("TRUE", -1, fp);
else
NET_XP_FileWrite("FALSE", -1, fp);
NET_XP_FileWrite("\t", 1, fp);
NET_XP_FileWrite(cookie_s->path, -1, fp);
NET_XP_FileWrite("\t", 1, fp);
HG74640
NET_XP_FileWrite("FALSE", -1, fp);
NET_XP_FileWrite("\t", 1, fp);
PR_snprintf(date_string, sizeof(date_string), "%lu", cookie_s->expires);
NET_XP_FileWrite(date_string, -1, fp);
NET_XP_FileWrite("\t", 1, fp);
NET_XP_FileWrite(cookie_s->name, -1, fp);
NET_XP_FileWrite("\t", 1, fp);
NET_XP_FileWrite(cookie_s->cookie, -1, fp);
len = NET_XP_FileWrite(LINEBREAK, -1, fp);
if (len < 0)
{
NET_XP_FileClose(fp);
net_unlock_cookie_list();
return -1;
}
}
cookies_changed = FALSE;
NET_XP_FileClose(fp);
net_unlock_cookie_list();
return(0);
}
*/
/* This isn't needed any more */
/*
PRIVATE void
NET_InitRDFCookieResources (void)
{
}
*/
/* reads HTTP cookies from disk
*
* on entry pass in the name of the file to read
*
* returns 0 on success -1 on failure.
*
*
*/
/*#define LINE_BUFFER_SIZE 4096 */
/*
PUBLIC int
NET_ReadCookies(char * filename)
{
XP_List * list_ptr;
net_CookieStruct *new_cookie, *tmp_cookie_ptr;
size_t new_len;
XP_File fp;
char buffer[LINE_BUFFER_SIZE];
char *host, *is_domain, *path, *xxx, *expires, *name, *cookie;
Bool added_to_list;
#if defined(CookieManagement)
net_ReadCookiePermissions(NULL);
#endif
if(!(fp = NET_XP_FileOpen(filename, xpHTTPCookie, XP_FILE_READ)))
return(-1);
net_lock_cookie_list();
list_ptr = net_cookie_list;
// format is:
//
// host \t is_domain \t path \t xxx \t expires \t name \t cookie
//
// if this format isn't respected we move onto the next line in the file.
// is_domain is TRUE or FALSE -- defaulting to FALSE
// xxx is TRUE or FALSE -- should default to TRUE
// expires is a time_t integer
// cookie can have tabs
//
while(NET_XP_FileReadLine(buffer, LINE_BUFFER_SIZE, fp))
{
added_to_list = FALSE;
if (*buffer == '#' || *buffer == CR || *buffer == LF || *buffer == 0)
continue;
host = buffer;
if( !(is_domain = PL_strchr(host, '\t')) )
continue;
*is_domain++ = '\0';
if(*is_domain == CR || *is_domain == LF || *is_domain == 0)
continue;
if( !(path = PL_strchr(is_domain, '\t')) )
continue;
*path++ = '\0';
if(*path == CR || *path == LF || *path == 0)
continue;
if( !(xxx = PL_strchr(path, '\t')) )
continue;
*xxx++ = '\0';
if(*xxx == CR || *xxx == LF || *xxx == 0)
continue;
if( !(expires = PL_strchr(xxx, '\t')) )
continue;
*expires++ = '\0';
if(*expires == CR || *expires == LF || *expires == 0)
continue;
if( !(name = PL_strchr(expires, '\t')) )
continue;
*name++ = '\0';
if(*name == CR || *name == LF || *name == 0)
continue;
if( !(cookie = PL_strchr(name, '\t')) )
continue;
*cookie++ = '\0';
if(*cookie == CR || *cookie == LF || *cookie == 0)
continue;
// remove the '\n' from the end of the cookie
XP_StripLine(cookie);
// construct a new cookie_struct
//
new_cookie = PR_NEW(net_CookieStruct);
if(!new_cookie)
{
net_unlock_cookie_list();
return(-1);
}
memset(new_cookie, 0, sizeof(net_CookieStruct));
//copy
//
StrAllocCopy(new_cookie->cookie, cookie);
StrAllocCopy(new_cookie->name, name);
StrAllocCopy(new_cookie->path, path);
StrAllocCopy(new_cookie->host, host);
new_cookie->expires = atol(expires);
HG87365
if(!PL_strcmp(is_domain, "TRUE"))
new_cookie->is_domain = TRUE;
else
new_cookie->is_domain = FALSE;
if(!net_cookie_list)
{
net_cookie_list = XP_ListNew();
if(!net_cookie_list)
{
net_unlock_cookie_list();
return(-1);
}
}
// add it to the list so that it is before any strings of
// smaller length
//
new_len = PL_strlen(new_cookie->path);
while((tmp_cookie_ptr = (net_CookieStruct *) XP_ListNextObject(list_ptr)) != NULL)
{
if(new_len > PL_strlen(tmp_cookie_ptr->path))
{
XP_ListInsertObject(net_cookie_list, tmp_cookie_ptr, new_cookie);
added_to_list = TRUE;
break;
}
}
// no shorter strings found in list
if(!added_to_list)
XP_ListAddObjectToEnd(net_cookie_list, new_cookie);
}
NET_XP_FileClose(fp);
net_unlock_cookie_list();
cookies_changed = FALSE;
return(0);
}
*/
/* --- New stuff: General auth utils (currently used only by proxy auth) --- */
/*
* Figure out the authentication scheme used; currently supported:
*
* * Basic
*
*/
HG73632
PRIVATE net_AuthType
net_auth_type(char *name)
{
if (name) {
while (*name && NET_IS_SPACE(*name))
name++;
if (!PL_strncasecmp(name, "basic", 5))
return AUTH_BASIC;
#ifdef SIMPLE_MD5
HG29383
#endif
/*FORTEZZA checks*/
else if (!PL_strncasecmp(name, "fortezzaproxy", 13))
return AUTH_FORTEZZA;
}
return AUTH_INVALID;
}
/*
* Figure out better of two {WWW,Proxy}-Authenticate headers;
* SimpleMD5 is better than Basic. Uses the order of AuthType
* enum values.
*
*/
MODULE_PRIVATE PRBool
net_IsBetterAuth(char *new_auth, char *old_auth)
{
if (!old_auth || net_auth_type(new_auth) >= net_auth_type(old_auth))
return PR_TRUE;
else
return PR_FALSE;
}
/*
* Turns binary data of given lenght into a newly-allocated HEX string.
*
*
*/
PRIVATE char *
bin2hex(unsigned char *data, int len)
{
char *buf = (char *)PR_Malloc(2 * len + 1);
char *p = buf;
if(!buf)
return NULL;
while (len-- > 0) {
sprintf(p, "%02x", *data);
p += 2;
data++;
}
*p = '\0';
return buf;
}
/*
* Parse {WWW,Proxy}-Authenticate header parameters into a net_AuthStruct
* structure.
*
*/
#define SKIP_WS(p) while((*(p)) && NET_IS_SPACE(*(p))) p++
PRIVATE PRBool
next_params(char **pp, char **name, char **value)
{
char *q, *p = *pp;
SKIP_WS(p);
if (!p || !(*p) || !(q = strchr(p, '=')))
return FALSE;
*name = p;
*q++ = '\0';
if (*q == '"') {
*value = q + 1;
q = strchr(*value, '"');
if (q)
*q++ = '\0';
}
else {
*value = q;
while (*q && !NET_IS_SPACE(*q)) q++;
if (*q)
*q++ = '\0';
}
*pp = q;
return TRUE;
}
PRIVATE net_AuthStruct *
net_parse_authenticate_line(char *auth, net_AuthStruct *ret)
{
char *name, *value, *p = auth;
if (!auth || !*auth)
return NULL;
if (!ret)
ret = PR_NEWZAP(net_AuthStruct);
if(!ret)
return NULL;
SKIP_WS(p);
ret->auth_type = net_auth_type(p);
while (*p && !NET_IS_SPACE(*p)) p++;
while (next_params(&p, &name, &value)) {
if (!PL_strcasecmp(name, "realm"))
{
StrAllocCopy(ret->realm, value);
}
#ifdef SIMPLE_MD5
else if (!PL_strcasecmp(name, "domain"))
{
StrAllocCopy(ret->domain, value);
}
else if (!PL_strcasecmp(name, "nonce"))
{
StrAllocCopy(ret->nonce, value);
}
else if (!PL_strcasecmp(name, "opaque"))
{
StrAllocCopy(ret->opaque, value);
}
else if (!PL_strcasecmp(name, "oldnonce"))
{
ret->oldNonce = (!PL_strcasecmp(value, "TRUE")) ? TRUE : FALSE;
}
#endif /* SIMPLE_MD5 */
/* Some FORTEZZA checks */
else if (!PL_strcasecmp(name, "challenge"))
{
StrAllocCopy(ret->challenge, value);
}
else if (!PL_strcasecmp(name, "oldchallenge"))
{
ret->oldChallenge = (!PL_strcasecmp(value, "TRUE")) ? TRUE : FALSE;
}
/* End FORTEZZA checks */
}
#ifdef SIMPLE_MD5
if (!ret->oldNonce)
ret->oldNonce_retries = 0;
#endif /* SIMPLE_MD5 */
/*Another FORTEZZA addition*/
if (!ret->oldChallenge)
ret->oldChallenge_retries = 0;
/*End FORTEZZA addition */
return ret;
}
#ifdef SIMPLE_MD5
/* ---------- New stuff: SimpleMD5 Authentication for proxies -------------- */
PRIVATE void do_md5(unsigned char *stuff, unsigned char digest[16])
{
SECStatus rv;
rv = HASH_HashBuf(HASH_AlgMD5, digest, stuff, strlen((char *)stuff));
return;
}
/*
* Generate a response for a SimpleMD5 challenge.
*
* HEX( MD5("challenge password method url"))
*
*/
char *net_generate_md5_challenge_response(char *challenge,
char *password,
int method,
char *url)
{
unsigned char digest[16];
unsigned char *cookie =
(unsigned char *)PR_Malloc(strlen(challenge) + strlen(password) +
strlen(url) + 10);
if(!cookie)
return NULL;
sprintf((char *)cookie, "%s %s %s %s", challenge, password,
(method==URL_POST_METHOD ? "POST" :
method==URL_HEAD_METHOD ? "HEAD" : "GET"),
url);
do_md5(cookie, digest);
return bin2hex(digest, 16);
}
#define SIMPLEMD5_AUTHORIZATION_FMT "SimpleMD5\
username=\"%s\",\
realm=\"%s\",\
nonce=\"%s\",\
response=\"%s\",\
opaque=\"%s\""
#endif /* SIMPLE_MD5 */
PRIVATE
char *net_generate_auth_string(URL_Struct *url_s,
net_AuthStruct *auth_s)
{
if (!auth_s)
return NULL;
switch (auth_s->auth_type) {
case AUTH_INVALID:
break;
case AUTH_BASIC:
if (!auth_s->auth_string) {
int len;
char *u_pass_string = NULL;
StrAllocCopy(u_pass_string, auth_s->username);
StrAllocCat (u_pass_string, ":");
StrAllocCat (u_pass_string, auth_s->password);
len = PL_strlen(u_pass_string);
if (!(auth_s->auth_string = (char*) PR_Malloc((((len+1)*4)/3)+20)))
{
return NULL;
}
PL_strcpy(auth_s->auth_string, "Basic ");
NET_UUEncode((unsigned char *)u_pass_string,
(unsigned char *)&auth_s->auth_string[6],
len);
PR_Free(u_pass_string);
}
break;
#ifdef SIMPLE_MD5
case AUTH_SIMPLEMD5:
if (auth_s->username && auth_s->password &&
auth_s->nonce && auth_s->opaque &&
url_s && url_s->address)
{
char *resp;
PR_FREEIF(auth_s->auth_string);
auth_s->auth_string = NULL;
if ((resp = net_generate_md5_challenge_response(auth_s->nonce,
auth_s->password,
url_s->method,
url_s->address)))
{
if ((auth_s->auth_string =
(char *)PR_Malloc(PL_strlen(auth_s->username) +
PL_strlen(auth_s->realm) +
PL_strlen(auth_s->nonce) +
PL_strlen(resp) +
PL_strlen(auth_s->opaque) +
100)))
{
sprintf(auth_s->auth_string,
SIMPLEMD5_AUTHORIZATION_FMT,
auth_s->username,
auth_s->realm,
auth_s->nonce,
resp,
auth_s->opaque);
}
PR_Free(resp);
}
}
break;
#endif /* SIMPLE_MD5 */
/* Handle the FORTEZZA case */
case AUTH_FORTEZZA:
HG26251
break;
/* Done Handling the FORTEZZA case */
}
return auth_s->auth_string;
}
/* --------------- New stuff: client-proxy authentication --------------- */
PRIVATE net_AuthStruct *
net_CheckForProxyAuth(char * proxy_addr)
{
XP_List * lp = net_proxy_auth_list;
net_AuthStruct * s;
while ((s = (net_AuthStruct *)XP_ListNextObject(lp)) != NULL)
{
if (!PL_strcasecmp(s->proxy_addr, proxy_addr))
return s;
}
return NULL;
}
/*
* returns a proxy authorization string if one is required, otherwise
* returns NULL
*/
PUBLIC char *
NET_BuildProxyAuthString(MWContext * context,
URL_Struct * url_s,
char * proxy_addr)
{
net_AuthStruct * auth_s = net_CheckForProxyAuth(proxy_addr);
return auth_s ? net_generate_auth_string(url_s, auth_s) : NULL;
}
/*
* Returns FALSE if the user wishes to cancel proxy authorization
* and TRUE if the user wants to continue with a new authorization
* string.
*/
#define INVALID_AUTH_HEADER XP_GetString( XP_PROXY_REQUIRES_UNSUPPORTED_AUTH_SCHEME )
#define LOOPING_OLD_NONCES XP_GetString( XP_LOOPING_OLD_NONCES )
PUBLIC PRBool
NET_AskForProxyAuth(MWContext * context,
char * proxy_addr,
char * pauth_params,
PRBool already_sent_auth,
void * closure)
{
net_AuthStruct * prev;
PRBool new_entry = FALSE;
char * username = NULL;
char * password = NULL;
char * buf;
int32 len=0;
TRACEMSG(("Entering NET_AskForProxyAuth"));
if (!proxy_addr || !*proxy_addr || !pauth_params || !*pauth_params)
return FALSE;
prev = net_CheckForProxyAuth(proxy_addr);
if (prev) {
new_entry = FALSE;
net_parse_authenticate_line(pauth_params, prev);
}
else {
new_entry = TRUE;
if (!(prev = net_parse_authenticate_line(pauth_params, NULL)))
{
FE_Alert(context, INVALID_AUTH_HEADER);
return FALSE;
}
StrAllocCopy(prev->proxy_addr, proxy_addr);
}
if (!prev->realm || !*prev->realm)
StrAllocCopy(prev->realm, XP_GetString( XP_UNIDENTIFIED_PROXY_SERVER ) );
if (!new_entry) {
if (!already_sent_auth)
{
/* somehow the mapping changed since the time we sent
* the authorization.
* This happens sometimes because of the parrallel
* nature of the requests.
* In this case we want to just retry the connection
* since it will probably succeed now.
*/
return TRUE;
}
#ifdef SIMPLE_MD5
else if (prev->oldNonce && prev->oldNonce_retries++ < 3)
{
/*
* We already sent the authorization string and the
* nonce was expired -- auto-retry.
*/
if (!FE_Confirm(context, LOOPING_OLD_NONCES))
return FALSE;
}
#endif /* SIMPLE_MD5 */
/* Do the good old FORTEZZA stuff */
else if (prev->oldChallenge && (prev->oldChallenge_retries++ > 3))
{
/*
* We already sent the authorization string and the
* nonce was expired -- auto-retry.
*/
if (!FE_Confirm(context, XP_GetString(XP_CONFIRM_PROXYAUTHOR_FAIL)))
return FALSE;
}
else if (prev->auth_type != AUTH_FORTEZZA)
{
/*
* We already sent the authorization string and it failed.
*/
if (!FE_Confirm(context, XP_GetString(XP_CONFIRM_PROXYAUTHOR_FAIL)))
return FALSE;
}
}
if (prev->auth_type == AUTH_FORTEZZA) {
SECStatus rv;
rv = HG26252
if ( rv != SECSuccess ) {
return(FALSE);
}
} else
{
username = prev->username;
password = prev->password;
len = PL_strlen(prev->realm) + PL_strlen(proxy_addr) + 50;
buf = (char*)PR_Malloc(len*sizeof(char));
if(buf)
{
PR_snprintf(buf, len*sizeof(char), XP_GetString( XP_PROXY_AUTH_REQUIRED_FOR ), prev->realm, proxy_addr);
NET_Progress(context, XP_GetString( XP_CONNECT_PLEASE_ENTER_PASSWORD_FOR_PROXY ) );
#if 1
#if defined(SingleSignon)
/* prefill prompt with previous username/passwords if any */
len = SI_PromptUsernameAndPassword
(context, buf, &username, &password, proxy_addr);
#else
len = FE_PromptUsernameAndPassword
(context, buf, &username, &password);
#endif
#else
/* the new multi-thread case -- we return with out user/pass */
len = stub_PromptUsernameAndPassword
(context, buf, &username, &password, closure);
#endif
PR_Free(buf);
}
else
{
len = 0;
}
if (!len)
{
TRACEMSG(("Waiting for user auth"));
return FALSE;
#if notused
TRACEMSG(("User canceled login!!!"));
return FALSE;
#endif /* notused */
}
else if (!username || !password)
{
return FALSE;
}
PR_FREEIF(prev->auth_string);
prev->auth_string = NULL; /* Generate a new one */
PR_FREEIF(prev->username);
prev->username = username;
PR_FREEIF(prev->password);
prev->password = password;
}
if (new_entry)
{
if (!net_proxy_auth_list)
{
net_proxy_auth_list = XP_ListNew();
if (!net_proxy_auth_list)
{
return TRUE;
}
}
XP_ListAddObjectToEnd(net_proxy_auth_list, prev);
}
return TRUE;
}
#if defined(CookieManagement)
/*
#include "htmldlgs.h"
extern int XP_CERT_PAGE_STRINGS;
extern int SA_REMOVE_BUTTON_LABEL;
// return TRUE if "number" is in sequence of comma-separated numbers
Bool net_InSequence(char* sequence, int number) {
char* ptr;
char* endptr;
char* undo = NULL;
Bool retval = FALSE;
int i;
// not necessary -- routine will work even with null sequence
if (!*sequence) {
return FALSE;
}
for (ptr = sequence ; ptr ; ptr = endptr) {
// get to next comma
endptr = PL_strchr(ptr, ',');
// if comma found, process it
if (endptr) {
// restore last comma-to-null back to comma
if (undo) {
*undo = ',';
}
// set the comma to a null
undo = endptr;
*endptr++ = '\0';
// compare the number before the comma with "number"
if (*ptr) {
i = atoi(ptr);
if (i == number) {
// "number" was in the sequence so return TRUE
retval = TRUE;
break;
}
}
}
}
// restore last comma-to-null back to comma
if (undo) {
*undo = ',';
}
return retval;
}
*/
/*
PR_STATIC_CALLBACK(PRBool)
net_AboutCookiesDialogDone(XPDialogState* state, char** argv, int argc,
unsigned int button)
{
XP_List *list;
net_CookieStruct *cookie;
net_CookiePermissionStruct *cookiePermission;
char *buttonName;
int cookieNumber;
net_CookieStruct *cookieToDelete = 0;
net_CookiePermissionStruct *cookiePermissionToDelete = 0;
char* gone;
buttonName = XP_FindValueInArgs("button", argv, argc);
if (button != XP_DIALOG_OK_BUTTON) {
// OK button not pressed (must be cancel button that was pressed)
return PR_FALSE;
}
// OK was pressed, do the deletions
// get the comma-separated sequence of cookies to be deleted
gone = XP_FindValueInArgs("goneC", argv, argc);
PR_ASSERT(gone);
if (!gone) {
return PR_FALSE;
}
// walk through the cookie list, deleting the designated cookies
// Note: we can't delete cookie while "list" is pointing to it because
// that would destroy "list". So we do a lazy deletion
//
net_lock_cookie_list();
list = net_cookie_list;
cookieNumber = 0;
while ( (cookie=(net_CookieStruct *) XP_ListNextObject(list)) ) {
if (net_InSequence(gone, cookieNumber)) {
if (cookieToDelete) {
net_FreeCookie(cookieToDelete);
}
cookieToDelete = cookie;
}
cookieNumber++;
}
if (cookieToDelete) {
net_FreeCookie(cookieToDelete);
cookies_changed = TRUE;
NET_SaveCookies(NULL);
}
net_unlock_cookie_list();
// get the comma-separated sequence of permissions to be deleted
gone = XP_FindValueInArgs("goneP", argv, argc);
PR_ASSERT(gone);
if (!gone) {
return PR_FALSE;
}
// walk through the cookie permission list, deleting the designated permissions
// Note: we can't delete permissions while "list" is pointing to it because
// that would destroy "list". So we do a lazy deletion
//
net_lock_cookie_permission_list();
list = net_cookie_permission_list;
cookieNumber = 0;
while ( (cookiePermission=(net_CookiePermissionStruct *) XP_ListNextObject(list)) ) {
if (net_InSequence(gone, cookieNumber)) {
if (cookiePermissionToDelete) {
net_FreeCookiePermission(cookiePermissionToDelete, TRUE);
}
cookiePermissionToDelete = cookiePermission;
}
cookieNumber++;
}
if (cookiePermissionToDelete) {
net_FreeCookiePermission(cookiePermissionToDelete, TRUE);
cookie_permissions_changed = TRUE;
net_SaveCookiePermissions(NULL);
}
net_unlock_cookie_permission_list();
return PR_FALSE;
}
*/
/*
PRIVATE Bool
CookieCompare (net_CookieStruct * cookie1, net_CookieStruct * cookie2) {
char * host1 = cookie1->host;
char * host2 = cookie2->host;
// get rid of leading period on host name, if any
if (*host1 == '.') {
host1++;
}
if (*host2 == '.') {
host2++;
}
// make decision based on host name if they are unequal
if (PL_strcmp (host1, host2) < 0) {
return -1;
}
if (PL_strcmp (host1, host2) > 0) {
return 1;
}
// if host names are equal, make decision based on cookie name
return (PL_strcmp (cookie1->name, cookie2->name));
}
*/
/*
* find the next cookie that is alphabetically after the specified cookie
* ordering is based on hostname and the cookie name
* if specified cookie is NULL, find the first cookie alphabetically
*/
/*
PRIVATE net_CookieStruct *
NextCookieAfter(net_CookieStruct * cookie, int * cookieNum) {
XP_List *cookie_list=net_cookie_list;
net_CookieStruct *cookie_ptr;
net_CookieStruct *lowestCookie = NULL;
int localCookieNum = 0;
int lowestCookieNum;
while ( (cookie_ptr=(net_CookieStruct *) XP_ListNextObject(cookie_list)) ) {
if (!cookie || (CookieCompare(cookie_ptr, cookie) > 0)) {
if (!lowestCookie ||
(CookieCompare(cookie_ptr, lowestCookie) < 0)) {
lowestCookie = cookie_ptr;
lowestCookieNum = localCookieNum;
}
}
localCookieNum++;
}
*cookieNum = lowestCookieNum;
return lowestCookie;
}
*/
/*
typedef struct _CookieViewerDialog CookieViewerDialog;
struct _CookieViewerDialog {
void *window;
void *parent_window;
PRBool dialogUp;
XPDialogState *state;
};
*/
#ifdef TRUST_LABELS
/* Purpose: given a cookie name look in the list containing the cookperm.txt
* file and locate a matching trust label. If a matching trust label
* is found then format a simple text string that describes the trust label
* information in a user friendly manner.
*
* If a matching label is not found return a string with a single space.
* The caller must free the string.
*
* History:
* 9/9/98 Paul Chek - switch recipient from a range to a single value
*/
/*
char *GetTrustLabelString(char *CookieName)
{
XP_List * list_ptr, *Tptr;
TrustEntry *TEntry;
net_CookiePermissionStruct *cookperm;
char *szTemp = NULL;
char *szPurpose = NULL;
char *szRecipient = NULL;
char *szBy = NULL;
int i, j;
// here's how we would like to write the code but it doesn't compile on the mac
//
// int PurposeIds[] = {MK_ACCESS_TL_PPH0, MK_ACCESS_TL_PPH1,
// MK_ACCESS_TL_PPH2, MK_ACCESS_TL_PPH3,
// MK_ACCESS_TL_PPH4, MK_ACCESS_TL_PPH5};
// int RecpIds[] = { MK_ACCESS_TL_RPH0, MK_ACCESS_TL_RPH1,
// MK_ACCESS_TL_RPH2, MK_ACCESS_TL_RPH3};
//
#define NumPurposeBits 6 // number of bits in the recipient value
int PurposeIds[NumPurposeBits];
#define NumRecpBits 4 // number of bits in the recipient value
// the list of msg Ids for the recipient value.
int RecpIds[NumRecpBits];
#if NumPurposeBits > NumRecpBits
#define NumStrs NumPurposeBits
#else
#define NumStrs NumRecpBits
#endif
// this array holds strings used in formatting the message
char *szTempStrs[ NumStrs ];
PurposeIds[0] = MK_ACCESS_TL_PPH0;
PurposeIds[1] = MK_ACCESS_TL_PPH1;
PurposeIds[2] = MK_ACCESS_TL_PPH2;
PurposeIds[3] = MK_ACCESS_TL_PPH3;
PurposeIds[4] = MK_ACCESS_TL_PPH4;
PurposeIds[5] = MK_ACCESS_TL_PPH5;
RecpIds[0] = MK_ACCESS_TL_RPH0;
RecpIds[1] = MK_ACCESS_TL_RPH1;
RecpIds[2] = MK_ACCESS_TL_RPH2;
RecpIds[3] = MK_ACCESS_TL_RPH3;
if( CookieName ) {
//look thru the cookie permission list for a matching trust label //
net_lock_cookie_permission_list();
list_ptr = net_cookie_permission_list;
while( szTemp == NULL &&
(cookperm = (net_CookiePermissionStruct *) XP_ListNextObject(list_ptr))!=0) {
//look thru the trust list for this cookie //
if (cookperm->TrustList ) {
Tptr = cookperm->TrustList;
while( (TEntry = (TrustEntry *)XP_ListNextObject(Tptr))) {
if( TEntry->CookieName
&& !PL_strcmp(CookieName, TEntry->CookieName)) {
// this permission entry matches the given cookie//
szTemp = (char*)PR_Malloc(BUFLEN);
break;
}
}
}
}
net_unlock_cookie_permission_list();
// was a match found??
if (szTemp) {
// yes convert the ratings info into user strings //
for( j=0; j<NumStrs; j++) {
szTempStrs[j] = NULL;
}
// count the number of purpose bits set AND
// make a list of the phrases to use
//
for (j=0,i=0; i<NumPurposeBits; i++) {
if ((TEntry->purpose>>i) & 1) {
//this bit is set get the associated phrase
szTempStrs[j++] = PL_strdup( XP_GetString( PurposeIds[i] ) );
}
}
// build the purpose string
// For translation purposes I am using strings
// of the form "This information is used for %1$s, %2$s and %3$s."
// and inserting the additional phrases in the formating.
switch ( j ) {
case 1:
PR_snprintf(szTemp, BUFLEN,
XP_GetString( MK_ACCESS_TL_PUR1 ),
szTempStrs[0]
);
break;
case 2:
PR_snprintf(szTemp, BUFLEN,
XP_GetString( MK_ACCESS_TL_PUR2 ),
szTempStrs[0],
szTempStrs[1]
);
break;
case 3:
PR_snprintf(szTemp, BUFLEN,
XP_GetString( MK_ACCESS_TL_PUR3 ),
szTempStrs[0],
szTempStrs[1],
szTempStrs[2]
);
break;
case 4:
PR_snprintf(szTemp, BUFLEN,
XP_GetString( MK_ACCESS_TL_PUR4 ),
szTempStrs[0],
szTempStrs[1],
szTempStrs[2],
szTempStrs[3]
);
break;
case 5:
PR_snprintf(szTemp, BUFLEN,
XP_GetString( MK_ACCESS_TL_PUR5 ),
szTempStrs[0],
szTempStrs[1],
szTempStrs[2],
szTempStrs[3],
szTempStrs[4]
);
break;
case 6:
PR_snprintf(szTemp, BUFLEN,
XP_GetString( MK_ACCESS_TL_PUR6 ),
szTempStrs[0],
szTempStrs[1],
szTempStrs[2],
szTempStrs[3],
szTempStrs[4],
szTempStrs[5]
);
break;
} // switch ( j )
// I did things this way to avoid buffer overflow problems
szPurpose = PL_strdup( szTemp );
// free the temporary strings
for( j=0; j<NumStrs; j++) {
PR_FREEIF(szTempStrs[j]);
szTempStrs[j] = NULL;
}
// second, build the recipient phrase list. The recipients value as
// ossolated between allowing a range of values (0:2) and a single
// value, thats the reason for the ifdef'd code.
#ifndef RECIPIENT_RANGE
szTempStrs[0] = PL_strdup( XP_GetString( RecpIds[ TEntry->recipient] ) );
PR_snprintf(szTemp, BUFLEN,
XP_GetString( MK_ACCESS_TL_RECP1 ),
szTempStrs[0]
);
PR_FREEIF(szTempStrs[0]);
szRecipient = PL_strdup( szTemp );
#else
// is just a single bit set and is that bit 0 ?
// if RECIPIENT_RANGE is defined you will need to
// include these lines in allxpstr.h
// ResDef(MK_ACCESS_TL_RECP2, (TRUST_LABEL_BASE + 17),
// "It is %1$s and %2$s." )
// ResDef(MK_ACCESS_TL_RECP3, (TRUST_LABEL_BASE + 18),
// "It is %1$s, %2$s and %3$s." )
///
if ( TEntry->recipient == 1 ) {
szTempStrs[0] = PL_strdup( XP_GetString( MK_ACCESS_TL_RPH0 ) );
PR_snprintf(szTemp, BUFLEN,
XP_GetString( MK_ACCESS_TL_RECP1 ),
szTempStrs[0]
);
} else {
// if bits other than bit 0 are set then dont
// output the "used only by this site" text
//
// count the number of purpose bits set AND
// make a list of the phrases to use
///
for (j=0,i=1; i<NumRecpBits; i++) {
if ((TEntry->recipient>>i) & 1) {
// this bit is set get the associated phrase
szTempStrs[j++] = PL_strdup( XP_GetString( RecpIds[i] ) );
}
}
// format the recipient string according to the
// number of bits set
//
switch ( j ) {
case 1:
PR_snprintf(szTemp, BUFLEN,
XP_GetString( MK_ACCESS_TL_RECP1 ),
szTempStrs[0]
);
break;
case 2:
PR_snprintf(szTemp, BUFLEN,
XP_GetString( MK_ACCESS_TL_RECP2 ),
szTempStrs[0],
szTempStrs[1]
);
break;
case 3:
PR_snprintf(szTemp, BUFLEN,
XP_GetString( MK_ACCESS_TL_RECP3 ),
szTempStrs[0],
szTempStrs[1],
szTempStrs[2]
);
break;
} // switch ( j )
}
// I did things this way to avoid buffer overflow problems
szRecipient = PL_strdup( szTemp );
// free the temporary strings
for( j=0; j<NumStrs; j++) {
PR_FREEIF(szTempStrs[j]);
szTempStrs[j] = NULL;
}
#endif
//construct the by string
if (TEntry->by) {
PR_snprintf(szTemp, BUFLEN, XP_GetString(MK_ACCESS_TL_BY), TEntry->by);
szBy = PL_strdup( szTemp );
} else {
szBy = PL_strdup( " " );
}
// construct the entire trust label statement.
// WATCHOUT: you can only execute four XP_GetString calls
// in this format string.
//
PR_snprintf(szTemp, BUFLEN,
"%s " // identifiable text
"%s " // purpose string
"%s " /// receipent
"%s", // by string
(TEntry->bIdentifiable
? XP_GetString(MK_ACCESS_TL_ID1)
: XP_GetString(MK_ACCESS_TL_ID0)),
szPurpose, szRecipient, szBy);
}
}
PR_FREEIF(szPurpose);
PR_FREEIF(szRecipient);
PR_FREEIF(szBy);
return szTemp;
}
*/
/*
#define STR_TRUST_LABEL "(TrustLabel"
// these structures describe the layout of the trust label information in
// the cookperm.txt. The structures are used for both reading and writing the
// file.
//
enum {TYPE_QUOTED_STRING, TYPE_INT};
typedef struct {
char *szMatchStr; // the string to look for coming in
int ValueType; // what kind of thing the value is
int DataOffset; // where in the TrustEntry struct to store the value
} ParseItem;
static ParseItem ParseData[] = {
{"cookie", TYPE_QUOTED_STRING, offsetof(TrustEntry, CookieName)},
{"purpose", TYPE_INT, offsetof(TrustEntry, purpose)},
{"id", TYPE_INT, offsetof(TrustEntry, bIdentifiable)},
{"recipient", TYPE_INT, offsetof(TrustEntry, recipient)},
{"by", TYPE_QUOTED_STRING, offsetof(TrustEntry, by)},
//the timestamp is the date and time when the cookie was set.
// It is in the form "14 Apr 89 03:20 GMT". Use PR_ParseTimeString
// to parse it into a PR_Exploded time.
//
{"timestamp", TYPE_QUOTED_STRING, offsetof(TrustEntry, CookieSet)}
};
#define NUM_ITEMS sizeof(ParseData) / sizeof( ParseItem)
*/
/******************************************************
* Purpose: parse all the trust label string from a line in
* cookperm.txt and store the result in a net_CookiePermissionStruct.
*
* This is a simple table driven parser.
******************************************************/
/*
PRIVATE
void ParseTrustLabelInfo
(char *Buf, net_CookiePermissionStruct * cookie_permission)
{
char *pToken, *p, *pEnd, *pSub;
int i, k, len;
Bool Status = FALSE;
char *pChar, *szTemp;
char *pCopy = NULL;
TrustEntry *TEntry;
// Look for the trust label information which is in the form
// "(TrustLabel" - must be the first token
// "cookie:"<cookie name>
// "purpose:"<purpose value>
// "id:"<"0"|"1">
// "recipient:"<recipient value>
// "by:"<by value>
// "timestamp:"<timestamp>
// ")" - must be the last token
// purpose value == a hex value corresponding to the purpose value to set
// recipient value == a hex value corresponding to the recipient value to set
// by value == a text string enclosed in double quotes
// timestamp == time when the cookie was set: format is quoted string in any of the
// formats that PR_Time will accept.
// cookie name == the name of the cookie enclosed in quotes
//
// The middle tokens can be in any order.
///
// Do I have a well formed trust label string ??
// - can I find a beginning and an end??
//
p = Buf;
while ((p=strcasestr(p, (char *)STR_TRUST_LABEL)) && (pEnd=strchr(p,')'))) {
p += PL_strlen(STR_TRUST_LABEL);
// Allocate a new trust Entry
TEntry = PR_NEW(TrustEntry);
if (TEntry) {
// init the elements
TEntry->CookieName = NULL;
TEntry->purpose = 0;
TEntry->recipient = 0;
TEntry->bIdentifiable = FALSE;
TEntry->by = NULL;
TEntry->CookieSet = NULL;
// isolate this trust label string for parsing, I must make a copy
// of the incoming string because the tokenizer will add nulls to it.
// Also allocate one more byte than I really need so that the tokenizer
// can write an extra Null at the end.
//
len = pEnd-p+1;
pCopy = XP_ALLOC(len + 1);
if (!pCopy) return;
XP_MEMCPY(pCopy, p, len-1);
pCopy[len] = '\0';
// get the first token from the copy
pToken = XP_STRTOK_R(pCopy, " :", &pSub);
while (pToken) {
if (pToken != ")") {
for ( i=0; i<NUM_ITEMS; i++ ) {
// Is this token one that we are interested in ??
if (PL_strcasecmp(pToken, ParseData[i].szMatchStr) == 0) {
// yes - extract its associated value and store it
switch(ParseData[i].ValueType) {
case TYPE_QUOTED_STRING:
/// since I allow white space INSIDE the
// quoted string, AND I want the next token
// to contain all the stuff inside the
// quoted string; I need to eat all the
// whitespace between the : and the
// next "
///
while(*pSub == ' ' || *pSub == '\t') {
pSub++;
}
// get next token which should be "
pToken = XP_STRTOK_R(nil, "\"", &pSub );
if (pToken) {
pChar = (char *)((void *)(TEntry))
+ ParseData[i].DataOffset;
szTemp = PL_strdup(pToken);
XP_MEMCPY((void *)pChar,
(void *)&szTemp,
sizeof(char *) );
}
break;
case TYPE_INT:
// get the next token which should be some
// number
//
pToken = XP_STRTOK_R(nil, " ", &pSub );
if (pToken) {
pChar = (char *)((void *)(TEntry))
+ ParseData[i].DataOffset;
k = XP_ATOI( pToken );
XP_MEMCPY((void *)pChar,
(void *)&k, sizeof(int));
}
break;
}
break; // break out of the for loop
}
}
} else {
// all done
break;
}
pToken = XP_STRTOK_R(nil, " :", &pSub ); // get the next token
} // end while
PR_FREEIF( pCopy );
// Does the trust list exist in this entry, if not create it
if(!cookie_permission->TrustList) {
cookie_permission->TrustList = XP_ListNew();
if(!cookie_permission->TrustList) {
return;
}
}
// add the entry to the list in the permission entry
XP_ListAddObjectToEnd( cookie_permission->TrustList, TEntry );
} //end if (TEntry)
// set up for the next entry
p = ++pEnd;
} // end while ((p=strcasestr(
return;
}
*/
/****************************************************************
* Purpose: Write the trust label information from the permission
* list to cookperm.txt
*
* History:
* Paul Chek - initial creation
****************************************************************/
/*
PRIVATE
void SaveTrustLabelData
( net_CookiePermissionStruct * cookie_permission, XP_File fp )
{
XP_List *Tptr;
TrustEntry *TEntry;
char *szTemp;
char *szTemp2;
char **pChar;
int *pInt;
int T2Size = 50;
int len, i;
// do an initial allocation for szTemp2. Whenever a quoted string
// is processed the size of szTemp2 is tested to make sure it is big enough,
// if it is not it is resized.
//
szTemp2 = XP_ALLOC( T2Size );
if ( fp && cookie_permission && cookie_permission->TrustList && szTemp2 ) {
// there is trust label information, write it
Tptr = cookie_permission->TrustList;
while( (TEntry = (TrustEntry *)XP_ListNextObject(Tptr))) {
// build the string up one piece at a time, its slower but safer
szTemp = NULL;
StrAllocCopy( szTemp, " "STR_TRUST_LABEL);
// march thru the Parsing table and output the TrustLabel information
for ( i=0; i<NUM_ITEMS; i++ ) {
switch(ParseData[i].ValueType) {
case TYPE_QUOTED_STRING:
pChar = (char **)(((char *)TEntry)+ ParseData[i].DataOffset);
if ( PL_strlen( *pChar ) ) {
// make sure szTemp2 is big enough.
len = PL_strlen( ParseData[i].szMatchStr ) + PL_strlen(*pChar) + 3;
if ( T2Size <= len ) {
T2Size = len +50;
szTemp2 = XP_REALLOC( szTemp2, T2Size );
}
if ( szTemp2 ) {
PR_snprintf( szTemp2, T2Size, " %s:\"%s\"",
ParseData[i].szMatchStr, *pChar );
StrAllocCat( szTemp, szTemp2 );
} else {
// error reallocating szTemp2, blast out
PR_FREEIF( szTemp );
return;
}
}
break;
case TYPE_INT:
pInt = (int *)(((char *)TEntry)+ ParseData[i].DataOffset);
PR_snprintf( szTemp2, T2Size, " %s:%d",
ParseData[i].szMatchStr, *pInt );
StrAllocCat( szTemp, szTemp2 );
break;
}
} // end for
StrAllocCat( szTemp, " )" ); // add the termination paren
// write a single trust label string
NET_XP_FileWrite(szTemp, -1, fp);
PR_FREEIF( szTemp );
} // end while( (TEntry =
PR_FREEIF( szTemp2 );
}
}
*/
/****************************************************************
* Purpose: search for a TrustEntry in the trust list of a cookie
* permission entry.
*
* History:
* Paul Chek - initial creation
****************************************************************/
/*
PRIVATE
Bool FindTrustEntry( char *CookieName, XP_List *TList, TrustEntry **TheEntry )
{
TrustEntry *TEntry;
XP_List *TPtr;
Bool Status = FALSE;
if ( TList && !XP_ListIsEmpty( TList ) ) {
TPtr = TList;
while( (TEntry = (TrustEntry *)XP_ListNextObject(TPtr))) {
if (PL_strcasecmp(CookieName, TEntry->CookieName) == 0) {
// the entry was found
*TheEntry = TEntry;
Status = TRUE;
break;
}
}
}
return Status;
}
*/
/****************************************************************
* Purpose: given a TrustLabel struct sat up the corresponding TrustEntry
*
* History:
* Paul Chek - initial creation
****************************************************************/
/*
PRIVATE
void CopyTrustEntry( char *CookieName, TrustEntry *TEntry, TrustLabel *trustlabel )
{
PRExplodedTime now;
char line[100];
if ( TEntry && trustlabel ) {
PR_FREEIF(TEntry->CookieName);
PR_FREEIF(TEntry->by);
PR_FREEIF(TEntry->CookieSet);
TEntry->CookieName = PL_strdup( CookieName );
TEntry->purpose = trustlabel->purpose;
TEntry->recipient = trustlabel->recipients;
TEntry->bIdentifiable = trustlabel->ID;
TEntry->by = PL_strdup( trustlabel->szBy );
// format an ASCII timestamp for when the cookie was set. Use a
//format that PR_ParseTimeString supports. "22-AUG-1993 10:59 PM"
//
PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &now);
PR_FormatTimeUSEnglish(line, 400, "%d-%b-%Y %I:%M %p", &now);
TEntry->CookieSet = PL_strdup( line );
}
}
*/
/****************************************************************
* Purpose: look in the permissions list to see if there is
* trust label information for the cookie. If so delete it.
*
* History:
* Paul Chek - initial creation
****************************************************************/
/*
PRIVATE
void DeleteCookieFromPermissions( char *CookieHost, char *CookieName )
{
XP_List *TmpList;
TrustEntry *TEntry;
net_CookiePermissionStruct * cookie_permission;
// lock the permission list
TmpList=net_cookie_permission_list;
net_lock_cookie_permission_list();
while ( (cookie_permission=(net_CookiePermissionStruct *)XP_ListNextObject(TmpList)) ) {
// is this the corect host for the cookie */
if (PL_strcasecmp(CookieHost, cookie_permission->host) == 0) {
// yes - see if there is a trust label entry for the cookie
if ( FindTrustEntry( CookieName, cookie_permission->TrustList, &TEntry ) ) {
// yes there is - delete it */
XP_ListRemoveObject( cookie_permission->TrustList, TEntry);
// free the strings in the entry
PR_FREEIF(TEntry->CookieName);
PR_FREEIF(TEntry->by);
PR_FREEIF(TEntry->CookieSet);
}
// dont need to look in the list anymore cause there is only one entry per host
break;
}
}
net_unlock_cookie_permission_list();
}
*/
/****************************************************************
* Purpose: given a TrustLabel struct containing the trust label
* info that matches a particular cookie add the trust
* label info to the cookie permission list
*
* History:
* Paul Chek - initial creation
****************************************************************/
/*
PRIVATE
void AddTrustLabelInfo( char *CookieName, TrustLabel *trustlabel )
{
XP_List *TmpList;
TrustEntry *TEntry;
net_CookiePermissionStruct * cookie_permission;
// lock the permission list //
TmpList=net_cookie_permission_list;
net_lock_cookie_permission_list();
while ( (cookie_permission=(net_CookiePermissionStruct *)XP_ListNextObject(TmpList)) ) {
// is this the corect host for the cookie
if (PL_strcasecmp(trustlabel->domainName, cookie_permission->host) == 0) {
// OK - we have found the entry for this host. Look thru the trust list
// to see if we have an existing entry for this cookie. If so replace it.
// If not add a new entry
//
if ( FindTrustEntry( CookieName, cookie_permission->TrustList, &TEntry ) ) {
//the entry exists modify it
CopyTrustEntry( CookieName, TEntry, trustlabel );
} else {
// the entry does NOT exist - add a new one
TEntry = PR_NEWZAP( TrustEntry );
if ( TEntry ) {
// yes - build the entry for the cookie
CopyTrustEntry( CookieName, TEntry, trustlabel );
// Does the trust list exist in this entry, if not create it
if(!cookie_permission->TrustList) {
cookie_permission->TrustList = XP_ListNew();
if(!cookie_permission->TrustList) {
return;
}
}
// add it to the list
XP_ListAddObjectToEnd(cookie_permission->TrustList, TEntry);
break; // all done
}
}
}
}
net_unlock_cookie_permission_list();
}
*/
#endif
/*
* return a string that has each " of the argument sting
* replaced with \" so it can be used inside a quoted string
*/
PRIVATE char*
net_FixQuoted(char* s) {
char * result;
int count = PL_strlen(s);
char *quote = s;
unsigned int i, j;
while (quote = PL_strchr(quote, '"')) {
count = count++;
quote++;
}
result = XP_ALLOC(count + 1);
for (i=0, j=0; i<PL_strlen(s); i++) {
if (s[i] == '"') {
result[i+(j++)] = '\\';
}
result[i+j] = s[i];
}
result[i+j] = '\0';
return result;
}
#ifdef XP_MAC
/* pinkerton - if we don't do this, it won't compile because it runs out of registers */
#pragma global_optimizer on
#endif
/*
PRIVATE void
net_DisplayCookieInfoAsHTML(MWContext *context, char* host)
{
char *buffer = (char*)PR_Malloc(BUFLEN);
char *buffer2 = 0;
int g = 0, count, cookieNum;
XP_List *cookie_list;
XP_List *cookie_permission_list;
net_CookieStruct *cookie;
net_CookiePermissionStruct *cookperm;
CookieViewerDialog *dlg;
int i;
char * view_sites = NULL;
char * view_cookies = NULL;
char * heading = NULL;
#ifdef TRUST_LABELS
char * szTrustLabel = NULL;
#endif
static XPDialogInfo dialogInfo = {
0,
net_AboutCookiesDialogDone,
600,
400
};
XPDialogStrings* strings;
strings = XP_GetDialogStrings(XP_CERT_PAGE_STRINGS);
if (!strings) {
return;
}
StrAllocCopy(buffer2, "");
StrAllocCopy (view_cookies, XP_GetString(MK_ACCESS_VIEW_COOKIES));
StrAllocCopy (view_sites, XP_GetString(MK_ACCESS_VIEW_SITES));
// generate initial section of html file
g += PR_snprintf(buffer+g, BUFLEN-g,
"<HTML>\n"
"<HEAD>\n"
" <TITLE>Cookies</TITLE>\n"
" <SCRIPT>\n"
" index_frame = 0;\n"
" title_frame = 1;\n"
" spacer1_frame = 2;\n"
" list_frame = 3;\n"
" spacer2_frame = 4;\n"
" prop_frame = 5;\n"
" spacer3_frame = 6;\n"
" button_frame = 7;\n"
"\n"
" var cookie_mode;\n"
" var goneC;\n"
" var goneP;\n"
" deleted_cookies = new Array (0"
);
FLUSH_BUFFER
//fill in initial 0's for deleted_cookies and deleted_sites arrays
count = XP_ListCount(net_cookie_list);
for (i=1; i<count; i++) {
g += PR_snprintf(buffer+g, BUFLEN-g,
",0"
);
if ((i%50) == 0) {
g += PR_snprintf(buffer+g, BUFLEN-g,
"\n "
);
}
}
g += PR_snprintf(buffer+g, BUFLEN-g,
");\n"
" deleted_sites = new Array (0"
);
count = XP_ListCount(net_cookie_permission_list);
for (i=1; i<count; i++) {
g += PR_snprintf(buffer+g, BUFLEN-g,
",0"
);
if ((i%50) == 0) {
g += PR_snprintf(buffer+g, BUFLEN-g,
"\n "
);
}
}
FLUSH_BUFFER
g += PR_snprintf(buffer+g, BUFLEN-g,
");\n"
"\n"
" function DeleteItemSelected() {\n"
" if (cookie_mode) {\n"
" DeleteCookieSelected();\n"
" } else {\n"
" DeleteSiteSelected();\n"
" }\n"
" }\n"
"\n"
" function DeleteCookieSelected() {\n"
" selname = top.frames[list_frame].document.fSelectCookie.selname;\n"
" goneC = top.frames[button_frame].document.buttons.goneC;\n"
" var p;\n"
" var i;\n"
" for (i=selname.options.length; i>0; i--) {\n"
" if (selname.options[i-1].selected) {\n"
" selname.options[i-1].selected = 0;\n"
" goneC.value = goneC.value + selname.options[i-1].value + \",\";\n"
" deleted_cookies[selname.options[i-1].value] = 1;\n"
" for (j=i ; j<selname.options.length ; j++) {\n"
" selname.options[j-1] = selname.options[j];\n"
" }\n"
" selname.options[selname.options.length-1] = null;\n"
" }\n"
" }\n"
" top.frames[prop_frame].document.open();\n"
" top.frames[prop_frame].document.close();\n"
" }\n"
"\n"
" function DeleteSiteSelected() {\n"
" selname = top.frames[list_frame].document.fSelectSite.selname;\n"
" goneP = top.frames[button_frame].document.buttons.goneP;\n"
" var p;\n"
" var i;\n"
" for (i=selname.options.length; i>0; i--) {\n"
" if (selname.options[i-1].selected) {\n"
" selname.options[i-1].selected = 0;\n"
" goneP.value = goneP.value + selname.options[i-1].value + \",\";\n"
" deleted_sites[selname.options[i-1].value] = 1;\n"
" for (j=i; j < selname.options.length; j++) {\n"
" selname.options[j-1] = selname.options[j];\n"
" }\n"
" selname.options[selname.options.length-1] = null;\n"
" }\n"
" }\n"
" top.frames[prop_frame].document.open();\n"
" top.frames[prop_frame].document.close();\n"
" }\n"
"\n"
" function ViewCookieSelected(selCookie) {\n"
" selname = top.frames[list_frame].document.fSelectCookie.selname;\n"
" top.frames[prop_frame].document.open();\n"
" switch (selname.options[selCookie].value) {\n"
);
FLUSH_BUFFER
// Get rid of any expired cookies now so user doesn't
// think/see that we're keeping cookies in memory.
//
net_lock_cookie_list();
net_remove_expired_cookies();
// Generate the html for the cookie properties (alphabetical order)
cookie_list=net_cookie_list;
cookie = NULL;
while (cookie = NextCookieAfter(cookie, &cookieNum)) {
char * name = NULL;
char * value = NULL;
char * domain_or_host = NULL;
char * path = NULL;
char * secure = NULL;
char * yes_or_no = NULL;
char * expires = NULL;
char * expireDate = NULL;
char *fixed_name = net_FixQuoted(cookie->name);
char *fixed_value = net_FixQuoted(cookie->cookie);
char *fixed_domain_or_host = net_FixQuoted(cookie->host);
char *fixed_path = net_FixQuoted(cookie->path);
StrAllocCopy (name, XP_GetString(MK_ACCESS_NAME));
StrAllocCopy (value, XP_GetString(MK_ACCESS_VALUE));
StrAllocCopy (domain_or_host,
cookie->is_domain
? XP_GetString(MK_ACCESS_DOMAIN)
: XP_GetString(MK_ACCESS_HOST));
StrAllocCopy (path, XP_GetString(MK_ACCESS_PATH));
StrAllocCopy (secure, XP_GetString(MK_ACCESS_SECURE));
StrAllocCopy (yes_or_no,
HG78111
? XP_GetString(MK_ACCESS_YES)
: XP_GetString(MK_ACCESS_NO));
StrAllocCopy (expires, XP_GetString(MK_ACCESS_EXPIRES));
StrAllocCopy (expireDate,
cookie->expires
? ctime(&(cookie->expires))
: XP_GetString(MK_ACCESS_END_OF_SESSION));
if (!expireDate) {
StrAllocCopy (expireDate, "");
} else if (expireDate[PL_strlen(expireDate)-1] == '\n') {
expireDate[PL_strlen(expireDate)-1] = ' ';
}
g += PR_snprintf(buffer+g, BUFLEN-g,
" case %d:\n"
" top.frames[prop_frame].document.write(\n"
" \"<NOBR><b>%s</b> %s</NOBR><BR>\" +\n"
" \"<NOBR><b>%s</b> %s</NOBR><BR>\" +\n"
" \"<NOBR><b>%s</b> %s</NOBR><BR>\" +\n"
" \"<NOBR><b>%s</b> %s</NOBR><BR>\" +\n"
" \"<NOBR><b>%s</b> %s</NOBR><BR>\" +\n"
" \"<NOBR><b>%s</b> %s</NOBR><BR>\" ",
cookieNum,
name, fixed_name,
value, fixed_value,
domain_or_host, fixed_domain_or_host,
path, fixed_path,
secure, yes_or_no,
expires, expireDate
);
FLUSH_BUFFER
PR_FREEIF(fixed_name);
PR_FREEIF(fixed_value);
PR_FREEIF(fixed_domain_or_host);
PR_FREEIF(fixed_path);
PR_FREEIF(name);
PR_FREEIF(value);
PR_FREEIF(domain_or_host);
PR_FREEIF(path);
PR_FREEIF(secure);
PR_FREEIF(yes_or_no);
PR_FREEIF(expires);
PR_FREEIF(expireDate);
// caveat: It would have been simpler to not allocate and free the
// above strings but rather just use the XP_GetString(...) parameters
// in the call to PR_snprintf. However there are only four buffers
// that XP_GetString uses and it keeps recycling them. Since the
// above would require more than four parameters which are calls to
// XP_GetString, some of the returned buffers would be overwritten
// before they could be used. Hence the simpler approach wouldn't work
//
#ifdef TRUST_LABELS
// add an entry that contains the trust label information
szTrustLabel = GetTrustLabelString( cookie->name );
if ( szTrustLabel ) {
g += PR_snprintf(buffer+g, BUFLEN-g,
"+\n"
" \"<HR WIDTH=100%> <FONT SIZE=2> %s </FONT>\"",
szTrustLabel);
PR_FREEIF(szTrustLabel);
}
#endif
g += PR_snprintf(buffer+g, BUFLEN-g,
"\n"
" );\n"
" break;\n"
);
FLUSH_BUFFER
}
// generate next section of html file
g += PR_snprintf(buffer+g, BUFLEN-g,
" }\n"
" top.frames[prop_frame].document.close();\n"
" }\n"
"\n"
" function loadCookies(){\n"
" cookie_mode = 1;\n"
);
FLUSH_BUFFER
// generate index frame only if full viewer
if (!host) {
g += PR_snprintf(buffer+g, BUFLEN-g,
" top.frames[index_frame].document.open();\n"
" top.frames[index_frame].document.write(\n"
" \"<BODY BGCOLOR=#C0C0C0>\" +\n"
" \"<TABLE BORDER=0 WIDTH=100%>\" +\n"
" \"<TR>\" +\n"
" \"<TD> <SPACER TYPE=HORIZONTAL SIZE=10> </TD>\" +\n"
" \"<TD ALIGN=CENTER VALIGN=MIDDLE BGCOLOR=#FFFFFF>\" +\n"
" \"<FONT SIZE=2 COLOR=#666666>\" +\n"
" \"<B>%s</B>\" +\n"
" \"</FONT>\" +\n"
" \"</TD>\" +\n"
" \"<TD>&nbsp;&nbsp;&nbsp;</TD>\" +\n"
" \"<TD ALIGN=CENTER VALIGN=MIDDLE BGCOLOR=#C0C0C0>\" +\n"
" \"<A HREF=javascript:top.loadSites();>\" +\n"
" \"<FONT SIZE=2>%s</FONT>\" +\n"
" \"</A>\" +\n"
" \"</TD>\" +\n"
" \"<TD>&nbsp;&nbsp;&nbsp;</TD>\" +\n"
" \"</TR>\" +\n"
" \"</TABLE>\" +\n"
" \"</BODY>\"\n"
" );\n"
" top.frames[index_frame].document.close();\n"
"\n",
view_cookies, view_sites);
FLUSH_BUFFER
}
// generate next section of html file
if (!host) {
StrAllocCopy (heading, XP_GetString(MK_ACCESS_COOKIES_ACCEPTED));
} else {
StrAllocCopy (heading, XP_GetString(MK_ACCESS_SITE_COOKIES_ACCEPTED));
}
g += PR_snprintf(buffer+g, BUFLEN-g,
" top.frames[title_frame].document.open();\n"
" top.frames[title_frame].document.write\n"
" (\"&nbsp;%s\");\n"
" top.frames[title_frame].document.close();\n"
"\n"
" top.frames[list_frame].document.open();\n"
" top.frames[list_frame].document.write(\n"
" \"<FORM name=fSelectCookie>\" +\n"
" \"<P>\" +\n"
" \"<TABLE BORDER=0 WIDTH=100% HEIGHT=95%>\" +\n"
" \"<TR>\" +\n"
" \"<TD WIDTH=100% VALIGN=TOP>\" +\n"
" \"<CENTER>\" +\n"
" \"<P>\" +\n"
" \"<SELECT NAME=selname \" +\n"
" \"SIZE=15 \" +\n"
" \"MULTIPLE \" +\n"
" \"onchange=top.ViewCookieSelected(selname.selectedIndex);>\"\n"
" );\n",
heading);
FLUSH_BUFFER
PR_FREEIF(heading);
// generate the html for the list of cookies in alphabetical order
cookie_list=net_cookie_list;
cookie = NULL;
while (cookie = NextCookieAfter(cookie, &cookieNum)) {
if (!host || net_CookieIsFromHost(cookie, host)) {
char *fixed_name = net_FixQuoted(cookie->name);
g += PR_snprintf(buffer+g, BUFLEN-g,
" if (!deleted_cookies[%d]) {\n"
" top.frames[list_frame].document.write(\n"
" \"<OPTION value=%d>\" +\n"
" \"%s:%s\" +\n"
" \"</OPTION>\"\n"
" );\n"
" }\n",
cookieNum, cookieNum,
(*(cookie->host)=='.') ? (cookie->host)+1: cookie->host,
fixed_name
);
FLUSH_BUFFER
PR_FREEIF(fixed_name);
}
}
net_unlock_cookie_list();
// generate next section of html file
StrAllocCopy (heading, XP_GetString(MK_ACCESS_COOKIES_PERMISSION));
g += PR_snprintf(buffer+g, BUFLEN-g,
" top.frames[list_frame].document.write(\n"
" \"</SELECT>\" +\n"
" \"</CENTER>\" +\n"
" \"</TD>\" +\n"
" \"</TR>\" +\n"
" \"</TABLE>\" +\n"
" \"</FORM>\"\n"
" );\n"
" top.frames[list_frame].document.close();\n"
"\n"
" top.frames[prop_frame].document.open();\n"
" top.frames[prop_frame].document.close();\n"
" }\n"
"\n"
" function loadSites(){\n"
" cookie_mode = 0;\n"
" top.frames[index_frame].document.open();\n"
" top.frames[index_frame].document.write(\n"
" \"<BODY BGCOLOR=#C0C0C0>\" +\n"
" \"<TABLE BORDER=0 WIDTH=100%>\" +\n"
" \"<TR>\" +\n"
" \"<TD> <SPACER TYPE=HORIZONTAL SIZE=10> </TD>\" +\n"
" \"<TD ALIGN=CENTER VALIGN=MIDDLE BGCOLOR=#C0C0C0>\" +\n"
" \"<A HREF=javascript:top.loadCookies();>\" +\n"
" \"<FONT SIZE=2>%s</FONT>\" +\n"
" \"</A>\" +\n"
" \"</TD>\" +\n"
" \"<TD>&nbsp;&nbsp;&nbsp;</TD>\" +\n"
" \"<TD ALIGN=CENTER VALIGN=MIDDLE BGCOLOR=#FFFFFF>\" +\n"
" \"<FONT SIZE=2 COLOR=#666666>\" +\n"
" \"<B>%s</B>\" +\n"
" \"</FONT>\" +\n"
" \"</TD>\" +\n"
" \"<TD>&nbsp;&nbsp;&nbsp;</TD>\" +\n"
" \"</TR>\" +\n"
" \"</TABLE>\" +\n"
" \"</BODY>\"\n"
" );\n"
" top.frames[index_frame].document.close();\n"
"\n"
" top.frames[title_frame].document.open();\n"
" top.frames[title_frame].document.write\n"
" (\"&nbsp;%s\");\n"
" top.frames[title_frame].document.close();\n"
"\n"
" top.frames[list_frame].document.open();\n"
" top.frames[list_frame].document.write(\n"
" \"<FORM name=fSelectSite>\" +\n"
" \"<P>\" +\n"
" \"<TABLE BORDER=0 WIDTH=100% HEIGHT=95%>\" +\n"
" \"<TR>\" +\n"
" \"<TD WIDTH=100% VALIGN=TOP>\" +\n"
" \"<CENTER>\" +\n"
" \"<P>\" +\n"
" \"<SELECT NAME=selname SIZE=15 MULTIPLE> \"\n"
" );\n",
view_cookies, view_sites, heading);
FLUSH_BUFFER
PR_FREEIF(heading);
FLUSH_BUFFER
// generate the html for the list of cookie permissions
cookieNum = 0;
cookie_permission_list=net_cookie_permission_list;
net_lock_cookie_permission_list();
while ( (cookperm=(net_CookiePermissionStruct *)
XP_ListNextObject(cookie_permission_list)) ) {
g += PR_snprintf(buffer+g, BUFLEN-g,
" if (!deleted_sites[%d]) {\n"
" top.frames[list_frame].document.write(\n"
" \"<OPTION value=\" +\n"
" \"%d>\" +\n"
" \"%s %s\" +\n"
" \"</OPTION>\"\n"
" );\n"
" }\n",
cookieNum, cookieNum,
cookperm->permission ? "+" : "-",
cookperm->host);
FLUSH_BUFFER
cookieNum++;
}
net_unlock_cookie_permission_list();
// generate next section of html file
g += PR_snprintf(buffer+g, BUFLEN-g,
" top.frames[list_frame].document.write(\n"
" \"</SELECT>\" +\n"
" \"</CENTER>\" +\n"
" \"</TD>\" +\n"
" \"</TR>\" +\n"
" \"</TABLE>\" +\n"
" \"</FORM>\"\n"
" );\n"
" top.frames[list_frame].document.close();\n"
"\n"
" top.frames[prop_frame].document.open();\n"
" top.frames[prop_frame].document.close();\n"
" }\n"
"\n"
" function loadButtons(){\n"
" top.frames[button_frame].document.open();\n"
" top.frames[button_frame].document.write(\n"
" \"<FORM name=buttons action=internal-cookieViewer-handler method=post>\" +\n"
" \"<BR>\" +\n"
" \"&nbsp;\" +\n"
" \"<INPUT type=BUTTON \" +\n"
" \"value=Remove \" +\n"
" \"onclick=top.DeleteItemSelected();>\" +\n"
" \"<DIV align=right>\" +\n"
" \"<INPUT type=BUTTON value=OK width=80 onclick=parent.clicker(this,window.parent)>\" +\n"
" \" &nbsp;&nbsp;\" +\n"
" \"<INPUT type=BUTTON value=Cancel width=80 onclick=parent.clicker(this,window.parent)>\" +\n"
" \"</DIV>\" +\n"
" \"<INPUT type=HIDDEN name=xxxbuttonxxx>\" +\n"
" \"<INPUT type=HIDDEN name=handle value="
);
FLUSH_BUFFER
// transfer what we have so far into strings->args[0]
if (buffer2) {
XP_SetDialogString(strings, 0, buffer2);
buffer2 = NULL;
}
//Note: strings->args[1] will later be filled in with value of handle
// generate remainder of html, it will go into strings->arg[2]
g += PR_snprintf(buffer+g, BUFLEN-g,
">\" +\n"
" \"<INPUT TYPE=HIDDEN NAME=goneC SIZE=-1>\" +\n"
" \"<INPUT TYPE=HIDDEN NAME=goneP SIZE=-1>\" +\n"
" \"</FORM>\"\n"
" );\n"
" top.frames[button_frame].document.close();\n"
" }\n"
"\n"
" function loadFrames(){\n"
" loadCookies();\n"
" loadButtons();\n"
" }\n"
"\n"
" function clicker(but,win){\n"
#ifndef HTMLDialogs
" var goneC = top.frames[button_frame].document.buttons.goneC;\n"
" var goneP = top.frames[button_frame].document.buttons.goneP;\n"
" var expires = new Date();\n"
" expires.setTime(expires.getTime() + 1000*60*60*24*365);\n"
" document.cookie = \"htmldlgs=|\" + but.value +\n"
" \"|goneC|\" + goneC.value + \"|goneP|\" + goneP.value + \"|\" +\n"
" \"; expires=\" + expires.toGMTString();\n"
#endif
" top.frames[button_frame].document.buttons.xxxbuttonxxx.value = but.value;\n"
" top.frames[button_frame].document.buttons.xxxbuttonxxx.name = 'button';\n"
" top.frames[button_frame].document.buttons.submit();\n"
" }\n"
"\n"
" </SCRIPT>\n"
"</HEAD>\n"
"<FRAMESET ROWS = 25,25,*,75\n"
" BORDER=0\n"
" FRAMESPACING=0\n"
" onLoad=loadFrames()>\n"
" <FRAME SRC=about:blank\n"
" NAME=index_frame\n"
" SCROLLING=NO\n"
" MARGINWIDTH=1\n"
" MARGINHEIGHT=1\n"
" NORESIZE>\n"
" <FRAME SRC=about:blank\n"
" NAME=title_frame\n"
" SCROLLING=NO\n"
" MARGINWIDTH=1\n"
" MARGINHEIGHT=1\n"
" NORESIZE>\n"
" <FRAMESET COLS=5,*,10,*,5\n"
" BORDER=0\n"
" FRAMESPACING=0>\n"
" <FRAME SRC=about:blank\n"
" NAME=spacer1_frame\n"
" SCROLLING=AUTO\n"
" MARGINWIDTH=0\n"
" MARGINHEIGHT=0\n"
" NORESIZE>\n"
" <FRAME SRC=about:blank\n"
" NAME=list_frame\n"
" SCROLLING=AUTO\n"
" MARGINWIDTH=0\n"
" MARGINHEIGHT=0\n"
" NORESIZE>\n"
" <FRAME SRC=about:blank\n"
" NAME=spacer2_frame\n"
" SCROLLING=AUTO\n"
" MARGINWIDTH=0\n"
" MARGINHEIGHT=0\n"
" NORESIZE>\n"
" <FRAME SRC=about:blank\n"
" NAME=prop_frame\n"
" SCROLLING=AUTO\n"
" MARGINWIDTH=0\n"
" MARGINHEIGHT=0\n"
" NORESIZE>\n"
" <FRAME SRC=about:blank\n"
" NAME=spacer3_frame\n"
" SCROLLING=AUTO\n"
" MARGINWIDTH=0\n"
" MARGINHEIGHT=0\n"
" NORESIZE>\n"
" </FRAMESET>\n"
" <FRAME SRC=about:blank\n"
" NAME=button_frame\n"
" SCROLLING=NO\n"
" MARGINWIDTH=1\n"
" MARGINHEIGHT=1\n"
" NORESIZE>\n"
"</FRAMESET>\n"
"\n"
"<NOFRAMES>\n"
" <BODY> <P> </BODY>\n"
"</NOFRAMES>\n"
"</HTML>\n"
);
FLUSH_BUFFER
// free some strings that are no longer needed //
PR_FREEIF(view_cookies);
PR_FREEIF(view_sites);
PR_FREEIF(buffer);
// put html just generated into strings->arg[2] and invoke HTML dialog //
if (buffer2) {
XP_SetDialogString(strings, 2, buffer2);
buffer2 = NULL;
}
dlg = PORT_ZAlloc(sizeof(CookieViewerDialog));
if ( dlg == NULL ) {
return;
}
dlg->parent_window = (void *)context;
dlg->dialogUp = PR_TRUE;
dlg->state =XP_MakeHTMLDialog(NULL, &dialogInfo, MK_ACCESS_YOUR_COOKIES,
strings, (void *)dlg, PR_FALSE);
return;
}
*/
/*
PUBLIC void
NET_CookieViewerReturn() {
}
*/
/*
PUBLIC void
NET_DisplayCookieInfoOfSiteAsHTML(MWContext * context, char * URLName)
{
char * host;
char * colon;
// remove protocol from URL name
host = NET_ParseURL(URLName, GET_HOST_PART);
// remove port number from URL name
colon = PL_strchr(host, ':');
if(colon) {
*colon = '\0';
}
net_DisplayCookieInfoAsHTML(context, host);
// free up allocated string and return
if(colon) {
*colon = ':';
}
PR_Free(host);
}
*/
PUBLIC void
NET_DisplayCookieInfoAsHTML(MWContext * context)
{
}
#ifdef XP_MAC
/* pinkerton - reset optimization state (see above) */
#pragma global_optimizer reset
#endif
#else
/*
PUBLIC void
NET_DisplayCookieInfoAsHTML(MWContext * context)
{
}
*/
#endif