2008-11-21 23:10:58 -05:00
|
|
|
! Copyright (C) 2008 Doug Coleman.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
|
|
USING: accessors combinators io kernel locals math multiline
|
2008-11-29 03:38:27 -05:00
|
|
|
sequences splitting prettyprint namespaces http.parsers
|
|
|
|
ascii assocs unicode.case io.files.unique io.files io.encodings.binary
|
|
|
|
byte-arrays io.encodings make fry ;
|
2008-11-21 23:10:58 -05:00
|
|
|
IN: mime.multipart
|
|
|
|
|
|
|
|
TUPLE: multipart-stream stream n leftover separator ;
|
|
|
|
|
|
|
|
: <multipart-stream> ( stream separator -- multipart-stream )
|
|
|
|
multipart-stream new
|
|
|
|
swap >>separator
|
|
|
|
swap >>stream
|
|
|
|
16 2^ >>n ;
|
|
|
|
|
|
|
|
<PRIVATE
|
|
|
|
|
|
|
|
: ?append ( seq1 seq2 -- newseq/seq2 )
|
|
|
|
over [ append ] [ nip ] if ;
|
|
|
|
|
|
|
|
: ?cut* ( seq n -- before after )
|
|
|
|
over length over <= [ drop f swap ] [ cut* ] if ;
|
|
|
|
|
|
|
|
: read-n ( stream -- bytes end-stream? )
|
|
|
|
[ f ] change-leftover
|
|
|
|
[ n>> ] [ stream>> ] bi stream-read [ ?append ] keep not ;
|
|
|
|
|
2008-11-21 23:31:05 -05:00
|
|
|
: multipart-split ( bytes separator -- before after seq=? )
|
|
|
|
2dup sequence= [ 2drop f f t ] [ split1 f ] if ;
|
2008-11-21 23:10:58 -05:00
|
|
|
|
2008-11-29 03:38:27 -05:00
|
|
|
:: multipart-step-found ( bytes stream quot: ( bytes -- ) -- ? )
|
|
|
|
bytes [ quot unless-empty ]
|
|
|
|
[ stream (>>leftover) quot unless-empty ] if-empty f ; inline
|
2008-11-22 01:12:44 -05:00
|
|
|
|
2008-11-29 03:38:27 -05:00
|
|
|
:: multipart-step-not-found ( bytes stream end-stream? separator quot: ( bytes -- ) -- ? )
|
|
|
|
bytes end-stream? [
|
2008-11-22 01:12:44 -05:00
|
|
|
quot unless-empty f
|
|
|
|
] [
|
|
|
|
separator length 1- ?cut* stream (>>leftover)
|
|
|
|
quot unless-empty t
|
2008-11-29 03:38:27 -05:00
|
|
|
] if ; inline
|
2008-11-22 01:12:44 -05:00
|
|
|
|
2008-11-21 23:10:58 -05:00
|
|
|
:: multipart-step ( stream bytes end-stream? separator quot: ( bytes -- ) -- ? end-stream? )
|
|
|
|
#! return t to loop again
|
2008-11-21 23:56:40 -05:00
|
|
|
bytes separator multipart-split
|
2008-11-29 03:38:27 -05:00
|
|
|
[ 2drop f ]
|
2008-11-22 01:12:44 -05:00
|
|
|
[
|
|
|
|
[ stream quot multipart-step-found ]
|
|
|
|
[ stream end-stream? separator quot multipart-step-not-found ] if*
|
2008-11-29 03:38:27 -05:00
|
|
|
] if stream leftover>> end-stream? not or >boolean ;
|
2008-11-21 23:10:58 -05:00
|
|
|
|
2008-11-21 23:56:40 -05:00
|
|
|
|
2008-11-29 03:38:27 -05:00
|
|
|
:: multipart-step-loop ( stream quot1: ( bytes -- ) -- ? )
|
2008-11-21 23:10:58 -05:00
|
|
|
stream dup [ read-n ] [ separator>> ] bi quot1 multipart-step
|
2008-11-29 03:38:27 -05:00
|
|
|
swap [ drop stream quot1 multipart-step-loop ] when ; inline recursive
|
|
|
|
|
|
|
|
SYMBOL: header
|
|
|
|
SYMBOL: parsed-header
|
|
|
|
SYMBOL: magic-separator
|
|
|
|
|
|
|
|
: trim-blanks ( str -- str' ) [ blank? ] trim ;
|
|
|
|
|
|
|
|
: trim-quotes ( str -- str' )
|
|
|
|
[ [ CHAR: " = ] [ CHAR: ' = ] bi or ] trim ;
|
2008-11-21 23:10:58 -05:00
|
|
|
|
2008-11-29 03:38:27 -05:00
|
|
|
: parse-content-disposition ( str -- content-disposition hash )
|
|
|
|
";" split [ first ] [ rest-slice ] bi [ "=" split ] map
|
|
|
|
[ [ trim-blanks ] [ trim-quotes ] bi* ] H{ } assoc-map-as ;
|
|
|
|
|
|
|
|
: parse-multipart-header ( string -- headers )
|
|
|
|
"\r\n" split harvest
|
|
|
|
[ parse-header-line first2 ] H{ } map>assoc ;
|
|
|
|
|
|
|
|
ERROR: expected-file ;
|
|
|
|
|
|
|
|
TUPLE: uploaded-file path filename name ;
|
|
|
|
|
|
|
|
: (parse-multipart) ( stream -- ? )
|
|
|
|
"\r\n\r\n" >>separator
|
|
|
|
header off
|
|
|
|
dup [ header [ prepend ] change ] multipart-step-loop drop
|
|
|
|
header get dup magic-separator get [ length ] bi@ < [
|
|
|
|
2drop f
|
|
|
|
] [
|
|
|
|
parse-multipart-header
|
|
|
|
parsed-header set
|
|
|
|
"\r\n" magic-separator get append >>separator
|
|
|
|
"factor-upload" "httpd" make-unique-file tuck
|
|
|
|
binary [ [ write ] multipart-step-loop ] with-file-writer swap
|
|
|
|
"content-disposition" parsed-header get at parse-content-disposition
|
|
|
|
nip [ "filename" swap at ] [ "name" swap at ] bi
|
|
|
|
uploaded-file boa ,
|
|
|
|
] if ;
|
|
|
|
|
2008-11-29 03:39:41 -05:00
|
|
|
PRIVATE>
|
|
|
|
|
2008-11-29 03:38:27 -05:00
|
|
|
: parse-multipart ( stream -- array )
|
|
|
|
[
|
|
|
|
"\r\n" <multipart-stream>
|
|
|
|
magic-separator off
|
|
|
|
dup [ magic-separator [ prepend ] change ]
|
|
|
|
multipart-step-loop drop
|
|
|
|
'[ [ _ (parse-multipart) ] loop ] { } make
|
|
|
|
] with-scope ;
|