packages feed

hellnet-0.1: Hellnet/Meta.hs

module Hellnet.Meta (Meta(..), fromByteString, toByteString, emptyMeta) where

import Codec.Crypto.RSA
import qualified Data.ByteString.Lazy as BSL
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BS8
import qualified Data.ByteString.Lazy.Char8 as BSL8
import qualified Data.ByteString.UTF8 as BU
import qualified Data.ByteString.Lazy.UTF8 as BUL
import qualified Data.Map as Map
import Data.Maybe
import Debug.Trace
import Hellnet
import Hellnet.Utils
import Hellnet.URI
import Text.HJson as Json
import Text.JSON.JPath

data Meta = Meta {
	keyID :: KeyID -- ^ Public key ID
	, metaName :: String -- ^ Meta name
	, timestamp :: Integer -- ^ Updated timestamp
	, contentURI :: HellnetURI -- ^ Meta content location
	, message :: Maybe BSL.ByteString -- ^ JSON as ByteString
	, signature :: Maybe Signature -- ^ Digital signature
	} deriving (Eq, Show)

emptyMeta = Meta {
	keyID = [] -- ^ Public key ID
	, metaName = "" -- ^ Meta name
	, timestamp = 0 -- ^ Updated timestamp
	, contentURI = ChunkURI [] Nothing Nothing -- ^ Meta content location
	, message = Nothing -- ^ JSON as ByteString
	, signature = Nothing -- ^ Digital signature
}

instance Jsonable Meta where
	fromJson v = let
		keyIDV = jPath' "key" v;
		timestampV = jPath' "updated" v;
		nameV = jPath' "name" v;
		contentV = jPath' "content" v in
			case [keyIDV, timestampV, nameV, contentV] of
				[	[JString keyHash]
					, [JNumber timestampF]
					, [JString nameS]
					, [JString contentURI]
					] -> maybe (Nothing) (\u -> Just $ Meta {
						keyID = hexToHash keyHash
						, metaName = nameS
						, timestamp = (round timestampF)
						, contentURI = u
						, signature = Nothing
						, message = Nothing}) (parseHellnetURI contentURI)
				otherwise -> Nothing
	toJson m = toJson $ Map.fromList [
		("key", toJson $ hashToHex $ keyID m)
		, ("updated", toJson $ timestamp m)
		, ("name", toJson $ metaName m)
		, ("content", toJson $ show $ contentURI m)
		]

fromByteString :: BSL.ByteString -> Maybe Meta
fromByteString bs = let
	(s, sigTail) = breakLazySubstring (BSL8.pack "\n\n") bs;
	sig = BSL.drop 2 sigTail
	js = BUL.toString s
	pM = either (const Nothing) (fromJson) $ Json.fromString js in
		case pM of
			Nothing -> Nothing
			Just preMeta -> Just $ preMeta { message = Just s, signature = Just sig}

toByteString :: Meta -> BSL.ByteString
toByteString m = case (message m, signature m) of
	(Just msg, Just sig) -> BSL.concat [msg, BSL8.pack "\n\n", sig]
	otherwise -> BSL.empty