1<?php
2
3/**
4 * This file is part of the FreeDSx LDAP 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\Ldap\Operation\Response;
13
14use FreeDSx\Asn1\Asn1;
15use FreeDSx\Asn1\Exception\EncoderException;
16use FreeDSx\Asn1\Type\AbstractType;
17use FreeDSx\Asn1\Type\SequenceType;
18use FreeDSx\Ldap\Exception\ProtocolException;
19use FreeDSx\Ldap\Operation\LdapResult;
20
21/**
22 * RFC 4511 Section 4.2.2
23 *
24 * BindResponse ::= [APPLICATION 1] SEQUENCE {
25 *     COMPONENTS OF LDAPResult,
26 *     serverSaslCreds    [7] OCTET STRING OPTIONAL }
27 *
28 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
29 */
30class BindResponse extends LdapResult
31{
32    /**
33     * @var int
34     */
35    protected $tagNumber = 1;
36
37    /**
38     * @var null|string
39     */
40    protected $saslCreds;
41
42    /**
43     * @param LdapResult $result
44     * @param null|string $saslCreds
45     */
46    public function __construct(LdapResult $result, ?string $saslCreds = null)
47    {
48        $this->saslCreds = $saslCreds;
49        parent::__construct($result->getResultCode(), $result->getDn(), $result->getDiagnosticMessage(), ...$result->getReferrals());
50    }
51
52    /**
53     * @return null|string
54     */
55    public function getSaslCredentials(): ?string
56    {
57        return $this->saslCreds;
58    }
59
60    /**
61     * @return SequenceType
62     * @throws ProtocolException
63     */
64    public function toAsn1(): AbstractType
65    {
66        /** @var SequenceType $response */
67        $response = parent::toAsn1();
68
69        if ($this->saslCreds !== null) {
70            $response->addChild(Asn1::context(7, Asn1::octetString($this->saslCreds)));
71        }
72
73        return $response;
74    }
75
76    /**
77     * {@inheritDoc}
78     * @return self
79     * @throws EncoderException
80     */
81    public static function fromAsn1(AbstractType $type)
82    {
83        [$resultCode, $dn, $diag, $ref] = self::parseResultData($type);
84        $saslCreds = null;
85
86        foreach ($type->getChildren() as $child) {
87            if ($child->getTagNumber() === 7 && $child->getTagClass() === AbstractType::TAG_CLASS_CONTEXT_SPECIFIC) {
88                $saslCreds = $child->getValue();
89                break;
90            }
91        }
92
93        return new self(new LdapResult($resultCode, $dn, $diag, ...$ref), $saslCreds);
94    }
95}
96