瀏覽代碼

2007-11-11 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	urlencode the given url inside Request::parseUrl(...)
	* src/Request.{h, cc}
	* src/Util.{h, cc}
	* test/RequestTest.cc

	Removed #!metalink3! notation support because it is deleted from
	the metalink specification.
	* src/Request.{h, cc}
	* test/RequestTest.cc
Tatsuhiro Tsujikawa 18 年之前
父節點
當前提交
d84aa986d6
共有 6 個文件被更改,包括 79 次插入46 次删除
  1. 12 0
      ChangeLog
  2. 30 7
      src/Request.cc
  3. 5 2
      src/Request.h
  4. 17 9
      src/Util.cc
  5. 2 0
      src/Util.h
  6. 13 28
      test/RequestTest.cc

+ 12 - 0
ChangeLog

@@ -1,3 +1,15 @@
+2007-11-11  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	urlencode the given url inside Request::parseUrl(...)
+	* src/Request.{h, cc}
+	* src/Util.{h, cc}
+	* test/RequestTest.cc
+
+	Removed #!metalink3! notation support because it is deleted from
+	the metalink specification.
+	* src/Request.{h, cc}
+	* test/RequestTest.cc
+
 2007-11-10  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	* src/SocketCore.cc (writeData): Fixed send error with GnuTLS.

+ 30 - 7
src/Request.cc

