Package: mutagen Version: 1.8-1.1 Severity: normal Tags: patch Hi,
Attached is the diff for my mutagen 1.8-1.2 NMU.
diff -u mutagen-1.8/mutagen/id3.py mutagen-1.8/mutagen/id3.py --- mutagen-1.8/mutagen/id3.py +++ mutagen-1.8/mutagen/id3.py @@ -291,10 +291,6 @@ except ID3JunkFrameError: pass def __load_framedata(self, tag, flags, framedata): - if self.f_unsynch or flags & 0x40: - try: framedata = unsynch.decode(framedata) - except ValueError: pass - flags &= ~0x40 return tag.fromData(self, flags, framedata) f_unsynch = property(lambda s: bool(s.__flags & 0x80)) @@ -974,7 +970,7 @@ # all we need are the raw bytes. datalen_bytes = data[:4] data = data[4:] - if tflags & Frame.FLAG24_UNSYNCH and not id3.f_unsynch: + if tflags & Frame.FLAG24_UNSYNCH or id3.f_unsynch: try: data = unsynch.decode(data) except ValueError, err: if id3.PEDANTIC: diff -u mutagen-1.8/tests/test_id3.py mutagen-1.8/tests/test_id3.py --- mutagen-1.8/tests/test_id3.py +++ mutagen-1.8/tests/test_id3.py @@ -140,7 +140,7 @@ id3._ID3__load_framedata(Frames["TPE2"], 0, badsync), [u"\xffab"]) id3._ID3__flags = 0x00 self.assertEquals(id3._ID3__load_framedata( - Frames["TPE2"],0x40, badsync), [u"\xffab"]) + Frames["TPE2"], 0x02, badsync), [u"\xffab"]) tag = id3._ID3__load_framedata(Frames["TPE2"], 0, badsync) self.assertEquals(tag, [u"\xff", u"ab"]) diff -u mutagen-1.8/debian/changelog mutagen-1.8/debian/changelog --- mutagen-1.8/debian/changelog +++ mutagen-1.8/debian/changelog @@ -1,3 +1,13 @@ +mutagen (1.8-1.2) unstable; urgency=high + + * Non-maintainer upload. + * Apply patch from upstream Subversion repository (r3965), which complements + the ID3 fix from -1.1 and thus really Closes: #403542. + * Fix APEv2 writing, applying patch from upstream Subversion (r3989, r3991), + making sure no invalid tags are written. (Closes: #411433) + + -- Steinar H. Gunderson <[EMAIL PROTECTED]> Wed, 28 Feb 2007 17:42:43 +0100 + mutagen (1.8-1.1) unstable; urgency=medium * NMU to fix RC bug; urgency medium only in patch2: unchanged: --- mutagen-1.8.orig/tests/test_apev2.py +++ mutagen-1.8/tests/test_apev2.py @@ -10,7 +10,7 @@ import mutagen.apev2 -from mutagen.apev2 import APEv2File, APEv2 +from mutagen.apev2 import APEv2File, APEv2, is_valid_apev2_key DIR = os.path.dirname(__file__) SAMPLE = os.path.join(DIR, "data", "click.mpc") @@ -18,6 +18,17 @@ BROKEN = os.path.join(DIR, "data", "brokentag.apev2") LYRICS2 = os.path.join(DIR, "data", "apev2-lyricsv2.mp3") +class Tis_valid_apev2_key(TestCase): + uses_mmap = False + def test_yes(self): + for key in ["foo", "Foo", " f ~~~"]: + self.failUnless(is_valid_apev2_key(key)) + + def test_no(self): + for key in ["\x11hi", "ffoo\xFF", u"\u1234", "a", "", "foo" * 100]: + self.failIf(is_valid_apev2_key(key)) +add(Tis_valid_apev2_key) + class TAPEWriter(TestCase): offset = 0 @@ -146,6 +157,10 @@ shutil.copy(OLD, self.filename) self.audio = APEv2(self.filename) + def test_invalid_key(self): + self.failUnlessRaises( + KeyError, self.audio.__setitem__, u"\u1234", "foo") + def test_guess_text(self): from mutagen.apev2 import APETextValue self.audio["test"] = u"foobar" only in patch2: unchanged: --- mutagen-1.8.orig/mutagen/apev2.py +++ mutagen-1.8/mutagen/apev2.py @@ -16,9 +16,11 @@ decoders and taggers. APEv2 tags, like Vorbis comments, are freeform key=value pairs. APEv2 -keys can be any UTF-8 string, but restricting keys to ASCII is -strongly recommended. Keys are case-insensitive, but usually stored -title-cased (e.g. 'Artist' rather than 'artist'). +keys can be any ASCII string with characters from 0x20 to 0x7E, +between 2 and 255 characters long. Keys are case-sensitive, but +readers are recommended to be case insensitive, and it is forbidden to +multiple keys which differ only in case. Keys are usually stored +title-cased (e.g. 'Artist' rather than 'artist'). APEv2 values are slightly more structured than Vorbis comments; values are flagged as one of text, binary, or an external reference (usually @@ -33,6 +35,10 @@ import struct from cStringIO import StringIO +def is_valid_apev2_key(key): + return (2 <= len(key) <= 255 and min(key) >= ' ' and max(key) <= '~' and + key not in ["OggS", "TAG", "ID3", "MP+"]) + # There are three different kinds of APE tag values. # "0: Item contains text information coded in UTF-8 # 1: Item contains binary information @@ -41,7 +47,7 @@ TEXT, BINARY, EXTERNAL = range(3) HAS_HEADER = 1L << 31 -HAS_FOOTER = 1L << 30 +HAS_NO_FOOTER = 1L << 30 IS_HEADER = 1L << 29 class error(IOError): pass @@ -233,9 +239,15 @@ self[key] = APEValue(value, kind) def __getitem__(self, key): + if not is_valid_apev2_key(key): + raise KeyError("%r is not a valid APEv2 key" % key) return super(APEv2, self).__getitem__(key.lower()) + def __delitem__(self, key): + if not is_valid_apev2_key(key): + raise KeyError("%r is not a valid APEv2 key" % key) return super(APEv2, self).__delitem__(key.lower()) + def __setitem__(self, key, value): """'Magic' value setter. @@ -310,7 +322,7 @@ header = "APETAGEX%s%s" %( # version, tag size, item count, flags struct.pack("<4I", 2000, len(tags) + 32, num_tags, - HAS_HEADER | HAS_FOOTER | IS_HEADER), + HAS_HEADER | IS_HEADER), "\0" * 8) fileobj.write(header) @@ -319,7 +331,7 @@ footer = "APETAGEX%s%s" %( # version, tag size, item count, flags struct.pack("<4I", 2000, len(tags) + 32, num_tags, - HAS_HEADER | HAS_FOOTER), + HAS_HEADER), "\0" * 8) fileobj.write(footer) fileobj.close()