diff --git a/ChangeLog b/ChangeLog index dea04061..6eaa6f91 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2010-05-06 Tatsuhiro Tsujikawa + + 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 Release 1.9.2 diff --git a/src/util.cc b/src/util.cc index 58a37d4a..11f89f57 100644 --- a/src/util.cc +++ b/src/util.cc @@ -679,11 +679,50 @@ std::string iso8859ToUtf8(const std::string& src) return dest; } +template +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 params; - split(header, std::back_inserter(params), A2STR::SEMICOLON_C, true); + parseParam(std::back_inserter(params), header); for(std::vector::const_iterator i = params.begin(), eoi = params.end(); i != eoi; ++i) { const std::string& param = *i; diff --git a/test/UtilTest.cc b/test/UtilTest.cc index 25c187de..ddbc4fec 100644 --- a/test/UtilTest.cc +++ b/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\""));