Completed
Branch develop (aa6d31)
by
unknown
24:05
created
htdocs/includes/swiftmailer/lib/classes/Swift/CharacterStream.php 1 patch
Indentation   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -19,69 +19,69 @@
 block discarded – undo
19 19
  */
20 20
 interface Swift_CharacterStream
21 21
 {
22
-    /**
23
-     * Set the character set used in this CharacterStream.
24
-     *
25
-     * @param string $charset
26
-     */
27
-    public function setCharacterSet($charset);
22
+	/**
23
+	 * Set the character set used in this CharacterStream.
24
+	 *
25
+	 * @param string $charset
26
+	 */
27
+	public function setCharacterSet($charset);
28 28
 
29
-    /**
30
-     * Set the CharacterReaderFactory for multi charset support.
31
-     */
32
-    public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory);
29
+	/**
30
+	 * Set the CharacterReaderFactory for multi charset support.
31
+	 */
32
+	public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory);
33 33
 
34
-    /**
35
-     * Overwrite this character stream using the byte sequence in the byte stream.
36
-     *
37
-     * @param Swift_OutputByteStream $os output stream to read from
38
-     */
39
-    public function importByteStream(Swift_OutputByteStream $os);
34
+	/**
35
+	 * Overwrite this character stream using the byte sequence in the byte stream.
36
+	 *
37
+	 * @param Swift_OutputByteStream $os output stream to read from
38
+	 */
39
+	public function importByteStream(Swift_OutputByteStream $os);
40 40
 
41
-    /**
42
-     * Import a string a bytes into this CharacterStream, overwriting any existing
43
-     * data in the stream.
44
-     *
45
-     * @param string $string
46
-     */
47
-    public function importString($string);
41
+	/**
42
+	 * Import a string a bytes into this CharacterStream, overwriting any existing
43
+	 * data in the stream.
44
+	 *
45
+	 * @param string $string
46
+	 */
47
+	public function importString($string);
48 48
 
49
-    /**
50
-     * Read $length characters from the stream and move the internal pointer
51
-     * $length further into the stream.
52
-     *
53
-     * @param int $length
54
-     *
55
-     * @return string
56
-     */
57
-    public function read($length);
49
+	/**
50
+	 * Read $length characters from the stream and move the internal pointer
51
+	 * $length further into the stream.
52
+	 *
53
+	 * @param int $length
54
+	 *
55
+	 * @return string
56
+	 */
57
+	public function read($length);
58 58
 
59
-    /**
60
-     * Read $length characters from the stream and return a 1-dimensional array
61
-     * containing there octet values.
62
-     *
63
-     * @param int $length
64
-     *
65
-     * @return int[]
66
-     */
67
-    public function readBytes($length);
59
+	/**
60
+	 * Read $length characters from the stream and return a 1-dimensional array
61
+	 * containing there octet values.
62
+	 *
63
+	 * @param int $length
64
+	 *
65
+	 * @return int[]
66
+	 */
67
+	public function readBytes($length);
68 68
 
69
-    /**
70
-     * Write $chars to the end of the stream.
71
-     *
72
-     * @param string $chars
73
-     */
74
-    public function write($chars);
69
+	/**
70
+	 * Write $chars to the end of the stream.
71
+	 *
72
+	 * @param string $chars
73
+	 */
74
+	public function write($chars);
75 75
 
76
-    /**
77
-     * Move the internal pointer to $charOffset in the stream.
78
-     *
79
-     * @param int $charOffset
80
-     */
81
-    public function setPointer($charOffset);
76
+	/**
77
+	 * Move the internal pointer to $charOffset in the stream.
78
+	 *
79
+	 * @param int $charOffset
80
+	 */
81
+	public function setPointer($charOffset);
82 82
 
83
-    /**
84
-     * Empty the stream and reset the internal pointer.
85
-     */
86
-    public function flushContents();
83
+	/**
84
+	 * Empty the stream and reset the internal pointer.
85
+	 */
86
+	public function flushContents();
87 87
 }
Please login to merge, or discard this patch.
htdocs/includes/swiftmailer/lib/classes/Swift/TransportException.php 1 patch
Indentation   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -15,14 +15,14 @@
 block discarded – undo
15 15
  */
16 16
 class Swift_TransportException extends Swift_IoException
17 17
 {
18
-    /**
19
-     * Create a new TransportException with $message.
20
-     *
21
-     * @param string $message
22
-     * @param int    $code
23
-     */
24
-    public function __construct($message, $code = 0, Exception $previous = null)
25
-    {
26
-        parent::__construct($message, $code, $previous);
27
-    }
18
+	/**
19
+	 * Create a new TransportException with $message.
20
+	 *
21
+	 * @param string $message
22
+	 * @param int    $code
23
+	 */
24
+	public function __construct($message, $code = 0, Exception $previous = null)
25
+	{
26
+		parent::__construct($message, $code, $previous);
27
+	}
28 28
 }
Please login to merge, or discard this patch.
htdocs/includes/swiftmailer/lib/classes/Swift/Image.php 1 patch
Indentation   +24 added lines, -24 removed lines patch added patch discarded remove patch
@@ -15,29 +15,29 @@
 block discarded – undo
15 15
  */
16 16
 class Swift_Image extends Swift_EmbeddedFile
17 17
 {
18
-    /**
19
-     * Create a new EmbeddedFile.
20
-     *
21
-     * Details may be optionally provided to the constructor.
22
-     *
23
-     * @param string|Swift_OutputByteStream $data
24
-     * @param string                        $filename
25
-     * @param string                        $contentType
26
-     */
27
-    public function __construct($data = null, $filename = null, $contentType = null)
28
-    {
29
-        parent::__construct($data, $filename, $contentType);
30
-    }
18
+	/**
19
+	 * Create a new EmbeddedFile.
20
+	 *
21
+	 * Details may be optionally provided to the constructor.
22
+	 *
23
+	 * @param string|Swift_OutputByteStream $data
24
+	 * @param string                        $filename
25
+	 * @param string                        $contentType
26
+	 */
27
+	public function __construct($data = null, $filename = null, $contentType = null)
28
+	{
29
+		parent::__construct($data, $filename, $contentType);
30
+	}
31 31
 
32
-    /**
33
-     * Create a new Image from a filesystem path.
34
-     *
35
-     * @param string $path
36
-     *
37
-     * @return self
38
-     */
39
-    public static function fromPath($path)
40
-    {
41
-        return (new self())->setFile(new Swift_ByteStream_FileByteStream($path));
42
-    }
32
+	/**
33
+	 * Create a new Image from a filesystem path.
34
+	 *
35
+	 * @param string $path
36
+	 *
37
+	 * @return self
38
+	 */
39
+	public static function fromPath($path)
40
+	{
41
+		return (new self())->setFile(new Swift_ByteStream_FileByteStream($path));
42
+	}
43 43
 }
Please login to merge, or discard this patch.
htdocs/includes/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php 1 patch
Indentation   +522 added lines, -522 removed lines patch added patch discarded remove patch
@@ -17,526 +17,526 @@
 block discarded – undo
17 17
  */
18 18
 class Swift_Signers_SMimeSigner implements Swift_Signers_BodySigner
