Source of file Headers.php
Size: 14,073 Bytes - Last Modified: 2014-03-12T23:21:18+01:00
/home/theseer/Downloads/ZendFramework-2.3.0/library/Zend/Mail/Headers.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 | <?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\Mail; use ArrayIterator; use Countable; use Iterator; use Traversable; use Zend\Loader\PluginClassLocator; /** * Basic mail headers collection functionality * * Handles aggregation of headers */ class Headers implements Countable, Iterator { /** @var string End of Line for fields */ const EOL = "\r\n"; /** @var string Start of Line when folding */ const FOLDING = "\r\n "; /** * @var \Zend\Loader\PluginClassLoader */ protected $pluginClassLoader = null; /** * @var array key names for $headers array */ protected $headersKeys = array(); /** * @var Header\HeaderInterface[] instances */ protected $headers = array(); /** * Header encoding; defaults to ASCII * * @var string */ protected $encoding = 'ASCII'; /** * Populates headers from string representation * * Parses a string for headers, and aggregates them, in order, in the * current instance, primarily as strings until they are needed (they * will be lazy loaded) * * @param string $string * @param string $EOL EOL string; defaults to {@link EOL} * @throws Exception\RuntimeException * @return Headers */ public static function fromString($string, $EOL = self::EOL) { $headers = new static(); $currentLine = ''; // iterate the header lines, some might be continuations foreach (explode($EOL, $string) as $line) { // check if a header name is present if (preg_match('/^(?P<name>[\x21-\x39\x3B-\x7E]+):.*$/', $line, $matches)) { if ($currentLine) { // a header name was present, then store the current complete line $headers->addHeaderLine($currentLine); } $currentLine = trim($line); } elseif (preg_match('/^\s+.*$/', $line, $matches)) { // continuation: append to current line $currentLine .= trim($line); } elseif (preg_match('/^\s*$/', $line)) { // empty line indicates end of headers break; } else { // Line does not match header format! throw new Exception\RuntimeException(sprintf( 'Line "%s"does not match header format!', $line )); } } if ($currentLine) { $headers->addHeaderLine($currentLine); } return $headers; } /** * Set an alternate implementation for the PluginClassLoader * * @param PluginClassLocator $pluginClassLoader * @return Headers */ public function setPluginClassLoader(PluginClassLocator $pluginClassLoader) { $this->pluginClassLoader = $pluginClassLoader; return $this; } /** * Return an instance of a PluginClassLocator, lazyload and inject map if necessary * * @return PluginClassLocator */ public function getPluginClassLoader() { if ($this->pluginClassLoader === null) { $this->pluginClassLoader = new Header\HeaderLoader(); } return $this->pluginClassLoader; } /** * Set the header encoding * * @param string $encoding * @return Headers */ public function setEncoding($encoding) { $this->encoding = $encoding; foreach ($this as $header) { $header->setEncoding($encoding); } return $this; } /** * Get the header encoding * * @return string */ public function getEncoding() { return $this->encoding; } /** * Add many headers at once * * Expects an array (or Traversable object) of type/value pairs. * * @param array|Traversable $headers * @throws Exception\InvalidArgumentException * @return Headers */ public function addHeaders($headers) { if (!is_array($headers) && !$headers instanceof Traversable) { throw new Exception\InvalidArgumentException(sprintf( 'Expected array or Traversable; received "%s"', (is_object($headers) ? get_class($headers) : gettype($headers)) )); } foreach ($headers as $name => $value) { if (is_int($name)) { if (is_string($value)) { $this->addHeaderLine($value); } elseif (is_array($value) && count($value) == 1) { $this->addHeaderLine(key($value), current($value)); } elseif (is_array($value) && count($value) == 2) { $this->addHeaderLine($value[0], $value[1]); } elseif ($value instanceof Header\HeaderInterface) { $this->addHeader($value); } } elseif (is_string($name)) { $this->addHeaderLine($name, $value); } } return $this; } /** * Add a raw header line, either in name => value, or as a single string 'name: value' * * This method allows for lazy-loading in that the parsing and instantiation of HeaderInterface object * will be delayed until they are retrieved by either get() or current() * * @throws Exception\InvalidArgumentException * @param string $headerFieldNameOrLine * @param string $fieldValue optional * @return Headers */ public function addHeaderLine($headerFieldNameOrLine, $fieldValue = null) { if (!is_string($headerFieldNameOrLine)) { throw new Exception\InvalidArgumentException(sprintf( '%s expects its first argument to be a string; received "%s"', (is_object($headerFieldNameOrLine) ? get_class($headerFieldNameOrLine) : gettype($headerFieldNameOrLine)) )); } if ($fieldValue === null) { $this->addHeader(Header\GenericHeader::fromString($headerFieldNameOrLine)); } elseif (is_array($fieldValue)) { foreach ($fieldValue as $i) { $this->addHeader(new Header\GenericMultiHeader($headerFieldNameOrLine, $i)); } } else { $this->addHeader(new Header\GenericHeader($headerFieldNameOrLine, $fieldValue)); } return $this; } /** * Add a Header\Interface to this container, for raw values see {@link addHeaderLine()} and {@link addHeaders()} * * @param Header\HeaderInterface $header * @return Headers */ public function addHeader(Header\HeaderInterface $header) { $key = $this->normalizeFieldName($header->getFieldName()); $this->headersKeys[] = $key; $this->headers[] = $header; if ($this->getEncoding() !== 'ASCII') { $header->setEncoding($this->getEncoding()); } return $this; } /** * Remove a Header from the container * * @param string|Header\HeaderInterface field name or specific header instance to remove * @return bool */ public function removeHeader($instanceOrFieldName) { if ($instanceOrFieldName instanceof Header\HeaderInterface) { $indexes = array_keys($this->headers, $instanceOrFieldName, true); } else { $key = $this->normalizeFieldName($instanceOrFieldName); $indexes = array_keys($this->headersKeys, $key, true); } if (!empty($indexes)) { foreach ($indexes as $index) { unset ($this->headersKeys[$index]); unset ($this->headers[$index]); } return true; } return false; } /** * Clear all headers * * Removes all headers from queue * * @return Headers */ public function clearHeaders() { $this->headers = $this->headersKeys = array(); return $this; } /** * Get all headers of a certain name/type * * @param string $name * @return bool|ArrayIterator|Header\HeaderInterface Returns false if there is no headers with $name in this * contain, an ArrayIterator if the header is a MultipleHeadersInterface instance and finally returns * HeaderInterface for the rest of cases. */ public function get($name) { $key = $this->normalizeFieldName($name); $results = array(); foreach (array_keys($this->headersKeys, $key) as $index) { if ($this->headers[$index] instanceof Header\GenericHeader) { $results[] = $this->lazyLoadHeader($index); } else { $results[] = $this->headers[$index]; } } switch (count($results)) { case 0: return false; case 1: if ($results[0] instanceof Header\MultipleHeadersInterface) { return new ArrayIterator($results); } else { return $results[0]; } default: return new ArrayIterator($results); } } /** * Test for existence of a type of header * * @param string $name * @return bool */ public function has($name) { $name = $this->normalizeFieldName($name); return in_array($name, $this->headersKeys); } /** * Advance the pointer for this object as an iterator * */ public function next() { next($this->headers); } /** * Return the current key for this object as an iterator * * @return mixed */ public function key() { return key($this->headers); } /** * Is this iterator still valid? * * @return bool */ public function valid() { return (current($this->headers) !== false); } /** * Reset the internal pointer for this object as an iterator * */ public function rewind() { reset($this->headers); } /** * Return the current value for this iterator, lazy loading it if need be * * @return Header\HeaderInterface */ public function current() { $current = current($this->headers); if ($current instanceof Header\GenericHeader) { $current = $this->lazyLoadHeader(key($this->headers)); } return $current; } /** * Return the number of headers in this contain, if all headers have not been parsed, actual count could * increase if MultipleHeader objects exist in the Request/Response. If you need an exact count, iterate * * @return int count of currently known headers */ public function count() { return count($this->headers); } /** * Render all headers at once * * This method handles the normal iteration of headers; it is up to the * concrete classes to prepend with the appropriate status/request line. * * @return string */ public function toString() { $headers = ''; foreach ($this as $header) { if ($str = $header->toString()) { $headers .= $str . self::EOL; } } return $headers; } /** * Return the headers container as an array * * @todo determine how to produce single line headers, if they are supported * @return array */ public function toArray() { $headers = array(); /* @var $header Header\HeaderInterface */ foreach ($this->headers as $header) { if ($header instanceof Header\MultipleHeadersInterface) { $name = $header->getFieldName(); if (!isset($headers[$name])) { $headers[$name] = array(); } $headers[$name][] = $header->getFieldValue(); } else { $headers[$header->getFieldName()] = $header->getFieldValue(); } } return $headers; } /** * By calling this, it will force parsing and loading of all headers, after this count() will be accurate * * @return bool */ public function forceLoading() { foreach ($this as $item) { // $item should now be loaded } return true; } /** * @param $index * @return mixed */ protected function lazyLoadHeader($index) { $current = $this->headers[$index]; $key = $this->headersKeys[$index]; /* @var $class Header\HeaderInterface */ $class = ($this->getPluginClassLoader()->load($key)) ?: 'Zend\Mail\Header\GenericHeader'; $encoding = $current->getEncoding(); $headers = $class::fromString($current->toString()); if (is_array($headers)) { $current = array_shift($headers); $current->setEncoding($encoding); $this->headers[$index] = $current; foreach ($headers as $header) { $header->setEncoding($encoding); $this->headersKeys[] = $key; $this->headers[] = $header; } return $current; } $current = $headers; $current->setEncoding($encoding); $this->headers[$index] = $current; return $current; } /** * Normalize a field name * * @param string $fieldName * @return string */ protected function normalizeFieldName($fieldName) { return str_replace(array('-', '_', ' ', '.'), '', strtolower($fieldName)); } } |