src/eric7/WebBrowser/Sync/SyncHandler.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
17 17
18 18
19 class SyncHandler(QObject): 19 class SyncHandler(QObject):
20 """ 20 """
21 Base class for synchronization handlers. 21 Base class for synchronization handlers.
22 22
23 @signal syncStatus(type_, message) emitted to indicate the synchronization 23 @signal syncStatus(type_, message) emitted to indicate the synchronization
24 status (string one of "bookmarks", "history", "passwords", 24 status (string one of "bookmarks", "history", "passwords",
25 "useragents" or "speeddial", string) 25 "useragents" or "speeddial", string)
26 @signal syncError(message) emitted for a general error with the error 26 @signal syncError(message) emitted for a general error with the error
27 message (string) 27 message (string)
29 synchronization (string) 29 synchronization (string)
30 @signal syncFinished(type_, done, download) emitted after a 30 @signal syncFinished(type_, done, download) emitted after a
31 synchronization has finished (string one of "bookmarks", "history", 31 synchronization has finished (string one of "bookmarks", "history",
32 "passwords", "useragents" or "speeddial", boolean, boolean) 32 "passwords", "useragents" or "speeddial", boolean, boolean)
33 """ 33 """
34
34 syncStatus = pyqtSignal(str, str) 35 syncStatus = pyqtSignal(str, str)
35 syncError = pyqtSignal(str) 36 syncError = pyqtSignal(str)
36 syncMessage = pyqtSignal(str) 37 syncMessage = pyqtSignal(str)
37 syncFinished = pyqtSignal(str, bool, bool) 38 syncFinished = pyqtSignal(str, bool, bool)
38 39
39 def __init__(self, parent=None): 40 def __init__(self, parent=None):
40 """ 41 """
41 Constructor 42 Constructor
42 43
43 @param parent reference to the parent object (QObject) 44 @param parent reference to the parent object (QObject)
44 """ 45 """
45 super().__init__(parent) 46 super().__init__(parent)
46 47
47 self._firstTimeSynced = False 48 self._firstTimeSynced = False
48 49
49 self._remoteFiles = { 50 self._remoteFiles = {
50 "bookmarks": "Bookmarks", 51 "bookmarks": "Bookmarks",
51 "history": "History", 52 "history": "History",
52 "passwords": "Logins", 53 "passwords": "Logins",
53 "useragents": "UserAgentSettings", 54 "useragents": "UserAgentSettings",
54 "speeddial": "SpeedDial", 55 "speeddial": "SpeedDial",
55 } 56 }
56 57
57 self._messages = { 58 self._messages = {
58 "bookmarks": { 59 "bookmarks": {
59 "RemoteExists": self.tr( 60 "RemoteExists": self.tr(
60 "Remote bookmarks file exists! Syncing local copy..."), 61 "Remote bookmarks file exists! Syncing local copy..."
61 "RemoteMissing": self.tr( 62 ),
62 "Remote bookmarks file does NOT exist. Exporting" 63 "RemoteMissing": self.tr(
63 " local copy..."), 64 "Remote bookmarks file does NOT exist. Exporting" " local copy..."
64 "LocalNewer": self.tr( 65 ),
65 "Local bookmarks file is NEWER. Exporting local copy..."), 66 "LocalNewer": self.tr(
66 "LocalMissing": self.tr( 67 "Local bookmarks file is NEWER. Exporting local copy..."
67 "Local bookmarks file does NOT exist. Skipping" 68 ),
68 " synchronization!"), 69 "LocalMissing": self.tr(
70 "Local bookmarks file does NOT exist. Skipping" " synchronization!"
71 ),
69 "Uploading": self.tr("Uploading local bookmarks file..."), 72 "Uploading": self.tr("Uploading local bookmarks file..."),
70 }, 73 },
71 "history": { 74 "history": {
72 "RemoteExists": self.tr( 75 "RemoteExists": self.tr(
73 "Remote history file exists! Syncing local copy..."), 76 "Remote history file exists! Syncing local copy..."
74 "RemoteMissing": self.tr( 77 ),
75 "Remote history file does NOT exist. Exporting" 78 "RemoteMissing": self.tr(
76 " local copy..."), 79 "Remote history file does NOT exist. Exporting" " local copy..."
77 "LocalNewer": self.tr( 80 ),
78 "Local history file is NEWER. Exporting local copy..."), 81 "LocalNewer": self.tr(
79 "LocalMissing": self.tr( 82 "Local history file is NEWER. Exporting local copy..."
80 "Local history file does NOT exist. Skipping" 83 ),
81 " synchronization!"), 84 "LocalMissing": self.tr(
85 "Local history file does NOT exist. Skipping" " synchronization!"
86 ),
82 "Uploading": self.tr("Uploading local history file..."), 87 "Uploading": self.tr("Uploading local history file..."),
83 }, 88 },
84 "passwords": { 89 "passwords": {
85 "RemoteExists": self.tr( 90 "RemoteExists": self.tr(
86 "Remote logins file exists! Syncing local copy..."), 91 "Remote logins file exists! Syncing local copy..."
87 "RemoteMissing": self.tr( 92 ),
88 "Remote logins file does NOT exist. Exporting" 93 "RemoteMissing": self.tr(
89 " local copy..."), 94 "Remote logins file does NOT exist. Exporting" " local copy..."
90 "LocalNewer": self.tr( 95 ),
91 "Local logins file is NEWER. Exporting local copy..."), 96 "LocalNewer": self.tr(
92 "LocalMissing": self.tr( 97 "Local logins file is NEWER. Exporting local copy..."
93 "Local logins file does NOT exist. Skipping" 98 ),
94 " synchronization!"), 99 "LocalMissing": self.tr(
100 "Local logins file does NOT exist. Skipping" " synchronization!"
101 ),
95 "Uploading": self.tr("Uploading local logins file..."), 102 "Uploading": self.tr("Uploading local logins file..."),
96 }, 103 },
97 "useragents": { 104 "useragents": {
98 "RemoteExists": self.tr( 105 "RemoteExists": self.tr(
99 "Remote user agent settings file exists! Syncing local" 106 "Remote user agent settings file exists! Syncing local" " copy..."
100 " copy..."), 107 ),
101 "RemoteMissing": self.tr( 108 "RemoteMissing": self.tr(
102 "Remote user agent settings file does NOT exist." 109 "Remote user agent settings file does NOT exist."
103 " Exporting local copy..."), 110 " Exporting local copy..."
111 ),
104 "LocalNewer": self.tr( 112 "LocalNewer": self.tr(
105 "Local user agent settings file is NEWER. Exporting" 113 "Local user agent settings file is NEWER. Exporting"
106 " local copy..."), 114 " local copy..."
115 ),
107 "LocalMissing": self.tr( 116 "LocalMissing": self.tr(
108 "Local user agent settings file does NOT exist." 117 "Local user agent settings file does NOT exist."
109 " Skipping synchronization!"), 118 " Skipping synchronization!"
110 "Uploading": self.tr( 119 ),
111 "Uploading local user agent settings file..."), 120 "Uploading": self.tr("Uploading local user agent settings file..."),
112 }, 121 },
113 "speeddial": { 122 "speeddial": {
114 "RemoteExists": self.tr( 123 "RemoteExists": self.tr(
115 "Remote speed dial settings file exists! Syncing local" 124 "Remote speed dial settings file exists! Syncing local" " copy..."
116 " copy..."), 125 ),
117 "RemoteMissing": self.tr( 126 "RemoteMissing": self.tr(
118 "Remote speed dial settings file does NOT exist." 127 "Remote speed dial settings file does NOT exist."
119 " Exporting local copy..."), 128 " Exporting local copy..."
129 ),
120 "LocalNewer": self.tr( 130 "LocalNewer": self.tr(
121 "Local speed dial settings file is NEWER. Exporting" 131 "Local speed dial settings file is NEWER. Exporting"
122 " local copy..."), 132 " local copy..."
133 ),
123 "LocalMissing": self.tr( 134 "LocalMissing": self.tr(
124 "Local speed dial settings file does NOT exist." 135 "Local speed dial settings file does NOT exist."
125 " Skipping synchronization!"), 136 " Skipping synchronization!"
126 "Uploading": self.tr( 137 ),
127 "Uploading local speed dial settings file..."), 138 "Uploading": self.tr("Uploading local speed dial settings file..."),
128 }, 139 },
129 } 140 }
130 141
131 def syncBookmarks(self): 142 def syncBookmarks(self):
132 """ 143 """
133 Public method to synchronize the bookmarks. 144 Public method to synchronize the bookmarks.
134 145
135 @exception NotImplementedError raised to indicate that this method 146 @exception NotImplementedError raised to indicate that this method
136 must be implemented by subclasses 147 must be implemented by subclasses
137 """ 148 """
138 raise NotImplementedError 149 raise NotImplementedError
139 150
140 def syncHistory(self): 151 def syncHistory(self):
141 """ 152 """
142 Public method to synchronize the history. 153 Public method to synchronize the history.
143 154
144 @exception NotImplementedError raised to indicate that this method 155 @exception NotImplementedError raised to indicate that this method
145 must be implemented by subclasses 156 must be implemented by subclasses
146 """ 157 """
147 raise NotImplementedError 158 raise NotImplementedError
148 159
149 def syncPasswords(self): 160 def syncPasswords(self):
150 """ 161 """
151 Public method to synchronize the passwords. 162 Public method to synchronize the passwords.
152 163
153 @exception NotImplementedError raised to indicate that this method 164 @exception NotImplementedError raised to indicate that this method
154 must be implemented by subclasses 165 must be implemented by subclasses
155 """ 166 """
156 raise NotImplementedError 167 raise NotImplementedError
157 168
158 def syncUserAgents(self): 169 def syncUserAgents(self):
159 """ 170 """
160 Public method to synchronize the user agents. 171 Public method to synchronize the user agents.
161 172
162 @exception NotImplementedError raised to indicate that this method 173 @exception NotImplementedError raised to indicate that this method
163 must be implemented by subclasses 174 must be implemented by subclasses
164 """ 175 """
165 raise NotImplementedError 176 raise NotImplementedError
166 177
167 def syncSpeedDial(self): 178 def syncSpeedDial(self):
168 """ 179 """
169 Public method to synchronize the speed dial data. 180 Public method to synchronize the speed dial data.
170 181
171 @exception NotImplementedError raised to indicate that this method 182 @exception NotImplementedError raised to indicate that this method
172 must be implemented by subclasses 183 must be implemented by subclasses
173 """ 184 """
174 raise NotImplementedError 185 raise NotImplementedError
175 186
176 def initialLoadAndCheck(self, forceUpload): 187 def initialLoadAndCheck(self, forceUpload):
177 """ 188 """
178 Public method to do the initial check. 189 Public method to do the initial check.
179 190
180 @param forceUpload flag indicating a forced upload of the files 191 @param forceUpload flag indicating a forced upload of the files
181 (boolean) 192 (boolean)
182 @exception NotImplementedError raised to indicate that this method 193 @exception NotImplementedError raised to indicate that this method
183 must be implemented by subclasses 194 must be implemented by subclasses
184 """ 195 """
185 raise NotImplementedError 196 raise NotImplementedError
186 197
187 def shutdown(self): 198 def shutdown(self):
188 """ 199 """
189 Public method to shut down the handler. 200 Public method to shut down the handler.
190 201
191 @exception NotImplementedError raised to indicate that this method 202 @exception NotImplementedError raised to indicate that this method
192 must be implemented by subclasses 203 must be implemented by subclasses
193 """ 204 """
194 raise NotImplementedError 205 raise NotImplementedError
195 206
196 def readFile(self, fileName, type_): 207 def readFile(self, fileName, type_):
197 """ 208 """
198 Public method to read a file. 209 Public method to read a file.
199 210
200 If encrypted synchronization is enabled, the data will be encrypted 211 If encrypted synchronization is enabled, the data will be encrypted
201 using the relevant encryption key. 212 using the relevant encryption key.
202 213
203 @param fileName name of the file to be read (string) 214 @param fileName name of the file to be read (string)
204 @param type_ type of the synchronization event (string one 215 @param type_ type of the synchronization event (string one
205 of "bookmarks", "history", "passwords", "useragents" or 216 of "bookmarks", "history", "passwords", "useragents" or
206 "speeddial") 217 "speeddial")
207 @return data of the file, optionally encrypted (QByteArray) 218 @return data of the file, optionally encrypted (QByteArray)
210 try: 221 try:
211 with open(fileName, "rb") as inputFile: 222 with open(fileName, "rb") as inputFile:
212 data = inputFile.read() 223 data = inputFile.read()
213 except OSError: 224 except OSError:
214 return QByteArray() 225 return QByteArray()
215 226
216 if ( 227 if Preferences.getWebBrowser("SyncEncryptData") and (
217 Preferences.getWebBrowser("SyncEncryptData") and 228 not Preferences.getWebBrowser("SyncEncryptPasswordsOnly")
218 (not Preferences.getWebBrowser("SyncEncryptPasswordsOnly") or 229 or (
219 (Preferences.getWebBrowser("SyncEncryptPasswordsOnly") and 230 Preferences.getWebBrowser("SyncEncryptPasswordsOnly")
220 type_ == "passwords")) 231 and type_ == "passwords"
232 )
221 ): 233 ):
222 key = Preferences.getWebBrowser("SyncEncryptionKey") 234 key = Preferences.getWebBrowser("SyncEncryptionKey")
223 if not key: 235 if not key:
224 return QByteArray() 236 return QByteArray()
225 237
226 data, ok = dataEncrypt( 238 data, ok = dataEncrypt(
227 data, key, 239 data,
228 keyLength=Preferences.getWebBrowser( 240 key,
229 "SyncEncryptionKeyLength"), 241 keyLength=Preferences.getWebBrowser("SyncEncryptionKeyLength"),
230 hashIterations=100) 242 hashIterations=100,
243 )
231 if not ok: 244 if not ok:
232 return QByteArray() 245 return QByteArray()
233 246
234 return QByteArray(data) 247 return QByteArray(data)
235 248
236 return QByteArray() 249 return QByteArray()
237 250
238 def writeFile(self, data, fileName, type_, timestamp=0): 251 def writeFile(self, data, fileName, type_, timestamp=0):
239 """ 252 """
240 Public method to write the data to a file. 253 Public method to write the data to a file.
241 254
242 If encrypted synchronization is enabled, the data will be decrypted 255 If encrypted synchronization is enabled, the data will be decrypted
243 using the relevant encryption key. 256 using the relevant encryption key.
244 257
245 @param data data to be written and optionally decrypted (QByteArray) 258 @param data data to be written and optionally decrypted (QByteArray)
246 @param fileName name of the file the data is to be written to (string) 259 @param fileName name of the file the data is to be written to (string)
247 @param type_ type of the synchronization event (string one 260 @param type_ type of the synchronization event (string one
248 of "bookmarks", "history", "passwords", "useragents" or 261 of "bookmarks", "history", "passwords", "useragents" or
249 "speeddial") 262 "speeddial")
250 @param timestamp timestamp to be given to the file (int) 263 @param timestamp timestamp to be given to the file (int)
251 @return tuple giving a success flag and an error string (boolean, 264 @return tuple giving a success flag and an error string (boolean,
252 string) 265 string)
253 """ 266 """
254 data = bytes(data) 267 data = bytes(data)
255 268
256 if ( 269 if Preferences.getWebBrowser("SyncEncryptData") and (
257 Preferences.getWebBrowser("SyncEncryptData") and 270 not Preferences.getWebBrowser("SyncEncryptPasswordsOnly")
258 (not Preferences.getWebBrowser("SyncEncryptPasswordsOnly") or 271 or (
259 (Preferences.getWebBrowser("SyncEncryptPasswordsOnly") and 272 Preferences.getWebBrowser("SyncEncryptPasswordsOnly")
260 type_ == "passwords")) 273 and type_ == "passwords"
274 )
261 ): 275 ):
262 key = Preferences.getWebBrowser("SyncEncryptionKey") 276 key = Preferences.getWebBrowser("SyncEncryptionKey")
263 if not key: 277 if not key:
264 return False, self.tr("Invalid encryption key given.") 278 return False, self.tr("Invalid encryption key given.")
265 279
266 data, ok = dataDecrypt( 280 data, ok = dataDecrypt(
267 data, key, 281 data,
268 keyLength=Preferences.getWebBrowser("SyncEncryptionKeyLength")) 282 key,
283 keyLength=Preferences.getWebBrowser("SyncEncryptionKeyLength"),
284 )
269 if not ok: 285 if not ok:
270 return False, self.tr("Data cannot be decrypted.") 286 return False, self.tr("Data cannot be decrypted.")
271 287
272 try: 288 try:
273 with open(fileName, "wb") as outputFile: 289 with open(fileName, "wb") as outputFile:
274 outputFile.write(data) 290 outputFile.write(data)
275 if timestamp > 0: 291 if timestamp > 0:
276 os.utime(fileName, (timestamp, timestamp)) 292 os.utime(fileName, (timestamp, timestamp))

eric ide

mercurial