Bug 1574475 - Delete FTP code r=necko-reviewers,dragana

Differential Revision: https://phabricator.services.mozilla.com/D111246
This commit is contained in:
Valentin Gosu 2021-04-28 09:33:45 +00:00
Родитель b6c4d8cd4d
Коммит 824826fd4e
22 изменённых файлов: 0 добавлений и 8877 удалений

Просмотреть файл

@ -1,541 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/net/NeckoChild.h"
#include "mozilla/net/FTPChannelChild.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/BrowserChild.h"
#include "nsContentUtils.h"
#include "nsFtpProtocolHandler.h"
#include "nsIBrowserChild.h"
#include "nsStringStream.h"
#include "nsNetUtil.h"
#include "base/compiler_specific.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/URIUtils.h"
#include "SerializedLoadContext.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "nsIURIMutator.h"
#include "nsContentSecurityManager.h"
#include "mozilla/ScopeExit.h"
using mozilla::dom::ContentChild;
using namespace mozilla::ipc;
#undef LOG
#define LOG(args) MOZ_LOG(gFTPLog, mozilla::LogLevel::Debug, args)
namespace mozilla {
namespace net {
FTPChannelChild::FTPChannelChild(nsIURI* aUri)
: mIPCOpen(false),
mEventQ(new ChannelEventQueue(static_cast<nsIFTPChannel*>(this))),
mCanceled(false),
mSuspendCount(0),
mIsPending(false),
mLastModifiedTime(0),
mStartPos(0),
mSuspendSent(false) {
LOG(("Creating FTPChannelChild @%p\n", this));
// grab a reference to the handler to ensure that it doesn't go away.
NS_ADDREF(gFtpHandler);
SetURI(aUri);
// We could support thread retargeting, but as long as we're being driven by
// IPDL on the main thread it doesn't buy us anything.
DisallowThreadRetargeting();
}
FTPChannelChild::~FTPChannelChild() {
LOG(("Destroying FTPChannelChild @%p\n", this));
gFtpHandler->Release();
}
void FTPChannelChild::AddIPDLReference() {
MOZ_ASSERT(!mIPCOpen, "Attempt to retain more than one IPDL reference");
mIPCOpen = true;
AddRef();
}
void FTPChannelChild::ReleaseIPDLReference() {
MOZ_ASSERT(mIPCOpen, "Attempt to release nonexistent IPDL reference");
mIPCOpen = false;
Release();
}
//-----------------------------------------------------------------------------
// FTPChannelChild::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS_INHERITED(FTPChannelChild, nsBaseChannel, nsIFTPChannel,
nsIUploadChannel, nsIResumableChannel,
nsIProxiedChannel, nsIChildChannel)
//-----------------------------------------------------------------------------
NS_IMETHODIMP
FTPChannelChild::GetLastModifiedTime(PRTime* aLastModifiedTime) {
*aLastModifiedTime = mLastModifiedTime;
return NS_OK;
}
NS_IMETHODIMP
FTPChannelChild::SetLastModifiedTime(PRTime aLastModifiedTime) {
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
FTPChannelChild::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID) {
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
mStartPos = aStartPos;
mEntityID = aEntityID;
return NS_OK;
}
NS_IMETHODIMP
FTPChannelChild::GetEntityID(nsACString& aEntityID) {
aEntityID = mEntityID;
return NS_OK;
}
NS_IMETHODIMP
FTPChannelChild::GetProxyInfo(nsIProxyInfo** aProxyInfo) { DROP_DEAD(); }
NS_IMETHODIMP FTPChannelChild::GetHttpProxyConnectResponseCode(
int32_t* aResponseCode) {
DROP_DEAD();
}
NS_IMETHODIMP
FTPChannelChild::SetUploadStream(nsIInputStream* aStream,
const nsACString& aContentType,
int64_t aContentLength) {
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
mUploadStream = aStream;
// NOTE: contentLength is intentionally ignored here.
return NS_OK;
}
NS_IMETHODIMP
FTPChannelChild::GetUploadStream(nsIInputStream** aStream) {
NS_ENSURE_ARG_POINTER(aStream);
*aStream = mUploadStream;
NS_IF_ADDREF(*aStream);
return NS_OK;
}
NS_IMETHODIMP
FTPChannelChild::AsyncOpen(nsIStreamListener* aListener) {
nsCOMPtr<nsIStreamListener> listener = aListener;
nsresult rv =
nsContentSecurityManager::doContentSecurityCheck(this, listener);
NS_ENSURE_SUCCESS(rv, rv);
LOG(("FTPChannelChild::AsyncOpen [this=%p]\n", this));
NS_ENSURE_TRUE((gNeckoChild), NS_ERROR_FAILURE);
NS_ENSURE_TRUE(
!static_cast<ContentChild*>(gNeckoChild->Manager())->IsShuttingDown(),
NS_ERROR_FAILURE);
NS_ENSURE_ARG_POINTER(listener);
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
// Port checked in parent, but duplicate here so we can return with error
// immediately, as we've done since before e10s.
rv = NS_CheckPortSafety(nsBaseChannel::URI()); // Need to disambiguate,
// because in the child ipdl,
// a typedef URI is defined...
if (NS_FAILED(rv)) return rv;
mozilla::dom::BrowserChild* browserChild = nullptr;
nsCOMPtr<nsIBrowserChild> iBrowserChild;
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
NS_GET_IID(nsIBrowserChild),
getter_AddRefs(iBrowserChild));
GetCallback(iBrowserChild);
if (iBrowserChild) {
browserChild =
static_cast<mozilla::dom::BrowserChild*>(iBrowserChild.get());
}
mListener = listener;
// add ourselves to the load group.
if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr);
mozilla::ipc::AutoIPCStream autoStream;
autoStream.Serialize(mUploadStream,
static_cast<ContentChild*>(gNeckoChild->Manager()));
uint32_t loadFlags = 0;
GetLoadFlags(&loadFlags);
FTPChannelOpenArgs openArgs;
SerializeURI(nsBaseChannel::URI(), openArgs.uri());
openArgs.startPos() = mStartPos;
openArgs.entityID() = mEntityID;
openArgs.uploadStream() = autoStream.TakeOptionalValue();
openArgs.loadFlags() = loadFlags;
nsCOMPtr<nsILoadInfo> loadInfo = LoadInfo();
rv = mozilla::ipc::LoadInfoToLoadInfoArgs(loadInfo, &openArgs.loadInfo());
NS_ENSURE_SUCCESS(rv, rv);
// This must happen before the constructor message is sent.
SetupNeckoTarget();
gNeckoChild->SendPFTPChannelConstructor(
this, browserChild, IPC::SerializedLoadContext(this), openArgs);
// The socket transport layer in the chrome process now has a logical ref to
// us until OnStopRequest is called.
AddIPDLReference();
mIsPending = true;
mWasOpened = true;
return rv;
}
NS_IMETHODIMP
FTPChannelChild::IsPending(bool* aResult) {
*aResult = mIsPending;
return NS_OK;
}
nsresult FTPChannelChild::OpenContentStream(bool aAsync,
nsIInputStream** aStream,
nsIChannel** aChannel) {
MOZ_CRASH("FTPChannel*Child* should never have OpenContentStream called!");
return NS_OK;
}
//-----------------------------------------------------------------------------
// FTPChannelChild::PFTPChannelChild
//-----------------------------------------------------------------------------
mozilla::ipc::IPCResult FTPChannelChild::RecvOnStartRequest(
const nsresult& aChannelStatus, const int64_t& aContentLength,
const nsCString& aContentType, const PRTime& aLastModified,
const nsCString& aEntityID, const URIParams& aURI) {
LOG(("FTPChannelChild::RecvOnStartRequest [this=%p]\n", this));
mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
this, [self = UnsafePtr<FTPChannelChild>(this), aChannelStatus,
aContentLength, aContentType, aLastModified, aEntityID, aURI]() {
self->DoOnStartRequest(aChannelStatus, aContentLength, aContentType,
aLastModified, aEntityID, aURI);
}));
return IPC_OK();
}
void FTPChannelChild::DoOnStartRequest(const nsresult& aChannelStatus,
const int64_t& aContentLength,
const nsCString& aContentType,
const PRTime& aLastModified,
const nsCString& aEntityID,
const URIParams& aURI) {
mDuringOnStart = true;
RefPtr<FTPChannelChild> self = this;
auto clearDuringFlag =
mozilla::MakeScopeExit([self] { self->mDuringOnStart = false; });
LOG(("FTPChannelChild::DoOnStartRequest [this=%p]\n", this));
if (!mCanceled && NS_SUCCEEDED(mStatus)) {
mStatus = aChannelStatus;
}
mContentLength = aContentLength;
SetContentType(aContentType);
mLastModifiedTime = aLastModified;
mEntityID = aEntityID;
nsCString spec;
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
nsresult rv = uri->GetSpec(spec);
if (NS_SUCCEEDED(rv)) {
// Changes nsBaseChannel::URI()
rv = NS_MutateURI(mURI).SetSpec(spec).Finalize(mURI);
if (NS_FAILED(rv)) {
Cancel(rv);
}
} else {
Cancel(rv);
}
AutoEventEnqueuer ensureSerialDispatch(mEventQ);
rv = mListener->OnStartRequest(this);
if (NS_FAILED(rv)) Cancel(rv);
}
mozilla::ipc::IPCResult FTPChannelChild::RecvOnDataAvailable(
const nsresult& aChannelStatus, const nsCString& aData,
const uint64_t& aOffset, const uint32_t& aCount) {
LOG(("FTPChannelChild::RecvOnDataAvailable [this=%p]\n", this));
mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
this, [self = UnsafePtr<FTPChannelChild>(this), aChannelStatus, aData,
aOffset, aCount]() {
self->DoOnDataAvailable(aChannelStatus, aData, aOffset, aCount);
}));
return IPC_OK();
}
void FTPChannelChild::DoOnDataAvailable(const nsresult& aChannelStatus,
const nsCString& aData,
const uint64_t& aOffset,
const uint32_t& aCount) {
LOG(("FTPChannelChild::DoOnDataAvailable [this=%p]\n", this));
if (!mCanceled && NS_SUCCEEDED(mStatus)) {
mStatus = aChannelStatus;
}
if (mCanceled) {
return;
}
// NOTE: the OnDataAvailable contract requires the client to read all the data
// in the inputstream. This code relies on that ('data' will go away after
// this function). Apparently the previous, non-e10s behavior was to actually
// support only reading part of the data, allowing later calls to read the
// rest.
nsCOMPtr<nsIInputStream> stringStream;
nsresult rv =
NS_NewByteInputStream(getter_AddRefs(stringStream),
Span(aData).To(aCount), NS_ASSIGNMENT_DEPEND);
if (NS_FAILED(rv)) {
Cancel(rv);
return;
}
AutoEventEnqueuer ensureSerialDispatch(mEventQ);
rv = mListener->OnDataAvailable(this, stringStream, aOffset, aCount);
if (NS_FAILED(rv)) {
Cancel(rv);
}
stringStream->Close();
}
mozilla::ipc::IPCResult FTPChannelChild::RecvOnStopRequest(
const nsresult& aChannelStatus, const nsCString& aErrorMsg,
const bool& aUseUTF8) {
LOG(("FTPChannelChild::RecvOnStopRequest [this=%p status=%" PRIx32 "]\n",
this, static_cast<uint32_t>(aChannelStatus)));
mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
this, [self = UnsafePtr<FTPChannelChild>(this), aChannelStatus, aErrorMsg,
aUseUTF8]() {
self->DoOnStopRequest(aChannelStatus, aErrorMsg, aUseUTF8);
}));
return IPC_OK();
}
void FTPChannelChild::DoOnStopRequest(const nsresult& aChannelStatus,
const nsCString& aErrorMsg,
bool aUseUTF8) {
LOG(("FTPChannelChild::DoOnStopRequest [this=%p status=%" PRIx32 "]\n", this,
static_cast<uint32_t>(aChannelStatus)));
if (!mCanceled) mStatus = aChannelStatus;
{ // Ensure that all queued ipdl events are dispatched before
// we initiate protocol deletion below.
mIsPending = false;
AutoEventEnqueuer ensureSerialDispatch(mEventQ);
(void)mListener->OnStopRequest(this, aChannelStatus);
mListener = nullptr;
if (mLoadGroup) {
mLoadGroup->RemoveRequest(this, nullptr, aChannelStatus);
}
}
// This calls NeckoChild::DeallocPFTPChannelChild(), which deletes |this| if
// IPDL holds the last reference. Don't rely on |this| existing after here!
Send__delete__(this);
}
mozilla::ipc::IPCResult FTPChannelChild::RecvFailedAsyncOpen(
const nsresult& aStatusCode) {
LOG(("FTPChannelChild::RecvFailedAsyncOpen [this=%p status=%" PRIx32 "]\n",
this, static_cast<uint32_t>(aStatusCode)));
mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
this, [self = UnsafePtr<FTPChannelChild>(this), aStatusCode]() {
self->DoFailedAsyncOpen(aStatusCode);
}));
return IPC_OK();
}
void FTPChannelChild::DoFailedAsyncOpen(const nsresult& aStatusCode) {
LOG(("FTPChannelChild::DoFailedAsyncOpen [this=%p status=%" PRIx32 "]\n",
this, static_cast<uint32_t>(aStatusCode)));
mStatus = aStatusCode;
if (mLoadGroup) {
mLoadGroup->RemoveRequest(this, nullptr, aStatusCode);
}
if (mListener) {
mListener->OnStartRequest(this);
mIsPending = false;
mListener->OnStopRequest(this, aStatusCode);
} else {
mIsPending = false;
}
mListener = nullptr;
if (mIPCOpen) {
Send__delete__(this);
}
}
mozilla::ipc::IPCResult FTPChannelChild::RecvDeleteSelf() {
mEventQ->RunOrEnqueue(new NeckoTargetChannelFunctionEvent(
this,
[self = UnsafePtr<FTPChannelChild>(this)]() { self->DoDeleteSelf(); }));
return IPC_OK();
}
void FTPChannelChild::DoDeleteSelf() {
if (mIPCOpen) {
Send__delete__(this);
}
}
NS_IMETHODIMP
FTPChannelChild::Cancel(nsresult aStatus) {
LOG(("FTPChannelChild::Cancel [this=%p]\n", this));
if (mCanceled) {
return NS_OK;
}
mCanceled = true;
mStatus = aStatus;
if (mIPCOpen) {
SendCancel(aStatus);
}
return NS_OK;
}
NS_IMETHODIMP
FTPChannelChild::Suspend() {
NS_ENSURE_TRUE(mIPCOpen, NS_ERROR_NOT_AVAILABLE);
LOG(("FTPChannelChild::Suspend [this=%p]\n", this));
// SendSuspend only once, when suspend goes from 0 to 1.
if (!mSuspendCount++) {
SendSuspend();
mSuspendSent = true;
}
mEventQ->Suspend();
return NS_OK;
}
NS_IMETHODIMP
FTPChannelChild::Resume() {
NS_ENSURE_TRUE(mIPCOpen, NS_ERROR_NOT_AVAILABLE);
LOG(("FTPChannelChild::Resume [this=%p]\n", this));
// SendResume only once, when suspend count drops to 0.
if (!--mSuspendCount && mSuspendSent) {
SendResume();
}
mEventQ->Resume();
return NS_OK;
}
//-----------------------------------------------------------------------------
// FTPChannelChild::nsIChildChannel
//-----------------------------------------------------------------------------
NS_IMETHODIMP
FTPChannelChild::ConnectParent(uint32_t aId) {
NS_ENSURE_TRUE((gNeckoChild), NS_ERROR_FAILURE);
NS_ENSURE_TRUE(
!static_cast<ContentChild*>(gNeckoChild->Manager())->IsShuttingDown(),
NS_ERROR_FAILURE);
LOG(("FTPChannelChild::ConnectParent [this=%p]\n", this));
mozilla::dom::BrowserChild* browserChild = nullptr;
nsCOMPtr<nsIBrowserChild> iBrowserChild;
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
NS_GET_IID(nsIBrowserChild),
getter_AddRefs(iBrowserChild));
GetCallback(iBrowserChild);
if (iBrowserChild) {
browserChild =
static_cast<mozilla::dom::BrowserChild*>(iBrowserChild.get());
}
// This must happen before the constructor message is sent.
SetupNeckoTarget();
// The socket transport in the chrome process now holds a logical ref to us
// until OnStopRequest, or we do a redirect, or we hit an IPDL error.
AddIPDLReference();
FTPChannelConnectArgs connectArgs(aId);
if (!gNeckoChild->SendPFTPChannelConstructor(
this, browserChild, IPC::SerializedLoadContext(this), connectArgs)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
FTPChannelChild::CompleteRedirectSetup(nsIStreamListener* aListener) {
LOG(("FTPChannelChild::CompleteRedirectSetup [this=%p]\n", this));
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
mIsPending = true;
mWasOpened = true;
mListener = aListener;
// add ourselves to the load group.
if (mLoadGroup) {
mLoadGroup->AddRequest(this, nullptr);
}
// We already have an open IPDL connection to the parent. If on-modify-request
// listeners or load group observers canceled us, let the parent handle it
// and send it back to us naturally.
return NS_OK;
}
void FTPChannelChild::SetupNeckoTarget() {
if (mNeckoTarget) {
return;
}
nsCOMPtr<nsILoadInfo> loadInfo = LoadInfo();
mNeckoTarget =
nsContentUtils::GetEventTargetByLoadInfo(loadInfo, TaskCategory::Network);
if (!mNeckoTarget) {
return;
}
gNeckoChild->SetEventTargetForActor(this, mNeckoTarget);
}
} // namespace net
} // namespace mozilla

