PHP Classes

File: src/webfan/MimeStub.php

Recommend this page to a friend!
  Classes of Till Wehowski   MIME Stub   src/webfan/MimeStub.php   Download  
File: src/webfan/MimeStub.php
Role: Class source
Content type: text/plain
Description: Class source
Class: MIME Stub
Generate PHP script that can self-execute the code
Author: By
Last change: Update of src/webfan/MimeStub.php
Date: 1 year ago
Size: 36,711 bytes
 

Contents

Class file image Download
<?php /** * Copyright (c) 2017, Till Wehowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of frdl/webfan nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY frdl/webfan ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL frdl/webfan BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ namespace webfan; use frdl; define('___BLOCK_WEBFAN_MIME_VM_RUNNING_STUB___', true); $run = function($file = null){ $args = func_get_args(); header_remove(); $MimeVM = new MimeVM($args[0]); $MimeVM('run'); return $MimeVM; }; $included_files = get_included_files(); if(!___BLOCK_WEBFAN_MIME_VM_RUNNING_STUB___ && !in_array(__FILE__, $included_files) || __FILE__===$included_files[0]) { $run(__FILE__); } class Context { } class Env { } class Response { } class MimeVM { public $e_level = E_USER_ERROR; protected $Request = false; protected $Response = false; protected $raw = false; protected $MIME = false; protected $__FILE__ = false; protected $buf; //stream protected $IO = false; protected $file = false; protected $host = false; protected $mode = false; protected $offset = false; protected $Context = false; protected $Env = false; protected $initial_offset = 0; protected $php = array(); protected $mimes_engine = array( 'application/vnd.frdl.script.php' => '_run_php_1', 'application/php' => '_run_php_1', 'text/php' => '_run_php_1', 'php' => '_run_php_1', 'multipart/mixed' => '_run_multipart', 'multipart/serial' => '_run_multipart', 'multipart/related' => '_run_multipart', 'application/x-httpd-php' => '_run_php_1', ); protected function _run_multipart($_Part){ foreach( $_Part->getParts() as $pos => $part){ if(isset($this->mimes_engine[$part->getMimeType()])){ call_user_func_array(array($this, $this->mimes_engine[$part->getMimeType()]), array($part)); } } } protected function runStubs(){ //echo $this->document; // return; foreach( $this->document->getParts() as $rootPos => $rootPart){ if($rootPart->isMultiPart()) { foreach( $rootPart->getParts() as $pos => $part){ if(isset($this->mimes_engine[$part->getMimeType()])){ call_user_func_array(array($this, $this->mimes_engine[$part->getMimeType()]), array($part)); } } } break; } } public function get_file($part, $file, $name){ if($part->isMultiPart()) { foreach( $part->getParts() as $pos => $_part){ $_f = $this->get_file($_part, $file, $name); if(false !== $_f)return $_f; } } else{ if($file === $part->getFileName() || $name === $part->getName()){ $_f = &$part; return $_f; } } return false; } public function Autoload($class){ $fnames = array( '$LIB/'.str_replace('\\', '/', $class).'.php', str_replace('\\', '/', $class).'.php', '$DIR_PSR4/'.str_replace('\\', '/', $class).'.php', '$DIR_LIB/'.str_replace('\\', '/', $class).'.php', ); $name = 'class '.$class; foreach($fnames as $fn){ $_p = $this->get_file($this->document, $fn, $name); if(false !== $_p){ $this->_run_php_1($_p); return $_p; } } return false; } protected function _run_php_1($part){ $code = $part->getBody(); $code = trim($code); $code = trim($code, '<?>php '); eval($code); } public function __construct($file = null, $offset = 0){ $this->buf = &$this; if(null===$file)$file=__FILE__; $this->__FILE__ = $file; if(__FILE__===$this->__FILE__){ $this->offset = $this->getAttachmentOffset(); }else{ $this->offset = $offset; } $this->initial_offset = $this->offset; //$this->php = array( // '<?' => array( // // ), // '#!' => array( // // ), // '#' => array( // // ), //); // MimeStubApp::God()->addStreamWrapper( 'frdl', 'mime', $this, true ) ; } final public function __destruct(){ try{ if(is_resource($this->IO))fclose($this->IO); }catch(\Exception $e){ trigger_error($e->getMessage(). ' in '.__METHOD__, $this->e_level); } } public function __set($name, $value) { if('location'===$name){ $code =$this->__toString(); file_put_contents($value, $code); return null; } $trace = debug_backtrace(); trigger_error( 'Undefined property via __set(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE); return null; } public function getAttachmentOffset(){ return __COMPILER_HALT_OFFSET__; } public function __toString() { // $document = $this->document; $code = $this->exports; if(__FILE__ === $this->__FILE__) { $php = substr($code, 0, $this->getAttachmentOffset()); }else{ $php = substr($code, 0, $this->initial_offset); } // $php = str_replace('define(\'___BLOCK_WEBFAN_MIME_VM_RUNNING_STUB___\', true);', 'define(\'___BLOCK_WEBFAN_MIME_VM_RUNNING_STUB___\', false);', $php); $php = str_replace('define(\'___BLOCK_WEBFAN_MIME_VM_RUNNING_STUB___\', true);', '', $php); $newClassName = "webfan\InstalShield\MimeStubAPC".mt_rand(10000000000000000,999999999999999999999999); $php = preg_replace("/((\r\n|\r|\n)?namespace\swebfan;(\r\n|\r|\n)use\sfrdl;(\r\n|\r|\n))/", "\r\nnamespace ".$newClassName.";\r\n"."use frdl;".";\r\n", $php); $mime = $this->document; return $php.$mime; } public function __get($name) { switch($name){ case 'exports': return $this->getFileAttachment($this->__FILE__, 0); break; case 'location': return $this->__FILE__; break; case 'document': if(false===$this->raw){ $this->raw=$this->getFileAttachment($this->__FILE__, $this->initial_offset); } if(false===$this->MIME){ $this->MIME=MimeStub::create($this->raw); } return $this->MIME; break; default: return null; break; } $trace = debug_backtrace(); trigger_error( 'Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE); return null; } public function __invoke() { $args = func_get_args(); if(false===$this->raw){ $this->raw=$this->getFileAttachment($this->__FILE__, $this->initial_offset); } if(false===$this->MIME){ $this->MIME=MimeStub::create($this->raw); } $this->Request = new Request(); $this->Env = new Env(); $this->Context = new Context(); $this->Response = new Response(); $res = &$this; if(0<count($args)){ $i=-1; foreach($args as $arg){ $i++; if(is_object($arg) && get_class($this->Request)===get_class($arg)){ $this->Request = &$arg; }elseif(is_object($arg) && get_class($this->Env)===get_class($arg)){ $this->Env = &$arg; }elseif(is_object($arg) && get_class($this->Context)===get_class($arg)){ $this->Context = &$arg; }elseif(is_object($arg) && get_class($this->Response)===get_class($arg)){ $this->Response = &$arg; } if(is_array($arg)){ $this->Context = new Context($arg); }if(is_string($arg)){ $cmd = $arg; if('run'===$arg){ $res = call_user_func_array(array($this, '_run'), $args); }else{ $u = parse_url($cmd); $c = explode('.',$u['host']); $c = array_reverse($c); $tld = array_shift($c); $f = false; if('frdl'===$u['scheme']){ if('mime'===$tld){ if(!isset($args[$i+1])){ $res = $this->getFileAttachment($cmd, 0); $f = true; }else if(isset($args[$i+1])){ //@todo write } } } if(false===$f){ //todo... //if('#'===substr($cmd, 0, 1)){ // $this->php['#'][]=$cmd; //}elseif('#!'===substr($cmd, 0, 2)){ // $this->php['#!'][]=$cmd; //}elseif('<?'===substr($cmd, 0, 2)){ // $this->php['<?'][]=$cmd; //}else{ $parent = (isset($this->MIME->parent) && null !== $this->MIME->parent) ? $this->MIME->parent : null; $this->MIME=MimeStub::create($cmd, $parent); // } } } } } }elseif(0===count($args)){ $res = &$this->buf; } return $res; } protected function _run(){ $this->runStubs(); return $this; } public function __call($name, $arguments) { return call_user_func_array(array($this->document, $name), $arguments); } public function getFileAttachment($file = null, $offset = null){ if(null === $file)$file = &$this->file; if(null === $offset)$offset = $this->offset; $IO = fopen($file, 'r'); fseek($IO, $offset); try{ $buf = stream_get_contents($IO); if(is_resource($IO))fclose($IO); }catch(\Exception $e){ $buf = ''; if(is_resource($IO))fclose($IO); trigger_error($e->getMessage(), $this->e_level); } return $buf; } } class Request { function __construct(){ $this->SAPI = PHP_SAPI; $this->argv = ('cli' ===$this->SAPI && isset($_SERVER['argv']) /* && isset($_SERVER['argv'][0])*/) ? $_SERVER['argv'][0] : false; $this->protocoll = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443) ? 'https' : 'http'; $this->method = $_SERVER['REQUEST_METHOD']; $this->server_name = $_SERVER['SERVER_NAME']; $this->origin = $_SERVER['HTTP_ORIGIN']; $this->get = $_GET; $this->post = $_POST; $this->cookies = $_COOKIE; $this->session = $_SESSION; $this->uri = $_SERVER['REQUEST_URI']; $this->parsed = parse_url($this->protocoll.'://'.$this->server_name.$this->uri); switch($this->method){ case 'HEAD' : case 'GET' : $this->request = $_GET; break; case 'POST' : case 'PUT' : case 'DELETE' : $this->request = $_POST; break; default : $this->request = $_REQUEST; break; } } } /** * https://github.com/Riverline/multipart-parser * * Class Part * @package Riverline\MultiPartParser * * Copyright (c) 2015-2016 Romain Cambien * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the Software * is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * - edited by webfan.de */ class MimeStub { const NS = __NAMESPACE__; const DS = DIRECTORY_SEPARATOR; const FILE = __FILE__; const DIR = __DIR__; const numbers = '0123456789'; const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; const specials = '!$%^&*()_+|~-=`{}[]:;<>?,./'; protected static $__i = -1; //protected $_parent; protected $_id = null; protected $_p = -1; /** * @var array */ protected $headers; /** * @var string */ protected $body; protected $_parent = null; /** * @var Part[] */ protected $parts = array(); /** * @var bool */ protected $multipart = false; protected $modified = false; protected $contentType = false; protected $encoding = false; protected $charset = false; protected $boundary = false; protected function _defaultsRandchars ($opts = array()) { $opts = array_merge(array( 'length' => 8, 'numeric' => true, 'letters' => true, 'special' => false ), $opts); return array( 'length' => (is_int($opts['length'])) ? $opts['length'] : 8, 'numeric' => (is_bool($opts['numeric'])) ? $opts['numeric'] : true, 'letters' => (is_bool($opts['letters'])) ? $opts['letters'] : true, 'special' => (is_bool($opts['special'])) ? $opts['special'] : false ); } protected function _buildRandomChars ($opts = array()) { $chars = ''; if ($opts['numeric']) { $chars .= self::numbers; } if ($opts['letters']) { $chars .= self::letters; } if ($opts['special']) { $chars .= self::specials; } return $chars; } public function generateBundary($opts = array()) { $opts = $this->_defaultsRandchars($opts); $i = 0; $rn = ''; $rnd = ''; $len = $opts['length']; $randomChars = $this->_buildRandomChars($opts); for ($i = 1; $i <= $len; $i++) { $rn = mt_rand(0, strlen($randomChars) -1); $n = substr($randomChars, $rn, 1); $rnd .= $n; } return $rnd; } public function __set($name, $value) { $trace = debug_backtrace(); trigger_error( 'Undefined property via __set(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE); return null; } public function __get($name) { // echo "Getting '$name'\n"; // if (array_key_exists($name, $this->data)) { // return $this->data[$name]; // } switch($name){ case 'parent': return $this->_parent; break; case 'id': return $this->_id; break; case 'nextChild': $this->_p=++$this->_p; if($this->_p >= count($this->parts)/* -1*/)return false; return (is_array($this->parts)) ? $this->parts[$this->_p] : null; break; case 'next': return $this->nextChild; break; case 'rewind': $this->_p=-1; return $this; case 'root': if(null === $this->parent || (get_class($this->parent) !== get_class($this)))return $this; return $this->parent->root; break; case 'isRoot': return ($this->root->id === $this->id) ? true : false; break; case 'lastChild': return (is_array($this->parts)) ? $this->parts[count($this->parts)-1] : null; break; case 'firstChild': return (is_array($this->parts) && isset($this->parts[0])) ? $this->parts[0] : null; break; default: return null; break; } $trace = debug_backtrace(); trigger_error( 'Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE); return null; } public function __call($name, $arguments) { if('append'===$name){ if(!isset($arguments[0]))$arguments[0]=''; $this->parts[] = new self($arguments[0], $this); return $this; } //https://tools.ietf.org/id/draft-snell-http-batch-00.html foreach(array('from', 'to', 'sender', 'subject', 'reply-to'/* ->{'reply-to'} */, 'in-reply-to', 'message-id') as $_header){ if($_header===$name){ if(0===count($arguments)){ return $this->getHeader($_header, null); }elseif(null===$arguments[0]){ $this->removeHeader($_header); }elseif(isset($arguments[0]) && is_string($arguments[0])){ $this->setHeader($_header, $arguments[0]); } return $this; } } // Note: value of $name is case sensitive. $trace = debug_backtrace(); trigger_error( 'Undefined property via __call(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE); return null; } /** As of PHP 5.3.0 */ public static function __callStatic($name, $arguments) { if('run'===$name){ return call_user_func_array('run', $arguments); } if('vm'===$name){ if(0===count($arguments)){ return new MimeVM(); }elseif(1===count($arguments)){ return new MimeVM($arguments[0]); }elseif(2===count($arguments)){ return new MimeVM($arguments[0], $arguments[1]); } // return call_user_func_array(array(webfan\MimeVM, '__construct'), $arguments); return new MimeVM(); } if('create'===$name){ if(!isset($arguments[0]))$arguments[0]=''; if(!isset($arguments[1]))$arguments[1]=null; return new self($arguments[0], $arguments[1]); } // Note: value of $name is case sensitive. $trace = debug_backtrace(); trigger_error( 'Undefined property via __callStatic(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE); return null; } public function getContentType() { $this->contentType=$this->getMimeType(); return $this->contentType; } public function headerName($headName) { $headName = str_replace('-', ' ', $headName); $headName = ucwords($headName); return preg_replace("/\s+/", "\s", str_replace(' ', '-', $headName)); } /** * @param string $input A base64 encoded string * * @return string A decoded string */ public static function urlsafeB64Decode($input) { $remainder = strlen($input) % 4; if ($remainder) { $padlen = 4 - $remainder; $input .= str_repeat('=', $padlen); } return base64_decode(strtr($input, '-_', '+/')); } /** * @param string $input Anything really * * @return string The base64 encode of what you passed in */ public static function urlsafeB64Encode($input) { return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); } public static function strip_body($s,$s1,$s2=false,$offset=0, $_trim = true) { /* * http://php.net/manual/en/function.strpos.php#75146 */ // if( $s2 === false ) { $s2 = $s1; } if( $s2 === false ) { $s2 = $s1.'--'; } $result = array(); $result_2 = array(); $L1 = strlen($s1); $L2 = strlen($s2); if( $L1==0 || $L2==0 ) { return false; } do { $pos1 = strpos($s,$s1,$offset); if( $pos1 !== false ) { $pos1 += $L1; $pos2 = strpos($s,$s2,$pos1); if( $pos2 !== false ) { $key_len = $pos2 - $pos1; $this_key = substr($s,$pos1,$key_len); if(true===$_trim){ $this_key = trim($this_key); } if( !array_key_exists($this_key,$result) ) { $result[$this_key] = array(); } $result[$this_key][] = $pos1; $result_2[] = array( 'pos' => $pos1, 'content' => $this_key ); $offset = $pos2 + $L2; } else { $pos1 = false; } } } while($pos1 !== false ); return array( 'pindex' => $result_2, 'cindex' => $result ); } /** * MultiPart constructor. * @param string $content * @throws \InvalidArgumentException */ protected function __construct($content, &$parent = null) { $this->_id = ++self::$__i; $this->_parent = $parent; // Split headers and body $splits = preg_split('/(\r?\n){2}/', $content, 2); if (count($splits) < 2) { throw new \InvalidArgumentException("Content is not valid, can't split headers and content"); } list ($headers, $body) = $splits; // Regroup multiline headers $currentHeader = ''; $headerLines = array(); foreach (preg_split('/\r?\n/', $headers) as $line) { if (empty($line)) { continue; } if (preg_match('/^\h+(.+)/', $line, $matches)) { // Multi line header $currentHeader .= ' '.$matches[1]; } else { if (!empty($currentHeader)) { $headerLines[] = $currentHeader; } $currentHeader = trim($line); } } if (!empty($currentHeader)) { $headerLines[] = $currentHeader; } // Parse headers $this->headers = array(); foreach ($headerLines as $line) { $lineSplit = explode(':', $line, 2); if (2 === count($lineSplit)) { list($key, $value) = $lineSplit; // Decode value $value = mb_decode_mimeheader(trim($value)); } else { // Bogus header $key = $lineSplit[0]; $value = ''; } // Case-insensitive key $key = strtolower($key); if (!isset($this->headers[$key])) { $this->headers[$key] = $value; } else { if (!is_array($this->headers[$key])) { $this->headers[$key] = (array)$this->headers[$key]; } $this->headers[$key][] = $value; } } // Is MultiPart ? $contentType = $this->getHeader('Content-Type'); $this->contentType=$contentType; if ('multipart' === strstr(self::getHeaderValue($contentType), '/', true)) { // MultiPart ! $this->multipart = true; $boundary = self::getHeaderOption($contentType, 'boundary'); $this->boundary=$boundary; if (null === $boundary) { throw new \InvalidArgumentException("Can't find boundary in content type"); } $separator = '--'.preg_quote($boundary, '/'); if (0 === preg_match('/'.$separator.'\r?\n(.+?)\r?\n'.$separator.'--/s', $body, $matches) || preg_last_error() !== PREG_NO_ERROR ) { $bodyParts = self::strip_body($body,$separator."",$separator."--",0); if(1 !== count($bodyParts['pindex'])){ throw new \InvalidArgumentException("Can't find multi-part content"); } $bodyStr = $bodyParts['pindex'][0]['content']; }else{ $bodyStr = $matches[1]; } $parts = preg_split('/\r?\n'.$separator.'\r?\n/', $bodyStr); unset($bodyStr); foreach ($parts as $part) { //$this->parts[] = new self($part, $this); $this->append($part); } } else { // Decode $encoding = $this->getEcoding(); switch ($encoding) { case 'base64': $body = $this->urlsafeB64Decode($body); break; case 'quoted-printable': $body = quoted_printable_decode($body); break; } // Convert to UTF-8 ( Not if binary or 7bit ( aka Ascii ) ) if (!in_array($encoding, array('binary', '7bit'))) { // Charset $charset = self::getHeaderOption($contentType, 'charset'); if (null === $charset) { // Try to detect $charset = mb_detect_encoding($body) ?: 'utf-8'; } $this->charset=$charset; // Only convert if not UTF-8 if ('utf-8' !== strtolower($charset)) { $body = mb_convert_encoding($body, 'utf-8', $charset); } } $this->body = $body; } } public function __toString() { $boundary = $this->getBoundary($this->isMultiPart()); $s=''; foreach($this->headers as $hname => $hvalue){ $s.= $this->headerName($hname).': '. $this->getHeader($hname) /*$hvalue*/."\r\n"; } $s.= "\r\n" ; if ($this->isMultiPart()) $s.= "--" ; $s.= $boundary ; if ($this->isMultiPart()) $s.= "\r\n" ; if ($this->isMultiPart()) { foreach ($this->parts as $part) { $s.= (get_class($this) === get_class($part)) ? $part : $part->__toString() . "\r\n" ; } $s.= "\r\n"."--" . $boundary . '--'; }else{ $s.= $this->getBody(true, $encoding); } if (null!==$this->parent && $this->parent->isMultiPart() && $this->parent->lastChild->id !== $this->id){ $s.= "\r\n" . "--" .$this->parent->getBoundary() . "\r\n"; } return $s; } public function getEcoding() { $this->encoding=strtolower($this->getHeader('Content-Transfer-Encoding')); return $this->encoding; } public function getCharset() { // return $this->charset; $charset = self::getHeaderOption($this->getMimeType(), 'charset'); if(!is_string($charset)) { // Try to detect $charset = mb_detect_encoding($this->body) ?: 'utf-8'; } $this->charset=$charset; return $this->charset; } public function setBoundary($boundary = null, $opts = array()) { $this->mod(); if(null===$boundary){ $size = 8; if(8 < count($this->parts))$size = 16; if(16 < count($this->parts))$size = 24; if(75 < count($this->parts))$size = 32; if(200 < count($this->parts))$size = 64; $opt = array( 'length' => $size ); $options = array_merge($opt, $opts); $boundary = $this->generateBundary($options); } $this->boundary =$boundary; $this->setHeaderOption('Content-Type', $this->boundary, 'boundary'); } public function getBoundary($generate = true) { $this->boundary = self::getHeaderOption($this->getHeader('Content-Type'), 'boundary'); if(true === $generate && $this->isMultiPart() && (!is_string($this->boundary) || 0===strlen(trim($this->boundary))) ){ $this->setBoundary(); } return $this->boundary; } /** * @param string $key * @param mixed $default * @return mixed */ public function mod() { $this->modified = true; return $this; } public function setHeader($key, $value) { $this->mod(); $key = strtolower($key); $this->headers[$key]=$value; // echo print_r($this->headers, true); return $this; } public function removeHeader($key) { $this->mod(); unset($this->headers[$key]); return $this; } public function setHeaderOption($headerName, $value = null, $opt = null) { $this->mod(); $old_header_value = $this->getHeader($headerName); if(null===$opt && null !==$value){ $this->headers[$headerName]=$value; }else if(null !==$opt && null !==$value){ list($headerValue,$options) = self::parseHeaderContent($old_header_value); $options[$opt]=$value; $new_header_value = $headerValue; // $new_header_value=''; foreach($options as $o => $v){ $new_header_value .= ';'.$o.'='.$v.''; } $this->setHeader($headerName, $new_header_value); } return $this; } /** * @return bool */ public function isMultiPart() { return $this->multipart; } /** * @return string * @throws \LogicException if is multipart */ public function getBody($reEncode = false, &$encoding = null) { if ($this->isMultiPart()) { throw new \LogicException("MultiPart content, there aren't body"); } else { $body = $this->body; if(true===$reEncode){ $encoding = $this->getEcoding(); switch ($encoding) { case 'base64': $body = $this->urlsafeB64Encode($body); break; case 'quoted-printable': $body = quoted_printable_encode($body); break; } // Convert to UTF-8 ( Not if binary or 7bit ( aka Ascii ) ) if (!in_array($encoding, array('binary', '7bit'))) { // back de-/encode if ( 'utf-8' !== strtolower(self::getHeaderOption($this->getMimeType(), 'charset')) && 'utf-8' === mb_detect_encoding($body)) { $body = mb_convert_encoding($body, self::getHeaderOption($this->getMimeType(), 'charset'), 'utf-8'); }elseif ( 'utf-8' === strtolower(self::getHeaderOption($this->getMimeType(), 'charset')) && 'utf-8' !== mb_detect_encoding($body)) { $body = mb_convert_encoding($body, 'utf-8', mb_detect_encoding($body)); } } } return $body; } } /** * @return array */ public function getHeaders() { return $this->headers; } /** * @param string $key * @param mixed $default * @return mixed */ public function getHeader($key, $default = null) { // Case-insensitive key $key = strtolower($key); if (isset($this->headers[$key])) { return $this->headers[$key]; } else { return $default; } } /** * @param string $content * @return array */ static protected function parseHeaderContent($content) { $parts = explode(';', $content); $headerValue = array_shift($parts); $options = array(); // Parse options foreach ($parts as $part) { if (!empty($part)) { $partSplit = explode('=', $part, 2); if (2 === count($partSplit)) { list ($key, $value) = $partSplit; $options[trim($key)] = trim($value, ' "'); } else { // Bogus option $options[$partSplit[0]] = ''; } } } return array($headerValue, $options); } /** * @param string $header * @return string */ static public function getHeaderValue($header) { list($value) = self::parseHeaderContent($header); return $value; } /** * @param string $header * @return string */ static public function getHeaderOptions($header) { list(,$options) = self::parseHeaderContent($header); return $options; } /** * @param string $header * @param string $key * @param mixed $default * @return mixed */ static public function getHeaderOption($header, $key, $default = null) { $options = self::getHeaderOptions($header); if (isset($options[$key])) { return $options[$key]; } else { return $default; } } /** * @return string */ public function getMimeType() { // Find Content-Disposition $contentType = $this->getHeader('Content-Type'); return self::getHeaderValue($contentType) ?: 'application/octet-stream'; } /** * @return string|null */ public function getName() { // Find Content-Disposition $contentDisposition = $this->getHeader('Content-Disposition'); return self::getHeaderOption($contentDisposition, 'name'); } /** * @return string|null */ public function getFileName() { // Find Content-Disposition $contentDisposition = $this->getHeader('Content-Disposition'); return self::getHeaderOption($contentDisposition, 'filename'); } /** * @return bool */ public function isFile() { return !is_null($this->getFileName()); } /** * @return Part[] * @throws \LogicException if is not multipart */ public function getParts() { if ($this->isMultiPart()) { return $this->parts; } else { throw new \LogicException("Not MultiPart content, there aren't any parts"); } } /** * @param string $name * @return Part[] * @throws \LogicException if is not multipart */ public function getPartsByName($name) { $parts = array(); foreach ($this->getParts() as $part) { if ($part->getName() === $name) { $parts[] = $part; } } return $parts; } } __halt_compiler();Mime-Version: 1.0 Content-Type: multipart/mixed;boundary=hoHoBundary12344dh To: test@example.com --hoHoBundary12344dh Content-Type: multipart/alternate;boundary=EVGuDPPT --EVGuDPPT Content-Type: text/html;charset=utf-8 <h1>Test</h1> <p>This is the <strong>HTML</strong> version of the message.</p> --EVGuDPPT Content-Type: text/plain;charset=utf-8 This is the plain text version of the message. --EVGuDPPT Content-Type: multipart/related;boundary=4444EVGuDPPT Content-Disposition: php ;filename="$__FILE__/stub.zip";name="archive stub.zip" --4444EVGuDPPT Content-Type: application/x-httpd-php;charset=utf-8 Content-Disposition: php ;filename="$STUB/bootstrap.php";name="stub bootstrap.php" <?php spl_autoload_register(array($this,'Autoload'), true, true); --4444EVGuDPPT Content-Type: application/x-httpd-php;charset=utf-8 Content-Disposition: php ;filename="$HOME/index.php";name="stub index.php" <?php echo 'Hello World!'; echo '<br /><br />Test: '; try{ $o = new \O_Test; }catch(\Exception $e){ $o = new \stdclass; } if('O_Test'===get_class($o)){ echo 'OK'; }else{ echo ' ERROR'; } ?> --4444EVGuDPPT-- --EVGuDPPT-- --hoHoBundary12344dh Content-Type: multipart/related;boundary=3333EVGuDPPT --3333EVGuDPPT Content-Type: application/x-httpd-php;charset=utf-8 Content-Disposition: php ;filename="$DIR_PSR4/O_Test.php";name="class O_Test" <?php /** * Compression Shortcut */ class O_Test extends \stdclass{} --3333EVGuDPPT-- --hoHoBundary12344dh--