зеркало из https://github.com/mozilla/gecko-dev.git
Bug 26767 - FTP client detects UTF-8 if server returns UTF8 on FEAT. r=michal.novotny
This commit is contained in:
Родитель
df5eac109e
Коммит
d20c2455e3
|
@ -92,6 +92,7 @@ nsFtpState::nsFtpState()
|
||||||
, mPort(21)
|
, mPort(21)
|
||||||
, mAddressChecked(false)
|
, mAddressChecked(false)
|
||||||
, mServerIsIPv6(false)
|
, mServerIsIPv6(false)
|
||||||
|
, mUseUTF8(false)
|
||||||
, mControlStatus(NS_OK)
|
, mControlStatus(NS_OK)
|
||||||
, mDeferredCallbackPending(false)
|
, mDeferredCallbackPending(false)
|
||||||
{
|
{
|
||||||
|
@ -276,7 +277,12 @@ nsFtpState::EstablishControlConnection()
|
||||||
mServerType = mControlConnection->mServerType;
|
mServerType = mControlConnection->mServerType;
|
||||||
mPassword = mControlConnection->mPassword;
|
mPassword = mControlConnection->mPassword;
|
||||||
mPwd = mControlConnection->mPwd;
|
mPwd = mControlConnection->mPwd;
|
||||||
|
mUseUTF8 = mControlConnection->mUseUTF8;
|
||||||
mTryingCachedControl = true;
|
mTryingCachedControl = true;
|
||||||
|
|
||||||
|
// we have to set charset to connection if server supports utf-8
|
||||||
|
if (mUseUTF8)
|
||||||
|
mChannel->SetContentCharset(NS_LITERAL_CSTRING("UTF-8"));
|
||||||
|
|
||||||
// we're already connected to this server, skip login.
|
// we're already connected to this server, skip login.
|
||||||
mState = FTP_S_PASV;
|
mState = FTP_S_PASV;
|
||||||
|
@ -646,7 +652,43 @@ nsFtpState::Process()
|
||||||
mInternalError = NS_ERROR_FTP_PWD;
|
mInternalError = NS_ERROR_FTP_PWD;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// FEAT for RFC2640 support
|
||||||
|
case FTP_S_FEAT:
|
||||||
|
rv = S_feat();
|
||||||
|
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
mInternalError = rv;
|
||||||
|
|
||||||
|
MoveToNextState(FTP_R_FEAT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FTP_R_FEAT:
|
||||||
|
mState = R_feat();
|
||||||
|
|
||||||
|
// Don't want to overwrite a more explicit status code
|
||||||
|
if (FTP_ERROR == mState && NS_SUCCEEDED(mInternalError))
|
||||||
|
mInternalError = NS_ERROR_FAILURE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// OPTS for some non-RFC2640-compliant servers support
|
||||||
|
case FTP_S_OPTS:
|
||||||
|
rv = S_opts();
|
||||||
|
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
mInternalError = rv;
|
||||||
|
|
||||||
|
MoveToNextState(FTP_R_OPTS);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FTP_R_OPTS:
|
||||||
|
mState = R_opts();
|
||||||
|
|
||||||
|
// Don't want to overwrite a more explicit status code
|
||||||
|
if (FTP_ERROR == mState && NS_SUCCEEDED(mInternalError))
|
||||||
|
mInternalError = NS_ERROR_FAILURE;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -923,7 +965,7 @@ nsFtpState::R_syst() {
|
||||||
return FTP_ERROR;
|
return FTP_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FTP_S_PWD;
|
return FTP_S_FEAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mResponseCode/100 == 5) {
|
if (mResponseCode/100 == 5) {
|
||||||
|
@ -931,7 +973,7 @@ nsFtpState::R_syst() {
|
||||||
// No clue. We will just hope it is UNIX type server.
|
// No clue. We will just hope it is UNIX type server.
|
||||||
mServerType = FTP_UNIX_TYPE;
|
mServerType = FTP_UNIX_TYPE;
|
||||||
|
|
||||||
return FTP_S_PWD;
|
return FTP_S_FEAT;
|
||||||
}
|
}
|
||||||
return FTP_ERROR;
|
return FTP_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -1135,6 +1177,10 @@ nsFtpState::S_list() {
|
||||||
serverType.AppendInt(mServerType);
|
serverType.AppendInt(mServerType);
|
||||||
mCacheEntry->SetMetaDataElement("servertype", serverType.get());
|
mCacheEntry->SetMetaDataElement("servertype", serverType.get());
|
||||||
|
|
||||||
|
nsAutoCString useUTF8;
|
||||||
|
useUTF8.AppendInt(mUseUTF8);
|
||||||
|
mCacheEntry->SetMetaDataElement("useUTF8", useUTF8.get());
|
||||||
|
|
||||||
// open cache entry for writing, and configure it to receive data.
|
// open cache entry for writing, and configure it to receive data.
|
||||||
if (NS_FAILED(InstallCacheListener())) {
|
if (NS_FAILED(InstallCacheListener())) {
|
||||||
mCacheEntry->AsyncDoom(nullptr);
|
mCacheEntry->AsyncDoom(nullptr);
|
||||||
|
@ -1551,6 +1597,39 @@ nsFtpState::R_pasv() {
|
||||||
return FTP_S_SIZE;
|
return FTP_S_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsFtpState::S_feat() {
|
||||||
|
return SendFTPCommand(NS_LITERAL_CSTRING("FEAT" CRLF));
|
||||||
|
}
|
||||||
|
|
||||||
|
FTP_STATE
|
||||||
|
nsFtpState::R_feat() {
|
||||||
|
if (mResponseCode/100 == 2) {
|
||||||
|
if (mResponseMsg.Find(NS_LITERAL_CSTRING(CRLF " UTF8" CRLF), true) > -1) {
|
||||||
|
// This FTP server supports UTF-8 encoding
|
||||||
|
mChannel->SetContentCharset(NS_LITERAL_CSTRING("UTF-8"));
|
||||||
|
mUseUTF8 = true;
|
||||||
|
return FTP_S_OPTS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mUseUTF8 = false;
|
||||||
|
return FTP_S_PWD;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsFtpState::S_opts() {
|
||||||
|
// This command is for compatibility of old FTP spec (IETF Draft)
|
||||||
|
return SendFTPCommand(NS_LITERAL_CSTRING("OPTS UTF8 ON" CRLF));
|
||||||
|
}
|
||||||
|
|
||||||
|
FTP_STATE
|
||||||
|
nsFtpState::R_opts() {
|
||||||
|
// Ignore error code because "OPTS UTF8 ON" is for compatibility of
|
||||||
|
// FTP server using IETF draft
|
||||||
|
return FTP_S_PWD;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// nsIRequest methods:
|
// nsIRequest methods:
|
||||||
|
|
||||||
|
@ -1847,6 +1926,7 @@ nsFtpState::KillControlConnection()
|
||||||
mControlConnection->mServerType = mServerType;
|
mControlConnection->mServerType = mServerType;
|
||||||
mControlConnection->mPassword = mPassword;
|
mControlConnection->mPassword = mPassword;
|
||||||
mControlConnection->mPwd = mPwd;
|
mControlConnection->mPwd = mPwd;
|
||||||
|
mControlConnection->mUseUTF8 = mUseUTF8;
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
// Don't cache controlconnection if anonymous (bug #473371)
|
// Don't cache controlconnection if anonymous (bug #473371)
|
||||||
|
@ -1865,7 +1945,7 @@ nsFtpState::KillControlConnection()
|
||||||
class nsFtpAsyncAlert : public nsRunnable
|
class nsFtpAsyncAlert : public nsRunnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
nsFtpAsyncAlert(nsIPrompt *aPrompter, nsACString& aResponseMsg)
|
nsFtpAsyncAlert(nsIPrompt *aPrompter, nsString aResponseMsg)
|
||||||
: mPrompter(aPrompter)
|
: mPrompter(aPrompter)
|
||||||
, mResponseMsg(aResponseMsg)
|
, mResponseMsg(aResponseMsg)
|
||||||
{
|
{
|
||||||
|
@ -1878,15 +1958,15 @@ public:
|
||||||
NS_IMETHOD Run()
|
NS_IMETHOD Run()
|
||||||
{
|
{
|
||||||
if (mPrompter) {
|
if (mPrompter) {
|
||||||
mPrompter->Alert(nullptr, NS_ConvertASCIItoUTF16(mResponseMsg).get());
|
mPrompter->Alert(nullptr, mResponseMsg.get());
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
nsCOMPtr<nsIPrompt> mPrompter;
|
nsCOMPtr<nsIPrompt> mPrompter;
|
||||||
nsCString mResponseMsg;
|
nsString mResponseMsg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsFtpState::StopProcessing()
|
nsFtpState::StopProcessing()
|
||||||
|
@ -1910,8 +1990,14 @@ nsFtpState::StopProcessing()
|
||||||
nsCOMPtr<nsIPrompt> prompter;
|
nsCOMPtr<nsIPrompt> prompter;
|
||||||
mChannel->GetCallback(prompter);
|
mChannel->GetCallback(prompter);
|
||||||
if (prompter) {
|
if (prompter) {
|
||||||
nsCOMPtr<nsIRunnable> alertEvent =
|
nsCOMPtr<nsIRunnable> alertEvent;
|
||||||
new nsFtpAsyncAlert(prompter, mResponseMsg);
|
if (mUseUTF8) {
|
||||||
|
alertEvent = new nsFtpAsyncAlert(prompter,
|
||||||
|
NS_ConvertUTF8toUTF16(mResponseMsg));
|
||||||
|
} else {
|
||||||
|
alertEvent = new nsFtpAsyncAlert(prompter,
|
||||||
|
NS_ConvertASCIItoUTF16(mResponseMsg));
|
||||||
|
}
|
||||||
NS_DispatchToMainThread(alertEvent, NS_DISPATCH_NORMAL);
|
NS_DispatchToMainThread(alertEvent, NS_DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2372,6 +2458,12 @@ nsFtpState::ReadCacheEntry()
|
||||||
nsAutoCString serverNum(serverType.get());
|
nsAutoCString serverNum(serverType.get());
|
||||||
nsresult err;
|
nsresult err;
|
||||||
mServerType = serverNum.ToInteger(&err);
|
mServerType = serverNum.ToInteger(&err);
|
||||||
|
|
||||||
|
nsXPIDLCString charset;
|
||||||
|
mCacheEntry->GetMetaDataElement("useUTF8", getter_Copies(charset));
|
||||||
|
const char *useUTF8 = charset.get();
|
||||||
|
if (useUTF8 && atoi(useUTF8) == 1)
|
||||||
|
mChannel->SetContentCharset(NS_LITERAL_CSTRING("UTF-8"));
|
||||||
|
|
||||||
mChannel->PushStreamConverter("text/ftp-dir",
|
mChannel->PushStreamConverter("text/ftp-dir",
|
||||||
APPLICATION_HTTP_INDEX_FORMAT);
|
APPLICATION_HTTP_INDEX_FORMAT);
|
||||||
|
|
|
@ -57,7 +57,9 @@ typedef enum _FTP_STATE {
|
||||||
FTP_S_STOR, FTP_R_STOR,
|
FTP_S_STOR, FTP_R_STOR,
|
||||||
FTP_S_LIST, FTP_R_LIST,
|
FTP_S_LIST, FTP_R_LIST,
|
||||||
FTP_S_PASV, FTP_R_PASV,
|
FTP_S_PASV, FTP_R_PASV,
|
||||||
FTP_S_PWD, FTP_R_PWD
|
FTP_S_PWD, FTP_R_PWD,
|
||||||
|
FTP_S_FEAT, FTP_R_FEAT,
|
||||||
|
FTP_S_OPTS, FTP_R_OPTS
|
||||||
} FTP_STATE;
|
} FTP_STATE;
|
||||||
|
|
||||||
// higher level ftp actions
|
// higher level ftp actions
|
||||||
|
@ -129,6 +131,8 @@ private:
|
||||||
nsresult S_stor(); FTP_STATE R_stor();
|
nsresult S_stor(); FTP_STATE R_stor();
|
||||||
nsresult S_pasv(); FTP_STATE R_pasv();
|
nsresult S_pasv(); FTP_STATE R_pasv();
|
||||||
nsresult S_pwd(); FTP_STATE R_pwd();
|
nsresult S_pwd(); FTP_STATE R_pwd();
|
||||||
|
nsresult S_feat(); FTP_STATE R_feat();
|
||||||
|
nsresult S_opts(); FTP_STATE R_opts();
|
||||||
// END: STATE METHODS
|
// END: STATE METHODS
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
|
|
||||||
|
@ -243,6 +247,7 @@ private:
|
||||||
nsCOMPtr<nsIRequest> mUploadRequest;
|
nsCOMPtr<nsIRequest> mUploadRequest;
|
||||||
bool mAddressChecked;
|
bool mAddressChecked;
|
||||||
bool mServerIsIPv6;
|
bool mServerIsIPv6;
|
||||||
|
bool mUseUTF8;
|
||||||
|
|
||||||
static uint32_t mSessionStartTime;
|
static uint32_t mSessionStartTime;
|
||||||
|
|
||||||
|
|
|
@ -65,8 +65,8 @@ nsFtpControlConnection::OnInputStreamReady(nsIAsyncInputStream *stream)
|
||||||
|
|
||||||
nsFtpControlConnection::nsFtpControlConnection(const nsCSubstring& host,
|
nsFtpControlConnection::nsFtpControlConnection(const nsCSubstring& host,
|
||||||
uint32_t port)
|
uint32_t port)
|
||||||
: mServerType(0), mSessionId(gFtpHandler->GetSessionId()), mHost(host)
|
: mServerType(0), mSessionId(gFtpHandler->GetSessionId())
|
||||||
, mPort(port)
|
, mUseUTF8(false), mHost(host), mPort(port)
|
||||||
{
|
{
|
||||||
LOG_ALWAYS(("FTP:CC created @%p", this));
|
LOG_ALWAYS(("FTP:CC created @%p", this));
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ public:
|
||||||
int32_t mSuspendedWrite;
|
int32_t mSuspendedWrite;
|
||||||
nsCString mPwd;
|
nsCString mPwd;
|
||||||
uint32_t mSessionId;
|
uint32_t mSessionId;
|
||||||
|
bool mUseUTF8;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsCString mHost;
|
nsCString mHost;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче