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\Exception\BindException; 16use FreeDSx\Ldap\Exception\OperationException; 17use FreeDSx\Ldap\Exception\ProtocolException; 18use FreeDSx\Ldap\Exception\UnsolicitedNotificationException; 19use FreeDSx\Ldap\Operation\LdapResult; 20use FreeDSx\Ldap\Operation\Request\BindRequest; 21use FreeDSx\Ldap\Operation\ResultCode; 22use FreeDSx\Ldap\Protocol\LdapMessageRequest; 23use FreeDSx\Ldap\Protocol\LdapMessageResponse; 24use FreeDSx\Ldap\Protocol\Queue\ClientQueue; 25use FreeDSx\Socket\Exception\ConnectionException; 26use function in_array; 27 28/** 29 * Logic for handling basic operations. 30 * 31 * @author Chad Sikorra <Chad.Sikorra@gmail.com> 32 */ 33class ClientBasicHandler implements RequestHandlerInterface, ResponseHandlerInterface 34{ 35 /** 36 * RFC 4511, A.1. These are considered result codes that do not indicate an error condition. 37 */ 38 protected const NON_ERROR_CODES = [ 39 ResultCode::SUCCESS, 40 ResultCode::COMPARE_FALSE, 41 ResultCode::COMPARE_TRUE, 42 ResultCode::REFERRAL, 43 ResultCode::SASL_BIND_IN_PROGRESS, 44 ]; 45 46 /** 47 * @param ClientProtocolContext $context 48 * @return LdapMessageResponse 49 * @throws ProtocolException 50 * @throws UnsolicitedNotificationException 51 * @throws ConnectionException 52 * @throws EncoderException 53 */ 54 public function handleRequest(ClientProtocolContext $context): ?LdapMessageResponse 55 { 56 $queue = $context->getQueue(); 57 $message = $context->messageToSend(); 58 $queue->sendMessage($message); 59 60 return $queue->getMessage($message->getMessageId()); 61 } 62 63 /** 64 * @param LdapMessageRequest $messageTo 65 * @param LdapMessageResponse $messageFrom 66 * @param ClientQueue $queue 67 * @param array $options 68 * @return LdapMessageResponse 69 * @throws BindException 70 * @throws OperationException 71 */ 72 public function handleResponse(LdapMessageRequest $messageTo, LdapMessageResponse $messageFrom, ClientQueue $queue, array $options): ?LdapMessageResponse 73 { 74 $result = $messageFrom->getResponse(); 75 76 # No action to take if we received something that isn't an LDAP Result, or on success. 77 if (!$result instanceof LdapResult || $result->getResultCode() === ResultCode::SUCCESS) { 78 return $messageFrom; 79 } 80 81 # The success code above should satisfy the majority of cases. This checks if the result code is really a non 82 # error condition defined in RFC 4511, A.1 83 if (in_array($result->getResultCode(), self::NON_ERROR_CODES, true)) { 84 return $messageFrom; 85 } 86 87 if ($messageTo->getRequest() instanceof BindRequest) { 88 throw new BindException( 89 sprintf('Unable to bind to LDAP. %s', $result->getDiagnosticMessage()), 90 $result->getResultCode() 91 ); 92 } 93 94 throw new OperationException($result->getDiagnosticMessage(), $result->getResultCode()); 95 } 96} 97