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\Protocol\ClientProtocolHandler;
13
14use FreeDSx\Asn1\Exception\EncoderException;
15use FreeDSx\Ldap\Entry\Entries;
16use FreeDSx\Ldap\Exception\BindException;
17use FreeDSx\Ldap\Exception\OperationException;
18use FreeDSx\Ldap\Exception\ProtocolException;
19use FreeDSx\Ldap\Exception\UnsolicitedNotificationException;
20use FreeDSx\Ldap\Operation\LdapResult;
21use FreeDSx\Ldap\Operation\Request\SearchRequest;
22use FreeDSx\Ldap\Operation\Response\SearchResponse;
23use FreeDSx\Ldap\Operation\Response\SearchResultDone;
24use FreeDSx\Ldap\Operation\Response\SearchResultEntry;
25use FreeDSx\Ldap\Protocol\LdapMessageRequest;
26use FreeDSx\Ldap\Protocol\LdapMessageResponse;
27use FreeDSx\Ldap\Protocol\Queue\ClientQueue;
28use FreeDSx\Socket\Exception\ConnectionException;
29
30/**
31 * Logic for handling search operations.
32 *
33 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
34 */
35class ClientSearchHandler extends ClientBasicHandler
36{
37    /**
38     * @param ClientProtocolContext $context
39     * @return LdapMessageResponse|null
40     * @throws EncoderException
41     * @throws ProtocolException
42     * @throws UnsolicitedNotificationException
43     * @throws ConnectionException
44     */
45    public function handleRequest(ClientProtocolContext $context): ?LdapMessageResponse
46    {
47        /** @var SearchRequest $request */
48        $request = $context->getRequest();
49        if ($request->getBaseDn() === null) {
50            $request->setBaseDn($context->getOptions()['base_dn'] ?? null);
51        }
52
53        return parent::handleRequest($context);
54    }
55
56    /**
57     * @param LdapMessageRequest $messageTo
58     * @param LdapMessageResponse $messageFrom
59     * @param ClientQueue $queue
60     * @param array $options
61     * @return LdapMessageResponse|null
62     * @throws OperationException
63     * @throws BindException
64     * @throws ProtocolException
65     * @throws UnsolicitedNotificationException
66     * @throws ConnectionException
67     */
68    public function handleResponse(LdapMessageRequest $messageTo, LdapMessageResponse $messageFrom, ClientQueue $queue, array $options): ?LdapMessageResponse
69    {
70        $entries = [];
71
72        while (!($messageFrom->getResponse() instanceof SearchResultDone)) {
73            $response = $messageFrom->getResponse();
74            if ($response instanceof SearchResultEntry) {
75                $entry = $response->getEntry();
76                $entries[] = $entry;
77            }
78            $messageFrom = $queue->getMessage($messageTo->getMessageId());
79        }
80
81        $ldapResult = $messageFrom->getResponse();
82        if (!$ldapResult instanceof LdapResult) {
83            throw new OperationException('The final search result is malformed.');
84        }
85
86        $finalResponse = new LdapMessageResponse(
87            $messageFrom->getMessageId(),
88            new SearchResponse($ldapResult, new Entries(...$entries)),
89            ...$messageFrom->controls()->toArray()
90        );
91
92        return parent::handleResponse($messageTo, $finalResponse, $queue, $options);
93    }
94}
95