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()