19 19
 {
20
-    protected $signCertificate;
21
-    protected $signPrivateKey;
22
-    protected $encryptCert;
23
-    protected $signThenEncrypt = true;
24
-    protected $signLevel;
25
-    protected $encryptLevel;
26
-    protected $signOptions;
27
-    protected $encryptOptions;
28
-    protected $encryptCipher;
29
-    protected $extraCerts = null;
30
-    protected $wrapFullMessage = false;
31
-
32
-    /**
33
-     * @var Swift_StreamFilters_StringReplacementFilterFactory
34
-     */
35
-    protected $replacementFactory;
36
-
37
-    /**
38
-     * @var Swift_Mime_SimpleHeaderFactory
39
-     */
40
-    protected $headerFactory;
41
-
42
-    /**
43
-     * Constructor.
44
-     *
45
-     * @param string|null $signCertificate
46
-     * @param string|null $signPrivateKey
47
-     * @param string|null $encryptCertificate
48
-     */
49
-    public function __construct($signCertificate = null, $signPrivateKey = null, $encryptCertificate = null)
50
-    {
51
-        if (null !== $signPrivateKey) {
52
-            $this->setSignCertificate($signCertificate, $signPrivateKey);
53
-        }
54
-
55
-        if (null !== $encryptCertificate) {
56
-            $this->setEncryptCertificate($encryptCertificate);
57
-        }
58
-
59
-        $this->replacementFactory = Swift_DependencyContainer::getInstance()
60
-            ->lookup('transport.replacementfactory');
61
-
62
-        $this->signOptions = PKCS7_DETACHED;
63
-        $this->encryptCipher = OPENSSL_CIPHER_AES_128_CBC;
64
-    }
65
-
66
-    /**
67
-     * Set the certificate location to use for signing.
68
-     *
69
-     * @see https://secure.php.net/manual/en/openssl.pkcs7.flags.php
70
-     *
71
-     * @param string       $certificate
72
-     * @param string|array $privateKey  If the key needs an passphrase use array('file-location', 'passphrase') instead
73
-     * @param int          $signOptions Bitwise operator options for openssl_pkcs7_sign()
74
-     * @param string       $extraCerts  A file containing intermediate certificates needed by the signing certificate
75
-     *
76
-     * @return $this
77
-     */
78
-    public function setSignCertificate($certificate, $privateKey = null, $signOptions = PKCS7_DETACHED, $extraCerts = null)
79
-    {
80
-        $this->signCertificate = 'file://'.str_replace('\\', '/', realpath($certificate));
81
-
82
-        if (null !== $privateKey) {
83
-            if (\is_array($privateKey)) {
84
-                $this->signPrivateKey = $privateKey;
85
-                $this->signPrivateKey[0] = 'file://'.str_replace('\\', '/', realpath($privateKey[0]));
86
-            } else {
87
-                $this->signPrivateKey = 'file://'.str_replace('\\', '/', realpath($privateKey));
88
-            }
89
-        }
90
-
91
-        $this->signOptions = $signOptions;
92
-        $this->extraCerts = $extraCerts ? realpath($extraCerts) : null;
93
-
94
-        return $this;
95
-    }
96
-
97
-    /**
98
-     * Set the certificate location to use for encryption.
99
-     *
100
-     * @see https://secure.php.net/manual/en/openssl.pkcs7.flags.php
101
-     * @see https://secure.php.net/manual/en/openssl.ciphers.php
102
-     *
103
-     * @param string|array $recipientCerts Either an single X.509 certificate, or an assoc array of X.509 certificates.
104
-     * @param int          $cipher
105
-     *
106
-     * @return $this
107
-     */
108
-    public function setEncryptCertificate($recipientCerts, $cipher = null)
109
-    {
110
-        if (\is_array($recipientCerts)) {
111
-            $this->encryptCert = [];
112
-
113
-            foreach ($recipientCerts as $cert) {
114
-                $this->encryptCert[] = 'file://'.str_replace('\\', '/', realpath($cert));
115
-            }
116
-        } else {
117
-            $this->encryptCert = 'file://'.str_replace('\\', '/', realpath($recipientCerts));
118
-        }
119
-
120
-        if (null !== $cipher) {
121
-            $this->encryptCipher = $cipher;
122
-        }
123
-
124
-        return $this;
125
-    }
126
-
127
-    /**
128
-     * @return string
129
-     */
130
-    public function getSignCertificate()
131
-    {
132
-        return $this->signCertificate;
133
-    }
134
-
135
-    /**
136
-     * @return string
137
-     */
138
-    public function getSignPrivateKey()
139
-    {
140
-        return $this->signPrivateKey;
141
-    }
142
-
143
-    /**
144
-     * Set perform signing before encryption.
145
-     *
146
-     * The default is to first sign the message and then encrypt.
147
-     * But some older mail clients, namely Microsoft Outlook 2000 will work when the message first encrypted.
148
-     * As this goes against the official specs, its recommended to only use 'encryption -> signing' when specifically targeting these 'broken' clients.
149
-     *
150
-     * @param bool $signThenEncrypt
151
-     *
152
-     * @return $this
153
-     */
154
-    public function setSignThenEncrypt($signThenEncrypt = true)
155
-    {
156
-        $this->signThenEncrypt = $signThenEncrypt;
157
-
158
-        return $this;
159
-    }
160
-
161
-    /**
162
-     * @return bool
163
-     */
164
-    public function isSignThenEncrypt()
165
-    {
166
-        return $this->signThenEncrypt;
167
-    }
168
-
169
-    /**
170
-     * Resets internal states.
171
-     *
172
-     * @return $this
173
-     */
174
-    public function reset()
175
-    {
176
-        return $this;
177
-    }
178
-
179
-    /**
180
-     * Specify whether to wrap the entire MIME message in the S/MIME message.
181
-     *
182
-     * According to RFC5751 section 3.1:
183
-     * In order to protect outer, non-content-related message header fields
184
-     * (for instance, the "Subject", "To", "From", and "Cc" fields), the
185
-     * sending client MAY wrap a full MIME message in a message/rfc822
186
-     * wrapper in order to apply S/MIME security services to these header
187
-     * fields.  It is up to the receiving client to decide how to present
188
-     * this "inner" header along with the unprotected "outer" header.
189
-     *
190
-     * @param bool $wrap
191
-     *
192
-     * @return $this
193
-     */
194
-    public function setWrapFullMessage($wrap)
195
-    {
196
-        $this->wrapFullMessage = $wrap;
197
-    }
198
-
199
-    /**
200
-     * Change the Swift_Message to apply the signing.
201
-     *
202
-     * @return $this
203
-     */
204
-    public function signMessage(Swift_Message $message)
205
-    {
206
-        if (null === $this->signCertificate && null === $this->encryptCert) {
207
-            return $this;
208
-        }
209
-
210
-        if ($this->signThenEncrypt) {
211
-            $this->smimeSignMessage($message);
212
-            $this->smimeEncryptMessage($message);
213
-        } else {
214
-            $this->smimeEncryptMessage($message);
215
-            $this->smimeSignMessage($message);
216
-        }
217
-    }
218
-
219
-    /**
220
-     * Return the list of header a signer might tamper.
221
-     *
222
-     * @return array
223
-     */
224
-    public function getAlteredHeaders()
225
-    {
226
-        return ['Content-Type', 'Content-Transfer-Encoding', 'Content-Disposition'];
227
-    }
228
-
229
-    /**
230
-     * Sign a Swift message.
231
-     */
232
-    protected function smimeSignMessage(Swift_Message $message)
233
-    {
234
-        // If we don't have a certificate we can't sign the message
235
-        if (null === $this->signCertificate) {
236
-            return;
237
-        }
238
-
239
-        // Work on a clone of the original message
240
-        $signMessage = clone $message;
241
-        $signMessage->clearSigners();
242
-
243
-        if ($this->wrapFullMessage) {
244
-            // The original message essentially becomes the body of the new
245
-            // wrapped message
246
-            $signMessage = $this->wrapMimeMessage($signMessage);
247
-        } else {
248
-            // Only keep header needed to parse the body correctly
249
-            $this->clearAllHeaders($signMessage);
250
-            $this->copyHeaders(
251
-                $message,
252
-                $signMessage,
253
-                [
254
-                    'Content-Type',
255
-                    'Content-Transfer-Encoding',
256
-                    'Content-Disposition',
257
-                ]
258
-            );
259
-        }
260
-
261
-        // Copy the cloned message into a temporary file stream
262
-        $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
263
-        $signMessage->toByteStream($messageStream);
264
-        $messageStream->commit();
265
-        $signedMessageStream = new Swift_ByteStream_TemporaryFileByteStream();
266
-
267
-        // Sign the message using openssl
268
-        if (!openssl_pkcs7_sign(
269
-                $messageStream->getPath(),
270
-                $signedMessageStream->getPath(),
271
-                $this->signCertificate,
272
-                $this->signPrivateKey,
273
-                [],
274
-                $this->signOptions,
275
-                $this->extraCerts
276
-            )
277
-        ) {
278
-            throw new Swift_IoException(sprintf('Failed to sign S/Mime message. Error: "%s".', openssl_error_string()));
279
-        }
280
-
281
-        // Parse the resulting signed message content back into the Swift message
282
-        // preserving the original headers
283
-        $this->parseSSLOutput($signedMessageStream, $message);
284
-    }
285
-
286
-    /**
287
-     * Encrypt a Swift message.
288
-     */
289
-    protected function smimeEncryptMessage(Swift_Message $message)
290
-    {
291
-        // If we don't have a certificate we can't encrypt the message
292
-        if (null === $this->encryptCert) {
293
-            return;
294
-        }
295
-
296
-        // Work on a clone of the original message
297
-        $encryptMessage = clone $message;
298
-        $encryptMessage->clearSigners();
299
-
300
-        if ($this->wrapFullMessage) {
301
-            // The original message essentially becomes the body of the new
302
-            // wrapped message
303
-            $encryptMessage = $this->wrapMimeMessage($encryptMessage);
304
-        } else {
305
-            // Only keep header needed to parse the body correctly
306
-            $this->clearAllHeaders($encryptMessage);
307
-            $this->copyHeaders(
308
-                $message,
309
-                $encryptMessage,
310
-                [
311
-                    'Content-Type',
312
-                    'Content-Transfer-Encoding',
313
-                    'Content-Disposition',
314
-                ]
315
-            );
316
-        }
317
-
318
-        // Convert the message content (including headers) to a string
319
-        // and place it in a temporary file
320
-        $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
321
-        $encryptMessage->toByteStream($messageStream);
322
-        $messageStream->commit();
323
-        $encryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream();
324
-
325
-        // Encrypt the message
326
-        if (!openssl_pkcs7_encrypt(
327
-                $messageStream->getPath(),
328
-                $encryptedMessageStream->getPath(),
329
-                $this->encryptCert,
330
-                [],
331
-                0,
332
-                $this->encryptCipher
333
-            )
334
-        ) {
335
-            throw new Swift_IoException(sprintf('Failed to encrypt S/Mime message. Error: "%s".', openssl_error_string()));
336
-        }
337
-
338
-        // Parse the resulting signed message content back into the Swift message
339
-        // preserving the original headers
340
-        $this->parseSSLOutput($encryptedMessageStream, $message);
341
-    }
342
-
343
-    /**
344
-     * Copy named headers from one Swift message to another.
345
-     */
346
-    protected function copyHeaders(
347
-        Swift_Message $fromMessage,
348
-        Swift_Message $toMessage,
349
-        array $headers = []
350
-    ) {
351
-        foreach ($headers as $header) {
352
-            $this->copyHeader($fromMessage, $toMessage, $header);
353
-        }
354
-    }
355
-
356
-    /**
357
-     * Copy a single header from one Swift message to another.
358
-     *
359
-     * @param string $headerName
360
-     */
361
-    protected function copyHeader(Swift_Message $fromMessage, Swift_Message $toMessage, $headerName)
362
-    {
363
-        $header = $fromMessage->getHeaders()->get($headerName);
364
-        if (!$header) {
365
-            return;
366
-        }
367
-        $headers = $toMessage->getHeaders();
368
-        switch ($header->getFieldType()) {
369
-            case Swift_Mime_Header::TYPE_TEXT:
370
-                $headers->addTextHeader($header->getFieldName(), $header->getValue());
371
-                break;
372
-            case Swift_Mime_Header::TYPE_PARAMETERIZED:
373
-                $headers->addParameterizedHeader(
374
-                    $header->getFieldName(),
375
-                    $header->getValue(),
376
-                    $header->getParameters()
377
-                );
378
-                break;
379
-        }
380
-    }
381
-
382
-    /**
383
-     * Remove all headers from a Swift message.
384
-     */
385
-    protected function clearAllHeaders(Swift_Message $message)
386
-    {
387
-        $headers = $message->getHeaders();
388
-        foreach ($headers->listAll() as $header) {
389
-            $headers->removeAll($header);
390
-        }
391
-    }
392
-
393
-    /**
394
-     * Wraps a Swift_Message in a message/rfc822 MIME part.
395
-     *
396
-     * @return Swift_MimePart
397
-     */
398
-    protected function wrapMimeMessage(Swift_Message $message)
399
-    {
400
-        // Start by copying the original message into a message stream
401
-        $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
402
-        $message->toByteStream($messageStream);
403
-        $messageStream->commit();
404
-
405
-        // Create a new MIME part that wraps the original stream
406
-        $wrappedMessage = new Swift_MimePart($messageStream, 'message/rfc822');
407
-        $wrappedMessage->setEncoder(new Swift_Mime_ContentEncoder_PlainContentEncoder('7bit'));
408
-
409
-        return $wrappedMessage;
410
-    }
411
-
412
-    protected function parseSSLOutput(Swift_InputByteStream $inputStream, Swift_Message $message)
413
-    {
414
-        $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
415
-        $this->copyFromOpenSSLOutput($inputStream, $messageStream);
416
-
417
-        $this->streamToMime($messageStream, $message);
418
-    }
419
-
420
-    /**
421
-     * Merges an OutputByteStream from OpenSSL to a Swift_Message.
422
-     */
423
-    protected function streamToMime(Swift_OutputByteStream $fromStream, Swift_Message $message)
424
-    {
425
-        // Parse the stream into headers and body
426
-        list($headers, $messageStream) = $this->parseStream($fromStream);
427
-
428
-        // Get the original message headers
429
-        $messageHeaders = $message->getHeaders();
430
-
431
-        // Let the stream determine the headers describing the body content,
432
-        // since the body of the original message is overwritten by the body
433
-        // coming from the stream.
434
-        // These are all content-* headers.
435
-
436
-        // Default transfer encoding is 7bit if not set
437
-        $encoding = '';
438
-        // Remove all existing transfer encoding headers
439
-        $messageHeaders->removeAll('Content-Transfer-Encoding');
440
-        // See whether the stream sets the transfer encoding
441
-        if (isset($headers['content-transfer-encoding'])) {
442
-            $encoding = $headers['content-transfer-encoding'];
443
-        }
444
-
445
-        // We use the null content encoder, since the body is already encoded
446
-        // according to the transfer encoding specified in the stream
447
-        $message->setEncoder(new Swift_Mime_ContentEncoder_NullContentEncoder($encoding));
448
-
449
-        // Set the disposition, if present
450
-        if (isset($headers['content-disposition'])) {
451
-            $messageHeaders->addTextHeader('Content-Disposition', $headers['content-disposition']);
452
-        }
453
-
454
-        // Copy over the body from the stream using the content type dictated
455
-        // by the stream content
456
-        $message->setChildren([]);
457
-        $message->setBody($messageStream, $headers['content-type']);
458
-    }
459
-
460
-    /**
461
-     * This message will parse the headers of a MIME email byte stream
462
-     * and return an array that contains the headers as an associative
463
-     * array and the email body as a string.
464
-     *
465
-     * @return array
466
-     */
467
-    protected function parseStream(Swift_OutputByteStream $emailStream)
468
-    {
469
-        $bufferLength = 78;
470
-        $headerData = '';
471
-        $headerBodySeparator = "\r\n\r\n";
472
-
473
-        $emailStream->setReadPointer(0);
474
-
475
-        // Read out the headers section from the stream to a string
476
-        while (false !== ($buffer = $emailStream->read($bufferLength))) {
477
-            $headerData .= $buffer;
478
-
479
-            $headersPosEnd = strpos($headerData, $headerBodySeparator);
480
-
481
-            // Stop reading if we found the end of the headers
482
-            if (false !== $headersPosEnd) {
483
-                break;
484
-            }
485
-        }
486
-
487
-        // Split the header data into lines
488
-        $headerData = trim(substr($headerData, 0, $headersPosEnd));
489
-        $headerLines = explode("\r\n", $headerData);
490
-        unset($headerData);
491
-
492
-        $headers = [];
493
-        $currentHeaderName = '';
494
-
495
-        // Transform header lines into an associative array
496
-        foreach ($headerLines as $headerLine) {
497
-            // Handle headers that span multiple lines
498
-            if (false === strpos($headerLine, ':')) {
499
-                $headers[$currentHeaderName] .= ' '.trim($headerLine ?? '');
500
-                continue;
501
-            }
502
-
503
-            $header = explode(':', $headerLine, 2);
504
-            $currentHeaderName = strtolower($header[0] ?? '');
505
-            $headers[$currentHeaderName] = trim($header[1] ?? '');
506
-        }
507
-
508
-        // Read the entire email body into a byte stream
509
-        $bodyStream = new Swift_ByteStream_TemporaryFileByteStream();
510
-
511
-        // Skip the header and separator and point to the body
512
-        $emailStream->setReadPointer($headersPosEnd + \strlen($headerBodySeparator));
513
-
514
-        while (false !== ($buffer = $emailStream->read($bufferLength))) {
515
-            $bodyStream->write($buffer);
516
-        }
517
-
518
-        $bodyStream->commit();
519
-
520
-        return [$headers, $bodyStream];
521
-    }
522
-
523
-    protected function copyFromOpenSSLOutput(Swift_OutputByteStream $fromStream, Swift_InputByteStream $toStream)
524
-    {
525
-        $bufferLength = 4096;
526
-        $filteredStream = new Swift_ByteStream_TemporaryFileByteStream();
527
-        $filteredStream->addFilter($this->replacementFactory->createFilter("\r\n", "\n"), 'CRLF to LF');
528
-        $filteredStream->addFilter($this->replacementFactory->createFilter("\n", "\r\n"), 'LF to CRLF');
529
-
530
-        while (false !== ($buffer = $fromStream->read($bufferLength))) {
531
-            $filteredStream->write($buffer);
532
-        }
533
-
534
-        $filteredStream->flushBuffers();
535
-
536
-        while (false !== ($buffer = $filteredStream->read($bufferLength))) {
537
-            $toStream->write($buffer);
538
-        }
539
-
540
-        $toStream->commit();
541
-    }
20
+	protected $signCertificate;
21
+	protected $signPrivateKey;
22
+	protected $encryptCert;
23
+	protected $signThenEncrypt = true;
24
+	protected $signLevel;
25
+	protected $encryptLevel;
26
+	protected $signOptions;
27
+	protected $encryptOptions;
28
+	protected $encryptCipher;
29
+	protected $extraCerts = null;
30
+	protected $wrapFullMessage = false;
31
+
32
+	/**
33
+	 * @var Swift_StreamFilters_StringReplacementFilterFactory
34
+	 */
35
+	protected $replacementFactory;
36
+
37
+	/**
38
+	 * @var Swift_Mime_SimpleHeaderFactory
39
+	 */
40
+	protected $headerFactory;
41
+
42
+	/**
43
+	 * Constructor.
44
+	 *
45
+	 * @param string|null $signCertificate
46
+	 * @param string|null $signPrivateKey
47
+	 * @param string|null $encryptCertificate
48
+	 */
49
+	public function __construct($signCertificate = null, $signPrivateKey = null, $encryptCertificate = null)
50
+	{
51
+		if (null !== $signPrivateKey) {
52
+			$this->setSignCertificate($signCertificate, $signPrivateKey);
53
+		}
54
+
55
+		if (null !== $encryptCertificate) {
56
+			$this->setEncryptCertificate($encryptCertificate);
57
+		}
58
+
59
+		$this->replacementFactory = Swift_DependencyContainer::getInstance()
60
+			->lookup('transport.replacementfactory');
61
+
62
+		$this->signOptions = PKCS7_DETACHED;
63
+		$this->encryptCipher = OPENSSL_CIPHER_AES_128_CBC;
64
+	}
65
+
66
+	/**
67
+	 * Set the certificate location to use for signing.
68
+	 *
69
+	 * @see https://secure.php.net/manual/en/openssl.pkcs7.flags.php
70
+	 *
71
+	 * @param string       $certificate
72
+	 * @param string|array $privateKey  If the key needs an passphrase use array('file-location', 'passphrase') instead
73
+	 * @param int          $signOptions Bitwise operator options for openssl_pkcs7_sign()
74
+	 * @param string       $extraCerts  A file containing intermediate certificates needed by the signing certificate
75
+	 *
76
+	 * @return $this
77
+	 */
78
+	public function setSignCertificate($certificate, $privateKey = null, $signOptions = PKCS7_DETACHED, $extraCerts = null)
79
+	{
80
+		$this->signCertificate = 'file://'.str_replace('\\', '/', realpath($certificate));
81
+
82
+		if (null !== $privateKey) {
83
+			if (\is_array($privateKey)) {
84
+				$this->signPrivateKey = $privateKey;
85
+				$this->signPrivateKey[0] = 'file://'.str_replace('\\', '/', realpath($privateKey[0]));
86
+			} else {
87
+				$this->signPrivateKey = 'file://'.str_replace('\\', '/', realpath($privateKey));
88
+			}
89
+		}
90
+
91
+		$this->signOptions = $signOptions;
92
+		$this->extraCerts = $extraCerts ? realpath($extraCerts) : null;
93
+
94
+		return $this;
95
+	}
96
+
97
+	/**
98
+	 * Set the certificate location to use for encryption.
99
+	 *
100
+	 * @see https://secure.php.net/manual/en/openssl.pkcs7.flags.php
101
+	 * @see https://secure.php.net/manual/en/openssl.ciphers.php
102
+	 *
103
+	 * @param string|array $recipientCerts Either an single X.509 certificate, or an assoc array of X.509 certificates.
104
+	 * @param int          $cipher
105
+	 *
106
+	 * @return $this
107
+	 */
108
+	public function setEncryptCertificate($recipientCerts, $cipher = null)
109
+	{
110
+		if (\is_array($recipientCerts)) {
111
+			$this->encryptCert = [];
112
+
113
+			foreach ($recipientCerts as $cert) {
114
+				$this->encryptCert[] = 'file://'.str_replace('\\', '/', realpath($cert));
115
+			}
116
+		} else {
117
+			$this->encryptCert = 'file://'.str_replace('\\', '/', realpath($recipientCerts));
118
+		}
119
+
120
+		if (null !== $cipher) {
121
+			$this->encryptCipher = $cipher;
122
+		}
123
+
124
+		return $this;
125
+	}
126
+
127
+	/**
128
+	 * @return string
129
+	 */
130
+	public function getSignCertificate()
131
+	{
132
+		return $this->signCertificate;
133
+	}
134
+
135
+	/**
136
+	 * @return string
137
+	 */
138
+	public function getSignPrivateKey()
139
+	{
140
+		return $this->signPrivateKey;
141
+	}
142
+
143
+	/**
144
+	 * Set perform signing before encryption.
145
+	 *
146
+	 * The default is to first sign the message and then encrypt.
147
+	 * But some older mail clients, namely Microsoft Outlook 2000 will work when the message first encrypted.
148
+	 * As this goes against the official specs, its recommended to only use 'encryption -> signing' when specifically targeting these 'broken' clients.
149
+	 *
150
+	 * @param bool $signThenEncrypt
151
+	 *
152
+	 * @return $this
153
+	 */
154
+	public function setSignThenEncrypt($signThenEncrypt = true)
155
+	{
156
+		$this->signThenEncrypt = $signThenEncrypt;
157
+
158
+		return $this;
159
+	}
160
+
161
+	/**
162
+	 * @return bool
163
+	 */
164
+	public function isSignThenEncrypt()
165
+	{
166
+		return $this->signThenEncrypt;
167
+	}
168
+
169
+	/**
170
+	 * Resets internal states.
171
+	 *
172
+	 * @return $this
173
+	 */
174
+	public function reset()
175
+	{
176
+		return $this;
177
+	}
178
+
179
+	/**
180
+	 * Specify whether to wrap the entire MIME message in the S/MIME message.
181
+	 *
182
+	 * According to RFC5751 section 3.1:
183
+	 * In order to protect outer, non-content-related message header fields
184
+	 * (for instance, the "Subject", "To", "From", and "Cc" fields), the
185
+	 * sending client MAY wrap a full MIME message in a message/rfc822
186
+	 * wrapper in order to apply S/MIME security services to these header
187
+	 * fields.  It is up to the receiving client to decide how to present
188
+	 * this "inner" header along with the unprotected "outer" header.
189
+	 *
190
+	 * @param bool $wrap
191
+	 *
192
+	 * @return $this
193
+	 */
194
+	public function setWrapFullMessage($wrap)
195
+	{
196
+		$this->wrapFullMessage = $wrap;
197
+	}
198
+
199
+	/**
200
+	 * Change the Swift_Message to apply the signing.
201
+	 *
202
+	 * @return $this
203
+	 */
204
+	public function signMessage(Swift_Message $message)
205
+	{
206
+		if (null === $this->signCertificate && null === $this->encryptCert) {
207
+			return $this;
208
+		}
209
+
210
+		if ($this->signThenEncrypt) {
211
+			$this->smimeSignMessage($message);
212
+			$this->smimeEncryptMessage($message);
213
+		} else {
214
+			$this->smimeEncryptMessage($message);
215
+			$this->smimeSignMessage($message);
216
+		}
217
+	}
218
+
219
+	/**
220
+	 * Return the list of header a signer might tamper.
221
+	 *
222
+	 * @return array
223
+	 */
224
+	public function getAlteredHeaders()
225
+	{
226
+		return ['Content-Type', 'Content-Transfer-Encoding', 'Content-Disposition'];
227
+	}
228
+
229
+	/**
230
+	 * Sign a Swift message.
231
+	 */
232
+	protected function smimeSignMessage(Swift_Message $message)
233
+	{
234
+		// If we don't have a certificate we can't sign the message
235
+		if (null === $this->signCertificate) {
236
+			return;
237
+		}
238
+
239
+		// Work on a clone of the original message
240
+		$signMessage = clone $message;
241
+		$signMessage->clearSigners();
242
+
243
+		if ($this->wrapFullMessage) {
244
+			// The original message essentially becomes the body of the new
245
+			// wrapped message
246
+			$signMessage = $this->wrapMimeMessage($signMessage);
247
+		} else {
248
+			// Only keep header needed to parse the body correctly
249
+			$this->clearAllHeaders($signMessage);
250
+			$this->copyHeaders(
251
+				$message,
252
+				$signMessage,
253
+				[
254
+					'Content-Type',
255
+					'Content-Transfer-Encoding',
256
+					'Content-Disposition',
257
+				]
258
+			);
259
+		}
260
+
261
+		// Copy the cloned message into a temporary file stream
262
+		$messageStream = new Swift_ByteStream_TemporaryFileByteStream();
263
+		$signMessage->toByteStream($messageStream);
264
+		$messageStream->commit();
265
+		$signedMessageStream = new Swift_ByteStream_TemporaryFileByteStream();
266
+
267
+		// Sign the message using openssl
268
+		if (!openssl_pkcs7_sign(
269
+				$messageStream->getPath(),
270
+				$signedMessageStream->getPath(),
271
+				$this->signCertificate,
272
+				$this->signPrivateKey,
273
+				[],
274
+				$this->signOptions,
275
+				$this->extraCerts
276
+			)
277
+		) {
278
+			throw new Swift_IoException(sprintf('Failed to sign S/Mime message. Error: "%s".', openssl_error_string()));
279
+		}
280
+
281
+		// Parse the resulting signed message content back into the Swift message
282
+		// preserving the original headers
283
+		$this->parseSSLOutput($signedMessageStream, $message);
284
+	}
285
+
286
+	/**
287
+	 * Encrypt a Swift message.
288
+	 */
289
+	protected function smimeEncryptMessage(Swift_Message $message)
290
+	{
291
+		// If we don't have a certificate we can't encrypt the message
292
+		if (null === $this->encryptCert) {
293
+			return;
294
+		}
295
+
296
+		// Work on a clone of the original message
297
+		$encryptMessage = clone $message;
298
+		$encryptMessage->clearSigners();
299
+
300
+		if ($this->wrapFullMessage) {
301
+			// The original message essentially becomes the body of the new
302
+			// wrapped message
303
+			$encryptMessage = $this->wrapMimeMessage($encryptMessage);
304
+		} else {
305
+			// Only keep header needed to parse the body correctly
306
+			$this->clearAllHeaders($encryptMessage);
307
+			$this->copyHeaders(
308
+				$message,
309
+				$encryptMessage,
310
+				[
311
+					'Content-Type',
312
+					'Content-Transfer-Encoding',
313
+					'Content-Disposition',
314
+				]
315
+			);
316
+		}
317
+
318
+		// Convert the message content (including headers) to a string
319
+		// and place it in a temporary file
320
+		$messageStream = new Swift_ByteStream_TemporaryFileByteStream();
321
+		$encryptMessage->toByteStream($messageStream);
322
+		$messageStream->commit();
323
+		$encryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream();
324
+
325
+		// Encrypt the message
326
+		if (!openssl_pkcs7_encrypt(
327
+				$messageStream->getPath(),
328
+				$encryptedMessageStream->getPath(),
329
+				$this->encryptCert,
330
+				[],
331
+				0,
332
+				$this->encryptCipher
333
+			)
334
+		) {
335
+			throw new Swift_IoException(sprintf('Failed to encrypt S/Mime message. Error: "%s".', openssl_error_string()));
336
+		}
337
+
338
+		// Parse the resulting signed message content back into the Swift message
339
+		// preserving the original headers
340
+		$this->parseSSLOutput($encryptedMessageStream, $message);
341
+	}
342
+
343
+	/**
344
+	 * Copy named headers from one Swift message to another.
345
+	 */
346
+	protected function copyHeaders(
347
+		Swift_Message $fromMessage,
348
+		Swift_Message $toMessage,
349
+		array $headers = []
350
+	) {
351
+		foreach ($headers as $header) {
352
+			$this->copyHeader($fromMessage, $toMessage, $header);
353
+		}
354
+	}
355
+
356
+	/**
357
+	 * Copy a single header from one Swift message to another.
358
+	 *
359
+	 * @param string $headerName
360
+	 */
361
+	protected function copyHeader(Swift_Message $fromMessage, Swift_Message $toMessage, $headerName)
362
+	{
363
+		$header = $fromMessage->getHeaders()->get($headerName);
364
+		if (!$header) {
365
+			return;
366
+		}
367
+		$headers = $toMessage->getHeaders();
368
+		switch ($header->getFieldType()) {
369
+			case Swift_Mime_Header::TYPE_TEXT:
370
+				$headers->addTextHeader($header->getFieldName(), $header->getValue());
371
+				break;
372
+			case Swift_Mime_Header::TYPE_PARAMETERIZED:
373
+				$headers->addParameterizedHeader(
374
+					$header->getFieldName(),
375
+					$header->getValue(),
376
+					$header->getParameters()
377
+				);
378
+				break;
379
+		}
380
+	}
381
+
382
+	/**
383
+	 * Remove all headers from a Swift message.
384
+	 */
385
+	protected function clearAllHeaders(Swift_Message $message)
386
+	{
387
+		$headers = $message->getHeaders();
388
+		foreach ($headers->listAll() as $header) {
389
+			$headers->removeAll($header);
390
+		}
391
+	}
392
+
393
+	/**
394
+	 * Wraps a Swift_Message in a message/rfc822 MIME part.
395
+	 *
396
+	 * @return Swift_MimePart
397
+	 */
398
+	protected function wrapMimeMessage(Swift_Message $message)
399
+	{
400
+		// Start by copying the original message into a message stream
401
+		$messageStream = new Swift_ByteStream_TemporaryFileByteStream();
402
+		$message->toByteStream($messageStream);
403
+		$messageStream->commit();
404
+
405
+		// Create a new MIME part that wraps the original stream
406
+		$wrappedMessage = new Swift_MimePart($messageStream, 'message/rfc822');
407
+		$wrappedMessage->setEncoder(new Swift_Mime_ContentEncoder_PlainContentEncoder('7bit'));
408
+
409
+		return $wrappedMessage;
410
+	}
411
+
412
+	protected function parseSSLOutput(Swift_InputByteStream $inputStream, Swift_Message $message)
413
+	{
414
+		$messageStream = new Swift_ByteStream_TemporaryFileByteStream();
415
+		$this->copyFromOpenSSLOutput($inputStream, $messageStream);
416
+
417
+		$this->streamToMime($messageStream, $message);
418
+	}
419
+
420
+	/**
421
+	 * Merges an OutputByteStream from OpenSSL to a Swift_Message.
422
+	 */
423
+	protected function streamToMime(Swift_OutputByteStream $fromStream, Swift_Message $message)
424
+	{
425
+		// Parse the stream into headers and body
426
+		list($headers, $messageStream) = $this->parseStream($fromStream);
427
+
428
+		// Get the original message headers
429
+		$messageHeaders = $message->getHeaders();
430
+
431
+		// Let the stream determine the headers describing the body content,
432
+		// since the body of the original message is overwritten by the body
433
+		// coming from the stream.
434
+		// These are all content-* headers.
435
+
436
+		// Default transfer encoding is 7bit if not set
437
+		$encoding = '';
438
+		// Remove all existing transfer encoding headers
439
+		$messageHeaders->removeAll('Content-Transfer-Encoding');
440
+		// See whether the stream sets the transfer encoding
441
+		if (isset($headers['content-transfer-encoding'])) {
442
+			$encoding = $headers['content-transfer-encoding'];
443
+		}
444
+
445
+		// We use the null content encoder, since the body is already encoded
446
+		// according to the transfer encoding specified in the stream
447
+		$message->setEncoder(new Swift_Mime_ContentEncoder_NullContentEncoder($encoding));
448
+
449
+		// Set the disposition, if present
450
+		if (isset($headers['content-disposition'])) {
451
+			$messageHeaders->addTextHeader('Content-Disposition', $headers['content-disposition']);
452
+		}
453
+
454
+		// Copy over the body from the stream using the content type dictated
455
+		// by the stream content
456
+		$message->setChildren([]);
457
+		$message->setBody($messageStream, $headers['content-type']);
458
+	}
459
+
460
+	/**
461
+	 * This message will parse the headers of a MIME email byte stream
462
+	 * and return an array that contains the headers as an associative
463
+	 * array and the email body as a string.
464
+	 *
465
+	 * @return array
466
+	 */
467
+	protected function parseStream(Swift_OutputByteStream $emailStream)
468
+	{
469
+		$bufferLength = 78;
470
+		$headerData = '';
471
+		$headerBodySeparator = "\r\n\r\n";
472
+
473
+		$emailStream->setReadPointer(0);
474
+
475
+		// Read out the headers section from the stream to a string
476
+		while (false !== ($buffer = $emailStream->read($bufferLength))) {
477
+			$headerData .= $buffer;
478
+
479
+			$headersPosEnd = strpos($headerData, $headerBodySeparator);
480
+
481
+			// Stop reading if we found the end of the headers
482
+			if (false !== $headersPosEnd) {
483
+				break;
484
+			}
485
+		}
486
+
487
+		// Split the header data into lines
488
+		$headerData = trim(substr($headerData, 0, $headersPosEnd));
489
+		$headerLines = explode("\r\n", $headerData);
490
+		unset($headerData);
491
+
492
+		$headers = [];
493
+		$currentHeaderName = '';
494
+
495
+		// Transform header lines into an associative array
496
+		foreach ($headerLines as $headerLine) {
497
+			// Handle headers that span multiple lines
498
+			if (false === strpos($headerLine, ':')) {
499
+				$headers[$currentHeaderName] .= ' '.trim($headerLine ?? '');
500
+				continue;
501
+			}
502
+
503
+			$header = explode(':', $headerLine, 2);
504
+			$currentHeaderName = strtolower($header[0] ?? '');
505
+			$headers[$currentHeaderName] = trim($header[1] ?? '');
506
+		}
507
+
508
+		// Read the entire email body into a byte stream
509
+		$bodyStream = new Swift_ByteStream_TemporaryFileByteStream();
510
+
511
+		// Skip the header and separator and point to the body
512
+		$emailStream->setReadPointer($headersPosEnd + \strlen($headerBodySeparator));
513
+
514
+		while (false !== ($buffer = $emailStream->read($bufferLength))) {
515
+			$bodyStream->write($buffer);
516
+		}
517
+
518
+		$bodyStream->commit();
519
+
520
+		return [$headers, $bodyStream];
521
+	}
522
+
523
+	protected function copyFromOpenSSLOutput(Swift_OutputByteStream $fromStream, Swift_InputByteStream $toStream)
524
+	{
525
+		$bufferLength = 4096;
526
+		$filteredStream = new Swift_ByteStream_TemporaryFileByteStream();
527
+		$filteredStream->addFilter($this->replacementFactory->createFilter("\r\n", "\n"), 'CRLF to LF');
528
+		$filteredStream->addFilter($this->replacementFactory->createFilter("\n", "\r\n"), 'LF to CRLF');
529
+
530
+		while (false !== ($buffer = $fromStream->read($bufferLength))) {
531
+			$filteredStream->write($buffer);
532
+		}
533
+
534
+		$filteredStream->flushBuffers();
535
+
536
+		while (false !== ($buffer = $filteredStream->read($bufferLength))) {
537
+			$toStream->write($buffer);
538
+		}
539
+
540
+		$toStream->commit();
541
+	}
542 542
 }
