Переглянути джерело

2010-05-06 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Fixed the bug that if filename in Content-Disposition header
	includes ';', aria2 cuts filename after ';'.
	* src/util.cc
	* test/UtilTest.cc
Tatsuhiro Tsujikawa 15 роки тому
батько
коміт
2bcf648102
3 змінених файлів з 53 додано та 2 видалено
  1. 7 0
      ChangeLog
  2. 40 1
      src/util.cc
  3. 6 1
      test/UtilTest.cc

+ 7 - 0
ChangeLog

@@ -1,3 +1,10 @@
+2010-05-06  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Fixed the bug that if filename in Content-Disposition header
+	includes ';', aria2 cuts filename after ';'.
+	* src/util.cc
+	* test/UtilTest.cc
+
 2010-04-28  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Release 1.9.2

+ 40 - 1
src/util.cc

@@ -679,11 +679,50 @@ std::string iso8859ToUtf8(const std::string& src)
   return dest;
 }
 
+template<typename OutputIterator>
+static void parseParam(OutputIterator out, const std::string& header)
+{
+  for(std::string::const_iterator i = header.begin(), eoi = header.end();
+      i != eoi;) {
+    std::string::const_iterator paramFirst = i;
+    std::string::const_iterator paramLast = paramFirst;
+    for(; paramLast != eoi && *paramLast != '=' && *paramLast != ';';
+        ++paramLast);
+    std::string param;
+    if(paramLast == eoi || *paramLast == ';') {
+      // No value, parmname only
+      param = std::string(paramFirst, paramLast);
+    } else {
+      for(; paramLast != eoi && *paramLast != '"' && *paramLast != ';';
+          ++paramLast);
+      if(paramLast != eoi && *paramLast == '"') {
+        // quoted-string
+        ++paramLast;
+        for(; paramLast != eoi && *paramLast != '"'; ++paramLast);
+        if(paramLast != eoi) {
+          ++paramLast;
+        }
+        param = std::string(paramFirst, paramLast);
+        for(; paramLast != eoi && *paramLast != ';'; ++paramLast);
+      } else {
+        param = std::string(paramFirst, paramLast);
+      }
+    }
+    trimSelf(param);
+    *out++ = param;
+    if(paramLast == eoi) {
+      break;
+    }
+    i = paramLast;
+    ++i;
+  }
+}
+
 std::string getContentDispositionFilename(const std::string& header)
 {
   std::string filename;
   std::vector<std::string> params;
-  split(header, std::back_inserter(params), A2STR::SEMICOLON_C, true);
+  parseParam(std::back_inserter(params), header);
   for(std::vector<std::string>::const_iterator i = params.begin(),
         eoi = params.end(); i != eoi; ++i) {
     const std::string& param = *i;

+ 6 - 1
test/UtilTest.cc

@@ -301,7 +301,7 @@ void UtilTest::testGetContentDispositionFilename() {
   CPPUNIT_ASSERT_EQUAL(std::string("aria2.tar.bz2"), util::getContentDispositionFilename(h8));
 
   std::string h9 = "attachment; filename=\"aria2.tar.bz2; creation-date=20 Jun 2007 00:00:00 GMT\"";
-  CPPUNIT_ASSERT_EQUAL(std::string("aria2.tar.bz2"),
+  CPPUNIT_ASSERT_EQUAL(std::string("aria2.tar.bz2; creation-date=20 Jun 2007 00:00:00 GMT"),
                        util::getContentDispositionFilename(h9));
 
   std::string h10 = "attachment; filename=";
@@ -313,6 +313,11 @@ void UtilTest::testGetContentDispositionFilename() {
   std::string filenameWithDir = "attachment; filename=dir/file";
   CPPUNIT_ASSERT_EQUAL(std::string(""),
                        util::getContentDispositionFilename(filenameWithDir));
+
+  std::string semicolonInside = "attachment; filename=\"foo;bar\"";
+  CPPUNIT_ASSERT_EQUAL(std::string("foo;bar"),
+                       util::getContentDispositionFilename(semicolonInside));
+
   CPPUNIT_ASSERT_EQUAL
     (std::string(""),
      util::getContentDispositionFilename("filename=\"%2E%2E%2Ffoo.html\""));