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

Reply via email to