hs-php-session 0.0.9.1 → 0.0.9.2
raw patch · 4 files changed
+202/−85 lines, 4 filesPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
API changes (from Hackage documentation)
+ Data.PHPSession: decodePHPSessionEither :: ByteString -> Either PHPSessionDecodingError PHPSessionVariableList
+ Data.PHPSession: decodePHPSessionValueEither :: ByteString -> Either PHPSessionDecodingError PHPSessionValue
+ Data.PHPSession: decodePartialPHPSessionValueEither :: ByteString -> Either PHPSessionDecodingError (PHPSessionValue, ByteString)
+ Data.PHPSession.Types: PHPSessionCouldntDecodeObjectPast :: ByteString -> PHPSessionDecodingError
+ Data.PHPSession.Types: PHPSessionCouldntDecodePast :: ByteString -> PHPSessionDecodingError
+ Data.PHPSession.Types: PHPSessionCouldntDecodeSerializablePast :: ByteString -> PHPSessionDecodingError
+ Data.PHPSession.Types: PHPSessionCouldntDecodeStringPast :: ByteString -> PHPSessionDecodingError
+ Data.PHPSession.Types: PHPSessionNotFullyDecoded :: PHPSessionVariableList -> ByteString -> PHPSessionDecodingError
+ Data.PHPSession.Types: PHPSessionStringEmpty :: PHPSessionDecodingError
+ Data.PHPSession.Types: PHPSessionValueNotFullyDecoded :: PHPSessionValue -> ByteString -> PHPSessionDecodingError
+ Data.PHPSession.Types: data PHPSessionDecodingError
+ Data.PHPSession.Types: instance Eq PHPSessionDecodingError
+ Data.PHPSession.Types: instance Show PHPSessionDecodingError
Files
- Data/PHPSession.hs +106/−64
- Data/PHPSession/Types.hs +59/−1
- Test/General.hs +36/−19
- hs-php-session.cabal +1/−1
Data/PHPSession.hs view
@@ -14,12 +14,15 @@ module Data.PHPSession ( -- * Decode from 'ByteString' decodePHPSession,+ decodePHPSessionEither, decodePHPSessionValue,+ decodePHPSessionValueEither, -- * Encode to 'ByteString' encodePHPSession, encodePHPSessionValue, -- * Decode only part of a 'ByteString' decodePartialPHPSessionValue,+ decodePartialPHPSessionValueEither, -- * PHP session types PHPSessionVariableList, PHPSessionClassName (..),@@ -35,25 +38,36 @@ import qualified Data.Char as C import Data.List (foldl') --- import qualified Text.Regex.Posix as TR --- | Decodes a 'ByteString' containing a serialization of a list of session variables++-- | Decodes a 'LBS.ByteString' containing a serialization of a list of session variables -- using the \"php\" session serialization format into a 'PHPSessionVariableList'+-- decodePHPSession :: LBS.ByteString -> Maybe PHPSessionVariableList decodePHPSession input =- case decodePHPSessionEachTopLevel input [] of- Nothing -> Nothing- Just (everything,"") -> Just everything- Just (_, _) -> Nothing+ case decodePHPSessionEither input of+ Left _ -> Nothing+ Right result -> Just result ++-- | A version of 'decodePHPSession' that returns a 'PHPSessionDecodingError' when+-- decoding the 'LBS.ByteString' fails.+--+decodePHPSessionEither :: LBS.ByteString -> Either PHPSessionDecodingError PHPSessionVariableList+decodePHPSessionEither input =+ case decodePHPSessionEachTopLevelEither input [] of+ Left err -> Left err+ Right (everything,"") -> Right everything+ Right (a, b) -> Left (PHPSessionNotFullyDecoded a b)+ where- decodePHPSessionEachTopLevel input lst =+ decodePHPSessionEachTopLevelEither input lst = case input of- "" -> Just (reverse lst,"")+ "" -> Right (reverse lst,"") _ -> do (name, rest) <- decodePHPSessionTopLevelVarName input- (sym, rest') <- decodePartialPHPSessionValue rest- decodePHPSessionEachTopLevel rest' ((name, sym):lst)+ (sym, rest') <- decodePartialPHPSessionValueEither rest+ decodePHPSessionEachTopLevelEither rest' ((name, sym):lst) decodePHPSessionTopLevelVarName input = do (varname,n1) <- get_name_until_vertbar input@@ -61,8 +75,11 @@ return (varname, n2) get_name_until_vertbar input = case LBS.takeWhile (/= '|') input of- l -> Just (l, LBS.drop (LBS.length l) input)- get_vertbar input = case LBS.take 1 input of "|" -> Just ("|", LBS.drop 1 input); _ -> Nothing+ l -> Right (l, LBS.drop (LBS.length l) input)+ get_vertbar input =+ case LBS.take 1 input of+ "|" -> Right ("|", LBS.drop 1 input)+ _ -> Left $ PHPSessionCouldntDecodePast input -- Not exported and used by decodePartialPHPSessionValue@@ -79,7 +96,7 @@ decodePartialPHPSessionValuesNested rest (sym:lst) --- | Decodes a 'ByteString' containing a session serialization of a value into a +-- | Decodes a 'LBS.ByteString' containing a session serialization of a value into a -- 'PHPSessionValue'. The format being decoded is similar if not probably the same -- format used by PHP's serialize/unserialize functions. -- 'Nothing' is returned if the input bytestring could not be parsed correctly.@@ -90,8 +107,18 @@ Nothing -> Nothing Just (everything,"") -> Just everything Just (_, _) -> Nothing+ +-- | A version of 'decodePHPSessionValue' that returns 'PHPSessionDecodingError'+-- when decoding the 'LBS.ByteString' fails.+--+decodePHPSessionValueEither :: LBS.ByteString -> Either PHPSessionDecodingError PHPSessionValue+decodePHPSessionValueEither input =+ case decodePartialPHPSessionValueEither input of+ Left err -> Left err+ Right (everything,"") -> Right everything+ Right (a, b) -> Left (PHPSessionValueNotFullyDecoded a b) --- | Decodes as much of a 'ByteString' as needed into a 'PHPSessionValue' and returns+-- | Decodes as much of a 'LBS.ByteString' as needed into a 'PHPSessionValue' and returns -- the rest of the string. Decoding ends at either the end of the string or when the -- extent of the current nested structure is met when an extra closing curly brace is -- encountered. The format being decoded is similar if not probably the same @@ -99,111 +126,126 @@ -- 'Nothing' is returned if the input bytestring could not be parsed correctly. -- decodePartialPHPSessionValue :: LBS.ByteString -> Maybe (PHPSessionValue, LBS.ByteString)-decodePartialPHPSessionValue "" = Nothing decodePartialPHPSessionValue input =+ decodePartialPHPSessionValueCommon input+ (\a -> Just a) -- Successfully decoded+ (\a -> Nothing) -- Could not decode++-- | A version of 'decodePartialPHPSessionValue' that uses Either, on decoding error a+-- 'PHPSessionDecodingError' is returned.+--+decodePartialPHPSessionValueEither :: LBS.ByteString -> Either PHPSessionDecodingError (PHPSessionValue, LBS.ByteString)+decodePartialPHPSessionValueEither input =+ decodePartialPHPSessionValueCommon input+ (\a -> Right a) -- Successfully decoded+ (\b -> Left b) -- Could not decode+ +decodePartialPHPSessionValueCommon ::+ LBS.ByteString+ -> ((PHPSessionValue, LBS.ByteString) -> dtype)+ -> (PHPSessionDecodingError -> dtype)+ -> dtype+decodePartialPHPSessionValueCommon "" done couldntDecode =+ couldntDecode PHPSessionStringEmpty+decodePartialPHPSessionValueCommon input done couldntDecode = let sertype = LBS.take 1 input rest = LBS.drop 1 input in case sertype of -- "Object implementing Serializeable" (C) -- ex: hi|C:9:"ClassName":5:{harr}}- "C" -> do- (_classnamelen,cls',numrest) <-- dec_colon_integer_colon_dquote_classname_dquote_colon rest- --case rest TR.=~ (":[0-9]+:\"[A-Za-z0-9_]+\":" :: LBS.ByteString) :: (LBS.ByteString,LBS.ByteString,LBS.ByteString) of- -- ("",cls,numrest) ->- case LBS.span (/=':') numrest of+ "C" -> + case do+ (_classnamelen,cls',numrest) <-+ dec_colon_integer_colon_dquote_classname_dquote_colon rest+ case LBS.span (/=':') numrest of (num, colrest) ->- -- let [_,cls',_] = LBS.split '"' cls let num' = read (LBS.unpack num) (dat,rest') = LBS.splitAt num' $ LBS.drop 2 colrest rest'' = LBS.drop 1 rest' in Just (PHPSessionValueObjectSerializeable (PHPSessionClassName cls') dat, rest'')+ of+ Nothing -> couldntDecode (PHPSessionCouldntDecodeSerializablePast rest)+ Just ok -> done ok -- Object (O) ex: hi|O:9:"ClassName":2:{s:4:"blah";i:1;s:3:"str";s:6:"string";}- "O" -> do- (_,cls',attrest) <- - dec_colon_integer_colon_dquote_classname_dquote rest- -- case rest TR.=~ (":[0-9]+:\"[A-Za-z0-9_]+\"" :: LBS.ByteString) :: (LBS.ByteString,LBS.ByteString,LBS.ByteString) of- let (l,rest') = decodePartialPHPSessionAttr attrest []+ "O" ->+ case dec_colon_integer_colon_dquote_classname_dquote rest of+ Nothing -> couldntDecode (PHPSessionCouldntDecodeObjectPast rest)+ Just (_,cls',attrest) ->+ let (l,rest') = decodePartialPHPSessionAttr attrest [] in case l of- Nothing -> Nothing -- , input)- Just [PHPSessionAttrInt _, PHPSessionAttrNested vals] ->+ Left err -> couldntDecode err+ Right [PHPSessionAttrInt _, PHPSessionAttrNested vals] -> let (al, bl) = L.partition (odd . snd) (zip vals [1..]) arlst = map (\[a,b] -> (a,b)) $ L.transpose [ map (\(a,_)->a) al, map (\(a,_)->a) bl ]- in Just ((PHPSessionValueObject (PHPSessionClassName cls') arlst),rest')+ in done ((PHPSessionValueObject (PHPSessionClassName cls') arlst),rest') -- String (s) ex: hi|s:6:"string"; "s" -> do- (len, strrest) <- dec_colon_integer_colon_dquote rest- --case rest TR.=~ (":[0-9]+:\"" :: LBS.ByteString) :: (LBS.ByteString,LBS.ByteString,LBS.ByteString) of- -- ("",strlen,strrest) ->- -- let [_,len,_] = LBS.split ':' strlen- let len' = read (LBS.unpack len)- (str,rest') = LBS.splitAt len' $ strrest- rest'' = LBS.drop 2 rest' - in Just (PHPSessionValueString str,rest'')+ case dec_colon_integer_colon_dquote rest of+ Nothing -> couldntDecode (PHPSessionCouldntDecodeStringPast rest)+ Just (len, strrest) ->+ let len' = read (LBS.unpack len)+ (str,rest') = LBS.splitAt len' $ strrest+ rest'' = LBS.drop 2 rest' + in done (PHPSessionValueString str,rest'') _ -> let (l,rest') = decodePartialPHPSessionAttr rest [] in case (sertype, l) of -- Array (a) ex: hi|a:3:{i:0;i:1;i:1;i:2;i:2;s:3:"abc";}- ("a",Just [PHPSessionAttrInt _, PHPSessionAttrNested vals]) -> + ("a",Right [PHPSessionAttrInt _, PHPSessionAttrNested vals]) -> let (al, bl) = L.partition (odd . snd) (zip vals [1..]) arlst = map (\[a,b] -> (a,b)) $ L.transpose [ map (\(a,_)->a) al, map (\(a,_)->a) bl ]- in Just (PHPSessionValueArray arlst, rest')+ in done (PHPSessionValueArray arlst, rest') -- Boolean (b) ex: hi|b:0; = FALSE -- hi|b:1; = TRUE- ("b",Just [PHPSessionAttrInt 1]) -> Just (PHPSessionValueBool True,rest')- ("b",Just [PHPSessionAttrInt 0]) -> Just (PHPSessionValueBool False,rest')+ ("b",Right [PHPSessionAttrInt 1]) -> done (PHPSessionValueBool True,rest')+ ("b",Right [PHPSessionAttrInt 0]) -> done (PHPSessionValueBool False,rest') -- Float (d) ex: hi|d:0.1000000000000000055511151231257827021181583404541015625;- ("d",Just [PHPSessionAttrFloat num]) -> Just ((PHPSessionValueFloat $ Right num),rest')- ("d",Just [PHPSessionAttrInt num]) -> Just ((PHPSessionValueFloat $ Left num),rest')+ ("d",Right [PHPSessionAttrFloat num]) -> done ((PHPSessionValueFloat $ Right num),rest')+ ("d",Right [PHPSessionAttrInt num]) -> done ((PHPSessionValueFloat $ Left num),rest') -- Integer (i) ex: hi|i:26;- ("i",Just [PHPSessionAttrInt num]) -> Just (PHPSessionValueInt num,rest')+ ("i",Right [PHPSessionAttrInt num]) -> done (PHPSessionValueInt num,rest') -- Null (N) ex: hi|N;- ("N",Just []) -> Just (PHPSessionValueNull,rest')+ ("N",Right []) -> done (PHPSessionValueNull,rest') -- Recursive values and references (r), (R), TODO: PHP 6 encoded String (S) _ -> case l of- Just l' -> Just ((PHPSessionValueMisc sertype l'),rest')- Nothing -> Nothing -- , input)+ Right l' -> done ((PHPSessionValueMisc sertype l'),rest')+ Left err -> couldntDecode err where - decodePartialPHPSessionAttr :: LBS.ByteString -> [PHPSessionAttr] -> (Maybe [PHPSessionAttr],LBS.ByteString)+ decodePartialPHPSessionAttr :: LBS.ByteString -> [PHPSessionAttr] -> (Either PHPSessionDecodingError [PHPSessionAttr],LBS.ByteString) decodePartialPHPSessionAttr input l = case LBS.take 1 input of ";" ->- (Just $ reverse l,LBS.drop 1 input)+ (Right $ reverse l,LBS.drop 1 input) _ -> case dec_colon_and_number input of Just (num,rest) ->- --case input TR.=~ (":[-0-9.]+" :: LBS.ByteString) :: (LBS.ByteString,LBS.ByteString,LBS.ByteString) of- -- ("",num,rest) ->- let num' = LBS.unpack $ num -- LBS.drop 1 + let num' = LBS.unpack num in case LBS.elem '.' num of True ->- decodePartialPHPSessionAttr rest ((PHPSessionAttrFloat $ read $ num'):l)+ decodePartialPHPSessionAttr rest ((PHPSessionAttrFloat $ read num'):l) False ->- decodePartialPHPSessionAttr rest ((PHPSessionAttrInt $ read $ num'):l)+ decodePartialPHPSessionAttr rest ((PHPSessionAttrInt $ read num'):l) Nothing -> case dec_colon_and_open_curly input of Just (":{", rest) ->- -- case input TR.=~ (":{" :: LBS.ByteString) :: (LBS.ByteString,LBS.ByteString,LBS.ByteString) of- -- ("",":{",rest) ->- let Just (sub,rest') = decodePartialPHPSessionValuesNested rest []- in (Just $ reverse (PHPSessionAttrNested sub:l),rest')+ let Just (sub,rest') = decodePartialPHPSessionValuesNested rest []+ in (Right $ reverse (PHPSessionAttrNested sub:l),rest') Nothing -> case dec_colon_uppercase_letters input of Just ("NAN", rest) -> decodePartialPHPSessionAttr rest ((PHPSessionAttrFloat $ 0/0):l) Just ("INF", rest) -> decodePartialPHPSessionAttr rest ((PHPSessionAttrFloat $ 1/0):l) Just ("-INF", rest) -> decodePartialPHPSessionAttr rest ((PHPSessionAttrFloat $ -1/0):l) Nothing ->- error $ show input- -- (Nothing, input)- -- error "No good"+ (Left $ PHPSessionCouldntDecodePast input, input)+ dec_colon_integer_colon_dquote_classname_dquote_colon input = do (_0,n0) <- dec_get_colon input (len,n1) <- dec_get_integer n0@@ -278,7 +320,7 @@ dec_get_dash input = case LBS.take 1 input of "-" -> Just ("-", LBS.drop 1 input); _ -> Nothing dec_get_dot input = case LBS.take 1 input of "." -> Just (".", LBS.drop 1 input); _ -> Nothing --- | Encode a 'PHPSessionVariableList' into a 'ByteString' containing the serialization+-- | Encode a 'PHPSessionVariableList' into a 'LBS.ByteString' containing the serialization -- of a list of session variables using the \"php\" session serialization format. encodePHPSession :: PHPSessionVariableList -> LBS.ByteString encodePHPSession lst =@@ -294,7 +336,7 @@ encodePHPSessionVarName name = LBS.concat [name, "|"] --- | Encode a 'PHPSessionValue' into a 'ByteString' containing the serialization of a+-- | Encode a 'PHPSessionValue' into a 'LBS.ByteString' containing the serialization of a -- PHP value. The format being encoded into is similar if not probably the same -- format used by PHP's serialize/unserialize functions. --
Data/PHPSession/Types.hs view
@@ -15,7 +15,8 @@ PHPSessionVariableList, PHPSessionClassName (..), PHPSessionValue (..),- PHPSessionAttr (..)+ PHPSessionAttr (..),+ PHPSessionDecodingError (..) ) where import qualified Data.ByteString.Lazy.Char8 as LBS@@ -127,3 +128,60 @@ PHPSessionAttrNested a == PHPSessionAttrNested b = a == b _ == _ = False ++-- | 'PHPSessionDecodingError' are error types that can be returned if decoding+-- did not succeed. They are returned by the 'Either' versions of the decoding+-- functions.+--+-- * 'PHPSessionStringEmpty' is given if the decoder got an empty byte sequence.+--+-- * 'PHPSessionCouldntDecodeSerializablePast' is given if the decoding does not+-- succeed while in the particular byte sequence for a class that implements+-- Serializable.+--+-- * 'PHPSessionCouldntDecodeObjectPast' is given if the decoding does not succeed+-- while in the particular byte sequence for a PHP object value.+--+-- * 'PHPSessionCouldntDecodeStringPast' is given if the decoding does not succeed+-- while in the particular byte sequence for a PHP string.+--+-- * 'PHPSessionCouldntDecodePast' is given if the decoding does not succeed while+-- decoding common byte sequences which are composed mainly of 'PHPSessionAttr'+-- forms.+--+-- * 'PHPSessionValueNotFullyDecoded' is given if the byte sequence is not fully+-- decoded to a 'PHPSessionValue' when using decodePHPSessionValue or+-- decodePHPSessionValueEither.+--+-- * 'PHPSessionNotFullyDecoded' is given.if the byte sequence is not fully+-- decoded to a 'PHPSessionVariableList' when using decodePHPSession or+-- decodePHPSessionEither.+--+data PHPSessionDecodingError =+ PHPSessionStringEmpty |+ PHPSessionCouldntDecodeSerializablePast LBS.ByteString |+ PHPSessionCouldntDecodeObjectPast LBS.ByteString |+ PHPSessionCouldntDecodeStringPast LBS.ByteString |+ PHPSessionCouldntDecodePast LBS.ByteString |+ PHPSessionValueNotFullyDecoded PHPSessionValue LBS.ByteString |+ PHPSessionNotFullyDecoded PHPSessionVariableList LBS.ByteString+ +instance Show PHPSessionDecodingError where+ show (PHPSessionStringEmpty) = "PHPSessionStringEmpty"+ show (PHPSessionCouldntDecodeSerializablePast str) = "PHPSessionCouldntDecodeSerializablePast " ++ show str+ show (PHPSessionCouldntDecodeObjectPast str) = "PHPSessionCouldntDecodeObjectPast " ++ show str+ show (PHPSessionCouldntDecodeStringPast str) = "PHPSessionCouldntDecodeStringPast " ++ show str+ show (PHPSessionCouldntDecodePast str) = "PHPSessionCouldntDecodePast " ++ show str+ show (PHPSessionValueNotFullyDecoded val str) = "PHPSessionNotFullyDecoded " ++ show val ++ " ... " ++ show str+ show (PHPSessionNotFullyDecoded val str) = "PHPSessionNotFullyDecoded " ++ show val ++ " ... " ++ show str++instance Eq PHPSessionDecodingError where+ PHPSessionStringEmpty == PHPSessionStringEmpty = True+ PHPSessionCouldntDecodeSerializablePast str == PHPSessionCouldntDecodeSerializablePast str' = str == str'+ PHPSessionCouldntDecodeObjectPast str == PHPSessionCouldntDecodeObjectPast str' = str == str'+ PHPSessionCouldntDecodeStringPast str == PHPSessionCouldntDecodeStringPast str' = str == str'+ PHPSessionCouldntDecodePast str == PHPSessionCouldntDecodePast str' = str == str'+ PHPSessionValueNotFullyDecoded a b == PHPSessionValueNotFullyDecoded a' b' = a == a' && b == b'+ PHPSessionNotFullyDecoded a b == PHPSessionNotFullyDecoded a' b' = a == a' && b == b'+ _ == _ = False+
Test/General.hs view
@@ -9,30 +9,47 @@ -- {-# LANGUAGE OverloadedStrings #-} -module Test.General where+module Test.General (testcases, testcasesWith) where import Data.PHPSession import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Lazy.Char8 as LBS import qualified Data.List as L--- import qualified Text.Regex.Posix as TR import Data.List (foldl')+import System.IO -testcases :: Bool-testcases =- let test1 = "v1|s:94:\" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}\";v2|a:3:{i:0;i:10;i:1;i:9;i:2;s:5:\"eight\";}v3|C:9:\"ClassName\":94:{ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}}v4|b:1;v5|i:10;v6|d:5.5;v7|N;"- test2 = "v1|a:3:{i:0;i:10;i:1;i:9;i:2;a:3:{i:0;i:8;i:1;i:7;i:2;a:3:{i:0;i:6;i:1;s:4:\"five\";i:2;d:4;}}}v2|O:9:\"ClassName\":2:{s:4:\"blah\";i:1;s:3:\"str\";s:94:\" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}\";}"- test3 = "v1|s:256:\"00000000000000000000000000000000 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\";"- test4 = "teststr1|s:0:\"\";test_array|a:1:{i:0;a:2:{s:4:\"ABCD\";s:9:\"987654321\";s:0:\"\";b:1;}}test_int|i:1;teststr2|s:4:\"1234\";"- test5 = "testfloat1|d:1.00001121;testfloat2|d:NAN;testfloat3|d:INF;testfloat4|d:-INF;"- tresults = map (\test -> case decodePHPSession test of- Nothing -> False- Just dec -> let result = encodePHPSession dec in- if result == test- then True- else error $ "Not same: " ++ LBS.unpack test ++ " and " ++ LBS.unpack result)- [test1,test2,test3,test4,test5]- fresults = map (\test -> case decodePHPSession test of Nothing -> False; Just dec -> let result = encodePHPSession dec in result == test)- []- in and tresults && ((or fresults) /= True) +test1 = "v1|s:94:\" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}\";v2|a:3:{i:0;i:10;i:1;i:9;i:2;s:5:\"eight\";}v3|C:9:\"ClassName\":94:{ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}}v4|b:1;v5|i:10;v6|d:5.5;v7|N;"+test2 = "v1|a:3:{i:0;i:10;i:1;i:9;i:2;a:3:{i:0;i:8;i:1;i:7;i:2;a:3:{i:0;i:6;i:1;s:4:\"five\";i:2;d:4;}}}v2|O:9:\"ClassName\":2:{s:4:\"blah\";i:1;s:3:\"str\";s:94:\" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}\";}"+test3 = "v1|s:256:\"00000000000000000000000000000000 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\";"+test4 = "teststr1|s:0:\"\";test_array|a:1:{i:0;a:2:{s:4:\"ABCD\";s:9:\"987654321\";s:0:\"\";b:1;}}test_int|i:1;teststr2|s:4:\"1234\";"+test5 = "testfloat1|d:1.00001121;testfloat2|d:NAN;testfloat3|d:INF;testfloat4|d:-INF;"++testcases :: IO Bool+testcases = do+ testcasesWith (\message -> hPutStrLn stderr message)++testcasesWith :: (String -> IO ()) -> IO Bool+testcasesWith issue = do+ let tresults = map testDecodeAndReencode [test1,test2,test3,test4,test5]+ fresults = map testDecodeOnly []+ tresults' <- mapM issueIfDidntDecodedAndReencoded tresults+ fresults' <- mapM issueIfDecodedAndReencodedWhenItShouldnt fresults+ return $ and tresults' && ((or fresults') /= True) + where+ issueIfDidntDecodedAndReencoded a =+ case a of+ Left message -> issue message >> return False+ Right b -> return b+ issueIfDecodedAndReencodedWhenItShouldnt a =+ case a of+ Right decoded -> (issue $ "Decoded when it shouldnt " ++ (show decoded)) >> return False+ Left b -> return True+ testDecodeAndReencode test = + case decodePHPSessionEither test of+ Left err -> Left (show err)+ Right dec -> let result = encodePHPSession dec in+ if result == test+ then Right True+ else Left $ "Not same: " ++ LBS.unpack test ++ " and " ++ LBS.unpack result+ testDecodeOnly test = decodePHPSessionEither test
hs-php-session.cabal view
@@ -1,5 +1,5 @@ name: hs-php-session -version: 0.0.9.1 +version: 0.0.9.2 synopsis: PHP session and values serialization description: A library for encoding and decoding serialized PHP sessions in the format