Helpviewer/Sync/FtpSyncHandler.py

changeset 1626
a77c8ea8582c
child 1638
cd2f9e526710
equal deleted inserted replaced
1625:4f03e45703e9 1626:a77c8ea8582c
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a synchronization handler using FTP.
8 """
9
10 from PyQt4.QtCore import pyqtSignal, QUrl, QFile, QIODevice, QTime, QThread
11 from PyQt4.QtNetwork import QFtp, QNetworkProxyQuery, QNetworkProxy, QNetworkProxyFactory
12
13 from .SyncHandler import SyncHandler
14
15 import Helpviewer.HelpWindow
16
17 import Preferences
18
19
20 class FtpSyncHandler(SyncHandler):
21 """
22 Class implementing a synchronization handler using FTP.
23
24 @signal syncStatus(type_, done, message) emitted to indicate the synchronization
25 status (string one of "bookmarks", "history", "passwords" or "useragents",
26 boolean, string)
27 @signal syncError(message) emitted for a general error with the error message (string)
28 @signal syncFinished(type_, done, download) emitted after a synchronization has
29 finished (string one of "bookmarks", "history", "passwords" or "useragents",
30 boolean, boolean)
31 """
32 syncStatus = pyqtSignal(str, bool, str)
33 syncError = pyqtSignal(str)
34 syncFinished = pyqtSignal(str, bool, bool)
35
36 def __init__(self, parent=None):
37 """
38 Constructor
39
40 @param parent reference to the parent object (QObject)
41 """
42 super().__init__(parent)
43
44 self.__state = "idle"
45
46 self.__remoteFiles = {
47 "bookmarks": "Bookmarks",
48 "history": "History",
49 "passwords": "Logins",
50 "useragents": "UserAgentSettings"
51 }
52 self.__remoteFilesFound = []
53
54 self.__messages = {
55 "bookmarks": {
56 "RemoteExists": self.trUtf8(
57 "Remote bookmarks file exists! Syncing local copy..."),
58 "RemoteMissing": self.trUtf8(
59 "Remote bookmarks file does NOT exists. Exporting local copy..."),
60 "LocalMissing": self.trUtf8(
61 "Local bookmarks file does NOT exist. Skipping synchronization!"),
62 },
63 "history": {
64 "RemoteExists": self.trUtf8(
65 "Remote history file exists! Syncing local copy..."),
66 "RemoteMissing": self.trUtf8(
67 "Remote history file does NOT exists. Exporting local copy..."),
68 "LocalMissing": self.trUtf8(
69 "Local history file does NOT exist. Skipping synchronization!"),
70 },
71 "passwords": {
72 "RemoteExists": self.trUtf8(
73 "Remote logins file exists! Syncing local copy..."),
74 "RemoteMissing": self.trUtf8(
75 "Remote logins file does NOT exists. Exporting local copy..."),
76 "LocalMissing": self.trUtf8(
77 "Local logins file does NOT exist. Skipping synchronization!"),
78 },
79 "useragents": {
80 "RemoteExists": self.trUtf8(
81 "Remote user agent settings file exists! Syncing local copy..."),
82 "RemoteMissing": self.trUtf8(
83 "Remote user agent settings file does NOT exists."
84 " Exporting local copy..."),
85 "LocalMissing": self.trUtf8(
86 "Local user agent settings file does NOT exist."
87 " Skipping synchronization!"),
88 },
89 }
90
91 def initialLoadAndCheck(self):
92 """
93 Public method to do the initial check.
94 """
95 if not Preferences.getHelp("SyncEnabled"):
96 return
97
98 self.__state = "initializing"
99
100 self.__remoteFilesFound = []
101 self.__syncIDs = {}
102
103 self.__ftp = QFtp(self)
104 self.__ftp.commandFinished.connect(self.__commandFinished)
105 self.__ftp.listInfo.connect(self.__checkSyncFiles)
106
107 # do proxy setup
108 url = QUrl("ftp://{0}:{1}".format(
109 Preferences.getHelp("SyncFtpServer"),
110 Preferences.getHelp("SyncFtpPort")
111 ))
112 query = QNetworkProxyQuery(url)
113 proxyList = QNetworkProxyFactory.proxyForQuery(query)
114 ftpProxy = QNetworkProxy()
115 for proxy in proxyList:
116 if proxy.type() == QNetworkProxy.NoProxy or \
117 proxy.type() == QNetworkProxy.FtpCachingProxy:
118 ftpProxy = proxy
119 break
120 if ftpProxy.type() == QNetworkProxy.DefaultProxy:
121 self.syncError.emit(self.trUtf8("No suitable proxy found."))
122 return
123 elif ftpProxy.type() == QNetworkProxy.FtpCachingProxy:
124 self.__ftp.setProxy(ftpProxy.hostName(), ftpProxy.port())
125
126 self.__ftp.connectToHost(Preferences.getHelp("SyncFtpServer"),
127 Preferences.getHelp("SyncFtpPort"))
128 self.__ftp.login(Preferences.getHelp("SyncFtpUser"),
129 Preferences.getHelp("SyncFtpPassword"))
130
131 def __changeToStore(self):
132 """
133 Private slot to change to the storage directory.
134
135 This action might cause the storage path to be created on the server.
136 """
137 self.__storePathList = \
138 Preferences.getHelp("SyncFtpPath").replace("\\", "/").split("/")
139 if self.__storePathList[0] == "":
140 del self.__storePathList[0]
141 self.__ftp.cd(self.__storePathList[0])
142
143 def __commandFinished(self, id, error):
144 """
145 Private slot handling the end of a command.
146
147 @param id id of the finished command (integer)
148 @param error flag indicating an error situation (boolean)
149 """
150 if error:
151 if self.__ftp.currentCommand() in [
152 QFtp.ConnectToHost, QFtp.Login, QFtp.Mkdir, QFtp.List]:
153 self.syncError.emit(self.__ftp.errorString())
154 elif self.__ftp.currentCommand() == QFtp.Cd:
155 self.__ftp.mkdir(self.__storePathList[0])
156 self.__ftp.cd(self.__storePathList[0])
157 else:
158 if id in self.__syncIDs:
159 self.__syncIDs[id][1].close()
160 self.syncStatus.emit(self.__syncIDs[id][0], False,
161 self.__ftp.errorString())
162 self.syncFinished.emit(self.__syncIDs[id][0], False,
163 self.__syncIDs[id][2])
164 del self.__syncIDs[id]
165 else:
166 if self.__ftp.currentCommand() == QFtp.Login:
167 self.__changeToStore()
168 elif self.__ftp.currentCommand() == QFtp.Cd:
169 del self.__storePathList[0]
170 if self.__storePathList:
171 self.__ftp.cd(self.__storePathList[0])
172 else:
173 self.__storeReached()
174 elif self.__ftp.currentCommand() == QFtp.List:
175 self.__initialSync()
176 else:
177 if id in self.__syncIDs:
178 self.__syncIDs[id][1].close()
179 self.syncFinished.emit(self.__syncIDs[id][0], True,
180 self.__syncIDs[id][2])
181 del self.__syncIDs[id]
182
183 def __storeReached(self):
184 """
185 Private slot executed, when the storage directory was reached.
186 """
187 self.__ftp.list()
188
189 def __checkSyncFiles(self, info):
190 """
191 Private slot called for each entry sent by the FTP list command.
192
193 @param info info about the entry (QUrlInfo)
194 """
195 if info.isValid() and info.isFile():
196 if info.name() in self.__remoteFiles.values():
197 self.__remoteFilesFound.append(info.name())
198
199 def __initialSyncFile(self, type_, fileName):
200 """
201 Private method to do the initial synchronization of the given file.
202
203 @param type_ type of the synchronization event (string one
204 of "bookmarks", "history", "passwords" or "useragents")
205 @param fileName name of the file to be synchronized (string)
206 """
207 f = QFile(fileName)
208 if self.__remoteFiles[type_] in self.__remoteFilesFound:
209 self.syncStatus.emit(type_, True,
210 self.__messages[type_]["RemoteExists"])
211 f.open(QIODevice.WriteOnly)
212 id = self.__ftp.get(self.__remoteFiles[type_], f)
213 self.__syncIDs[id] = (type_, f, True)
214 else:
215 if f.exists():
216 self.syncStatus.emit(type_, True,
217 self.__messages[type_]["RemoteMissing"])
218 f.open(QIODevice.ReadOnly)
219 id = self.__ftp.put(f, self.__remoteFiles[type_])
220 self.__syncIDs[id] = (type_, f, False)
221 else:
222 self.syncStatus.emit(type_, True,
223 self.__messages[type_]["LocalMissing"])
224
225 def __initialSync(self):
226 """
227 Private slot to do the initial synchronization.
228 """
229 # Bookmarks
230 if Preferences.getHelp("SyncBookmarks"):
231 self.__initialSyncFile("bookmarks",
232 Helpviewer.HelpWindow.HelpWindow.bookmarksManager().getFileName())
233
234 # History
235 if Preferences.getHelp("SyncHistory"):
236 self.__initialSyncFile("history",
237 Helpviewer.HelpWindow.HelpWindow.historyManager().getFileName())
238
239 # Passwords
240 if Preferences.getHelp("SyncPasswords"):
241 self.__initialSyncFile("passwords",
242 Helpviewer.HelpWindow.HelpWindow.passwordManager().getFileName())
243
244 # User Agent Settings
245 if Preferences.getHelp("SyncUserAgents"):
246 self.__initialSyncFile("useragents",
247 Helpviewer.HelpWindow.HelpWindow.userAgentsManager().getFileName())
248
249 def __syncFile(self, type_, fileName):
250 """
251 Private method to synchronize the given file.
252
253 @param type_ type of the synchronization event (string one
254 of "bookmarks", "history", "passwords" or "useragents")
255 @param fileName name of the file to be synchronized (string)
256 """
257 f = QFile(fileName)
258 if f.exists():
259 f.open(QIODevice.ReadOnly)
260 id = self.__ftp.put(f, self.__remoteFiles[type_])
261 self.__syncIDs[id] = (type_, f, False)
262
263 def syncBookmarks(self):
264 """
265 Public method to synchronize the bookmarks.
266 """
267 self.__syncFile("bookmarks",
268 Helpviewer.HelpWindow.HelpWindow.bookmarksManager().getFileName())
269
270 def syncHistory(self):
271 """
272 Public method to synchronize the history.
273 """
274 self.__syncFile("history",
275 Helpviewer.HelpWindow.HelpWindow.historyManager().getFileName())
276
277 def syncPasswords(self):
278 """
279 Public method to synchronize the passwords.
280 """
281 self.__syncFile("passwords",
282 Helpviewer.HelpWindow.HelpWindow.passwordManager().getFileName())
283
284 def syncUserAgents(self):
285 """
286 Public method to synchronize the user agents.
287 """
288 self.__syncFile("useragents",
289 Helpviewer.HelpWindow.HelpWindow.userAgentsManager().getFileName())
290
291 def shutdown(self):
292 """
293 Public method to shut down the handler.
294 """
295 t = QTime.currentTime()
296 t.start()
297 while t.elapsed() < 5000 and self.__ftp.hasPendingCommands():
298 QThread.msleep(200)
299 if self.__ftp.hasPendingCommands():
300 self.__ftp.clearPendingCommands()
301 if self.__ftp.currentCommand() != 0:
302 self.__ftp.abort()

eric ide

mercurial