@@ -68,14 +68,9 @@ bool Request::parseUrl(const string& url) {
   string tempUrl;
   string::size_type sharpIndex = url.find("#");
   if(sharpIndex != string::npos) {
-    if(FeatureConfig::getInstance()->isSupported("metalink") &&
-       url.find(METALINK_MARK) == sharpIndex) {
-      tempUrl = url.substr(sharpIndex+strlen(METALINK_MARK));
-    } else {
-      tempUrl = url.substr(0, sharpIndex);
-    }
+    tempUrl = urlencode(url.substr(0, sharpIndex));
   } else {
-    tempUrl = url;
+    tempUrl = urlencode(url);
   }
 
   currentUrl = tempUrl;
@@ -145,3 +140,31 @@ AuthConfigHandle Request::resolveHttpProxyAuthConfig()
 {
   return _httpProxyAuthResolver->resolveAuthConfig(getHost());
 }
+
+bool Request::isHexNumber(const char c) const
+{
+  return '0' <= c && c <= '9' || 'A' <= c && c <= 'F' || 'a' <= c && c <= 'f';
+}
+
+string Request::urlencode(const string& src) const
+{
+  int32_t lastIndex = src.size()-1;
+  string result = src+"  ";
+  for(int32_t index = lastIndex; index >= 0; --index) {
+    const char c = result[index];
+    // '/' is not urlencoded because src is expected to be a path.
+    if(Util::shouldUrlencode(c)) {
+      if(c == '%') {
+	if(!isHexNumber(result[index+1]) || !isHexNumber(result[index+2])) {
+	  result.replace(index, 1, "%25");
+	}
+      } else {
+	char temp[4];
+	sprintf(temp, "%%%02x", c);
+	temp[3] = '\0';
+	result.replace(index, 1, temp);
+      }
+    }
+  }
+  return result.substr(0, result.size()-2);
+}

+ 5 - 2
src/Request.h

@@ -48,8 +48,6 @@
 "%"\
 "#"
 
-#define METALINK_MARK "#!metalink3!"
-
 class Request {
 public:
   enum TRACKER_EVENT {
@@ -87,6 +85,11 @@ private:
   AuthResolverHandle _ftpAuthResolver;
 
   bool parseUrl(const string& url);
+
+  bool isHexNumber(const char c) const;
+
+  string urlencode(const string& src) const;
+
 public:
   CookieBoxHandle cookieBox;
 public:

+ 17 - 9
src/Util.cc

@@ -238,18 +238,26 @@ string Util::replace(const string& target, const string& oldstr, const string& n
   return result;
 }
 
+bool Util::shouldUrlencode(const char c)
+{
+  return !(// ALPHA
+	   'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' ||
+	   // DIGIT
+	   '0' <= c && c <= '9' ||
+	   // safe
+	   '$' == c || '-' == c || '_' == c || '.' == c ||
+	   // extra
+	   '!' == c || '*' == c || '\'' == c ||'(' == c ||
+	   ')' == c || ',' == c ||
+	   // reserved
+	   ';' == c || '/' == c || '?' == c  || ':' == c ||
+	   '@' == c || '&' == c || '=' == c || '+' == c);   
+}
+
 string Util::urlencode(const unsigned char* target, int32_t len) {
   string dest;
   for(int32_t i = 0; i < len; i++) {
-    if(!('0' <= target[i] && target[i] <= '9' ||
-	 'A' <= target[i] && target[i] <= 'Z' ||
-	 'a' <= target[i] && target[i] <= 'z' ||
-	 '$' == target[i] || '-' == target[i] ||
-	 '_' == target[i] || '.' == target[i] ||
-	 '+' == target[i] || '!' == target[i] ||
-	 '*' == target[i] || '\'' == target[i] ||
-	 '(' == target[i] || ')' == target[i] ||
-	 ',' == target[i])) {
+    if(shouldUrlencode(target[i])) {
       char temp[4];
       sprintf(temp, "%%%02x", target[i]);
       temp[sizeof(temp)-1] = '\0';

+ 2 - 0
src/Util.h

@@ -76,6 +76,8 @@ public:
 
   static string replace(const string& target, const string& oldstr, const string& newstr);
 
+  static bool shouldUrlencode(const char c);
+
   static string urlencode(const unsigned char* target, int32_t len);
 
   static string urlencode(const string& target)

+ 13 - 28
test/RequestTest.cc

@@ -21,12 +21,11 @@ class RequestTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testSetUrl12);
   CPPUNIT_TEST(testSetUrl13);
   CPPUNIT_TEST(testSetUrl14);
+  CPPUNIT_TEST(testSetUrl17);
   CPPUNIT_TEST(testRedirectUrl);
   CPPUNIT_TEST(testRedirectUrl2);
   CPPUNIT_TEST(testResetUrl);
-  CPPUNIT_TEST(testSafeChar);
   CPPUNIT_TEST(testInnerLink);
-  CPPUNIT_TEST(testMetalink);
   CPPUNIT_TEST(testResolveHttpAuthConfig);
   CPPUNIT_TEST(testResolveHttpAuthConfig_noCandidate);
   CPPUNIT_TEST(testResolveHttpProxyAuthConfig);
@@ -48,12 +47,11 @@ public:
   void testSetUrl12();
   void testSetUrl13();
   void testSetUrl14();
+  void testSetUrl17();
   void testRedirectUrl();
   void testRedirectUrl2();
   void testResetUrl();
-  void testSafeChar();
   void testInnerLink();
-  void testMetalink();
   void testResolveHttpAuthConfig();
   void testResolveHttpAuthConfig_noCandidate();
   void testResolveHttpProxyAuthConfig();
@@ -217,6 +215,17 @@ void RequestTest::testSetUrl14() {
   CPPUNIT_ASSERT_EQUAL(string("abc?query"), req.getFile());
 }
 
+void RequestTest::testSetUrl17()
+{
+  Request req;
+  bool v = req.setUrl("http://host:80/file<with%2 %20space/file with space;param?a=/?");
+  CPPUNIT_ASSERT(v);
+  CPPUNIT_ASSERT_EQUAL(string("http"), req.getProtocol());
+  CPPUNIT_ASSERT_EQUAL(string("host"), req.getHost());
+  CPPUNIT_ASSERT_EQUAL(string("/file%3cwith%252%20%20space"), req.getDir());
+  CPPUNIT_ASSERT_EQUAL(string("file%20with%20space;param?a=/?"), req.getFile());
+}
+
 void RequestTest::testRedirectUrl() {
   Request req;
   bool v = req.setUrl("http://aria.rednoah.com:8080/aria2/index.html");
@@ -279,12 +288,6 @@ void RequestTest::testResetUrl() {
   CPPUNIT_ASSERT_EQUAL(string("index.html"), req.getFile());
 }
 
-void RequestTest::testSafeChar() {
-  Request req;
-  bool v = req.setUrl("http://aria.rednoah.com/|<>");
-  CPPUNIT_ASSERT(!v);
-}
-
 void RequestTest::testInnerLink() {
   Request req;
   bool v = req.setUrl("http://aria.rednoah.com/index.html#download");
@@ -292,24 +295,6 @@ void RequestTest::testInnerLink() {
   CPPUNIT_ASSERT_EQUAL(string("index.html"), req.getFile());
 }
 
-void RequestTest::testMetalink() {
-  Request req;
-  bool v = req.setUrl("http://aria.rednoah.com/download/aria.tar.bz2#!metalink3!http://aria2.sourceforge.net/download/aria.metalink");
-  CPPUNIT_ASSERT(v);
-#ifdef ENABLE_METALINK
-  CPPUNIT_ASSERT_EQUAL(string("aria2.sourceforge.net"), req.getHost());
-  CPPUNIT_ASSERT_EQUAL(string("/download"), req.getDir());
-  CPPUNIT_ASSERT_EQUAL(string("aria.metalink"), req.getFile());
-
-  bool v2 = req.setUrl("http://aria.rednoah.com/download/aria.tar.bz2#!metalink3!");
-  CPPUNIT_ASSERT(!v2);
-#else
-  CPPUNIT_ASSERT_EQUAL(string("aria.rednoah.com"), req.getHost());
-  CPPUNIT_ASSERT_EQUAL(string("/download"), req.getDir());
-  CPPUNIT_ASSERT_EQUAL(string("aria.tar.bz2"), req.getFile());
-#endif // ENABLE_METALINK
-}
-
 void RequestTest::testResolveHttpAuthConfig()
 {
   Request req;