Skip to content

Instantly share code, notes, and snippets.

@ccbrown
Forked from jas-/class.stream.php
Created April 19, 2016 01:49
Show Gist options
  • Select an option

  • Save ccbrown/c13b319219aa810696de73fec527d9db to your computer and use it in GitHub Desktop.

Select an option

Save ccbrown/c13b319219aa810696de73fec527d9db to your computer and use it in GitHub Desktop.

Revisions

  1. @jas- jas- revised this gist Aug 1, 2014. 2 changed files with 15 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion class.stream.php
    Original file line number Diff line number Diff line change
    @@ -203,9 +203,12 @@ private function post($string)
    /**
    * @function merge
    * @param $array array
    *
    * Ugly ugly ugly
    *
    * @returns Array
    */
    private function merge($array, $key)
    private function merge($array)
    {
    $results = array(
    'post' => array(),
    11 changes: 11 additions & 0 deletions usage.php
    Original file line number Diff line number Diff line change
    @@ -7,3 +7,14 @@

    $_PUT = $data['post'];
    $_FILES = $data['file'];

    /* Handle moving the file(s) */
    if (count($_FILES) > 0) {
    foreach($_FILES as $key => $value) {
    if (!is_uploaded_file($value['tmp_name'])) {
    rename($value['tmp_name'], '/path/to/uploads/'.$value['name']);
    } else {
    move_uploaded_file($value['tmp_name'], '/path/to/uploads/'.$value['name']);
    }
    }
    }
  2. @jas- jas- revised this gist Jul 31, 2014. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion usage.php
    Original file line number Diff line number Diff line change
    @@ -5,4 +5,5 @@

    new stream($data);

    echo '<pre>'; print_r($data); echo '</pre>';
    $_PUT = $data['post'];
    $_FILES = $data['file'];
  3. @jas- jas- revised this gist Jul 31, 2014. 1 changed file with 8 additions and 0 deletions.
    8 changes: 8 additions & 0 deletions usage.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,8 @@
    <?php
    include_once('class.stream.php');

    $data = array();

    new stream($data);

    echo '<pre>'; print_r($data); echo '</pre>';
  4. @jas- jas- revised this gist Jul 31, 2014. 2 changed files with 246 additions and 0 deletions.
    245 changes: 245 additions & 0 deletions class.stream.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,245 @@
    <?php

    /**
    * stream - Handle raw input stream
    *
    * LICENSE: This source file is subject to version 3.01 of the GPL license
    * that is available through the world-wide-web at the following URI:
    * http://www.gnu.org/licenses/gpl.html. If you did not receive a copy of
    * the GPL License and are unable to obtain it through the web, please
    *
    * @author [email protected]
    * @license http://www.gnu.org/licenses/gpl.html GPL License 3
    */

    class stream
    {
    /**
    * @var input
    * @abstract Raw input stream
    */
    protected $input;

    /**
    * @function __construct
    * @param $data stream
    */
    public function __construct(array &$data)
    {
    $this->input = file_get_contents('php://input');

    $boundary = $this->boundary();

    if (!count($boundary)) {
    return array(
    'post' => $this->parse($this->input),
    'file' => array()
    );
    }

    $blocks = $this->split($boundary);

    $data = $this->blocks($blocks);

    return $data;
    }

    /**
    * @function boundary
    * @returns Array
    */
    private function boundary()
    {
    preg_match('/boundary=(.*)$/', $_SERVER['CONTENT_TYPE'], $matches);
    return $matches[1];
    }

    /**
    * @function parse
    * @returns Array
    */
    private function parse()
    {
    parse_str(urldecode($this->input), $result);
    return $result;
    }

    /**
    * @function split
    * @param $boundary string
    * @returns Array
    */
    private function split($boundary)
    {
    $result = preg_split("/-+$boundary/", $this->input);
    array_pop($result);
    return $result;
    }

    /**
    * @function blocks
    * @param $array array
    * @returns Array
    */
    private function blocks($array)
    {
    $results = array(
    'post' => array(),
    'file' => array()
    );

    foreach($array as $key => $value)
    {
    if (empty($value))
    continue;

    $block = $this->decide($value);

    if (count($block['post']) > 0)
    array_push($results['post'], $block['post']);

    if (count($block['file']) > 0)
    array_push($results['file'], $block['file']);
    }

    return $this->merge($results);
    }

    /**
    * @function decide
    * @param $string string
    * @returns Array
    */
    private function decide($string)
    {
    if (strpos($string, 'application/octet-stream') !== FALSE)
    {
    return array(
    'post' => $this->file($string),
    'file' => array()
    );
    }

    if (strpos($string, 'filename') !== FALSE)
    {
    return array(
    'post' => array(),
    'file' => $this->file_stream($string)
    );
    }

    return array(
    'post' => $this->post($string),
    'file' => array()
    );
    }

    /**
    * @function file
    * @param $boundary string
    * @returns Array
    */
    private function file($string)
    {
    preg_match('/name=\"([^\"]*)\".*stream[\n|\r]+([^\n\r].*)?$/s', $string, $match);
    return array(
    $match[1] => $match[2]
    );
    }

    /**
    * @function file_stream
    * @param $boundary string
    * @returns Array
    */
    private function file_stream($string)
    {
    $data = array();

    preg_match('/name=\"([^\"]*)\"; filename=\"([^\"]*)\"[\n|\r]+([^\n\r].*)?\r$/s', $string, $match);
    preg_match('/Content-Type: (.*)?/', $match[3], $mime);

    $image = preg_replace('/Content-Type: (.*)[^\n\r]/', '', $match[3]);

    $path = sys_get_temp_dir().'/php'.substr(sha1(rand()), 0, 6);

    $err = file_put_contents($path, $image);

    if (preg_match('/^(.*)\[\]$/i', $match[1], $tmp)) {
    $index = $tmp[1];
    } else {
    $index = $match[1];
    }

    $data[$index]['name'][] = $match[2];
    $data[$index]['type'][] = $mime[1];
    $data[$index]['tmp_name'][] = $path;
    $data[$index]['error'][] = ($err === FALSE) ? $err : 0;
    $data[$index]['size'][] = filesize($path);

    return $data;
    }

    /**
    * @function post
    * @param $boundary string
    * @returns Array
    */
    private function post($string)
    {
    $data = array();

    preg_match('/name=\"([^\"]*)\"[\n|\r]+([^\n\r].*)?\r$/s', $string, $match);

    if (preg_match('/^(.*)\[\]$/i', $match[1], $tmp)) {
    $data[$tmp[1]][] = $match[2];
    } else {
    $data[$match[1]] = $match[2];
    }

    return $data;
    }

    /**
    * @function merge
    * @param $array array
    * @returns Array
    */
    private function merge($array, $key)
    {
    $results = array(
    'post' => array(),
    'file' => array()
    );

    if (count($array['post'] > 0)) {
    foreach($array['post'] as $key => $value) {
    foreach($value as $k => $v) {
    if (is_array($v)) {
    foreach($v as $kk => $vv) {
    $results['post'][$k][] = $vv;
    }
    } else {
    $results['post'][$k] = $v;
    }
    }
    }
    }

    if (count($array['file'] > 0)) {
    foreach($array['file'] as $key => $value) {
    foreach($value as $k => $v) {
    if (is_array($v)) {
    foreach($v as $kk => $vv) {
    $results['file'][$kk][] = $vv[0];
    }
    } else {
    $results['file'][$key] = $v;
    }
    }
    }
    }

    return $results;
    }
    }
    1 change: 1 addition & 0 deletions stream.php
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    <?php
    /**
    * Parse raw HTTP request data
    * http://www.chlab.ch/blog/archives/php/manually-parse-raw-http-data-php
  5. @jas- jas- created this gist Jul 30, 2014.
    95 changes: 95 additions & 0 deletions stream.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,95 @@
    /**
    * Parse raw HTTP request data
    * http://www.chlab.ch/blog/archives/php/manually-parse-raw-http-data-php
    *
    * Pass in $a_data as an array. This is done by reference to avoid copying
    * the data around too much.
    *
    * Any files found in the request will be added by their field name to the
    * $data['files'] array.
    *
    * @param array Empty array to fill with data
    * @return array Associative array of request data
    */
    function parse_raw_http_request(array &$a_data)
    {
    // read incoming data
    $input = file_get_contents('php://input');

    // grab multipart boundary from content type header
    preg_match('/boundary=(.*)$/', $_SERVER['CONTENT_TYPE'], $matches);

    // content type is probably regular form-encoded
    if (!count($matches))
    {
    // we expect regular puts to containt a query string containing data
    parse_str(urldecode($input), $a_data);
    return $a_data;
    }

    $boundary = $matches[1];

    // split content by boundary and get rid of last -- element
    $a_blocks = preg_split("/-+$boundary/", $input);
    array_pop($a_blocks);

    // loop data blocks
    foreach ($a_blocks as $id =&gt; $block)
    {
    if (empty($block))
    continue;

    // you'll have to var_dump $block to understand this and maybe replace \n or \r with a visibile char

    // parse uploaded files
    if (strpos($block, 'application/octet-stream') !== FALSE)
    {
    // match "name", then everything after "stream" (optional) except for prepending newlines
    preg_match("/name=\"([^\"]*)\".*stream[\n|\r]+([^\n\r].*)?$/s", $block, $matches);
    $a_data['files'][$matches[1]] = $matches[2];
    }
    // parse all other fields
    else
    {
    if (strpos($block, 'filename') !== FALSE)
    {
    // match "name" and optional value in between newline sequences
    preg_match('/name=\"([^\"]*)\"; filename=\"([^\"]*)\"[\n|\r]+([^\n\r].*)?\r$/s', $block, $matches);
    preg_match('/Content-Type: (.*)?/', $matches[3], $mime);

    // match the mime type supplied from the browser
    $image = preg_replace('/Content-Type: (.*)[^\n\r]/', '', $matches[3]);

    // get current system path and create tempory file name & path
    $path = sys_get_temp_dir().'/php'.substr(sha1(rand()), 0, 6);

    // write temporary file to emulate $_FILES super global
    $err = file_put_contents($path, $image);

    // Did the user use the infamous &lt;input name="array[]" for multiple file uploads?
    if (preg_match('/^(.*)\[\]$/i', $matches[1], $tmp)) {
    $a_data[$tmp[1]]['name'][] = $matches[2];
    } else {
    $a_data[$matches[1]]['name'][] = $matches[2];
    }

    // Create the remainder of the $_FILES super global
    $a_data[$tmp[1]]['type'][] = $mime[1];
    $a_data[$tmp[1]]['tmp_name'][] = $path;
    $a_data[$tmp[1]]['error'][] = ($err === FALSE) ? $err : 0;
    $a_data[$tmp[1]]['size'][] = filesize($path);
    }
    else
    {
    // match "name" and optional value in between newline sequences
    preg_match('/name=\"([^\"]*)\"[\n|\r]+([^\n\r].*)?\r$/s', $block, $matches);

    if (preg_match('/^(.*)\[\]$/i', $matches[1], $tmp)) {
    $a_data[$tmp[1]][] = $matches[2];
    } else {
    $a_data[$matches[1]] = $matches[2];
    }
    }
    }
    }
    }