1<?php
2
3/**
4 * This file is part of the FreeDSx SASL package.
5 *
6 * (c) Chad Sikorra <Chad.Sikorra@gmail.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace FreeDSx\Sasl\Encoder;
13
14use FreeDSx\Sasl\Exception\SaslEncodingException;
15use FreeDSx\Sasl\Message;
16use FreeDSx\Sasl\SaslContext;
17
18/**
19 * Responsible for encoding / decoding PLAIN messages.
20 *
21 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
22 */
23class PlainEncoder implements EncoderInterface
24{
25    /**
26     * {@inheritDoc}
27     */
28    public function encode(Message $message, SaslContext $context): string
29    {
30        if (!$message->has('authzid')) {
31            throw new SaslEncodingException('The PLAIN message must contain a authzid.');
32        }
33        if (!$message->has('authcid')) {
34            throw new SaslEncodingException('The PLAIN message must contain a authzid.');
35        }
36        if (!$message->has('password')) {
37            throw new SaslEncodingException('The PLAIN message must contain a password.');
38        }
39        $authzid = $this->validate($message->get('authzid'));
40        $authcid = $this->validate($message->get('authcid'));
41        $password = $this->validate($message->get('password'));
42
43        return $authzid . "\x00" . $authcid . "\x00" . $password;
44    }
45
46    /**
47     * {@inheritDoc}
48     */
49    public function decode(string $data, SaslContext $context): Message
50    {
51        if (preg_match('/^([^\x0]+)\x00([^\x0]+)\x00([^\x0]+)$/', $data, $matches) === 0) {
52            throw new SaslEncodingException('The PLAIN message data is malformed.');
53        }
54
55        return new Message([
56            'authzid' => $matches[1],
57            'authcid' => $matches[2],
58            'password' => $matches[3],
59        ]);
60    }
61
62    protected function validate(string $data): string
63    {
64        if (strpos($data,"\x00") !== false) {
65            throw new SaslEncodingException('PLAIN mechanism data cannot contain a null character.');
66        }
67
68        return $data;
69    }
70}
71