Please login to merge, or discard this patch.
htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php 1 patch
Indentation   +664 added lines, -664 removed lines patch added patch discarded remove patch
@@ -15,668 +15,668 @@
 block discarded – undo
15 15
  */
16 16
 class Swift_Signers_DKIMSigner implements Swift_Signers_HeaderSigner
17 17
 {
18
-    /**
19
-     * PrivateKey.
20
-     *
21
-     * @var string
22
-     */
23
-    protected $privateKey;
24
-
25
-    /**
26
-     * DomainName.
27
-     *
28
-     * @var string
29
-     */
30
-    protected $domainName;
31
-
32
-    /**
33
-     * Selector.
34
-     *
35
-     * @var string
36
-     */
37
-    protected $selector;
38
-
39
-    private $passphrase = '';
40
-
41
-    /**
42
-     * Hash algorithm used.
43
-     *
44
-     * @see RFC6376 3.3: Signers MUST implement and SHOULD sign using rsa-sha256.
45
-     *
46
-     * @var string
47
-     */
48
-    protected $hashAlgorithm = 'rsa-sha256';
49
-
50
-    /**
51
-     * Body canon method.
52
-     *
53
-     * @var string
54
-     */
55
-    protected $bodyCanon = 'simple';
56
-
57
-    /**
58
-     * Header canon method.
59
-     *
60
-     * @var string
61
-     */
62
-    protected $headerCanon = 'simple';
63
-
64
-    /**
65
-     * Headers not being signed.
66
-     *
67
-     * @var array
68
-     */
69
-    protected $ignoredHeaders = ['return-path' => true];
70
-
71
-    /**
72
-     * Signer identity.
73
-     *
74
-     * @var string
75
-     */
76
-    protected $signerIdentity;
77
-
78
-    /**
79
-     * BodyLength.
80
-     *
81
-     * @var int
82
-     */
83
-    protected $bodyLen = 0;
84
-
85
-    /**
86
-     * Maximum signedLen.
87
-     *
88
-     * @var int
89
-     */
90
-    protected $maxLen = PHP_INT_MAX;
91
-
92
-    /**
93
-     * Embbed bodyLen in signature.
94
-     *
95
-     * @var bool
96
-     */
97
-    protected $showLen = false;
98
-
99
-    /**
100
-     * When the signature has been applied (true means time()), false means not embedded.
101
-     *
102
-     * @var mixed
103
-     */
104
-    protected $signatureTimestamp = true;
105
-
106
-    /**
107
-     * When will the signature expires false means not embedded, if sigTimestamp is auto
108
-     * Expiration is relative, otherwise it's absolute.
109
-     *
110
-     * @var int
111
-     */
112
-    protected $signatureExpiration = false;
113
-
114
-    /**
115
-     * Must we embed signed headers?
116
-     *
117
-     * @var bool
118
-     */
119
-    protected $debugHeaders = false;
120
-
121
-    // work variables
122
-    /**
123
-     * Headers used to generate hash.
124
-     *
125
-     * @var array
126
-     */
127
-    protected $signedHeaders = [];
128
-
129
-    /**
130
-     * If debugHeaders is set store debugData here.
131
-     *
132
-     * @var string[]
133
-     */
134
-    private $debugHeadersData = [];
135
-
136
-    /**
137
-     * Stores the bodyHash.
138
-     *
139
-     * @var string
140
-     */
141
-    private $bodyHash = '';
142
-
143
-    /**
144
-     * Stores the signature header.
145
-     *
146
-     * @var Swift_Mime_Headers_ParameterizedHeader
147
-     */
148
-    protected $dkimHeader;
149
-
150
-    private $bodyHashHandler;
151
-
152
-    private $headerHash;
153
-
154
-    private $headerCanonData = '';
155
-
156
-    private $bodyCanonEmptyCounter = 0;
157
-
158
-    private $bodyCanonIgnoreStart = 2;
159
-
160
-    private $bodyCanonSpace = false;
161
-
162
-    private $bodyCanonLastChar = null;
163
-
164
-    private $bodyCanonLine = '';
165
-
166
-    private $bound = [];
167
-
168
-    /**
169
-     * Constructor.
170
-     *
171
-     * @param string $privateKey
172
-     * @param string $domainName
173
-     * @param string $selector
174
-     * @param string $passphrase
175
-     */
176
-    public function __construct($privateKey, $domainName, $selector, $passphrase = '')
177
-    {
178
-        $this->privateKey = $privateKey;
179
-        $this->domainName = $domainName;
180
-        $this->signerIdentity = '@'.$domainName;
181
-        $this->selector = $selector;
182
-        $this->passphrase = $passphrase;
183
-    }
184
-
185
-    /**
186
-     * Reset the Signer.
187
-     *
188
-     * @see Swift_Signer::reset()
189
-     */
190
-    public function reset()
191
-    {
192
-        $this->headerHash = null;
193
-        $this->signedHeaders = [];
194
-        $this->bodyHash = null;
195
-        $this->bodyHashHandler = null;
196
-        $this->bodyCanonIgnoreStart = 2;
197
-        $this->bodyCanonEmptyCounter = 0;
198
-        $this->bodyCanonLastChar = null;
199
-        $this->bodyCanonSpace = false;
200
-    }
201
-
202
-    /**
203
-     * Writes $bytes to the end of the stream.
204
-     *
205
-     * Writing may not happen immediately if the stream chooses to buffer.  If
206
-     * you want to write these bytes with immediate effect, call {@link commit()}
207
-     * after calling write().
208
-     *
209
-     * This method returns the sequence ID of the write (i.e. 1 for first, 2 for
210
-     * second, etc etc).
211
-     *
212
-     * @param string $bytes
213
-     *
214
-     * @return int
215
-     *
216
-     * @throws Swift_IoException
217
-     */
218
-    // TODO fix return
219
-    public function write($bytes)
220
-    {
221
-        $this->canonicalizeBody($bytes);
222
-        foreach ($this->bound as $is) {
223
-            $is->write($bytes);
224
-        }
225
-    }
226
-
227
-    /**
228
-     * For any bytes that are currently buffered inside the stream, force them
229
-     * off the buffer.
230
-     */
231
-    public function commit()
232
-    {
233
-        // Nothing to do
234
-        return;
235
-    }
236
-
237
-    /**
238
-     * Attach $is to this stream.
239
-     *
240
-     * The stream acts as an observer, receiving all data that is written.
241
-     * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
242
-     */
243
-    public function bind(Swift_InputByteStream $is)
244
-    {
245
-        // Don't have to mirror anything
246
-        $this->bound[] = $is;
247
-
248
-        return;
249
-    }
250
-
251
-    /**
252
-     * Remove an already bound stream.
253
-     *
254
-     * If $is is not bound, no errors will be raised.
255
-     * If the stream currently has any buffered data it will be written to $is
256
-     * before unbinding occurs.
257
-     */
258
-    public function unbind(Swift_InputByteStream $is)
259
-    {
260
-        // Don't have to mirror anything
261
-        foreach ($this->bound as $k => $stream) {
262
-            if ($stream === $is) {
263
-                unset($this->bound[$k]);
264
-
265
-                return;
266
-            }
267
-        }
268
-    }
269
-
270
-    /**
271
-     * Flush the contents of the stream (empty it) and set the internal pointer
272
-     * to the beginning.
273
-     *
274
-     * @throws Swift_IoException
275
-     */
276
-    public function flushBuffers()
277
-    {
278
-        $this->reset();
279
-    }
280
-
281
-    /**
282
-     * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1.
283
-     *
284
-     * @param string $hash 'rsa-sha1' or 'rsa-sha256'
285
-     *
286
-     * @throws Swift_SwiftException
287
-     *
288
-     * @return $this
289
-     */
290
-    public function setHashAlgorithm($hash)
291
-    {
292
-        switch ($hash) {
293
-            case 'rsa-sha1':
294
-                $this->hashAlgorithm = 'rsa-sha1';
295
-                break;
296
-            case 'rsa-sha256':
297
-                $this->hashAlgorithm = 'rsa-sha256';
298
-                if (!\defined('OPENSSL_ALGO_SHA256')) {
299
-                    throw new Swift_SwiftException('Unable to set sha256 as it is not supported by OpenSSL.');
300
-                }
301
-                break;
302
-            default:
303
-                throw new Swift_SwiftException('Unable to set the hash algorithm, must be one of rsa-sha1 or rsa-sha256 (%s given).', $hash);
304
-        }
305
-
306
-        return $this;
307
-    }
308
-
309
-    /**
310
-     * Set the body canonicalization algorithm.
311
-     *
312
-     * @param string $canon
313
-     *
314
-     * @return $this
315
-     */
316
-    public function setBodyCanon($canon)
317
-    {
318
-        if ('relaxed' == $canon) {
319
-            $this->bodyCanon = 'relaxed';
320
-        } else {
321
-            $this->bodyCanon = 'simple';
322
-        }
323
-
324
-        return $this;
325
-    }
326
-
327
-    /**
328
-     * Set the header canonicalization algorithm.
329
-     *
330
-     * @param string $canon
331
-     *
332
-     * @return $this
333
-     */
334
-    public function setHeaderCanon($canon)
335
-    {
336
-        if ('relaxed' == $canon) {
337
-            $this->headerCanon = 'relaxed';
338
-        } else {
339
-            $this->headerCanon = 'simple';
340
-        }
341
-
342
-        return $this;
343
-    }
344
-
345
-    /**
346
-     * Set the signer identity.
347
-     *
348
-     * @param string $identity
349
-     *
350
-     * @return $this
351
-     */
352
-    public function setSignerIdentity($identity)
353
-    {
354
-        $this->signerIdentity = $identity;
355
-
356
-        return $this;
357
-    }
358
-
359
-    /**
360
-     * Set the length of the body to sign.
361
-     *
362
-     * @param mixed $len (bool or int)
363
-     *
364
-     * @return $this
365
-     */
366
-    public function setBodySignedLen($len)
367
-    {
368
-        if (true === $len) {
369
-            $this->showLen = true;
370
-            $this->maxLen = PHP_INT_MAX;
371
-        } elseif (false === $len) {
372
-            $this->showLen = false;
373
-            $this->maxLen = PHP_INT_MAX;
374
-        } else {
375
-            $this->showLen = true;
376
-            $this->maxLen = (int) $len;
377
-        }
378
-
379
-        return $this;
380
-    }
381
-
382
-    /**
383
-     * Set the signature timestamp.
384
-     *
385
-     * @param int $time A timestamp
386
-     *
387
-     * @return $this
388
-     */
389
-    public function setSignatureTimestamp($time)
390
-    {
391
-        $this->signatureTimestamp = $time;
392
-
393
-        return $this;
394
-    }
395
-
396
-    /**
397
-     * Set the signature expiration timestamp.
398
-     *
399
-     * @param int $time A timestamp
400
-     *
401
-     * @return $this
402
-     */
403
-    public function setSignatureExpiration($time)
404
-    {
405
-        $this->signatureExpiration = $time;
406
-
407
-        return $this;
408
-    }
409
-
410
-    /**
411
-     * Enable / disable the DebugHeaders.
412
-     *
413
-     * @param bool $debug
414
-     *
415
-     * @return Swift_Signers_DKIMSigner
416
-     */
417
-    public function setDebugHeaders($debug)
418
-    {
419
-        $this->debugHeaders = (bool) $debug;
420
-
421
-        return $this;
422
-    }
423
-
424
-    /**
425
-     * Start Body.
426
-     */
427
-    public function startBody()
428
-    {
429
-        // Init
430
-        switch ($this->hashAlgorithm) {
431
-            case 'rsa-sha256':
432
-                $this->bodyHashHandler = hash_init('sha256');
433
-                break;
434
-            case 'rsa-sha1':
435
-                $this->bodyHashHandler = hash_init('sha1');
436
-                break;
437
-        }
438
-        $this->bodyCanonLine = '';
439
-    }
440
-
441
-    /**
442
-     * End Body.
443
-     */
444
-    public function endBody()
445
-    {
446
-        $this->endOfBody();
447
-    }
448
-
449
-    /**
450
-     * Returns the list of Headers Tampered by this plugin.
451
-     *
452
-     * @return array
453
-     */
454
-    public function getAlteredHeaders()
455
-    {
456
-        if ($this->debugHeaders) {
457
-            return ['DKIM-Signature', 'X-DebugHash'];
458
-        } else {
459
-            return ['DKIM-Signature'];
460
-        }
461
-    }
462
-
463
-    /**
464
-     * Adds an ignored Header.
465
-     *
466
-     * @param string $header_name
467
-     *
468
-     * @return Swift_Signers_DKIMSigner
469
-     */
470
-    public function ignoreHeader($header_name)
471
-    {
472
-        $this->ignoredHeaders[strtolower($header_name ?? '')] = true;
473
-
474
-        return $this;
475
-    }
476
-
477
-    /**
478
-     * Set the headers to sign.
479
-     *
480
-     * @return Swift_Signers_DKIMSigner
481
-     */
482
-    public function setHeaders(Swift_Mime_SimpleHeaderSet $headers)
483
-    {
484
-        $this->headerCanonData = '';
485
-        // Loop through Headers
486
-        $listHeaders = $headers->listAll();
487
-        foreach ($listHeaders as $hName) {
488
-            // Check if we need to ignore Header
489
-            if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) {
490
-                if ($headers->has($hName)) {
491
-                    $tmp = $headers->getAll($hName);
492
-                    foreach ($tmp as $header) {
493
-                        if ('' != $header->getFieldBody()) {
494
-                            $this->addHeader($header->toString());
495
-                            $this->signedHeaders[] = $header->getFieldName();
496
-                        }
497
-                    }
498
-                }
499
-            }
500
-        }
501
-
502
-        return $this;
503
-    }
504
-
505
-    /**
506
-     * Add the signature to the given Headers.
507
-     *
508
-     * @return Swift_Signers_DKIMSigner
509
-     */
510
-    public function addSignature(Swift_Mime_SimpleHeaderSet $headers)
511
-    {
512
-        // Prepare the DKIM-Signature
513
-        $params = ['v' => '1', 'a' => $this->hashAlgorithm, 'bh' => base64_encode($this->bodyHash ?? ''), 'd' => $this->domainName, 'h' => implode(': ', $this->signedHeaders), 'i' => $this->signerIdentity, 's' => $this->selector];
514
-        if ('simple' != $this->bodyCanon) {
515
-            $params['c'] = $this->headerCanon.'/'.$this->bodyCanon;
516
-        } elseif ('simple' != $this->headerCanon) {
517
-            $params['c'] = $this->headerCanon;
518
-        }
519
-        if ($this->showLen) {
520
-            $params['l'] = $this->bodyLen;
521
-        }
522
-        if (true === $this->signatureTimestamp) {
523
-            $params['t'] = time();
524
-            if (false !== $this->signatureExpiration) {
525
-                $params['x'] = $params['t'] + $this->signatureExpiration;
526
-            }
527
-        } else {
528
-            if (false !== $this->signatureTimestamp) {
529
-                $params['t'] = $this->signatureTimestamp;
530
-            }
531
-            if (false !== $this->signatureExpiration) {
532
-                $params['x'] = $this->signatureExpiration;
533
-            }
534
-        }
535
-        if ($this->debugHeaders) {
536
-            $params['z'] = implode('|', $this->debugHeadersData);
537
-        }
538
-        $string = '';
539
-        foreach ($params as $k => $v) {
540
-            $string .= $k.'='.$v.'; ';
541
-        }
542
-        $string = trim($string);
543
-        $headers->addTextHeader('DKIM-Signature', $string);
544
-        // Add the last DKIM-Signature
545
-        $tmp = $headers->getAll('DKIM-Signature');
546
-        $this->dkimHeader = end($tmp);
547
-        $this->addHeader(trim($this->dkimHeader->toString() ?? '')."\r\n b=", true);
548
-        if ($this->debugHeaders) {
549
-            $headers->addTextHeader('X-DebugHash', base64_encode($this->headerHash ?? ''));
550
-        }
551
-        $this->dkimHeader->setValue($string.' b='.trim(chunk_split(base64_encode($this->getEncryptedHash() ?? ''), 73, ' ')));
552
-
553
-        return $this;
554
-    }
555
-
556
-    /* Private helpers */
557
-
558
-    protected function addHeader($header, $is_sig = false)
559
-    {
560
-        switch ($this->headerCanon) {
561
-            case 'relaxed':
562
-                // Prepare Header and cascade
563
-                $exploded = explode(':', $header, 2);
564
-                $name = strtolower(trim($exploded[0]));
565
-                $value = str_replace("\r\n", '', $exploded[1]);
566
-                $value = preg_replace("/[ \t][ \t]+/", ' ', $value);
567
-                $header = $name.':'.trim($value).($is_sig ? '' : "\r\n");
568
-                // no break
569
-            case 'simple':
570
-                // Nothing to do
571
-        }
572
-        $this->addToHeaderHash($header);
573
-    }
574
-
575
-    protected function canonicalizeBody($string)
576
-    {
577
-        $len = \strlen($string);
578
-        $canon = '';
579
-        $method = ('relaxed' == $this->bodyCanon);
580
-        for ($i = 0; $i < $len; ++$i) {
581
-            if ($this->bodyCanonIgnoreStart > 0) {
582
-                --$this->bodyCanonIgnoreStart;
583
-                continue;
584
-            }
585
-            switch ($string[$i]) {
586
-                case "\r":
587
-                    $this->bodyCanonLastChar = "\r";
588
-                    break;
589
-                case "\n":
590
-                    if ("\r" == $this->bodyCanonLastChar) {
591
-                        if ($method) {
592
-                            $this->bodyCanonSpace = false;
593
-                        }
594
-                        if ('' == $this->bodyCanonLine) {
595
-                            ++$this->bodyCanonEmptyCounter;
596
-                        } else {
597
-                            $this->bodyCanonLine = '';
598
-                            $canon .= "\r\n";
599
-                        }
600
-                    } else {
601
-                        // Wooops Error
602
-                        // todo handle it but should never happen
603
-                    }
604
-                    break;
605
-                case ' ':
606
-                case "\t":
607
-                    if ($method) {
608
-                        $this->bodyCanonSpace = true;
609
-                        break;
610
-                    }
611
-                    // no break
612
-                default:
613
-                    if ($this->bodyCanonEmptyCounter > 0) {
614
-                        $canon .= str_repeat("\r\n", $this->bodyCanonEmptyCounter);
615
-                        $this->bodyCanonEmptyCounter = 0;
616
-                    }
617
-                    if ($this->bodyCanonSpace) {
618
-                        $this->bodyCanonLine .= ' ';
619
-                        $canon .= ' ';
620
-                        $this->bodyCanonSpace = false;
621
-                    }
622
-                    $this->bodyCanonLine .= $string[$i];
623
-                    $canon .= $string[$i];
624
-            }
625
-        }
626
-        $this->addToBodyHash($canon);
627
-    }
628
-
629
-    protected function endOfBody()
630
-    {
631
-        // Add trailing Line return if last line is non empty
632
-        if (\strlen($this->bodyCanonLine) > 0) {
633
-            $this->addToBodyHash("\r\n");
634
-        }
635
-        $this->bodyHash = hash_final($this->bodyHashHandler, true);
636
-    }
637
-
638
-    private function addToBodyHash($string)
639
-    {
640
-        $len = \strlen($string);
641
-        if ($len > ($new_len = ($this->maxLen - $this->bodyLen))) {
642
-            $string = substr($string, 0, $new_len);
643
-            $len = $new_len;
644
-        }
645
-        hash_update($this->bodyHashHandler, $string);
646
-        $this->bodyLen += $len;
647
-    }
648
-
649
-    private function addToHeaderHash($header)
650
-    {
651
-        if ($this->debugHeaders) {
652
-            $this->debugHeadersData[] = trim($header ?? '');
653
-        }
654
-        $this->headerCanonData .= $header;
655
-    }
656
-
657
-    /**
658
-     * @throws Swift_SwiftException
659
-     *
660
-     * @return string
661
-     */
662
-    private function getEncryptedHash()
663
-    {
664
-        $signature = '';
665
-        switch ($this->hashAlgorithm) {
666
-            case 'rsa-sha1':
667
-                $algorithm = OPENSSL_ALGO_SHA1;
668
-                break;
669
-            case 'rsa-sha256':
670
-                $algorithm = OPENSSL_ALGO_SHA256;
671
-                break;
672
-        }
673
-        $pkeyId = openssl_get_privatekey($this->privateKey, $this->passphrase);
674
-        if (!$pkeyId) {
675
-            throw new Swift_SwiftException('Unable to load DKIM Private Key ['.openssl_error_string().']');
676
-        }
677
-        if (openssl_sign($this->headerCanonData, $signature, $pkeyId, $algorithm)) {
678
-            return $signature;
679
-        }
680
-        throw new Swift_SwiftException('Unable to sign DKIM Hash ['.openssl_error_string().']');
681
-    }
18
+	/**
19
+	 * PrivateKey.
20
+	 *
21
+	 * @var string
22
+	 */
23
+	protected $privateKey;
24
+
25
+	/**
26
+	 * DomainName.
27
+	 *
28
+	 * @var string
29
+	 */
30
+	protected $domainName;
31
+
32
+	/**
33
+	 * Selector.
34
+	 *
35
+	 * @var string
36
+	 */
37
+	protected $selector;
38
+
39
+	private $passphrase = '';
40
+
41
+	/**
42
+	 * Hash algorithm used.
43
+	 *
44
+	 * @see RFC6376 3.3: Signers MUST implement and SHOULD sign using rsa-sha256.
45
+	 *
46
+	 * @var string
47
+	 */
48
+	protected $hashAlgorithm = 'rsa-sha256';
49
+
50
+	/**
51
+	 * Body canon method.
52
+	 *
53
+	 * @var string
54
+	 */
55
+	protected $bodyCanon = 'simple';
56
+
57
+	/**
58
+	 * Header canon method.
59
+	 *
60
+	 * @var string
61
+	 */
62
+	protected $headerCanon = 'simple';
63
+
64
+	/**
65
+	 * Headers not being signed.
66
+	 *
67
+	 * @var array
68
+	 */
69
+	protected $ignoredHeaders = ['return-path' => true];
70
+
71
+	/**
72
+	 * Signer identity.
73
+	 *
74
+	 * @var string
75
+	 */
76
+	protected $signerIdentity;
77
+
78
+	/**
79
+	 * BodyLength.
80
+	 *
81
+	 * @var int
82
+	 */
83
+	protected $bodyLen = 0;
84
+
85
+	/**
86
+	 * Maximum signedLen.
87
+	 *
88
+	 * @var int
89
+	 */
90
+	protected $maxLen = PHP_INT_MAX;
91
+
92
+	/**
93
+	 * Embbed bodyLen in signature.
94
+	 *
95
+	 * @var bool
96
+	 */
97
+	protected $showLen = false;
98
+
99
+	/**
100
+	 * When the signature has been applied (true means time()), false means not embedded.
101
+	 *
102
+	 * @var mixed
103
+	 */
104
+	protected $signatureTimestamp = true;
105
+
106
+	/**
107
+	 * When will the signature expires false means not embedded, if sigTimestamp is auto
108
+	 * Expiration is relative, otherwise it's absolute.
109
+	 *
110
+	 * @var int
111
+	 */
112
+	protected $signatureExpiration = false;
113
+
114
+	/**
115
+	 * Must we embed signed headers?
116
+	 *
117
+	 * @var bool
118
+	 */
119
+	protected $debugHeaders = false;
120
+
121
+	// work variables
122
+	/**
123
+	 * Headers used to generate hash.
124
+	 *
125
+	 * @var array
126
+	 */
127
+	protected $signedHeaders = [];
128
+
129
+	/**
130
+	 * If debugHeaders is set store debugData here.
131
+	 *
132
+	 * @var string[]
133
+	 */
134
+	private $debugHeadersData = [];
135
+
136
+	/**
137
+	 * Stores the bodyHash.
138
+	 *
139
+	 * @var string
140
+	 */
141
+	private $bodyHash = '';
142
+
143
+	/**
144
+	 * Stores the signature header.
145
+	 *
146
+	 * @var Swift_Mime_Headers_ParameterizedHeader
147
+	 */
148
+	protected $dkimHeader;
149
+
150
+	private $bodyHashHandler;
151
+
152
+	private $headerHash;
153
+
154
+	private $headerCanonData = '';
155
+
156
+	private $bodyCanonEmptyCounter = 0;
157
+
158
+	private $bodyCanonIgnoreStart = 2;
159
+
160
+	private $bodyCanonSpace = false;
161
+
162
+	private $bodyCanonLastChar = null;
163
+
164
+	private $bodyCanonLine = '';
165
+
166
+	private $bound = [];
167
+
168
+	/**
169
+	 * Constructor.
170
+	 *
171
+	 * @param string $privateKey
172
+	 * @param string $domainName
173
+	 * @param string $selector
174
+	 * @param string $passphrase
175
+	 */
176
+	public function __construct($privateKey, $domainName, $selector, $passphrase = '')
177
+	{
178
+		$this->privateKey = $privateKey;
179
+		$this->domainName = $domainName;
180
+		$this->signerIdentity = '@'.$domainName;
181
+		$this->selector = $selector;
182
+		$this->passphrase = $passphrase;
183
+	}
184
+
185
+	/**
186
+	 * Reset the Signer.
187
+	 *
188
+	 * @see Swift_Signer::reset()
189
+	 */
190
+	public function reset()
191
+	{
192
+		$this->headerHash = null;
193
+		$this->signedHeaders = [];
194
+		$this->bodyHash = null;
195
+		$this->bodyHashHandler = null;
196
+		$this->bodyCanonIgnoreStart = 2;
197
+		$this->bodyCanonEmptyCounter = 0;
198
+		$this->bodyCanonLastChar = null;
199
+		$this->bodyCanonSpace = false;
200
+	}
201
+
202
+	/**
203
+	 * Writes $bytes to the end of the stream.
204
+	 *
205
+	 * Writing may not happen immediately if the stream chooses to buffer.  If
206
+	 * you want to write these bytes with immediate effect, call {@link commit()}
207
+	 * after calling write().
208
+	 *
209
+	 * This method returns the sequence ID of the write (i.e. 1 for first, 2 for
210
+	 * second, etc etc).
211
+	 *
212
+	 * @param string $bytes
213
+	 *
214
+	 * @return int
215
+	 *
216
+	 * @throws Swift_IoException
217
+	 */
218
+	// TODO fix return
219
+	public function write($bytes)
220
+	{
221
+		$this->canonicalizeBody($bytes);
222
+		foreach ($this->bound as $is) {
223
+			$is->write($bytes);
224
+		}
225
+	}
226
+
227
+	/**
228
+	 * For any bytes that are currently buffered inside the stream, force them
229
+	 * off the buffer.
230
+	 */
231
+	public function commit()
232
+	{
233
+		// Nothing to do
234
+		return;
235
+	}
236
+
237
+	/**
238
+	 * Attach $is to this stream.
239
+	 *
240
+	 * The stream acts as an observer, receiving all data that is written.
241
+	 * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
242
+	 */
243
+	public function bind(Swift_InputByteStream $is)
244
+	{
245
+		// Don't have to mirror anything
246
+		$this->bound[] = $is;
247
+
248
+		return;
249
+	}
250
+
251
+	/**
252
+	 * Remove an already bound stream.
253
+	 *
254
+	 * If $is is not bound, no errors will be raised.
255
+	 * If the stream currently has any buffered data it will be written to $is
256
+	 * before unbinding occurs.
257
+	 */
258
+	public function unbind(Swift_InputByteStream $is)
259
+	{
260
+		// Don't have to mirror anything
261
+		foreach ($this->bound as $k => $stream) {
262
+			if ($stream === $is) {
263
+				unset($this->bound[$k]);
264
+
265
+				return;
266
+			}
267
+		}
268
+	}
269
+
270
+	/**
271
+	 * Flush the contents of the stream (empty it) and set the internal pointer
272
+	 * to the beginning.
273
+	 *
274
+	 * @throws Swift_IoException
275
+	 */
276
+	public function flushBuffers()
277
+	{
278
+		$this->reset();
279
+	}
280
+
281
+	/**
282
+	 * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1.
283
+	 *
284
+	 * @param string $hash 'rsa-sha1' or 'rsa-sha256'
285
+	 *
286
+	 * @throws Swift_SwiftException
287
+	 *
288
+	 * @return $this
289
+	 */
290
+	public function setHashAlgorithm($hash)
291
+	{
292
+		switch ($hash) {
293
+			case 'rsa-sha1':
294
+				$this->hashAlgorithm = 'rsa-sha1';
295
+				break;
296
+			case 'rsa-sha256':
297
+				$this->hashAlgorithm = 'rsa-sha256';
298
+				if (!\defined('OPENSSL_ALGO_SHA256')) {
299
+					throw new Swift_SwiftException('Unable to set sha256 as it is not supported by OpenSSL.');
300
+				}
301
+				break;
302
+			default:
303
+				throw new Swift_SwiftException('Unable to set the hash algorithm, must be one of rsa-sha1 or rsa-sha256 (%s given).', $hash);
304
+		}
305
+
306
+		return $this;
307
+	}
308
+
309
+	/**
310
+	 * Set the body canonicalization algorithm.
311
+	 *
312
+	 * @param string $canon
313
+	 *
314
+	 * @return $this
315
+	 */
316
+	public function setBodyCanon($canon)
317
+	{
318
+		if ('relaxed' == $canon) {
319
+			$this->bodyCanon = 'relaxed';
320
+		} else {
321
+			$this->bodyCanon = 'simple';
322
+		}
323
+
324
+		return $this;
325
+	}
326
+
327
+	/**
328
+	 * Set the header canonicalization algorithm.
329
+	 *
330
+	 * @param string $canon
331
+	 *
332
+	 * @return $this
333
+	 */
334
+	public function setHeaderCanon($canon)
335
+	{
336
+		if ('relaxed' == $canon) {
337
+			$this->headerCanon = 'relaxed';
338
+		} else {
339
+			$this->headerCanon = 'simple';
340
+		}
341
+
342
+		return $this;
343
+	}
344
+
345
+	/**
346
+	 * Set the signer identity.
347
+	 *
348
+	 * @param string $identity
349
+	 *
350
+	 * @return $this
351
+	 */
352
+	public function setSignerIdentity($identity)
353
+	{
354
+		$this->signerIdentity = $identity;
355
+
356
+		return $this;
357
+	}
358
+
359
+	/**
360
+	 * Set the length of the body to sign.
361
+	 *
362
+	 * @param mixed $len (bool or int)
363
+	 *
364
+	 * @return $this
365
+	 */
366
+	public function setBodySignedLen($len)
367
+	{
368
+		if (true === $len) {
369
+			$this->showLen = true;
370
+			$this->maxLen = PHP_INT_MAX;
371
+		} elseif (false === $len) {
372
+			$this->showLen = false;
373
+			$this->maxLen = PHP_INT_MAX;
374
+		} else {
375
+			$this->showLen = true;
376
+			$this->maxLen = (int) $len;
377
+		}
378
+
379
+		return $this;
380
+	}
381
+
382
+	/**
383
+	 * Set the signature timestamp.
384
+	 *
385
+	 * @param int $time A timestamp
386
+	 *
387
+	 * @return $this
388
+	 */
389
+	public function setSignatureTimestamp($time)
390
+	{
391
+		$this->signatureTimestamp = $time;
392
+
393
+		return $this;
394
+	}
395
+
396
+	/**
397
+	 * Set the signature expiration timestamp.
398
+	 *
399
+	 * @param int $time A timestamp
400
+	 *
401
+	 * @return $this
402
+	 */
403
+	public function setSignatureExpiration($time)
404
+	{
405
+		$this->signatureExpiration = $time;
406
+
407
+		return $this;
408
+	}
409
+
410
+	/**
411
+	 * Enable / disable the DebugHeaders.
412
+	 *
413
+	 * @param bool $debug
414
+	 *
415
+	 * @return Swift_Signers_DKIMSigner
416
+	 */
417
+	public function setDebugHeaders($debug)
418
+	{
419
+		$this->debugHeaders = (bool) $debug;
420
+
421
+		return $this;
422
+	}
423
+
424
+	/**
425
+	 * Start Body.
426
+	 */
427
+	public function startBody()
428
+	{
429
+		// Init
430
+		switch ($this->hashAlgorithm) {
431
+			case 'rsa-sha256':
432
+				$this->bodyHashHandler = hash_init('sha256');
433
+				break;
434
+			case 'rsa-sha1':
435
+				$this->bodyHashHandler = hash_init('sha1');
436
+				break;
437
+		}
438
+		$this->bodyCanonLine = '';
439
+	}
440
+
441
+	/**
442
+	 * End Body.
443
+	 */
444
+	public function endBody()
445
+	{
446
+		$this->endOfBody();
447
+	}
448
+
449
+	/**
450
+	 * Returns the list of Headers Tampered by this plugin.
451
+	 *
452
+	 * @return array
453
+	 */
454
+	public function getAlteredHeaders()
455
+	{
456
+		if ($this->debugHeaders) {
457
+			return ['DKIM-Signature', 'X-DebugHash'];
458
+		} else {
459
+			return ['DKIM-Signature'];
460
+		}
461
+	}
462
+
463
+	/**
464
+	 * Adds an ignored Header.
465
+	 *
466
+	 * @param string $header_name
467
+	 *
468
+	 * @return Swift_Signers_DKIMSigner
469
+	 */
470
+	public function ignoreHeader($header_name)
471
+	{
472
+		$this->ignoredHeaders[strtolower($header_name ?? '')] = true;
473
+
474
+		return $this;
475
+	}
476
+
477
+	/**
478
+	 * Set the headers to sign.
479
+	 *
480
+	 * @return Swift_Signers_DKIMSigner
481
+	 */
482
+	public function setHeaders(Swift_Mime_SimpleHeaderSet $headers)
483
+	{
484
+		$this->headerCanonData = '';
485
+		// Loop through Headers
486
+		$listHeaders = $headers->listAll();
487
+		foreach ($listHeaders as $hName) {
488
+			// Check if we need to ignore Header
489
+			if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) {
490
+				if ($headers->has($hName)) {
491
+					$tmp = $headers->getAll($hName);
492
+					foreach ($tmp as $header) {
493
+						if ('' != $header->getFieldBody()) {
494
+							$this->addHeader($header->toString());
495
+							$this->signedHeaders[] = $header->getFieldName();
496
+						}
497
+					}
498
+				}
499
+			}
500
+		}
501
+
502
+		return $this;
503
+	}
504
+
505
+	/**
506
+	 * Add the signature to the given Headers.
507
+	 *
508
+	 * @return Swift_Signers_DKIMSigner
509
+	 */
510
+	public function addSignature(Swift_Mime_SimpleHeaderSet $headers)
511
+	{
512
+		// Prepare the DKIM-Signature
513
+		$params = ['v' => '1', 'a' => $this->hashAlgorithm, 'bh' => base64_encode($this->bodyHash ?? ''), 'd' => $this->domainName, 'h' => implode(': ', $this->signedHeaders), 'i' => $this->signerIdentity, 's' => $this->selector];
514
+		if ('simple' != $this->bodyCanon) {
515
+			$params['c'] = $this->headerCanon.'/'.$this->bodyCanon;
516
+		} elseif ('simple' != $this->headerCanon) {
517
+			$params['c'] = $this->headerCanon;
518
+		}
519
+		if ($this->showLen) {
520
+			$params['l'] = $this->bodyLen;
521
+		}
522
+		if (true === $this->signatureTimestamp) {
523
+			$params['t'] = time();
524
+			if (false !== $this->signatureExpiration) {
525
+				$params['x'] = $params['t'] + $this->signatureExpiration;
526
+			}
527
+		} else {
528
+			if (false !== $this->signatureTimestamp) {
529
+				$params['t'] = $this->signatureTimestamp;
530
+			}
531
+			if (false !== $this->signatureExpiration) {
532
+				$params['x'] = $this->signatureExpiration;
533
+			}
534
+		}
535
+		if ($this->debugHeaders) {
536
+			$params['z'] = implode('|', $this->debugHeadersData);
537
+		}
538
+		$string = '';
539
+		foreach ($params as $k => $v) {
540
+			$string .= $k.'='.$v.'; ';
541
+		}
542
+		$string = trim($string);
543
+		$headers->addTextHeader('DKIM-Signature', $string);
544
+		// Add the last DKIM-Signature
545
+		$tmp = $headers->getAll('DKIM-Signature');
546
+		$this->dkimHeader = end($tmp);
547
+		$this->addHeader(trim($this->dkimHeader->toString() ?? '')."\r\n b=", true);
548
+		if ($this->debugHeaders) {
549
+			$headers->addTextHeader('X-DebugHash', base64_encode($this->headerHash ?? ''));
550
+		}
551
+		$this->dkimHeader->setValue($string.' b='.trim(chunk_split(base64_encode($this->getEncryptedHash() ?? ''), 73, ' ')));
552
+
553
+		return $this;
554
+	}
555
+
556
+	/* Private helpers */
557
+
558
+	protected function addHeader($header, $is_sig = false)
559
+	{
560
+		switch ($this->headerCanon) {
561
+			case 'relaxed':
562
+				// Prepare Header and cascade
563
+				$exploded = explode(':', $header, 2);
564
+				$name = strtolower(trim($exploded[0]));
565
+				$value = str_replace("\r\n", '', $exploded[1]);
566
+				$value = preg_replace("/[ \t][ \t]+/", ' ', $value);
567
+				$header = $name.':'.trim($value).($is_sig ? '' : "\r\n");
568
+				// no break
569
+			case 'simple':
570
+				// Nothing to do
571
+		}
572
+		$this->addToHeaderHash($header);
573
+	}
574
+
575
+	protected function canonicalizeBody($string)
576
+	{
577
+		$len = \strlen($string);
578
+		$canon = '';
579
+		$method = ('relaxed' == $this->bodyCanon);
580
+		for ($i = 0; $i < $len; ++$i) {
581
+			if ($this->bodyCanonIgnoreStart > 0) {
582
+				--$this->bodyCanonIgnoreStart;
583
+				continue;
584
+			}
585
+			switch ($string[$i]) {
586
+				case "\r":
587
+					$this->bodyCanonLastChar = "\r";
588
+					break;
589
+				case "\n":
590
+					if ("\r" == $this->bodyCanonLastChar) {
591
+						if ($method) {
592
+							$this->bodyCanonSpace = false;
593
+						}
594
+						if ('' == $this->bodyCanonLine) {
595
+							++$this->bodyCanonEmptyCounter;
596
+						} else {
597
+							$this->bodyCanonLine = '';
598
+							$canon .= "\r\n";
599
+						}
600
+					} else {
601
+						// Wooops Error
602
+						// todo handle it but should never happen
603
+					}
604
+					break;
605
+				case ' ':
606
+				case "\t":
607
+					if ($method) {
608
+						$this->bodyCanonSpace = true;
609
+						break;
610
+					}
611
+					// no break
612
+				default:
613
+					if ($this->bodyCanonEmptyCounter > 0) {
614
+						$canon .= str_repeat("\r\n", $this->bodyCanonEmptyCounter);
615
+						$this->bodyCanonEmptyCounter = 0;
616
+					}
617
+					if ($this->bodyCanonSpace) {
618
+						$this->bodyCanonLine .= ' ';
619
+						$canon .= ' ';
620
+						$this->bodyCanonSpace = false;
621
+					}
622
+					$this->bodyCanonLine .= $string[$i];
623
+					$canon .= $string[$i];
624
+			}
625
+		}
626
+		$this->addToBodyHash($canon);
627
+	}
628
+
629
+	protected function endOfBody()
630
+	{
631
+		// Add trailing Line return if last line is non empty
632
+		if (\strlen($this->bodyCanonLine) > 0) {
633
+			$this->addToBodyHash("\r\n");
634
+		}
635
+		$this->bodyHash = hash_final($this->bodyHashHandler, true);
636
+	}
637
+
638
+	private function addToBodyHash($string)
639
+	{
640
+		$len = \strlen($string);
641
+		if ($len > ($new_len = ($this->maxLen - $this->bodyLen))) {
642
+			$string = substr($string, 0, $new_len);
643
+			$len = $new_len;
644
+		}
645
+		hash_update($this->bodyHashHandler, $string);
646
+		$this->bodyLen += $len;
647
+	}
648
+
649
+	private function addToHeaderHash($header)
650
+	{
651
+		if ($this->debugHeaders) {
652
+			$this->debugHeadersData[] = trim($header ?? '');
653
+		}
654
+		$this->headerCanonData .= $header;
655
+	}
656
+
657
+	/**
658
+	 * @throws Swift_SwiftException
659
+	 *
660
+	 * @return string
661
+	 */
662
+	private function getEncryptedHash()
663
+	{
664
+		$signature = '';
665
+		switch ($this->hashAlgorithm) {
666
+			case 'rsa-sha1':
667
+				$algorithm = OPENSSL_ALGO_SHA1;
668
+				break;
669
+			case 'rsa-sha256':
670
+				$algorithm = OPENSSL_ALGO_SHA256;
671
+				break;
672
+		}
673
+		$pkeyId = openssl_get_privatekey($this->privateKey, $this->passphrase);
674
+		if (!$pkeyId) {
675
+			throw new Swift_SwiftException('Unable to load DKIM Private Key ['.openssl_error_string().']');
676
+		}
677
+		if (openssl_sign($this->headerCanonData, $signature, $pkeyId, $algorithm)) {
678
+			return $signature;
679
+		}
680
+		throw new Swift_SwiftException('Unable to sign DKIM Hash ['.openssl_error_string().']');
681
+	}
682 682
 }
