(module bot mzscheme
(require (lib "url.ss" "net"))
(require (lib "uri-codec.ss" "net"))
(require (planet "roos.scm" ("oesterholt" "roos.plt" 1 3)))
(provide form-data
(all-from (planet "roos.scm" ("oesterholt" "roos.plt" 1 3)))
(all-from (lib "url.ss" "net"))
)
(def-class
(roos-doc (sp "This class can be used to post forms using the " (s% "multipart/form-data") " content-type."
"It can be used to act as a posting client, to post forms to websites, e.g. a MediaWiki."
)
(sp (s== "Synopsys"))
(sp (sverb "(require (planet \"bot.scm\" (\"oesterholt\" \"webbot.plt\" 1 0))"
"(define F (form-data))"
"(-> F form-add 'name \"A name\")"
"(-> F form-add 'file (build-path \"my-file.txt\"))"
"(let ((p (-> F form-post (string->url \"http://test.form.org/post-it.php\"))))"
" (display (read-string 1000000 p))"
" (close-input-port p))"
"(exit)")))
(this (form-data))
(supers)
(private
(define _form '())
(define _boundary "87689sadfgioawgfaout786TUGDQO@ggdfyudfsgajsguygOI*USW")
(define (read-in path)
(define (rd port)
(let ((r (read-string 1024 port)))
(if (eq? r eof)
(begin
(close-input-port port)
"")
(string-append r (rd port)))))
(rd (open-input-file path)))
)
(public
((define (sp "This member can be used to add a (form) field to be posted. It automatically does the "
"right thing given it's input value. If value is of type " (s% 'path?) " the form will "
"add the file to be uploaded; otherwise the string representation of the input value "
"is taken (using " (s% "format") ".")
(sp (s% "Input parameters: ") (s% 'name:<symbol>) ", " (s% 'value:<anytype>) ".")
(sp (s% "Returns : ") (s% 'this)))
(form-add name value)
(set! _form (cons (cons name (format "~a" value)) _form))
this)
((define (sp "Clears the form. New fields can be added.")
(sp (s% "Returns : ") (s% 'this)))
(form-clear)
(set! _form '())
this)
((define (sp "Converts the form to a 'bytes' representation.")
(sp (s% "Returns : ") "The converted form"))
(form->bytes)
(values (list (string-append "Content-type: multipart/form-data, boundary=" _boundary)
)
(string->bytes/utf-8
(apply string-append
(map (lambda (field-value)
(string-append (format "--~a~%" _boundary)
(if (path? (cdr field-value))
(string-append
(format "content-disposition: form-data; name=\"~a\"; filename=\"~a\"~%"
(symbol->string (car field-value))
(call-with-values (lambda () (split-path (cdr field-value)))
(lambda (p n x) n)))
(format "Content-Transfer-Encoding: binary~%")
(format "~%")
(read-in (cdr field-value)))
(string-append
(format "content-disposition: form-data; name=\"~a\"~%" (symbol->string (car field-value)))
(format "~%")
(format "~a~%" (cdr field-value))))))
_form)))))
((define (sp "Posts the form to the given " (s% 'url))
(sp (s% "Input parameters: ") (s% 'url:<url>) " (see the " (s% "net") " collection)")
(sp (s% "Returns : ") (s% "<input-port>") " (can be used to read the results of the post"))
(form-post url)
(call-with-values (lambda () (-> this form->bytes))
(lambda (content-types data)
(post-pure-port url data content-types))))
)
((constructor (sp "Takes no arguments")))
)
)