1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim:set ts=4 sts=4 sw=4 et cin: */
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 1998
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "nsFTPChannel.h"
40 : #include "nsFtpConnectionThread.h" // defines nsFtpState
41 :
42 : #include "nsIStreamListener.h"
43 : #include "nsIServiceManager.h"
44 : #include "nsThreadUtils.h"
45 : #include "nsNetUtil.h"
46 : #include "nsMimeTypes.h"
47 : #include "nsReadableUtils.h"
48 : #include "nsIPrefService.h"
49 : #include "nsIPrefBranch.h"
50 : #include "nsIStreamConverterService.h"
51 : #include "nsISocketTransport.h"
52 : #include "nsURLHelper.h"
53 :
54 : #if defined(PR_LOGGING)
55 : extern PRLogModuleInfo* gFTPLog;
56 : #endif /* PR_LOGGING */
57 :
58 : ////////////// this needs to move to nspr
59 : static inline PRUint32
60 : PRTimeToSeconds(PRTime t_usec)
61 : {
62 : return PRUint32(t_usec / PR_USEC_PER_SEC);
63 : }
64 :
65 : #define NowInSeconds() PRTimeToSeconds(PR_Now())
66 : ////////////// end
67 :
68 :
69 : // There are two transport connections established for an
70 : // ftp connection. One is used for the command channel , and
71 : // the other for the data channel. The command channel is the first
72 : // connection made and is used to negotiate the second, data, channel.
73 : // The data channel is driven by the command channel and is either
74 : // initiated by the server (PORT command) or by the client (PASV command).
75 : // Client initiation is the most common case and is attempted first.
76 :
77 : //-----------------------------------------------------------------------------
78 :
79 466 : NS_IMPL_ISUPPORTS_INHERITED4(nsFtpChannel,
80 : nsBaseChannel,
81 : nsIUploadChannel,
82 : nsIResumableChannel,
83 : nsIFTPChannel,
84 : nsIProxiedChannel)
85 :
86 : //-----------------------------------------------------------------------------
87 :
88 : NS_IMETHODIMP
89 0 : nsFtpChannel::SetUploadStream(nsIInputStream *stream,
90 : const nsACString &contentType,
91 : PRInt32 contentLength)
92 : {
93 0 : NS_ENSURE_TRUE(!IsPending(), NS_ERROR_IN_PROGRESS);
94 :
95 0 : mUploadStream = stream;
96 :
97 : // NOTE: contentLength is intentionally ignored here.
98 :
99 0 : return NS_OK;
100 : }
101 :
102 : NS_IMETHODIMP
103 0 : nsFtpChannel::GetUploadStream(nsIInputStream **stream)
104 : {
105 0 : NS_ENSURE_ARG_POINTER(stream);
106 0 : *stream = mUploadStream;
107 0 : NS_IF_ADDREF(*stream);
108 0 : return NS_OK;
109 : }
110 :
111 : //-----------------------------------------------------------------------------
112 :
113 : NS_IMETHODIMP
114 0 : nsFtpChannel::ResumeAt(PRUint64 aStartPos, const nsACString& aEntityID)
115 : {
116 0 : NS_ENSURE_TRUE(!IsPending(), NS_ERROR_IN_PROGRESS);
117 0 : mEntityID = aEntityID;
118 0 : mStartPos = aStartPos;
119 0 : mResumeRequested = (mStartPos || !mEntityID.IsEmpty());
120 0 : return NS_OK;
121 : }
122 :
123 : NS_IMETHODIMP
124 0 : nsFtpChannel::GetEntityID(nsACString& entityID)
125 : {
126 0 : if (mEntityID.IsEmpty())
127 0 : return NS_ERROR_NOT_RESUMABLE;
128 :
129 0 : entityID = mEntityID;
130 0 : return NS_OK;
131 : }
132 :
133 : //-----------------------------------------------------------------------------
134 : NS_IMETHODIMP
135 0 : nsFtpChannel::GetProxyInfo(nsIProxyInfo** aProxyInfo)
136 : {
137 0 : *aProxyInfo = ProxyInfo();
138 0 : NS_IF_ADDREF(*aProxyInfo);
139 0 : return NS_OK;
140 : }
141 :
142 : //-----------------------------------------------------------------------------
143 :
144 : nsresult
145 34 : nsFtpChannel::OpenContentStream(bool async, nsIInputStream **result,
146 : nsIChannel** channel)
147 : {
148 34 : if (!async)
149 17 : return NS_ERROR_NOT_IMPLEMENTED;
150 :
151 17 : nsFtpState *state = new nsFtpState();
152 17 : if (!state)
153 0 : return NS_ERROR_OUT_OF_MEMORY;
154 17 : NS_ADDREF(state);
155 :
156 17 : nsresult rv = state->Init(this);
157 17 : if (NS_FAILED(rv)) {
158 0 : NS_RELEASE(state);
159 0 : return rv;
160 : }
161 :
162 17 : *result = state;
163 17 : return NS_OK;
164 : }
165 :
166 : bool
167 0 : nsFtpChannel::GetStatusArg(nsresult status, nsString &statusArg)
168 : {
169 0 : nsCAutoString host;
170 0 : URI()->GetHost(host);
171 0 : CopyUTF8toUTF16(host, statusArg);
172 0 : return true;
173 : }
174 :
175 : void
176 17 : nsFtpChannel::OnCallbacksChanged()
177 : {
178 17 : mFTPEventSink = nsnull;
179 17 : }
180 :
181 : //-----------------------------------------------------------------------------
182 :
183 : namespace {
184 :
185 : class FTPEventSinkProxy : public nsIFTPEventSink
186 0 : {
187 : public:
188 0 : FTPEventSinkProxy(nsIFTPEventSink* aTarget)
189 : : mTarget(aTarget)
190 0 : , mTargetThread(do_GetCurrentThread())
191 0 : { }
192 :
193 : NS_DECL_ISUPPORTS
194 : NS_DECL_NSIFTPEVENTSINK
195 :
196 : class OnFTPControlLogRunnable : public nsRunnable
197 0 : {
198 : public:
199 0 : OnFTPControlLogRunnable(nsIFTPEventSink* aTarget,
200 : bool aServer,
201 : const char* aMessage)
202 : : mTarget(aTarget)
203 : , mServer(aServer)
204 0 : , mMessage(aMessage)
205 0 : { }
206 :
207 : NS_DECL_NSIRUNNABLE
208 :
209 : private:
210 : nsCOMPtr<nsIFTPEventSink> mTarget;
211 : bool mServer;
212 : nsCString mMessage;
213 : };
214 :
215 : private:
216 : nsCOMPtr<nsIFTPEventSink> mTarget;
217 : nsCOMPtr<nsIThread> mTargetThread;
218 : };
219 :
220 0 : NS_IMPL_THREADSAFE_ISUPPORTS1(FTPEventSinkProxy, nsIFTPEventSink)
221 :
222 : NS_IMETHODIMP
223 0 : FTPEventSinkProxy::OnFTPControlLog(bool aServer, const char* aMsg)
224 : {
225 : nsRefPtr<OnFTPControlLogRunnable> r =
226 0 : new OnFTPControlLogRunnable(mTarget, aServer, aMsg);
227 0 : return mTargetThread->Dispatch(r, NS_DISPATCH_NORMAL);
228 : }
229 :
230 : NS_IMETHODIMP
231 0 : FTPEventSinkProxy::OnFTPControlLogRunnable::Run()
232 : {
233 0 : mTarget->OnFTPControlLog(mServer, mMessage.get());
234 0 : return NS_OK;
235 : }
236 :
237 : } // anonymous namespace
238 :
239 : void
240 0 : nsFtpChannel::GetFTPEventSink(nsCOMPtr<nsIFTPEventSink> &aResult)
241 : {
242 0 : if (!mFTPEventSink) {
243 0 : nsCOMPtr<nsIFTPEventSink> ftpSink;
244 0 : GetCallback(ftpSink);
245 0 : if (ftpSink) {
246 0 : mFTPEventSink = new FTPEventSinkProxy(ftpSink);
247 : }
248 : }
249 0 : aResult = mFTPEventSink;
250 0 : }
|