12 import errno |
12 import errno |
13 import mimetypes |
13 import mimetypes |
14 |
14 |
15 from PyQt4.QtCore import QByteArray, QIODevice, Qt, QUrl, QTimer, QBuffer, \ |
15 from PyQt4.QtCore import QByteArray, QIODevice, Qt, QUrl, QTimer, QBuffer, \ |
16 QCoreApplication |
16 QCoreApplication |
17 from PyQt4.QtGui import QPixmap, QDialog |
17 from PyQt4.QtGui import QPixmap |
18 from PyQt4.QtNetwork import QNetworkReply, QNetworkRequest |
18 from PyQt4.QtNetwork import QNetworkReply, QNetworkRequest, QNetworkProxyQuery, \ |
|
19 QNetworkProxy, QAuthenticator |
19 from PyQt4.QtWebKit import QWebSettings |
20 from PyQt4.QtWebKit import QWebSettings |
20 |
21 |
21 import Helpviewer.HelpWindow |
|
22 |
|
23 from UI.AuthenticationDialog import AuthenticationDialog |
|
24 |
|
25 import Preferences |
|
26 import UI.PixmapCache |
22 import UI.PixmapCache |
27 from Utilities.FtpUtilities import FtpDirLineParser, FtpDirLineParserError |
23 from Utilities.FtpUtilities import FtpDirLineParser, FtpDirLineParserError |
28 |
24 |
29 ftpListPage_html = """\ |
25 ftpListPage_html = """\ |
30 <?xml version="1.0" encoding="UTF-8" ?> |
26 <?xml version="1.0" encoding="UTF-8" ?> |
140 self.__dirLineParser = FtpDirLineParser() |
138 self.__dirLineParser = FtpDirLineParser() |
141 |
139 |
142 if url.path() == "": |
140 if url.path() == "": |
143 url.setPath("/") |
141 url.setPath("/") |
144 self.setUrl(url) |
142 self.setUrl(url) |
|
143 |
|
144 # do proxy setup |
|
145 self.__proxy = None |
|
146 query = QNetworkProxyQuery(url) |
|
147 proxyList = parent.proxyFactory().queryProxy(query) |
|
148 ftpProxy = QNetworkProxy() |
|
149 for proxy in proxyList: |
|
150 if proxy.type() == QNetworkProxy.NoProxy or \ |
|
151 proxy.type() == QNetworkProxy.FtpCachingProxy: |
|
152 ftpProxy = proxy |
|
153 break |
|
154 if ftpProxy.type() == QNetworkProxy.DefaultProxy: |
|
155 self.setError(QNetworkReply.ProxyNotFoundError, |
|
156 self.trUtf8("No suitable proxy found.")) |
|
157 QTimer.singleShot(0, self.__errorSignals) |
|
158 return |
|
159 elif ftpProxy.type() == QNetworkProxy.FtpCachingProxy: |
|
160 self.__proxy = ftpProxy |
145 |
161 |
146 self.__loggingIn = False |
162 self.__loggingIn = False |
147 |
163 |
148 QTimer.singleShot(0, self.__doFtpCommands) |
164 QTimer.singleShot(0, self.__doFtpCommands) |
149 |
165 |
187 """ |
203 """ |
188 Private slot doing the sequence of FTP commands to get the requested result. |
204 Private slot doing the sequence of FTP commands to get the requested result. |
189 """ |
205 """ |
190 retry = True |
206 retry = True |
191 try: |
207 try: |
|
208 username = self.url().userName() |
|
209 password = self.url().password() |
|
210 byAuth = False |
192 while retry: |
211 while retry: |
193 self.__ftp.connect(self.url().host(), self.url().port(ftplib.FTP_PORT), |
212 if self.__proxy: |
194 timeout=10) |
213 self.__ftp.connect(self.__proxy.hostName(), self.__proxy.port()) |
195 ok, retry = self.__doFtpLogin(self.url().userName(), self.url().password()) |
214 else: |
|
215 self.__ftp.connect( |
|
216 self.url().host(), self.url().port(ftplib.FTP_PORT), timeout=10) |
|
217 ok, retry = self.__doFtpLogin(username, password, byAuth) |
|
218 if not ok and retry: |
|
219 auth = self.__handler.getAuthenticator(self.url().host()) |
|
220 if auth and not auth.isNull() and auth.user(): |
|
221 username = auth.user() |
|
222 password = auth.password() |
|
223 byAuth = True |
|
224 else: |
|
225 retry = False |
196 if ok: |
226 if ok: |
197 self.__ftp.retrlines("LIST " + self.url().path(), self.__dirCallback) |
227 self.__ftp.retrlines("LIST " + self.url().path(), self.__dirCallback) |
198 if len(self.__items) == 1 and \ |
228 if len(self.__items) == 1 and \ |
199 self.__items[0].isFile(): |
229 self.__items[0].isFile(): |
200 self.__setContent() |
230 self.__setContent() |
201 self.__ftp.retrbinary("RETR " + self.url().path(), self.__retrCallback) |
231 self.__ftp.retrbinary( |
|
232 "RETR " + self.url().path(), self.__retrCallback) |
202 self.__content.append(512 * b' ') |
233 self.__content.append(512 * b' ') |
203 self.readyRead.emit() |
234 self.readyRead.emit() |
204 else: |
235 else: |
205 self.__setListContent() |
236 self.__setListContent() |
206 self.__ftp.quit() |
237 self.__ftp.quit() |
213 errCode = QNetworkReply.ProtocolFailure |
244 errCode = QNetworkReply.ProtocolFailure |
214 self.setError(errCode, str(err)) |
245 self.setError(errCode, str(err)) |
215 self.error.emit(errCode) |
246 self.error.emit(errCode) |
216 self.finished.emit() |
247 self.finished.emit() |
217 |
248 |
218 def __doFtpLogin(self, username, password): |
249 def __doFtpLogin(self, username, password, byAuth=False): |
219 """ |
250 """ |
220 Private method to do the FTP login with asking for a username and password, |
251 Private method to do the FTP login with asking for a username and password, |
221 if the login fails with an error 530. |
252 if the login fails with an error 530. |
222 |
253 |
223 @param username user name to use for the login (string) |
254 @param username user name to use for the login (string) |
224 @param password password to use for the login (string) |
255 @param password password to use for the login (string) |
|
256 @param byAuth flag indicating that the login data was provided by an |
|
257 authenticator (boolean) |
225 @return tuple of two flags indicating a successful login and |
258 @return tuple of two flags indicating a successful login and |
226 if the login should be retried (boolean, boolean) |
259 if the login should be retried (boolean, boolean) |
227 """ |
260 """ |
|
261 # 1. do proxy login, if a proxy is used |
|
262 if self.__proxy: |
|
263 try: |
|
264 self.__ftp.login(self.__proxy.user(), self.__proxy.password()) |
|
265 except ftplib.error_perm as err: |
|
266 code, msg = err.args[0].split(None, 1) |
|
267 if code.strip() == "530": |
|
268 auth = QAuthenticator() |
|
269 auth.setOption("realm", self.__proxy.hostName()) |
|
270 self.__manager.proxyAuthenticationRequired.emit(self.__proxy, auth) |
|
271 if not auth.isNull() and auth.user(): |
|
272 self.__proxy.setUser(auth.user()) |
|
273 self.__proxy.setPassword(auth.password()) |
|
274 return False, True |
|
275 return False, False |
|
276 |
|
277 # 2. do the real login |
228 try: |
278 try: |
229 self.__ftp.login(username, password) |
279 if self.__proxy: |
|
280 loginName = "{0}@{1}".format(username, self.url().host()) |
|
281 if self.url().port(ftplib.FTP_PORT) != ftplib.FTP_PORT: |
|
282 loginName = "{0}:{1}".format(loginName, self.url().port()) |
|
283 else: |
|
284 loginName = username |
|
285 self.__ftp.login(loginName, password) |
230 return True, False |
286 return True, False |
231 except ftplib.error_perm as err: |
287 except ftplib.error_perm as err: |
232 code, msg = err.args[0].split(None, 1) |
288 code, msg = err.args[0].split(None, 1) |
233 if code.strip() == "530": |
289 if code.strip() == "530": |
234 # error 530 -> Login incorrect |
290 # error 530 -> Login incorrect |
235 urlRoot = "{0}://{1}"\ |
291 if byAuth: |
236 .format(self.url().scheme(), self.url().authority()) |
292 self.__handler.setAuthenticator(self.url().host(), None) |
237 info = self.trUtf8("<b>Enter username and password for '{0}'</b>")\ |
293 auth = None |
238 .format(urlRoot) |
294 else: |
239 dlg = AuthenticationDialog(info, self.url().userName(), |
295 auth = self.__handler.getAuthenticator(self.url().host()) |
240 Preferences.getUser("SavePasswords"), |
296 if not auth or auth.isNull() or not auth.user(): |
241 Preferences.getUser("SavePasswords")) |
297 auth = QAuthenticator() |
242 if Preferences.getUser("SavePasswords"): |
298 auth.setOption("realm", self.url().host()) |
243 username, password = \ |
299 self.__manager.authenticationRequired.emit(self, auth) |
244 Helpviewer.HelpWindow.HelpWindow.passwordManager().getLogin( |
300 if not auth.isNull(): |
245 self.url(), "") |
301 if auth.user(): |
246 if username: |
302 self.__handler.setAuthenticator(self.url().host(), auth) |
247 dlg.setData(username, password) |
303 return False, True |
248 if dlg.exec_() == QDialog.Accepted: |
304 return False, False |
249 username, password = dlg.getData() |
305 else: |
250 if Preferences.getUser("SavePasswords"): |
|
251 Helpviewer.HelpWindow.HelpWindow.passwordManager().setLogin( |
|
252 self.url(), "", username, password) |
|
253 url = self.url() |
|
254 url.setUserName(username) |
|
255 url.setPassword(password) |
|
256 self.setUrl(url) |
|
257 return False, True |
306 return False, True |
258 else: |
|
259 return False, False |
|
260 else: |
307 else: |
261 raise |
308 raise |
262 |
309 |
263 def __dirCallback(self, line): |
310 def __dirCallback(self, line): |
264 """ |
311 """ |