瀏覽代碼

2010-01-11 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Replaced '/' and '_' with '_' in HTTP/FTP filename.
	* src/A2STR.cc
	* src/A2STR.h
	* src/FtpNegotiationCommand.cc
	* src/HttpResponseCommand.cc
	* src/util.cc
	* src/util.h
	* test/UtilTest.cc
Tatsuhiro Tsujikawa 15 年之前
父節點
當前提交
768f78f771
共有 8 個文件被更改,包括 47 次插入2 次删除
  1. 11 0
      ChangeLog
  2. 4 0
      src/A2STR.cc
  3. 4 0
      src/A2STR.h
  4. 2 1
      src/FtpNegotiationCommand.cc
  5. 2 1
      src/HttpResponseCommand.cc
  6. 6 0
      src/util.cc
  7. 9 0
      src/util.h
  8. 9 0
      test/UtilTest.cc

+ 11 - 0
ChangeLog

@@ -1,3 +1,14 @@
+2010-01-11  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Replaced '/' and '_' with '_' in HTTP/FTP filename.
+	* src/A2STR.cc
+	* src/A2STR.h
+	* src/FtpNegotiationCommand.cc
+	* src/HttpResponseCommand.cc
+	* src/util.cc
+	* src/util.h
+	* test/UtilTest.cc
+
 2010-01-11  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Treat --dir="" as --dir="."

+ 4 - 0
src/A2STR.cc

@@ -56,4 +56,8 @@ const std::string A2STR::SEMICOLON_C(";");
 
 const std::string A2STR::EQUAL_C("=");
 
+const std::string A2STR::UNDERSCORE_C("_");
+
+const std::string A2STR::BACK_SLASH_C("\\");
+
 } // namespace aria2

+ 4 - 0
src/A2STR.h

@@ -62,6 +62,10 @@ public:
   static const std::string SEMICOLON_C;
 
   static const std::string EQUAL_C;
+
+  static const std::string UNDERSCORE_C;
+
+  static const std::string BACK_SLASH_C;
 };
 } // namespace aria2
 

+ 2 - 1
src/FtpNegotiationCommand.cc

@@ -337,7 +337,8 @@ bool FtpNegotiationCommand::onFileSizeDetermined(uint64_t totalLength)
   if(_fileEntry->getPath().empty()) {
     _fileEntry->setPath
       (util::applyDir
-       (getDownloadContext()->getDir(), util::urldecode(req->getFile())));
+       (getDownloadContext()->getDir(),
+        util::fixTaintedBasename(util::urldecode(req->getFile()))));
   }
   _requestGroup->preDownloadProcessing();
   if(e->_requestGroupMan->isSameFileBeingDownloaded(_requestGroup)) {

+ 2 - 1
src/HttpResponseCommand.cc

@@ -132,7 +132,8 @@ bool HttpResponseCommand::executeInternal()
     if(_fileEntry->getPath().empty()) {
       _fileEntry->setPath
         (util::applyDir
-         (getDownloadContext()->getDir(), httpResponse->determinFilename()));
+         (getDownloadContext()->getDir(),
+          util::fixTaintedBasename(httpResponse->determinFilename())));
     }
     _fileEntry->setContentType(httpResponse->getContentType());
     _requestGroup->preDownloadProcessing();

+ 6 - 0
src/util.cc

@@ -1011,6 +1011,12 @@ std::string applyDir(const std::string& dir, const std::string& relPath)
   }
 }
 
+std::string fixTaintedBasename(const std::string& src)
+{
+  return replace(replace(src, A2STR::SLASH_C, A2STR::UNDERSCORE_C),
+                 A2STR::BACK_SLASH_C, A2STR::UNDERSCORE_C);
+}
+
 } // namespace util
 
 } // namespace aria2

+ 9 - 0
src/util.h

@@ -362,6 +362,15 @@ bool saveAs
 // dir = "/",    relPath = "foo" => "/foo"
 std::string applyDir(const std::string& dir, const std::string& relPath);
 
+// In HTTP/FTP, file name is file component in URI. In HTTP, filename
+// may be a value of Content-Disposition header.  They are likely
+// percent encoded. If they contains, for example, %2F, when decoded,
+// basename contains dir component. This should be avoided.  This
+// function is created to fix these issues.  This function expects src
+// should be non-percent-encoded basename.  Currently, this function
+// replaces '/' and '\' with '_'.
+std::string fixTaintedBasename(const std::string& src);
+
 } // namespace util
 
 } // namespace aria2

+ 9 - 0
test/UtilTest.cc

@@ -59,6 +59,7 @@ class UtilTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testFromHex);
   CPPUNIT_TEST(testParsePrioritizePieceRange);
   CPPUNIT_TEST(testApplyDir);
+  CPPUNIT_TEST(testFixTaintedBasename);
   CPPUNIT_TEST_SUITE_END();
 private:
 
@@ -106,6 +107,7 @@ public:
   void testFromHex();
   void testParsePrioritizePieceRange();
   void testApplyDir();
+  void testFixTaintedBasename();
 };
 
 
@@ -910,4 +912,11 @@ void UtilTest::testApplyDir()
   CPPUNIT_ASSERT_EQUAL(std::string("/dl/pred"), util::applyDir("/dl", "pred"));
 }
 
+void UtilTest::testFixTaintedBasename()
+{
+  CPPUNIT_ASSERT_EQUAL(std::string("a_b"), util::fixTaintedBasename("a/b"));
+  CPPUNIT_ASSERT_EQUAL(std::string("a_b"), util::fixTaintedBasename("a\\b"));
+  CPPUNIT_ASSERT_EQUAL(std::string("a__b"), util::fixTaintedBasename("a\\/b"));
+}
+
 } // namespace aria2