Please login to merge, or discard this patch.
htdocs/includes/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php 1 patch
Indentation   +162 added lines, -162 removed lines patch added patch discarded remove patch
@@ -18,166 +18,166 @@
 block discarded – undo
18 18
  */
19 19
 class Swift_Signers_OpenDKIMSigner extends Swift_Signers_DKIMSigner
20 20
 {
21
-    private $peclLoaded = false;
22
-
23
-    private $dkimHandler = null;
24
-
25
-    private $dropFirstLF = true;
26
-
27
-    const CANON_RELAXED = 1;
28
-    const CANON_SIMPLE = 2;
29
-    const SIG_RSA_SHA1 = 3;
30
-    const SIG_RSA_SHA256 = 4;
31
-
32
-    public function __construct($privateKey, $domainName, $selector)
33
-    {
34
-        if (!\extension_loaded('opendkim')) {
35
-            throw new Swift_SwiftException('php-opendkim extension not found');
36
-        }
37
-
38
-        $this->peclLoaded = true;
39
-
40
-        parent::__construct($privateKey, $domainName, $selector);
41
-    }
42
-
43
-    public function addSignature(Swift_Mime_SimpleHeaderSet $headers)
44
-    {
45
-        $header = new Swift_Mime_Headers_OpenDKIMHeader('DKIM-Signature');
46
-        $headerVal = $this->dkimHandler->getSignatureHeader();
47
-        if (false === $headerVal || \is_int($headerVal)) {
48
-            throw new Swift_SwiftException('OpenDKIM Error: '.$this->dkimHandler->getError());
49
-        }
50
-        $header->setValue($headerVal);
51
-        $headers->set($header);
52
-
53
-        return $this;
54
-    }
55
-
56
-    public function setHeaders(Swift_Mime_SimpleHeaderSet $headers)
57
-    {
58
-        $hash = 'rsa-sha1' == $this->hashAlgorithm ? OpenDKIMSign::ALG_RSASHA1 : OpenDKIMSign::ALG_RSASHA256;
59
-        $bodyCanon = 'simple' == $this->bodyCanon ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED;
60
-        $headerCanon = 'simple' == $this->headerCanon ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED;
61
-        $this->dkimHandler = new OpenDKIMSign($this->privateKey, $this->selector, $this->domainName, $headerCanon, $bodyCanon, $hash, -1);
62
-        // Hardcode signature Margin for now
63
-        $this->dkimHandler->setMargin(78);
64
-
65
-        if (!is_numeric($this->signatureTimestamp)) {
66
-            OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, time());
67
-        } else {
68
-            if (!OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, $this->signatureTimestamp)) {
69
-                throw new Swift_SwiftException('Unable to force signature timestamp ['.openssl_error_string().']');
70
-            }
71
-        }
72
-        if (isset($this->signerIdentity)) {
73
-            $this->dkimHandler->setSigner($this->signerIdentity);
74
-        }
75
-        $listHeaders = $headers->listAll();
76
-        foreach ($listHeaders as $hName) {
77
-            // Check if we need to ignore Header
78
-            if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) {
79
-                $tmp = $headers->getAll($hName);
80
-                if ($headers->has($hName)) {
81
-                    foreach ($tmp as $header) {
82
-                        if ('' != $header->getFieldBody()) {
83
-                            $htosign = $header->toString();
84
-                            $this->dkimHandler->header($htosign);
85
-                            $this->signedHeaders[] = $header->getFieldName();
86
-                        }
87
-                    }
88
-                }
89
-            }
90
-        }
91
-
92
-        return $this;
93
-    }
94
-
95
-    public function startBody()
96
-    {
97
-        if (!$this->peclLoaded) {
98
-            return parent::startBody();
99
-        }
100
-        $this->dropFirstLF = true;
101
-        $this->dkimHandler->eoh();
102
-
103
-        return $this;
104
-    }
105
-
106
-    public function endBody()
107
-    {
108
-        if (!$this->peclLoaded) {
109
-            return parent::endBody();
110
-        }
111
-        $this->dkimHandler->eom();
112
-
113
-        return $this;
114
-    }
115
-
116
-    public function reset()
117
-    {
118
-        $this->dkimHandler = null;
119
-        parent::reset();
120
-
121
-        return $this;
122
-    }
123
-
124
-    /**
125
-     * Set the signature timestamp.
126
-     *
127
-     * @param int $time
128
-     *
129
-     * @return $this
130
-     */
131
-    public function setSignatureTimestamp($time)
132
-    {
133
-        $this->signatureTimestamp = $time;
134
-
135
-        return $this;
136
-    }
137
-
138
-    /**
139
-     * Set the signature expiration timestamp.
140
-     *
141
-     * @param int $time
142
-     *
143
-     * @return $this
144
-     */
145
-    public function setSignatureExpiration($time)
146
-    {
147
-        $this->signatureExpiration = $time;
148
-
149
-        return $this;
150
-    }
151
-
152
-    /**
153
-     * Enable / disable the DebugHeaders.
154
-     *
155
-     * @param bool $debug
156
-     *
157
-     * @return $this
158
-     */
159
-    public function setDebugHeaders($debug)
160
-    {
161
-        $this->debugHeaders = (bool) $debug;
162
-
163
-        return $this;
164
-    }
165
-
166
-    // Protected
167
-
168
-    protected function canonicalizeBody($string)
169
-    {
170
-        if (!$this->peclLoaded) {
171
-            return parent::canonicalizeBody($string);
172
-        }
173
-        if (true === $this->dropFirstLF) {
174
-            if ("\r" == $string[0] && "\n" == $string[1]) {
175
-                $string = substr($string, 2);
176
-            }
177
-        }
178
-        $this->dropFirstLF = false;
179
-        if (\strlen($string)) {
180
-            $this->dkimHandler->body($string);
181
-        }
182
-    }
21
+	private $peclLoaded = false;
22
+
23
+	private $dkimHandler = null;
24
+
25
+	private $dropFirstLF = true;
26
+
27
+	const CANON_RELAXED = 1;
28
+	const CANON_SIMPLE = 2;
29
+	const SIG_RSA_SHA1 = 3;
30
+	const SIG_RSA_SHA256 = 4;
31
+
32
+	public function __construct($privateKey, $domainName, $selector)
33
+	{
34
+		if (!\extension_loaded('opendkim')) {
35
+			throw new Swift_SwiftException('php-opendkim extension not found');
36
+		}
37
+
38
+		$this->peclLoaded = true;
39
+
40
+		parent::__construct($privateKey, $domainName, $selector);
41
+	}
42
+
43
+	public function addSignature(Swift_Mime_SimpleHeaderSet $headers)
44
+	{
45
+		$header = new Swift_Mime_Headers_OpenDKIMHeader('DKIM-Signature');
46
+		$headerVal = $this->dkimHandler->getSignatureHeader();
47
+		if (false === $headerVal || \is_int($headerVal)) {
48
+			throw new Swift_SwiftException('OpenDKIM Error: '.$this->dkimHandler->getError());
49
+		}
50
+		$header->setValue($headerVal);
51
+		$headers->set($header);
52
+
53
+		return $this;
54
+	}
55
+
56
+	public function setHeaders(Swift_Mime_SimpleHeaderSet $headers)
57
+	{
58
+		$hash = 'rsa-sha1' == $this->hashAlgorithm ? OpenDKIMSign::ALG_RSASHA1 : OpenDKIMSign::ALG_RSASHA256;
59
+		$bodyCanon = 'simple' == $this->bodyCanon ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED;
60
+		$headerCanon = 'simple' == $this->headerCanon ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED;
61
+		$this->dkimHandler = new OpenDKIMSign($this->privateKey, $this->selector, $this->domainName, $headerCanon, $bodyCanon, $hash, -1);
62
+		// Hardcode signature Margin for now
63
+		$this->dkimHandler->setMargin(78);
64
+
65
+		if (!is_numeric($this->signatureTimestamp)) {
66
+			OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, time());
67
+		} else {
68
+			if (!OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, $this->signatureTimestamp)) {
69
+				throw new Swift_SwiftException('Unable to force signature timestamp ['.openssl_error_string().']');
70
+			}
71
+		}
72
+		if (isset($this->signerIdentity)) {
73
+			$this->dkimHandler->setSigner($this->signerIdentity);
74
+		}
75
+		$listHeaders = $headers->listAll();
76
+		foreach ($listHeaders as $hName) {
77
+			// Check if we need to ignore Header
78
+			if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) {
79
+				$tmp = $headers->getAll($hName);
80
+				if ($headers->has($hName)) {
81
+					foreach ($tmp as $header) {
82
+						if ('' != $header->getFieldBody()) {
83
+							$htosign = $header->toString();
84
+							$this->dkimHandler->header($htosign);
85
+							$this->signedHeaders[] = $header->getFieldName();
86
+						}
87
+					}
88
+				}
89
+			}
90
+		}
91
+
92
+		return $this;
93
+	}
94
+
95
+	public function startBody()
96
+	{
97
+		if (!$this->peclLoaded) {
98
+			return parent::startBody();
99
+		}
100
+		$this->dropFirstLF = true;
101
+		$this->dkimHandler->eoh();
102
+
103
+		return $this;
104
+	}
105
+
106
+	public function endBody()
107
+	{
108
+		if (!$this->peclLoaded) {
109
+			return parent::endBody();
110
+		}
111
+		$this->dkimHandler->eom();
112
+
113
+		return $this;
114
+	}
115
+
116
+	public function reset()
117
+	{
118
+		$this->dkimHandler = null;
119
+		parent::reset();
120
+
121
+		return $this;
122
+	}
123
+
124
+	/**
125
+	 * Set the signature timestamp.
126
+	 *
127
+	 * @param int $time
128
+	 *
129
+	 * @return $this
130
+	 */
131
+	public function setSignatureTimestamp($time)
132
+	{
133
+		$this->signatureTimestamp = $time;
134
+
135
+		return $this;
136
+	}
137
+
138
+	/**
139
+	 * Set the signature expiration timestamp.
140
+	 *
141
+	 * @param int $time
142
+	 *
143
+	 * @return $this
144
+	 */
145
+	public function setSignatureExpiration($time)
146
+	{
147
+		$this->signatureExpiration = $time;
148
+
149
+		return $this;
150
+	}
151
+
152
+	/**
153
+	 * Enable / disable the DebugHeaders.
154
+	 *
155
+	 * @param bool $debug
156
+	 *
157
+	 * @return $this
158
+	 */
159
+	public function setDebugHeaders($debug)
160
+	{
161
+		$this->debugHeaders = (bool) $debug;
162
+
163
+		return $this;
164
+	}
165
+
166
+	// Protected
167
+
168
+	protected function canonicalizeBody($string)
169
+	{
170
+		if (!$this->peclLoaded) {
171
+			return parent::canonicalizeBody($string);
172
+		}
173
+		if (true === $this->dropFirstLF) {
174
+			if ("\r" == $string[0] && "\n" == $string[1]) {
175
+				$string = substr($string, 2);
176
+			}
177
+		}
178
+		$this->dropFirstLF = false;
179
+		if (\strlen($string)) {
180
+			$this->dkimHandler->body($string);
181
+		}
182
+	}
183 183
 }
