packages feed

iptadmin-1.0.0: src/IptAdmin/EditForm/Render.hs

{-# LANGUAGE OverloadedStrings #-}

module IptAdmin.EditForm.Render where

import Data.Monoid
import Data.Set (member)
import Data.String
import IptAdmin.EditForm.Class
import IptAdmin.EditForm.Types
import Iptables.Types
import Text.Blaze
import qualified Text.Blaze.Html5 as H
import qualified Text.Blaze.Html5.Attributes as A

checkBox :: String -> Bool -> Html
checkBox name on = do
    let chBox = H.input ! A.type_ "checkbox" ! A.name (fromString name) ! A.value "on"
    if on then chBox ! A.checked "checked"
          else chBox

printMesTd :: ResMessage -> Html
printMesTd rm = H.td $ fromString $ case rm of
                        RMError mes -> mes
                        RMSucc mes -> "ok " ++ mes
                        RMIgnore -> "ignored"

maybeListToListMaybe :: Maybe [a] -> [Maybe a]
maybeListToListMaybe (Just list) = map Just list
maybeListToListMaybe Nothing = repeat Nothing

editFormHtml :: EditForm a => (String,String,Int,[String]) -> a -> Maybe [ResMessage] -> Html
editFormHtml (tableName, chainName, rulePos, userChainNames) form errorListMay =
    let entryList = toEntryList form
        mesListMay = maybeListToListMaybe errorListMay
    in
        H.div ! A.class_ "editForm" $
            H.form ! A.id "editform" ! A.method "post" $ do
                H.input ! A.type_ "hidden" ! A.name "table" ! A.value (fromString tableName)
                H.input ! A.type_ "hidden" ! A.name "chain" ! A.value (fromString chainName)
                H.input ! A.type_ "hidden" ! A.name "rulePos" ! A.value (fromString $ show rulePos)
                H.table ! A.class_ "editForm" $ do
                    H.tr $ do
                        H.th "Option"
                        H.th "Not"
                        H.th "Parameter"
                        maybe mempty (\_-> H.th "Message") errorListMay
                    mapM_ (renderFormEntry userChainNames) $ zip entryList mesListMay
                H.input ! A.id "check" ! A.name "submit" ! A.type_ "submit" ! A.value "Check"
                H.input ! A.id "submit" ! A.name "submit" ! A.type_ "submit" ! A.value "Submit"

renderFormEntry :: [String] -> (FormEntry, Maybe ResMessage) -> Html
renderFormEntry _ (FESrc en inv str, resMesMay) =
    H.tr $ do
        H.td $ do
            "Source" >> H.br
            checkBox "sourceEnable" en
        H.td $ do
            "!"
            checkBox "sourceInv" inv
        H.td $
            H.input ! A.type_ "text" ! A.name "source" ! A.value (fromString str)
        maybe mempty printMesTd resMesMay
renderFormEntry _ (FEDst en inv str, resMesMay) =
    H.tr $ do
        H.td $ do
            "Destination" >> H.br
            checkBox "destinationEnable" en
        H.td $ do
            "!"
            checkBox "destinationInv" inv
        H.td $
            H.input ! A.type_ "text" ! A.name "destination" ! A.value (fromString str)
        maybe mempty printMesTd resMesMay
renderFormEntry _ (FEProt en inv prot, resMesMay) =
    H.tr $ do
        H.td $ do
            "Protocol" >> H.br
            checkBox "protocolEnable" en
        H.td $ do
            "!"
            checkBox "protocolInv" inv
        H.td $
            H.select ! A.id "protocol" ! A.name "protocol" $ do
                let tcpOpt = H.option ! A.value "tcp" $ "TCP"
                let udpOpt = H.option ! A.value "udp" $ "UDP"
                let icmpOpt = H.option ! A.value "icmp" $ "ICMP"
                case prot of
                    FTCP -> do
                        tcpOpt ! A.selected "selected"
                        udpOpt >> icmpOpt
                    FUDP -> do
                        tcpOpt
                        udpOpt ! A.selected "selected"
                        icmpOpt
                    FICMP -> do
                        tcpOpt >> udpOpt
                        icmpOpt ! A.selected "selected"
        maybe mempty printMesTd resMesMay
renderFormEntry _ (FESPort en inv str, resMesMay) =
    H.tr $ do
        H.td $ do
            "Source port" >> H.br
            checkBox "sportEnable" en
        H.td $ do
            "!"
            checkBox "sportInv" inv
        H.td $
            H.input ! A.type_ "text" ! A.name "sport" ! A.value (fromString str)
        maybe mempty printMesTd resMesMay
renderFormEntry _ (FEDPort en inv str, resMesMay) =
    H.tr $ do
        H.td $ do
            "Destination port" >> H.br
            checkBox "dportEnable" en
        H.td $ do
            "!"
            checkBox "dportInv" inv
        H.td $
            H.input ! A.type_ "text" ! A.name "dport" ! A.value (fromString str)
        maybe mempty printMesTd resMesMay
renderFormEntry _ (FEInput en inv str, resMesMay) =
    H.tr $ do
        H.td $ do
            "Input interface" >> H.br
            checkBox "inputEnable" en
        H.td $ do
            "!"
            checkBox "inputInv" inv
        H.td $
            H.input ! A.type_ "text" ! A.name "input" ! A.value (fromString str)
        maybe mempty printMesTd resMesMay
renderFormEntry _ (FEOutput en inv str, resMesMay) =
    H.tr $ do
        H.td $ do
            "Output interface" >> H.br
            checkBox "outputEnable" en
        H.td $ do
            "!"
            checkBox "outputInv" inv
        H.td $
            H.input ! A.type_ "text" ! A.name "output" ! A.value (fromString str)
        maybe mempty printMesTd resMesMay
renderFormEntry _ (FEState en stateSet, resMesMay) =
    H.tr $ do
        H.td $ do
            "State" >> H.br
            checkBox "stateEnable" en
        H.td ""
        H.td $ do
            checkBox "stateNew" $ CStNew `member` stateSet
            "New" >> H.br
            checkBox "stateEstablished" $ CStEstablished `member` stateSet
            "Established" >> H.br
            checkBox "stateRelated" $ CStRelated `member` stateSet
            "Related" >> H.br
            checkBox "stateInvalid" $ CStInvalid `member` stateSet
            "Invalid" >> H.br
            checkBox "stateUntracked" $ CStUntracked `member` stateSet
            "Untracked" >> H.br
        maybe mempty printMesTd resMesMay

renderFormEntry userChainNames (FEFiltTar filtTar rejectType userChain, resMesMay) =
    H.tr $ do
        H.td ! A.colspan "3" ! A.class_ "inline" $
            H.table ! A.class_ "inline" $ do
                H.tr $ do
                    H.th ! A.class_ "target" $ "Target"
                    H.th ! A.class_ "targetParam" $ "Parameters"
                H.tr $ do
                    H.td ! A.class_ "target" $ do
                        let acceptRadio = H.input ! A.type_ "radio" ! A.name "target" ! A.value "accept"
                        case filtTar of
                            FAccept -> acceptRadio ! A.checked "checked"
                            _ -> acceptRadio
                        "Acccept"
                    H.td ! A.class_ "targetParam" $ ""
                H.tr $ do
                    H.td ! A.class_ "target" $ do
                        let dropRadio = H.input ! A.type_ "radio" ! A.name "target" ! A.value "drop"
                        case filtTar of
                            FDrop -> dropRadio ! A.checked "checked"
                            _ -> dropRadio
                        "Drop"
                    H.td ! A.class_ "targetParam" $ ""
                H.tr $ do
                    H.td ! A.class_ "target" $ do
                        let rejectRadio = H.input ! A.type_ "radio" ! A.name "target" ! A.value "reject"
                        case filtTar of
                            FReject -> rejectRadio ! A.checked "checked"
                            _ -> rejectRadio
                        "Reject" >> H.br
                    H.td ! A.class_ "targetParam" $
                        H.select ! A.id "rejectType" ! A.name "rejectType" $
                            let
                                netUnrOpt = H.option ! A.value "icmp-net-unreachable" $ "Icmp-net-unreachable"
                                netUnrOptSel = if rejectType == RTNetUnreachable then netUnrOpt ! A.selected "selected"
                                                                                 else netUnrOpt
                                hostUnrOpt = H.option ! A.value "icmp-host-unreachable" $ "Icmp-host-unreachable"
                                hostUnrOptSel = if rejectType == RTHostUnreachable then hostUnrOpt ! A.selected "selected"
                                                                                   else hostUnrOpt
                                portUnrOpt = H.option ! A.value "icmp-port-unreachable" $ "Icmp-port-unreachable"
                                portUnrOptSel = if rejectType == RTPortUnreachable then portUnrOpt ! A.selected "selected"
                                                                                  else portUnrOpt
                                protoUnrOpt = H.option ! A.value "icmp-proto-unreachable" $ "Icmp-proto-unreachable"
                                protoUnrOptSel = if rejectType == RTProtoUnreachable then protoUnrOpt ! A.selected "selected"
                                                                                    else protoUnrOpt
                                netProhOpt = H.option ! A.value "icmp-net-prohibited" $ "Icmp-net-prohibited"
                                netProhOptSel = if rejectType == RTNetProhibited then netProhOpt ! A.selected "selected"
                                                                                else netProhOpt
                                hostProhOpt = H.option ! A.value "icmp-host-prohibited" $ "Icmp-host-prohibited"
                                hostProhOptSel = if rejectType == RTHostProhibited then hostProhOpt ! A.selected "selected"
                                                                                  else hostProhOpt
                                admProhOpt = H.option ! A.value "icmp-admin-prohibited" $ "Icmp-admin-prohibited"
                                admProhOptSel = if rejectType == RTAdminProhibited then admProhOpt ! A.selected "selected"
                                                                                  else admProhOpt
                                tcpResetOpt = H.option ! A.value "tcp-reset" $ "Tcp-reset"
                                tcpResetOptSel = if rejectType == RTTcpReset then tcpResetOpt ! A.selected "selected"
                                                                            else tcpResetOpt
                            in
                                netUnrOptSel
                                >> hostUnrOptSel
                                >> portUnrOptSel
                                >> protoUnrOptSel
                                >> netProhOptSel
                                >> hostProhOptSel
                                >> admProhOptSel
                                >> tcpResetOptSel
                if not $ null userChainNames
                    then
                        let checked = case filtTar of
                                FFUserChain -> True
                                _ -> False
                        in renderUserChain checked userChainNames userChain
                    else mempty
        maybe mempty printMesTd resMesMay
renderFormEntry userChainNames (FENatPrerOutTar natPrerTar dnataddr dnatrand dnatpersist redirport redirrand userChain, resMesMay) =
    H.tr $ do
        H.td ! A.colspan "3" ! A.class_ "inline" $
            H.table ! A.class_ "inline" $ do
                H.tr $ do
                    H.th ! A.class_ "target" $ "Target"
                    H.th ! A.class_ "targetParam" $ "Parameters"
                let checked = case natPrerTar of
                        FDNat -> True
                        _ -> False
                renderDNat checked dnataddr dnatrand dnatpersist
                let checked' = case natPrerTar of
                        FRedirect -> True
                        _ -> False
                renderRedirect checked' redirport redirrand
                if not $ null userChainNames
                    then
                        let checked'' = case natPrerTar of
                                FNPrerUserChain -> True
                                _ -> False
                        in renderUserChain checked'' userChainNames userChain
                    else mempty
        maybe mempty printMesTd resMesMay
renderFormEntry userChainNames (FENatPostrTar natPostrTar snataddr snatrand snatpersist masqport masqrand userChain, resMesMay) =
    H.tr $ do
        H.td ! A.colspan "3" ! A.class_ "inline" $
            H.table ! A.class_ "inline" $ do
                H.tr $ do
                    H.th ! A.class_ "target" $ "Target"
                    H.th ! A.class_ "targetParam" $ "Parameters"
                let checked = case natPostrTar of
                        FMasq -> True
                        _ -> False
                renderMasq checked masqport masqrand
                let checked' = case natPostrTar of
                        FSNat -> True
                        _ -> False
                renderSNat checked' snataddr snatrand snatpersist
                if not $ null userChainNames
                    then
                        let checked'' = case natPostrTar of
                                FNPostrUserChain -> True
                                _ -> False
                        in renderUserChain checked'' userChainNames userChain
                    else
                        mempty
        maybe mempty printMesTd resMesMay
renderFormEntry userChainNames (FENatUserTar natUserTar dnatAddr dnatRand dnatPersist redirPort redirRand snatAddr snatRand snatPersist masqPort masqRand userChain, resMesMay) =
    H.tr $ do
        H.td ! A.colspan "3" ! A.class_ "inline" $
            H.table ! A.class_ "inline" $ do
                H.tr $ do
                    H.th ! A.class_ "target" $ "Target"
                    H.th ! A.class_ "targetParam" $ "Parameters"
                let checked = case natUserTar of
                        FUDNat -> True
                        _ -> False
                renderDNat checked dnatAddr dnatRand dnatPersist
                let checked' = case natUserTar of
                        FURedirect -> True
                        _ -> False
                renderRedirect checked' redirPort redirRand
                let checked'' = case natUserTar of
                        FUSNat -> True
                        _ -> False
                renderSNat checked'' snatAddr snatRand snatPersist
                let checked''' = case natUserTar of
                        FUMasq -> True
                        _ -> False
                renderMasq checked''' masqPort masqRand
                if not $ null userChainNames
                    then
                        let checked'''' = case natUserTar of
                                FNUserUserChain -> True
                                _ -> False
                        in renderUserChain checked'''' userChainNames userChain
                    else
                        mempty
        maybe mempty printMesTd resMesMay
renderFormEntry _ a = H.tr $ fromString $ "Unknown form entry: " ++ show a

renderDNat :: Bool -> String -> Bool -> Bool -> Html
renderDNat checked dnatAddr dnatRand dnatPersist =
    H.tr $ do
        H.td ! A.class_ "target" $ do
            let dnatRadio = H.input ! A.type_ "radio" ! A.name "target" ! A.value "dnat"
            if checked then dnatRadio ! A.checked "checked"
                       else dnatRadio
            "Destination Nat"
        H.td ! A.class_ "targetParam" $ do
            "dnat address:"
            H.input ! A.type_ "text" ! A.name "dnataddress" ! A.value (fromString dnatAddr) >> H.br
            "random:"
            checkBox "dnatrandom" dnatRand >> H.br
            "persistent:"
            checkBox "dnatpersistent" dnatPersist >> H.br

renderRedirect :: Bool -> String -> Bool -> Html
renderRedirect checked redirPort redirRand =
    H.tr $ do
        H.td ! A.class_ "target" $ do
            let redirRadio = H.input ! A.type_ "radio" ! A.name "target" ! A.value "redirect"
            if checked then redirRadio ! A.checked "checked"
                       else redirRadio
            "Redirect"
        H.td ! A.class_ "targetParam" $ do
            "port:"
            H.input ! A.type_ "text" ! A.name "redirport" ! A.value (fromString redirPort) >> H.br
            "random:"
            checkBox "redirrandom" redirRand

renderSNat :: Bool -> String -> Bool -> Bool -> Html
renderSNat checked snatAddr snatRand snatPersist =
    H.tr $ do
        H.td ! A.class_ "target" $ do
            let snatRadio = H.input ! A.type_ "radio" ! A.name "target" ! A.value "snat"
            if checked then snatRadio ! A.checked "checked"
                       else snatRadio
            "Source Nat"
        H.td ! A.class_ "targetParam" $ do
            "snat address:"
            H.input ! A.type_ "text" ! A.name "snataddress" ! A.value (fromString snatAddr) >> H.br
            "random:"
            checkBox "snatrandom" snatRand >> H.br
            "persistent:"
            checkBox "snatpersistent" snatPersist >> H.br
renderMasq :: Bool -> String -> Bool -> Html
renderMasq checked masqPort masqRand =
    H.tr $ do
        H.td ! A.class_ "target" $ do
            let masqRadio = H.input ! A.type_ "radio" ! A.name "target" ! A.value "masquerade"
            if checked then masqRadio ! A.checked "checked"
                       else masqRadio
            "Masquerade"
        H.td ! A.class_ "targetParam" $ do
            "port:"
            H.input ! A.type_ "text" ! A.name "masqport" ! A.value (fromString masqPort) >> H.br
            "random:"
            checkBox "masqrandom" masqRand

renderUserChain :: Bool -> [String] -> String -> Html
renderUserChain checked allChains chain =
    H.tr $ do
        H.td ! A.class_ "target" $ do
            let userChainRadio = H.input ! A.type_ "radio" ! A.name "target" ! A.value "userChain"
            if checked then userChainRadio ! A.checked "checked"
                       else userChainRadio
            "User chain"
        H.td ! A.class_ "targetParam" $
            H.select ! A.id "userChain" ! A.name "userChain" $
                mapM_ (renderOption chain) allChains
    where
    renderOption :: String -> String -> Html
    renderOption selName optName = do
        let opt = H.option ! A.value (fromString optName) $ fromString optName
        let optSel = if optName == selName then opt ! A.selected "selected"
                                           else opt
        optSel