[ Index ]

MailPress 7.2

[ Index ]     [ Classes ]     [ Functions ]     [ Variables ]     [ Constants ]     [ Statistics ]    

title

Body

[close]

/mp-includes/composer/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/ -> StreamBuffer.php (source)

   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  /**
  12   * A generic IoBuffer implementation supporting remote sockets and local processes.
  13   *
  14   * @author     Chris Corbyn
  15   */
  16  class Swift_Transport_StreamBuffer extends Swift_ByteStream_AbstractFilterableInputStream implements Swift_Transport_IoBuffer
  17  {
  18      /** A primary socket */
  19      private $stream;
  20  
  21      /** The input stream */
  22      private $in;
  23  
  24      /** The output stream */
  25      private $out;
  26  
  27      /** Buffer initialization parameters */
  28      private $params = [];
  29  
  30      /** The ReplacementFilterFactory */
  31      private $replacementFactory;
  32  
  33      /** Translations performed on data being streamed into the buffer */
  34      private $translations = [];
  35  
  36      /**
  37       * Create a new StreamBuffer using $replacementFactory for transformations.
  38       */
  39      public function __construct(Swift_ReplacementFilterFactory $replacementFactory)
  40      {
  41          $this->replacementFactory = $replacementFactory;
  42      }
  43  
  44      /**
  45       * Perform any initialization needed, using the given $params.
  46       *
  47       * Parameters will vary depending upon the type of IoBuffer used.
  48       */
  49      public function initialize(array $params)
  50      {
  51          $this->params = $params;
  52          switch ($params['type']) {
  53              case self::TYPE_PROCESS:
  54                  $this->establishProcessConnection();
  55                  break;
  56              case self::TYPE_SOCKET:
  57              default:
  58                  $this->establishSocketConnection();
  59                  break;
  60          }
  61      }
  62  
  63      /**
  64       * Set an individual param on the buffer (e.g. switching to SSL).
  65       *
  66       * @param string $param
  67       * @param mixed  $value
  68       */
  69      public function setParam($param, $value)
  70      {
  71          if (isset($this->stream)) {
  72              switch ($param) {
  73                  case 'timeout':
  74                      if ($this->stream) {
  75                          stream_set_timeout($this->stream, $value);
  76                      }
  77                      break;
  78  
  79                  case 'blocking':
  80                      if ($this->stream) {
  81                          stream_set_blocking($this->stream, 1);
  82                      }
  83              }
  84          }
  85          $this->params[$param] = $value;
  86      }
  87  
  88      public function startTLS()
  89      {
  90          // STREAM_CRYPTO_METHOD_TLS_CLIENT only allow tls1.0 connections (some php versions)
  91          // To support modern tls we allow explicit tls1.0, tls1.1, tls1.2
  92          // Ssl3 and older are not allowed because they are vulnerable
  93          // @TODO make tls arguments configurable
  94          return stream_socket_enable_crypto($this->stream, true, STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT);
  95      }
  96  
  97      /**
  98       * Perform any shutdown logic needed.
  99       */
 100      public function terminate()
 101      {
 102          if (isset($this->stream)) {
 103              switch ($this->params['type']) {
 104                  case self::TYPE_PROCESS:
 105                      fclose($this->in);
 106                      fclose($this->out);
 107                      proc_close($this->stream);
 108                      break;
 109                  case self::TYPE_SOCKET:
 110                  default:
 111                      fclose($this->stream);
 112                      break;
 113              }
 114          }
 115          $this->stream = null;
 116          $this->out = null;
 117          $this->in = null;
 118      }
 119  
 120      /**
 121       * Set an array of string replacements which should be made on data written
 122       * to the buffer.
 123       *
 124       * This could replace LF with CRLF for example.
 125       *
 126       * @param string[] $replacements
 127       */
 128      public function setWriteTranslations(array $replacements)
 129      {
 130          foreach ($this->translations as $search => $replace) {
 131              if (!isset($replacements[$search])) {
 132                  $this->removeFilter($search);
 133                  unset($this->translations[$search]);
 134              }
 135          }
 136  
 137          foreach ($replacements as $search => $replace) {
 138              if (!isset($this->translations[$search])) {
 139                  $this->addFilter(
 140                      $this->replacementFactory->createFilter($search, $replace), $search
 141                      );
 142                  $this->translations[$search] = true;
 143              }
 144          }
 145      }
 146  
 147      /**
 148       * Get a line of output (including any CRLF).
 149       *
 150       * The $sequence number comes from any writes and may or may not be used
 151       * depending upon the implementation.
 152       *
 153       * @param int $sequence of last write to scan from
 154       *
 155       * @return string
 156       *
 157       * @throws Swift_IoException
 158       */
 159      public function readLine($sequence)
 160      {
 161          if (isset($this->out) && !feof($this->out)) {
 162              $line = fgets($this->out);
 163              if (0 == strlen($line)) {
 164                  $metas = stream_get_meta_data($this->out);
 165                  if ($metas['timed_out']) {
 166                      throw new Swift_IoException('Connection to '.$this->getReadConnectionDescription().' Timed Out');
 167                  }
 168              }
 169  
 170              return $line;
 171          }
 172      }
 173  
 174      /**
 175       * Reads $length bytes from the stream into a string and moves the pointer
 176       * through the stream by $length.
 177       *
 178       * If less bytes exist than are requested the remaining bytes are given instead.
 179       * If no bytes are remaining at all, boolean false is returned.
 180       *
 181       * @param int $length
 182       *
 183       * @return string|bool
 184       *
 185       * @throws Swift_IoException
 186       */
 187      public function read($length)
 188      {
 189          if (isset($this->out) && !feof($this->out)) {
 190              $ret = fread($this->out, $length);
 191              if (0 == strlen($ret)) {
 192                  $metas = stream_get_meta_data($this->out);
 193                  if ($metas['timed_out']) {
 194                      throw new Swift_IoException('Connection to '.$this->getReadConnectionDescription().' Timed Out');
 195                  }
 196              }
 197  
 198              return $ret;
 199          }
 200      }
 201  
 202      /** Not implemented */
 203      public function setReadPointer($byteOffset)
 204      {
 205      }
 206  
 207      /** Flush the stream contents */
 208      protected function flush()
 209      {
 210          if (isset($this->in)) {
 211              fflush($this->in);
 212          }
 213      }
 214  
 215      /** Write this bytes to the stream */
 216      protected function doCommit($bytes)
 217      {
 218          if (isset($this->in)) {
 219              $bytesToWrite = strlen($bytes);
 220              $totalBytesWritten = 0;
 221  
 222              while ($totalBytesWritten < $bytesToWrite) {
 223                  $bytesWritten = fwrite($this->in, substr($bytes, $totalBytesWritten));
 224                  if (false === $bytesWritten || 0 === $bytesWritten) {
 225                      break;
 226                  }
 227  
 228                  $totalBytesWritten += $bytesWritten;
 229              }
 230  
 231              if ($totalBytesWritten > 0) {
 232                  return ++$this->sequence;
 233              }
 234          }
 235      }
 236  
 237      /**
 238       * Establishes a connection to a remote server.
 239       */
 240      private function establishSocketConnection()
 241      {
 242          $host = $this->params['host'];
 243          if (!empty($this->params['protocol'])) {
 244              $host = $this->params['protocol'].'://'.$host;
 245          }
 246          $timeout = 15;
 247          if (!empty($this->params['timeout'])) {
 248              $timeout = $this->params['timeout'];
 249          }
 250          $options = [];
 251          if (!empty($this->params['sourceIp'])) {
 252              $options['socket']['bindto'] = $this->params['sourceIp'].':0';
 253          }
 254  
 255          if (isset($this->params['stream_context_options'])) {
 256              $options = array_merge($options, $this->params['stream_context_options']);
 257          }
 258          $streamContext = stream_context_create($options);
 259  
 260          set_error_handler(function ($type, $msg) {
 261              throw new Swift_TransportException('Connection could not be established with host '.$this->params['host'].' :'.$msg);
 262          });
 263          try {
 264              $this->stream = stream_socket_client($host.':'.$this->params['port'], $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $streamContext);
 265          } finally {
 266              restore_error_handler();
 267          }
 268  
 269          if (!empty($this->params['blocking'])) {
 270              stream_set_blocking($this->stream, 1);
 271          } else {
 272              stream_set_blocking($this->stream, 0);
 273          }
 274          stream_set_timeout($this->stream, $timeout);
 275          $this->in = &$this->stream;
 276          $this->out = &$this->stream;
 277      }
 278  
 279      /**
 280       * Opens a process for input/output.
 281       */
 282      private function establishProcessConnection()
 283      {
 284          $command = $this->params['command'];
 285          $descriptorSpec = [
 286              0 => ['pipe', 'r'],
 287              1 => ['pipe', 'w'],
 288              2 => ['pipe', 'w'],
 289              ];
 290          $pipes = [];
 291          $this->stream = proc_open($command, $descriptorSpec, $pipes);
 292          stream_set_blocking($pipes[2], 0);
 293          if ($err = stream_get_contents($pipes[2])) {
 294              throw new Swift_TransportException('Process could not be started ['.$err.']');
 295          }
 296          $this->in = &$pipes[0];
 297          $this->out = &$pipes[1];
 298      }
 299  
 300      private function getReadConnectionDescription()
 301      {
 302          switch ($this->params['type']) {
 303              case self::TYPE_PROCESS:
 304                  return 'Process '.$this->params['command'];
 305                  break;
 306  
 307              case self::TYPE_SOCKET:
 308              default:
 309                  $host = $this->params['host'];
 310                  if (!empty($this->params['protocol'])) {
 311                      $host = $this->params['protocol'].'://'.$host;
 312                  }
 313                  $host .= ':'.$this->params['port'];
 314  
 315                  return $host;
 316                  break;
 317          }
 318      }
 319  }


Generated: Tue May 19 15:55:14 2020 Cross-referenced by PHPXref 0.7.1