1 ------------------------------------------------------------------------------
    2 -- | This module contains primitives and helper functions for handling
    3 -- requests with @Content-type: multipart/form-data@, i.e. HTML forms and file
    4 -- uploads.
    5 --
    6 -- Typically most users will want to use 'handleFileUploads', which writes
    7 -- uploaded files to a temporary directory before sending them on to a handler
    8 -- specified by the user.
    9 --
   10 -- Users who wish to handle their file uploads differently can use the
   11 -- lower-level interface called 'handleMultipart'. That function takes
   12 -- uploaded files and streams them to a consumer of the user's choosing.
   13 --
   14 -- Using these functions requires making \"policy\" decisions which Snap can't
   15 -- really make for users, such as \"what's the largest PDF file a user is
   16 -- allowed to upload?\" and \"should we read form inputs into the parameters
   17 -- mapping?\". Policy is specified on a \"global\" basis (using
   18 -- 'UploadPolicy'), and on a per-file basis (using 'PartUploadPolicy', which
   19 -- allows you to reject or limit the size of certain uploaded
   20 -- @Content-type@s).
   21 --
   22 -- Example usage:
   23 --
   24 -- @
   25 -- {-\# LANGUAGE OverloadedStrings #-}
   26 --
   27 -- module Main where
   28 --
   29 -- import qualified Data.ByteString.Char8 as B8
   30 -- import           Data.Functor          ((\<$>))
   31 -- import           "Snap.Core"             ('Snap.Core.Snap', 'Snap.Core.route', 'Snap.Core.writeBS')
   32 -- import           Snap.Http.Server      (quickHttpServe)
   33 -- import           "Snap.Util.FileUploads"
   34 -- import           System.Posix          (FileOffset, fileSize, getFileStatus)
   35 --
   36 -- uploadForm :: 'Snap.Core.Snap' ()
   37 -- uploadForm = 'Snap.Core.writeBS' \"\<form enctype=\\\"multipart\/form-data\\\" action=\\"\/do-upload\\\" method=\\\"POST\\\">\\
   38 --     \\\<input name=\\\"file\\\" type=\\\"file\\\" \/>\\
   39 --     \\\<input type=\\\"submit\\\" value=\\\"Send File\\\" \/>\\
   40 --     \\\<\/form>\"
   41 --
   42 -- getFileSize :: FilePath -> IO FileOffset
   43 -- getFileSize path = fileSize \<$> getFileStatus path
   44 --
   45 -- -- Upload handler that prints out the uploaded file\'s size.
   46 -- doUpload :: 'Snap.Core.Snap' ()
   47 -- doUpload = do
   48 --   l \<- 'handleFileUploads' \"\/tmp\" 'defaultUploadPolicy'
   49 --        (const $ 'allowWithMaximumSize' ('getMaximumFormInputSize' 'defaultUploadPolicy'))
   50 --        (\\pinfo mbfname -> do fsize \<- either (const $ return 0) getFileSize mbfname
   51 --                              return ('partFileName' pinfo, fsize))
   52 --   'writeBS' . B8.pack . show $ l
   53 --
   54 -- site :: 'Snap.Core.Snap' ()
   55 -- site = 'Snap.Core.route'
   56 --   [ (\"\/upload\",    uploadForm)
   57 --   , (\"\/do-upload\", doUpload)]
   58 --
   59 -- main :: IO ()
   60 -- main = quickHttpServe site
   61 -- @
   62 module Snap.Util.FileUploads
   63   ( -- * Functions
   64     handleFileUploads
   65   , handleMultipart
   66   , PartProcessor
   67 
   68     -- * Uploaded parts
   69   , PartInfo
   70   , PartDisposition(..)
   71   , partFieldName
   72   , partFileName
   73   , partContentType
   74   , partHeaders
   75   , partDisposition
   76 
   77     -- ** Policy
   78     -- *** General upload policy
   79   , UploadPolicy
   80   , defaultUploadPolicy
   81   , doProcessFormInputs
   82   , setProcessFormInputs
   83   , getMaximumFormInputSize
   84   , setMaximumFormInputSize
   85   , getMaximumNumberOfFormInputs
   86   , setMaximumNumberOfFormInputs
   87   , getMinimumUploadRate
   88   , setMinimumUploadRate
   89   , getMinimumUploadSeconds
   90   , setMinimumUploadSeconds
   91   , getUploadTimeout
   92   , setUploadTimeout
   93 
   94     -- *** Per-file upload policy
   95   , PartUploadPolicy
   96   , disallow
   97   , allowWithMaximumSize
   98 
   99     -- * Exceptions
  100   , FileUploadException
  101   , fileUploadExceptionReason
  102   , BadPartException
  103   , badPartExceptionReason
  104   , PolicyViolationException
  105   , policyViolationExceptionReason
  106   ) where
  107 
  108 
  109 import           Snap.Internal.Util.FileUploads (BadPartException (badPartExceptionReason), FileUploadException, PartDisposition (..), PartInfo (..), PartProcessor, PartUploadPolicy, PolicyViolationException (policyViolationExceptionReason), UploadPolicy, allowWithMaximumSize, defaultUploadPolicy, disallow, doProcessFormInputs, fileUploadExceptionReason, getMaximumFormInputSize, getMaximumNumberOfFormInputs, getMinimumUploadRate, getMinimumUploadSeconds, getUploadTimeout, handleFileUploads, handleMultipart, setMaximumFormInputSize, setMaximumNumberOfFormInputs, setMinimumUploadRate, setMinimumUploadSeconds, setProcessFormInputs, setUploadTimeout)