Helpviewer/Sync/FtpSyncHandler.py

changeset 2074
5cb87968aad5
parent 2064
79cfe18963ae
child 2076
0d6286344ac1
equal deleted inserted replaced
2071:136eb25e4314 2074:5cb87968aad5
8 """ 8 """
9 9
10 import ftplib 10 import ftplib
11 import io 11 import io
12 12
13 from PyQt4.QtCore import pyqtSignal, QUrl, QTimer, QFileInfo, QCoreApplication, QByteArray 13 from PyQt4.QtCore import pyqtSignal, QTimer, QFileInfo, QCoreApplication, QByteArray
14 from PyQt4.QtNetwork import QNetworkProxyQuery, QNetworkProxy, QAuthenticator 14
15 15 from E5Network.E5Ftp import E5Ftp, E5FtpProxyType, E5FtpProxyError
16 from E5Network.E5NetworkProxyFactory import E5NetworkProxyFactory, \
17 proxyAuthenticationRequired
18 16
19 from .SyncHandler import SyncHandler 17 from .SyncHandler import SyncHandler
20 18
21 import Helpviewer.HelpWindow 19 import Helpviewer.HelpWindow
22 20
74 72
75 self.__idleTimer = QTimer(self) 73 self.__idleTimer = QTimer(self)
76 self.__idleTimer.setInterval(Preferences.getHelp("SyncFtpIdleTimeout") * 1000) 74 self.__idleTimer.setInterval(Preferences.getHelp("SyncFtpIdleTimeout") * 1000)
77 self.__idleTimer.timeout.connect(self.__idleTimeout) 75 self.__idleTimer.timeout.connect(self.__idleTimeout)
78 76
79 self.__ftp = ftplib.FTP() 77 self.__ftp = E5Ftp()
80 78
81 # do proxy setup 79 # do proxy setup
82 self.__proxy = None 80 if not Preferences.getUI("UseProxy"):
83 url = QUrl("ftp://{0}:{1}".format( 81 proxyType = E5FtpProxyType.NoProxy
84 Preferences.getHelp("SyncFtpServer"), 82 else:
85 Preferences.getHelp("SyncFtpPort") 83 proxyType = Preferences.getUI("ProxyType/Ftp")
86 )) 84 if proxyType != E5FtpProxyType.NoProxy:
87 query = QNetworkProxyQuery(url) 85 self.__ftp.setProxy(proxyType,
88 proxyList = E5NetworkProxyFactory().queryProxy(query) 86 Preferences.getUI("ProxyHost/Ftp"),
89 ftpProxy = QNetworkProxy() 87 Preferences.getUI("ProxyPort/Ftp"))
90 for proxy in proxyList: 88 if proxyType != E5FtpProxyType.NonAuthorizing:
91 if proxy.type() == QNetworkProxy.NoProxy or \ 89 self.__ftp.setProxyAuthentication(
92 proxy.type() == QNetworkProxy.FtpCachingProxy: 90 Preferences.getUI("ProxyUser/Ftp"),
93 ftpProxy = proxy 91 Preferences.getUI("ProxyPassword/Ftp"),
94 break 92 Preferences.getUI("ProxyAccount/Ftp"))
95 if ftpProxy.type() == QNetworkProxy.DefaultProxy:
96 self.syncError.emit(self.trUtf8("No suitable proxy found."))
97 return
98 elif ftpProxy.type() == QNetworkProxy.FtpCachingProxy:
99 self.__proxy = ftpProxy
100 93
101 QTimer.singleShot(0, self.__doFtpCommands) 94 QTimer.singleShot(0, self.__doFtpCommands)
102 95
103 def __doFtpCommands(self): 96 def __doFtpCommands(self):
104 """ 97 """
110 self.__changeToStore() 103 self.__changeToStore()
111 self.__ftp.retrlines("LIST", self.__dirListCallback) 104 self.__ftp.retrlines("LIST", self.__dirListCallback)
112 self.__initialSync() 105 self.__initialSync()
113 self.__state = "idle" 106 self.__state = "idle"
114 self.__idleTimer.start() 107 self.__idleTimer.start()
115 except ftplib.all_errors as err: 108 except (ftplib.all_errors, E5FtpProxyError) as err:
116 self.syncError.emit(str(err)) 109 self.syncError.emit(str(err))
117 110
118 def __connectAndLogin(self): 111 def __connectAndLogin(self):
119 """ 112 """
120 Private method to connect to the FTP server and log in. 113 Private method to connect to the FTP server and log in.
121 114
122 @return flag indicating a successful log in (boolean) 115 @return flag indicating a successful log in (boolean)
123 """ 116 """
124 retry = True 117 self.__ftp.connect(
125 while retry: 118 Preferences.getHelp("SyncFtpServer"),
126 if self.__proxy: 119 Preferences.getHelp("SyncFtpPort"),
127 self.__ftp.connect( 120 timeout=5)
128 self.__proxy.hostName(), 121 self.__ftp.login(
129 self.__proxy.port(), 122 Preferences.getHelp("SyncFtpUser"),
130 timeout=10) 123 Preferences.getHelp("SyncFtpPassword"))
131 else: 124 self.__connected = True
132 self.__ftp.connect( 125 return True
133 Preferences.getHelp("SyncFtpServer"),
134 Preferences.getHelp("SyncFtpPort"),
135 timeout=10)
136 ok, retry = self.__doFtpLogin(
137 Preferences.getHelp("SyncFtpUser"),
138 Preferences.getHelp("SyncFtpPassword"))
139 self.__connected = ok
140 if not ok:
141 self.syncError.emit(self.trUtf8("Cannot log in to FTP host."))
142
143 return ok
144
145 def __doFtpLogin(self, username, password):
146 """
147 Private method to do the FTP login with asking for a username and password,
148 if the login fails with an error 530.
149
150 @param username user name to use for the login (string)
151 @param password password to use for the login (string)
152 @return tuple of two flags indicating a successful login and
153 if the login should be retried (boolean, boolean)
154 """
155 # 1. do proxy login, if a proxy is used
156 if self.__proxy:
157 try:
158 self.__ftp.login(self.__proxy.user(), self.__proxy.password())
159 except ftplib.error_perm as err:
160 code, msg = err.args[0].split(None, 1)
161 if code.strip() == "530":
162 auth = QAuthenticator()
163 auth.setOption("realm", self.__proxy.hostName())
164 proxyAuthenticationRequired(self.__proxy, auth)
165 if not auth.isNull() and auth.user():
166 self.__proxy.setUser(auth.user())
167 self.__proxy.setPassword(auth.password())
168 return False, True
169 return False, False
170
171 # 2. do the real login
172 if self.__proxy:
173 loginName = "{0}@{1}".format(
174 username, Preferences.getHelp("SyncFtpServer"))
175 if Preferences.getHelp("SyncFtpPort") != ftplib.FTP_PORT:
176 loginName = "{0}:{1}".format(
177 loginName, Preferences.getHelp("SyncFtpPort"))
178 else:
179 loginName = username
180 self.__ftp.login(loginName, password)
181 return True, False
182 126
183 def __changeToStore(self): 127 def __changeToStore(self):
184 """ 128 """
185 Private slot to change to the storage directory. 129 Private slot to change to the storage directory.
186 130
195 while storePathList: 139 while storePathList:
196 path = storePathList[0] 140 path = storePathList[0]
197 try: 141 try:
198 self.__ftp.cwd(path) 142 self.__ftp.cwd(path)
199 except ftplib.error_perm as err: 143 except ftplib.error_perm as err:
200 code, msg = err.args[0].split(None, 1) 144 code = err.args[0].strip()[:3]
201 if code.strip() == "550": 145 if code == "550":
202 # path does not exist, create it 146 # path does not exist, create it
203 self.__ftp.mkd(path) 147 self.__ftp.mkd(path)
204 self.__ftp.cwd(path) 148 self.__ftp.cwd(path)
205 else: 149 else:
206 raise 150 raise
265 Private method to upload the given file. 209 Private method to upload the given file.
266 210
267 @param type_ type of the synchronization event (string one 211 @param type_ type of the synchronization event (string one
268 of "bookmarks", "history", "passwords", "useragents" or "speeddial") 212 of "bookmarks", "history", "passwords", "useragents" or "speeddial")
269 @param fileName name of the file to be uploaded (string) 213 @param fileName name of the file to be uploaded (string)
270 """ 214 @return flag indicating success (boolean)
215 """
216 res = False
271 data = self.readFile(fileName, type_) 217 data = self.readFile(fileName, type_)
272 if data.isEmpty(): 218 if data.isEmpty():
273 self.syncStatus.emit(type_, self._messages[type_]["LocalMissing"]) 219 self.syncStatus.emit(type_, self._messages[type_]["LocalMissing"])
274 self.syncFinished(type_, False, False) 220 self.syncFinished(type_, False, False)
275 else: 221 else:
278 self.__ftp.storbinary( 224 self.__ftp.storbinary(
279 "STOR {0}".format(self._remoteFiles[type_]), 225 "STOR {0}".format(self._remoteFiles[type_]),
280 buffer, 226 buffer,
281 callback=lambda x: QCoreApplication.processEvents()) 227 callback=lambda x: QCoreApplication.processEvents())
282 self.syncFinished.emit(type_, True, False) 228 self.syncFinished.emit(type_, True, False)
229 res = True
283 except ftplib.all_errors as err: 230 except ftplib.all_errors as err:
284 self.syncStatus.emit(type_, str(err)) 231 self.syncStatus.emit(type_, str(err))
285 self.syncFinished.emit(type_, False, False) 232 self.syncFinished.emit(type_, False, False)
233 return res
286 234
287 def __initialSyncFile(self, type_, fileName): 235 def __initialSyncFile(self, type_, fileName):
288 """ 236 """
289 Private method to do the initial synchronization of the given file. 237 Private method to do the initial synchronization of the given file.
290 238
360 return 308 return
361 309
362 # upload the changed file 310 # upload the changed file
363 self.__state = "uploading" 311 self.__state = "uploading"
364 self.syncStatus.emit(type_, self._messages[type_]["Uploading"]) 312 self.syncStatus.emit(type_, self._messages[type_]["Uploading"])
365 self.__uploadFile(type_, fileName) 313 if self.__uploadFile(type_, fileName):
366 self.syncStatus.emit(type_, self.trUtf8("Synchronization finished.")) 314 self.syncStatus.emit(type_, self.trUtf8("Synchronization finished."))
367 self.__state = "idle" 315 self.__state = "idle"
368 316
369 def syncBookmarks(self): 317 def syncBookmarks(self):
370 """ 318 """
371 Public method to synchronize the bookmarks. 319 Public method to synchronize the bookmarks.
421 """ 369 """
422 if self.__state == "idle" and self.__connected: 370 if self.__state == "idle" and self.__connected:
423 try: 371 try:
424 self.__ftp.voidcmd("NOOP") 372 self.__ftp.voidcmd("NOOP")
425 except ftplib.Error as err: 373 except ftplib.Error as err:
426 code, msg = err.args[0].split(None, 1) 374 code = err.args[0].strip()[:3]
427 if code.strip() == "421": 375 if code == "421":
428 self.__connected = False 376 self.__connected = False
429 except IOError: 377 except IOError:
430 self.__connected = False 378 self.__connected = False

eric ide

mercurial