["?content", "objectClass=*", "filtre de recherche"], "attrs" => ["?array", [], "attributs à retourner"], "searchbase" => ["?string", null, "DN de base pour la recherche"], "scope" => ["?string", "sub", "étendue de la recherche"], "suffix" => ["?string", null, "DN de base du serveur"], "attributes_only" => ["bool", false, "faut-il ne retourner que les attributs?"], "sizelimit" => ["int", -1, "limite de taille"], "timelimit" => ["int", -1, "limite de temps"], "deref" => ["int", LDAP_DEREF_NEVER, "type de déférencement"], "controls" => ["array", [], "contrôles de la recherche"], ]; private static $search_md; static function search_md(): Metadata { return md_utils::ensure_md(self::$search_md, self::PARAMETRABLE_PARAMS_SCHEMA); } function __construct($conn, array $params) { $this->conn = $conn; parent::__construct($params); } /** @var resource */ protected $conn; /** @var string */ protected $ppSearchbase; /** @var string */ protected $filter; function pp_setFilter($filter): void { $this->filter = filters::parse($filter); } /** @var array */ protected $ppAttrs; /** retourner la liste des attributs demandés */ function getAttrs(): array { return $this->ppAttrs; } /** @var int */ protected $scope; function pp_setScope(string $scope): void { switch ($scope) { case self::SCOPE_SUBTREE: case "subtree": case "sub": case "s": $this->scope = self::SCOPE_SUBTREE; break; case self::SCOPE_ONELEVEL: case "onelevel": case "one": case "o": $this->scope = self::SCOPE_ONELEVEL; break; case self::SCOPE_BASE: case "base": case "b": $this->scope = self::SCOPE_BASE; break; default: throw ValueException::invalid_value($scope, "scope"); } } /** @var string */ protected $ppSuffix; /** @var bool */ protected $ppAttributesOnly; /** @var int */ protected $ppSizelimit; /** @var int */ protected $ppTimelimit; /** @var int */ protected $ppDeref; /** @var array */ protected $ppControls; /** @throws LdapException */ function getIterator() { $conn = $this->conn; $args = [$conn]; $base = []; if ($this->ppSearchbase) $base[] = $this->ppSearchbase; if ($this->ppSuffix) $base[] = $this->ppSuffix; $args[] = implode(",", $base); A::merge($args, [ $this->filter?: "", $this->ppAttrs?: [], $this->ppAttributesOnly, $this->ppSizelimit, $this->ppTimelimit, $this->ppDeref, $this->ppControls, ]); msg::debug("Searching searchbase=$args[1] filter=$args[2]"); $scope = $this->scope; if ($scope == self::SCOPE_SUBTREE) $rr = @ldap_search(...$args); elseif ($scope == self::SCOPE_ONELEVEL) $rr = @ldap_list(...$args); elseif ($scope == self::SCOPE_BASE) $rr = @ldap_read(...$args); else throw ValueException::invalid_value($scope, "scope"); $rr = LdapException::check("search", $conn, $rr, 32); if ($rr === false) return; // pas trouvé try { $er = LdapException::check("first_entry", $conn, ldap_first_entry($conn, $rr), 32); while ($er !== false) { $dn = ldap_get_dn($conn, $er); $entry = ldap_get_attributes($conn, $er); yield $dn => $entry; $er = LdapException::check("next_entry", $conn, ldap_next_entry($conn, $er), 32); } } catch (StopException $e) { } finally { ldap_free_result($rr); } } /** * retourner la première entrée du résultat de la recherche ou null si la * recherche ne retourne aucun résultat * * @throws LdapException */ function first(?string &$dn=null): ?array { $it = $this->getIterator(); $it->rewind(); if (!$it->valid()) return null; try { $dn = $it->key(); return $it->current(); } finally { iter::close($it); } } static function cook(array $initial_names, string $dn, array $entry): array { # attributs demandés $lkey2names = ["dn" => "dn"]; foreach ($initial_names as $name) { if ($name == "+" || $name == "*") continue; $lkey2names[strtolower($name)] = $name; } # attributs obtenus effectivement $count = $entry["count"]; $attrs = ["dn" => [$dn]]; for ($i = 0; $i < $count; $i++) { $name = $entry[$i]; $attr = $entry[$name]; unset($attr["count"]); $attrs[$name] = $attr; $lkey2names[strtolower($name)] = $name; } # ensuite, mettre à null les attributs qui n'ont pas été obtenus foreach ($lkey2names as $name) { if (!array_key_exists($name, $attrs)) { $attrs[$name] = null; } } # calculer les clés qui composent le DN $dn_names = names::get_dn_names($dn, $lkey2names); return [$attrs, $lkey2names, $dn_names]; } }