Please login to merge, or discard this patch.
htdocs/includes/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php 1 patch
Indentation   +486 added lines, -486 removed lines patch added patch discarded remove patch
@@ -15,490 +15,490 @@
 block discarded – undo
15 15
  */
16 16
 class Swift_Signers_DomainKeySigner implements Swift_Signers_HeaderSigner
17 17
 {
18
-    /**
19
-     * PrivateKey.
20
-     *
21
-     * @var string
22
-     */
23
-    protected $privateKey;
24
-
25
-    /**
26
-     * DomainName.
27
-     *
28
-     * @var string
29
-     */
30
-    protected $domainName;
31
-
32
-    /**
33
-     * Selector.
34
-     *
35
-     * @var string
36
-     */
37
-    protected $selector;
38
-
39
-    /**
40
-     * Hash algorithm used.
41
-     *
42
-     * @var string
43
-     */
44
-    protected $hashAlgorithm = 'rsa-sha1';
45
-
46
-    /**
47
-     * Canonisation method.
48
-     *
49
-     * @var string
50
-     */
51
-    protected $canon = 'simple';
52
-
53
-    /**
54
-     * Headers not being signed.
55
-     *
56
-     * @var array
57
-     */
58
-    protected $ignoredHeaders = [];
59
-
60
-    /**
61
-     * Signer identity.
62
-     *
63
-     * @var string
64
-     */
65
-    protected $signerIdentity;
66
-
67
-    /**
68
-     * Must we embed signed headers?
69
-     *
70
-     * @var bool
71
-     */
72
-    protected $debugHeaders = false;
73
-
74
-    // work variables
75
-    /**
76
-     * Headers used to generate hash.
77
-     *
78
-     * @var array
79
-     */
80
-    private $signedHeaders = [];
81
-
82
-    /**
83
-     * Stores the signature header.
84
-     *
85
-     * @var Swift_Mime_Headers_ParameterizedHeader
86
-     */
87
-    protected $domainKeyHeader;
88
-
89
-    /**
90
-     * Hash Handler.
91
-     *
92
-     * @var resource|null
93
-     */
94
-    private $hashHandler;
95
-
96
-    private $canonData = '';
97
-
98
-    private $bodyCanonEmptyCounter = 0;
99
-
100
-    private $bodyCanonIgnoreStart = 2;
101
-
102
-    private $bodyCanonSpace = false;
103
-
104
-    private $bodyCanonLastChar = null;
105
-
106
-    private $bodyCanonLine = '';
107
-
108
-    private $bound = [];
109
-
110
-    /**
111
-     * Constructor.
112
-     *
113
-     * @param string $privateKey
114
-     * @param string $domainName
115
-     * @param string $selector
116
-     */
117
-    public function __construct($privateKey, $domainName, $selector)
118
-    {
119
-        $this->privateKey = $privateKey;
120
-        $this->domainName = $domainName;
121
-        $this->signerIdentity = '@'.$domainName;
122
-        $this->selector = $selector;
123
-    }
124
-
125
-    /**
126
-     * Resets internal states.
127
-     *
128
-     * @return $this
129
-     */
130
-    public function reset()
131
-    {
132
-        $this->hashHandler = null;
133
-        $this->bodyCanonIgnoreStart = 2;
134
-        $this->bodyCanonEmptyCounter = 0;
135
-        $this->bodyCanonLastChar = null;
136
-        $this->bodyCanonSpace = false;
137
-
138
-        return $this;
139
-    }
140
-
141
-    /**
142
-     * Writes $bytes to the end of the stream.
143
-     *
144
-     * Writing may not happen immediately if the stream chooses to buffer.  If
145
-     * you want to write these bytes with immediate effect, call {@link commit()}
146
-     * after calling write().
147
-     *
148
-     * This method returns the sequence ID of the write (i.e. 1 for first, 2 for
149
-     * second, etc etc).
150
-     *
151
-     * @param string $bytes
152
-     *
153
-     * @return int
154
-     *
155
-     * @throws Swift_IoException
156
-     *
157
-     * @return $this
158
-     */
159
-    public function write($bytes)
160
-    {
161
-        $this->canonicalizeBody($bytes);
162
-        foreach ($this->bound as $is) {
163
-            $is->write($bytes);
164
-        }
165
-
166
-        return $this;
167
-    }
168
-
169
-    /**
170
-     * For any bytes that are currently buffered inside the stream, force them
171
-     * off the buffer.
172
-     *
173
-     * @throws Swift_IoException
174
-     *
175
-     * @return $this
176
-     */
177
-    public function commit()
178
-    {
179
-        // Nothing to do
180
-        return $this;
181
-    }
182
-
183
-    /**
184
-     * Attach $is to this stream.
185
-     *
186
-     * The stream acts as an observer, receiving all data that is written.
187
-     * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
188
-     *
189
-     * @return $this
190
-     */
191
-    public function bind(Swift_InputByteStream $is)
192
-    {
193
-        // Don't have to mirror anything
194
-        $this->bound[] = $is;
195
-
196
-        return $this;
197
-    }
198
-
199
-    /**
200
-     * Remove an already bound stream.
201
-     *
202
-     * If $is is not bound, no errors will be raised.
203
-     * If the stream currently has any buffered data it will be written to $is
204
-     * before unbinding occurs.
205
-     *
206
-     * @return $this
207
-     */
208
-    public function unbind(Swift_InputByteStream $is)
209
-    {
210
-        // Don't have to mirror anything
211
-        foreach ($this->bound as $k => $stream) {
212
-            if ($stream === $is) {
213
-                unset($this->bound[$k]);
214
-
215
-                break;
216
-            }
217
-        }
218
-
219
-        return $this;
220
-    }
221
-
222
-    /**
223
-     * Flush the contents of the stream (empty it) and set the internal pointer
224
-     * to the beginning.
225
-     *
226
-     * @throws Swift_IoException
227
-     *
228
-     * @return $this
229
-     */
230
-    public function flushBuffers()
231
-    {
232
-        $this->reset();
233
-
234
-        return $this;
235
-    }
236
-
237
-    /**
238
-     * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1 defaults to rsa-sha256.
239
-     *
240
-     * @param string $hash
241
-     *
242
-     * @return $this
243
-     */
244
-    public function setHashAlgorithm($hash)
245
-    {
246
-        $this->hashAlgorithm = 'rsa-sha1';
247
-
248
-        return $this;
249
-    }
250
-
251
-    /**
252
-     * Set the canonicalization algorithm.
253
-     *
254
-     * @param string $canon simple | nofws defaults to simple
255
-     *
256
-     * @return $this
257
-     */
258
-    public function setCanon($canon)
259
-    {
260
-        if ('nofws' == $canon) {
261
-            $this->canon = 'nofws';
262
-        } else {
263
-            $this->canon = 'simple';
264
-        }
265
-
266
-        return $this;
267
-    }
268
-
269
-    /**
270
-     * Set the signer identity.
271
-     *
272
-     * @param string $identity
273
-     *
274
-     * @return $this
275
-     */
276
-    public function setSignerIdentity($identity)
277
-    {
278
-        $this->signerIdentity = $identity;
279
-
280
-        return $this;
281
-    }
282
-
283
-    /**
284
-     * Enable / disable the DebugHeaders.
285
-     *
286
-     * @param bool $debug
287
-     *
288
-     * @return $this
289
-     */
290
-    public function setDebugHeaders($debug)
291
-    {
292
-        $this->debugHeaders = (bool) $debug;
293
-
294
-        return $this;
295
-    }
296
-
297
-    /**
298
-     * Start Body.
299
-     */
300
-    public function startBody()
301
-    {
302
-    }
303
-
304
-    /**
305
-     * End Body.
306
-     */
307
-    public function endBody()
308
-    {
309
-        $this->endOfBody();
310
-    }
311
-
312
-    /**
313
-     * Returns the list of Headers Tampered by this plugin.
314
-     *
315
-     * @return array
316
-     */
317
-    public function getAlteredHeaders()
318
-    {
319
-        if ($this->debugHeaders) {
320
-            return ['DomainKey-Signature', 'X-DebugHash'];
321
-        }
322
-
323
-        return ['DomainKey-Signature'];
324
-    }
325
-
326
-    /**
327
-     * Adds an ignored Header.
328
-     *
329
-     * @param string $header_name
330
-     *
331
-     * @return $this
332
-     */
333
-    public function ignoreHeader($header_name)
334
-    {
335
-        $this->ignoredHeaders[strtolower($header_name ?? '')] = true;
336
-
337
-        return $this;
338
-    }
339
-
340
-    /**
341
-     * Set the headers to sign.
342
-     *
343
-     * @return $this
344
-     */
345
-    public function setHeaders(Swift_Mime_SimpleHeaderSet $headers)
346
-    {
347
-        $this->startHash();
348
-        $this->canonData = '';
349
-        // Loop through Headers
350
-        $listHeaders = $headers->listAll();
351
-        foreach ($listHeaders as $hName) {
352
-            // Check if we need to ignore Header
353
-            if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) {
354
-                if ($headers->has($hName)) {
355
-                    $tmp = $headers->getAll($hName);
356
-                    foreach ($tmp as $header) {
357
-                        if ('' != $header->getFieldBody()) {
358
-                            $this->addHeader($header->toString());
359
-                            $this->signedHeaders[] = $header->getFieldName();
360
-                        }
361
-                    }
362
-                }
363
-            }
364
-        }
365
-        $this->endOfHeaders();
366
-
367
-        return $this;
368
-    }
369
-
370
-    /**
371
-     * Add the signature to the given Headers.
372
-     *
373
-     * @return $this
374
-     */
375
-    public function addSignature(Swift_Mime_SimpleHeaderSet $headers)
376
-    {
377
-        // Prepare the DomainKey-Signature Header
378
-        $params = ['a' => $this->hashAlgorithm, 'b' => chunk_split(base64_encode($this->getEncryptedHash() ?? ''), 73, ' '), 'c' => $this->canon, 'd' => $this->domainName, 'h' => implode(': ', $this->signedHeaders), 'q' => 'dns', 's' => $this->selector];
379
-        $string = '';
380
-        foreach ($params as $k => $v) {
381
-            $string .= $k.'='.$v.'; ';
382
-        }
383
-        $string = trim($string);
384
-        $headers->addTextHeader('DomainKey-Signature', $string);
385
-
386
-        return $this;
387
-    }
388
-
389
-    /* Private helpers */
390
-
391
-    protected function addHeader($header)
392
-    {
393
-        switch ($this->canon) {
394
-            case 'nofws':
395
-                // Prepare Header and cascade
396
-                $exploded = explode(':', $header, 2);
397
-                $name = strtolower(trim($exploded[0]));
398
-                $value = str_replace("\r\n", '', $exploded[1]);
399
-                $value = preg_replace("/[ \t][ \t]+/", ' ', $value);
400
-                $header = $name.':'.trim($value)."\r\n";
401
-                // no break
402
-            case 'simple':
403
-                // Nothing to do
404
-        }
405
-        $this->addToHash($header);
406
-    }
407
-
408
-    protected function endOfHeaders()
409
-    {
410
-        $this->bodyCanonEmptyCounter = 1;
411
-    }
412
-
413
-    protected function canonicalizeBody($string)
414
-    {
415
-        $len = \strlen($string);
416
-        $canon = '';
417
-        $nofws = ('nofws' == $this->canon);
418
-        for ($i = 0; $i < $len; ++$i) {
419
-            if ($this->bodyCanonIgnoreStart > 0) {
420
-                --$this->bodyCanonIgnoreStart;
421
-                continue;
422
-            }
423
-            switch ($string[$i]) {
424
-                case "\r":
425
-                    $this->bodyCanonLastChar = "\r";
426
-                    break;
427
-                case "\n":
428
-                    if ("\r" == $this->bodyCanonLastChar) {
429
-                        if ($nofws) {
430
-                            $this->bodyCanonSpace = false;
431
-                        }
432
-                        if ('' == $this->bodyCanonLine) {
433
-                            ++$this->bodyCanonEmptyCounter;
434
-                        } else {
435
-                            $this->bodyCanonLine = '';
436
-                            $canon .= "\r\n";
437
-                        }
438
-                    } else {
439
-                        // Wooops Error
440
-                        throw new Swift_SwiftException('Invalid new line sequence in mail found \n without preceding \r');
441
-                    }
442
-                    break;
443
-                case ' ':
444
-                case "\t":
445
-                case "\x09": //HTAB
446
-                    if ($nofws) {
447
-                        $this->bodyCanonSpace = true;
448
-                        break;
449
-                    }
450
-                    // no break
451
-                default:
452
-                    if ($this->bodyCanonEmptyCounter > 0) {
453
-                        $canon .= str_repeat("\r\n", $this->bodyCanonEmptyCounter);
454
-                        $this->bodyCanonEmptyCounter = 0;
455
-                    }
456
-                    $this->bodyCanonLine .= $string[$i];
457
-                    $canon .= $string[$i];
458
-            }
459
-        }
460
-        $this->addToHash($canon);
461
-    }
462
-
463
-    protected function endOfBody()
464
-    {
465
-        if (\strlen($this->bodyCanonLine) > 0) {
466
-            $this->addToHash("\r\n");
467
-        }
468
-    }
469
-
470
-    private function addToHash($string)
471
-    {
472
-        $this->canonData .= $string;
473
-        hash_update($this->hashHandler, $string);
474
-    }
475
-
476
-    private function startHash()
477
-    {
478
-        // Init
479
-        switch ($this->hashAlgorithm) {
480
-            case 'rsa-sha1':
481
-                $this->hashHandler = hash_init('sha1');
482
-                break;
483
-        }
484
-        $this->bodyCanonLine = '';
485
-    }
486
-
487
-    /**
488
-     * @throws Swift_SwiftException
489
-     *
490
-     * @return string
491
-     */
492
-    private function getEncryptedHash()
493
-    {
494
-        $signature = '';
495
-        $pkeyId = openssl_get_privatekey($this->privateKey);
496
-        if (!$pkeyId) {
497
-            throw new Swift_SwiftException('Unable to load DomainKey Private Key ['.openssl_error_string().']');
498
-        }
499
-        if (openssl_sign($this->canonData, $signature, $pkeyId, OPENSSL_ALGO_SHA1)) {
500
-            return $signature;
501
-        }
502
-        throw new Swift_SwiftException('Unable to sign DomainKey Hash  ['.openssl_error_string().']');
503
-    }
18
+	/**
19
+	 * PrivateKey.
20
+	 *
21
+	 * @var string
22
+	 */
23
+	protected $privateKey;
24
+
25
+	/**
26
+	 * DomainName.
27
+	 *
28
+	 * @var string
29
+	 */
30
+	protected $domainName;
31
+
32
+	/**
33
+	 * Selector.
34
+	 *
35
+	 * @var string
36
+	 */
37
+	protected $selector;
38
+
39
+	/**
40
+	 * Hash algorithm used.
41
+	 *
42
+	 * @var string
43
+	 */
44
+	protected $hashAlgorithm = 'rsa-sha1';
45
+
46
+	/**
47
+	 * Canonisation method.
48
+	 *
49
+	 * @var string
50
+	 */
51
+	protected $canon = 'simple';
52
+
53
+	/**
54
+	 * Headers not being signed.
55
+	 *
56
+	 * @var array
57
+	 */
58
+	protected $ignoredHeaders = [];
59
+
60
+	/**
61
+	 * Signer identity.
62
+	 *
63
+	 * @var string
64
+	 */
65
+	protected $signerIdentity;
66
+
67
+	/**
68
+	 * Must we embed signed headers?
69
+	 *
70
+	 * @var bool
71
+	 */
72
+	protected $debugHeaders = false;
73
+
74
+	// work variables
75
+	/**
76
+	 * Headers used to generate hash.
77
+	 *
78
+	 * @var array
79
+	 */
80
+	private $signedHeaders = [];
81
+
82
+	/**
83
+	 * Stores the signature header.
84
+	 *
85
+	 * @var Swift_Mime_Headers_ParameterizedHeader
86
+	 */
87
+	protected $domainKeyHeader;
88
+
89
+	/**
90
+	 * Hash Handler.
91
+	 *
92
+	 * @var resource|null
93
+	 */
94
+	private $hashHandler;
95
+
96
+	private $canonData = '';
97
+
98
+	private $bodyCanonEmptyCounter = 0;
99
+
100
+	private $bodyCanonIgnoreStart = 2;
101
+
102
+	private $bodyCanonSpace = false;
103
+
104
+	private $bodyCanonLastChar = null;
105
+
106
+	private $bodyCanonLine = '';
107
+
108
+	private $bound = [];
109
+
110
+	/**
111
+	 * Constructor.
112
+	 *
113
+	 * @param string $privateKey
114
+	 * @param string $domainName
115
+	 * @param string $selector
116
+	 */
117
+	public function __construct($privateKey, $domainName, $selector)
118
+	{
119
+		$this->privateKey = $privateKey;
120
+		$this->domainName = $domainName;
121
+		$this->signerIdentity = '@'.$domainName;
122
+		$this->selector = $selector;
123
+	}
124
+
125
+	/**
126
+	 * Resets internal states.
127
+	 *
128
+	 * @return $this
129
+	 */
130
+	public function reset()
131
+	{
132
+		$this->hashHandler = null;
133
+		$this->bodyCanonIgnoreStart = 2;
134
+		$this->bodyCanonEmptyCounter = 0;
135
+		$this->bodyCanonLastChar = null;
136
+		$this->bodyCanonSpace = false;
137
+
138
+		return $this;
139
+	}
140
+
141
+	/**
142
+	 * Writes $bytes to the end of the stream.
143
+	 *
144
+	 * Writing may not happen immediately if the stream chooses to buffer.  If
145
+	 * you want to write these bytes with immediate effect, call {@link commit()}
146
+	 * after calling write().
147
+	 *
148
+	 * This method returns the sequence ID of the write (i.e. 1 for first, 2 for
149
+	 * second, etc etc).
150
+	 *
151
+	 * @param string $bytes
152
+	 *
153
+	 * @return int
154
+	 *
155
+	 * @throws Swift_IoException
156
+	 *
157
+	 * @return $this
158
+	 */
159
+	public function write($bytes)
160
+	{
161
+		$this->canonicalizeBody($bytes);
162
+		foreach ($this->bound as $is) {
163
+			$is->write($bytes);
164
+		}
165
+
166
+		return $this;
167
+	}
168
+
169
+	/**
170
+	 * For any bytes that are currently buffered inside the stream, force them
171
+	 * off the buffer.
172
+	 *
173
+	 * @throws Swift_IoException
174
+	 *
175
+	 * @return $this
176
+	 */
177
+	public function commit()
178
+	{
179
+		// Nothing to do
180
+		return $this;
181
+	}
182
+
183
+	/**
184
+	 * Attach $is to this stream.
185
+	 *
186
+	 * The stream acts as an observer, receiving all data that is written.
187
+	 * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
188
+	 *
189
+	 * @return $this
190
+	 */
191
+	public function bind(Swift_InputByteStream $is)
192
+	{
193
+		// Don't have to mirror anything
194
+		$this->bound[] = $is;
195
+
196
+		return $this;
197
+	}
198
+
199
+	/**
200
+	 * Remove an already bound stream.
201
+	 *
202
+	 * If $is is not bound, no errors will be raised.
203
+	 * If the stream currently has any buffered data it will be written to $is
204
+	 * before unbinding occurs.
205
+	 *
206
+	 * @return $this
207
+	 */
208
+	public function unbind(Swift_InputByteStream $is)
209
+	{
210
+		// Don't have to mirror anything
211
+		foreach ($this->bound as $k => $stream) {
212
+			if ($stream === $is) {
213
+				unset($this->bound[$k]);
214
+
215
+				break;
216
+			}
217
+		}
218
+
219
+		return $this;
220
+	}
221
+
222
+	/**
223
+	 * Flush the contents of the stream (empty it) and set the internal pointer
224
+	 * to the beginning.
225
+	 *
226
+	 * @throws Swift_IoException
227
+	 *
228
+	 * @return $this
229
+	 */
230
+	public function flushBuffers()
231
+	{
232
+		$this->reset();
233
+
234
+		return $this;
235
+	}
236
+
237
+	/**
238
+	 * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1 defaults to rsa-sha256.
239
+	 *
240
+	 * @param string $hash
241
+	 *
242
+	 * @return $this
243
+	 */
244
+	public function setHashAlgorithm($hash)
245
+	{
246
+		$this->hashAlgorithm = 'rsa-sha1';
247
+
248
+		return $this;
249
+	}
250
+
251
+	/**
252
+	 * Set the canonicalization algorithm.
253
+	 *
254
+	 * @param string $canon simple | nofws defaults to simple
255
+	 *
256
+	 * @return $this
257
+	 */
258
+	public function setCanon($canon)
259
+	{
260
+		if ('nofws' == $canon) {
261
+			$this->canon = 'nofws';
262
+		} else {
263
+			$this->canon = 'simple';
264
+		}
265
+
266
+		return $this;
267
+	}
268
+
269
+	/**
270
+	 * Set the signer identity.
271
+	 *
272
+	 * @param string $identity
273
+	 *
274
+	 * @return $this
275
+	 */
276
+	public function setSignerIdentity($identity)
277
+	{
278
+		$this->signerIdentity = $identity;
279
+
280
+		return $this;
281
+	}
282
+
283
+	/**
284
+	 * Enable / disable the DebugHeaders.
285
+	 *
286
+	 * @param bool $debug
287
+	 *
288
+	 * @return $this
289
+	 */
290
+	public function setDebugHeaders($debug)
291
+	{
292
+		$this->debugHeaders = (bool) $debug;
293
+
294
+		return $this;
295
+	}
296
+
297
+	/**
298
+	 * Start Body.
299
+	 */
300
+	public function startBody()
301
+	{
302
+	}
303
+
304
+	/**
305
+	 * End Body.
306
+	 */
307
+	public function endBody()
308
+	{
309
+		$this->endOfBody();
310
+	}
311
+
312
+	/**
313
+	 * Returns the list of Headers Tampered by this plugin.
314
+	 *
315
+	 * @return array
316
+	 */
317
+	public function getAlteredHeaders()
318
+	{
319
+		if ($this->debugHeaders) {
320
+			return ['DomainKey-Signature', 'X-DebugHash'];
321
+		}
322
+
323
+		return ['DomainKey-Signature'];
324
+	}
325
+
326
+	/**
327
+	 * Adds an ignored Header.
328
+	 *
329
+	 * @param string $header_name
330
+	 *
331
+	 * @return $this
332
+	 */
333
+	public function ignoreHeader($header_name)
334
+	{
335
+		$this->ignoredHeaders[strtolower($header_name ?? '')] = true;
336
+
337
+		return $this;
338
+	}
339
+
340
+	/**
341
+	 * Set the headers to sign.
342
+	 *
343
+	 * @return $this
344
+	 */
345
+	public function setHeaders(Swift_Mime_SimpleHeaderSet $headers)
346
+	{
347
+		$this->startHash();
348
+		$this->canonData = '';
349
+		// Loop through Headers
350
+		$listHeaders = $headers->listAll();
351
+		foreach ($listHeaders as $hName) {
352
+			// Check if we need to ignore Header
353
+			if (!isset($this->ignoredHeaders[strtolower($hName ?? '')])) {
354
+				if ($headers->has($hName)) {
355
+					$tmp = $headers->getAll($hName);
356
+					foreach ($tmp as $header) {
357
+						if ('' != $header->getFieldBody()) {
358
+							$this->addHeader($header->toString());
359
+							$this->signedHeaders[] = $header->getFieldName();
360
+						}
361
+					}
362
+				}
363
+			}
364
+		}
365
+		$this->endOfHeaders();
366
+
367
+		return $this;
368
+	}
369
+
370
+	/**
371
+	 * Add the signature to the given Headers.
372
+	 *
373
+	 * @return $this
374
+	 */
375
+	public function addSignature(Swift_Mime_SimpleHeaderSet $headers)
376
+	{
377
+		// Prepare the DomainKey-Signature Header
378
+		$params = ['a' => $this->hashAlgorithm, 'b' => chunk_split(base64_encode($this->getEncryptedHash() ?? ''), 73, ' '), 'c' => $this->canon, 'd' => $this->domainName, 'h' => implode(': ', $this->signedHeaders), 'q' => 'dns', 's' => $this->selector];
379
+		$string = '';
380
+		foreach ($params as $k => $v) {
381
+			$string .= $k.'='.$v.'; ';
382
+		}
383
+		$string = trim($string);
384
+		$headers->addTextHeader('DomainKey-Signature', $string);
385
+
386
+		return $this;
387
+	}
388
+
389
+	/* Private helpers */
390
+
391
+	protected function addHeader($header)
392
+	{
393
+		switch ($this->canon) {
394
+			case 'nofws':
395
+				// Prepare Header and cascade
396
+				$exploded = explode(':', $header, 2);
397
+				$name = strtolower(trim($exploded[0]));
398
+				$value = str_replace("\r\n", '', $exploded[1]);
399
+				$value = preg_replace("/[ \t][ \t]+/", ' ', $value);
400
+				$header = $name.':'.trim($value)."\r\n";
401
+				// no break
402
+			case 'simple':
403
+				// Nothing to do
404
+		}
405
+		$this->addToHash($header);
406
+	}
407
+
408
+	protected function endOfHeaders()
409
+	{
410
+		$this->bodyCanonEmptyCounter = 1;
411
+	}
412
+
413
+	protected function canonicalizeBody($string)
414
+	{
415
+		$len = \strlen($string);
416
+		$canon = '';
417
+		$nofws = ('nofws' == $this->canon);
418
+		for ($i = 0; $i < $len; ++$i) {
419
+			if ($this->bodyCanonIgnoreStart > 0) {
420
+				--$this->bodyCanonIgnoreStart;
421
+				continue;
422
+			}
423
+			switch ($string[$i]) {
424
+				case "\r":
425
+					$this->bodyCanonLastChar = "\r";
426
+					break;
427
+				case "\n":
428
+					if ("\r" == $this->bodyCanonLastChar) {
429
+						if ($nofws) {
430
+							$this->bodyCanonSpace = false;
431
+						}
432
+						if ('' == $this->bodyCanonLine) {
433
+							++$this->bodyCanonEmptyCounter;
434
+						} else {
435
+							$this->bodyCanonLine = '';
436
+							$canon .= "\r\n";
437
+						}
438
+					} else {
439
+						// Wooops Error
440
+						throw new Swift_SwiftException('Invalid new line sequence in mail found \n without preceding \r');
441
+					}
442
+					break;
443
+				case ' ':
444
+				case "\t":
445
+				case "\x09": //HTAB
446
+					if ($nofws) {
447
+						$this->bodyCanonSpace = true;
448
+						break;
449
+					}
450
+					// no break
451
+				default:
452
+					if ($this->bodyCanonEmptyCounter > 0) {
453
+						$canon .= str_repeat("\r\n", $this->bodyCanonEmptyCounter);
454
+						$this->bodyCanonEmptyCounter = 0;
455
+					}
456
+					$this->bodyCanonLine .= $string[$i];
457
+					$canon .= $string[$i];
458
+			}
459
+		}
460
+		$this->addToHash($canon);
461
+	}
462
+
463
+	protected function endOfBody()
464
+	{
465
+		if (\strlen($this->bodyCanonLine) > 0) {
466
+			$this->addToHash("\r\n");
467
+		}
468
+	}
469
+
470
+	private function addToHash($string)
471
+	{
472
+		$this->canonData .= $string;
473
+		hash_update($this->hashHandler, $string);
474
+	}
475
+
476
+	private function startHash()
477
+	{
478
+		// Init
479
+		switch ($this->hashAlgorithm) {
480
+			case 'rsa-sha1':
481
+				$this->hashHandler = hash_init('sha1');
482
+				break;
483
+		}
484
+		$this->bodyCanonLine = '';
485
+	}
486
+
487
+	/**
488
+	 * @throws Swift_SwiftException
489
+	 *
490
+	 * @return string
491
+	 */
492
+	private function getEncryptedHash()
493
+	{
494
+		$signature = '';
495
+		$pkeyId = openssl_get_privatekey($this->privateKey);
496
+		if (!$pkeyId) {
497
+			throw new Swift_SwiftException('Unable to load DomainKey Private Key ['.openssl_error_string().']');
498
+		}
499
+		if (openssl_sign($this->canonData, $signature, $pkeyId, OPENSSL_ALGO_SHA1)) {
500
+			return $signature;
501
+		}
502
+		throw new Swift_SwiftException('Unable to sign DomainKey Hash  ['.openssl_error_string().']');
503
+	}
504 504
 }
Please login to merge, or discard this patch.
htdocs/includes/swiftmailer/lib/classes/Swift/Signers/BodySigner.php 1 patch
Indentation   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -15,17 +15,17 @@
 block discarded – undo
15 15
  */
16 16
 interface Swift_Signers_BodySigner extends Swift_Signer
17 17
 {
18
-    /**
19
-     * Change the Swift_Signed_Message to apply the singing.
20
-     *
21
-     * @return self
22
-     */
23
-    public function signMessage(Swift_Message $message);
18
+	/**
19
+	 * Change the Swift_Signed_Message to apply the singing.
20
+	 *
21
+	 * @return self
22
+	 */
23
+	public function signMessage(Swift_Message $message);
24 24
 
25
-    /**
26
-     * Return the list of header a signer might tamper.
27
-     *
28
-     * @return array
29
-     */
30
-    public function getAlteredHeaders();
25
+	/**
26
+	 * Return the list of header a signer might tamper.
27
+	 *
28
+	 * @return array
29
+	 */
30
+	public function getAlteredHeaders();
31 31
 }
Please login to merge, or discard this patch.
htdocs/includes/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php 1 patch
Indentation   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -15,47 +15,47 @@
 block discarded – undo
15 15
  */
16 16
 interface Swift_Signers_HeaderSigner extends Swift_Signer, Swift_InputByteStream
