Source of file Http.php
Size: 14,662 Bytes - Last Modified: 2014-03-12T23:21:18+01:00
/home/theseer/Downloads/ZendFramework-2.3.0/library/Zend/File/Transfer/Adapter/Http.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466 | <?php /** * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace Zend\File\Transfer\Adapter; use Zend\File\Transfer; use Zend\File\Transfer\Exception; use Zend\ProgressBar; use Zend\ProgressBar\Adapter; /** * File transfer adapter class for the HTTP protocol * */ class Http extends AbstractAdapter { protected static $callbackApc = 'apc_fetch'; protected static $callbackUploadProgress = 'uploadprogress_get_info'; /** * Constructor for Http File Transfers * * @param array $options OPTIONAL Options to set * @throws Exception\PhpEnvironmentException if file uploads are not allowed */ public function __construct($options = array()) { if (ini_get('file_uploads') == false) { throw new Exception\PhpEnvironmentException('File uploads are not allowed in your php config!'); } $this->setOptions($options); $this->prepareFiles(); $this->addValidator('Upload', false, $this->files); } /** * Sets a validator for the class, erasing all previous set * * @param array $validators Validator to set * @param string|array $files Files to limit this validator to * @return AbstractAdapter */ public function setValidators(array $validators, $files = null) { $this->clearValidators(); return $this->addValidators($validators, $files); } /** * Remove an individual validator * * @param string $name * @return AbstractAdapter */ public function removeValidator($name) { if ($name == 'Upload') { return $this; } return parent::removeValidator($name); } /** * Clear the validators * * @return AbstractAdapter */ public function clearValidators() { parent::clearValidators(); $this->addValidator('Upload', false, $this->files); return $this; } /** * Send the file to the client (Download) * * @param string|array $options Options for the file(s) to send * @return void * @throws Exception\BadMethodCallException Not implemented */ public function send($options = null) { throw new Exception\BadMethodCallException('Method not implemented'); } /** * Checks if the files are valid * * @param string|array $files (Optional) Files to check * @return bool True if all checks are valid */ public function isValid($files = null) { // Workaround for WebServer not conforming HTTP and omitting CONTENT_LENGTH $content = 0; if (isset($_SERVER['CONTENT_LENGTH'])) { $content = $_SERVER['CONTENT_LENGTH']; } elseif (!empty($_POST)) { $content = serialize($_POST); } // Workaround for a PHP error returning empty $_FILES when form data exceeds php settings if (empty($this->files) && ($content > 0)) { if (is_array($files)) { $files = current($files); } $temp = array($files => array( 'name' => $files, 'error' => 1)); $validator = $this->validators['Zend\Validator\File\Upload']; $validator->setTranslator($this->getTranslator()) ->setFiles($temp) ->isValid($files, null); $this->messages += $validator->getMessages(); return false; } return parent::isValid($files); } /** * Receive the file from the client (Upload) * * @param string|array $files (Optional) Files to receive * @return bool */ public function receive($files = null) { if (!$this->isValid($files)) { return false; } $check = $this->getFiles($files); foreach ($check as $file => $content) { if (!$content['received']) { $directory = ''; $destination = $this->getDestination($file); if ($destination !== null) { $directory = $destination . DIRECTORY_SEPARATOR; } $filename = $directory . $content['name']; $rename = $this->getFilter('Rename'); if ($rename !== null) { $tmp = $rename->getNewName($content['tmp_name']); if ($tmp != $content['tmp_name']) { $filename = $tmp; } if (dirname($filename) == '.') { $filename = $directory . $filename; } $key = array_search(get_class($rename), $this->files[$file]['filters']); unset($this->files[$file]['filters'][$key]); } // Should never return false when it's tested by the upload validator if (!move_uploaded_file($content['tmp_name'], $filename)) { if ($content['options']['ignoreNoFile']) { $this->files[$file]['received'] = true; $this->files[$file]['filtered'] = true; continue; } $this->files[$file]['received'] = false; return false; } if ($rename !== null) { $this->files[$file]['destination'] = dirname($filename); $this->files[$file]['name'] = basename($filename); } $this->files[$file]['tmp_name'] = $filename; $this->files[$file]['received'] = true; } if (!$content['filtered']) { if (!$this->filter($file)) { $this->files[$file]['filtered'] = false; return false; } $this->files[$file]['filtered'] = true; } } return true; } /** * Checks if the file was already sent * * @param string|array $files Files to check * @return bool * @throws Exception\BadMethodCallException Not implemented */ public function isSent($files = null) { throw new Exception\BadMethodCallException('Method not implemented'); } /** * Checks if the file was already received * * @param string|array $files (Optional) Files to check * @return bool */ public function isReceived($files = null) { $files = $this->getFiles($files, false, true); if (empty($files)) { return false; } foreach ($files as $content) { if ($content['received'] !== true) { return false; } } return true; } /** * Checks if the file was already filtered * * @param string|array $files (Optional) Files to check * @return bool */ public function isFiltered($files = null) { $files = $this->getFiles($files, false, true); if (empty($files)) { return false; } foreach ($files as $content) { if ($content['filtered'] !== true) { return false; } } return true; } /** * Has a file been uploaded ? * * @param array|string|null $files * @return bool */ public function isUploaded($files = null) { $files = $this->getFiles($files, false, true); if (empty($files)) { return false; } foreach ($files as $file) { if (empty($file['name'])) { return false; } } return true; } /** * Returns the actual progress of file up-/downloads * * @param string|array $id The upload to get the progress for * @return array|null * @throws Exception\PhpEnvironmentException whether APC nor UploadProgress extension installed * @throws Exception\RuntimeException */ public static function getProgress($id = null) { if (!static::isApcAvailable() && !static::isUploadProgressAvailable()) { throw new Exception\PhpEnvironmentException('Neither APC nor UploadProgress extension installed'); } $session = 'Zend\File\Transfer\Adapter\Http\ProgressBar'; $status = array( 'total' => 0, 'current' => 0, 'rate' => 0, 'message' => '', 'done' => false ); if (is_array($id)) { if (isset($id['progress'])) { $adapter = $id['progress']; } if (isset($id['session'])) { $session = $id['session']; } if (isset($id['id'])) { $id = $id['id']; } else { unset($id); } } if (!empty($id) && (($id instanceof Adapter\AbstractAdapter) || ($id instanceof ProgressBar\ProgressBar))) { $adapter = $id; unset($id); } if (empty($id)) { if (!isset($_GET['progress_key'])) { $status['message'] = 'No upload in progress'; $status['done'] = true; } else { $id = $_GET['progress_key']; } } if (!empty($id)) { if (static::isApcAvailable()) { $call = call_user_func(static::$callbackApc, ini_get('apc.rfc1867_prefix') . $id); if (is_array($call)) { $status = $call + $status; } } elseif (static::isUploadProgressAvailable()) { $call = call_user_func(static::$callbackUploadProgress, $id); if (is_array($call)) { $status = $call + $status; $status['total'] = $status['bytes_total']; $status['current'] = $status['bytes_uploaded']; $status['rate'] = $status['speed_average']; if ($status['total'] == $status['current']) { $status['done'] = true; } } } if (!is_array($call)) { $status['done'] = true; $status['message'] = 'Failure while retrieving the upload progress'; } elseif (!empty($status['cancel_upload'])) { $status['done'] = true; $status['message'] = 'The upload has been canceled'; } else { $status['message'] = static::toByteString($status['current']) . " - " . static::toByteString($status['total']); } $status['id'] = $id; } if (isset($adapter) && isset($status['id'])) { if ($adapter instanceof Adapter\AbstractAdapter) { $adapter = new ProgressBar\ProgressBar($adapter, 0, $status['total'], $session); } if (!($adapter instanceof ProgressBar\ProgressBar)) { throw new Exception\RuntimeException('Unknown Adapter given'); } if ($status['done']) { $adapter->finish(); } else { $adapter->update($status['current'], $status['message']); } $status['progress'] = $adapter; } return $status; } /** * Checks the APC extension for progress information * * @return bool */ public static function isApcAvailable() { return (bool) ini_get('apc.enabled') && (bool) ini_get('apc.rfc1867') && is_callable(static::$callbackApc); } /** * Checks the UploadProgress extension for progress information * * @return bool */ public static function isUploadProgressAvailable() { return is_callable(static::$callbackUploadProgress); } /** * Prepare the $_FILES array to match the internal syntax of one file per entry * * @return Http */ protected function prepareFiles() { $this->files = array(); foreach ($_FILES as $form => $content) { if (is_array($content['name'])) { foreach ($content as $param => $file) { foreach ($file as $number => $target) { $this->files[$form . '_' . $number . '_'][$param] = $target; $this->files[$form]['multifiles'][$number] = $form . '_' . $number . '_'; } } $this->files[$form]['name'] = $form; foreach ($this->files[$form]['multifiles'] as $key => $value) { $this->files[$value]['options'] = $this->options; $this->files[$value]['validated'] = false; $this->files[$value]['received'] = false; $this->files[$value]['filtered'] = false; $mimetype = $this->detectMimeType($this->files[$value]); $this->files[$value]['type'] = $mimetype; $filesize = $this->detectFileSize($this->files[$value]); $this->files[$value]['size'] = $filesize; if ($this->options['detectInfos']) { $_FILES[$form]['type'][$key] = $mimetype; $_FILES[$form]['size'][$key] = $filesize; } } } else { $this->files[$form] = $content; $this->files[$form]['options'] = $this->options; $this->files[$form]['validated'] = false; $this->files[$form]['received'] = false; $this->files[$form]['filtered'] = false; $mimetype = $this->detectMimeType($this->files[$form]); $this->files[$form]['type'] = $mimetype; $filesize = $this->detectFileSize($this->files[$form]); $this->files[$form]['size'] = $filesize; if ($this->options['detectInfos']) { $_FILES[$form]['type'] = $mimetype; $_FILES[$form]['size'] = $filesize; } } } return $this; } } |