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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -58,6 +58,7 @@ REQUIRES = xpcom \
|
||||
CPPSRCS = \
|
||||
nsTransportUtils.cpp \
|
||||
nsAsyncStreamCopier.cpp \
|
||||
nsAuthInformationHolder.cpp \
|
||||
nsBaseChannel.cpp \
|
||||
nsBaseContentStream.cpp \
|
||||
nsBufferedStreams.cpp \
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -62,7 +62,6 @@
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsIAuthPrompt.h"
|
||||
#include "nsITransport.h"
|
||||
#include "nsIProxyInfo.h"
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = "";
|
||||
|
||||
Reference in New Issue
Block a user