diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 71784a80..925bdc81 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -16,6 +16,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . +Changes in v2023.5.1: + 1/ Tab labels use two lines instead of eliding to fit width. + 2/ Ignore NULL bytes in some phone images' Exif comment values. + 3/ Italian localisation is complete. + 4/ Other minor improvements and bug fixes. + Changes in v2023.5.0: 1/ Latitude & longitude values no longer have comma separator. 2/ All numeric values are localised, e.g. to use decimal comma. diff --git a/src/photini/__init__.py b/src/photini/__init__.py index 12494106..f8717376 100644 --- a/src/photini/__init__.py +++ b/src/photini/__init__.py @@ -1,4 +1,4 @@ """Full documentation is at https://photini.readthedocs.io/""" __version__ = '2023.5.1' -build = '2719 (e80171b)' +build = '2722 (64e9222)' diff --git a/src/photini/exiv2.py b/src/photini/exiv2.py index 4efd7cc7..7c04bd12 100644 --- a/src/photini/exiv2.py +++ b/src/photini/exiv2.py @@ -335,25 +335,33 @@ def get_exif_comment(self, tag, datum): if charset != exiv2.CharsetId.undefined: logger.warning('%s: %s: unknown charset', self._name, tag) raw_value = data + result = None for encoding in encodings: result = self.decode_string(tag, raw_value, encoding) if result: - return result - detector = chardet.universaldetector.UniversalDetector() - for i in range(0, len(raw_value), 100): - detector.feed(raw_value[i:i+100]) - if detector.done: break - detector.close() - encoding = detector.result['encoding'] - if encoding: - result = self.decode_string(tag, raw_value, encoding) - if result: - return result - logger.error( - '%s: %s: %d bytes binary data will be deleted when metadata' - ' is saved', self._name, tag, value.size()) - return None + else: + detector = chardet.universaldetector.UniversalDetector() + for i in range(0, len(raw_value), 100): + detector.feed(raw_value[i:i+100]) + if detector.done: + break + detector.close() + encoding = detector.result['encoding'] + if encoding: + result = self.decode_string(tag, raw_value, encoding) + if result and '\0' in result: + # terminating NULLs are allowed + result = result.strip('\0') + if '\0' in result: + # NULLs within the string are not allowed + result = None + if not result: + logger.error( + '%s: %s: %d bytes binary data will be deleted when metadata' + ' is saved', self._name, tag, value.size()) + return None + return result def get_exif_value(self, tag): datum = self._exifData.findKey(exiv2.ExifKey(tag)) diff --git a/src/photini/types.py b/src/photini/types.py index 7f3b1269..17f2615a 100644 --- a/src/photini/types.py +++ b/src/photini/types.py @@ -690,10 +690,10 @@ def get_type(cls, key, value): @classmethod def from_exiv2(cls, file_value, tag): + file_value = file_value or {} if isinstance(file_value, (list, tuple)): # "legacy" list of string values file_value = dict(zip(cls.legacy_keys, file_value)) - file_value = file_value or {} for key, value in file_value.items(): file_value[key] = cls.get_type(key, value).from_exiv2(value, tag) return cls(file_value)