]> granicus.if.org Git - taglib/commitdiff
Support broken Latin-1 encodings in ID3V2
authortsuda.kageyu@gmail.com <Tsuda Kageyu>
Thu, 23 Aug 2012 02:40:32 +0000 (11:40 +0900)
committertsuda.kageyu@gmail.com <Tsuda Kageyu>
Thu, 23 Aug 2012 03:19:51 +0000 (12:19 +0900)
taglib/mpeg/id3v2/frames/commentsframe.cpp
taglib/mpeg/id3v2/frames/textidentificationframe.cpp
taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp
taglib/mpeg/id3v2/id3v2frame.cpp
taglib/mpeg/id3v2/id3v2tag.cpp
taglib/mpeg/id3v2/id3v2tag.h

index 2c6c49f9cada6de2a79733c0c244aa77e6e89f9f..ec70e89167146b890db7bab1c98e3bea7820f41d 100644 (file)
@@ -158,8 +158,13 @@ void CommentsFrame::parseFields(const ByteVector &data)
   ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2);
 
   if(l.size() == 2) {
-    d->description = String(l.front(), d->textEncoding);
-    d->text = String(l.back(), d->textEncoding);
+    if(d->textEncoding == String::Latin1) {
+      d->description = Tag::latin1StringHandler()->parse(l.front());
+      d->text = Tag::latin1StringHandler()->parse(l.back());
+    } else {
+      d->description = String(l.front(), d->textEncoding);
+      d->text = String(l.back(), d->textEncoding);
+    }  
   }
 }
 
index b6a02b06818610ed5dcf704ee061bf6b9ded18d3..d9f696b7756715c0d06e90ec4e4505dcbc0ecf67 100644 (file)
@@ -213,8 +213,10 @@ void TextIdentificationFrame::parseFields(const ByteVector &data)
 
   for(ByteVectorList::Iterator it = l.begin(); it != l.end(); it++) {
     if(!(*it).isEmpty()) {
-      String s(*it, d->textEncoding);
-      d->fieldList.append(s);
+      if(d->textEncoding == String::Latin1)
+        d->fieldList.append(Tag::latin1StringHandler()->parse(*it));
+      else
+        d->fieldList.append(String(*it, d->textEncoding));    
     }
   }
 }
index 9d76164da9c5eb0ed04f4ef72385b4e4b13e999c..0b14091272d980fa95b36e53e0bf3d09969b4e03 100644 (file)
@@ -158,8 +158,13 @@ void UnsynchronizedLyricsFrame::parseFields(const ByteVector &data)
     ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2);
 
   if(l.size() == 2) {
-    d->description = String(l.front(), d->textEncoding);
-    d->text = String(l.back(), d->textEncoding);
+    if(d->textEncoding == String::Latin1) {
+      d->description = Tag::latin1StringHandler()->parse(l.front());
+      d->text = Tag::latin1StringHandler()->parse(l.back());
+    } else {
+      d->description = String(l.front(), d->textEncoding);
+      d->text = String(l.back(), d->textEncoding);
+    }  
   }
 }
 
index 9c9c640c6afcb2a6d292f97c3f8754a0dbcb67e1..e15adc8c03d6365ea9b88a83271b0fc0d561a88b 100644 (file)
@@ -36,6 +36,7 @@
 #include <tdebug.h>
 #include <tstringlist.h>
 
+#include "id3v2tag.h"
 #include "id3v2frame.h"
 #include "id3v2synchdata.h"
 #include "tpropertymap.h"
@@ -273,7 +274,11 @@ String Frame::readStringField(const ByteVector &data, String::Type encoding, int
   if(end < *position)
     return String::null;
 
-  String str = String(data.mid(*position, end - *position), encoding);
+  String str;
+  if(encoding == String::Latin1)
+    str = Tag::latin1StringHandler()->parse(data.mid(*position, end - *position));
+  else
+    str = String(data.mid(*position, end - *position), encoding);
 
   *position = end + delimiter.size();
 
index 662fd1593a5093086b3e2725bb154ba1485610fe..8b623f826703d23b00c07984206dcb416f93981d 100644 (file)
@@ -70,8 +70,26 @@ public:
 
   FrameListMap frameListMap;
   FrameList frameList;
+
+  static const Latin1StringHandler *stringHandler;
 };
 
