Bläddra i källkod

2008-11-28 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	RFC3986 complied Percent-Encoding(urlencode).
	Use uppercase hexadecimal digits for encoded text instead of
	lowercase ones.
	* src/Request.cc
	* src/Util.cc
	* src/Util.h
	* test/BtHandshakeMessageTest.cc
	* test/DefaultBtAnnounceTest.cc
	* test/DefaultBtContextTest.cc
	* test/RequestTest.cc
	* test/UtilTest.cc
Tatsuhiro Tsujikawa 17 år sedan
förälder
incheckning
b3aa7cef1d
9 ändrade filer med 126 tillägg och 68 borttagningar
  1. 14 0
      ChangeLog
  2. 2 2
      src/Request.cc
  3. 37 28
      src/Util.cc
  4. 10 5
      src/Util.h
  5. 6 3
      test/BtHandshakeMessageTest.cc
  6. 24 21
      test/DefaultBtAnnounceTest.cc
  7. 7 4
      test/DefaultBtContextTest.cc
  8. 2 2
      test/RequestTest.cc
  9. 24 3
      test/UtilTest.cc

+ 14 - 0
ChangeLog

@@ -1,3 +1,17 @@
+2008-11-28  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	RFC3986 complied Percent-Encoding(urlencode).
+	Use uppercase hexadecimal digits for encoded text instead of lowercase
+	ones.
+	* src/Request.cc
+	* src/Util.cc
+	* src/Util.h
+	* test/BtHandshakeMessageTest.cc
+	* test/DefaultBtAnnounceTest.cc
+	* test/DefaultBtContextTest.cc
+	* test/RequestTest.cc
+	* test/UtilTest.cc
+
 2008-11-27  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Fixed the bug that prevents aria2 from downloading 0-length files

+ 2 - 2
src/Request.cc

