Helpviewer/Passwords/PasswordManager.py

branch
Py2 comp.
changeset 3057
10516539f238
parent 2525
8b507a9a2d40
parent 3002
6ffc581f00f1
child 3058
0a02c433f52d
equal deleted inserted replaced
3056:9986ec0e559a 3057:10516539f238
9 9
10 from __future__ import unicode_literals # __IGNORE_WARNING__ 10 from __future__ import unicode_literals # __IGNORE_WARNING__
11 11
12 import os 12 import os
13 13
14 from PyQt4.QtCore import pyqtSignal, QObject, QByteArray, QUrl, QCoreApplication, \ 14 from PyQt4.QtCore import pyqtSignal, QObject, QByteArray, QUrl, \
15 QXmlStreamReader 15 QCoreApplication, QXmlStreamReader
16 from PyQt4.QtGui import QProgressDialog, QApplication 16 from PyQt4.QtGui import QProgressDialog, QApplication
17 from PyQt4.QtNetwork import QNetworkRequest 17 from PyQt4.QtNetwork import QNetworkRequest
18 from PyQt4.QtWebKit import QWebSettings, QWebPage 18 from PyQt4.QtWebKit import QWebSettings, QWebPage
19 19
20 from E5Gui import E5MessageBox 20 from E5Gui import E5MessageBox
99 """ 99 """
100 if not self.__loaded: 100 if not self.__loaded:
101 self.__load() 101 self.__load()
102 102
103 key = self.__createKey(url, realm) 103 key = self.__createKey(url, realm)
104 self.__logins[key] = (username, Utilities.crypto.pwConvert(password, encode=True)) 104 self.__logins[key] = (
105 username,
106 Utilities.crypto.pwConvert(password, encode=True)
107 )
105 self.changed.emit() 108 self.changed.emit()
106 109
107 def __createKey(self, url, realm): 110 def __createKey(self, url, realm):
108 """ 111 """
109 Private method to create the key string for the login credentials. 112 Private method to create the key string for the login credentials.
111 @param url URL to get the credentials for (QUrl) 114 @param url URL to get the credentials for (QUrl)
112 @param realm realm to get the credentials for (string) 115 @param realm realm to get the credentials for (string)
113 @return key string (string) 116 @return key string (string)
114 """ 117 """
115 if realm: 118 if realm:
116 key = "{0}://{1} ({2})".format(url.scheme(), url.authority(), realm) 119 key = "{0}://{1} ({2})".format(
120 url.scheme(), url.authority(), realm)
117 else: 121 else:
118 key = "{0}://{1}".format(url.scheme(), url.authority()) 122 key = "{0}://{1}".format(url.scheme(), url.authority())
119 return key 123 return key
120 124
121 def getFileName(self): 125 def getFileName(self):
134 return 138 return
135 139
136 from .PasswordWriter import PasswordWriter 140 from .PasswordWriter import PasswordWriter
137 loginFile = self.getFileName() 141 loginFile = self.getFileName()
138 writer = PasswordWriter() 142 writer = PasswordWriter()
139 if not writer.write(loginFile, self.__logins, self.__loginForms, self.__never): 143 if not writer.write(
144 loginFile, self.__logins, self.__loginForms, self.__never):
140 E5MessageBox.critical(None, 145 E5MessageBox.critical(None,
141 self.trUtf8("Saving login data"), 146 self.trUtf8("Saving login data"),
142 self.trUtf8("""<p>Login data could not be saved to <b>{0}</b></p>""" 147 self.trUtf8(
143 ).format(loginFile)) 148 """<p>Login data could not be saved to <b>{0}</b></p>"""
149 ).format(loginFile))
144 else: 150 else:
145 self.passwordsSaved.emit() 151 self.passwordsSaved.emit()
146 152
147 def __load(self): 153 def __load(self):
148 """ 154 """
152 if not os.path.exists(loginFile): 158 if not os.path.exists(loginFile):
153 self.__loadNonXml(os.path.splitext(loginFile)[0]) 159 self.__loadNonXml(os.path.splitext(loginFile)[0])
154 else: 160 else:
155 from .PasswordReader import PasswordReader 161 from .PasswordReader import PasswordReader
156 reader = PasswordReader() 162 reader = PasswordReader()
157 self.__logins, self.__loginForms, self.__never = reader.read(loginFile) 163 self.__logins, self.__loginForms, self.__never = \
164 reader.read(loginFile)
158 if reader.error() != QXmlStreamReader.NoError: 165 if reader.error() != QXmlStreamReader.NoError:
159 E5MessageBox.warning(None, 166 E5MessageBox.warning(None,
160 self.trUtf8("Loading login data"), 167 self.trUtf8("Loading login data"),
161 self.trUtf8("""Error when loading login data on""" 168 self.trUtf8("""Error when loading login data on"""
162 """ line {0}, column {1}:\n{2}""")\ 169 """ line {0}, column {1}:\n{2}""")\
188 """<p>Reason: {1}</p>""")\ 195 """<p>Reason: {1}</p>""")\
189 .format(loginFile, str(err))) 196 .format(loginFile, str(err)))
190 return 197 return
191 198
192 data = [] 199 data = []
193 section = 0 # 0 = login data, 1 = forms data, 2 = never store info 200 section = 0 # 0 = login data, 1 = forms data,
201 # 2 = never store info
194 for line in lines.splitlines(): 202 for line in lines.splitlines():
195 if line == self.FORMS: 203 if line == self.FORMS:
196 section = 1 204 section = 1
197 continue 205 continue
198 elif line == self.NEVER: 206 elif line == self.NEVER:
204 data.append(line) 212 data.append(line)
205 else: 213 else:
206 if len(data) != 3: 214 if len(data) != 3:
207 E5MessageBox.critical(None, 215 E5MessageBox.critical(None,
208 self.trUtf8("Loading login data"), 216 self.trUtf8("Loading login data"),
209 self.trUtf8("""<p>Login data could not be loaded """ 217 self.trUtf8(
210 """from <b>{0}</b></p>""" 218 """<p>Login data could not be loaded """
211 """<p>Reason: Wrong input format</p>""")\ 219 """from <b>{0}</b></p>"""
220 """<p>Reason: Wrong input format</p>""")\
212 .format(loginFile)) 221 .format(loginFile))
213 return 222 return
214 self.__logins[data[0]] = (data[1], data[2]) 223 self.__logins[data[0]] = (data[1], data[2])
215 data = [] 224 data = []
216 225
373 mb = E5MessageBox.E5MessageBox(E5MessageBox.Question, 382 mb = E5MessageBox.E5MessageBox(E5MessageBox.Question,
374 self.trUtf8("Save password"), 383 self.trUtf8("Save password"),
375 self.trUtf8( 384 self.trUtf8(
376 """<b>Would you like to save this password?</b><br/>""" 385 """<b>Would you like to save this password?</b><br/>"""
377 """To review passwords you have saved and remove them, """ 386 """To review passwords you have saved and remove them, """
378 """use the password management dialog of the Settings menu."""), 387 """use the password management dialog of the Settings"""
388 """ menu."""),
379 modal=True) 389 modal=True)
380 neverButton = mb.addButton( 390 neverButton = mb.addButton(
381 self.trUtf8("Never for this site"), E5MessageBox.DestructiveRole) 391 self.trUtf8("Never for this site"),
382 noButton = mb.addButton(self.trUtf8("Not now"), E5MessageBox.RejectRole) 392 E5MessageBox.DestructiveRole)
393 noButton = mb.addButton(
394 self.trUtf8("Not now"), E5MessageBox.RejectRole)
383 mb.addButton(E5MessageBox.Yes) 395 mb.addButton(E5MessageBox.Yes)
384 mb.exec_() 396 mb.exec_()
385 if mb.clickedButton() == neverButton: 397 if mb.clickedButton() == neverButton:
386 self.__never.append(url.toString()) 398 self.__never.append(url.toString())
387 return 399 return
400 elif password == "" and \ 412 elif password == "" and \
401 type_ == "password": 413 type_ == "password":
402 password = element[1] 414 password = element[1]
403 form.elements[index] = (element[0], "--PASSWORD--") 415 form.elements[index] = (element[0], "--PASSWORD--")
404 if user and password: 416 if user and password:
405 self.__logins[key] = (user, Utilities.crypto.pwConvert(password, encode=True)) 417 self.__logins[key] = \
418 (user, Utilities.crypto.pwConvert(password, encode=True))
406 self.__loginForms[key] = form 419 self.__loginForms[key] = form
407 self.changed.emit() 420 self.changed.emit()
408 421
409 def __stripUrl(self, url): 422 def __stripUrl(self, url):
410 """ 423 """
423 """ 436 """
424 Private method to find the form used for logging in. 437 Private method to find the form used for logging in.
425 438
426 @param webPage reference to the web page (QWebPage) 439 @param webPage reference to the web page (QWebPage)
427 @param data data to be sent (QByteArray) 440 @param data data to be sent (QByteArray)
428 @keyparam boundary boundary string (QByteArray) for multipart encoded data, 441 @keyparam boundary boundary string (QByteArray) for multipart
429 None for urlencoded data 442 encoded data, None for urlencoded data
430 @return parsed form (LoginForm) 443 @return parsed form (LoginForm)
431 """ 444 """
432 from .LoginForm import LoginForm 445 from .LoginForm import LoginForm
433 form = LoginForm() 446 form = LoginForm()
434 if boundary is not None: 447 if boundary is not None:
546 for element in form.elements: 559 for element in form.elements:
547 name = element[0] 560 name = element[0]
548 value = element[1] 561 value = element[1]
549 562
550 disabled = page.mainFrame().evaluateJavaScript( 563 disabled = page.mainFrame().evaluateJavaScript(
551 'document.forms[{0}].elements["{1}"].disabled'.format(formName, name)) 564 'document.forms[{0}].elements["{1}"].disabled'.format(
565 formName, name))
552 if disabled: 566 if disabled:
553 continue 567 continue
554 568
555 readOnly = page.mainFrame().evaluateJavaScript( 569 readOnly = page.mainFrame().evaluateJavaScript(
556 'document.forms[{0}].elements["{1}"].readOnly'.format(formName, name)) 570 'document.forms[{0}].elements["{1}"].readOnly'.format(
571 formName, name))
557 if readOnly: 572 if readOnly:
558 continue 573 continue
559 574
560 type_ = page.mainFrame().evaluateJavaScript( 575 type_ = page.mainFrame().evaluateJavaScript(
561 'document.forms[{0}].elements["{1}"].type'.format(formName, name)) 576 'document.forms[{0}].elements["{1}"].type'.format(
577 formName, name))
562 if type_ == "" or \ 578 if type_ == "" or \
563 type_ in ["hidden", "reset", "submit"]: 579 type_ in ["hidden", "reset", "submit"]:
564 continue 580 continue
565 if type_ == "password": 581 if type_ == "password":
566 value = Utilities.crypto.pwConvert(self.__logins[key][1], encode=False) 582 value = Utilities.crypto.pwConvert(
583 self.__logins[key][1], encode=False)
567 setType = type_ == "checkbox" and "checked" or "value" 584 setType = type_ == "checkbox" and "checked" or "value"
568 value = value.replace("\\", "\\\\") 585 value = value.replace("\\", "\\\\")
569 value = value.replace('"', '\\"') 586 value = value.replace('"', '\\"')
570 javascript = 'document.forms[{0}].elements["{1}"].{2}="{3}";'.format( 587 javascript = \
571 formName, name, setType, value) 588 'document.forms[{0}].elements["{1}"].{2}="{3}";'.format(
589 formName, name, setType, value)
572 page.mainFrame().evaluateJavaScript(javascript) 590 page.mainFrame().evaluateJavaScript(javascript)
573 591
574 def masterPasswordChanged(self, oldPassword, newPassword): 592 def masterPasswordChanged(self, oldPassword, newPassword):
575 """ 593 """
576 Public slot to handle the change of the master password. 594 Public slot to handle the change of the master password.
579 @param newPassword new master password (string) 597 @param newPassword new master password (string)
580 """ 598 """
581 if not self.__loaded: 599 if not self.__loaded:
582 self.__load() 600 self.__load()
583 601
584 progress = QProgressDialog(self.trUtf8("Re-encoding saved passwords..."), 602 progress = QProgressDialog(
603 self.trUtf8("Re-encoding saved passwords..."),
585 None, 0, len(self.__logins), QApplication.activeModalWidget()) 604 None, 0, len(self.__logins), QApplication.activeModalWidget())
586 progress.setMinimumDuration(0) 605 progress.setMinimumDuration(0)
587 count = 0 606 count = 0
588 607
589 for key in self.__logins: 608 for key in self.__logins:

eric ide

mercurial