Просмотреть файл

@ -1,137 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_net_FTPChannelChild_h
#define mozilla_net_FTPChannelChild_h
#include "mozilla/UniquePtr.h"
#include "mozilla/net/PFTPChannelChild.h"
#include "mozilla/net/ChannelEventQueue.h"
#include "nsBaseChannel.h"
#include "nsIFTPChannel.h"
#include "nsIUploadChannel.h"
#include "nsIProxiedChannel.h"
#include "nsIResumableChannel.h"
#include "nsIChildChannel.h"
#include "nsIEventTarget.h"
#include "nsIStreamListener.h"
#include "mozilla/net/PrivateBrowsingChannel.h"
class nsIEventTarget;
namespace mozilla {
namespace net {
// This class inherits logic from nsBaseChannel that is not needed for an
// e10s child channel, but it works. At some point we could slice up
// nsBaseChannel and have a new class that has only the common logic for
// nsFTPChannel/FTPChannelChild.
class FTPChannelChild final : public PFTPChannelChild,
public nsBaseChannel,
public nsIFTPChannel,
public nsIUploadChannel,
public nsIResumableChannel,
public nsIProxiedChannel,
public nsIChildChannel {
public:
typedef ::nsIStreamListener nsIStreamListener;
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIFTPCHANNEL
NS_DECL_NSIUPLOADCHANNEL
NS_DECL_NSIRESUMABLECHANNEL
NS_DECL_NSIPROXIEDCHANNEL
NS_DECL_NSICHILDCHANNEL
NS_IMETHOD Cancel(nsresult aStatus) override;
NS_IMETHOD Suspend() override;
NS_IMETHOD Resume() override;
explicit FTPChannelChild(nsIURI* aUri);
void AddIPDLReference();
void ReleaseIPDLReference();
NS_IMETHOD AsyncOpen(nsIStreamListener* aListener) override;
// Note that we handle this ourselves, overriding the nsBaseChannel
// default behavior, in order to be e10s-friendly.
NS_IMETHOD IsPending(bool* aResult) override;
nsresult OpenContentStream(bool aAsync, nsIInputStream** aStream,
nsIChannel** aChannel) override;
bool IsSuspended() const;
protected:
virtual ~FTPChannelChild();
mozilla::ipc::IPCResult RecvOnStartRequest(const nsresult& aChannelStatus,
const int64_t& aContentLength,
const nsCString& aContentType,
const PRTime& aLastModified,
const nsCString& aEntityID,
const URIParams& aURI) override;
mozilla::ipc::IPCResult RecvOnDataAvailable(const nsresult& aChannelStatus,
const nsCString& aData,
const uint64_t& aOffset,
const uint32_t& aCount) override;
mozilla::ipc::IPCResult RecvOnStopRequest(const nsresult& aChannelStatus,
const nsCString& aErrorMsg,
const bool& aUseUTF8) override;
mozilla::ipc::IPCResult RecvFailedAsyncOpen(
const nsresult& aStatusCode) override;
mozilla::ipc::IPCResult RecvDeleteSelf() override;
void DoOnStartRequest(const nsresult& aChannelStatus,
const int64_t& aContentLength,
const nsCString& aContentType,
const PRTime& aLastModified, const nsCString& aEntityID,
const URIParams& aURI);
void DoOnDataAvailable(const nsresult& aChannelStatus, const nsCString& aData,
const uint64_t& aOffset, const uint32_t& aCount);
void DoOnStopRequest(const nsresult& StatusCode, const nsCString& aErrorMsg,
bool aUseUTF8);
void DoFailedAsyncOpen(const nsresult& aStatusCode);
void DoDeleteSelf();
void SetupNeckoTarget() override;
friend class NeckoTargetChannelFunctionEvent;
private:
nsCOMPtr<nsIInputStream> mUploadStream;
bool mIPCOpen;
const RefPtr<ChannelEventQueue> mEventQ;
bool mCanceled;
uint32_t mSuspendCount;
bool mIsPending;
// This will only be true while DoOnStartRequest is in progress.
// It is used to enforce that DivertToParent is only called during that time.
bool mDuringOnStart = false;
PRTime mLastModifiedTime;
uint64_t mStartPos;
nsCString mEntityID;
// Set if SendSuspend is called. Determines if SendResume is needed when
// diverting callbacks to parent.
bool mSuspendSent;
};
inline bool FTPChannelChild::IsSuspended() const { return mSuspendCount != 0; }
} // namespace net
} // namespace mozilla
#endif // mozilla_net_FTPChannelChild_h

Просмотреть файл

