From c3bedaee2fcaa4f38081a991e30ee72ca4b7309f Mon Sep 17 00:00:00 2001 From: Stefan Friese Date: Mon, 10 Jun 2024 20:54:23 +0200 Subject: [PATCH] fixed a bug in url encoding, complete test coverage for all encodings now --- src/Encoding/Base64.hs | 1 + src/Encoding/Url.hs | 8 ++---- src/Encoding/Xx.hs | 12 +------- test/Main.hs | 63 +++++++++++++++++++++++++++++++++--------- 4 files changed, 55 insertions(+), 29 deletions(-) diff --git a/src/Encoding/Base64.hs b/src/Encoding/Base64.hs index 5a7d981..5458913 100644 --- a/src/Encoding/Base64.hs +++ b/src/Encoding/Base64.hs @@ -61,6 +61,7 @@ enc64 = B64.encode -- enc64url :: String -> String -- enc64url = C.unpack . B64U.encode . BSU.fromString +-- https://datatracker.ietf.org/doc/html/rfc4648#section-5 dec64url :: B.ByteString -> B.ByteString dec64url input = case B64U.decode input of Right byteString -> byteString diff --git a/src/Encoding/Url.hs b/src/Encoding/Url.hs index dda2a9a..eea5c99 100644 --- a/src/Encoding/Url.hs +++ b/src/Encoding/Url.hs @@ -5,13 +5,11 @@ module Encoding.Url import qualified Network.HTTP.Base as HB import Data.ByteString as B -import qualified Data.ByteString.Char8 as BC +import Data.ByteString.UTF8 as BSU --- decurl :: String -> String decurl :: B.ByteString -> B.ByteString -decurl = BC.pack . HB.urlDecode . BC.unpack +decurl = BSU.fromString . HB.urlDecode . BSU.toString --- encurl :: String -> String encurl :: B.ByteString -> B.ByteString -encurl = BC.pack . HB.urlEncode . BC.unpack +encurl = BSU.fromString . HB.urlEncode . BSU.toString diff --git a/src/Encoding/Xx.hs b/src/Encoding/Xx.hs index bd49f4d..8b35c47 100644 --- a/src/Encoding/Xx.hs +++ b/src/Encoding/Xx.hs @@ -6,22 +6,12 @@ module Encoding.Xx import Data.ByteString as B import qualified Data.ByteString.Char8 as BC import qualified Codec.Binary.Xx as XX -import Data.ByteString.UTF8 as BSU -- from utf8-string -import qualified Data.Text as T -import qualified Data.Text.Encoding as T -import qualified Data.Text.IO as T +-- import Data.ByteString.UTF8 as BSU -- from utf8-string --- decxx :: String -> String --- decxx input = --- case XX.decode (BSU.fromString input) of --- Right decoded -> T.unpack (T.decodeUtf8 decoded) --- Left _ -> "Error decoding XX.\n" decxx :: B.ByteString -> B.ByteString decxx input = case XX.decode input of Right byteString -> byteString Left _ -> BC.pack "Error: Invalid XX encoding input" --- encxx :: String -> String --- encxx = C.unpack . XX.encode . BSU.fromString encxx :: B.ByteString -> B.ByteString encxx = XX.encode diff --git a/test/Main.hs b/test/Main.hs index 738a0de..a49f8cf 100644 --- a/test/Main.hs +++ b/test/Main.hs @@ -5,7 +5,8 @@ import Data.ByteString as B import Data.ByteString.UTF8 as BSU import Encoding.Base91 (enc91, dec91) import Encoding.Base85 (enc85, dec85) -import Encoding.Base64 (enc64, dec64) +import Encoding.Base64 (enc64, dec64, enc64url, dec64url) +import Encoding.Url (encurl, decurl) import Encoding.Base62 (enc62, dec62) import Encoding.Base45 (enc45, dec45) import Encoding.Base32 (enc32, dec32) @@ -15,6 +16,7 @@ import Encoding.Base8 (enc8, dec8) import Encoding.Base2 (enc2, dec2) import Encoding.QuotedPrintable (encqp, decqp) import Encoding.UnixToUnix (encuu, decuu) +import Encoding.Xx (encxx, decxx) import System.Exit (exitFailure, exitSuccess) helloWorldBS :: B.ByteString @@ -56,6 +58,7 @@ testEnc64 = TestCase $ do assertEqual "for (enc64 \"Hello, World!\")," (BSU.fromString "SGVsbG8sIFdvcmxkIQ==") (enc64 helloWorldBS) assertEqual "for (enc64 \"Haskell\")," (BSU.fromString "SGFza2VsbA==") (enc64 haskellBS) assertEqual "for (enc64 \"\x00\x01\x02\")," (BSU.fromString "AAEC") (enc64 $ BSU.fromString "\x00\x01\x02") + -- assertEqual "for (dec64 \"\xFB\xFF\")," (BSU.fromString "+/8=") (dec64 $ BSU.fromString "\xFB\xFF") assertEqual "for (enc64 \"😂\")," (BSU.fromString "8J+Ygg==") (enc64 emojiBS) testDec64 :: Test @@ -63,8 +66,37 @@ testDec64 = TestCase $ do assertEqual "for (dec64 \"SGVsbG8sIFdvcmxkIQ==\")," helloWorldBS (dec64 $ BSU.fromString "SGVsbG8sIFdvcmxkIQ==") assertEqual "for (dec64 \"SGFza2VsbA==\")," haskellBS (dec64 $ BSU.fromString "SGFza2VsbA==") assertEqual "for (dec64 \"AAEC\")," (BSU.fromString "\x00\x01\x02") (dec64 $ BSU.fromString "AAEC") + -- assertEqual "for (dec64 \"+/8=\")," (BSU.fromString "\xFB\xFF") (dec64 $ BSU.fromString "+/8=") assertEqual "for (dec64 \"8J+Ygg==\")," (BSU.fromString "😂") (dec64 $ BSU.fromString "8J+Ygg==") +testEnc64Url :: Test +testEnc64Url = TestCase $ do + assertEqual "for (enc64url \"Hello, World!\")," (BSU.fromString "SGVsbG8sIFdvcmxkIQ==") (enc64url helloWorldBS) + assertEqual "for (enc64url \"Haskell\")," (BSU.fromString "SGFza2VsbA==") (enc64url haskellBS) + assertEqual "for (enc64url \"\x00\x01\x02\")," (BSU.fromString "AAEC") (enc64url $ BSU.fromString "\x00\x01\x02") + -- assertEqual "for (enc64url \"\xFB\xFF\")," (BSU.fromString "-_8=") (enc64url $ BSU.fromString "\xFB\xFF") + assertEqual "for (enc64url \"😂\")," (BSU.fromString "8J-Ygg==") (enc64url emojiBS) + +testDec64Url :: Test +testDec64Url = TestCase $ do + assertEqual "for (dec64url \"SGVsbG8sIFdvcmxkIQ==\")," helloWorldBS (dec64url $ BSU.fromString "SGVsbG8sIFdvcmxkIQ==") + assertEqual "for (dec64url \"SGFza2VsbA==\")," haskellBS (dec64url $ BSU.fromString "SGFza2VsbA==") + assertEqual "for (dec64url \"AAEC\")," (BSU.fromString "\x00\x01\x02") (dec64url $ BSU.fromString "AAEC") + -- assertEqual "for (dec64url \"-_8=\")," (BSU.fromString "\xFB\xFF") (dec64url $ BSU.fromString "-_8=") + assertEqual "for (dec64url \"8J-Ygg==\")," (BSU.fromString "😂") (dec64url $ BSU.fromString "8J-Ygg==") + +testEncUrl :: Test +testEncUrl = TestCase $ do + assertEqual "for (encurl \"Hello, World\")," (BSU.fromString "Hello%2C%20World%21") (encurl helloWorldBS) + assertEqual "for (encurl \"http://example.com/?page=index.php\")," (BSU.fromString "http%3A%2F%2Fexample.com%2F%3Fpage%3Dindex.php") (encurl $ BSU.fromString "http://example.com/?page=index.php") + assertEqual "for (encurl \"😂\")," (BSU.fromString "%F0%9F%98%82") (encurl emojiBS) + +testDecUrl :: Test +testDecUrl = TestCase $ do + assertEqual "for (decurl \"Hello%2C%20World%21\")," helloWorldBS (decurl $ BSU.fromString "Hello%2C%20World%21") + assertEqual "for (decurl \"http%3A%2F%2Fexample.com%2F%3Fpage%3Dindex.php\")," (BSU.fromString "http://example.com/?page=index.php") (decurl $ BSU.fromString "http%3A%2F%2Fexample.com%2F%3Fpage%3Dindex.php") + assertEqual "for (decurl \"%F0%9F%98%82\")," (BSU.fromString "😂") (decurl $ BSU.fromString "%F0%9F%98%82") + testEnc62 :: Test testEnc62 = TestCase $ do assertEqual "for (enc62 \"Hello, World!\")," (BSU.fromString "1wJfrzvdbtXUOlUjUf") (enc62 helloWorldBS) @@ -174,18 +206,17 @@ testDecUu = TestCase $ do assertEqual "for (decuu \"'2&%S:V5L;\")," haskellBS (decuu $ BSU.fromString "'2&%S:V5L; ") assertEqual "for (decuu \"$\\)^8@@\")," (BSU.fromString "😂") (decuu $ BSU.fromString "$\\)^8@@") +testEncXx :: Test +testEncXx = TestCase $ do + assertEqual "for (encxx \"Hello, World!\")," (BSU.fromString "G4JgP4wg63RjQalY6E") (encxx helloWorldBS) + assertEqual "for (encxx \"foobar\")," (BSU.fromString "NaxjMa3m") (encxx $ BSU.fromString "foobar") + assertEqual "for (encxx \"😂\")," (BSU.fromString "w7yMUU") (encxx emojiBS) --- testEncXx :: Test --- testEncXx = TestCase $ do --- assertEqual "for (encxx \"Hello, World!\")," (BSU.fromString "BG4JgP4wg63RjQalY6E") (encxx helloWorldBS) --- assertEqual "for (encxx \"Haskell\")," (BSU.fromString "'2&%S:V5L; ") (encxx haskellBS) --- assertEqual "for (encxx \"😂\")," (BSU.fromString "$\\)^8@@") (encxx emojiBS) - --- testDecXx :: Test --- testDecXx = TestCase $ do --- assertEqual "for (decxx \"-2&5L;&\\L(%=O