diff --git a/deluge/common.py b/deluge/common.py index 1deffd0a9..eec129a1b 100644 --- a/deluge/common.py +++ b/deluge/common.py @@ -626,37 +626,55 @@ def xml_encode(string): def decode_string(s, encoding="utf8"): """ - Decodes a string and re-encodes it in utf8. If it cannot decode using - `:param:encoding` then it will try to detect the string encoding and - decode it. + Decodes a string and return unicode. If it cannot decode using + `:param:encoding` then it will try latin1, and if that fails, + try to detect the string encoding. If that fails, decode with + ignore. :param s: string to decode :type s: string :keyword encoding: the encoding to use in the decoding :type encoding: string + :returns: s converted to unicode + :rtype: unicode """ + if not s: + return u'' + elif isinstance(s, unicode): + return s - try: - s = s.decode(encoding).encode("utf8", "ignore") - except UnicodeDecodeError: - s = s.decode(chardet.detect(s)["encoding"], "ignore").encode("utf8", "ignore") - return s + encodings = [lambda: ("utf8", 'strict'), + lambda: ("iso-8859-1", 'strict'), + lambda: (chardet.detect(s)["encoding"], 'strict'), + lambda: (encoding, 'ignore')] -def utf8_encoded(s): + if not encoding is "utf8": + encodings.insert(0, lambda: (encoding, 'strict')) + + for l in encodings: + try: + return s.decode(*l()) + except UnicodeDecodeError: + pass + return u'' + +def utf8_encoded(s, encoding="utf8"): """ Returns a utf8 encoded string of s :param s: (unicode) string to (re-)encode :type s: basestring + :keyword encoding: the encoding to use in the decoding + :type encoding: string :returns: a utf8 encoded string of s :rtype: str """ if isinstance(s, str): - s = decode_string(s) + s = decode_string(s, encoding).encode("utf8") elif isinstance(s, unicode): - s = s.encode("utf8", "ignore") + s = s.encode("utf8") return s class VersionSplit(object): diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py index f193410c9..6b5093b19 100644 --- a/deluge/core/torrent.py +++ b/deluge/core/torrent.py @@ -389,7 +389,7 @@ class Torrent(object): # First we check for an error from libtorrent, and set the state to that # if any occurred. - status_error = self.handle.status().error + status_error = deluge.common.decode_string(self.handle.status().error) if status_error or self.error_statusmsg: # This is an error'd torrent self.state = "Error" diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py index d4a548a4f..9ecc4149a 100644 --- a/deluge/core/torrentmanager.py +++ b/deluge/core/torrentmanager.py @@ -55,7 +55,7 @@ from deluge.configmanager import ConfigManager, get_config_dir from deluge.core.torrent import Torrent from deluge.core.torrent import TorrentOptions import deluge.core.oldstateupgrader -from deluge.common import utf8_encoded +from deluge.common import utf8_encoded, decode_string from deluge.log import LOG as log @@ -972,7 +972,7 @@ class TorrentManager(component.Component): torrent.update_state() def on_alert_tracker_reply(self, alert): - log.debug("on_alert_tracker_reply: %s", alert.message().decode("utf8")) + log.debug("on_alert_tracker_reply: %s", decode_string(alert.message())) try: torrent = self.torrents[str(alert.handle.info_hash())] except: @@ -1004,7 +1004,7 @@ class TorrentManager(component.Component): torrent = self.torrents[str(alert.handle.info_hash())] except: return - tracker_status = '%s: %s' % (_("Warning"), str(alert.message())) + tracker_status = '%s: %s' % (_("Warning"), decode_string(alert.message())) # Set the tracker status for the torrent torrent.set_tracker_status(tracker_status) @@ -1034,7 +1034,7 @@ class TorrentManager(component.Component): def on_alert_storage_moved_failed(self, alert): """Alert handler for libtorrent storage_moved_failed_alert""" - log.debug("on_alert_storage_moved_failed: %s", alert.message()) + log.debug("on_alert_storage_moved_failed: %s", decode_string(alert.message())) try: torrent_id = str(alert.handle.info_hash()) torrent = self.torrents[torrent_id] @@ -1097,7 +1097,7 @@ class TorrentManager(component.Component): self.save_resume_data_file() def on_alert_save_resume_data_failed(self, alert): - log.debug("on_alert_save_resume_data_failed: %s", alert.message()) + log.debug("on_alert_save_resume_data_failed: %s", decode_string(alert.message())) try: torrent = self.torrents[str(alert.handle.info_hash())] except: @@ -1111,7 +1111,7 @@ class TorrentManager(component.Component): def on_alert_file_renamed(self, alert): log.debug("on_alert_file_renamed") - log.debug("index: %s name: %s", alert.index, alert.name.decode("utf8")) + log.debug("index: %s name: %s", alert.index, decode_string(alert.name)) try: torrent = self.torrents[str(alert.handle.info_hash())] torrent_id = str(alert.handle.info_hash()) @@ -1149,7 +1149,7 @@ class TorrentManager(component.Component): torrent.on_metadata_received() def on_alert_file_error(self, alert): - log.debug("on_alert_file_error: %s", alert.message()) + log.debug("on_alert_file_error: %s", decode_string(alert.message())) try: torrent = self.torrents[str(alert.handle.info_hash())] except: @@ -1157,7 +1157,7 @@ class TorrentManager(component.Component): torrent.update_state() def on_alert_file_completed(self, alert): - log.debug("file_completed_alert: %s", alert.message()) + log.debug("file_completed_alert: %s", decode_string(alert.message())) try: torrent_id = str(alert.handle.info_hash()) except: diff --git a/deluge/ui/common.py b/deluge/ui/common.py index 968bb68e9..e3fbb44b3 100644 --- a/deluge/ui/common.py +++ b/deluge/ui/common.py @@ -50,7 +50,7 @@ except ImportError: from sha import sha from deluge import bencode -from deluge.common import decode_string, path_join +from deluge.common import utf8_encoded, path_join from deluge.log import LOG as log import deluge.configmanager @@ -86,9 +86,9 @@ class TorrentInfo(object): # Check if 'name.utf-8' is in the torrent and if not try to decode the string # using the encoding found. if "name.utf-8" in self.__m_metadata["info"]: - self.__m_name = decode_string(self.__m_metadata["info"]["name.utf-8"]) + self.__m_name = utf8_encoded(self.__m_metadata["info"]["name.utf-8"]) else: - self.__m_name = decode_string(self.__m_metadata["info"]["name"], self.encoding) + self.__m_name = utf8_encoded(self.__m_metadata["info"]["name"], self.encoding) # Get list of files from torrent info paths = {} @@ -103,7 +103,7 @@ class TorrentInfo(object): path = os.path.join(prefix, *f["path.utf-8"]) del f["path.utf-8"] else: - path = decode_string(os.path.join(prefix, decode_string(os.path.join(*f["path"]), self.encoding)), self.encoding) + path = utf8_encoded(os.path.join(prefix, utf8_encoded(os.path.join(*f["path"]), self.encoding)), self.encoding) f["path"] = path f["index"] = index if "sha1" in f and len(f["sha1"]) == 20: