123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- <?php
- /*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace Symfony\Component\Mailer\Transport\Smtp\Stream;
- use Symfony\Component\Mailer\Exception\TransportException;
- /**
- * A stream supporting remote sockets and local processes.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- * @author Nicolas Grekas <p@tchwork.com>
- * @author Chris Corbyn
- *
- * @internal
- */
- abstract class AbstractStream
- {
- protected $stream;
- protected $in;
- protected $out;
- private $debug = '';
- public function write(string $bytes, bool $debug = true): void
- {
- if ($debug) {
- foreach (explode("\n", trim($bytes)) as $line) {
- $this->debug .= sprintf("> %s\n", $line);
- }
- }
- $bytesToWrite = \strlen($bytes);
- $totalBytesWritten = 0;
- while ($totalBytesWritten < $bytesToWrite) {
- $bytesWritten = @fwrite($this->in, substr($bytes, $totalBytesWritten));
- if (false === $bytesWritten || 0 === $bytesWritten) {
- throw new TransportException('Unable to write bytes on the wire.');
- }
- $totalBytesWritten += $bytesWritten;
- }
- }
- /**
- * Flushes the contents of the stream (empty it) and set the internal pointer to the beginning.
- */
- public function flush(): void
- {
- fflush($this->in);
- }
- /**
- * Performs any initialization needed.
- */
- abstract public function initialize(): void;
- public function terminate(): void
- {
- $this->stream = $this->out = $this->in = null;
- }
- public function readLine(): string
- {
- if (feof($this->out)) {
- return '';
- }
- $line = fgets($this->out);
- if (0 === \strlen($line)) {
- $metas = stream_get_meta_data($this->out);
- if ($metas['timed_out']) {
- throw new TransportException(sprintf('Connection to "%s" timed out.', $this->getReadConnectionDescription()));
- }
- if ($metas['eof']) {
- throw new TransportException(sprintf('Connection to "%s" has been closed unexpectedly.', $this->getReadConnectionDescription()));
- }
- }
- $this->debug .= sprintf('< %s', $line);
- return $line;
- }
- public function getDebug(): string
- {
- $debug = $this->debug;
- $this->debug = '';
- return $debug;
- }
- public static function replace(string $from, string $to, iterable $chunks): \Generator
- {
- if ('' === $from) {
- yield from $chunks;
- return;
- }
- $carry = '';
- $fromLen = \strlen($from);
- foreach ($chunks as $chunk) {
- if ('' === $chunk = $carry.$chunk) {
- continue;
- }
- if (false !== strpos($chunk, $from)) {
- $chunk = explode($from, $chunk);
- $carry = array_pop($chunk);
- yield implode($to, $chunk).$to;
- } else {
- $carry = $chunk;
- }
- if (\strlen($carry) > $fromLen) {
- yield substr($carry, 0, -$fromLen);
- $carry = substr($carry, -$fromLen);
- }
- }
- if ('' !== $carry) {
- yield $carry;
- }
- }
- abstract protected function getReadConnectionDescription(): string;
- }
|