From 4f59dc84bfa4be6e5fcea98b5f8775ddf7764dfa Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 11 Nov 2007 04:25:56 +0000 Subject: [PATCH] 2007-11-11 Tatsuhiro Tsujikawa 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 --- ChangeLog | 12 ++++++++++++ src/Request.cc | 40 ++++++++++++++++++++++++++++++---------- src/Request.h | 7 +++++-- src/Util.cc | 26 +++++++++++++++++--------- src/Util.h | 2 ++ test/RequestTest.cc | 43 ++++++++++++++----------------------------- 6 files changed, 80 insertions(+), 50 deletions(-) diff --git a/ChangeLog b/ChangeLog index 47aeee85..7ef4875c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2007-11-11 Tatsuhiro Tsujikawa + + 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 Don't connect server before checking file integrity at startup, if diff --git a/src/Request.cc b/src/Request.cc index c519c501..69cf025e 100644 --- a/src/Request.cc +++ b/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); +} diff --git a/src/Request.h b/src/Request.h index 3dc26c35..facbc022 100644 --- a/src/Request.h +++ b/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: diff --git a/src/Util.cc b/src/Util.cc index 9035766f..00f84399 100644 --- a/src/Util.cc +++ b/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'; diff --git a/src/Util.h b/src/Util.h index 1873566b..f49219fa 100644 --- a/src/Util.h +++ b/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); diff --git a/test/RequestTest.cc b/test/RequestTest.cc index 04da1740..13ab75c4 100644 --- a/test/RequestTest.cc +++ b/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"); - 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;