PageRenderTime 60ms CodeModel.GetById 49ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/framework/vendor/swift/lib/classes/Swift/Transport/StreamBuffer.php

http://zoop.googlecode.com/
PHP | 276 lines | 178 code | 25 blank | 73 comment | 24 complexity | 72ed249a7ce2b4abf4da0db9e13339e0 MD5 | raw file
  1<?php
  2
  3/*
  4 * This file is part of SwiftMailer.
  5 * (c) 2004-2009 Chris Corbyn
  6 *
  7 * For the full copyright and license information, please view the LICENSE
  8 * file that was distributed with this source code.
  9 */
 10
 11//@require 'Swift/ByteStream/AbstractFilterableInputStream.php';
 12//@require 'Swift/ReplacementFilterFactory.php';
 13//@require 'Swift/Transport/IoBuffer.php';
 14//@require 'Swift/TransportException.php';
 15
 16/**
 17 * A generic IoBuffer implementation supporting remote sockets and local processes.
 18 * @package Swift
 19 * @subpackage Transport
 20 * @author Chris Corbyn
 21 */
 22class Swift_Transport_StreamBuffer
 23  extends Swift_ByteStream_AbstractFilterableInputStream
 24  implements Swift_Transport_IoBuffer
 25{
 26  
 27  /** A primary socket */
 28  private $_stream;
 29  
 30  /** The input stream */
 31  private $_in;
 32  
 33  /** The output stream */
 34  private $_out;
 35  
 36  /** Buffer initialization parameters */
 37  private $_params = array();
 38  
 39  /** The ReplacementFilterFactory */
 40  private $_replacementFactory;
 41  
 42  /** Translations performed on data being streamed into the buffer */
 43  private $_translations = array();
 44  
 45  /**
 46   * Create a new StreamBuffer using $replacementFactory for transformations.
 47   * @param Swift_ReplacementFilterFactory $replacementFactory
 48   */
 49  public function __construct(
 50    Swift_ReplacementFilterFactory $replacementFactory)
 51  {
 52    $this->_replacementFactory = $replacementFactory;
 53  }
 54  
 55  /**
 56   * Perform any initialization needed, using the given $params.
 57   * Parameters will vary depending upon the type of IoBuffer used.
 58   * @param array $params
 59   */
 60  public function initialize(array $params)
 61  {
 62    $this->_params = $params;
 63    switch ($params['type'])
 64    {
 65      case self::TYPE_PROCESS:
 66        $this->_establishProcessConnection();
 67        break;
 68      case self::TYPE_SOCKET:
 69      default:
 70        $this->_establishSocketConnection();
 71        break;
 72    }
 73  }
 74  
 75  /**
 76   * Set an individual param on the buffer (e.g. switching to SSL).
 77   * @param string $param
 78   * @param mixed $value
 79   */
 80  public function setParam($param, $value)
 81  {
 82    if (isset($this->_stream))
 83    {
 84      switch ($param)
 85      {
 86        case 'protocol':
 87          if (!array_key_exists('protocol', $this->_params)
 88            || $value != $this->_params['protocol'])
 89          {
 90            if ('tls' == $value)
 91            {
 92              stream_socket_enable_crypto(
 93                $this->_stream, true, STREAM_CRYPTO_METHOD_TLS_CLIENT
 94                );
 95            }
 96          }
 97          break;
 98      }
 99    }
100    $this->_params[$param] = $value;
101  }
102  
103  /**
104   * Perform any shutdown logic needed.
105   */
106  public function terminate()
107  {
108    if (isset($this->_stream))
109    {
110      switch ($this->_params['type'])
111      {
112        case self::TYPE_PROCESS:
113          fclose($this->_in);
114          fclose($this->_out);
115          proc_close($this->_stream);
116          break;
117        case self::TYPE_SOCKET:
118        default:
119          fclose($this->_stream);
120          break;
121      }
122    }
123    $this->_stream = null;
124    $this->_out = null;
125    $this->_in = null;
126  }
127  
128  /**
129   * Set an array of string replacements which should be made on data written
130   * to the buffer.  This could replace LF with CRLF for example.
131   * @param string[] $replacements
132   */
133  public function setWriteTranslations(array $replacements)
134  {
135    foreach ($this->_translations as $search => $replace)
136    {
137      if (!isset($replacements[$search]))
138      {
139        $this->removeFilter($search);
140        unset($this->_translations[$search]);
141      }
142    }
143    
144    foreach ($replacements as $search => $replace)
145    {
146      if (!isset($this->_translations[$search]))
147      {
148        $this->addFilter(
149          $this->_replacementFactory->createFilter($search, $replace), $search
150          );
151        $this->_translations[$search] = true;
152      }
153    }
154  }
155  
156  /**
157   * Get a line of output (including any CRLF).
158   * The $sequence number comes from any writes and may or may not be used
159   * depending upon the implementation.
160   * @param int $sequence of last write to scan from
161   * @return string
162   */
163  public function readLine($sequence)
164  {
165    if (isset($this->_out) && !feof($this->_out))
166    {
167      $line = fgets($this->_out);
168      return $line;
169    }
170  }
171  
172  /**
173   * Reads $length bytes from the stream into a string and moves the pointer
174   * through the stream by $length. If less bytes exist than are requested the
175   * remaining bytes are given instead. If no bytes are remaining at all, boolean
176   * false is returned.
177   * @param int $length
178   * @return string
179   */
180  public function read($length)
181  {
182    if (isset($this->_out) && !feof($this->_out))
183    {
184      $ret = fread($this->_out, $length);
185      return $ret;
186    }
187  }
188  
189  /** Not implemented */
190  public function setReadPointer($byteOffset)
191  {
192  }
193  
194  // -- Protected methods
195  
196  /** Flush the stream contents */
197  protected function _flush()
198  {
199    if (isset($this->_in))
200    {
201      fflush($this->_in);
202    }
203  }
204  
205  /** Write this bytes to the stream */
206  protected function _commit($bytes)
207  {
208    if (isset($this->_in)
209      && fwrite($this->_in, $bytes))
210    {
211      return ++$this->_sequence;
212    }
213  }
214  
215  // -- Private methods
216  
217  /**
218   * Establishes a connection to a remote server.
219   * @access private
220   */
221  private function _establishSocketConnection()
222  {
223    $host = $this->_params['host'];
224    if (!empty($this->_params['protocol']))
225    {
226      $host = $this->_params['protocol'] . '://' . $host;
227    }
228    $timeout = 15;
229    if (!empty($this->_params['timeout']))
230    {
231      $timeout = $this->_params['timeout'];
232    }
233    if (!$this->_stream = fsockopen($host, $this->_params['port'], $errno, $errstr, $timeout))
234    {
235      throw new Swift_TransportException(
236        'Connection could not be established with host ' . $this->_params['host'] .
237        ' [' . $errstr . ' #' . $errno . ']'
238        );
239    }
240    if (!empty($this->_params['blocking']))
241    {
242      stream_set_blocking($this->_stream, 1);
243    }
244    else
245    {
246      stream_set_blocking($this->_stream, 0);
247    }
248    $this->_in =& $this->_stream;
249    $this->_out =& $this->_stream;
250  }
251  
252  /**
253   * Opens a process for input/output.
254   * @access private
255   */
256  private function _establishProcessConnection()
257  {
258    $command = $this->_params['command'];
259    $descriptorSpec = array(
260      0 => array('pipe', 'r'),
261      1 => array('pipe', 'w'),
262      2 => array('pipe', 'w')
263      );
264    $this->_stream = proc_open($command, $descriptorSpec, $pipes);
265    stream_set_blocking($pipes[2], 0);
266    if ($err = stream_get_contents($pipes[2]))
267    {
268      throw new Swift_TransportException(
269        'Process could not be started [' . $err . ']'
270        );
271    }
272    $this->_in =& $pipes[0];
273    $this->_out =& $pipes[1];
274  }
275  
276}