@ -1,418 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/net/FTPChannelParent.h"
#include "nsStringStream.h"
#include "mozilla/net/ChannelEventQueue.h"
#include "mozilla/dom/BrowserParent.h"
#include "nsFTPChannel.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsQueryObject.h"
#include "nsFtpProtocolHandler.h"
#include "nsIAuthPrompt.h"
#include "nsIAuthPromptProvider.h"
#include "nsIHttpChannelInternal.h"
#include "nsISecureBrowserUI.h"
#include "nsIForcePendingChannel.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/URIUtils.h"
#include "mozilla/Unused.h"
#include "SerializedLoadContext.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/dom/ContentParent.h"
using namespace mozilla::dom;
using namespace mozilla::ipc;
#undef LOG
#define LOG(args) MOZ_LOG(gFTPLog, mozilla::LogLevel::Debug, args)
namespace mozilla {
namespace net {
FTPChannelParent::FTPChannelParent(dom::BrowserParent* aIframeEmbedding,
nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus)
: mIPCClosed(false),
mLoadContext(aLoadContext),
mPBOverride(aOverrideStatus),
mStatus(NS_OK),
mBrowserParent(aIframeEmbedding),
mUseUTF8(false) {
nsIProtocolHandler* handler;
CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "ftp", &handler);
MOZ_ASSERT(handler, "no ftp handler");
mEventQ = new ChannelEventQueue(static_cast<nsIParentChannel*>(this));
}
FTPChannelParent::~FTPChannelParent() { gFtpHandler->Release(); }
void FTPChannelParent::ActorDestroy(ActorDestroyReason why) {
// We may still have refcount>0 if the channel hasn't called OnStopRequest
// yet, but we must not send any more msgs to child.
mIPCClosed = true;
}
//-----------------------------------------------------------------------------
// FTPChannelParent::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS(FTPChannelParent, nsIStreamListener, nsIParentChannel,
nsIInterfaceRequestor, nsIRequestObserver,
nsIChannelEventSink, nsIFTPChannelParentInternal)
//-----------------------------------------------------------------------------
// FTPChannelParent::PFTPChannelParent
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FTPChannelParent methods
//-----------------------------------------------------------------------------
bool FTPChannelParent::Init(const FTPChannelCreationArgs& aArgs) {
switch (aArgs.type()) {
case FTPChannelCreationArgs::TFTPChannelOpenArgs: {
const FTPChannelOpenArgs& a = aArgs.get_FTPChannelOpenArgs();
return DoAsyncOpen(a.uri(), a.startPos(), a.entityID(), a.uploadStream(),
a.loadInfo(), a.loadFlags());
}
case FTPChannelCreationArgs::TFTPChannelConnectArgs: {
const FTPChannelConnectArgs& cArgs = aArgs.get_FTPChannelConnectArgs();
return ConnectChannel(cArgs.channelId());
}
default:
MOZ_ASSERT_UNREACHABLE("unknown open type");
return false;
}
}
bool FTPChannelParent::DoAsyncOpen(const URIParams& aURI,
const uint64_t& aStartPos,
const nsCString& aEntityID,
const Maybe<IPCStream>& aUploadStream,
const Maybe<LoadInfoArgs>& aLoadInfoArgs,
const uint32_t& aLoadFlags) {
nsresult rv;
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
if (!uri) return false;
#ifdef DEBUG
LOG(("FTPChannelParent DoAsyncOpen [this=%p uri=%s]\n", this,
uri->GetSpecOrDefault().get()));
#endif
nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
if (NS_FAILED(rv)) {
return SendFailedAsyncOpen(rv);
}
nsCOMPtr<nsILoadInfo> loadInfo;
rv = mozilla::ipc::LoadInfoArgsToLoadInfo(aLoadInfoArgs,
getter_AddRefs(loadInfo));
if (NS_FAILED(rv)) {
return SendFailedAsyncOpen(rv);
}
OriginAttributes attrs;
rv = loadInfo->GetOriginAttributes(&attrs);
if (NS_FAILED(rv)) {
return SendFailedAsyncOpen(rv);
}
nsCOMPtr<nsIChannel> chan;
rv = NS_NewChannelInternal(getter_AddRefs(chan), uri, loadInfo, nullptr,
nullptr, nullptr, aLoadFlags, ios);
if (NS_FAILED(rv)) return SendFailedAsyncOpen(rv);
mChannel = chan;
// later on mChannel may become an HTTP channel (we'll be redirected to one
// if we're using a proxy), but for now this is safe
nsFtpChannel* ftpChan = static_cast<nsFtpChannel*>(mChannel.get());
if (mPBOverride != kPBOverride_Unset) {
ftpChan->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
}
rv = ftpChan->SetNotificationCallbacks(this);
if (NS_FAILED(rv)) return SendFailedAsyncOpen(rv);
nsCOMPtr<nsIInputStream> upload = DeserializeIPCStream(aUploadStream);
if (upload) {
// contentType and contentLength are ignored
rv = ftpChan->SetUploadStream(upload, ""_ns, 0);
if (NS_FAILED(rv)) return SendFailedAsyncOpen(rv);
}
rv = ftpChan->ResumeAt(aStartPos, aEntityID);
if (NS_FAILED(rv)) return SendFailedAsyncOpen(rv);
rv = ftpChan->AsyncOpen(this);
if (NS_FAILED(rv)) return SendFailedAsyncOpen(rv);
return true;
}
bool FTPChannelParent::ConnectChannel(const uint64_t& channelId) {
nsresult rv;
LOG(("Looking for a registered channel [this=%p, id=%" PRIx64 "]", this,
channelId));
nsCOMPtr<nsIChannel> channel;
rv = NS_LinkRedirectChannels(channelId, this, getter_AddRefs(channel));
if (NS_SUCCEEDED(rv)) mChannel = channel;
LOG((" found channel %p, rv=%08" PRIx32, mChannel.get(),
static_cast<uint32_t>(rv)));
return true;
}
mozilla::ipc::IPCResult FTPChannelParent::RecvCancel(const nsresult& status) {
if (mChannel) mChannel->Cancel(status);
return IPC_OK();
}
mozilla::ipc::IPCResult FTPChannelParent::RecvSuspend() {
if (mChannel) {
mChannel->Suspend();
}
return IPC_OK();
}
mozilla::ipc::IPCResult FTPChannelParent::RecvResume() {
if (mChannel) {
mChannel->Resume();
}
return IPC_OK();
}
//-----------------------------------------------------------------------------
// FTPChannelParent::nsIRequestObserver
//-----------------------------------------------------------------------------
NS_IMETHODIMP
FTPChannelParent::OnStartRequest(nsIRequest* aRequest) {
LOG(("FTPChannelParent::OnStartRequest [this=%p]\n", this));
nsCOMPtr<nsIChannel> chan = do_QueryInterface(aRequest);
MOZ_ASSERT(chan);
NS_ENSURE_TRUE(chan, NS_ERROR_UNEXPECTED);
// Send down any permissions which are relevant to this URL if we are
// performing a document load.
if (!mIPCClosed) {
PContentParent* pcp = Manager()->Manager();
MOZ_ASSERT(pcp, "We should have a manager if our IPC isn't closed");
DebugOnly<nsresult> rv =
static_cast<ContentParent*>(pcp)->AboutToLoadHttpFtpDocumentForChild(
chan);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
int64_t contentLength;
chan->GetContentLength(&contentLength);
nsCString contentType;
chan->GetContentType(contentType);
nsresult channelStatus = NS_OK;
chan->GetStatus(&channelStatus);
nsCString entityID;
nsCOMPtr<nsIResumableChannel> resChan = do_QueryInterface(aRequest);
MOZ_ASSERT(
resChan); // both FTP and HTTP should implement nsIResumableChannel
if (resChan) {
resChan->GetEntityID(entityID);
}
PRTime lastModified = 0;
nsCOMPtr<nsIFTPChannel> ftpChan = do_QueryInterface(aRequest);
if (ftpChan) {
ftpChan->GetLastModifiedTime(&lastModified);
}
nsCOMPtr<nsIHttpChannelInternal> httpChan = do_QueryInterface(aRequest);
if (httpChan) {
Unused << httpChan->GetLastModifiedTime(&lastModified);
}
URIParams uriparam;
nsCOMPtr<nsIURI> uri;
chan->GetURI(getter_AddRefs(uri));
SerializeURI(uri, uriparam);
if (mIPCClosed ||
!SendOnStartRequest(channelStatus, contentLength, contentType,
lastModified, entityID, uriparam)) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
NS_IMETHODIMP
FTPChannelParent::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
LOG(("FTPChannelParent::OnStopRequest: [this=%p status=%" PRIu32 "]\n", this,
static_cast<uint32_t>(aStatusCode)));
if (mIPCClosed || !SendOnStopRequest(aStatusCode, mErrorMsg, mUseUTF8)) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// FTPChannelParent::nsIStreamListener
//-----------------------------------------------------------------------------
NS_IMETHODIMP
FTPChannelParent::OnDataAvailable(nsIRequest* aRequest,
nsIInputStream* aInputStream,
uint64_t aOffset, uint32_t aCount) {
LOG(("FTPChannelParent::OnDataAvailable [this=%p]\n", this));
nsCString data;
nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount);
if (NS_FAILED(rv)) return rv;
nsresult channelStatus = NS_OK;
mChannel->GetStatus(&channelStatus);
if (mIPCClosed || !SendOnDataAvailable(channelStatus, data, aOffset, aCount))
return NS_ERROR_UNEXPECTED;
return NS_OK;
}
//-----------------------------------------------------------------------------
// FTPChannelParent::nsIParentChannel
//-----------------------------------------------------------------------------
NS_IMETHODIMP
FTPChannelParent::SetParentListener(ParentChannelListener* aListener) {
// Do not need ptr to ParentChannelListener.
return NS_OK;
}
NS_IMETHODIMP
FTPChannelParent::NotifyClassificationFlags(uint32_t aClassificationFlags,
bool aIsThirdParty) {
// One day, this should probably be filled in.
return NS_OK;
}
NS_IMETHODIMP
FTPChannelParent::NotifyFlashPluginStateChanged(
nsIHttpChannel::FlashPluginState aState) {
// One day, this should probably be filled in.
return NS_OK;
}
NS_IMETHODIMP
FTPChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
const nsACString& aProvider,
const nsACString& aFullHash) {
// One day, this should probably be filled in.
return NS_OK;
}
NS_IMETHODIMP
FTPChannelParent::SetClassifierMatchedTrackingInfo(
const nsACString& aLists, const nsACString& aFullHashes) {
// One day, this should probably be filled in.
return NS_OK;
}
NS_IMETHODIMP
FTPChannelParent::Delete() {
if (mIPCClosed || !SendDeleteSelf()) return NS_ERROR_UNEXPECTED;
return NS_OK;
}
NS_IMETHODIMP
FTPChannelParent::GetRemoteType(nsACString& aRemoteType) {
if (!CanSend()) {
return NS_ERROR_UNEXPECTED;
}
dom::PContentParent* pcp = Manager()->Manager();
aRemoteType = static_cast<dom::ContentParent*>(pcp)->GetRemoteType();
return NS_OK;
}
//-----------------------------------------------------------------------------
// FTPChannelParent::nsIInterfaceRequestor
//-----------------------------------------------------------------------------
NS_IMETHODIMP
FTPChannelParent::GetInterface(const nsIID& uuid, void** result) {
if (uuid.Equals(NS_GET_IID(nsIAuthPromptProvider)) ||
uuid.Equals(NS_GET_IID(nsISecureBrowserUI))) {
if (mBrowserParent) {
return mBrowserParent->QueryInterface(uuid, result);
}
} else if (uuid.Equals(NS_GET_IID(nsIAuthPrompt)) ||
uuid.Equals(NS_GET_IID(nsIAuthPrompt2))) {
nsCOMPtr<nsIAuthPromptProvider> provider(do_QueryObject(mBrowserParent));
if (provider) {
nsresult rv = provider->GetAuthPrompt(
nsIAuthPromptProvider::PROMPT_NORMAL, uuid, result);
if (NS_FAILED(rv)) {
return NS_ERROR_NO_INTERFACE;
}
return NS_OK;
}
}
// Only support nsILoadContext if child channel's callbacks did too
if (uuid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) {
nsCOMPtr<nsILoadContext> copy = mLoadContext;
copy.forget(result);
return NS_OK;
}
return QueryInterface(uuid, result);
}
//-----------------------------------------------------------------------------
// FTPChannelParent::nsIChannelEventSink
//-----------------------------------------------------------------------------
NS_IMETHODIMP
FTPChannelParent::AsyncOnChannelRedirect(
nsIChannel* oldChannel, nsIChannel* newChannel, uint32_t redirectFlags,
nsIAsyncVerifyRedirectCallback* callback) {
nsCOMPtr<nsIFTPChannel> ftpChan = do_QueryInterface(newChannel);
if (!ftpChan) {
// when FTP is set to use HTTP proxying, we wind up getting redirected to an
// HTTP channel.
nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(newChannel);
if (!httpChan) return NS_ERROR_UNEXPECTED;
}
mChannel = newChannel;
callback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
NS_IMETHODIMP
FTPChannelParent::SetErrorMsg(const char* aMsg, bool aUseUTF8) {
mErrorMsg = aMsg;
mUseUTF8 = aUseUTF8;
return NS_OK;
}
//---------------------
} // namespace net
} // namespace mozilla

