Use uchardet to guess encoding of subtitle files and reject non-UTF-8.
authorCarl Hetherington <cth@carlh.net>
Tue, 22 Sep 2015 15:15:08 +0000 (16:15 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 22 Sep 2015 15:15:08 +0000 (16:15 +0100)
src/lib/exceptions.h
src/lib/subrip.cc
src/tools/wscript
test/wscript
wscript

index 7240611..6939f81 100644 (file)
@@ -263,4 +263,12 @@ public:
        ProgrammingError (std::string file, int line);
 };
 
+class TextEncodingError : public StringError
+{
+public:
+       TextEncodingError (std::string s)
+               : StringError (s)
+       {}
+};
+
 #endif
index f198679..d4adee4 100644 (file)
 #include "subrip_content.h"
 #include <sub/subrip_reader.h>
 #include <sub/collect.h>
+#include <uchardet/uchardet.h>
+#include <iostream>
 
 #include "i18n.h"
 
 using std::vector;
+using std::cout;
+using std::string;
 using boost::shared_ptr;
 
 SubRip::SubRip (shared_ptr<const SubRipContent> content)
@@ -36,6 +40,25 @@ SubRip::SubRip (shared_ptr<const SubRipContent> content)
                throw OpenFileError (content->path (0));
        }
 
+       /* Guess the encoding */
+       uchardet_t det = uchardet_new ();
+       char buffer[1024];
+       while (!feof (f)) {
+               int const n = fread (buffer, 1, sizeof (buffer), f);
+               if (uchardet_handle_data (det, buffer, n)) {
+                       break;
+               }
+       }
+
+       uchardet_data_end (det);
+       string charset = uchardet_get_charset (det);
+       uchardet_delete (det);
+
+       if (charset != "UTF-8") {
+               throw TextEncodingError (_("unrecognised character set; please use files encoded in UTF-8"));
+       }
+
+       rewind (f);
        sub::SubripReader reader (f);
        _subtitles = sub::collect<vector<sub::Subtitle> > (reader.subtitles ());
 }
index 33a631e..b01eee7 100644 (file)
@@ -29,6 +29,7 @@ def configure(conf):
 def build(bld):
     uselib =  'BOOST_THREAD BOOST_DATETIME OPENJPEG DCP XMLSEC CXML XMLPP AVFORMAT AVFILTER AVCODEC '
     uselib += 'AVUTIL SWSCALE POSTPROC CURL BOOST_FILESYSTEM SSH ZIP CAIROMM FONTCONFIG PANGOMM SUB MAGICK SNDFILE SAMPLERATE BOOST_REGEX '
+    uselib += 'UCHARDET '
 
     if bld.env.TARGET_WINDOWS:
         uselib += 'WINSOCK2'
index 1a1038e..a92e344 100644 (file)
@@ -31,7 +31,7 @@ def build(bld):
     obj = bld(features='cxx cxxprogram')
     obj.name   = 'unit-tests'
     obj.uselib =  'BOOST_TEST BOOST_THREAD BOOST_FILESYSTEM BOOST_DATETIME SNDFILE SAMPLERATE DCP OPENJPEG FONTCONFIG CAIROMM PANGOMM XMLPP '
-    obj.uselib += 'AVFORMAT AVFILTER AVCODEC AVUTIL SWSCALE POSTPROC CXML MAGICK SUB GLIB CURL SSH XMLSEC BOOST_REGEX '
+    obj.uselib += 'AVFORMAT AVFILTER AVCODEC AVUTIL SWSCALE POSTPROC CXML MAGICK SUB GLIB CURL SSH XMLSEC BOOST_REGEX UCHARDET '
     if bld.env.TARGET_WINDOWS:
         obj.uselib += 'WINSOCK2'
     obj.use    = 'libdcpomatic2'
diff --git a/wscript b/wscript
index 3e84dca..150e9cb 100644 (file)
--- a/wscript
+++ b/wscript
@@ -159,6 +159,8 @@ def configure(conf):
     else:
         conf.check_cfg(package='libcurl', args='--cflags --libs', uselib_store='CURL', mandatory=True)
 
+    # uchardet
+    conf.check_cfg(package='uchardet', args='--cflags --libs', uselib_store='UCHARDET', mandatory=True)
 
     # libsndfile
     conf.check_cfg(package='sndfile', args='--cflags --libs', uselib_store='SNDFILE', mandatory=True)