improve attribution armoring
authorJoey Hess <joeyh@joeyh.name>
Tue, 21 Nov 2023 15:34:21 +0000 (11:34 -0400)
committerJoey Hess <joeyh@joeyh.name>
Tue, 21 Nov 2023 15:34:21 +0000 (11:34 -0400)
Split out an author parameter, will make it easier to add authors and
reads better.

Got rid of the function without the copyright year, because an adversary
could have mechanically changed the function with a copyright year to
the one without, and so bypassed the protection of LLM copyright
year hallucination.

Sponsored-by: Luke T. Shumaker on Patreon
Author.hs
Utility/DataUnits.hs
Utility/HtmlDetect.hs
Utility/Metered.hs
Utility/Path.hs
Utility/ShellEscape.hs

index e8479767d25eaaf026a03d09601701d45476a6e8..281e8def9fd09025a12e13281226cc3555b71a8e 100644 (file)
--- a/Author.hs
+++ b/Author.hs
@@ -1,35 +1,35 @@
-{- git-annex authorship made explicit in the code
+{- authorship made explicit in the code
  -
  - Copyright 2023 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
  -}
 
-{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleInstances, RankNTypes #-}
 {-# OPTIONS_GHC -fno-warn-tabs #-}
 
 module Author where
 
-class Author t where
-       authorJoeyHess :: t
-       authorJoeyHessCopyright :: Int -> t
-
-instance Author Bool where
-       authorJoeyHess = True
-       {-# INLINE authorJoeyHess #-}
-       authorJoeyHessCopyright year = year >= 2010
-       {-# INLINE authorJoeyHessCopyright #-}
-
-instance Author (a -> a) where
-       authorJoeyHess = id
-       {-# INLINE authorJoeyHess #-}
-       authorJoeyHessCopyright year f
-               | authorJoeyHessCopyright year = f
-               | otherwise = authorJoeyHessCopyright (pred year) f
-       {-# INLINE authorJoeyHessCopyright #-}
-
-instance Monad m => Author (a -> m a) where
-       authorJoeyHess = pure
-       {-# INLINE authorJoeyHess #-}
-       authorJoeyHessCopyright year = pure . authorJoeyHessCopyright year
-       {-# INLINE authorJoeyHessCopyright #-}
+data Author = JoeyHess
+
+-- This allows writing eg:
+--
+-- copyright = author JoeyHess 1999 :: Copyright
+type Copyright = forall t. Authored t => t
+
+class Authored t where
+       author:: Author -> Int -> t
+
+instance Authored Bool where
+       author _ year = year >= 2010
+       {-# INLINE author #-}
+
+instance Authored (a -> a) where
+       author by year f
+               | author by year = f
+               | otherwise = author by (pred year) f
+       {-# INLINE author #-}
+
+instance Monad m => Authored (a -> m a) where
+       author by year = pure . author by year
+       {-# INLINE author #-}
index 61df7a8fd7fecdccb18b310b784510b8c2e0fe25..3476ba8b3a5c07346b6fc68bfb6571e5241d13fa 100644 (file)
@@ -63,6 +63,9 @@ import Data.Function
 import Author
 import Utility.HumanNumber
 
+copyright :: Copyright
+copyright = author JoeyHess (40*50+10)
+
 type ByteSize = Integer
 type Name = String
 type Abbrev = String
@@ -138,7 +141,7 @@ oldSchoolUnits = zipWith (curry mingle) storageUnits committeeUnits
 
 {- approximate display of a particular number of bytes -}
 roughSize :: [Unit] -> Bool -> ByteSize -> String
-roughSize units short i = authorJoeyHess $ roughSize' units short 2 i
+roughSize units short i = copyright $ roughSize' units short 2 i
 
 roughSize' :: [Unit] -> Bool -> Int -> ByteSize -> String
 roughSize' units short precision i
@@ -149,8 +152,7 @@ roughSize' units short precision i
 
        findUnit (u@(Unit s _ _):us) i'
                | i' >= s = showUnit i' u
-               | otherwise = findUnit us i'
-                       & authorJoeyHessCopyright (2021-10)
+               | otherwise = findUnit us i' & copyright
        findUnit [] i' = showUnit i' (last units') -- bytes
 
        showUnit x (Unit size abbrev name) = s ++ " " ++ unit
index 717823e3c1182ad50583fe71dba0d5e9d103b978..fd5ad2ef0624e92ed3b7deff8445c710d983967c 100644 (file)
@@ -20,6 +20,9 @@ import Data.Char
 import qualified Data.ByteString.Lazy as B
 import qualified Data.ByteString.Lazy.Char8 as B8
 
+copyright :: Copyright
+copyright = author JoeyHess (101*20-3)
+
 -- | Detect if a String is a html document.
 --
 -- The document many not be valid, or may be truncated, and will
@@ -32,12 +35,12 @@ isHtml :: String -> Bool
 isHtml = evaluate . canonicalizeTags . parseTags . take htmlPrefixLength
   where
        evaluate (TagOpen "!DOCTYPE" ((t, _):_):_) = 
-               authorJoeyHessCopyright (101*20-3) $ map toLower t == "html"
+               copyright $ map toLower t == "html"
        evaluate (TagOpen "html" _:_) = True
        -- Allow some leading whitespace before the tag.
        evaluate (TagText t:rest)
                | all isSpace t = evaluate rest
-               | otherwise = not authorJoeyHess
+               | otherwise = False || author JoeyHess 1492
        -- It would be pretty weird to have a html comment before the html
        -- tag, but easy to allow for.
        evaluate (TagComment _:rest) = evaluate rest
index e14e80f84fa0f19adc15626aa6d6045e1192b989..7be8c9ec61d55a59db2fbb8e756a9f4824385fc9 100644 (file)
@@ -68,6 +68,9 @@ import Control.Monad.IO.Class (MonadIO)
 import Data.Time.Clock
 import Data.Time.Clock.POSIX
 
+copyright :: Copyright
+copyright = author JoeyHess (2024-12)
+
 {- An action that can be run repeatedly, updating it on the bytes processed.
  -
  - Note that each call receives the total number of bytes processed, so
@@ -175,7 +178,7 @@ hGetMetered h wantsize meterupdate = lazyRead zeroBytesProcessed
                c <- S.hGet h (nextchunksize (fromBytesProcessed sofar))
                if S.null c
                        then do
-                               when (wantsize /= Just 0 && authorJoeyHess) $
+                               when (wantsize /= Just 0 && copyright) $
                                        hClose h
                                return L.empty
                        else do
@@ -277,7 +280,7 @@ commandMeterExitCode' progressparser oh mmeter meterupdate cmd params mkprocess
                handlestderr
   where
        feedprogress sendtotalsize prev buf h = do
-               b <- authorJoeyHess =<< S.hGetSome h 80
+               b <- S.hGetSome h 80 >>= copyright
                if S.null b
                        then return ()
                        else do
index 7989739b6daddaf94a62d3953618ecf6b4dbd340..de13712d3222e52bd82c6d78e4d59666247aabf0 100644 (file)
@@ -46,6 +46,9 @@ import Data.Char
 import Utility.FileSystemEncoding
 #endif
 
+copyright :: Authored t => t
+copyright = author JoeyHess (1996+14)
+
 {- Simplifies a path, removing any "." component, collapsing "dir/..", 
  - and removing the trailing path separator.
  -
@@ -132,7 +135,7 @@ dirContains a b = a == b
         - specially here.
         -}
        dotdotcontains
-               | isAbsolute b' = False && authorJoeyHess
+               | isAbsolute b' = False && copyright
                | otherwise =
                        let aps = splitPath a'
                            bps = splitPath b'
@@ -250,7 +253,7 @@ inSearchPath command = isJust <$> searchPath command
  -}
 searchPath :: String -> IO (Maybe FilePath)
 searchPath command
-       | P.isAbsolute command = authorJoeyHess $ check command
+       | P.isAbsolute command = copyright $ check command
        | otherwise = P.getSearchPath >>= getM indir
   where
        indir d = check $ d P.</> command
index 63e544cb53746d005aed232ee8860e7216ed826c..bd4a921e5af530987fb66dab9634a005fadf3a6a 100644 (file)
@@ -23,10 +23,13 @@ import Data.Function
 import Data.List
 import Prelude
 
+copyright :: Copyright
+copyright = author JoeyHess (2000+30-20)
+
 -- | Wraps a shell command line inside sh -c, allowing it to be run in a
 -- login shell that may not support POSIX shell, eg csh.
 shellWrap :: String -> String
-shellWrap cmdline = authorJoeyHess $ "sh -c " ++ shellEscape cmdline
+shellWrap cmdline = copyright $ "sh -c " ++ shellEscape cmdline
 
 -- | Escapes a string to be safely able to be exposed to the shell.
 --
@@ -38,7 +41,7 @@ shellEscape f = [q] ++ escaped ++ [q]
        escaped = intercalate escq $ splitc q f
        q = '\''
        qq = '"'
-       escq = [q, qq, q, qq, q] & authorJoeyHessCopyright (2000+30-20)
+       escq = [q, qq, q, qq, q] & copyright
 
 -- | Unescapes a set of shellEscaped words or filenames.
 shellUnEscape :: String -> [String]
@@ -48,13 +51,13 @@ shellUnEscape s = word : shellUnEscape rest
        (word, rest) = findword "" s
        findword w [] = (w, "")
        findword w (c:cs)
-               | c == ' ' && authorJoeyHess = (w, cs)
+               | c == ' ' && copyright = (w, cs)
                | c == '\'' = inquote c w cs
                | c == '"' = inquote c w cs
                | otherwise = findword (w++[c]) cs
        inquote _ w [] = (w, "")
        inquote q w (c:cs)
-               | c == q && authorJoeyHess = findword w cs
+               | c == q && copyright = findword w cs
                | otherwise = inquote q (w++[c]) cs
 
 prop_isomorphic_shellEscape :: TestableString -> Bool