зеркало из https://github.com/mozilla/pjs.git
5415 строки
148 KiB
C
5415 строки
148 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.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
/*
|
|
*
|
|
* 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) {
|
|
MWContext *outermost_window = window_id;
|
|
Bool result;
|
|
if (!window_id) {
|
|
return FALSE;
|
|
}
|
|
while (outermost_window->grid_parent) {
|
|
outermost_window = outermost_window->grid_parent;
|
|
}
|
|
result = (window_id->anonymous != net_anonymous);
|
|
window_id->anonymous = net_anonymous;
|
|
return result;
|
|
}
|
|
|
|
/* 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 */
|
|
/* array of msg Ids for the purpose values */
|
|
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> </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> </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"
|
|
" (\" %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> </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> </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"
|
|
" (\" %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"
|
|
" \" \" +\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"
|
|
" \" \" +\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)
|
|
{
|
|
net_DisplayCookieInfoAsHTML(context, NULL);
|
|
}
|
|
|
|
|
|
#ifdef XP_MAC
|
|
/* pinkerton - reset optimization state (see above) */
|
|
#pragma global_optimizer reset
|
|
#endif
|
|
|
|
#else
|
|
PUBLIC void
|
|
NET_DisplayCookieInfoAsHTML(MWContext * context)
|
|
{
|
|
}
|
|
#endif
|
|
|