Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 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
 */
22
class 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
 
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
}