netwerk/protocol/ftp/nsFTPChannel.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* vim:set ts=4 sts=4 sw=4 et cin: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "nsFTPChannel.h"
michael@0 8 #include "nsFtpConnectionThread.h" // defines nsFtpState
michael@0 9
michael@0 10 #include "nsThreadUtils.h"
michael@0 11 #include "mozilla/Attributes.h"
michael@0 12
michael@0 13 #if defined(PR_LOGGING)
michael@0 14 extern PRLogModuleInfo* gFTPLog;
michael@0 15 #endif /* PR_LOGGING */
michael@0 16
michael@0 17 // There are two transport connections established for an
michael@0 18 // ftp connection. One is used for the command channel , and
michael@0 19 // the other for the data channel. The command channel is the first
michael@0 20 // connection made and is used to negotiate the second, data, channel.
michael@0 21 // The data channel is driven by the command channel and is either
michael@0 22 // initiated by the server (PORT command) or by the client (PASV command).
michael@0 23 // Client initiation is the most common case and is attempted first.
michael@0 24
michael@0 25 //-----------------------------------------------------------------------------
michael@0 26
michael@0 27 NS_IMPL_ISUPPORTS_INHERITED(nsFtpChannel,
michael@0 28 nsBaseChannel,
michael@0 29 nsIUploadChannel,
michael@0 30 nsIResumableChannel,
michael@0 31 nsIFTPChannel,
michael@0 32 nsIProxiedChannel)
michael@0 33
michael@0 34 //-----------------------------------------------------------------------------
michael@0 35
michael@0 36 NS_IMETHODIMP
michael@0 37 nsFtpChannel::SetUploadStream(nsIInputStream *stream,
michael@0 38 const nsACString &contentType,
michael@0 39 int64_t contentLength)
michael@0 40 {
michael@0 41 NS_ENSURE_TRUE(!Pending(), NS_ERROR_IN_PROGRESS);
michael@0 42
michael@0 43 mUploadStream = stream;
michael@0 44
michael@0 45 // NOTE: contentLength is intentionally ignored here.
michael@0 46
michael@0 47 return NS_OK;
michael@0 48 }
michael@0 49
michael@0 50 NS_IMETHODIMP
michael@0 51 nsFtpChannel::GetUploadStream(nsIInputStream **stream)
michael@0 52 {
michael@0 53 NS_ENSURE_ARG_POINTER(stream);
michael@0 54 *stream = mUploadStream;
michael@0 55 NS_IF_ADDREF(*stream);
michael@0 56 return NS_OK;
michael@0 57 }
michael@0 58
michael@0 59 //-----------------------------------------------------------------------------
michael@0 60
michael@0 61 NS_IMETHODIMP
michael@0 62 nsFtpChannel::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID)
michael@0 63 {
michael@0 64 NS_ENSURE_TRUE(!Pending(), NS_ERROR_IN_PROGRESS);
michael@0 65 mEntityID = aEntityID;
michael@0 66 mStartPos = aStartPos;
michael@0 67 mResumeRequested = (mStartPos || !mEntityID.IsEmpty());
michael@0 68 return NS_OK;
michael@0 69 }
michael@0 70
michael@0 71 NS_IMETHODIMP
michael@0 72 nsFtpChannel::GetEntityID(nsACString& entityID)
michael@0 73 {
michael@0 74 if (mEntityID.IsEmpty())
michael@0 75 return NS_ERROR_NOT_RESUMABLE;
michael@0 76
michael@0 77 entityID = mEntityID;
michael@0 78 return NS_OK;
michael@0 79 }
michael@0 80
michael@0 81 //-----------------------------------------------------------------------------
michael@0 82 NS_IMETHODIMP
michael@0 83 nsFtpChannel::GetProxyInfo(nsIProxyInfo** aProxyInfo)
michael@0 84 {
michael@0 85 *aProxyInfo = ProxyInfo();
michael@0 86 NS_IF_ADDREF(*aProxyInfo);
michael@0 87 return NS_OK;
michael@0 88 }
michael@0 89
michael@0 90 //-----------------------------------------------------------------------------
michael@0 91
michael@0 92 nsresult
michael@0 93 nsFtpChannel::OpenContentStream(bool async, nsIInputStream **result,
michael@0 94 nsIChannel** channel)
michael@0 95 {
michael@0 96 if (!async)
michael@0 97 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 98
michael@0 99 nsFtpState *state = new nsFtpState();
michael@0 100 if (!state)
michael@0 101 return NS_ERROR_OUT_OF_MEMORY;
michael@0 102 NS_ADDREF(state);
michael@0 103
michael@0 104 nsresult rv = state->Init(this);
michael@0 105 if (NS_FAILED(rv)) {
michael@0 106 NS_RELEASE(state);
michael@0 107 return rv;
michael@0 108 }
michael@0 109
michael@0 110 *result = state;
michael@0 111 return NS_OK;
michael@0 112 }
michael@0 113
michael@0 114 bool
michael@0 115 nsFtpChannel::GetStatusArg(nsresult status, nsString &statusArg)
michael@0 116 {
michael@0 117 nsAutoCString host;
michael@0 118 URI()->GetHost(host);
michael@0 119 CopyUTF8toUTF16(host, statusArg);
michael@0 120 return true;
michael@0 121 }
michael@0 122
michael@0 123 void
michael@0 124 nsFtpChannel::OnCallbacksChanged()
michael@0 125 {
michael@0 126 mFTPEventSink = nullptr;
michael@0 127 }
michael@0 128
michael@0 129 //-----------------------------------------------------------------------------
michael@0 130
michael@0 131 namespace {
michael@0 132
michael@0 133 class FTPEventSinkProxy MOZ_FINAL : public nsIFTPEventSink
michael@0 134 {
michael@0 135 public:
michael@0 136 FTPEventSinkProxy(nsIFTPEventSink* aTarget)
michael@0 137 : mTarget(aTarget)
michael@0 138 , mTargetThread(do_GetCurrentThread())
michael@0 139 { }
michael@0 140
michael@0 141 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 142 NS_DECL_NSIFTPEVENTSINK
michael@0 143
michael@0 144 class OnFTPControlLogRunnable : public nsRunnable
michael@0 145 {
michael@0 146 public:
michael@0 147 OnFTPControlLogRunnable(nsIFTPEventSink* aTarget,
michael@0 148 bool aServer,
michael@0 149 const char* aMessage)
michael@0 150 : mTarget(aTarget)
michael@0 151 , mServer(aServer)
michael@0 152 , mMessage(aMessage)
michael@0 153 { }
michael@0 154
michael@0 155 NS_DECL_NSIRUNNABLE
michael@0 156
michael@0 157 private:
michael@0 158 nsCOMPtr<nsIFTPEventSink> mTarget;
michael@0 159 bool mServer;
michael@0 160 nsCString mMessage;
michael@0 161 };
michael@0 162
michael@0 163 private:
michael@0 164 nsCOMPtr<nsIFTPEventSink> mTarget;
michael@0 165 nsCOMPtr<nsIThread> mTargetThread;
michael@0 166 };
michael@0 167
michael@0 168 NS_IMPL_ISUPPORTS(FTPEventSinkProxy, nsIFTPEventSink)
michael@0 169
michael@0 170 NS_IMETHODIMP
michael@0 171 FTPEventSinkProxy::OnFTPControlLog(bool aServer, const char* aMsg)
michael@0 172 {
michael@0 173 nsRefPtr<OnFTPControlLogRunnable> r =
michael@0 174 new OnFTPControlLogRunnable(mTarget, aServer, aMsg);
michael@0 175 return mTargetThread->Dispatch(r, NS_DISPATCH_NORMAL);
michael@0 176 }
michael@0 177
michael@0 178 NS_IMETHODIMP
michael@0 179 FTPEventSinkProxy::OnFTPControlLogRunnable::Run()
michael@0 180 {
michael@0 181 mTarget->OnFTPControlLog(mServer, mMessage.get());
michael@0 182 return NS_OK;
michael@0 183 }
michael@0 184
michael@0 185 } // anonymous namespace
michael@0 186
michael@0 187 void
michael@0 188 nsFtpChannel::GetFTPEventSink(nsCOMPtr<nsIFTPEventSink> &aResult)
michael@0 189 {
michael@0 190 if (!mFTPEventSink) {
michael@0 191 nsCOMPtr<nsIFTPEventSink> ftpSink;
michael@0 192 GetCallback(ftpSink);
michael@0 193 if (ftpSink) {
michael@0 194 mFTPEventSink = new FTPEventSinkProxy(ftpSink);
michael@0 195 }
michael@0 196 }
michael@0 197 aResult = mFTPEventSink;
michael@0 198 }
michael@0 199
michael@0 200 void
michael@0 201 nsFtpChannel::ForcePending(bool aForcePending)
michael@0 202 {
michael@0 203 // Set true here so IsPending will return true.
michael@0 204 // Required for callback diversion from child back to parent. In such cases
michael@0 205 // OnStopRequest can be called in the parent before callbacks are diverted
michael@0 206 // back from the child to the listener in the parent.
michael@0 207 mForcePending = aForcePending;
michael@0 208 }
michael@0 209
michael@0 210 NS_IMETHODIMP
michael@0 211 nsFtpChannel::IsPending(bool *result)
michael@0 212 {
michael@0 213 *result = Pending();
michael@0 214 return NS_OK;
michael@0 215 }
michael@0 216
michael@0 217 bool
michael@0 218 nsFtpChannel::Pending() const
michael@0 219 {
michael@0 220 return nsBaseChannel::Pending() || mForcePending;
michael@0 221 }

mercurial