From 6c7844689eeb86bd1676380fea88bf395b599d47 Mon Sep 17 00:00:00 2001 From: uckelman Date: Sun, 9 May 2010 14:49:20 +0000 Subject: Added a class for constructing HTTP POSTs of multipart/form-data. git-svn-id: https://vassalengine.svn.sourceforge.net/svnroot/vassalengine/site-src/trunk@6806 67b53d14-2c14-4ace-a08f-0dab2b34000c --- src/HTTP_POST_multipart.php | 132 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/HTTP_POST_multipart.php diff --git a/src/HTTP_POST_multipart.php b/src/HTTP_POST_multipart.php new file mode 100644 index 0000000..7ccc36a --- /dev/null +++ b/src/HTTP_POST_multipart.php @@ -0,0 +1,132 @@ +_parts[] = array( + 'name' => $name, + 'data' => $bytes + ); + } + + public function addFile($name, $filename, $mimetype, + $charset, $encoding, $data) { + $this->_parts[] = array( + 'name' => $name, + 'filename' => $filename, + 'mimetype' => $mimetype, + 'charset' => $charset, + 'encoding' => $encoding, + 'data' => $data + ); + } + + protected static buildDataPart($part) { + return 'Content-Disposition: form-data; name="' . $part['name'] . '"' . + EOL . EOL . $part['data'] . EOL; + } + + protected static buildFilePart($part) { + # build Content-Disposition + $p = 'Content-Disposition: form-data; name="' . $part['name'] . '"; ' . + 'filename="' . $part['filename'] . '"' . EOL; + + # build Content-Type + $p .= 'Content-Type: ' . $part['mimetype']; + if ($part['charset'] !== null) { + $p .= '; charset="' . $part['charset'] . '"'; + } + $p .= EOL; + + # build Content-Transfer-Encoding + $data = null; + + if ($part['encoding'] !== null) { + $p .= 'Content-Transfer-Encoding: ' . $part['encoding'] . EOL; + + switch ($part['encoding']) { + case 'binary': + $data = $part['data']; + break; + case 'base64': + $data = chunk_split(base64_encode($part['data']); + break; + default: + throw new Exception('unrecognized encoding: ' . $part['encoding']); + } + } + else { + $data = $part['data']; + } + + # build data + $p .= EOL . $data . EOL; + + return $p; + } + + protected static buildBoundary($postParts) { + # This isn't guaranteed to terminate, but it's unlikely + # to need more than one iteration on any real input. + while (1) { + $boundary = "---------------------------" . + base_convert(mt_rand(), 10, 36) . + base_convert(mt_rand(), 10, 36) . + base_convert(mt_rand(), 10, 36); + + foreach ($postParts as $part) { + if (strpos($part, $boundary) !== false) { + # the boundary already occurs in this part, try a new boundary + continue 2; + } + } + + # boundary occurs in no part, use it + return $boundary; + } + } + + protected static buildPost($parts) { + $postParts[] = array(); + + foreach ($parts as $part) { + if (array_key_exists('filename')) { + # this is a file part + $postParts[] = self::buildFilePart($part); + } + else { + # this is a simple data part + $postParts[] = self::buildDataPart($part); + } + } + + $boundary = self::buildBoundary($postParts); + + $bd = '--' . $boundary . EOL; + $final_bd = '--' . $boundary . '--' . EOL; + + return array($boundary, $bd . implode($bd, $postParts) . $final_bd); + } + + public function post($url) { + + list($boundary, $content) = buildPost($this->_parts); + $ctype = 'Content-Type: multipart/form-data; boundary="' . $boundary . '"'; + + $ctx = stream_context_create(array( + 'http' => array( + 'method' => 'POST', + 'header' => $ctype, + 'content' => $content + ) + ); + + return file_get_contents($url, false, $ctx); + } +} + +?> -- cgit v1.2.3