{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module CVE
( parseFeed,
CPE (..),
CPEMatch (..),
CPEMatchRow (..),
cpeMatches,
CVE (..),
CVEID,
cveLI,
)
where
import Data.Aeson
( FromJSON,
Object,
eitherDecode,
parseJSON,
withObject,
(.!=),
(.:),
(.:!),
)
import Data.Aeson.Types (Parser, prependFailure)
import qualified Data.ByteString.Lazy.Char8 as BSL
import Data.List (intercalate)
import qualified Data.Text as T
import Data.Time.Clock (UTCTime)
import Database.SQLite.Simple (FromRow, ToRow, field, fromRow, toRow)
import Database.SQLite.Simple.ToField (toField)
import OurPrelude
import Utils (Boundary (..), VersionMatcher (..))
type CVEID = Text
data CVE = CVE
{ CVE -> CVEID
cveID :: CVEID,
CVE -> [CPEMatch]
cveCPEMatches :: [CPEMatch],
CVE -> CVEID
cveDescription :: Text,
CVE -> UTCTime
cvePublished :: UTCTime,
CVE -> UTCTime
cveLastModified :: UTCTime
}
deriving (Int -> CVE -> ShowS
[CVE] -> ShowS
CVE -> String
(Int -> CVE -> ShowS)
-> (CVE -> String) -> ([CVE] -> ShowS) -> Show CVE
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CVE] -> ShowS
$cshowList :: [CVE] -> ShowS
show :: CVE -> String
$cshow :: CVE -> String
showsPrec :: Int -> CVE -> ShowS
$cshowsPrec :: Int -> CVE -> ShowS
Show, CVE -> CVE -> Bool
(CVE -> CVE -> Bool) -> (CVE -> CVE -> Bool) -> Eq CVE
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CVE -> CVE -> Bool
$c/= :: CVE -> CVE -> Bool
== :: CVE -> CVE -> Bool
$c== :: CVE -> CVE -> Bool
Eq, Eq CVE
Eq CVE
-> (CVE -> CVE -> Ordering)
-> (CVE -> CVE -> Bool)
-> (CVE -> CVE -> Bool)
-> (CVE -> CVE -> Bool)
-> (CVE -> CVE -> Bool)
-> (CVE -> CVE -> CVE)
-> (CVE -> CVE -> CVE)
-> Ord CVE
CVE -> CVE -> Bool
CVE -> CVE -> Ordering
CVE -> CVE -> CVE
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CVE -> CVE -> CVE
$cmin :: CVE -> CVE -> CVE
max :: CVE -> CVE -> CVE
$cmax :: CVE -> CVE -> CVE
>= :: CVE -> CVE -> Bool
$c>= :: CVE -> CVE -> Bool
> :: CVE -> CVE -> Bool
$c> :: CVE -> CVE -> Bool
<= :: CVE -> CVE -> Bool
$c<= :: CVE -> CVE -> Bool
< :: CVE -> CVE -> Bool
$c< :: CVE -> CVE -> Bool
compare :: CVE -> CVE -> Ordering
$ccompare :: CVE -> CVE -> Ordering
$cp1Ord :: Eq CVE
Ord)
cveLI :: CVE -> Bool -> Text
cveLI :: CVE -> Bool -> CVEID
cveLI CVE
c Bool
patched =
CVEID
"- ["
CVEID -> CVEID -> CVEID
forall a. Semigroup a => a -> a -> a
<> CVE -> CVEID
cveID CVE
c
CVEID -> CVEID -> CVEID
forall a. Semigroup a => a -> a -> a
<> CVEID
"](https://nvd.nist.gov/vuln/detail/"
CVEID -> CVEID -> CVEID
forall a. Semigroup a => a -> a -> a
<> CVE -> CVEID
cveID CVE
c
CVEID -> CVEID -> CVEID
forall a. Semigroup a => a -> a -> a
<> CVEID
")"
CVEID -> CVEID -> CVEID
forall a. Semigroup a => a -> a -> a
<> CVEID
p
where
p :: CVEID
p =
if Bool
patched
then CVEID
" (patched)"
else CVEID
""
data CPEMatch = CPEMatch
{ CPEMatch -> CPE
cpeMatchCPE :: CPE,
CPEMatch -> Bool
cpeMatchVulnerable :: Bool,
CPEMatch -> VersionMatcher
cpeMatchVersionMatcher :: VersionMatcher
}
deriving (Int -> CPEMatch -> ShowS
[CPEMatch] -> ShowS
CPEMatch -> String
(Int -> CPEMatch -> ShowS)
-> (CPEMatch -> String) -> ([CPEMatch] -> ShowS) -> Show CPEMatch
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CPEMatch] -> ShowS
$cshowList :: [CPEMatch] -> ShowS
show :: CPEMatch -> String
$cshow :: CPEMatch -> String
showsPrec :: Int -> CPEMatch -> ShowS
$cshowsPrec :: Int -> CPEMatch -> ShowS
Show, CPEMatch -> CPEMatch -> Bool
(CPEMatch -> CPEMatch -> Bool)
-> (CPEMatch -> CPEMatch -> Bool) -> Eq CPEMatch
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CPEMatch -> CPEMatch -> Bool
$c/= :: CPEMatch -> CPEMatch -> Bool
== :: CPEMatch -> CPEMatch -> Bool
$c== :: CPEMatch -> CPEMatch -> Bool
Eq, Eq CPEMatch
Eq CPEMatch
-> (CPEMatch -> CPEMatch -> Ordering)
-> (CPEMatch -> CPEMatch -> Bool)
-> (CPEMatch -> CPEMatch -> Bool)
-> (CPEMatch -> CPEMatch -> Bool)
-> (CPEMatch -> CPEMatch -> Bool)
-> (CPEMatch -> CPEMatch -> CPEMatch)
-> (CPEMatch -> CPEMatch -> CPEMatch)
-> Ord CPEMatch
CPEMatch -> CPEMatch -> Bool
CPEMatch -> CPEMatch -> Ordering
CPEMatch -> CPEMatch -> CPEMatch
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CPEMatch -> CPEMatch -> CPEMatch
$cmin :: CPEMatch -> CPEMatch -> CPEMatch
max :: CPEMatch -> CPEMatch -> CPEMatch
$cmax :: CPEMatch -> CPEMatch -> CPEMatch
>= :: CPEMatch -> CPEMatch -> Bool
$c>= :: CPEMatch -> CPEMatch -> Bool
> :: CPEMatch -> CPEMatch -> Bool
$c> :: CPEMatch -> CPEMatch -> Bool
<= :: CPEMatch -> CPEMatch -> Bool
$c<= :: CPEMatch -> CPEMatch -> Bool
< :: CPEMatch -> CPEMatch -> Bool
$c< :: CPEMatch -> CPEMatch -> Bool
compare :: CPEMatch -> CPEMatch -> Ordering
$ccompare :: CPEMatch -> CPEMatch -> Ordering
$cp1Ord :: Eq CPEMatch
Ord)
instance FromRow CPEMatch where
fromRow :: RowParser CPEMatch
fromRow = do
CPE
cpeMatchCPE <- RowParser CPE
forall a. FromRow a => RowParser a
fromRow
let cpeMatchVulnerable :: Bool
cpeMatchVulnerable = Bool
True
VersionMatcher
cpeMatchVersionMatcher <- RowParser VersionMatcher
forall a. FromField a => RowParser a
field
CPEMatch -> RowParser CPEMatch
forall (f :: * -> *) a. Applicative f => a -> f a
pure CPEMatch :: CPE -> Bool -> VersionMatcher -> CPEMatch
CPEMatch {Bool
VersionMatcher
CPE
cpeMatchVersionMatcher :: VersionMatcher
cpeMatchVulnerable :: Bool
cpeMatchCPE :: CPE
cpeMatchVersionMatcher :: VersionMatcher
cpeMatchVulnerable :: Bool
cpeMatchCPE :: CPE
..}
data CPE = CPE
{ CPE -> Maybe CVEID
cpePart :: (Maybe Text),
CPE -> Maybe CVEID
cpeVendor :: (Maybe Text),
CPE -> Maybe CVEID
cpeProduct :: (Maybe Text),
CPE -> Maybe CVEID
cpeVersion :: (Maybe Text),
CPE -> Maybe CVEID
cpeUpdate :: (Maybe Text),
CPE -> Maybe CVEID
cpeEdition :: (Maybe Text),
CPE -> Maybe CVEID
cpeLanguage :: (Maybe Text),
CPE -> Maybe CVEID
cpeSoftwareEdition :: (Maybe Text),
CPE -> Maybe CVEID
cpeTargetSoftware :: (Maybe Text),
CPE -> Maybe CVEID
cpeTargetHardware :: (Maybe Text),
CPE -> Maybe CVEID
cpeOther :: (Maybe Text)
}
deriving (CPE -> CPE -> Bool
(CPE -> CPE -> Bool) -> (CPE -> CPE -> Bool) -> Eq CPE
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CPE -> CPE -> Bool
$c/= :: CPE -> CPE -> Bool
== :: CPE -> CPE -> Bool
$c== :: CPE -> CPE -> Bool
Eq, Eq CPE
Eq CPE
-> (CPE -> CPE -> Ordering)
-> (CPE -> CPE -> Bool)
-> (CPE -> CPE -> Bool)
-> (CPE -> CPE -> Bool)
-> (CPE -> CPE -> Bool)
-> (CPE -> CPE -> CPE)
-> (CPE -> CPE -> CPE)
-> Ord CPE
CPE -> CPE -> Bool
CPE -> CPE -> Ordering
CPE -> CPE -> CPE
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CPE -> CPE -> CPE
$cmin :: CPE -> CPE -> CPE
max :: CPE -> CPE -> CPE
$cmax :: CPE -> CPE -> CPE
>= :: CPE -> CPE -> Bool
$c>= :: CPE -> CPE -> Bool
> :: CPE -> CPE -> Bool
$c> :: CPE -> CPE -> Bool
<= :: CPE -> CPE -> Bool
$c<= :: CPE -> CPE -> Bool
< :: CPE -> CPE -> Bool
$c< :: CPE -> CPE -> Bool
compare :: CPE -> CPE -> Ordering
$ccompare :: CPE -> CPE -> Ordering
$cp1Ord :: Eq CPE
Ord)
instance Show CPE where
show :: CPE -> String
show
CPE
{ Maybe CVEID
cpePart :: Maybe CVEID
cpePart :: CPE -> Maybe CVEID
cpePart,
Maybe CVEID
cpeVendor :: Maybe CVEID
cpeVendor :: CPE -> Maybe CVEID
cpeVendor,
Maybe CVEID
cpeProduct :: Maybe CVEID
cpeProduct :: CPE -> Maybe CVEID
cpeProduct,
Maybe CVEID
cpeVersion :: Maybe CVEID
cpeVersion :: CPE -> Maybe CVEID
cpeVersion,
Maybe CVEID
cpeUpdate :: Maybe CVEID
cpeUpdate :: CPE -> Maybe CVEID
cpeUpdate,
Maybe CVEID
cpeEdition :: Maybe CVEID
cpeEdition :: CPE -> Maybe CVEID
cpeEdition,
Maybe CVEID
cpeLanguage :: Maybe CVEID
cpeLanguage :: CPE -> Maybe CVEID
cpeLanguage,
Maybe CVEID
cpeSoftwareEdition :: Maybe CVEID
cpeSoftwareEdition :: CPE -> Maybe CVEID
cpeSoftwareEdition,
Maybe CVEID
cpeTargetSoftware :: Maybe CVEID
cpeTargetSoftware :: CPE -> Maybe CVEID
cpeTargetSoftware,
Maybe CVEID
cpeTargetHardware :: Maybe CVEID
cpeTargetHardware :: CPE -> Maybe CVEID
cpeTargetHardware,
Maybe CVEID
cpeOther :: Maybe CVEID
cpeOther :: CPE -> Maybe CVEID
cpeOther
} =
String
"CPE {"
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> (String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ([String] -> String)
-> ([[String]] -> [String]) -> [[String]] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat)
[ String -> Maybe CVEID -> [String]
forall a. Show a => String -> Maybe a -> [String]
cpeField String
"part" Maybe CVEID
cpePart,
String -> Maybe CVEID -> [String]
forall a. Show a => String -> Maybe a -> [String]
cpeField String
"vendor" Maybe CVEID
cpeVendor,
String -> Maybe CVEID -> [String]
forall a. Show a => String -> Maybe a -> [String]
cpeField String
"product" Maybe CVEID
cpeProduct,
String -> Maybe CVEID -> [String]
forall a. Show a => String -> Maybe a -> [String]
cpeField String
"version" Maybe CVEID
cpeVersion,
String -> Maybe CVEID -> [String]
forall a. Show a => String -> Maybe a -> [String]
cpeField String
"update" Maybe CVEID
cpeUpdate,
String -> Maybe CVEID -> [String]
forall a. Show a => String -> Maybe a -> [String]
cpeField String
"edition" Maybe CVEID
cpeEdition,
String -> Maybe CVEID -> [String]
forall a. Show a => String -> Maybe a -> [String]
cpeField String
"language" Maybe CVEID
cpeLanguage,
String -> Maybe CVEID -> [String]
forall a. Show a => String -> Maybe a -> [String]
cpeField String
"softwareEdition" Maybe CVEID
cpeSoftwareEdition,
String -> Maybe CVEID -> [String]
forall a. Show a => String -> Maybe a -> [String]
cpeField String
"targetSoftware" Maybe CVEID
cpeTargetSoftware,
String -> Maybe CVEID -> [String]
forall a. Show a => String -> Maybe a -> [String]
cpeField String
"targetHardware" Maybe CVEID
cpeTargetHardware,
String -> Maybe CVEID -> [String]
forall a. Show a => String -> Maybe a -> [String]
cpeField String
"other" Maybe CVEID
cpeOther
]
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"}"
where
cpeField :: Show a => String -> Maybe a -> [String]
cpeField :: String -> Maybe a -> [String]
cpeField String
_ Maybe a
Nothing = []
cpeField String
name (Just a
value) = [String
name String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" = " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
value]
instance ToRow CPE where
toRow :: CPE -> [SQLData]
toRow
CPE
{ Maybe CVEID
cpePart :: Maybe CVEID
cpePart :: CPE -> Maybe CVEID
cpePart,
Maybe CVEID
cpeVendor :: Maybe CVEID
cpeVendor :: CPE -> Maybe CVEID
cpeVendor,
Maybe CVEID
cpeProduct :: Maybe CVEID
cpeProduct :: CPE -> Maybe CVEID
cpeProduct,
Maybe CVEID
cpeVersion :: Maybe CVEID
cpeVersion :: CPE -> Maybe CVEID
cpeVersion,
Maybe CVEID
cpeUpdate :: Maybe CVEID
cpeUpdate :: CPE -> Maybe CVEID
cpeUpdate,
Maybe CVEID
cpeEdition :: Maybe CVEID
cpeEdition :: CPE -> Maybe CVEID
cpeEdition,
Maybe CVEID
cpeLanguage :: Maybe CVEID
cpeLanguage :: CPE -> Maybe CVEID
cpeLanguage,
Maybe CVEID
cpeSoftwareEdition :: Maybe CVEID
cpeSoftwareEdition :: CPE -> Maybe CVEID
cpeSoftwareEdition,
Maybe CVEID
cpeTargetSoftware :: Maybe CVEID
cpeTargetSoftware :: CPE -> Maybe CVEID
cpeTargetSoftware,
Maybe CVEID
cpeTargetHardware :: Maybe CVEID
cpeTargetHardware :: CPE -> Maybe CVEID
cpeTargetHardware,
Maybe CVEID
cpeOther :: Maybe CVEID
cpeOther :: CPE -> Maybe CVEID
cpeOther
} =
(Maybe CVEID -> SQLData) -> [Maybe CVEID] -> [SQLData]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
Maybe CVEID -> SQLData
forall a. ToField a => a -> SQLData
toField
[ Maybe CVEID
cpePart,
Maybe CVEID
cpeVendor,
Maybe CVEID
cpeProduct,
Maybe CVEID
cpeVersion,
Maybe CVEID
cpeUpdate,
Maybe CVEID
cpeEdition,
Maybe CVEID
cpeLanguage,
Maybe CVEID
cpeSoftwareEdition,
Maybe CVEID
cpeTargetSoftware,
Maybe CVEID
cpeTargetHardware,
Maybe CVEID
cpeOther
]
instance FromRow CPE where
fromRow :: RowParser CPE
fromRow = do
Maybe CVEID
cpePart <- RowParser (Maybe CVEID)
forall a. FromField a => RowParser a
field
Maybe CVEID
cpeVendor <- RowParser (Maybe CVEID)
forall a. FromField a => RowParser a
field
Maybe CVEID
cpeProduct <- RowParser (Maybe CVEID)
forall a. FromField a => RowParser a
field
Maybe CVEID
cpeVersion <- RowParser (Maybe CVEID)
forall a. FromField a => RowParser a
field
Maybe CVEID
cpeUpdate <- RowParser (Maybe CVEID)
forall a. FromField a => RowParser a
field
Maybe CVEID
cpeEdition <- RowParser (Maybe CVEID)
forall a. FromField a => RowParser a
field
Maybe CVEID
cpeLanguage <- RowParser (Maybe CVEID)
forall a. FromField a => RowParser a
field
Maybe CVEID
cpeSoftwareEdition <- RowParser (Maybe CVEID)
forall a. FromField a => RowParser a
field
Maybe CVEID
cpeTargetSoftware <- RowParser (Maybe CVEID)
forall a. FromField a => RowParser a
field
Maybe CVEID
cpeTargetHardware <- RowParser (Maybe CVEID)
forall a. FromField a => RowParser a
field
Maybe CVEID
cpeOther <- RowParser (Maybe CVEID)
forall a. FromField a => RowParser a
field
CPE -> RowParser CPE
forall (f :: * -> *) a. Applicative f => a -> f a
pure CPE :: Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> CPE
CPE {Maybe CVEID
cpeOther :: Maybe CVEID
cpeTargetHardware :: Maybe CVEID
cpeTargetSoftware :: Maybe CVEID
cpeSoftwareEdition :: Maybe CVEID
cpeLanguage :: Maybe CVEID
cpeEdition :: Maybe CVEID
cpeUpdate :: Maybe CVEID
cpeVersion :: Maybe CVEID
cpeProduct :: Maybe CVEID
cpeVendor :: Maybe CVEID
cpePart :: Maybe CVEID
cpeOther :: Maybe CVEID
cpeTargetHardware :: Maybe CVEID
cpeTargetSoftware :: Maybe CVEID
cpeSoftwareEdition :: Maybe CVEID
cpeLanguage :: Maybe CVEID
cpeEdition :: Maybe CVEID
cpeUpdate :: Maybe CVEID
cpeVersion :: Maybe CVEID
cpeProduct :: Maybe CVEID
cpeVendor :: Maybe CVEID
cpePart :: Maybe CVEID
..}
parseDescription :: Object -> Parser Text
parseDescription :: Object -> Parser CVEID
parseDescription Object
o = do
[Object]
dData <- Object
o Object -> CVEID -> Parser [Object]
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"description_data"
[CVEID]
descriptions <-
([[CVEID]] -> [CVEID]) -> Parser [[CVEID]] -> Parser [CVEID]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[CVEID]] -> [CVEID]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (Parser [[CVEID]] -> Parser [CVEID])
-> Parser [[CVEID]] -> Parser [CVEID]
forall a b. (a -> b) -> a -> b
$
[Parser [CVEID]] -> Parser [[CVEID]]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([Parser [CVEID]] -> Parser [[CVEID]])
-> [Parser [CVEID]] -> Parser [[CVEID]]
forall a b. (a -> b) -> a -> b
$
((Object -> Parser [CVEID]) -> [Object] -> [Parser [CVEID]])
-> [Object] -> (Object -> Parser [CVEID]) -> [Parser [CVEID]]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Object -> Parser [CVEID]) -> [Object] -> [Parser [CVEID]]
forall a b. (a -> b) -> [a] -> [b]
map [Object]
dData ((Object -> Parser [CVEID]) -> [Parser [CVEID]])
-> (Object -> Parser [CVEID]) -> [Parser [CVEID]]
forall a b. (a -> b) -> a -> b
$
\Object
dDatum -> do
CVEID
value <- Object
dDatum Object -> CVEID -> Parser CVEID
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"value"
CVEID
lang :: Text <- Object
dDatum Object -> CVEID -> Parser CVEID
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"lang"
[CVEID] -> Parser [CVEID]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([CVEID] -> Parser [CVEID]) -> [CVEID] -> Parser [CVEID]
forall a b. (a -> b) -> a -> b
$
case CVEID
lang of
CVEID
"en" -> [CVEID
value]
CVEID
_ -> []
CVEID -> Parser CVEID
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CVEID -> Parser CVEID) -> CVEID -> Parser CVEID
forall a b. (a -> b) -> a -> b
$ CVEID -> [CVEID] -> CVEID
T.intercalate CVEID
"\n\n" [CVEID]
descriptions
instance FromJSON CVE where
parseJSON :: Value -> Parser CVE
parseJSON =
String -> (Object -> Parser CVE) -> Value -> Parser CVE
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"CVE" ((Object -> Parser CVE) -> Value -> Parser CVE)
-> (Object -> Parser CVE) -> Value -> Parser CVE
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
Object
cve <- Object
o Object -> CVEID -> Parser Object
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"cve"
Object
meta <- Object
cve Object -> CVEID -> Parser Object
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"CVE_data_meta"
CVEID
cveID <- Object
meta Object -> CVEID -> Parser CVEID
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"ID"
String -> Parser CVE -> Parser CVE
forall a. String -> Parser a -> Parser a
prependFailure (CVEID -> String
T.unpack CVEID
cveID String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
": ") (Parser CVE -> Parser CVE) -> Parser CVE -> Parser CVE
forall a b. (a -> b) -> a -> b
$ do
Object
cfgs <- Object
o Object -> CVEID -> Parser Object
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"configurations"
[CPEMatch]
cveCPEMatches <- Object -> Parser [CPEMatch]
parseConfigurations Object
cfgs
UTCTime
cvePublished <- Object
o Object -> CVEID -> Parser UTCTime
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"publishedDate"
UTCTime
cveLastModified <- Object
o Object -> CVEID -> Parser UTCTime
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"lastModifiedDate"
Object
description <- Object
cve Object -> CVEID -> Parser Object
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"description"
CVEID
cveDescription <- Object -> Parser CVEID
parseDescription Object
description
CVE -> Parser CVE
forall (f :: * -> *) a. Applicative f => a -> f a
pure CVE :: CVEID -> [CPEMatch] -> CVEID -> UTCTime -> UTCTime -> CVE
CVE {[CPEMatch]
CVEID
UTCTime
cveDescription :: CVEID
cveLastModified :: UTCTime
cvePublished :: UTCTime
cveCPEMatches :: [CPEMatch]
cveID :: CVEID
cveLastModified :: UTCTime
cvePublished :: UTCTime
cveDescription :: CVEID
cveCPEMatches :: [CPEMatch]
cveID :: CVEID
..}
instance ToRow CVE where
toRow :: CVE -> [SQLData]
toRow CVE {CVEID
cveID :: CVEID
cveID :: CVE -> CVEID
cveID, CVEID
cveDescription :: CVEID
cveDescription :: CVE -> CVEID
cveDescription, UTCTime
cvePublished :: UTCTime
cvePublished :: CVE -> UTCTime
cvePublished, UTCTime
cveLastModified :: UTCTime
cveLastModified :: CVE -> UTCTime
cveLastModified} =
(CVEID, CVEID, UTCTime, UTCTime) -> [SQLData]
forall a. ToRow a => a -> [SQLData]
toRow (CVEID
cveID, CVEID
cveDescription, UTCTime
cvePublished, UTCTime
cveLastModified)
instance FromRow CVE where
fromRow :: RowParser CVE
fromRow = do
let cveCPEMatches :: [a]
cveCPEMatches = []
CVEID
cveID <- RowParser CVEID
forall a. FromField a => RowParser a
field
CVEID
cveDescription <- RowParser CVEID
forall a. FromField a => RowParser a
field
UTCTime
cvePublished <- RowParser UTCTime
forall a. FromField a => RowParser a
field
UTCTime
cveLastModified <- RowParser UTCTime
forall a. FromField a => RowParser a
field
CVE -> RowParser CVE
forall (f :: * -> *) a. Applicative f => a -> f a
pure CVE :: CVEID -> [CPEMatch] -> CVEID -> UTCTime -> UTCTime -> CVE
CVE {[CPEMatch]
CVEID
UTCTime
forall a. [a]
cveLastModified :: UTCTime
cvePublished :: UTCTime
cveDescription :: CVEID
cveID :: CVEID
cveCPEMatches :: forall a. [a]
cveLastModified :: UTCTime
cvePublished :: UTCTime
cveDescription :: CVEID
cveCPEMatches :: [CPEMatch]
cveID :: CVEID
..}
splitCPE :: Text -> [Maybe Text]
splitCPE :: CVEID -> [Maybe CVEID]
splitCPE =
(CVEID -> Maybe CVEID) -> [CVEID] -> [Maybe CVEID]
forall a b. (a -> b) -> [a] -> [b]
map (CVEID -> Maybe CVEID
forall a. (Eq a, IsString a) => a -> Maybe a
toMaybe (CVEID -> Maybe CVEID) -> (CVEID -> CVEID) -> CVEID -> Maybe CVEID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CVEID -> CVEID -> CVEID -> CVEID
T.replace CVEID
"\a" CVEID
":") ([CVEID] -> [Maybe CVEID])
-> (CVEID -> [CVEID]) -> CVEID -> [Maybe CVEID]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CVEID -> CVEID -> [CVEID]
T.splitOn CVEID
":" (CVEID -> [CVEID]) -> (CVEID -> CVEID) -> CVEID -> [CVEID]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CVEID -> CVEID -> CVEID -> CVEID
T.replace CVEID
"\\:" CVEID
"\a"
where
toMaybe :: a -> Maybe a
toMaybe a
"*" = Maybe a
forall a. Maybe a
Nothing
toMaybe a
x = a -> Maybe a
forall a. a -> Maybe a
Just a
x
instance FromJSON CPEMatch where
parseJSON :: Value -> Parser CPEMatch
parseJSON =
String -> (Object -> Parser CPEMatch) -> Value -> Parser CPEMatch
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"CPEMatch" ((Object -> Parser CPEMatch) -> Value -> Parser CPEMatch)
-> (Object -> Parser CPEMatch) -> Value -> Parser CPEMatch
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
CVEID
t <- Object
o Object -> CVEID -> Parser CVEID
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"cpe23Uri"
CPE
cpeMatchCPE <-
case CVEID -> [Maybe CVEID]
splitCPE CVEID
t of
[Just CVEID
"cpe", Just CVEID
"2.3", Maybe CVEID
cpePart, Maybe CVEID
cpeVendor, Maybe CVEID
cpeProduct, Maybe CVEID
cpeVersion, Maybe CVEID
cpeUpdate, Maybe CVEID
cpeEdition, Maybe CVEID
cpeLanguage, Maybe CVEID
cpeSoftwareEdition, Maybe CVEID
cpeTargetSoftware, Maybe CVEID
cpeTargetHardware, Maybe CVEID
cpeOther] ->
CPE -> Parser CPE
forall (f :: * -> *) a. Applicative f => a -> f a
pure CPE :: Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> Maybe CVEID
-> CPE
CPE {Maybe CVEID
cpeOther :: Maybe CVEID
cpeTargetHardware :: Maybe CVEID
cpeTargetSoftware :: Maybe CVEID
cpeSoftwareEdition :: Maybe CVEID
cpeLanguage :: Maybe CVEID
cpeEdition :: Maybe CVEID
cpeUpdate :: Maybe CVEID
cpeVersion :: Maybe CVEID
cpeProduct :: Maybe CVEID
cpeVendor :: Maybe CVEID
cpePart :: Maybe CVEID
cpeOther :: Maybe CVEID
cpeTargetHardware :: Maybe CVEID
cpeTargetSoftware :: Maybe CVEID
cpeSoftwareEdition :: Maybe CVEID
cpeLanguage :: Maybe CVEID
cpeEdition :: Maybe CVEID
cpeUpdate :: Maybe CVEID
cpeVersion :: Maybe CVEID
cpeProduct :: Maybe CVEID
cpeVendor :: Maybe CVEID
cpePart :: Maybe CVEID
..}
[Maybe CVEID]
_ -> String -> Parser CPE
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser CPE) -> String -> Parser CPE
forall a b. (a -> b) -> a -> b
$ String
"unparsable cpe23Uri: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> CVEID -> String
T.unpack CVEID
t
Bool
cpeMatchVulnerable <- Object
o Object -> CVEID -> Parser Bool
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"vulnerable"
Maybe CVEID
vStartIncluding <- Object
o Object -> CVEID -> Parser (Maybe CVEID)
forall a. FromJSON a => Object -> CVEID -> Parser (Maybe a)
.:! CVEID
"versionStartIncluding"
Maybe CVEID
vEndIncluding <- Object
o Object -> CVEID -> Parser (Maybe CVEID)
forall a. FromJSON a => Object -> CVEID -> Parser (Maybe a)
.:! CVEID
"versionEndIncluding"
Maybe CVEID
vStartExcluding <- Object
o Object -> CVEID -> Parser (Maybe CVEID)
forall a. FromJSON a => Object -> CVEID -> Parser (Maybe a)
.:! CVEID
"versionStartExcluding"
Maybe CVEID
vEndExcluding <- Object
o Object -> CVEID -> Parser (Maybe CVEID)
forall a. FromJSON a => Object -> CVEID -> Parser (Maybe a)
.:! CVEID
"versionEndExcluding"
Boundary CVEID
startBoundary <-
case (Maybe CVEID
vStartIncluding, Maybe CVEID
vStartExcluding) of
(Maybe CVEID
Nothing, Maybe CVEID
Nothing) -> Boundary CVEID -> Parser (Boundary CVEID)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Boundary CVEID
forall a. Boundary a
Unbounded
(Just CVEID
start, Maybe CVEID
Nothing) -> Boundary CVEID -> Parser (Boundary CVEID)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CVEID -> Boundary CVEID
forall a. a -> Boundary a
Including CVEID
start)
(Maybe CVEID
Nothing, Just CVEID
start) -> Boundary CVEID -> Parser (Boundary CVEID)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CVEID -> Boundary CVEID
forall a. a -> Boundary a
Excluding CVEID
start)
(Just CVEID
_, Just CVEID
_) -> String -> Parser (Boundary CVEID)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"multiple version starts"
Boundary CVEID
endBoundary <-
case (Maybe CVEID
vEndIncluding, Maybe CVEID
vEndExcluding) of
(Maybe CVEID
Nothing, Maybe CVEID
Nothing) -> Boundary CVEID -> Parser (Boundary CVEID)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Boundary CVEID
forall a. Boundary a
Unbounded
(Just CVEID
end, Maybe CVEID
Nothing) -> Boundary CVEID -> Parser (Boundary CVEID)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CVEID -> Boundary CVEID
forall a. a -> Boundary a
Including CVEID
end)
(Maybe CVEID
Nothing, Just CVEID
end) -> Boundary CVEID -> Parser (Boundary CVEID)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CVEID -> Boundary CVEID
forall a. a -> Boundary a
Excluding CVEID
end)
(Just CVEID
_, Just CVEID
_) -> String -> Parser (Boundary CVEID)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"multiple version ends"
VersionMatcher
cpeMatchVersionMatcher <-
case (CPE -> Maybe CVEID
cpeVersion CPE
cpeMatchCPE, Boundary CVEID
startBoundary, Boundary CVEID
endBoundary) of
(Just CVEID
v, Boundary CVEID
Unbounded, Boundary CVEID
Unbounded) -> VersionMatcher -> Parser VersionMatcher
forall (f :: * -> *) a. Applicative f => a -> f a
pure (VersionMatcher -> Parser VersionMatcher)
-> VersionMatcher -> Parser VersionMatcher
forall a b. (a -> b) -> a -> b
$ CVEID -> VersionMatcher
SingleMatcher CVEID
v
(Maybe CVEID
Nothing, Boundary CVEID
start, Boundary CVEID
end) -> VersionMatcher -> Parser VersionMatcher
forall (f :: * -> *) a. Applicative f => a -> f a
pure (VersionMatcher -> Parser VersionMatcher)
-> VersionMatcher -> Parser VersionMatcher
forall a b. (a -> b) -> a -> b
$ Boundary CVEID -> Boundary CVEID -> VersionMatcher
RangeMatcher Boundary CVEID
start Boundary CVEID
end
(Maybe CVEID, Boundary CVEID, Boundary CVEID)
_ ->
String -> Parser VersionMatcher
forall (m :: * -> *) a. MonadFail m => String -> m a
fail
( String
"cpe_match has both version "
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Maybe CVEID -> String
forall a. Show a => a -> String
show (CPE -> Maybe CVEID
cpeVersion CPE
cpeMatchCPE)
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" in cpe, and boundaries from "
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Boundary CVEID -> String
forall a. Show a => a -> String
show Boundary CVEID
startBoundary
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" to "
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Boundary CVEID -> String
forall a. Show a => a -> String
show Boundary CVEID
endBoundary
)
CPEMatch -> Parser CPEMatch
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CPEMatch :: CPE -> Bool -> VersionMatcher -> CPEMatch
CPEMatch {Bool
VersionMatcher
CPE
cpeMatchVersionMatcher :: VersionMatcher
cpeMatchVulnerable :: Bool
cpeMatchCPE :: CPE
cpeMatchVersionMatcher :: VersionMatcher
cpeMatchVulnerable :: Bool
cpeMatchCPE :: CPE
..})
data CPEMatchRow
= CPEMatchRow CVE CPEMatch
instance ToRow CPEMatchRow where
toRow :: CPEMatchRow -> [SQLData]
toRow (CPEMatchRow CVE {CVEID
cveID :: CVEID
cveID :: CVE -> CVEID
cveID} CPEMatch {CPE
cpeMatchCPE :: CPE
cpeMatchCPE :: CPEMatch -> CPE
cpeMatchCPE, VersionMatcher
cpeMatchVersionMatcher :: VersionMatcher
cpeMatchVersionMatcher :: CPEMatch -> VersionMatcher
cpeMatchVersionMatcher}) =
[Maybe CVEID -> SQLData
forall a. ToField a => a -> SQLData
toField (Maybe CVEID -> SQLData) -> Maybe CVEID -> SQLData
forall a b. (a -> b) -> a -> b
$ CVEID -> Maybe CVEID
forall a. a -> Maybe a
Just CVEID
cveID]
[SQLData] -> [SQLData] -> [SQLData]
forall a. [a] -> [a] -> [a]
++ CPE -> [SQLData]
forall a. ToRow a => a -> [SQLData]
toRow CPE
cpeMatchCPE
[SQLData] -> [SQLData] -> [SQLData]
forall a. [a] -> [a] -> [a]
++ [VersionMatcher -> SQLData
forall a. ToField a => a -> SQLData
toField VersionMatcher
cpeMatchVersionMatcher]
instance FromRow CPEMatchRow where
fromRow :: RowParser CPEMatchRow
fromRow = do
let cveCPEMatches :: [a]
cveCPEMatches = []
let cveDescription :: a
cveDescription = a
forall a. HasCallStack => a
undefined
let cvePublished :: a
cvePublished = a
forall a. HasCallStack => a
undefined
let cveLastModified :: a
cveLastModified = a
forall a. HasCallStack => a
undefined
CVEID
cveID <- RowParser CVEID
forall a. FromField a => RowParser a
field
CPEMatch
cpeM <- RowParser CPEMatch
forall a. FromRow a => RowParser a
fromRow
CPEMatchRow -> RowParser CPEMatchRow
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CPEMatchRow -> RowParser CPEMatchRow)
-> CPEMatchRow -> RowParser CPEMatchRow
forall a b. (a -> b) -> a -> b
$ CVE -> CPEMatch -> CPEMatchRow
CPEMatchRow (CVE :: CVEID -> [CPEMatch] -> CVEID -> UTCTime -> UTCTime -> CVE
CVE {[CPEMatch]
CVEID
UTCTime
forall a. a
forall a. [a]
cveID :: CVEID
cveLastModified :: forall a. a
cvePublished :: forall a. a
cveDescription :: forall a. a
cveCPEMatches :: forall a. [a]
cveLastModified :: UTCTime
cvePublished :: UTCTime
cveDescription :: CVEID
cveCPEMatches :: [CPEMatch]
cveID :: CVEID
..}) CPEMatch
cpeM
cpeMatches :: [CVE] -> [CPEMatchRow]
cpeMatches :: [CVE] -> [CPEMatchRow]
cpeMatches = (CVE -> [CPEMatchRow]) -> [CVE] -> [CPEMatchRow]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap CVE -> [CPEMatchRow]
rows
where
rows :: CVE -> [CPEMatchRow]
rows CVE
cve = (CPEMatch -> CPEMatchRow) -> [CPEMatch] -> [CPEMatchRow]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (CVE -> CPEMatch -> CPEMatchRow
CPEMatchRow CVE
cve) (CVE -> [CPEMatch]
cveCPEMatches CVE
cve)
guardAttr :: (Eq a, FromJSON a, Show a) => Object -> Text -> a -> Parser ()
guardAttr :: Object -> CVEID -> a -> Parser ()
guardAttr Object
object CVEID
attribute a
expected = do
a
actual <- Object
object Object -> CVEID -> Parser a
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
attribute
Bool -> Parser () -> Parser ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (a
actual a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
expected) (Parser () -> Parser ()) -> Parser () -> Parser ()
forall a b. (a -> b) -> a -> b
$
String -> Parser ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser ()) -> String -> Parser ()
forall a b. (a -> b) -> a -> b
$
String
"unexpected "
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> CVEID -> String
T.unpack CVEID
attribute
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
", expected "
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
expected
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
", got "
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
actual
boundedMatcher :: VersionMatcher -> Bool
boundedMatcher :: VersionMatcher -> Bool
boundedMatcher (RangeMatcher Boundary CVEID
Unbounded Boundary CVEID
Unbounded) = Bool
False
boundedMatcher VersionMatcher
_ = Bool
True
parseNode :: Object -> Parser [CPEMatch]
parseNode :: Object -> Parser [CPEMatch]
parseNode Object
node = do
Maybe [Object]
maybeChildren <- Object
node Object -> CVEID -> Parser (Maybe [Object])
forall a. FromJSON a => Object -> CVEID -> Parser (Maybe a)
.:! CVEID
"children"
case Maybe [Object]
maybeChildren of
Maybe [Object]
Nothing -> do
[CPEMatch]
matches <- Object
node Object -> CVEID -> Parser (Maybe [CPEMatch])
forall a. FromJSON a => Object -> CVEID -> Parser (Maybe a)
.:! CVEID
"cpe_match" Parser (Maybe [CPEMatch]) -> [CPEMatch] -> Parser [CPEMatch]
forall a. Parser (Maybe a) -> a -> Parser a
.!= []
[CPEMatch] -> Parser [CPEMatch]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([CPEMatch] -> Parser [CPEMatch])
-> [CPEMatch] -> Parser [CPEMatch]
forall a b. (a -> b) -> a -> b
$
(CPEMatch -> Bool) -> [CPEMatch] -> [CPEMatch]
forall a. (a -> Bool) -> [a] -> [a]
filter (CPEMatch -> VersionMatcher
cpeMatchVersionMatcher (CPEMatch -> VersionMatcher)
-> (VersionMatcher -> Bool) -> CPEMatch -> Bool
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> VersionMatcher -> Bool
boundedMatcher) ([CPEMatch] -> [CPEMatch]) -> [CPEMatch] -> [CPEMatch]
forall a b. (a -> b) -> a -> b
$
(CPEMatch -> Bool) -> [CPEMatch] -> [CPEMatch]
forall a. (a -> Bool) -> [a] -> [a]
filter CPEMatch -> Bool
cpeMatchVulnerable [CPEMatch]
matches
Just [Object]
children -> do
([[CPEMatch]] -> [CPEMatch])
-> Parser [[CPEMatch]] -> Parser [CPEMatch]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[CPEMatch]] -> [CPEMatch]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (Parser [[CPEMatch]] -> Parser [CPEMatch])
-> Parser [[CPEMatch]] -> Parser [CPEMatch]
forall a b. (a -> b) -> a -> b
$ [Parser [CPEMatch]] -> Parser [[CPEMatch]]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([Parser [CPEMatch]] -> Parser [[CPEMatch]])
-> [Parser [CPEMatch]] -> Parser [[CPEMatch]]
forall a b. (a -> b) -> a -> b
$ (Object -> Parser [CPEMatch]) -> [Object] -> [Parser [CPEMatch]]
forall a b. (a -> b) -> [a] -> [b]
map Object -> Parser [CPEMatch]
parseNode [Object]
children
parseConfigurations :: Object -> Parser [CPEMatch]
parseConfigurations :: Object -> Parser [CPEMatch]
parseConfigurations Object
o = do
Object -> CVEID -> CVEID -> Parser ()
forall a.
(Eq a, FromJSON a, Show a) =>
Object -> CVEID -> a -> Parser ()
guardAttr Object
o CVEID
"CVE_data_version" (CVEID
"4.0" :: Text)
[Object]
nodes <- Object
o Object -> CVEID -> Parser [Object]
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"nodes"
([[CPEMatch]] -> [CPEMatch])
-> Parser [[CPEMatch]] -> Parser [CPEMatch]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[CPEMatch]] -> [CPEMatch]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (Parser [[CPEMatch]] -> Parser [CPEMatch])
-> Parser [[CPEMatch]] -> Parser [CPEMatch]
forall a b. (a -> b) -> a -> b
$ [Parser [CPEMatch]] -> Parser [[CPEMatch]]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([Parser [CPEMatch]] -> Parser [[CPEMatch]])
-> [Parser [CPEMatch]] -> Parser [[CPEMatch]]
forall a b. (a -> b) -> a -> b
$ (Object -> Parser [CPEMatch]) -> [Object] -> [Parser [CPEMatch]]
forall a b. (a -> b) -> [a] -> [b]
map Object -> Parser [CPEMatch]
parseNode [Object]
nodes
parseFeed :: BSL.ByteString -> Either Text [CVE]
parseFeed :: ByteString -> Either CVEID [CVE]
parseFeed = (String -> CVEID)
-> (CVEFeed -> [CVE])
-> Either String CVEFeed
-> Either CVEID [CVE]
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap String -> CVEID
T.pack CVEFeed -> [CVE]
cvefItems (Either String CVEFeed -> Either CVEID [CVE])
-> (ByteString -> Either String CVEFeed)
-> ByteString
-> Either CVEID [CVE]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String CVEFeed
forall a. FromJSON a => ByteString -> Either String a
eitherDecode
data CVEFeed = CVEFeed
{ CVEFeed -> [CVE]
cvefItems :: [CVE]
}
instance FromJSON CVEFeed where
parseJSON :: Value -> Parser CVEFeed
parseJSON = String -> (Object -> Parser CVEFeed) -> Value -> Parser CVEFeed
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"CVEFeed" ((Object -> Parser CVEFeed) -> Value -> Parser CVEFeed)
-> (Object -> Parser CVEFeed) -> Value -> Parser CVEFeed
forall a b. (a -> b) -> a -> b
$ \Object
o -> [CVE] -> CVEFeed
CVEFeed ([CVE] -> CVEFeed) -> Parser [CVE] -> Parser CVEFeed
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> CVEID -> Parser [CVE]
forall a. FromJSON a => Object -> CVEID -> Parser a
.: CVEID
"CVE_Items"