@@ -100,13 +100,13 @@ static std::string urlencode(const std::string& src)
   for(int index = src.size()-1; index >= 0; --index) {
     const unsigned char c = result[index];
     // '/' is not urlencoded because src is expected to be a path.
-    if(Util::shouldUrlencode(c)) {
+    if(!Util::inRFC3986ReservedChars(c) && !Util::inRFC3986UnreservedChars(c)) {
       if(c == '%') {
 	if(!isHexNumber(result[index+1]) || !isHexNumber(result[index+2])) {
 	  result.replace(index, 1, "%25");
 	}
       } else {
-	result.replace(index, 1, StringFormat("%%%02x", c).str());
+	result.replace(index, 1, StringFormat("%%%02X", c).str());
       }
     }
   }

+ 37 - 28
src/Util.cc

@@ -33,20 +33,11 @@
  */
 /* copyright --> */
 #include "Util.h"
-#include "File.h"
-#include "message.h"
-#include "Randomizer.h"
-#include "a2netcompat.h"
-#include "DlAbortEx.h"
-#include "BitfieldMan.h"
-#include "DefaultDiskWriter.h"
-#include "FatalException.h"
-#include "FileEntry.h"
-#include "StringFormat.h"
-#include "A2STR.h"
+
 #include <signal.h>
 #include <limits.h>
 #include <stdint.h>
+
 #include <cerrno>
 #include <cassert>
 #include <cstring>
@@ -63,6 +54,19 @@
 # endif // HAVE_WINSOCK_H
 #endif // HAVE_SLEEP
 
+#include "File.h"
+#include "message.h"
+#include "Randomizer.h"
+#include "a2netcompat.h"
+#include "DlAbortEx.h"
+#include "BitfieldMan.h"
+#include "DefaultDiskWriter.h"
+#include "FatalException.h"
+#include "FileEntry.h"
+#include "StringFormat.h"
+#include "A2STR.h"
+#include "array_fun.h"
+
 // For libc6 which doesn't define ULLONG_MAX properly because of broken limits.h
 #ifndef ULLONG_MAX
 # define ULLONG_MAX 18446744073709551615ULL
@@ -207,28 +211,33 @@ std::string Util::replace(const std::string& target, const std::string& oldstr,
   return result;
 }
 
-bool Util::shouldUrlencode(const char c)
+bool Util::inRFC3986ReservedChars(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 ||
-	   '~' == c);	   
+  static const char reserved[] = {
+    ':' , '/' , '?' , '#' , '[' , ']' , '@',
+    '!' , '$' , '&' , '\'' , '(' , ')',
+    '*' , '+' , ',' , ';' , '=' };
+  return std::find(&reserved[0], &reserved[arrayLength(reserved)], c) !=
+    &reserved[arrayLength(reserved)];
+}
+
+bool Util::inRFC3986UnreservedChars(const char c)
+{
+  static const char unreserved[] = { '-', '.', '_', '~' };
+  return
+    // ALPHA
+    ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') ||
+    // DIGIT
+    ('0' <= c && c <= '9') ||
+    std::find(&unreserved[0], &unreserved[arrayLength(unreserved)], c) !=
+    &unreserved[arrayLength(unreserved)];
 }
 
 std::string Util::urlencode(const unsigned char* target, size_t len) {
   std::string dest;
   for(size_t i = 0; i < len; i++) {
-    if(shouldUrlencode(target[i])) {
-      dest.append(StringFormat("%%%02x", target[i]).str());
+    if(!inRFC3986UnreservedChars(target[i])) {
+      dest.append(StringFormat("%%%02X", target[i]).str());
     } else {
       dest += target[i];
     }
@@ -244,7 +253,7 @@ std::string Util::torrentUrlencode(const unsigned char* target, size_t len) {
        ('a' <= target[i] && target[i] <= 'z')) {
       dest += target[i];
     } else {
-      dest.append(StringFormat("%%%02x", target[i]).str());
+      dest.append(StringFormat("%%%02X", target[i]).str());
     }
   }
   return dest;

+ 10 - 5
src/Util.h

@@ -36,16 +36,19 @@
 #define _D_UTIL_H_
 
 #include "common.h"
-#include "SharedHandle.h"
-#include "IntSequence.h"
-#include "a2time.h"
-#include "a2netcompat.h"
+
 #include <sys/time.h>
+
 #include <string>
 #include <utility>
 #include <deque>
 #include <iosfwd>
 
+#include "SharedHandle.h"
+#include "IntSequence.h"
+#include "a2time.h"
+#include "a2netcompat.h"
+
 namespace aria2 {
 
 class Randomizer;
@@ -153,7 +156,9 @@ public:
     return urlencode((const unsigned char*)target.c_str(), target.size());
   }
 
-  static bool shouldUrlencode(const char c);
+  static bool inRFC3986ReservedChars(const char c);
+
+  static bool inRFC3986UnreservedChars(const char c);
 
   static std::string urldecode(const std::string& target);
 

+ 6 - 3
test/BtHandshakeMessageTest.cc

@@ -1,9 +1,12 @@
 #include "BtHandshakeMessage.h"
+
+#include <cstring>
+
+#include <cppunit/extensions/HelperMacros.h>
+
 #include "PeerMessageUtil.h"
 #include "Util.h"
 #include "BtConstants.h"
-#include <cstring>
-#include <cppunit/extensions/HelperMacros.h>
 
 namespace aria2 {
 
@@ -102,7 +105,7 @@ void BtHandshakeMessageTest::testToString() {
   msg.setInfoHash(infoHash);
   msg.setPeerId(peerId);
 
-  CPPUNIT_ASSERT_EQUAL(std::string("handshake peerId=%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0, reserved=0000000000100004"), msg.toString());
+  CPPUNIT_ASSERT_EQUAL(std::string("handshake peerId=%F0%F0%F0%F0%F0%F0%F0%F0%F0%F0%F0%F0%F0%F0%F0%F0%F0%F0%F0%F0, reserved=0000000000100004"), msg.toString());
 }
 
 void BtHandshakeMessageTest::testSetDHTEnabled()

+ 24 - 21
test/DefaultBtAnnounceTest.cc

@@ -1,4 +1,9 @@
 #include "DefaultBtAnnounce.h"
+
+#include <iostream>
+
+#include <cppunit/extensions/HelperMacros.h>
+
 #include "DefaultBtContext.h"
 #include "Option.h"
 #include "Util.h"
@@ -10,8 +15,6 @@
 #include "AnnounceTier.h"
 #include "FixedNumberRandomizer.h"
 #include "FileEntry.h"
-#include <iostream>
-#include <cppunit/extensions/HelperMacros.h>
 
 namespace aria2 {
 
@@ -109,35 +112,35 @@ void DefaultBtAnnounceTest::testNoMoreAnnounce()
   btAnnounce.setRandomizer(SharedHandle<Randomizer>(new FixedNumberRandomizer()));
   btAnnounce.generateKey();
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceSuccess();
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceFailure();
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceSuccess();
 
   _pieceStorage->setAllDownloadFinished(true);
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceSuccess();
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceSuccess();
 
   _btRuntime->setHalt(true);
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceSuccess();
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceSuccess();
 
@@ -160,23 +163,23 @@ void DefaultBtAnnounceTest::testGetAnnounceUrl()
   btAnnounce.setRandomizer(SharedHandle<Randomizer>(new FixedNumberRandomizer()));
   btAnnounce.generateKey();
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceSuccess();
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceSuccess();
 
   _pieceStorage->setAllDownloadFinished(true);
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceSuccess();
 
   _btRuntime->setHalt(true);
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 }
 
 void DefaultBtAnnounceTest::testIsAllAnnounceFailed()
@@ -202,11 +205,11 @@ void DefaultBtAnnounceTest::testIsAllAnnounceFailed()
   btAnnounce.setRandomizer(SharedHandle<Randomizer>(new FixedNumberRandomizer()));
   btAnnounce.generateKey();
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceFailure();
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceFailure();
 
@@ -234,17 +237,17 @@ void DefaultBtAnnounceTest::testURLOrderInStoppedEvent()
   btAnnounce.setRandomizer(SharedHandle<Randomizer>(new FixedNumberRandomizer()));
   btAnnounce.generateKey();
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceSuccess();
 
   _btRuntime->setHalt(true);
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceFailure();
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost2/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost2/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceSuccess();
 }
@@ -264,17 +267,17 @@ void DefaultBtAnnounceTest::testURLOrderInCompletedEvent()
   btAnnounce.setRandomizer(SharedHandle<Randomizer>(new FixedNumberRandomizer()));
   btAnnounce.generateKey();
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceSuccess();
 
   _pieceStorage->setAllDownloadFinished(true);
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceFailure();
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost2/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost2/announce?info_hash=%01%23Eg%89%AB%CD%EF%01%23Eg%89%AB%CD%EF%01%23Eg&peer_id=%2Daria2%2Dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
 
   btAnnounce.announceSuccess();
 }

+ 7 - 4
test/DefaultBtContextTest.cc

@@ -1,13 +1,16 @@
 #include "DefaultBtContext.h"
+
+#include <cstring>
+#include <iostream>
+
+#include <cppunit/extensions/HelperMacros.h>
+
 #include "Util.h"
 #include "RecoverableException.h"
 #include "AnnounceTier.h"
 #include "FixedNumberRandomizer.h"
 #include "FileEntry.h"
 #include "array_fun.h"
-#include <cstring>
-#include <iostream>
-#include <cppunit/extensions/HelperMacros.h>
 
 namespace aria2 {
 
@@ -236,7 +239,7 @@ void DefaultBtContextTest::testGetInfoHashAsString() {
 void DefaultBtContextTest::testGetPeerId() {
   DefaultBtContext btContext;
   btContext.setRandomizer(SharedHandle<Randomizer>(new FixedNumberRandomizer()));
-  CPPUNIT_ASSERT_EQUAL(std::string("%2daria2%2dAAAAAAAAAAAAA"), Util::torrentUrlencode(btContext.getPeerId(), 20));
+  CPPUNIT_ASSERT_EQUAL(std::string("%2Daria2%2DAAAAAAAAAAAAA"), Util::torrentUrlencode(btContext.getPeerId(), 20));
 }
 
 void DefaultBtContextTest::testComputeFastSet()

+ 2 - 2
test/RequestTest.cc

@@ -268,10 +268,10 @@ void RequestTest::testSetUrl17()
   CPPUNIT_ASSERT(v);
   CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol());
   CPPUNIT_ASSERT_EQUAL(std::string("host"), req.getHost());
-  CPPUNIT_ASSERT_EQUAL(std::string("/file%3cwith%252%20%20space"), req.getDir());
+  CPPUNIT_ASSERT_EQUAL(std::string("/file%3Cwith%252%20%20space"), req.getDir());
   CPPUNIT_ASSERT_EQUAL(std::string("file%20with%20space;param%25"), req.getFile());
   CPPUNIT_ASSERT_EQUAL(std::string("?a=/?"), req.getQuery());
-  CPPUNIT_ASSERT_EQUAL(std::string("http://host:80/file%3cwith%252%20%20space"
+  CPPUNIT_ASSERT_EQUAL(std::string("http://host:80/file%3Cwith%252%20%20space"
 				   "/file%20with%20space;param%25?a=/?"),
 		       req.getCurrentUrl());
   CPPUNIT_ASSERT_EQUAL(std::string("http://host:80/file<with%2 %20space"

+ 24 - 3
test/UtilTest.cc

@@ -1,13 +1,16 @@
 #include "Util.h"
+
+#include <string>
+#include <iostream>
+
+#include <cppunit/extensions/HelperMacros.h>
+
 #include "FixedNumberRandomizer.h"
 #include "DlAbortEx.h"
 #include "BitfieldMan.h"
 #include "ByteArrayDiskWriter.h"
 #include "FileEntry.h"
 #include "File.h"
-#include <string>
-#include <iostream>
-#include <cppunit/extensions/HelperMacros.h>
 
 namespace aria2 {
 
@@ -47,6 +50,7 @@ class UtilTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testUitos);
   CPPUNIT_TEST(testHttpGMT);
   CPPUNIT_TEST(testNtoh64);
+  CPPUNIT_TEST(testUrlencode);
   CPPUNIT_TEST_SUITE_END();
 private:
 
@@ -87,6 +91,7 @@ public:
   void testUitos();
   void testHttpGMT();
   void testNtoh64();
+  void testUrlencode();
 };
 
 
@@ -701,4 +706,20 @@ void UtilTest::testNtoh64()
 #endif // !WORDS_BIGENDIAN
 }
 
+void UtilTest::testUrlencode()
+{
+  CPPUNIT_ASSERT_EQUAL
+    (std::string("%3A%2F%3F%23%5B%5D%40%21%25%26%27%28%29%2A%2B%2C%3B%3D"),
+     Util::urlencode(":/?#[]@!%&'()*+,;="));
+
+  std::string unreserved =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    "abcdefghijklmnopqrstuvwxyz"
+    "0123456789"
+    "-._~";
+  CPPUNIT_ASSERT_EQUAL(unreserved, Util::urlencode(unreserved));
+
+  CPPUNIT_ASSERT_EQUAL(std::string("1%5EA%20"), Util::urlencode("1^A "));
+}
+
 } // namespace aria2