+static const Latin1StringHandler defaultStringHandler;
+const ID3v2::Latin1StringHandler *ID3v2::Tag::TagPrivate::stringHandler = &defaultStringHandler;
+
+////////////////////////////////////////////////////////////////////////////////
+// StringHandler implementation
+////////////////////////////////////////////////////////////////////////////////
+
+Latin1StringHandler::~Latin1StringHandler()
+{
+}
+
+String Latin1StringHandler::parse(const ByteVector &data) const
+{
+  return String(data, String::Latin1);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // public members
 ////////////////////////////////////////////////////////////////////////////////
@@ -584,6 +602,19 @@ ByteVector ID3v2::Tag::render(int version) const
   return d->header.render() + tagData;
 }
 
+Latin1StringHandler const *ID3v2::Tag::latin1StringHandler()
+{
+  return TagPrivate::stringHandler;
+}
+
+void ID3v2::Tag::setLatin1StringHandler(const Latin1StringHandler *handler)
+{
+  if(handler)
+    TagPrivate::stringHandler = handler;
+  else
+    TagPrivate::stringHandler = &defaultStringHandler;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // protected members
 ////////////////////////////////////////////////////////////////////////////////
index 94784e7614e4c63e34f5a60029489776bf931fd5..58bc5b5a383c1bcacdcade4fe84786112dfecd12 100644 (file)
@@ -57,6 +57,35 @@ namespace TagLib {
     typedef List<Frame *> FrameList;
     typedef Map<ByteVector, FrameList> FrameListMap;
 
+    //! An abstraction for the ISO-8859-1 string to data encoding in ID3v2 tags.
+
+    /*!
+     * ID3v2 tag can store strings in ISO-8859-1 (Latin1), and TagLib only 
+     * supports genuine ISO-8859-1 by default.  However, in practice, non 
+     * ISO-8859-1 encodings are often used instead of ISO-8859-1, such as 
+     * Windows-1252 for western languages, Shift_JIS for Japanese and so on.
+     *
+     * Here is an option to read such tags by subclassing this class,
+     * reimplementing parse() and setting your reimplementation as the default 
+     * with ID3v2::Tag::setStringHandler().
+     *
+     * \note Writing non-ISO-8859-1 tags is not implemented intentionally.
+     * Use UTF-16 or UTF-8 instead.
+     *
+     * \see ID3v2::Tag::setStringHandler()
+     */
+    class TAGLIB_EXPORT Latin1StringHandler
+    {
+    public:
+      virtual ~Latin1StringHandler();
+
+      /*!
+       * Decode a string from \a data.  The default implementation assumes that
+       * \a data is an ISO-8859-1 (Latin1) character array.
+       */
+      virtual String parse(const ByteVector &data) const;
+    };
+
     //! The main class in the ID3v2 implementation
 
     /*!
@@ -323,6 +352,25 @@ namespace TagLib {
        */
       // BIC: combine with the above method
       ByteVector render(int version) const;
+      
+      /*!
+       * Gets the current string handler that decides how the "Latin-1" data 
+       * will be converted to and from binary data.
+       *
+       * \see Latin1StringHandler
+       */
+      static Latin1StringHandler const *latin1StringHandler();
+
+      /*!
+       * Sets the string handler that decides how the "Latin-1" data will be
+       * converted to and from binary data.
+       *
+       * If the parameter \a handler is null, default ISO-8859-1 handler
+       * is restored.
+       * 
+       * \see Latin1StringHandler
+       */
+      static void setLatin1StringHandler(const Latin1StringHandler *handler);
 
     protected:
       /*!