module ElementBlocker (
elemBlock
) where
import InputParser hiding (Policy(..))
import qualified InputParser
import PolicyTree
import qualified Data.Map as Map
import Data.Maybe
import Utils
import System.IO
import System.FilePath
import Data.List
import System.Directory
import qualified Templates
import Control.Monad
import Data.String.Utils (startswith)
type BlockedRulesTree = DomainTree [Pattern]
data ElemBlockData = ElemBlockData [Pattern] BlockedRulesTree deriving Show
elemBlock :: String -> [String] -> [Line] -> IO ()
elemBlock path info = writeElemBlock . elemBlockData
where
writeElemBlock :: ElemBlockData -> IO ()
writeElemBlock (ElemBlockData flatPatterns rulesTree) =
do
let filteredInfo = filter ((||) <$> not . startswith "Url:" <*> startswith "Url: http") info
-- debugPath = path </> "debug"
createDirectoryIfMissing True path
cont <- getDirectoryContents path
_ <- sequence $ removeOld <$> cont
-- createDirectoryIfMissing True debugPath
-- writeBlockTree path debugPath rulesTree
writeBlockTree path rulesTree
writePatterns_with_debug filteredInfo (path </> "ab2p.common.css") "" flatPatterns
-- writePatterns_with_debug filteredInfo (path </> "ab2p.common.css") (debugPath </> "ab2p.common.css") flatPatterns
removeOld entry' =
let entry = path </> entry'
in do
isDir <- doesDirectoryExist entry
if isDir then when (head entry' /= '.') $ removeDirectoryRecursive entry
else when (takeExtension entry == ".css") $ removeFile entry
-- writeBlockTree :: String -> String -> BlockedRulesTree -> IO ()
-- writeBlockTree normalNodePath debugNodePath (Node name patterns children) =
writeBlockTree :: String -> BlockedRulesTree -> IO ()
writeBlockTree normalNodePath (Node name patterns children) =
do
createDirectoryIfMissing True normalPath
-- createDirectoryIfMissing True debugPath
-- _ <- sequence (writeBlockTree normalPath debugPath <$> children)
-- writePatterns ["See ab2p.common.css for sources info"] normalFilename debugFilename patterns
_ <- sequence (writeBlockTree normalPath <$> children)
writePatterns ["See ab2p.common.css for sources info"] normalFilename patterns
where
normalPath
| null name = normalNodePath
| otherwise = normalNodePath </> name
-- debugPath
-- | null name = debugNodePath
-- | otherwise = debugNodePath </> name
normalFilename = normalPath </> "ab2p.css"
-- debugFilename = debugPath </> "ab2p.css"
writePatterns_with_debug :: [String] -> String -> String -> [Pattern] -> IO ()
writePatterns_with_debug _ _ _ [] = return ()
writePatterns_with_debug info' normalFilename debugFilename patterns =
do
writeCssFile normalFilename $ intercalate "\n" ((++ Templates.blockCss) . intercalate "," <$>
splitEvery 4000 patterns)
when (debugFilename /= "") $
writeCssFile debugFilename $ intercalate "\n" $ (++ Templates.blockCss) <$> patterns
where
splitEvery n = takeWhile (not . null) . unfoldr (Just . splitAt n)
writeCssFile filename content =
do outFile <- openFile filename WriteMode
hSetEncoding outFile utf8
hPutStrLn outFile "/*"
_ <- mapM (hPutStrLn outFile) info'
hPutStrLn outFile "*/"
hPutStrLn outFile content
hClose outFile
writePatterns :: [String] -> String -> [Pattern] -> IO ()
writePatterns _ _ [] = return ()
writePatterns info' normalFilename patterns =
do
-- writeCssFile debugFilename $ intercalate "\n" $ (++ Templates.blockCss) <$> patterns
writeCssFile normalFilename $ intercalate "\n" ((++ Templates.blockCss) . intercalate "," <$>
splitEvery 4000 patterns)
where
splitEvery n = takeWhile (not . null) . unfoldr (Just . splitAt n)
writeCssFile filename content =
do outFile <- openFile filename WriteMode
hSetEncoding outFile utf8
hPutStrLn outFile "/*"
_ <- mapM (hPutStrLn outFile) info'
hPutStrLn outFile "*/"
hPutStrLn outFile content
hClose outFile
elemBlockData :: [Line] -> ElemBlockData
elemBlockData input = ElemBlockData
(Map.foldrWithKey appendFlatPattern [] policyTreeMap)
(Map.foldrWithKey appendTreePattern (Node "" [] []) policyTreeMap)
where
policyTreeMap :: Map.Map String PolicyTree
policyTreeMap = Map.unionWith (trimTree Block .*. mergePolicyTrees Unblock)
blockLinesMap
(erasePolicy Block <$> unblockLinesMap)
where
blockLinesMap = Map.fromListWith (mergeAndTrim Block) (mapMaybe blockLine input)
unblockLinesMap = Map.fromListWith (mergeAndTrim Unblock) (mapMaybe unblockLine input)
unblockLine (Line _ (ElementHide domains InputParser.Unblock pattern)) = (,) pattern <$> restrictionsTree Unblock domains
unblockLine _ = Nothing
blockLine (Line _ (ElementHide domains InputParser.Block pattern)) = (,) pattern <$> restrictionsTree Block domains
blockLine _ = Nothing
appendTreePattern :: Pattern -> PolicyTree -> BlockedRulesTree -> BlockedRulesTree
appendTreePattern pattern policyTree
| null $ _children policyTree = id
| otherwise = mergeTrees appendPattern policyTree
where appendPattern policy patterns = case policy of
Block -> pattern:patterns
_ -> patterns
appendFlatPattern :: Pattern -> PolicyTree -> [Pattern] -> [Pattern]
appendFlatPattern pattern policyTree patterns
| null (_children policyTree) && _value policyTree == Block = pattern:patterns
| otherwise = patterns