Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Validate doc-index.json on doctarball upload #604

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 57 additions & 4 deletions Distribution/Server/Features/Documentation.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{-# LANGUAGE RankNTypes, FlexibleContexts,
NamedFieldPuns, RecordWildCards, PatternGuards #-}
NamedFieldPuns, OverloadedStrings,
RecordWildCards, PatternGuards #-}
module Distribution.Server.Features.Documentation (
DocumentationFeature(..),
DocumentationResource(..),
Expand Down Expand Up @@ -28,9 +29,14 @@ import Distribution.Version (nullVersion)

import qualified Data.ByteString.Lazy as BSL
import qualified Data.Map as Map
import Data.Foldable (for_)
import Data.Function (fix)

import qualified Data.Aeson as Aeson
import qualified Data.HashMap.Strict as HashMap
import Data.Aeson (toJSON)
import qualified Text.HTML.TagSoup as TagSoup
import qualified Text.HTML.TagSoup.Match as TagSoup

import Data.Time.Clock (NominalDiffTime, diffUTCTime, getCurrentTime)
import System.Directory (getModificationTime)
Expand Down Expand Up @@ -316,7 +322,7 @@ documentationFeature name

case pkgVersion pkgid == nullVersion of
-- if no version is given we want to redirect to the latest version
True -> tempRedirect latestPkgPath (toResponse "")
True -> tempRedirect latestPkgPath (toResponse BSL.empty)
where
latest = packageId pkginfo
dpath' = [ if var == "package"
Expand Down Expand Up @@ -352,13 +358,60 @@ documentationFeature name
checkDocTarball :: PackageId -> BSL.ByteString -> Either String ()
checkDocTarball pkgid =
checkEntries
. fmapErr (either id show) . Tar.checkTarbomb (display pkgid ++ "-docs")
. fmapErr (either id show) . Tar.checkTarbomb pkgDocsDir
. fmapErr (either id show) . Tar.checkSecurity
. fmapErr (either id show) . Tar.checkPortability
. fmapErr show . Tar.read
where
pkgDocsDir = display pkgid ++ "-docs"

fmapErr f = Tar.foldEntries Tar.Next Tar.Done (Tar.Fail . f)
checkEntries = Tar.foldEntries (\_ remainder -> remainder) (Right ()) Left
checkEntries = Tar.foldEntries checkEntry (Right ()) Left

checkEntry entry remainder
| Tar.entryPath entry == pkgDocsDir </> "doc-index.json"
= case Tar.entryContent entry of
Tar.NormalFile content _ -> checkJsonDocIndex content
_ -> Left "doc-index.json not a file"
| otherwise
= remainder

checkJsonDocIndex :: BSL.ByteString -> Either String ()
checkJsonDocIndex jsDocIndex
| Just (Aeson.Array entries) <- Aeson.decode jsDocIndex
= for_ entries $ \entry -> do
case extractDisplayHtml entry of
Just displayHtml -> checkDisplayHtml displayHtml
_ -> Left "Expected display_html property"
| otherwise
= Left "Expected an array element"
where
extractDisplayHtml (Aeson.Object o) = do
Aeson.String displayHtml <- HashMap.lookup "display_html" o
return displayHtml
extractDisplayHtml _ = Nothing

checkDisplayHtml displayHtml =
checkTags (TagSoup.parseTagsOptions TagSoup.parseOptionsFast displayHtml)

checkTags [] = Right ()
checkTags (t:tx)
| TagSoup.tagOpen hasValidTag hasValidAttrs t
|| TagSoup.tagClose hasValidTag t
|| TagSoup.tagText (const True) t
= checkTags tx
| otherwise
= Left "Disallowed element found"

hasValidTag t = t `elem` whitelistedTags
hasValidAttrs _ = True

whitelistedTags =
[ "a"
, "span"
, "ul"
, "li"
]

{------------------------------------------------------------------------------
Auxiliary
Expand Down
1 change: 1 addition & 0 deletions hackage-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ library lib-server
, split ^>= 0.2
, stm ^>= 2.4
, tagged ^>= 0.8.5
, tagsoup ^>= 0.14
, tar ^>= 0.5
, text ^>= 1.2.2
, time-locale-compat ^>= 0.1.0.1
Expand Down