Helpviewer/Network/FtpReply.py

changeset 2050
585f6646bf50
parent 2047
739aa1717df5
child 2053
ef81185e8b89
equal deleted inserted replaced
2048:da2d82f84924 2050:585f6646bf50
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" ?>
119 "Oct": 10, 115 "Oct": 10,
120 "Nov": 11, 116 "Nov": 11,
121 "Dec": 12, 117 "Dec": 12,
122 } 118 }
123 119
124 def __init__(self, url, parent=None): 120 def __init__(self, url, accessHandler, parent=None):
125 """ 121 """
126 Constructor 122 Constructor
127 123
128 @param url requested FTP URL (QUrl) 124 @param url requested FTP URL (QUrl)
125 @param accessHandler reference to the access handler (FtpAccessHandler)
129 @param parent reference to the parent object (QObject) 126 @param parent reference to the parent object (QObject)
130 """ 127 """
131 super().__init__(parent) 128 super().__init__(parent)
132 129
133 self.__manager = parent 130 self.__manager = parent
131 self.__handler = accessHandler
134 132
135 self.__ftp = ftplib.FTP() 133 self.__ftp = ftplib.FTP()
136 134
137 self.__items = [] 135 self.__items = []
138 self.__content = QByteArray() 136 self.__content = QByteArray()
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 """

eric ide

mercurial