Parcourir la source

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 il y a 18 ans
Parent
commit
4f59dc84bf
6 fichiers modifiés avec 80 ajouts et 50 suppressions
  1. 12 0
      ChangeLog
  2. 30 10
      src/Request.cc
  3. 5 2
      src/Request.h
  4. 17 9
      src/Util.cc
  5. 2 0
      src/Util.h
  6. 14 29
      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>
 
 	Don't connect server before checking file integrity at startup, if

+ 30 - 10
src/Request.cc

@@ -66,14 +66,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;
   string query;
@@ -83,9 +78,6 @@ bool Request::parseUrl(const string& url) {
   file = "";
   _username = "";
   _password = "";
-  if(tempUrl.find_first_not_of(SAFE_CHARS) != string::npos) {
-    return false;
-  }
   // find query part
   string::size_type startQueryIndex = tempUrl.find("?");
   if(startQueryIndex != string::npos) {
@@ -152,3 +144,31 @@ bool Request::parseUrl(const string& url) {
   file += query;
   return true;
 }
+
+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

@@ -46,8 +46,6 @@
 "%"\
 "#"
 
-#define METALINK_MARK "#!metalink3!"
-
 class Request {
 public:
   enum TRACKER_EVENT {
@@ -83,6 +81,11 @@ private:
   string _password;
 
   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

@@ -247,18 +247,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

@@ -89,6 +89,8 @@ public:
     return urlencode((const unsigned char*)target.c_str(), target.size());
   }
 
+  static bool shouldUrlencode(const char c);
+
   static string urldecode(const string& target);
 
   static string torrentUrlencode(const unsigned char* target, int32_t len);

+ 14 - 29
test/RequestTest.cc

@@ -23,15 +23,14 @@ class RequestTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testSetUrl14);
   CPPUNIT_TEST(testSetUrl15);
   CPPUNIT_TEST(testSetUrl16);
+  CPPUNIT_TEST(testSetUrl17);
   CPPUNIT_TEST(testSetUrl_username);
   CPPUNIT_TEST(testSetUrl_usernamePassword);
   CPPUNIT_TEST(testSetUrl_zeroUsername);
   CPPUNIT_TEST(testRedirectUrl);
   CPPUNIT_TEST(testRedirectUrl2);
   CPPUNIT_TEST(testResetUrl);
-  CPPUNIT_TEST(testSafeChar);
   CPPUNIT_TEST(testInnerLink);
-  CPPUNIT_TEST(testMetalink);
   CPPUNIT_TEST_SUITE_END();
   
 public:
@@ -51,15 +50,14 @@ public:
   void testSetUrl14();
   void testSetUrl15();
   void testSetUrl16();
+  void testSetUrl17();
   void testSetUrl_username();
   void testSetUrl_usernamePassword();
   void testSetUrl_zeroUsername();
   void testRedirectUrl();
   void testRedirectUrl2();
   void testResetUrl();
-  void testSafeChar();
   void testInnerLink();
-  void testMetalink();
 };
 
 
@@ -179,7 +177,7 @@ void RequestTest::testSetUrl10() {
 void RequestTest::testSetUrl11() {
   Request req;
   bool v = req.setUrl("http://host?query/");
-  
+
   CPPUNIT_ASSERT(v);
   CPPUNIT_ASSERT_EQUAL(string("http"), req.getProtocol());
   CPPUNIT_ASSERT_EQUAL(string("host"), req.getHost());
@@ -245,6 +243,17 @@ void RequestTest::testSetUrl16()
   CPPUNIT_ASSERT_EQUAL(string("file"), 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;
   req.setKeepAlive(true);
@@ -310,12 +319,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");
@@ -323,24 +326,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::testSetUrl_zeroUsername()
 {
   Request req;