git subrepo commit (merge) mailcow/src/mailcow-dockerized

subrepo: subdir:   "mailcow/src/mailcow-dockerized"
  merged:   "02ae5285"
upstream: origin:   "https://github.com/mailcow/mailcow-dockerized.git"
  branch:   "master"
  commit:   "649a5c01"
git-subrepo: version:  "0.4.3"
  origin:   "???"
  commit:   "???"
Change-Id: I870ad468fba026cc5abf3c5699ed1e12ff28b32b
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedName.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedName.php
new file mode 100644
index 0000000..c092173
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedName.php
@@ -0,0 +1,419 @@
+<?php
+
+namespace LdapRecord\Models\Attributes;
+
+use LdapRecord\EscapesValues;
+use LdapRecord\Support\Arr;
+
+class DistinguishedName
+{
+    use EscapesValues;
+
+    /**
+     * The underlying raw value.
+     *
+     * @var string|null
+     */
+    protected $value;
+
+    /**
+     * Constructor.
+     *
+     * @param string|null $value
+     */
+    public function __construct($value = null)
+    {
+        $this->value = trim($value);
+    }
+
+    /**
+     * Get the distinguished name value.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return (string) $this->value;
+    }
+
+    /**
+     * Alias of the "build" method.
+     *
+     * @param string|null $value
+     *
+     * @return DistinguishedNameBuilder
+     */
+    public static function of($value = null)
+    {
+        return static::build($value);
+    }
+
+    /**
+     * Get a new DN builder object from the given DN.
+     *
+     * @param string|null $value
+     *
+     * @return DistinguishedNameBuilder
+     */
+    public static function build($value = null)
+    {
+        return new DistinguishedNameBuilder($value);
+    }
+
+    /**
+     * Make a new distinguished name instance.
+     *
+     * @param string|null $value
+     *
+     * @return static
+     */
+    public static function make($value = null)
+    {
+        return new static($value);
+    }
+
+    /**
+     * Explode a distinguished name into relative distinguished names.
+     *
+     * @param string $dn
+     *
+     * @return array
+     */
+    public static function explode($dn)
+    {
+        $dn = ldap_explode_dn($dn, $withoutAttributes = false);
+
+        if (! is_array($dn)) {
+            return [];
+        }
+
+        if (! array_key_exists('count', $dn)) {
+            return [];
+        }
+
+        unset($dn['count']);
+
+        return $dn;
+    }
+
+    /**
+     * Un-escapes a hexadecimal string into its original string representation.
+     *
+     * @param string $value
+     *
+     * @return string
+     */
+    public static function unescape($value)
+    {
+        return preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', function ($matches) {
+            return chr(hexdec($matches[1]));
+        }, $value);
+    }
+
+    /**
+     * Explode the RDN into an attribute and value.
+     *
+     * @param string $rdn
+     *
+     * @return array
+     */
+    public static function explodeRdn($rdn)
+    {
+        return explode('=', $rdn, $limit = 2);
+    }
+
+    /**
+     * Implode the component attribute and value into an RDN.
+     *
+     * @param string $rdn
+     *
+     * @return string
+     */
+    public static function makeRdn(array $component)
+    {
+        return implode('=', $component);
+    }
+
+    /**
+     * Get the underlying value.
+     *
+     * @return string|null
+     */
+    public function get()
+    {
+        return $this->value;
+    }
+
+    /**
+     * Set the underlying value.
+     *
+     * @param string|null $value
+     *
+     * @return $this
+     */
+    public function set($value)
+    {
+        $this->value = $value;
+
+        return $this;
+    }
+
+    /**
+     * Get the distinguished name values without attributes.
+     *
+     * @return array
+     */
+    public function values()
+    {
+        $values = [];
+
+        foreach ($this->multi() as [, $value]) {
+            $values[] = static::unescape($value);
+        }
+
+        return $values;
+    }
+
+    /**
+     * Get the distinguished name attributes without values.
+     *
+     * @return array
+     */
+    public function attributes()
+    {
+        $attributes = [];
+
+        foreach ($this->multi() as [$attribute]) {
+            $attributes[] = $attribute;
+        }
+
+        return $attributes;
+    }
+
+    /**
+     * Get the distinguished name components with attributes.
+     *
+     * @return array
+     */
+    public function components()
+    {
+        $components = [];
+
+        foreach ($this->multi() as [$attribute, $value]) {
+            // When a distinguished name is exploded, the values are automatically
+            // escaped. This cannot be opted out of. Here we will unescape
+            // the attribute value, then re-escape it to its original
+            // representation from the server using the "dn" flag.
+            $value = $this->escape(static::unescape($value))->dn();
+
+            $components[] = static::makeRdn([$attribute, $value]);
+        }
+
+        return $components;
+    }
+
+    /**
+     * Convert the distinguished name into an associative array.
+     *
+     * @return array
+     */
+    public function assoc()
+    {
+        $map = [];
+
+        foreach ($this->multi() as [$attribute, $value]) {
+            $attribute = $this->normalize($attribute);
+
+            array_key_exists($attribute, $map)
+                ? $map[$attribute][] = $value
+                : $map[$attribute] = [$value];
+        }
+
+        return $map;
+    }
+
+    /**
+     * Split the RDNs into a multi-dimensional array.
+     *
+     * @return array
+     */
+    public function multi()
+    {
+        return array_map(function ($rdn) {
+            return static::explodeRdn($rdn);
+        }, $this->rdns());
+    }
+
+    /**
+     * Split the distinguished name into an array of unescaped RDN's.
+     *
+     * @return array
+     */
+    public function rdns()
+    {
+        return static::explode($this->value);
+    }
+
+    /**
+     * Get the first RDNs value.
+     *
+     * @return string|null
+     */
+    public function name()
+    {
+        return Arr::first($this->values());
+    }
+
+    /**
+     * Get the first RDNs attribute.
+     *
+     * @return string|null
+     */
+    public function head()
+    {
+        return Arr::first($this->attributes());
+    }
+
+    /**
+     * Get the relative distinguished name.
+     *
+     * @return string|null
+     */
+    public function relative()
+    {
+        return Arr::first($this->components());
+    }
+
+    /**
+     * Alias of relative().
+     *
+     * Get the first RDN from the distinguished name.
+     *
+     * @return string|null
+     */
+    public function first()
+    {
+        return $this->relative();
+    }
+
+    /**
+     * Get the parent distinguished name.
+     *
+     * @return string|null
+     */
+    public function parent()
+    {
+        $components = $this->components();
+
+        array_shift($components);
+
+        return implode(',', $components) ?: null;
+    }
+
+    /**
+     * Determine if the current distinguished name is a parent of the given child.
+     *
+     * @param DistinguishedName $child
+     *
+     * @return bool
+     */
+    public function isParentOf(self $child)
+    {
+        return $child->isChildOf($this);
+    }
+
+    /**
+     * Determine if the current distinguished name is a child of the given parent.
+     *
+     * @param DistinguishedName $parent
+     *
+     * @return bool
+     */
+    public function isChildOf(self $parent)
+    {
+        if (
+            empty($components = $this->components()) ||
+            empty($parentComponents = $parent->components())
+        ) {
+            return false;
+        }
+
+        array_shift($components);
+
+        return $this->compare($components, $parentComponents);
+    }
+
+    /**
+     * Determine if the current distinguished name is an ancestor of the descendant.
+     *
+     * @param DistinguishedName $descendant
+     *
+     * @return bool
+     */
+    public function isAncestorOf(self $descendant)
+    {
+        return $descendant->isDescendantOf($this);
+    }
+
+    /**
+     * Determine if the current distinguished name is a descendant of the ancestor.
+     *
+     * @param DistinguishedName $ancestor
+     *
+     * @return bool
+     */
+    public function isDescendantOf(self $ancestor)
+    {
+        if (
+            empty($components = $this->components()) ||
+            empty($ancestorComponents = $ancestor->components())
+        ) {
+            return false;
+        }
+
+        if (! $length = count($components) - count($ancestorComponents)) {
+            return false;
+        }
+
+        array_splice($components, $offset = 0, $length);
+
+        return $this->compare($components, $ancestorComponents);
+    }
+
+    /**
+     * Compare whether the two distinguished name values are equal.
+     *
+     * @param array $values
+     * @param array $other
+     *
+     * @return bool
+     */
+    protected function compare(array $values, array $other)
+    {
+        return $this->recase($values) == $this->recase($other);
+    }
+
+    /**
+     * Recase the array values.
+     *
+     * @param array $values
+     *
+     * @return array
+     */
+    protected function recase(array $values)
+    {
+        return array_map([$this, 'normalize'], $values);
+    }
+
+    /**
+     * Normalize the string value.
+     *
+     * @param string $value
+     *
+     * @return string
+     */
+    protected function normalize($value)
+    {
+        return strtolower($value);
+    }
+}