XP_Bool remember_password;
XP_Bool remember_password = FALSE;
NET_AskForAuthString(MWContext *context,					 URL_Struct * URL_s, 					 char * authenticate, 					 char * prot_template,					 Bool   already_sent_auth){	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;	}	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);		password=PL_strdup(colon+1);		*colon=':';		PR_Free(unamePwd);	} else {		username=unamePwd;	}	if(username && !(*username) )	{		PR_FREEIF(username);		username = NULL;	}	if(password && !(*password) )	{		PR_FREEIF(password);		password = NULL;	}	/*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.  	 */	if(!password || re_authorize)	  {		XP_Bool remember_password;        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 defined(SingleSignon)			/* prefill prompt with previous username/passwords if any */			status = SI_PromptUsernameAndPassword			    (context, buf, &username, &password, URL_s->address);#else			status = PC_PromptUsernameAndPassword			    (context, buf, &username, &password,			    &remember_password, NET_IsURLSecure(URL_s->address));#endif				PR_Free(buf);        } else {	        status = 0;		}		PR_Free(host);		if(!status) {			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);		  }		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, '@')) ) {          if( (host=PL_strstr(new_address, "://")) ) {            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);}