[Remove outputFile, it was too complex, added a dependency on the parsedate package, and didn't work properly with persistent connections. Use outputFPS and read the file yourself. bjorn@bringert.net**20060617031827] { hunk ./Network/NewCGI.hs 51 - , output, outputFPS, outputFile, outputNothing, redirect + , output, outputFPS, outputNothing, redirect hunk ./Network/NewCGI.hs 82 -import System.Locale (defaultTimeLocale, rfc822DateFormat) -import System.Time (ClockTime, toUTCTime, toClockTime, formatCalendarTime) - -import System.Time.Parse (parseCalendarTime) hunk ./Network/NewCGI.hs 128 --- | Output the contents of a file lazily. The output is assumed --- to be text\/html, encoded using ISO-8859-1. To change this, set the --- Content-type header using 'setHeader'. --- The file must be a regular file, since this function looks at its --- size to set the Content-length header. To output the contents of --- non-regular files, use 'outputFPS'. --- This function also sets the Last-Modified header, and --- honors the If-Modified-Since header. --- --- FIXME: should we use Content-Disposition: attachment; filename="f" --- to provide a filename to the client? -outputFile :: (MonadIO m, MonadCGI m) => - FilePath - -> m CGIResult -outputFile f = - do mt <- liftIO $ getModificationTime f - ims <- liftM (>>= parseHTTPDate) $ getVar "HTTP_IF_MODIFIED_SINCE" - case ims of - Just t | mt <= t -> do setStatus 304 "Not Modified" - outputNothing - _ -> do setHeader "Last-modified" (formatHTTPDate mt) - (c,sz) <- liftIO $ contentsAndSize f - setHeader "Content-length" (show sz) - outputFPS c - where contentsAndSize x = do h <- openFile x ReadMode - sz <- hFileSize h - c <- BS.hGetContents h - return (c,sz) - hunk ./Network/NewCGI.hs 369 --- --- * HTTP dates --- - -formatHTTPDate :: ClockTime -> String -formatHTTPDate = - formatCalendarTime defaultTimeLocale rfc822DateFormat . toUTCTime - -parseHTTPDate :: String -> Maybe ClockTime -parseHTTPDate = - fmap toClockTime . parseCalendarTime defaultTimeLocale rfc822DateFormat - - hunk ./cgi.cabal 10 -Build-depends: haskell98, base, network, parsec, mtl, fps >= 0.7, xhtml, parsedate +Build-depends: haskell98, base, network, parsec, mtl, fps >= 0.7, xhtml hunk ./examples/Makefile 1 -PROGS = upload.cgi download.cgi printinput.cgi redirect.cgi hello.cgi \ +PROGS = upload.cgi printinput.cgi redirect.cgi hello.cgi \ hunk ./examples/download.hs 1 --- Takes server file path from the file parameter and sends --- that to the client. --- WARNING: this script is a SECURITY RISK and only for --- demo purposes. Do not put it on a public web server. - -import Network.NewCGI - -form = concat ["
"] - -sendFile f = do setHeader "Content-type" "application/octet-stream" - setHeader "Content-Disposition" ("attachment; filename=" ++ show f) - outputFile f - -cgiMain = getInput "file" >>= maybe (output form) sendFile - -main = runCGI cgiMain rmfile ./examples/download.hs }