def __pull_passwords(self, bulk_keys): """ Pull from passwords @param bulk_keys as KeyBundle @raise StopIteration """ Logger.sync_debug("pull passwords") records = self.__firefox_sync.get_records("passwords", bulk_keys) for record in records: self.__check_worker() if record["modified"] < self.__mtimes["passwords"]: continue sleep(0.01) Logger.sync_debug("pulling %s", record) password = record["payload"] password_id = password["id"].strip("{}") if "formSubmitURL" in password.keys(): self.__helper.clear(password_id, self.__helper.store, password["usernameField"], password["username"], password["passwordField"], password["password"], password["hostname"], password["formSubmitURL"], password_id, None) elif "deleted" in password.keys(): # We assume True self.__helper.clear(password_id)
def __on_secret_search(self, source, result, form_uri, callback, *args): """ Set username/password input @param source as GObject.Object @param result as Gio.AsyncResult @param form_uri as str @param callback as function @param args """ try: if result is not None: items = self.__secret.search_finish(result) count = len(items) index = 0 for item in items: item.load_secret(None, self.__on_load_secret, form_uri, index, count, callback, *args) index += 1 if not items: callback(None, None, form_uri, 0, 0, *args) else: callback(None, None, form_uri, 0, 0, *args) except Exception as e: Logger.debug("PasswordsHelper::__on_secret_search(): %s", e) callback(None, None, form_uri, 0, 0, *args)
def get_favicon(self, uri, scale_factor): """ @param uri as str @param suffix as str @param scale factor as int @return cairo.surface """ try: if not uri: return None filepath = self.get_favicon_path(uri) if filepath is not None and\ GLib.file_test(filepath, GLib.FileTest.IS_REGULAR): pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale( filepath, ArtSize.FAVICON * scale_factor, ArtSize.FAVICON * scale_factor, True) surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale_factor, None) return surface except Exception as e: Logger.debug("Art::get_favicon(): %s", e) return None
def add_language(self, code, uri): """ Add language for uri @param code as str @param uri as str """ parsed = urlparse(uri) if parsed.scheme not in ["http", "https"]: return try: with SqlCursor(self) as sql: codes = self.get_languages(uri) if codes is not None: if code not in codes: codes.append(code) sql.execute( "UPDATE settings\ SET languages=?\ WHERE uri=?", (";".join(codes), parsed.netloc)) else: sql.execute( "INSERT INTO settings\ (uri, languages)\ VALUES (?, ?)", (parsed.netloc, code)) except Exception as e: Logger.error("DatabaseSettings::add_language(): %s", e)
def set_chooser_uri(self, chooseruri, uri): """ Add an uri related to uri @param chooseruri as str @param uri as str """ parsed = urlparse(uri) if parsed.scheme not in ["http", "https"]: return try: with SqlCursor(self) as sql: result = sql.execute( "SELECT rowid FROM settings\ WHERE uri=?", (parsed.netloc, )) v = result.fetchone() if v is not None: sql.execute( "UPDATE settings\ SET chooseruri=?\ WHERE uri=?", (chooseruri, parsed.netloc)) else: sql.execute( "INSERT INTO settings\ (uri, chooseruri)\ VALUES (?, ?)", (parsed.netloc, chooseruri)) except Exception as e: Logger.error("DatabaseSettings::set_chooser_uri(): %s", e)
def allow_geolocation(self, uri, b): """ Allow geolocation for uri @param uri as str @param b as bool """ parsed = urlparse(uri) if parsed.scheme not in ["http", "https"]: return try: with SqlCursor(self) as sql: result = sql.execute( "SELECT rowid FROM settings\ WHERE uri=?", (parsed.netloc, )) v = result.fetchone() if v is not None: sql.execute( "UPDATE settings\ SET geolocation=?\ WHERE uri=?", (b, parsed.netloc)) else: sql.execute( "INSERT INTO settings\ (uri, geolocation)\ VALUES (?, ?)", (b, parsed.netloc)) except Exception as e: Logger.error("DatabaseSettings::allow_geolocation(): %s", e)
def set_zoom(self, zoom, uri): """ Set zoom for uri @param zoom as int @param uri as str """ parsed = urlparse(uri) if parsed.scheme not in ["http", "https"]: return try: with SqlCursor(self) as sql: result = sql.execute( "SELECT rowid FROM settings\ WHERE uri=?", (parsed.netloc, )) v = result.fetchone() if v is not None: sql.execute( "UPDATE settings\ SET zoom=?\ WHERE uri=?", (zoom, parsed.netloc)) else: sql.execute( "INSERT INTO settings\ (uri, zoom)\ VALUES (?, ?)", (parsed.netloc, zoom)) except Exception as e: Logger.error("DatabaseSettings::set_zoom(): %s", e)
def __save_abp_rules(self, rules): """ Save rules to db @param rules as bytes """ SqlCursor.add(self) result = rules.decode("utf-8") count = 0 for line in result.split('\n'): SqlCursor.allow_thread_execution(self) if self.__cancellable.is_cancelled(): SqlCursor.remove(self) raise Exception("Cancelled") if "-abp-" in line or "$" in line or "!" in line or "[" in line: continue elif line.startswith("##"): self.__save_css_default_rule(line) elif "#@#" in line: self.__save_css_exception(line) elif "##" in line: self.__save_css_domain_rule(line) elif line.startswith("@@"): self.__save_abp_rule(line[2:], True) else: self.__save_abp_rule(line, False) Logger.debug("Add abp filter: %s", line) count += 1 if count == 1000: SqlCursor.commit(self) # Do not flood sqlite, this allow webkit extension to run sleep(0.1) count = 0 SqlCursor.remove(self)
def __on_save_rules(self, result, uris=[]): """ Load next uri, if finished, load CSS rules @param result (unused) @param uris as [str] """ if self.__cancellable.is_cancelled(): return if uris: uri = uris.pop(0) self.__task_helper.load_uri_content(uri, self.__cancellable, self.__on_load_uri_content, uris) else: with SqlCursor(self) as sql: sql.execute("DELETE FROM adblock\ WHERE mtime!=?", (self.__adblock_mtime,)) sql.execute("DELETE FROM adblock_re\ WHERE mtime!=?", (self.__adblock_mtime,)) sql.execute("DELETE FROM adblock_re_domain\ WHERE mtime!=?", (self.__adblock_mtime,)) sql.execute("DELETE FROM adblock_re_domain_ex\ WHERE mtime!=?", (self.__adblock_mtime,)) sql.execute("DELETE FROM adblock_css\ WHERE mtime!=?", (self.__adblock_mtime,)) sql.execute("DELETE FROM adblock_cache") try: dump(self.__adblock_mtime, open(EOLIE_DATA_PATH + "/adblock.bin", "wb")) except Exception as e: Logger.error("DatabaseAdblock::__on_save_rules(): %s", e)
def __rule_to_regex(self, rule): """ Convert rule to regex @param rule as str @return regex as str """ try: # Do nothing if rule is already a regex if rule[0] == rule[-1] == "/": return rule[1:-1] rule = re.sub(self.__SPECIAL_CHARS, r"\\\1", rule) # Handle ^ separator character, *, etc... for key in self.__REPLACE_CHARS.keys(): rule = rule.replace(key, self.__REPLACE_CHARS[key]) # End of the address if rule[-1] == "|": rule = rule[:-1] + "$" # Start of the address if rule[0] == "|": rule = "^" + rule[1:] # Escape remaining | but not |$ => see self.__REPLACE_CHARS rule = re.sub("(\|)[^$]", r"\|", rule) return rule except Exception as e: Logger.error("DatabaseAdblock::__rule_to_regex(): %s", e) return None
def __save_rules(self, rules): """ Save rules to db @param rules bytes """ SqlCursor.add(self) result = rules.decode('utf-8') count = 0 for line in result.split('\n'): SqlCursor.allow_thread_execution(self) if self.__cancellable.is_cancelled(): SqlCursor.remove(self) raise Exception("Cancelled") if line.startswith('#'): continue array = line.replace( ' ', '\t', 1).replace('\t', '@', 1).split('@') if len(array) <= 1: continue netloc = array[1].replace( ' ', '').replace('\r', '').split('#')[0] # Update entry if exists, create else if netloc != "localhost": Logger.debug("Add filter: %s", netloc) self.__add_netloc(netloc) count += 1 if count == 1000: SqlCursor.commit(self) # Do not flood sqlite, this allow webkit extension to run sleep(0.1) count = 0 SqlCursor.remove(self)
def __vacuum(self): """ VACUUM DB @thread safe """ try: with SqlCursor(self.bookmarks) as sql: sql.isolation_level = None sql.execute("VACUUM") sql.isolation_level = "" with SqlCursor(self.history) as sql: sql.isolation_level = None sql.execute("VACUUM") sql.isolation_level = "" with SqlCursor(self.adblock) as sql: sql.isolation_level = None sql.execute("VACUUM") sql.isolation_level = "" with SqlCursor(self.phishing) as sql: sql.isolation_level = None sql.execute("VACUUM") sql.isolation_level = "" except Exception as e: Logger.error("Application::__vacuum(): %s ", e) self.art.vacuum()
def set_profiles(self): """ Set profiles """ try: f = Gio.File.new_for_path(EOLIE_DATA_PATH + "/profiles.json") if f.query_exists(): (status, contents, tag) = f.load_contents(None) self.__profiles = json.loads(contents.decode("utf-8")) else: PROFILES = { "default": _("Default"), "social": _("Social networks"), "work": _("Work"), "shopping": _("Shopping"), "personal": _("Personal"), "finance": _("Finance"), "sport": _("Sport") } content = json.dumps(PROFILES) f.replace_contents(content.encode("utf-8"), None, False, Gio.FileCreateFlags.REPLACE_DESTINATION, None) self.__profiles = PROFILES except Exception as e: Logger.error("Application::set_profiles(): %s", e)
def connect(self, bid_assertion, key): """ Connect to sync using FxA browserid assertion @param session as fxaSession @return bundle keys as KeyBundle """ state = None if key is not None: from binascii import hexlify state = hexlify(sha256(key).digest()[0:16]) self.__client = SyncClient(bid_assertion, state) sync_keys = KeyBundle.fromMasterKey( key, "identity.mozilla.com/picl/v1/oldsync") # Fetch the sync bundle keys out of storage. # They're encrypted with the account-level key. keys = self.__decrypt_payload( self.__client.get_record("crypto", "keys"), sync_keys) # There's some provision for using separate # key bundles for separate collections # but I haven't bothered digging through # to see what that's about because # it doesn't seem to be in use, at least on my account. if keys["collections"]: Logger.error("""no support for per-collection key bundles yet sorry :-(""") return None # Now use those keys to decrypt the records of interest. from base64 import b64decode bulk_keys = KeyBundle(b64decode(keys["default"][0]), b64decode(keys["default"][1])) return bulk_keys
def _on_default_zoom_changed(self, button): """ Save size @param button as Gtk.SpinButton """ button.set_text("{} %".format(int(button.get_value()))) monitor_model = get_current_monitor_model( self.__settings_dialog.get_transient_for()) try: # Add current value less monitor model zoom_levels = [] for zoom_level in App().settings.get_value("default-zoom-level"): zoom_splited = zoom_level.split('@') if zoom_splited[0] == monitor_model: continue else: zoom_levels.append("%s@%s" % (zoom_splited[0], zoom_splited[1])) # Add new zoom value for monitor model zoom_levels.append("%s@%s" % (monitor_model, button.get_value() / 100)) App().settings.set_value("default-zoom-level", GLib.Variant("as", zoom_levels)) for window in App().windows: window.update_zoom_level(True) except Exception as e: Logger.error("SettingsDialog::_on_default_zoom_changed(): %s", e)
def __init__(self, window): """ Init widget @param window as Gtk.Window """ self.__window = window builder = Gtk.Builder() builder.add_from_resource("/org/gnome/Eolie/DialogImportBookmarks.ui") builder.connect_signals(self) self.__dialog = builder.get_object("dialog") self.__dialog.set_transient_for(window) self.__listbox = builder.get_object("listbox") items = ["Firefox", "Chromium", "Chrome"] try: from bs4 import BeautifulSoup BeautifulSoup items.append(_("Others")) except Exception as e: Logger.error("ImportBookmarksDialog::__init__(): %s", e) for item in items: label = Gtk.Label.new(item) label.show() self.__listbox.add(label) headerbar = builder.get_object("headerbar") self.__dialog.set_titlebar(headerbar)
def __connect_firefox_sync(self, username, password): """ Connect to firefox sync @param username as str @param password as str @thread safe """ try: App().sync_worker.new_session() App().sync_worker.login({"login": username}, password) GLib.idle_add(self.__setup_sync_button, True) except Exception as e: Logger.error("SettingsDialog::__connect_firefox_sync(): %s", e) GLib.idle_add(self.__sync_button.set_sensitive, True) if str(e) == "Unverified account": GLib.timeout_add(500, self.__settings_dialog.destroy) self.__window.toolbar.end.show_sync_button() GLib.idle_add( App().active_window.toolbar.title.show_message, _("You've received an email" " to validate syncing")) else: GLib.idle_add(self.__result_label.set_text, str(e)) GLib.idle_add(self.__result_image.set_from_icon_name, "computer-fail-symbolic", Gtk.IconSize.MENU)
def __on_snapshot(self, webview, result, first_pass): """ Set snapshot on main image @param webview as WebView @param result as Gio.AsyncResult @param first_pass as bool """ try: snapshot = webview.get_snapshot_finish(result) pixbuf = Gdk.pixbuf_get_from_surface(snapshot, 0, 0, snapshot.get_width(), snapshot.get_height()) pixbuf.savev("/tmp/eolie_snapshot.png", "png", [None], [None]) Gtk.show_uri_on_window(self._window, "file:///tmp/eolie_snapshot.png", Gtk.get_current_event_time()) except Exception as e: Logger.error("WebView::__on_snapshot(): %s", e) # The 32767 limit on the width/height dimensions # of an image surface is new in cairo 1.10, # try with WebKit2.SnapshotRegion.VISIBLE if first_pass: self.get_snapshot(WebKit2.SnapshotRegion.VISIBLE, WebKit2.SnapshotOptions.NONE, None, self.__on_snapshot, False)
def set_accept_tls(self, uri, accept): """ Accept TLS for uri @param uri as str @param accept as bool """ parsed = urlparse(uri) if parsed.scheme != "https": return try: with SqlCursor(self) as sql: result = sql.execute( "SELECT rowid FROM settings\ WHERE uri=?", (parsed.netloc, )) v = result.fetchone() if v is not None: sql.execute( "UPDATE settings\ SET accept_tls=?\ WHERE uri=?", (accept, parsed.netloc)) else: sql.execute( "INSERT INTO settings\ (uri, accept_tls)\ VALUES (?, ?)", (parsed.netloc, accept)) except Exception as e: Logger.error("DatabaseSettings::set_accept_tls(): %s", e)
def __move_images(self): """ Move image to download directory """ parsed = urlparse(self.__uri) directory_uri = App().settings.get_value('download-uri').get_string() if not directory_uri: directory = GLib.get_user_special_dir( GLib.UserDirectory.DIRECTORY_DOWNLOAD) directory_uri = GLib.filename_to_uri(directory, None) destination_uri = "%s/%s" % (directory_uri, parsed.netloc) directory = Gio.File.new_for_uri(destination_uri) if not directory.query_exists(): directory.make_directory_with_parents() for child in self.__flowbox.get_children(): if child.uri.find(self.__filter) != -1: encoded = sha256(child.uri.encode("utf-8")).hexdigest() child_basename = child.uri.split("/")[-1] filepath = "%s/%s" % (EOLIE_CACHE_PATH, encoded) s = Gio.File.new_for_path(filepath) if not s.query_exists(): continue d = Gio.File.new_for_uri("%s/%s" % (destination_uri, child_basename)) try: s.move(d, Gio.FileCopyFlags.OVERWRITE, None, None, None) except Exception as e: Logger.error("ImagesPopover::__move_images(): %s", e) GLib.idle_add(self.hide)
def set_profile(self, profile, uri): """ Set profile for uri @param user_agent as str @param uri as str """ parsed = urlparse(uri) if parsed.scheme not in ["http", "https"]: return try: with SqlCursor(self) as sql: result = sql.execute( "SELECT rowid FROM settings\ WHERE uri=?", (parsed.netloc, )) v = result.fetchone() if v is not None: sql.execute( "UPDATE settings\ SET profile=?\ WHERE uri=?", (profile, parsed.netloc)) else: sql.execute( "INSERT INTO settings\ (uri, profile)\ VALUES (?, ?)", (parsed.netloc, profile)) except Exception as e: Logger.error("DatabaseSettings::set_profile(): %s", e)
def __on_send_request(self, webpage, request, redirect): """ Filter based on adblock db @param webpage as WebKit2WebExtension.WebPage @param request as WebKit2.URIRequest @param redirect as WebKit2WebExtension.URIResponse """ uri = webpage.get_uri() parsed = urlparse(uri) request_uri = request.get_uri() parsed_request = urlparse(request_uri) netloc = parsed.netloc.split(".")[-2:] netloc_request = parsed_request.netloc.split(".")[-2:] document = webpage.get_dom_document() if self.__document != document: self.__document = document self.__scripts = \ document.get_elements_by_tag_name_as_html_collection("script") if netloc == netloc_request and\ App().settings.get_value("trust-websites-js"): return False if App().settings.get_value("jsblock") and\ parsed.netloc not in self.__whitelist: if parsed_request.scheme in ["http", "https"] and\ not App().js_exceptions.find(parsed_request.netloc, parsed.netloc): for i in range(0, self.__scripts.get_length()): script = self.__scripts.item(i) if script.get_src() == request_uri: Logger.debug("JSblockExtension: blocking %s -> %s", request_uri, uri) return True
def __init__(self): """ Create database tables or manage update if needed @param suffix as str """ self.thread_lock = Lock() new_version = len(self.__UPGRADES) self.__DB_PATH = "%s/settings2.db" % EOLIE_DATA_PATH if not GLib.file_test(self.__DB_PATH, GLib.FileTest.IS_REGULAR): try: if not GLib.file_test(EOLIE_DATA_PATH, GLib.FileTest.IS_DIR): GLib.mkdir_with_parents(EOLIE_DATA_PATH, 0o0750) # Create db schema with SqlCursor(self) as sql: sql.execute(self.__create_settings) sql.execute("PRAGMA user_version=%s" % new_version) except Exception as e: Logger.error("DatabaseSettings::__init__(): %s", e) # DB upgrade, TODO Make it generic between class version = 0 with SqlCursor(self) as sql: result = sql.execute("PRAGMA user_version") v = result.fetchone() if v is not None: version = v[0] if version < new_version: for i in range(version + 1, new_version + 1): try: sql.execute(self.__UPGRADES[i]) except: Logger.error("Settings DB upgrade %s failed", i) sql.execute("PRAGMA user_version=%s" % new_version)
def new_page(self, uri, loading_type): """ Open a new page @param uri as uri @param loading_type as Gdk.LoadingType """ parsed = urlparse(uri) if App().settings.get_value("adblock") and\ parsed.scheme in ["http", "https"] and\ not App().adblock_exceptions.find_parsed(parsed): if App().adblock.is_netloc_blocked(parsed.netloc) or\ App().adblock.is_uri_blocked(uri, parsed.netloc): Logger.debug("WebView::new_page(): blocking %s ->%s", uri, self.uri) return True if loading_type == LoadingType.POPOVER: if self.ephemeral: webview = WebView.new_ephemeral(self._window, None) else: webview = WebView.new(self._window, None) self._window.container.popup_webview(webview, True) GLib.idle_add(webview.load_uri, uri) else: self.__new_pages_opened += 1 webview = self._window.container.add_webview( uri, loading_type, self.ephemeral, None, self.atime - self.__new_pages_opened) webview.set_parent(self) self.add_child(webview)
def _on_dialog_response(self, dialog, response_id): """ Save user agent @param dialog as Gtk.Dialog @param response_id as int """ try: profiles = {} for child in self.__profiles.get_children(): profile = child.item.get_property("profile") name = child.item.get_property("name") profiles[profile] = name content = json.dumps(profiles) f = Gio.File.new_for_path(EOLIE_DATA_PATH + "/profiles.json") f.replace_contents(content.encode("utf-8"), None, False, Gio.FileCreateFlags.REPLACE_DESTINATION, None) if response_id != Gtk.ResponseType.DELETE_EVENT: rows = self.__cookies.get_selected_rows() row = self.__profiles.get_selected_row() path = COOKIES_PATH % (EOLIE_DATA_PATH, row.item.get_property("profile")) request = "DELETE FROM moz_cookies WHERE " filters = () for row in rows: request += "host=? OR " filters += (row.item.name, ) request += " 0" sql = sqlite3.connect(path, 600.0) sql.execute(request, filters) sql.commit() except Exception as e: Logger.error("CookiesDialog::_on_dialog_response(): %s", e) App().set_profiles()
def __on_send_request(self, webpage, request, redirect): """ Filter based on adblock db @param webpage as WebKit2WebExtension.WebPage @param request as WebKit2.URIRequest @param redirect as WebKit2WebExtension.URIResponse """ uri = webpage.get_uri() parsed = urlparse(uri) request_uri = request.get_uri() parsed_request = urlparse(request_uri) netloc = parsed.netloc.split(".")[-2:] netloc_request = parsed_request.netloc.split(".")[-2:] if netloc == netloc_request and\ App().settings.get_value("trust-websites-adblock"): pass elif App().settings.get_value("adblock") and\ parsed_request.scheme in ["http", "https"] and\ not App().adblock_exceptions.find_parsed(parsed_request): if App().adblock.is_netloc_blocked(parsed_request.netloc) or\ App().adblock.is_uri_blocked(request_uri, parsed_request.netloc): Logger.debug("AdblockExtension: blocking %s ->%s", request_uri, uri) return True if App().settings.get_value("do-not-track"): headers = request.get_http_headers() if headers is not None: headers.append("DNT", "1")
def get(self, form_uri, userform, passform, callback, *args): """ Call function @param form_uri as str @param userform as str @param passform as str @param callback as function @param args """ try: self.__wait_for_secret(self.get, form_uri, userform, passform, callback, *args) SecretSchema = { "type": Secret.SchemaAttributeType.STRING, "formSubmitURL": Secret.SchemaAttributeType.STRING, "userform": Secret.SchemaAttributeType.STRING, } SecretAttributes = { "type": "eolie web login", "formSubmitURL": form_uri, "userform": userform, } if passform is not None: SecretSchema["passform"] = Secret.SchemaAttributeType.STRING SecretAttributes["passform"] = passform schema = Secret.Schema.new("org.gnome.Eolie", Secret.SchemaFlags.NONE, SecretSchema) self.__secret.search(schema, SecretAttributes, Secret.SearchFlags.ALL, None, self.__on_secret_search, form_uri, callback, *args) except Exception as e: Logger.debug("PasswordsHelper::get(): %s", e)
def get_snapshot(webview, result, callback, *args): """ Set snapshot on main image @param webview as WebKit2.WebView @param result as Gio.AsyncResult @return cairo.Surface """ ART_RATIO = 1.5 # ArtSize.START_WIDTH / ArtSize.START_HEIGHT try: snapshot = webview.get_snapshot_finish(result) # Set start image scale factor ratio = snapshot.get_width() / snapshot.get_height() if ratio > ART_RATIO: factor = ArtSize.START_HEIGHT / snapshot.get_height() else: factor = ArtSize.START_WIDTH / snapshot.get_width() surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, ArtSize.START_WIDTH, ArtSize.START_HEIGHT) context = cairo.Context(surface) context.scale(factor, factor) context.set_source_surface(snapshot, factor, 0) context.paint() callback(surface, *args) except Exception as e: Logger.error("get_snapshot(): %s", e) callback(None, *args)
def __sort_func(self, row1, row2): """ Sort listbox @param row1 as Row @param row2 as Row """ try: # Group pages by net location then atime if self.__sort_pages and row2.view.webview.uri is not None and\ row1.view.webview.uri is not None: netloc1 = get_safe_netloc(row1.view.webview.uri) netloc2 = get_safe_netloc(row2.view.webview.uri) if netloc1 != netloc2 and netloc1 in self.__sort_pages and\ netloc2 in self.__sort_pages: index1 = self.__sort_pages.index(netloc1) index2 = self.__sort_pages.index(netloc2) return index2 < index1 else: return row2.view.webview.atime > row1.view.webview.atime # Always show current first elif self.__current_child is not None and\ self.__current_child in [row1, row2]: return self.__current_child == row2 # Unshown first elif not row2.view.webview.shown and row1.view.webview.shown: return True else: return row2.view.webview.atime > row1.view.webview.atime except Exception as e: Logger.error("PagesManager::__sort_func(): %s", e)
def __push_password(self, user_form_name, user_form_value, pass_form_name, pass_form_value, uri, form_uri, uuid): """ Push password @param user_form_name as str @param user_form_value as str @param pass_form_name as str @param pass_form_value as str @param uri as str @param uuid as str """ try: record = {} record["id"] = "{%s}" % uuid record["hostname"] = uri record["formSubmitURL"] = form_uri record["httpRealm"] = None record["username"] = user_form_value record["password"] = pass_form_value record["usernameField"] = user_form_name record["passwordField"] = pass_form_name mtime = int(time() * 1000) record["timeCreated"] = mtime record["timePasswordChanged"] = mtime self.__pending_records["passwords"].append(record) self.__sync_pendings() except Exception as e: Logger.error("SyncWorker::__push_password(): %s", e)