Просмотреть файл

@ -1,92 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_net_FTPChannelParent_h
#define mozilla_net_FTPChannelParent_h
#include "mozilla/net/PFTPChannelParent.h"
#include "mozilla/net/NeckoParent.h"
#include "nsIParentChannel.h"
#include "nsIInterfaceRequestor.h"
#include "nsIChannelEventSink.h"
#include "nsIFTPChannelParentInternal.h"
class nsILoadContext;
namespace mozilla {
namespace dom {
class BrowserParent;
} // namespace dom
namespace net {
class ChannelEventQueue;
class FTPChannelParent final : public PFTPChannelParent,
public nsIParentChannel,
public nsIInterfaceRequestor,
public nsIChannelEventSink,
public nsIFTPChannelParentInternal {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIPARENTCHANNEL
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICHANNELEVENTSINK
FTPChannelParent(dom::BrowserParent* aIframeEmbedding,
nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus);
bool Init(const FTPChannelCreationArgs& aOpenArgs);
NS_IMETHOD SetErrorMsg(const char* aMsg, bool aUseUTF8) override;
protected:
virtual ~FTPChannelParent();
bool DoAsyncOpen(const URIParams& aURI, const uint64_t& aStartPos,
const nsCString& aEntityID,
const Maybe<IPCStream>& aUploadStream,
const Maybe<LoadInfoArgs>& aLoadInfoArgs,
const uint32_t& aLoadFlags);
// used to connect redirected-to channel in parent with just created
// ChildChannel. Used during HTTP->FTP redirects.
bool ConnectChannel(const uint64_t& channelId);
virtual mozilla::ipc::IPCResult RecvCancel(const nsresult& status) override;
virtual mozilla::ipc::IPCResult RecvSuspend() override;
virtual mozilla::ipc::IPCResult RecvResume() override;
virtual void ActorDestroy(ActorDestroyReason why) override;
// if configured to use HTTP proxy for FTP, this can an an HTTP channel.
nsCOMPtr<nsIChannel> mChannel;
bool mIPCClosed;
nsCOMPtr<nsILoadContext> mLoadContext;
PBOverrideStatus mPBOverride;
// Set to the canceled status value if the main channel was canceled.
nsresult mStatus;
RefPtr<mozilla::dom::BrowserParent> mBrowserParent;
RefPtr<ChannelEventQueue> mEventQ;
nsCString mErrorMsg;
bool mUseUTF8;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_FTPChannelParent_h

Просмотреть файл

@ -1,54 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PNecko;
include URIParams;
//FIXME: bug #792908 (NeckoChannelParams already included by PNecko)
include NeckoChannelParams;
using PRTime from "prtime.h";
namespace mozilla {
namespace net {
async protocol PFTPChannel
{
manager PNecko;
parent:
// Note: channels are opened during construction, so no open method here:
// see PNecko.ipdl
async __delete__();
async Cancel(nsresult status);
async Suspend();
async Resume();
child:
async OnStartRequest(nsresult aChannelStatus,
int64_t aContentLength,
nsCString aContentType,
PRTime aLastModified,
nsCString aEntityID,
URIParams aURI);
async OnDataAvailable(nsresult channelStatus,
nsCString data,
uint64_t offset,
uint32_t count);
async OnStopRequest(nsresult channelStatus,
nsCString aErrorMsg,
bool aUseUTF8);
async FailedAsyncOpen(nsresult statusCode);
async DeleteSelf();
};
} // namespace net
} // namespace mozilla

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,4 +0,0 @@
Test
here
there
everywhere

Просмотреть файл

@ -1,15 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __ftpCore_h___
#define __ftpCore_h___
#include "nsError.h"
/**
* Status nsresult codes
*/
#endif // __ftpCore_h___

Просмотреть файл

@ -1,50 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
with Files("**"):
BUG_COMPONENT = ("Core", "Networking: FTP")
XPIDL_SOURCES += [
"nsIFTPChannel.idl",
"nsIFTPChannelParentInternal.idl",
]
XPIDL_MODULE = "necko_ftp"
EXPORTS += [
"ftpCore.h",
]
EXPORTS.mozilla.net += [
"FTPChannelChild.h",
"FTPChannelParent.h",
]
UNIFIED_SOURCES += [
"FTPChannelChild.cpp",
"FTPChannelParent.cpp",
"nsFTPChannel.cpp",
"nsFtpConnectionThread.cpp",
"nsFtpControlConnection.cpp",
"nsFtpProtocolHandler.cpp",
]
IPDL_SOURCES += [
"PFTPChannel.ipdl",
]
include("/ipc/chromium/chromium-config.mozbuild")
FINAL_LIBRARY = "xul"
LOCAL_INCLUDES += [
"/netwerk/base",
]
if CONFIG["CC_TYPE"] in ("clang", "gcc"):
CXXFLAGS += ["-Wno-error=shadow"]
include("/tools/fuzzing/libfuzzer-config.mozbuild")

Просмотреть файл

@ -1,213 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=4 sts=2 sw=2 et cin: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsFTPChannel.h"
#include "nsFtpConnectionThread.h" // defines nsFtpState
#include "nsThreadUtils.h"
#include "mozilla/Attributes.h"
using namespace mozilla;
using namespace mozilla::net;
extern LazyLogModule gFTPLog;
// There are two transport connections established for an
// ftp connection. One is used for the command channel , and
// the other for the data channel. The command channel is the first
// connection made and is used to negotiate the second, data, channel.
// The data channel is driven by the command channel and is either
// initiated by the server (PORT command) or by the client (PASV command).
// Client initiation is the most common case and is attempted first.
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS_INHERITED(nsFtpChannel, nsBaseChannel, nsIUploadChannel,
nsIResumableChannel, nsIFTPChannel,
nsIProxiedChannel, nsIForcePendingChannel,
nsISupportsWeakReference)
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsFtpChannel::SetUploadStream(nsIInputStream* stream,
const nsACString& contentType,
int64_t contentLength) {
NS_ENSURE_TRUE(!Pending(), NS_ERROR_IN_PROGRESS);
mUploadStream = stream;
// NOTE: contentLength is intentionally ignored here.
return NS_OK;
}
NS_IMETHODIMP
nsFtpChannel::GetUploadStream(nsIInputStream** aStream) {
NS_ENSURE_ARG_POINTER(aStream);
nsCOMPtr<nsIInputStream> stream = mUploadStream;
stream.forget(aStream);
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsFtpChannel::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID) {
NS_ENSURE_TRUE(!Pending(), NS_ERROR_IN_PROGRESS);
mEntityID = aEntityID;
mStartPos = aStartPos;
mResumeRequested = (mStartPos || !mEntityID.IsEmpty());
return NS_OK;
}
NS_IMETHODIMP
nsFtpChannel::GetEntityID(nsACString& entityID) {
if (mEntityID.IsEmpty()) return NS_ERROR_NOT_RESUMABLE;
entityID = mEntityID;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsFtpChannel::GetProxyInfo(nsIProxyInfo** aProxyInfo) {
nsCOMPtr<nsIProxyInfo> info = ProxyInfo();
info.forget(aProxyInfo);
return NS_OK;
}
NS_IMETHODIMP nsFtpChannel::GetHttpProxyConnectResponseCode(
int32_t* aResponseCode) {
return NS_ERROR_NOT_IMPLEMENTED;
}
//-----------------------------------------------------------------------------
nsresult nsFtpChannel::OpenContentStream(bool async, nsIInputStream** result,
nsIChannel** channel) {
if (!async) return NS_ERROR_NOT_IMPLEMENTED;
RefPtr<nsFtpState> state = new nsFtpState();
nsresult rv = state->Init(this);
if (NS_FAILED(rv)) {
return rv;
}
state.forget(result);
return NS_OK;
}
bool nsFtpChannel::GetStatusArg(nsresult status, nsString& statusArg) {
nsAutoCString host;
URI()->GetHost(host);
CopyUTF8toUTF16(host, statusArg);
return true;
}
void nsFtpChannel::OnCallbacksChanged() { mFTPEventSink = nullptr; }
//-----------------------------------------------------------------------------
namespace {
class FTPEventSinkProxy final : public nsIFTPEventSink {
~FTPEventSinkProxy() = default;
public:
explicit FTPEventSinkProxy(nsIFTPEventSink* aTarget)
: mTarget(aTarget), mEventTarget(GetCurrentEventTarget()) {}
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIFTPEVENTSINK
class OnFTPControlLogRunnable : public Runnable {
public:
OnFTPControlLogRunnable(nsIFTPEventSink* aTarget, bool aServer,
const char* aMessage)
: mozilla::Runnable("FTPEventSinkProxy::OnFTPControlLogRunnable"),
mTarget(aTarget),
mServer(aServer),
mMessage(aMessage) {}
NS_DECL_NSIRUNNABLE
private:
nsCOMPtr<nsIFTPEventSink> mTarget;
bool mServer;
nsCString mMessage;
};
private:
nsCOMPtr<nsIFTPEventSink> mTarget;
nsCOMPtr<nsIEventTarget> mEventTarget;
};
NS_IMPL_ISUPPORTS(FTPEventSinkProxy, nsIFTPEventSink)
NS_IMETHODIMP
FTPEventSinkProxy::OnFTPControlLog(bool aServer, const char* aMsg) {
RefPtr<OnFTPControlLogRunnable> r =
new OnFTPControlLogRunnable(mTarget, aServer, aMsg);
return mEventTarget->Dispatch(r, NS_DISPATCH_NORMAL);
}
NS_IMETHODIMP
FTPEventSinkProxy::OnFTPControlLogRunnable::Run() {
mTarget->OnFTPControlLog(mServer, mMessage.get());
return NS_OK;
}
} // namespace
void nsFtpChannel::GetFTPEventSink(nsCOMPtr<nsIFTPEventSink>& aResult) {
if (!mFTPEventSink) {
nsCOMPtr<nsIFTPEventSink> ftpSink;
GetCallback(ftpSink);
if (ftpSink) {
mFTPEventSink = new FTPEventSinkProxy(ftpSink);
}
}
aResult = mFTPEventSink;
}
NS_IMETHODIMP
nsFtpChannel::ForcePending(bool aForcePending) {
// Set true here so IsPending will return true.
// Required for callback diversion from child back to parent. In such cases
// OnStopRequest can be called in the parent before callbacks are diverted
// back from the child to the listener in the parent.
mForcePending = aForcePending;
return NS_OK;
}
NS_IMETHODIMP
nsFtpChannel::IsPending(bool* result) {
*result = Pending();
return NS_OK;
}
bool nsFtpChannel::Pending() const {
return nsBaseChannel::Pending() || mForcePending;
}
NS_IMETHODIMP
nsFtpChannel::Suspend() {
LOG(("nsFtpChannel::Suspend [this=%p]\n", this));
NS_ENSURE_TRUE(Pending(), NS_ERROR_NOT_AVAILABLE);
++mSuspendCount;
return nsBaseChannel::Suspend();
}
NS_IMETHODIMP
nsFtpChannel::Resume() {
LOG(("nsFtpChannel::Resume [this=%p]\n", this));
NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED);
--mSuspendCount;
return nsBaseChannel::Resume();
}

Просмотреть файл

@ -1,115 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=4 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsFTPChannel_h___
#define nsFTPChannel_h___
#include "nsBaseChannel.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsIFTPChannel.h"
#include "nsIForcePendingChannel.h"
#include "nsIUploadChannel.h"
#include "nsIProxyInfo.h"
#include "nsIProxiedChannel.h"
#include "nsIResumableChannel.h"
#include "nsWeakReference.h"
class nsIURI;
class nsFtpChannel final : public nsBaseChannel,
public nsIFTPChannel,
public nsIUploadChannel,
public nsIResumableChannel,
public nsIProxiedChannel,
public nsIForcePendingChannel,
public nsSupportsWeakReference {
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIUPLOADCHANNEL
NS_DECL_NSIRESUMABLECHANNEL
NS_DECL_NSIPROXIEDCHANNEL
nsFtpChannel(nsIURI* uri, nsIProxyInfo* pi)
: mProxyInfo(pi),
mStartPos(0),
mResumeRequested(false),
mLastModifiedTime(0),
mForcePending(false),
mSuspendCount(0) {
SetURI(uri);
}
void UpdateURI(nsIURI* aURI) {
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread(), "Not thread-safe.");
mURI = aURI;
}
nsIProxyInfo* ProxyInfo() { return mProxyInfo; }
void SetProxyInfo(nsIProxyInfo* pi) { mProxyInfo = pi; }
NS_IMETHOD IsPending(bool* result) override;
// This is a short-cut to calling nsIRequest::IsPending().
// Overrides Pending in nsBaseChannel.
bool Pending() const override;
// Were we asked to resume a download?
bool ResumeRequested() { return mResumeRequested; }
// Download from this byte offset
uint64_t StartPos() { return mStartPos; }
// ID of the entity to resume downloading
const nsCString& EntityID() { return mEntityID; }
void SetEntityID(const nsACString& entityID) { mEntityID = entityID; }
NS_IMETHOD GetLastModifiedTime(PRTime* lastModifiedTime) override {
*lastModifiedTime = mLastModifiedTime;
return NS_OK;
}
NS_IMETHOD SetLastModifiedTime(PRTime lastModifiedTime) override {
mLastModifiedTime = lastModifiedTime;
return NS_OK;
}
// Data stream to upload
nsIInputStream* UploadStream() { return mUploadStream; }
// Helper function for getting the nsIFTPEventSink.
void GetFTPEventSink(nsCOMPtr<nsIFTPEventSink>& aResult);
NS_IMETHOD Suspend() override;
NS_IMETHOD Resume() override;
public:
NS_IMETHOD ForcePending(bool aForcePending) override;
protected:
virtual ~nsFtpChannel() = default;
virtual nsresult OpenContentStream(bool async, nsIInputStream** result,
nsIChannel** channel) override;
virtual bool GetStatusArg(nsresult status, nsString& statusArg) override;
virtual void OnCallbacksChanged() override;
private:
nsCOMPtr<nsIProxyInfo> mProxyInfo;
nsCOMPtr<nsIFTPEventSink> mFTPEventSink;
nsCOMPtr<nsIInputStream> mUploadStream;
uint64_t mStartPos;
nsCString mEntityID;
bool mResumeRequested;
PRTime mLastModifiedTime;
bool mForcePending;
// Current suspension depth for this channel object
uint32_t mSuspendCount;
};
#endif /* nsFTPChannel_h___ */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,254 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __nsFtpConnectionThread__h_
#define __nsFtpConnectionThread__h_
#include "nsBaseContentStream.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsIAsyncInputStream.h"
#include "nsITransport.h"
#include "mozilla/net/DNS.h"
#include "nsFtpControlConnection.h"
#include "nsIProtocolProxyCallback.h"
// ftp server types
#define FTP_GENERIC_TYPE 0
#define FTP_UNIX_TYPE 1
#define FTP_VMS_TYPE 8
#define FTP_NT_TYPE 9
#define FTP_OS2_TYPE 11
// ftp states
typedef enum _FTP_STATE {
///////////////////////
//// Internal states
FTP_INIT,
FTP_COMMAND_CONNECT,
FTP_READ_BUF,
FTP_ERROR,
FTP_COMPLETE,
///////////////////////
//// Command channel connection setup states
FTP_S_USER,
FTP_R_USER,
FTP_S_PASS,
FTP_R_PASS,
FTP_S_SYST,
FTP_R_SYST,
FTP_S_ACCT,
FTP_R_ACCT,
FTP_S_TYPE,
FTP_R_TYPE,
FTP_S_CWD,
FTP_R_CWD,
FTP_S_SIZE,
FTP_R_SIZE,
FTP_S_MDTM,
FTP_R_MDTM,
FTP_S_REST,
FTP_R_REST,
FTP_S_RETR,
FTP_R_RETR,
FTP_S_STOR,
FTP_R_STOR,
FTP_S_LIST,
FTP_R_LIST,
FTP_S_PASV,
FTP_R_PASV,
FTP_S_PWD,
FTP_R_PWD,
FTP_S_FEAT,
FTP_R_FEAT,
FTP_S_OPTS,
FTP_R_OPTS
} FTP_STATE;
// higher level ftp actions
typedef enum _FTP_ACTION { GET, PUT } FTP_ACTION;
class nsFtpChannel;
class nsICancelable;
class nsIProxyInfo;
class nsIStreamListener;
// The nsFtpState object is the content stream for the channel. It implements
// nsIInputStreamCallback, so it can read data from the control connection. It
// implements nsITransportEventSink so it can mix status events from both the
// control connection and the data connection.
class nsFtpState final : public nsBaseContentStream,
public nsIInputStreamCallback,
public nsITransportEventSink,
public nsIRequestObserver,
public nsFtpControlConnectionListener,
public nsIProtocolProxyCallback {
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSITRANSPORTEVENTSINK
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSIPROTOCOLPROXYCALLBACK
// Override input stream methods:
NS_IMETHOD CloseWithStatus(nsresult status) override;
NS_IMETHOD Available(uint64_t* result) override;
NS_IMETHOD ReadSegments(nsWriteSegmentFun fun, void* closure, uint32_t count,
uint32_t* result) override;
// nsFtpControlConnectionListener methods:
virtual void OnControlDataAvailable(const char* data,
uint32_t dataLen) override;
virtual void OnControlError(nsresult status) override;
nsFtpState();
nsresult Init(nsFtpChannel* channel);
protected:
// Notification from nsBaseContentStream::AsyncWait
virtual void OnCallbackPending() override;
private:
virtual ~nsFtpState();
///////////////////////////////////
// BEGIN: STATE METHODS
nsresult S_user();
FTP_STATE R_user();
nsresult S_pass();
FTP_STATE R_pass();
nsresult S_syst();
FTP_STATE R_syst();
nsresult S_acct();
FTP_STATE R_acct();
nsresult S_type();
FTP_STATE R_type();
nsresult S_cwd();
FTP_STATE R_cwd();
nsresult S_size();
FTP_STATE R_size();
nsresult S_mdtm();
FTP_STATE R_mdtm();
nsresult S_list();
FTP_STATE R_list();
nsresult S_rest();
FTP_STATE R_rest();
nsresult S_retr();
FTP_STATE R_retr();
nsresult S_stor();
FTP_STATE R_stor();
nsresult S_pasv();
FTP_STATE R_pasv();
nsresult S_pwd();
FTP_STATE R_pwd();
nsresult S_feat();
FTP_STATE R_feat();
nsresult S_opts();
FTP_STATE R_opts();
// END: STATE METHODS
///////////////////////////////////
// internal methods
void MoveToNextState(FTP_STATE nextState);
nsresult Process();
void KillControlConnection();
nsresult StopProcessing();
nsresult EstablishControlConnection();
nsresult SendFTPCommand(const nsACString& command);
void ConvertFilespecToVMS(nsCString& fileSpec);
void ConvertDirspecToVMS(nsCString& fileSpec);
void ConvertDirspecFromVMS(nsCString& fileSpec);
nsresult BuildStreamConverter(nsIStreamListener** convertStreamListener);
nsresult SetContentType();
/**
* This method is called to kick-off the FTP state machine. mState is
* reset to FTP_COMMAND_CONNECT, and the FTP state machine progresses from
* there. This method is initially called (indirectly) from the channel's
* AsyncOpen implementation.
*/
void Connect();
///////////////////////////////////
// Private members
nsCOMPtr<nsIProxiedProtocolHandler> mHandler; // Ref to gFtpHandler
// ****** state machine vars
FTP_STATE mState; // the current state
FTP_STATE mNextState; // the next state
bool mKeepRunning; // thread event loop boolean
int32_t mResponseCode; // the last command response code
nsCString mResponseMsg; // the last command response text
// ****** channel/transport/stream vars
RefPtr<nsFtpControlConnection>
mControlConnection; // cacheable control connection (owns mCPipe)
bool mReceivedControlData;
bool mTryingCachedControl; // retrying the password
bool mRETRFailed; // Did we already try a RETR and it failed?
uint64_t mFileSize;
nsCString mModTime;
// ****** consumer vars
RefPtr<nsFtpChannel>
mChannel; // our owning FTP channel we pass through our events
nsCOMPtr<nsIProxyInfo> mProxyInfo;
// ****** connection cache vars
int32_t mServerType; // What kind of server are we talking to
// ****** protocol interpretation related state vars
nsString mUsername; // username
nsString mPassword; // password
FTP_ACTION mAction; // the higher level action (GET/PUT)
bool mAnonymous; // try connecting anonymous (default)
bool mRetryPass; // retrying the password
bool mStorReplyReceived; // FALSE if waiting for STOR
// completion status from server
bool mRlist1xxReceived; // TRUE if we have received a LIST 1xx
// response from the server
bool mRretr1xxReceived; // TRUE if we have received a RETR 1xx
// response from the server
bool mRstor1xxReceived; // TRUE if we have received a STOR 1xx
// response from the server
nsresult mInternalError; // represents internal state errors
bool mReconnectAndLoginAgain;
bool mCacheConnection;
// ****** URI vars
int32_t mPort; // the port to connect to
nsString mFilename; // url filename (if any)
nsCString mPath; // the url's path
nsCString mPwd; // login Path
// ****** other vars
nsCOMPtr<nsITransport> mDataTransport;
nsCOMPtr<nsIAsyncInputStream> mDataStream;
nsCOMPtr<nsIRequest> mUploadRequest;
bool mAddressChecked;
bool mServerIsIPv6;
bool mUseUTF8;
mozilla::net::NetAddr mServerAddress;
// ***** control read gvars
nsresult mControlStatus;
nsCString mControlReadCarryOverBuf;
nsCString mSuppliedEntityID;
nsCOMPtr<nsICancelable> mProxyRequest;
bool mDeferredCallbackPending;
};
#endif //__nsFtpConnectionThread__h_

Просмотреть файл

@ -1,170 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsIOService.h"
#include "nsFtpControlConnection.h"
#include "nsFtpProtocolHandler.h"
#include "mozilla/Logging.h"
#include "nsIInputStream.h"
#include "nsISocketTransportService.h"
#include "nsISocketTransport.h"
#include "nsThreadUtils.h"
#include "nsNetCID.h"
#include "nsTArray.h"
#include <algorithm>
using namespace mozilla;
using namespace mozilla::net;
extern LazyLogModule gFTPLog;
#define LOG(args) MOZ_LOG(gFTPLog, mozilla::LogLevel::Debug, args)
#define LOG_INFO(args) MOZ_LOG(gFTPLog, mozilla::LogLevel::Info, args)
//
// nsFtpControlConnection implementation ...
//
NS_IMPL_ISUPPORTS(nsFtpControlConnection, nsIInputStreamCallback)
NS_IMETHODIMP
nsFtpControlConnection::OnInputStreamReady(nsIAsyncInputStream* stream) {
char data[4096];
// Consume data whether we have a listener or not.
uint64_t avail64;
uint32_t avail = 0;
nsresult rv = stream->Available(&avail64);
if (NS_SUCCEEDED(rv)) {
avail = (uint32_t)std::min(avail64, (uint64_t)sizeof(data));
uint32_t n;
rv = stream->Read(data, avail, &n);
if (NS_SUCCEEDED(rv)) avail = n;
}
// It's important that we null out mListener before calling one of its
// methods as it may call WaitData, which would queue up another read.
RefPtr<nsFtpControlConnectionListener> listener;
listener.swap(mListener);
if (!listener) return NS_OK;
if (NS_FAILED(rv)) {
listener->OnControlError(rv);
} else {
listener->OnControlDataAvailable(data, avail);
}
return NS_OK;
}
nsFtpControlConnection::nsFtpControlConnection(const nsACString& host,
uint32_t port)
: mServerType(0),
mSuspendedWrite(0),
mSessionId(gFtpHandler->GetSessionId()),
mUseUTF8(false),
mHost(host),
mPort(port) {
LOG_INFO(("FTP:CC created @%p", this));
}
nsFtpControlConnection::~nsFtpControlConnection() {
LOG_INFO(("FTP:CC destroyed @%p", this));
}
bool nsFtpControlConnection::IsAlive() {
if (!mSocket) return false;
bool isAlive = false;
mSocket->IsAlive(&isAlive);
return isAlive;
}
nsresult nsFtpControlConnection::Connect(nsIProxyInfo* proxyInfo,
nsITransportEventSink* eventSink) {
if (mSocket) return NS_OK;
// build our own
nsresult rv;
nsCOMPtr<nsISocketTransportService> sts =
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
rv = sts->CreateTransport(nsTArray<nsCString>(), mHost, mPort, proxyInfo,
nullptr,
getter_AddRefs(mSocket)); // the command transport
if (NS_FAILED(rv)) return rv;
mSocket->SetQoSBits(gFtpHandler->GetControlQoSBits());
// proxy transport events back to current thread
if (eventSink) mSocket->SetEventSink(eventSink, GetCurrentEventTarget());
// open buffered, blocking output stream to socket. so long as commands
// do not exceed 1024 bytes in length, the writing thread (the main thread)
// will not block. this should be OK.
rv = mSocket->OpenOutputStream(nsITransport::OPEN_BLOCKING, 1024, 1,
getter_AddRefs(mSocketOutput));
if (NS_FAILED(rv)) return rv;
// open buffered, non-blocking/asynchronous input stream to socket.
nsCOMPtr<nsIInputStream> inStream;
rv = mSocket->OpenInputStream(0, nsIOService::gDefaultSegmentSize,
nsIOService::gDefaultSegmentCount,
getter_AddRefs(inStream));
if (NS_SUCCEEDED(rv)) mSocketInput = do_QueryInterface(inStream);
return rv;
}
nsresult nsFtpControlConnection::WaitData(
nsFtpControlConnectionListener* listener) {
LOG(("FTP:(%p) wait data [listener=%p]\n", this, listener));
// If listener is null, then simply disconnect the listener. Otherwise,
// ensure that we are listening.
if (!listener) {
mListener = nullptr;
return NS_OK;
}
NS_ENSURE_STATE(mSocketInput);
mListener = listener;
return mSocketInput->AsyncWait(this, 0, 0, GetCurrentEventTarget());
}
nsresult nsFtpControlConnection::Disconnect(nsresult status) {
if (!mSocket) return NS_OK; // already disconnected
LOG_INFO(("FTP:(%p) CC disconnecting (%" PRIx32 ")", this,
static_cast<uint32_t>(status)));
if (NS_FAILED(status)) {
// break cyclic reference!
mSocket->Close(status);
mSocket = nullptr;
mSocketInput->AsyncWait(nullptr, 0, 0, nullptr); // clear any observer
mSocketInput = nullptr;
mSocketOutput = nullptr;
}
return NS_OK;
}
nsresult nsFtpControlConnection::Write(const nsACString& command) {
NS_ENSURE_STATE(mSocketOutput);
uint32_t len = command.Length();
uint32_t cnt;
nsresult rv = mSocketOutput->Write(command.Data(), len, &cnt);
if (NS_FAILED(rv)) return rv;
if (len != cnt) return NS_ERROR_FAILURE;
return NS_OK;
}

Просмотреть файл

@ -1,83 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set et ts=4 sts=2 sw=2 cin: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsFtpControlConnection_h___
#define nsFtpControlConnection_h___
#include "nsCOMPtr.h"
#include "nsISocketTransport.h"
#include "nsIAsyncInputStream.h"
#include "nsString.h"
#include "mozilla/Attributes.h"
class nsIOutputStream;
class nsIProxyInfo;
class nsITransportEventSink;
class nsFtpControlConnectionListener : public nsISupports {
public:
/**
* Called when a chunk of data arrives on the control connection.
* @param data
* The new data or null if an error occurred.
* @param dataLen
* The data length in bytes.
*/
virtual void OnControlDataAvailable(const char* data, uint32_t dataLen) = 0;
/**
* Called when an error occurs on the control connection.
* @param status
* A failure code providing more info about the error.
*/
virtual void OnControlError(nsresult status) = 0;
};
class nsFtpControlConnection final : public nsIInputStreamCallback {
~nsFtpControlConnection();
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIINPUTSTREAMCALLBACK
nsFtpControlConnection(const nsACString& host, uint32_t port);
nsresult Connect(nsIProxyInfo* proxyInfo, nsITransportEventSink* eventSink);
nsresult Disconnect(nsresult status);
nsresult Write(const nsACString& command);
bool IsAlive();
nsITransport* Transport() { return mSocket; }
/**
* Call this function to be notified asynchronously when there is data
* available for the socket. The listener passed to this method replaces
* any existing listener, and the listener can be null to disconnect the
* previous listener.
*/
nsresult WaitData(nsFtpControlConnectionListener* listener);
uint32_t mServerType; // what kind of server is it.
nsString mPassword;
int32_t mSuspendedWrite;
nsCString mPwd;
uint32_t mSessionId;
bool mUseUTF8;
private:
nsCString mHost;
uint32_t mPort;
nsCOMPtr<nsISocketTransport> mSocket;
nsCOMPtr<nsIOutputStream> mSocketOutput;
nsCOMPtr<nsIAsyncInputStream> mSocketInput;
RefPtr<nsFtpControlConnectionListener> mListener;
};
#endif

Просмотреть файл

@ -1,331 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/net/NeckoChild.h"
#include "mozilla/net/FTPChannelChild.h"
using namespace mozilla;
using namespace mozilla::net;
#include "nsFtpProtocolHandler.h"
#include "nsFTPChannel.h"
#include "mozilla/Logging.h"
#include "nsIPrefBranch.h"
#include "nsIObserverService.h"
#include "nsEscape.h"
#include "nsAlgorithm.h"
//-----------------------------------------------------------------------------
//
// Log module for FTP Protocol logging...
//
// To enable logging (see prlog.h for full details):
//
// set MOZ_LOG=nsFtp:5
// set MOZ_LOG_FILE=ftp.log
//
// This enables LogLevel::Debug level information and places all output in
// the file ftp.log.
//
LazyLogModule gFTPLog("nsFtp");
#undef LOG
#define LOG(args) MOZ_LOG(gFTPLog, mozilla::LogLevel::Debug, args)
//-----------------------------------------------------------------------------
#define IDLE_TIMEOUT_PREF "network.ftp.idleConnectionTimeout"
#define IDLE_CONNECTION_LIMIT 8 /* TODO pref me */
#define ENABLED_PREF "network.ftp.enabled"
#define QOS_DATA_PREF "network.ftp.data.qos"
#define QOS_CONTROL_PREF "network.ftp.control.qos"
nsFtpProtocolHandler* gFtpHandler = nullptr;
//-----------------------------------------------------------------------------
nsFtpProtocolHandler::nsFtpProtocolHandler()
: mIdleTimeout(-1),
mEnabled(true),
mSessionId(0),
mControlQoSBits(0x00),
mDataQoSBits(0x00) {
LOG(("FTP:creating handler @%p\n", this));
gFtpHandler = this;
}
nsFtpProtocolHandler::~nsFtpProtocolHandler() {
LOG(("FTP:destroying handler @%p\n", this));
NS_ASSERTION(mRootConnectionList.Length() == 0, "why wasn't Observe called?");
gFtpHandler = nullptr;
}
NS_IMPL_ISUPPORTS(nsFtpProtocolHandler, nsIProtocolHandler,
nsIProxiedProtocolHandler, nsIObserver,
nsISupportsWeakReference)
nsresult nsFtpProtocolHandler::Init() {
if (IsNeckoChild()) NeckoChild::InitNeckoChild();
if (mIdleTimeout == -1) {
nsresult rv;
nsCOMPtr<nsIPrefBranch> branch =
do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
rv = branch->GetIntPref(IDLE_TIMEOUT_PREF, &mIdleTimeout);
if (NS_FAILED(rv)) mIdleTimeout = 5 * 60; // 5 minute default
rv = branch->AddObserver(IDLE_TIMEOUT_PREF, this, true);
if (NS_FAILED(rv)) return rv;
rv = branch->GetBoolPref(ENABLED_PREF, &mEnabled);
if (NS_FAILED(rv)) mEnabled = true;
rv = branch->AddObserver(ENABLED_PREF, this, true);
if (NS_FAILED(rv)) return rv;
int32_t val;
rv = branch->GetIntPref(QOS_DATA_PREF, &val);
if (NS_SUCCEEDED(rv)) mDataQoSBits = (uint8_t)clamped(val, 0, 0xff);
rv = branch->AddObserver(QOS_DATA_PREF, this, true);
if (NS_FAILED(rv)) return rv;
rv = branch->GetIntPref(QOS_CONTROL_PREF, &val);
if (NS_SUCCEEDED(rv)) mControlQoSBits = (uint8_t)clamped(val, 0, 0xff);
rv = branch->AddObserver(QOS_CONTROL_PREF, this, true);
if (NS_FAILED(rv)) return rv;
}
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
observerService->AddObserver(this, "network:offline-about-to-go-offline",
true);
observerService->AddObserver(this, "net:clear-active-logins", true);
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsIProtocolHandler methods:
NS_IMETHODIMP
nsFtpProtocolHandler::GetScheme(nsACString& result) {
result.AssignLiteral("ftp");
return NS_OK;
}
NS_IMETHODIMP
nsFtpProtocolHandler::GetDefaultPort(int32_t* result) {
*result = 21;
return NS_OK;
}
NS_IMETHODIMP
nsFtpProtocolHandler::GetProtocolFlags(uint32_t* result) {
*result = URI_STD | ALLOWS_PROXY | ALLOWS_PROXY_HTTP | URI_LOADABLE_BY_ANYONE;
return NS_OK;
}
NS_IMETHODIMP
nsFtpProtocolHandler::NewChannel(nsIURI* url, nsILoadInfo* aLoadInfo,
nsIChannel** result) {
return NewProxiedChannel(url, nullptr, 0, nullptr, aLoadInfo, result);
}
NS_IMETHODIMP
nsFtpProtocolHandler::NewProxiedChannel(nsIURI* uri, nsIProxyInfo* proxyInfo,
uint32_t proxyResolveFlags,
nsIURI* proxyURI,
nsILoadInfo* aLoadInfo,
nsIChannel** result) {
if (!mEnabled) {
return NS_ERROR_UNKNOWN_PROTOCOL;
}
NS_ENSURE_ARG_POINTER(uri);
RefPtr<nsBaseChannel> channel;
if (IsNeckoChild())
channel = new FTPChannelChild(uri);
else
channel = new nsFtpChannel(uri, proxyInfo);
// set the loadInfo on the new channel
nsresult rv = channel->SetLoadInfo(aLoadInfo);
NS_ENSURE_SUCCESS(rv, rv);
channel.forget(result);
return rv;
}
NS_IMETHODIMP
nsFtpProtocolHandler::AllowPort(int32_t port, const char* scheme,
bool* _retval) {
*_retval = (port == 21 || port == 22);
return NS_OK;
}
// connection cache methods
void nsFtpProtocolHandler::Timeout(nsITimer* aTimer, void* aClosure) {
LOG(("FTP:timeout reached for %p\n", aClosure));
bool found = gFtpHandler->mRootConnectionList.RemoveElement(aClosure);
if (!found) {
NS_ERROR("timerStruct not found");
return;
}
timerStruct* s = (timerStruct*)aClosure;
delete s;
}
nsresult nsFtpProtocolHandler::RemoveConnection(
nsIURI* aKey, nsFtpControlConnection** _retval) {
NS_ASSERTION(_retval, "null pointer");
NS_ASSERTION(aKey, "null pointer");
*_retval = nullptr;
nsAutoCString spec;
aKey->GetPrePath(spec);
LOG(("FTP:removing connection for %s\n", spec.get()));
timerStruct* ts = nullptr;
uint32_t i;
bool found = false;
for (i = 0; i < mRootConnectionList.Length(); ++i) {
ts = mRootConnectionList[i];
if (strcmp(spec.get(), ts->key) == 0) {
found = true;
mRootConnectionList.RemoveElementAt(i);
break;
}
}
if (!found) return NS_ERROR_FAILURE;
// swap connection ownership
ts->conn.forget(_retval);
delete ts;
return NS_OK;
}
nsresult nsFtpProtocolHandler::InsertConnection(nsIURI* aKey,
nsFtpControlConnection* aConn) {
NS_ASSERTION(aConn, "null pointer");
NS_ASSERTION(aKey, "null pointer");
if (aConn->mSessionId != mSessionId) return NS_ERROR_FAILURE;
nsAutoCString spec;
aKey->GetPrePath(spec);
LOG(("FTP:inserting connection for %s\n", spec.get()));
timerStruct* ts = new timerStruct();
if (!ts) return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsITimer> timer;
nsresult rv = NS_NewTimerWithFuncCallback(
getter_AddRefs(timer), nsFtpProtocolHandler::Timeout, ts,
mIdleTimeout * 1000, nsITimer::TYPE_REPEATING_SLACK,
"nsFtpProtocolHandler::InsertConnection");
if (NS_FAILED(rv)) {
delete ts;
return rv;
}
ts->key = ToNewCString(spec, mozilla::fallible);
if (!ts->key) {
delete ts;
return NS_ERROR_OUT_OF_MEMORY;
}
// ts->conn is a RefPtr
ts->conn = aConn;
ts->timer = timer;
//
// limit number of idle connections. if limit is reached, then prune
// eldest connection with matching key. if none matching, then prune
// eldest connection.
//
if (mRootConnectionList.Length() == IDLE_CONNECTION_LIMIT) {
uint32_t i;
for (i = 0; i < mRootConnectionList.Length(); ++i) {
timerStruct* candidate = mRootConnectionList[i];
if (strcmp(candidate->key, ts->key) == 0) {
mRootConnectionList.RemoveElementAt(i);
delete candidate;
break;
}
}
if (mRootConnectionList.Length() == IDLE_CONNECTION_LIMIT) {
timerStruct* eldest = mRootConnectionList[0];
mRootConnectionList.RemoveElementAt(0);
delete eldest;
}
}
mRootConnectionList.AppendElement(ts);
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsIObserver
NS_IMETHODIMP
nsFtpProtocolHandler::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
LOG(("FTP:observing [%s]\n", aTopic));
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(aSubject);
if (!branch) {
NS_ERROR("no prefbranch");
return NS_ERROR_UNEXPECTED;
}
int32_t val;
nsresult rv = branch->GetIntPref(IDLE_TIMEOUT_PREF, &val);
if (NS_SUCCEEDED(rv)) mIdleTimeout = val;
bool enabled;
rv = branch->GetBoolPref(ENABLED_PREF, &enabled);
if (NS_SUCCEEDED(rv)) mEnabled = enabled;
rv = branch->GetIntPref(QOS_DATA_PREF, &val);
if (NS_SUCCEEDED(rv)) mDataQoSBits = (uint8_t)clamped(val, 0, 0xff);
rv = branch->GetIntPref(QOS_CONTROL_PREF, &val);
if (NS_SUCCEEDED(rv)) mControlQoSBits = (uint8_t)clamped(val, 0, 0xff);
} else if (!strcmp(aTopic, "network:offline-about-to-go-offline")) {
ClearAllConnections();
} else if (!strcmp(aTopic, "net:clear-active-logins")) {
ClearAllConnections();
mSessionId++;
} else {
MOZ_ASSERT_UNREACHABLE("unexpected topic");
}
return NS_OK;
}
void nsFtpProtocolHandler::ClearAllConnections() {
uint32_t i;
for (i = 0; i < mRootConnectionList.Length(); ++i)
delete mRootConnectionList[i];
mRootConnectionList.Clear();
}

Просмотреть файл

@ -1,85 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsFtpProtocolHandler_h__
#define nsFtpProtocolHandler_h__
#include "nsFtpControlConnection.h"
#include "nsIProxiedProtocolHandler.h"
#include "nsTArray.h"
#include "nsITimer.h"
#include "nsIObserver.h"
#include "nsWeakReference.h"
//-----------------------------------------------------------------------------
class nsFtpProtocolHandler final : public nsIProxiedProtocolHandler,
public nsIObserver,
public nsSupportsWeakReference {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIPROTOCOLHANDLER
NS_DECL_NSIPROXIEDPROTOCOLHANDLER
NS_DECL_NSIOBSERVER
nsFtpProtocolHandler();
nsresult Init();
// FTP Connection list access
nsresult InsertConnection(nsIURI* aKey, nsFtpControlConnection* aConn);
nsresult RemoveConnection(nsIURI* aKey, nsFtpControlConnection** aConn);
uint32_t GetSessionId() { return mSessionId; }
uint8_t GetDataQoSBits() { return mDataQoSBits; }
uint8_t GetControlQoSBits() { return mControlQoSBits; }
private:
virtual ~nsFtpProtocolHandler();
// Stuff for the timer callback function
struct timerStruct {
nsCOMPtr<nsITimer> timer;
RefPtr<nsFtpControlConnection> conn;
char* key;
timerStruct() : key(nullptr) {}
~timerStruct() {
if (timer) timer->Cancel();
if (key) free(key);
if (conn) {
conn->Disconnect(NS_ERROR_ABORT);
}
}
};
static void Timeout(nsITimer* aTimer, void* aClosure);
void ClearAllConnections();
nsTArray<timerStruct*> mRootConnectionList;
int32_t mIdleTimeout;
bool mEnabled;
// When "clear active logins" is performed, all idle connection are dropped
// and mSessionId is incremented. When nsFtpState wants to insert idle
// connection we refuse to cache if its mSessionId is different (i.e.
// control connection had been created before last "clear active logins" was
// performed.
uint32_t mSessionId;
uint8_t mControlQoSBits;
uint8_t mDataQoSBits;
};
//-----------------------------------------------------------------------------
extern nsFtpProtocolHandler* gFtpHandler;
#include "mozilla/Logging.h"
extern mozilla::LazyLogModule gFTPLog;
#endif // !nsFtpProtocolHandler_h__

Просмотреть файл

@ -1,29 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
/**
* This interface may be used to determine if a channel is a FTP channel.
*/
[scriptable, uuid(07f0d5cd-1fd5-4aa3-b6fc-665bdc5dbf9f)]
interface nsIFTPChannel : nsISupports
{
attribute PRTime lastModifiedTime;
};
/**
* This interface may be defined as a notification callback on the FTP
* channel. It allows a consumer to receive a log of the FTP control
* connection conversation.
*/
[scriptable, uuid(455d4234-0330-43d2-bbfb-99afbecbfeb0)]
interface nsIFTPEventSink : nsISupports
{
/**
* XXX document this method! (see bug 328915)
*/
void OnFTPControlLog(in boolean server, in string msg);
};

Просмотреть файл

@ -1,15 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
/**
* This is an internal interface for FTP parent channel.
*/
[builtinclass, uuid(87b58410-83cb-42a7-b57b-27c07ef828d7)]
interface nsIFTPChannelParentInternal : nsISupports
{
void setErrorMsg(in string msg, in boolean useUTF8);
};

Просмотреть файл

@ -1,5 +0,0 @@
<html>
<body>
<h2>Click a link to the left</h2>
</body>
</html>

Просмотреть файл

@ -1,12 +0,0 @@
<html>
<head>
<title>FTP Frameset Test</title>
</head>
<frameset cols="30%,70%" name="ftp_main_frame">
<frame src="menu.html" name="ftp_menu" scrolling="yes" marginwidth="0" marginheight="0" noresize>
<frame src="contents.html" name="ftp_content" scrolling="YES" marginwidth="0" marginheight="0" noresize>
</frameset>
</html>

Просмотреть файл

@ -1,371 +0,0 @@
<html>
<script language="javascript">
/* eslint-disable no-unsanitized/method */
<!--
function add_location(url) {
// faster to do this in one assignment, but who really cares.
var string = '<LI> <a href=\"javascript: ftp_open(\'';
string += url;
string += '\')\"';
string += 'onmouseover=\"window.status=\'ftp://';
string += url;
string += '\'; return true; \">';
string += url;
string += "</a>";
document.writeln(string);
}
function ftp_open(url) {
url = "ftp://" + url;
parent.ftp_content.location = url;
}
// I like this format.
document.writeln("<pre>");
document.writeln("<br><OL><b>Company sites</b>");
add_location("ftp.mozilla.org");
add_location("ftp.sun.com");
add_location("ftp.iplanet.com");
add_location("ftp.netscape.com");
add_location("ftp.apple.com");
add_location("ftp.microsoft.com");
add_location("ftp.netmanage.com");
document.writeln("</OL><br><OL><b>Misc sites</b>");
add_location("cal044202.student.utwente.nl");
add_location("download.intel.com");
add_location("fddisunsite.oit.unc.edu");
add_location("ftp.abas.de");
add_location("ftp.acm.org");
add_location("ftp.acomp.hu");
add_location("ftp.acri.fr");
add_location("ftp.alaska.edu");
add_location("ftp.altera.com");
add_location("ftp.amsat.org");
add_location("ftp.amtp.cam.ac.uk");
add_location("ftp.ar.freebsd.org");
add_location("ftp.ari.net");
add_location("ftp.arl.mil");
add_location("ftp.astro.ulg.ac.be");
add_location("ftp.avery-zweckform.com");
add_location("ftp.awi-bremerhaven.de");
add_location("ftp.axime-is.fr");
add_location("ftp.ba.cnr.it");
add_location("ftp.bath.ac.uk");
add_location("ftp.bic.mni.mcgill.ca");
add_location("ftp.biomed.ruhr-uni-bochum.de");
add_location("ftp.boerde.de");
add_location("ftp.bond.edu.au");
add_location("ftp.boulder.ibm.com");
add_location("ftp.brics.dk");
add_location("ftp.bris.ac.uk");
add_location("ftp.cablelabs.com");
add_location("ftp.cac.psu.edu");
add_location("ftp.cadpoint.se");
add_location("ftp.cas.cz");
add_location("ftp.cciw.ca");
add_location("ftp.ccs.queensu.ca");
add_location("ftp.ccsi.com");
add_location("ftp.cdrom.com");
add_location("ftp.cea.fr");
add_location("ftp.celestial.com");
add_location("ftp.cert.fr");
add_location("ftp.cgd.ucar.edu");
add_location("ftp.chiba-u.ac.jp");
add_location("ftp.cis.ksu.edu");
add_location("ftp.citi2.fr");
add_location("ftp.cityline.net");
add_location("ftp.cnam.fr");
add_location("ftp.cohesive.com");
add_location("ftp.contrib.net");
add_location("ftp.create.ucsb.edu");
add_location("ftp.cronyx.ru");
add_location("ftp.cs.arizona.edu");
add_location("ftp.cs.colorado.edu");
add_location("ftp.cs.concordia.ca");
add_location("ftp.cs.helsinki.fi");
add_location("ftp.cs.jhu.edu");
add_location("ftp.cs.monash.edu.au");
add_location("ftp.cs.ohiou.edu");
add_location("ftp.cs.rug.nl");
add_location("ftp.cs.toronto.edu");
add_location("ftp.cs.umanitoba.ca");
add_location("ftp.cs.uni-dortmund.de");
add_location("ftp.cs.vu.nl");
add_location("ftp.cse.cuhk.edu.hk");
add_location("ftp.cse.unsw.edu.au");
add_location("ftp.csse.monash.edu.au");
add_location("ftp.csus.edu");
add_location("ftp.cullasaja.com");
add_location("ftp.daimi.au.dk");
add_location("ftp.dcs.qmw.ac.uk");
add_location("ftp.delorie.com");
add_location("ftp.dementia.org");
add_location("ftp.dfki.uni-kl.de");
add_location("ftp.dgs.monash.edu.au");
add_location("ftp.dis.strath.ac.uk");
add_location("ftp.dosis.uni-dortmund.de");
add_location("ftp.duke.edu");
add_location("ftp.duplexx.com");
add_location("ftp.ece.ucdavis.edu");
add_location("ftp.ee.lbl.gov");
add_location("ftp.ee.rochester.edu");
add_location("ftp.ee.uts.edu.au");
add_location("ftp.efrei.fr");
add_location("ftp.elet.polimi.it");
add_location("ftp.elite.net");
add_location("ftp.embl-hamburg.de");
add_location("ftp.eng.buffalo.edu");
add_location("ftp.engr.uark.edu");
add_location("ftp.eni.co.jp");
add_location("ftp.enst-bretagne.fr");
add_location("ftp.epix.net");
add_location("ftp.eskimo.com");
add_location("ftp.essential.org");
add_location("ftp.eunet.fi");
add_location("ftp.eurexpo.com");
add_location("ftp.ex.ac.uk");
add_location("ftp.faximum.com");
add_location("ftp.fernuni-hagen.de");
add_location("ftp.fh-dortmund.de");
add_location("ftp.fit.qut.edu.au");
add_location("ftp.forum.swarthmore.edu");
add_location("ftp.fsu.edu");
add_location("ftp.ftp.epson.com");
add_location("ftp.fu-berlin.de");
add_location("ftp.fujixerox.co.jp");
add_location("ftp.game.org");
add_location("ftp.ge.ucl.ac.uk");
add_location("ftp.genetics.wisc.edu");
add_location("ftp.geo.uu.nl");
add_location("ftp.geom.umn.edu");
add_location("ftp.gfdl.gov");
add_location("ftp.gigo.com");
add_location("ftp.giss.nasa.gov");
add_location("ftp.globalnet.co.uk");
add_location("ftp.gnu.org");
add_location("ftp.gnu.vbs.at");
add_location("ftp.gps.caltech.edu");
add_location("ftp.grau-wzs.de");
add_location("ftp.gsoc.dlr.de");
add_location("ftp.gutenberg.org");
add_location("ftp.hawaii.edu");
add_location("ftp.hep.net");
add_location("ftp.hgc.edu");
add_location("ftp.hgmp.mrc.ac.uk");
add_location("ftp.hugin.dk");
add_location("ftp.ic.tsu.ru");
add_location("ftp.icce.rug.nl");
add_location("ftp.icon-stl.net");
add_location("ftp.icor.fr");
add_location("ftp.ics.uci.edu");
add_location("ftp.idsia.ch");
add_location("ftp.ifm.liu.se");
add_location("ftp.ifm.uni-kiel.de");
add_location("ftp.iglou.com");
add_location("ftp.ign.fr");
add_location("ftp.imag.fr");
add_location("ftp.inel.gov");
add_location("ftp.inf.ethz.ch");
add_location("ftp.inf.puc-rio.br");
add_location("ftp.infoflex.se");
add_location("ftp.informatik.rwth-aachen.de");
add_location("ftp.informatik.uni-bremen.de");
add_location("ftp.informatik.uni-hannover.de");
add_location("ftp.infoscandic.se");
add_location("ftp.intel.com");
add_location("ftp.intergraph.com");
add_location("ftp.ionet.net");
add_location("ftp.ipc.chiba-u.ac.jp");
add_location("ftp.ips.cs.tu-bs.de");
add_location("ftp.iram.rwth-aachen.de");
add_location("ftp.is.co.za");
add_location("ftp.isoc.org");
add_location("ftp.iteso.mx");
add_location("ftp.ivd.uni-stuttgart.de");
add_location("ftp.iway.fr");
add_location("ftp.jcu.edu.au");
add_location("ftp.jhuapl.edu");
add_location("ftp.jpix.ad.jp");
add_location("ftp.karlin.mff.cuni.cz");
add_location("ftp.kfu.com");
add_location("ftp.kfunigraz.ac.at");
add_location("ftp.khm.de");
add_location("ftp.ki.se");
add_location("ftp.komkon.org");
add_location("ftp.laas.fr");
add_location("ftp.lanl.gov");
add_location("ftp.lantronix.com");
add_location("ftp.lava.net");
add_location("ftp.lcs.mit.edu");
add_location("ftp.legend.co.uk");
add_location("ftp.leidenuniv.nl");
add_location("ftp.let.rug.nl");
add_location("ftp.linux.co.uk");
add_location("ftp.linux.unife.it");
add_location("ftp.liv.ac.uk");
add_location("ftp.livingston.com");
add_location("ftp.lnt.e-technik.tu-muenchen.de");
add_location("ftp.lsu.edu");
add_location("ftp.lth.se");
add_location("ftp.lysator.liu.se");
add_location("ftp.mailbase.ac.uk");
add_location("ftp.mainstream.net");
add_location("ftp.maricopa.edu");
add_location("ftp.math.fu-berlin.de");
add_location("ftp.math.hr");
add_location("ftp.math.utah.edu");
add_location("ftp.mathematik.uni-marburg.de");
add_location("ftp.maths.tcd.ie");
add_location("ftp.maths.usyd.edu.au");
add_location("ftp.mathworks.com");
add_location("ftp.mbb.ki.se");
add_location("ftp.mbt.ru");
add_location("ftp.mcs.net");
add_location("ftp.mcs.vuw.ac.nz");
add_location("ftp.media.mit.edu");
add_location("ftp.meme.com");
add_location("ftp.merl.com");
add_location("ftp.microport.com");
add_location("ftp.mms.de");
add_location("ftp.mpce.mq.edu.au");
add_location("ftp.mpgn.com");
add_location("ftp.mpipf-muenchen.mpg.de");
add_location("ftp.mscf.uky.edu");
add_location("ftp.natinst.com");
add_location("ftp.ncsa.uiuc.edu");
add_location("ftp.net-tel.co.uk");
add_location("ftp.net.cmu.edu");
add_location("ftp.netsw.org");
add_location("ftp.new-york.net");
add_location("ftp.nis.net");
add_location("ftp.nlm.nih.gov");
add_location("ftp.nmt.edu");
add_location("ftp.noao.edu");
add_location("ftp.ntnu.no");
add_location("ftp.nwu.edu");
add_location("ftp.nysaes.cornell.edu");
add_location("ftp.observ.u-bordeaux.fr");
add_location("ftp.oit.unc.edu");
add_location("ftp.oldenbourg.de");
add_location("ftp.omg.unb.ca");
add_location("ftp.onecall.net");
add_location("ftp.ornl.gov");
add_location("ftp.ozone.fmi.fi");
add_location("ftp.pacific.net.hk");
add_location("ftp.panix.com");
add_location("ftp.pcnet.com");
add_location("ftp.phred.org");
add_location("ftp.pnl.gov");
add_location("ftp.prairienet.org");
add_location("ftp.proxad.net");
add_location("ftp.proximity.com.au");
add_location("ftp.psg.com");
add_location("ftp.psy.uq.edu.au");
add_location("ftp.psychologie.uni-freiburg.de");
add_location("ftp.pwr.wroc.pl");
add_location("ftp.python.org");
add_location("ftp.quantum.de");
add_location("ftp.ra.phy.cam.ac.uk");
add_location("ftp.rasip.fer.hr");
add_location("ftp.rbgkew.org.uk");
add_location("ftp.rcsb.org");
add_location("ftp.realtime.net");
add_location("ftp.red-bean.com");
add_location("ftp.redac.co.uk");
add_location("ftp.redac.fr");
add_location("ftp.rediris.es");
add_location("ftp.rgn.it");
add_location("ftp.rice.edu");
add_location("ftp.rkk.hu");
add_location("ftp.robelle.com");
add_location("ftp.rose.hp.com");
add_location("ftp.rt66.com");
add_location("ftp.ruhr-uni-bochum.de");
add_location("ftp.rz.uni-frankfurt.de");
add_location("ftp.sat.dundee.ac.uk");
add_location("ftp.saugus.net");
add_location("ftp.schrodinger.com");
add_location("ftp.science-computing.de");
add_location("ftp.science.unitn.it");
add_location("ftp.sco.com");
add_location("ftp.scs.leeds.ac.uk");
add_location("ftp.scsr.nevada.edu");
add_location("ftp.sd.monash.edu.au");
add_location("ftp.sdv.fr");
add_location("ftp.selapo.vwl.uni-muenchen.de");
add_location("ftp.serv.net");
add_location("ftp.sgi.leeds.ac.uk");
add_location("ftp.shore.net");
add_location("ftp.socsci.auc.dk");
add_location("ftp.space.net");
add_location("ftp.spec.org");
add_location("ftp.stallion.com");
add_location("ftp.starnet.de");
add_location("ftp.stat.math.ethz.ch");
add_location("ftp.stat.umn.edu");
add_location("ftp.std.com");
add_location("ftp.structchem.uni-essen.de");
add_location("ftp.sunsite.org.uk");
add_location("ftp.syd.dms.csiro.au");
add_location("ftp.tapr.org");
add_location("ftp.teco.uni-karlsruhe.de");
add_location("ftp.tenon.com");
add_location("ftp.tierzucht.uni-kiel.de");
add_location("ftp.tnt.uni-hannover.de");
add_location("ftp.tu-clausthal.de");
add_location("ftp.uci.edu");
add_location("ftp.ucsd.edu");
add_location("ftp.udel.edu");
add_location("ftp.uec.ac.jp");
add_location("ftp.uibk.ac.at");
add_location("ftp.uit.co.uk");
add_location("ftp.uji.es");
add_location("ftp.uke.uni-hamburg.de");
add_location("ftp.ulcc.ac.uk");
add_location("ftp.um.es");
add_location("ftp.umi.cs.tu-bs.de");
add_location("ftp.uni-augsburg.de");
add_location("ftp.uni-dortmund.de");
add_location("ftp.uni-hannover.de");
add_location("ftp.uni-magdeburg.de");
add_location("ftp.unidata.ucar.edu");
add_location("ftp.unige.ch");
add_location("ftp.univ-aix.fr");
add_location("ftp.upc.es");
add_location("ftp.uradio.ku.dk");
add_location("ftp.uralexpress.ru");
add_location("ftp.urc.ac.ru");
add_location("ftp.ut.ee");
add_location("ftp.uunet.ca");
add_location("ftp.uwo.ca");
add_location("ftp.vaxxine.com");
add_location("ftp.visi.com");
add_location("ftp.vub.ac.be");
add_location("ftp.wfu.edu");
add_location("ftp.win.tue.nl");
add_location("ftp.wolfe.net");
add_location("sunsite.cnlab-switch.ch");
add_location("sunsite.sut.ac.jp");
add_location("ftp.cuhk.edu.hk");
add_location("ftp.cetis.hvu.nl");
add_location("ftp.clinet.fi");
add_location("ftp.gamma.ru");
add_location("ftp.itv.se");
add_location("ftp.cs.rpi.edu");
add_location("ftp.carrier.kiev.ua");
add_location("ftp.rosnet.ru");
add_location("ftp.nsk.su");
add_location("ftp.southcom.com.au");
// -->
</script>
<body>
<br><br><br>
</body>
</html>