17 17
 {
18
-    /**
19
-     * Exclude an header from the signed headers.
20
-     *
21
-     * @param string $header_name
22
-     *
23
-     * @return self
24
-     */
25
-    public function ignoreHeader($header_name);
18
+	/**
19
+	 * Exclude an header from the signed headers.
20
+	 *
21
+	 * @param string $header_name
22
+	 *
23
+	 * @return self
24
+	 */
25
+	public function ignoreHeader($header_name);
26 26
 
27
-    /**
28
-     * Prepare the Signer to get a new Body.
29
-     *
30
-     * @return self
31
-     */
32
-    public function startBody();
27
+	/**
28
+	 * Prepare the Signer to get a new Body.
29
+	 *
30
+	 * @return self
31
+	 */
32
+	public function startBody();
33 33
 
34
-    /**
35
-     * Give the signal that the body has finished streaming.
36
-     *
37
-     * @return self
38
-     */
39
-    public function endBody();
34
+	/**
35
+	 * Give the signal that the body has finished streaming.
36
+	 *
37
+	 * @return self
38
+	 */
39
+	public function endBody();
40 40
 
41
-    /**
42
-     * Give the headers already given.
43
-     *
44
-     * @return self
45
-     */
46
-    public function setHeaders(Swift_Mime_SimpleHeaderSet $headers);
41
+	/**
42
+	 * Give the headers already given.
43
+	 *
44
+	 * @return self
45
+	 */
46
+	public function setHeaders(Swift_Mime_SimpleHeaderSet $headers);
47 47
 
48
-    /**
49
-     * Add the header(s) to the headerSet.
50
-     *
51
-     * @return self
52
-     */
53
-    public function addSignature(Swift_Mime_SimpleHeaderSet $headers);
48
+	/**
49
+	 * Add the header(s) to the headerSet.
50
+	 *
51
+	 * @return self
52
+	 */
53
+	public function addSignature(Swift_Mime_SimpleHeaderSet $headers);
54 54
 
55
-    /**
56
-     * Return the list of header a signer might tamper.
57
-     *
58
-     * @return array
59
-     */
60
-    public function getAlteredHeaders();
55
+	/**
56
+	 * Return the list of header a signer might tamper.
57
+	 *
58
+	 * @return array
59
+	 */
60
+	public function getAlteredHeaders();
61 61
 }
Please login to merge, or discard this patch.