Bug 265780 make FTP use nsIAuthPrompt2

r=darin


git-svn-id: svn://10.0.0.236/trunk@212180 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
cbiesinger%web.de
2006-09-22 21:06:57 +00:00
parent 4f1ee8a11f
commit b9be660c26
9 changed files with 108 additions and 176 deletions

View File

@@ -38,6 +38,8 @@
#ifndef NSPROMPTUTILS_H_
#define NSPROMPTUTILS_H_
#include "nsIHttpChannel.h"
/**
* @file
* This file defines some helper functions that simplify interaction
@@ -139,6 +141,15 @@ inline void
NS_GetAuthKey(nsIChannel* aChannel, nsIAuthInformation* aAuthInfo,
nsCString& key)
{
// HTTP does this differently from other protocols
nsCOMPtr<nsIHttpChannel> http(do_QueryInterface(aChannel));
if (!http) {
nsCOMPtr<nsIURI> uri;
aChannel->GetURI(getter_AddRefs(uri));
uri->GetPrePath(key);
return;
}
// NOTE: For backwards-compatibility reasons, this must be the ASCII host.
nsCString host;
PRInt32 port = -1;

View File

@@ -667,9 +667,14 @@ nsPrompt::PromptPasswordAdapter(nsIPromptService* aService,
PRUnichar *user = ToNewUnicode(defaultUser),
*pass = ToNewUnicode(defaultPass);
nsresult rv;
rv = aService->PromptUsernameAndPassword(aParent, nsnull, message.get(),
&user, &pass, aCheckLabel,
aCheckValue, retval);
if (flags & nsIAuthInformation::ONLY_PASSWORD)
rv = aService->PromptPassword(aParent, nsnull, message.get(),
&pass, aCheckLabel,
aCheckValue, retval);
else
rv = aService->PromptUsernameAndPassword(aParent, nsnull, message.get(),
&user, &pass, aCheckLabel,
aCheckValue, retval);
nsAdoptingString userStr(user);
nsAdoptingString passStr(pass);

View File

@@ -2855,8 +2855,15 @@ SINGSIGN_PromptAuth
username,
password);
PRUint32 flags = 0;
aAuthInfo->GetFlags(&flags);
if (checked) {
NS_SetAuthInfo(aAuthInfo, username, password);
// If we were only asked for a password, return immediately
// (to match SINGSIGN_PromptPassword)
if (flags & nsIAuthInformation::ONLY_PASSWORD)
return NS_OK;
}
PRBool remembered = checked;

View File

@@ -58,6 +58,7 @@ REQUIRES = xpcom \
CPPSRCS = \
nsTransportUtils.cpp \
nsAsyncStreamCopier.cpp \
nsAuthInformationHolder.cpp \
nsBaseChannel.cpp \
nsBaseContentStream.cpp \
nsBufferedStreams.cpp \

View File

@@ -56,8 +56,6 @@
#include "netCore.h"
#include "nsIStreamListener.h"
#include "nsAutoLock.h"
#include "nsIPrompt.h"
#include "nsIAuthPrompt.h"
#include "nsIFTPChannel.h"
#include "nsIUploadChannel.h"
#include "nsIProxyInfo.h"
@@ -65,11 +63,6 @@
#include "nsIResumableChannel.h"
#include "nsHashPropertyBag.h"
#include "nsICacheService.h"
#include "nsICacheEntryDescriptor.h"
#include "nsICacheListener.h"
#include "nsICacheSession.h"
#define FTP_COMMAND_CHANNEL_SEG_SIZE 64
#define FTP_COMMAND_CHANNEL_SEG_COUNT 8

View File

@@ -58,6 +58,7 @@
#include "nsNetUtil.h"
#include "nsThreadUtils.h"
#include "nsStreamUtils.h"
#include "nsICacheService.h"
#include "nsIURL.h"
#include "nsISocketTransport.h"
#include "nsIStreamListenerTee.h"
@@ -65,6 +66,7 @@
#include "nsIPrefBranch.h"
#include "nsIStringBundle.h"
#include "nsCPasswordManager.h"
#include "nsAuthInformationHolder.h"
#if defined(PR_LOGGING)
extern PRLogModuleInfo* gFTPLog;
@@ -658,51 +660,27 @@ nsFtpState::S_user() {
usernameStr.AppendLiteral("anonymous");
} else {
if (mUsername.IsEmpty()) {
nsCOMPtr<nsIAuthPrompt> prompter;
mChannel->GetCallback(prompter);
nsCOMPtr<nsIAuthPrompt2> prompter;
NS_QueryAuthPrompt2(NS_STATIC_CAST(nsIChannel*, mChannel),
getter_AddRefs(prompter));
if (!prompter)
return NS_ERROR_NOT_INITIALIZED;
nsXPIDLString user, passwd;
nsCAutoString prePath;
rv = mChannel->URI()->GetPrePath(prePath);
if (NS_FAILED(rv))
return rv;
NS_ConvertUTF8toUTF16 prePathU(prePath);
nsCOMPtr<nsIStringBundleService> bundleService =
do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIStringBundle> bundle;
rv = bundleService->CreateBundle(NECKO_MSGS_URL, getter_AddRefs(bundle));
if (NS_FAILED(rv))
return rv;
const PRUnichar *formatStrings[] = { prePathU.get() };
NS_NAMED_LITERAL_STRING(name, "EnterUserPasswordFor");
nsXPIDLString formattedString;
rv = bundle->FormatStringFromName(name.get(), formatStrings, 1,
getter_Copies(formattedString));
if (NS_FAILED(rv))
return rv;
nsRefPtr<nsAuthInformationHolder> info =
new nsAuthInformationHolder(nsIAuthInformation::AUTH_HOST,
EmptyString(),
EmptyCString());
PRBool retval;
rv = prompter->PromptUsernameAndPassword(nsnull,
formattedString,
prePathU.get(),
nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
getter_Copies(user),
getter_Copies(passwd),
&retval);
rv = prompter->PromptAuth(mChannel, nsIAuthPrompt2::LEVEL_NONE,
info, &retval);
// if the user canceled or didn't supply a username we want to fail
if (NS_FAILED(rv) || !retval || (user && !*user) )
if (NS_FAILED(rv) || !retval || info->User().IsEmpty())
return NS_ERROR_FAILURE;
mUsername = user;
mPassword = passwd;
mUsername = info->User();
mPassword = info->Password();
}
// XXX Is UTF-8 the best choice?
AppendUTF16toUTF8(mUsername, usernameStr);
@@ -772,50 +750,28 @@ nsFtpState::S_pass() {
}
} else {
if (mPassword.IsEmpty() || mRetryPass) {
nsCOMPtr<nsIAuthPrompt> prompter;
mChannel->GetCallback(prompter);
nsCOMPtr<nsIAuthPrompt2> prompter;
NS_QueryAuthPrompt2(NS_STATIC_CAST(nsIChannel*, mChannel),
getter_AddRefs(prompter));
if (!prompter)
return NS_ERROR_NOT_INITIALIZED;
nsCAutoString prePath;
rv = mChannel->URI()->GetPrePath(prePath);
if (NS_FAILED(rv))
return rv;
NS_ConvertUTF8toUTF16 prePathU(prePath);
nsCOMPtr<nsIStringBundleService> bundleService =
do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
nsRefPtr<nsAuthInformationHolder> info =
new nsAuthInformationHolder(nsIAuthInformation::AUTH_HOST |
nsIAuthInformation::ONLY_PASSWORD,
EmptyString(),
EmptyCString());
nsCOMPtr<nsIStringBundle> bundle;
rv = bundleService->CreateBundle(NECKO_MSGS_URL,
getter_AddRefs(bundle));
const PRUnichar *formatStrings[2] = {
mUsername.get(), prePathU.get()
};
NS_NAMED_LITERAL_STRING(name, "EnterPasswordFor");
nsXPIDLString formattedString;
rv = bundle->FormatStringFromName(name.get(), formatStrings, 2,
getter_Copies(formattedString));
if (NS_FAILED(rv))
return rv;
nsXPIDLString passwd;
PRBool retval;
rv = prompter->PromptPassword(nsnull,
formattedString,
prePathU.get(),
nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
getter_Copies(passwd), &retval);
rv = prompter->PromptAuth(mChannel, nsIAuthPrompt2::LEVEL_NONE,
info, &retval);
// we want to fail if the user canceled. Note here that if they want
// a blank password, we will pass it along.
if (NS_FAILED(rv) || !retval)
return NS_ERROR_FAILURE;
mPassword = passwd;
mPassword = info->Password();
}
// XXX Is UTF-8 the best choice?
AppendUTF16toUTF8(mPassword, passwordStr);

View File

@@ -62,7 +62,6 @@
#include "nsAutoLock.h"
#include "nsAutoPtr.h"
#include "nsIPrompt.h"
#include "nsIAuthPrompt.h"
#include "nsITransport.h"
#include "nsIProxyInfo.h"

View File

@@ -75,6 +75,7 @@
#include "nsChannelProperties.h"
#include "nsStreamUtils.h"
#include "nsIOService.h"
#include "nsAuthInformationHolder.h"
// True if the local cache should be bypassed when processing a request.
#define BYPASS_LOCAL_CACHE(loadFlags) \
@@ -2665,99 +2666,20 @@ nsHttpChannel::ParseRealm(const char *challenge, nsACString &realm)
}
}
class nsAuthInformationHolder : public nsIAuthInformation {
public:
// aAuthType must be ASCII
nsAuthInformationHolder(PRUint32 aFlags, const nsString& aRealm,
const nsCString& aAuthType)
: mFlags(aFlags), mRealm(aRealm), mAuthType(aAuthType) {}
NS_DECL_ISUPPORTS
NS_DECL_NSIAUTHINFORMATION
class nsHTTPAuthInformation : public nsAuthInformationHolder {
public:
nsHTTPAuthInformation(PRUint32 aFlags, const nsString& aRealm,
const nsCString& aAuthType)
: nsAuthInformationHolder(aFlags, aRealm, aAuthType) {}
void SetToHttpAuthIdentity(PRUint32 authFlags, nsHttpAuthIdentity& identity);
private:
nsString mUser;
nsString mPassword;
nsString mDomain;
PRUint32 mFlags;
nsString mRealm;
nsCString mAuthType;
};
NS_IMPL_ISUPPORTS1(nsAuthInformationHolder, nsIAuthInformation)
NS_IMETHODIMP
nsAuthInformationHolder::GetFlags(PRUint32* aFlags)
{
*aFlags = mFlags;
return NS_OK;
}
NS_IMETHODIMP
nsAuthInformationHolder::GetRealm(nsAString& aRealm)
{
aRealm = mRealm;
return NS_OK;
}
NS_IMETHODIMP
nsAuthInformationHolder::GetAuthenticationScheme(nsACString& aScheme)
{
aScheme = mAuthType;
return NS_OK;
}
NS_IMETHODIMP
nsAuthInformationHolder::GetUsername(nsAString& aUserName)
{
aUserName = mUser;
return NS_OK;
}
NS_IMETHODIMP
nsAuthInformationHolder::SetUsername(const nsAString& aUserName)
{
if (!(mFlags & ONLY_PASSWORD))
mUser = aUserName;
return NS_OK;
}
NS_IMETHODIMP
nsAuthInformationHolder::GetPassword(nsAString& aPassword)
{
aPassword = mPassword;
return NS_OK;
}
NS_IMETHODIMP
nsAuthInformationHolder::SetPassword(const nsAString& aPassword)
{
mPassword = aPassword;
return NS_OK;
}
NS_IMETHODIMP
nsAuthInformationHolder::GetDomain(nsAString& aDomain)
{
aDomain = mDomain;
return NS_OK;
}
NS_IMETHODIMP
nsAuthInformationHolder::SetDomain(const nsAString& aDomain)
{
if (mFlags & NEED_DOMAIN)
mDomain = aDomain;
return NS_OK;
}
void
nsAuthInformationHolder::SetToHttpAuthIdentity(PRUint32 authFlags, nsHttpAuthIdentity& identity)
nsHTTPAuthInformation::SetToHttpAuthIdentity(PRUint32 authFlags, nsHttpAuthIdentity& identity)
{
SetIdent(identity, authFlags, ToNewUnicode(mUser), ToNewUnicode(mPassword));
identity.Set(mDomain.get(), mUser.get(), mPassword.get());
identity.Set(Domain().get(), User().get(), Password().get());
}
nsresult
@@ -2795,8 +2717,9 @@ nsHttpChannel::PromptForIdentity(PRUint32 level,
if (authFlags & nsIHttpAuthenticator::IDENTITY_INCLUDES_DOMAIN)
promptFlags |= nsIAuthInformation::NEED_DOMAIN;
nsRefPtr<nsAuthInformationHolder> holder =
new nsAuthInformationHolder(promptFlags, realmU, nsDependentCString(authType));
nsRefPtr<nsHTTPAuthInformation> holder =
new nsHTTPAuthInformation(promptFlags, realmU,
nsDependentCString(authType));
if (!holder)
return NS_ERROR_OUT_OF_MEMORY;
PRBool retval = PR_FALSE;

View File

@@ -1,6 +1,10 @@
// NOTE: This tests code outside of Necko. The test still lives here because
// the contract is part of Necko.
// TODO:
// - HTTPS
// - Proxies
const nsIAuthInformation = Components.interfaces.nsIAuthInformation;
const nsIAuthPromptAdapterFactory = Components.interfaces.nsIAuthPromptAdapterFactory;
@@ -41,6 +45,8 @@ function run_test() {
user: "foo\\bar",
pw: "bar",
scheme: "http",
QueryInterface: function authprompt_qi(iid) {
if (iid.equals(Components.interfaces.nsISupports) ||
iid.equals(Components.interfaces.nsIAuthPrompt))
@@ -72,18 +78,21 @@ function run_test() {
},
doChecks: function ap1_check(text, realm) {
do_check_eq(host + ":80 (" + info.realm + ")", realm);
if (this.scheme == "http")
do_check_eq(host + ":80 (" + info.realm + ")", realm);
else
do_check_eq(this.scheme + "://" + host, realm);
do_check_neq(text.indexOf(host), -1);
do_check_neq(text.indexOf(info.realm), -1);
// Only HTTP has realms
if (this.scheme == "http")
do_check_neq(text.indexOf(info.realm), -1);
// No explicit port in the URL; message should not contain -1
// for those cases
do_check_eq(text.indexOf("-1"), -1);
}
};
var prompt1 = new Prompt1();
var wrapper = adapter.createAdapter(prompt1);
// Also have to make up a channel
var ios = Components.classes["@mozilla.org/network/io-service;1"]
@@ -91,8 +100,14 @@ function run_test() {
var chan = ios.newChannel("http://" + host, "", null);
function do_tests(expectedRV) {
var prompt1;
var wrapper;
// 1: The simple case
prompt1 = new Prompt1();
prompt1.rv = expectedRV;
wrapper = adapter.createAdapter(prompt1);
var rv = wrapper.promptAuth(chan, 0, info);
do_check_eq(rv, prompt1.rv);
do_check_eq(prompt1.called, CALLED_PROMPTUP);
@@ -145,7 +160,7 @@ function run_test() {
do_check_eq(info.password, prompt1.pw);
}
info.flags &= ~nsIAuthInformation.ONLY_PASSWORD;
info.flags &= ~nsIAuthInformation.NEED_DOMAIN;
info.domain = "";
info.username = "";
@@ -169,7 +184,29 @@ function run_test() {
do_check_eq(info.password, prompt1.pw);
}
info.flags &= ~nsIAuthInformation.ONLY_PASSWORD;
info.flags &= ~nsIAuthInformation.NEED_DOMAIN;
info.domain = "";
info.username = "";
info.password = "";
// 5: FTP
var ftpchan = ios.newChannel("ftp://" + host, "", null);
prompt1 = new Prompt1();
prompt1.rv = expectedRV;
prompt1.scheme = "ftp";
wrapper = adapter.createAdapter(prompt1);
var rv = wrapper.promptAuth(ftpchan, 0, info);
do_check_eq(rv, prompt1.rv);
do_check_eq(prompt1.called, CALLED_PROMPTUP);
if (rv) {
do_check_eq(info.domain, "");
do_check_eq(info.username, prompt1.user);
do_check_eq(info.password, prompt1.pw);
}
info.domain = "";
info.username = "";