array( - Form is the name within the form or, if not set the filename * name, - Original name of this file * type, - Mime type of this file * size, - Filesize in bytes * tmp_name, - Internalally temporary filename for uploaded files * error, - Error which has occured * destination, - New destination for this file * validators, - Set validator names for this file * files - Set file names for this file * )) * * @var array */ protected $_files = array(); /** * TMP directory * @var string */ protected $_tmpDir; /** * Send file * * @param mixed $options * @return bool */ abstract public function send($options = null); /** * Receive file * * @param mixed $options * @return bool */ abstract public function receive($options = null); /** * Is file sent? * * @param array|string|null $file * @return bool */ abstract public function isSent($file = null); /** * Is file received? * * @param array|string|null $file * @return bool */ abstract public function isReceived($file = null); /** * Retrieve progress of transfer * * @return float */ abstract public function getProgress(); /** * Set plugin loader to use for validator or filter chain * * @param Zend_Loader_PluginLoader_Interface $loader * @param string $type 'filter', or 'validate' * @return Zend_File_Transfer_Adapter_Abstract * @throws Zend_File_Transfer_Exception on invalid type */ public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type) { $type = strtoupper($type); switch ($type) { case self::FILTER: case self::VALIDATE: $this->_loaders[$type] = $loader; return $this; default: require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception(sprintf('Invalid type "%s" provided to setPluginLoader()', $type)); } } /** * Retrieve plugin loader for validator or filter chain * * Instantiates with default rules if none available for that type. Use * 'filter' or 'validate' for $type. * * @param string $type * @return Zend_Loader_PluginLoader * @throws Zend_File_Transfer_Exception on invalid type. */ public function getPluginLoader($type) { $type = strtoupper($type); switch ($type) { case self::FILTER: case self::VALIDATE: $prefixSegment = ucfirst(strtolower($type)); $pathSegment = $prefixSegment; if (!isset($this->_loaders[$type])) { $paths = array( 'Zend_' . $prefixSegment . '_' => 'Zend/' . $pathSegment . '/', 'Zend_' . $prefixSegment . '_File' => 'Zend/' . $pathSegment . '/File', ); require_once 'Zend/Loader/PluginLoader.php'; $this->_loaders[$type] = new Zend_Loader_PluginLoader($paths); } return $this->_loaders[$type]; default: require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type)); } } /** * Add prefix path for plugin loader * * If no $type specified, assumes it is a base path for both filters and * validators, and sets each according to the following rules: * - filters: $prefix = $prefix . '_Filter' * - validators: $prefix = $prefix . '_Validate' * * Otherwise, the path prefix is set on the appropriate plugin loader. * * @param string $path * @return Zend_File_Transfer_Adapter_Abstract * @throws Zend_File_Transfer_Exception for invalid type */ public function addPrefixPath($prefix, $path, $type = null) { $type = strtoupper($type); switch ($type) { case self::FILTER: case self::VALIDATE: $loader = $this->getPluginLoader($type); $loader->addPrefixPath($prefix, $path); return $this; case null: $prefix = rtrim($prefix, '_'); $path = rtrim($path, DIRECTORY_SEPARATOR); foreach (array(self::FILTER, self::VALIDATE) as $type) { $cType = ucfirst(strtolower($type)); $pluginPath = $path . DIRECTORY_SEPARATOR . $cType . DIRECTORY_SEPARATOR; $pluginPrefix = $prefix . '_' . $cType; $loader = $this->getPluginLoader($type); $loader->addPrefixPath($pluginPrefix, $pluginPath); } return $this; default: require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type)); } } /** * Add many prefix paths at once * * @param array $spec * @return Zend_File_Transfer_Exception */ public function addPrefixPaths(array $spec) { if (isset($spec['prefix']) && isset($spec['path'])) { return $this->addPrefixPath($spec['prefix'], $spec['path']); } foreach ($spec as $type => $paths) { if (is_numeric($type) && is_array($paths)) { $type = null; if (isset($paths['prefix']) && isset($paths['path'])) { if (isset($paths['type'])) { $type = $paths['type']; } $this->addPrefixPath($paths['prefix'], $paths['path'], $type); } } elseif (!is_numeric($type)) { if (!isset($paths['prefix']) || !isset($paths['path'])) { foreach ($paths as $prefix => $spec) { if (is_array($spec)) { foreach ($spec as $path) { if (!is_string($path)) { continue; } $this->addPrefixPath($prefix, $path, $type); } } elseif (is_string($spec)) { $this->addPrefixPath($prefix, $spec, $type); } } } else { $this->addPrefixPath($paths['prefix'], $paths['path'], $type); } } } return $this; } /** * Adds a new validator for this class * * @param string|array $validator Type of validator to add * @param string|array $options Options to set for the validator * @param string|array $files Files to limit this validator to * @return Zend_File_Transfer_Adapter */ public function addValidator($validator, $options = null, $files = null) { if ($validator instanceof Zend_Validate_Interface) { $class = get_class($validator); } elseif (is_string($validator)) { $class = $this->getPluginLoader(self::VALIDATE)->load($validator); $validator = new $class($options); } else { require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception('Invalid validator specified'); } $this->_validators[$class] = $validator; if ($files === null) { $files = array_keys($this->_files); } else { if (!is_array($files)) { $files = array($files); } } foreach ($files as $key => $file) { if (!is_string($file)) { if (is_array($file) && !is_numeric($key)) { $file = $key; } else { continue; } } if (!array_key_exists($file, $this->_files)) { continue; } $this->_files[$file]['validators'][] = $class; } return $this; } /** * Add Multiple validators at once * * @param array $validators * @param string|array $files * @return Zend_File_Transfer_Adapter_Abstract */ public function addValidators(array $validators, $files = null) { foreach ($validators as $key => $spec) { if ($spec instanceof Zend_Validate_Interface) { $this->addValidator($spec, null, $files); continue; } if (is_string($key)) { $this->addValidator($key, $spec, $files); continue; } if (is_int($key)) { if (is_string($spec)) { $this->addValidator($spec, null, $files); continue; } if (is_array($spec)) { if (!array_key_exists('validator', $spec)) { continue; } $validator = $spec['validator']; unset($spec['validator']); $this->addValidator($validator, $spec, $files); continue; } continue; } } return $this; } /** * Sets a validator for the class, erasing all previous set * * @param string|array $validator Validator to set * @param string|array $files Files to limit this validator to * @return Zend_File_Transfer_Adapter */ public function setValidators(array $validators, $files = null) { $this->clearValidators(); return $this->addValidators($validators, $files); } /** * Determine if a given validator has already been registered * * @param string $name * @return bool */ public function hasValidator($name) { return (false !== $this->_getValidatorIdentifier($name)); } /** * Retrieve individual validator * * @param string $name * @return Zend_Validate_Interface|null */ public function getValidator($name) { if (false === ($identifier = $this->_getValidatorIdentifier($name))) { return null; } return $this->_validators[$identifier]; } /** * Returns all set validators * * @param string|array $files (Optional) Returns the validator for this files * @return null|array List of set validators * @throws Zend_File_Transfer_Exception When file not found */ public function getValidators($files = null) { if ($files === null) { return $this->_validators; } if (!is_array($files)) { $files = array($files); } $validators = array(); foreach ($files as $file) { if (!isset($this->_files[$file])) { require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception('Unknown file'); } $validators += $this->_files[$file]['validators']; } $validators = array_unique($validators); foreach ($validators as $validator) { $result[] = $this->_validators[$validator]; } return $result; } /** * Remove an individual validator * * @param string $name * @return Zend_File_Transfer_Adapter_Abstract */ public function removeValidator($name) { if (false === ($key = $this->_getValidatorIdentifier($name))) { return $this; } unset($this->_validators[$key]); foreach (array_keys($this->_files) as $file) { if (!$index = array_search($key, $this->_files[$file]['validators'])) { continue; } unset($this->_files[$file]['validators'][$index]); } return $this; } /** * Remove all validators * * @return Zend_File_Transfer_Adapter_Abstract */ public function clearValidators() { $this->_validators = array(); foreach (array_keys($this->_files) as $file) { $this->_files[$file]['validators'] = array(); } return $this; } /** * Checks if the files are valid * * @param string|array $files Files to check * @return boolean True if all checks are valid */ public function isValid($files) { $check = $this->_getFiles($files); $this->_messages = array(); foreach ($check as $file => $content) { $uploaderror = false; if (array_key_exists('validators', $content)) { foreach ($content['validators'] as $class) { $validator = $this->_validators[$class]; if (!$uploaderror and !$validator->isValid($content['tmp_name'], $content)) { $this->_messages += $validator->getMessages(); } if (($class === 'Zend_Validate_File_Upload') and (count($this->_messages) > 0)) { $uploaderror = true; } } } } if (count($this->_messages) > 0) { return false; } return true; } /** * Returns found validation messages * * @return array */ public function getMessages() { return $this->_messages; } /** * Retrieve error codes * * @return array */ public function getErrors() { return array_keys($this->_messages); } /** * Adds a new filter for this class * * @param string|array $filter Type of filter to add * @param string|array $options Options to set for the filter * @param string|array $files Files to limit this filter to * @return Zend_File_Transfer_Adapter */ public function addFilter($filter, $options = null, $files = null) { if ($filter instanceof Zend_Filter_Interface) { $class = get_class($filter); } elseif (is_string($filter)) { $class = $this->getPluginLoader(self::FILTER)->load($filter); $filter = new $class($options); } else { require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception('Invalid filter specified'); } $this->_filters[$class] = $filter; if ($files === null) { $files = array_keys($this->_files); } else { if (!is_array($files)) { $files = array($files); } } foreach ($files as $key => $file) { if (!is_string($file)) { if (is_array($file) && !is_numeric($key)) { $file = $key; } else { continue; } } if (!array_key_exists($file, $this->_files)) { continue; } $this->_files[$file]['filters'][] = $class; } return $this; } /** * Add Multiple filters at once * * @param array $filters * @param string|array $files * @return Zend_File_Transfer_Adapter_Abstract */ public function addFilters(array $filters, $files = null) { foreach ($filters as $key => $spec) { if ($spec instanceof Zend_Filter_Interface) { $this->addFilter($spec, null, $files); continue; } if (is_string($key)) { $this->addFilter($key, $spec, $files); continue; } if (is_int($key)) { if (is_string($spec)) { $this->addFilter($spec, null, $files); continue; } if (is_array($spec)) { if (!array_key_exists('filter', $spec)) { continue; } $filter = $spec['filter']; unset($spec['filter']); $this->addFilter($filter, $spec, $files); continue; } continue; } } return $this; } /** * Sets a filter for the class, erasing all previous set * * @param string|array $filter Filter to set * @param string|array $files Files to limit this filter to * @return Zend_File_Transfer_Adapter */ public function setFilters(array $filters, $files = null) { $this->clearFilters(); return $this->addFilters($filters, $files); } /** * Determine if a given filter has already been registered * * @param string $name * @return bool */ public function hasFilter($name) { return (false !== $this->_getFilterIdentifier($name)); } /** * Retrieve individual filter * * @param string $name * @return Zend_Filter_Interface|null */ public function getFilter($name) { if (false === ($identifier = $this->_getFilterIdentifier($name))) { return null; } return $this->_filters[$identifier]; } /** * Returns all set filters * * @param string|array $files (Optional) Returns the filter for this files * @return null|array List of set filters * @throws Zend_File_Transfer_Exception When file not found */ public function getFilters($files = null) { if ($files === null) { return $this->_filters; } if (!is_array($files)) { $files = array($files); } $filters = array(); foreach ($files as $file) { if (!isset($this->_files[$file])) { require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception('Unknown file'); } $filters += $this->_files[$file]['filters']; } $filters = array_unique($filters); foreach ($filters as $filter) { $result[] = $this->_filters[$filter]; } return $result; } /** * Remove an individual filter * * @param string $name * @return Zend_File_Transfer_Adapter_Abstract */ public function removeFilter($name) { if (false === ($key = $this->_getFilterIdentifier($name))) { return $this; } unset($this->_filters[$key]); foreach (array_keys($this->_files) as $file) { if (!$index = array_search($key, $this->_files[$file]['filters'])) { continue; } unset($this->_files[$file]['filters'][$index]); } return $this; } /** * Remove all filters * * @return Zend_File_Transfer_Adapter_Abstract */ public function clearFilters() { $this->_filters = array(); foreach (array_keys($this->_files) as $file) { $this->_files[$file]['filters'] = array(); } return $this; } /** * Returns all set files * * @return array List of set files * @throws Zend_File_Transfer_Exception Not implemented */ public function getFile() { require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception('Method not implemented'); } /** * Retrieve filename of transferred file * * Returns final target destnation of transferred file. * * @param string $file * @return string */ public function getFileName($file) { $file = (string) $file; if (!array_key_exists($file, $this->_files)) { return null; } $directory = $this->getDestination($file); return $directory . DIRECTORY_SEPARATOR . $this->_files[$file]['name']; } /** * Adds one or more files * * @param string|array $file File to add * @param string|array $validator Validators to use for this file, must be set before * @param string|array $filter Filters to use for this file, must be set before * @return Zend_File_Transfer_Adapter_Abstract * @throws Zend_File_Transfer_Exception Not implemented */ public function addFile($file, $validator = null, $filter = null) { require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception('Method not implemented'); } /** * Returns all set types * * @return array List of set types * @throws Zend_File_Transfer_Exception Not implemented */ public function getType() { require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception('Method not implemented'); } /** * Adds one or more type of files * * @param string|array $type Type of files to add * @param string|array $validator Validators to use for this file, must be set before * @param string|array $filter Filters to use for this file, must be set before * @return Zend_File_Transfer_Adapter_Abstract * @throws Zend_File_Transfer_Exception Not implemented */ public function addType($type, $validator = null, $filter = null) { require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception('Method not implemented'); } /** * Sets a new destination for the given files * * @deprecated Will be changed to be a filter!!! * @param string $destination New destination directory * @param string|array $files Files to set the new destination for * @return Zend_File_Transfer_Abstract */ public function setDestination($destination, $files = null) { if ($files === null) { foreach ($this->_files as $file => $content) { $this->_files[$file]['destination'] = $destination; } } else { if (!is_array($files)) { $files = array($files); } foreach ($files as $file) { $this->_files[$file]['destination'] = $destination; } } return $this; } /** * Retrieve destination directory value * * @param null|string|array $files * @return null|string|array */ public function getDestination($files = null) { if ((null === $files) || is_array($files)) { $destinations = array(); if (!is_array($files)) { $files = $this->_files; } else { $files = array_flip($files); $files = array_intersect_assoc($files, $this->_files); } foreach ($files as $file => $content) { if (array_key_exists('destination', $content)) { $destinations[$file] = $content['destination']; } else { $tmpdir = $this->_getTmpDir(); $this->setDestination($tmpdir, $file); $destinations[$file] = $tmpdir; } } return $destinations; } if (!is_string($files)) { require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception('Invalid file value passed to getDestination()'); } if (!array_key_exists($files, $this->_files)) { require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception(sprintf('Unknown file "%s" passed to getDestination()', $files)); } if (!array_key_exists('destination', $this->_files[$files])) { return $this->_getTmpDir(); } return $this->_files[$files]['destination']; } /** * Determine system TMP directory * * @return string * @throws Zend_File_Transfer_Exception if unable to determine directory */ protected function _getTmpDir() { if (null === $this->_tmpDir) { if (function_exists('sys_get_temp_dir')) { $tmpdir = sys_get_temp_dir(); } elseif (!empty($_ENV['TMP'])) { $tmpdir = realpath($_ENV['TMP']); } elseif (!empty($_ENV['TMPDIR'])) { $tmpdir = realpath($_ENV['TMPDIR']); } else if (!empty($_ENV['TEMP'])) { $tmpdir = realpath($_ENV['TEMP']); } else { // Attemp to detect by creating a temporary file $tempFile = tempnam(md5(uniqid(rand(), TRUE)), ''); if ($tempFile) { $tmpdir = realpath(dirname($tempFile)); unlink($tempFile); } else { require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception('Could not determine temp directory'); } } $this->_tmpDir = rtrim($tmpdir, "/\\"); } return $this->_tmpDir; } /** * Returns found files based on internal file array and given files * * @param string|array $files (Optional) Files to return * @return array Found files * @throws Zend_File_Transfer_Exception On false filename */ protected function _getFiles($files) { $check = null; if (is_string($files)) { $files = array($files); } if (is_array($files)) { foreach ($files as $find) { $found = null; foreach ($this->_files as $file => $content) { if ($content['name'] === $find) { $found = $file; break; } if ($file === $find) { $found = $file; break; } } if ($found === null) { require_once 'Zend/File/Transfer/Exception.php'; throw new Zend_File_Transfer_Exception(sprintf('"%s" not found by file transfer adapter', $file)); } $check[$found] = $this->_files[$found]; } } if ($files === null) { $check = $this->_files; } return $check; } /** * Retrieve internal identifier for a named validator * * @param string $name * @return string */ protected function _getValidatorIdentifier($name) { if (array_key_exists($name, $this->_validators)) { return $name; } foreach (array_keys($this->_validators) as $test) { if (preg_match('/' . preg_quote($name) . '$/i', $test)) { return $test; } } return false; } /** * Retrieve internal identifier for a named filter * * @param string $name * @return string */ protected function _getFilterIdentifier($name) { if (array_key_exists($name, $this->_filters)) { return $name; } foreach (array_keys($this->_filters) as $test) { if (preg_match('/' . preg_quote($name) . '$/i', $test)) { return $test; } } return false; } }