diff --git a/docs/30_Methods.md b/docs/30_Methods.md
new file mode 100644
index 0000000000000000000000000000000000000000..8fd210c8a505867f4d0ab2dbcca910dbddb347fa
--- /dev/null
+++ b/docs/30_Methods.md
@@ -0,0 +1,502 @@
+# ldap.class.php
+
+<!-- BEGIN DOC-COMMENT H2 ../src/ldap.class.php -->
+
+---
+## `class imlldap`
+
+IML LDAP CONNECTOR *<pre> 2022-02-22  ah  added objGet(), sanitizeFilter() <br> 2022-08-18  ah  mask password (showing 4 chars only) <br> 2022-08-22  ah  mhash is deprecated <br> 2022-08-26  ah  fix verifyPassword <br> </pre>
+
+---
+## `private $_aLdap = array( 'server' => false, 'port' => false, 'DnLdapUser' => false, // ldap rdn oder dn 'PwLdapUser' => false, 'DnUserNode' => false, // ou=People... 'DnAppNode' => false, // cn=AppGroup... 'protoVersion' => 3, 'debugLevel' => 0, )`
+
+---
+## `private $_ldapConn = false`
+
+---
+## `private $_ldapBind = false`
+
+---
+## `public function __construct($aConfig = array())`
+
+constructor
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$aConfig | array | optional set ldap connection
+
+---
+## `public function debugOn()`
+
+turn debug messages on; if this detail level is not enough, set a value with key debugLevel in ldap config array
+
+---
+## `public function debugOff()`
+
+turn debug messages off
+
+---
+## `private function _w($sText)`
+
+write debug message if denugOn() was fired.
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sText | string | message text
+
+**Return:**
+
+  boolean
+
+---
+## `private function _wLdaperror($sText = '')`
+
+write last ldap error as debug
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sText | string | message text
+
+**Return:**
+
+  boolean
+
+---
+## `public function setConfig($aConfig = array())`
+
+set a ldap config
+
+            'server'       => 'ldaps://ldap.example.com',
+            'port'         => 636,
+            'DnLdapUser' => 'cn=Lookup,ou=ServiceAccounts,dc=org,dc=example.com',     // ldap rdn oder dn
+            'PwLdapUser' => 'IkHEFFzlZ...99j0h8WdI0LrLhxU',  // password
+            'DnUserNode'   => 'ou=People,ou=ORG,dc=org,dc=example.com',
+            'DnAppNode'    => '' optional dn ... if a user must be member of a given group
+            'protoVersion' => 3
+            'debugLevel'   => 0 // for debugging set higher 0 AND call debugOn()
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$aConfig | array | new config items
+
+---
+## `public function close()`
+
+close an existing ldap connection
+
+---
+## `public function connect()`
+
+connect to ldap
+
+---
+## `public function bind($sUser = '', $sPw = '')`
+
+ldap bind connects with a ldap user. If the ldap connection was not opened yet the connection will be established. If a binding exists it will be unbind
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sUser | string | optional: username (overrides _aLdap['DnLdapUser'])
+$sPw | string | optional: password (overrides _aLdap['PwLdapUser'])
+
+---
+## `public function unbind()`
+
+ldap unbind ... if a bind exists
+
+---
+## `public function DnExists($sDn)`
+
+check if a DN already exists; return is true/ false
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sDn | string | DN to check
+
+**Return:**
+
+  boolean
+
+---
+## `public function normalizeSearchentry($aRecord)`
+
+get simpler array from ldap_get_entries after ldap_search
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$aRecord | array | singel result item
+
+**Return:**
+
+  array
+
+---
+## `public function normalizeSearchresult($aLdapSearchresult)`
+
+get simpler array from ldap_get_entries after ldap_search
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$aRecord | array | singel result item
+
+**Return:**
+
+  array
+
+---
+## `static public function sanitizeFilter($s)`
+
+sanitize value to put into a search filter WARNING: the implementation is incomplete! I replaces the first N ascii chars only
+
+source: https://www.rfc-editor.org/rfc/rfc4515.txt
+
+$sCn = 'John Smith (john)'; $sSearchFilter = '(cn='.$oLdap->sanitizeFilter($sCn).')';
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$s | string | value to sanitize
+
+**Return:**
+
+  string
+
+---
+## `public function searchDn($sDn, $sSearchFilter='(objectclass=*)', $aAttributesToGet = array("*"), $bRecursive=true)`
+
+search in ldap directory and get result as array
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sDn | string | DN to search for
+$sSearchFilter | string | filter in ldap filter syntax
+$aAttributesToGet | array | flat array of attributes to fetch
+$bRecursive | boolean | recusrive (uses ldap_search) or not (ldap_list)
+
+**Return:**
+
+  array
+
+---
+## `public function searchUser($sSearchFilter='', $aAttributesToGet = array("*"), $bRecursive=true)`
+
+search for entries in in ldap user node and get result as array
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sSearchFilter | string | filter in ldap filter syntax
+$aAttributesToGet | array | flat array of attributes to fetch
+$bRecursive | bool | flag: recursive search? default: true (=yes, recursive)
+
+**Return:**
+
+  array
+
+---
+## `public function getUserInfo($sUser, $aAttributesToGet = array("*"))`
+
+search user by a given username or email address. It returns false if the user does not exist or is not member of the group 'DnAppNode' (if it was set).
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sUser | type | user id (uid) or email (mail) to search
+$aAttributesToGet | type | i.e. array("ou", "sn", "vorname", "mail", "uid", "memberOf")
+
+**Return:**
+
+  boolean|array
+
+---
+## `public function getUserDn($sUser)`
+
+search for a DN entry with the lookup user by a given username or email address. It returns false if the user does not exist or is not member of the group 'DnAppNode' (if it was set).
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sUser | type | %s
+
+**Return:**
+
+  string
+
+---
+## `public function setPassword($sUser, $sPW)`
+
+set a password for a given user; this requires a ldap bind with master/ admin account
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sUser | string | username or email
+$sPW | string | password
+
+**Return:**
+
+  boolean
+
+---
+## `private function _getNTLMHash($Input)`
+
+get NTLM hash from a string taken from https://secure.php.net/manual/en/ref.hash.php
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$Input | string | %s
+
+**Return:**
+
+  string
+
+---
+## `public function setPasswordSamba($sUser, $sPW)`
+
+set a password for a given user for Samba this requires a ldap bind with master/ admin account see https://msdn.microsoft.com/en-us/library/cc223248.aspx see http://php.net/ldap-modify-batch  - last examle see https://secure.php.net/manual/en/ref.hash.php
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sUser | string | username or email
+$sPW | string | password
+
+**Return:**
+
+  boolean
+
+---
+## `public function objAdd($sDn, $aItem)`
+
+update an ldap object this requires a ldap bind with master/ admin account
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sDn | string | dn to update
+$aItem | string | array of new ldap properties
+
+**Return:**
+
+  boolean
+
+---
+## `public function objAddAttr($sDn, $aItem)`
+
+update an ldap attribute this requires a ldap bind with master/ admin account
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sDn | string | dn to update
+$aItem | string | array of new ldap properties
+
+**Return:**
+
+  boolean
+
+---
+## `public function objGet($sDn, $sSearchFilter='(objectclass=*)', $aAttributesToGet = array("*"))`
+
+read attributes from ldap node with given DN (using ldap_read)
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sDn | string | DN to search for
+$sSearchFilter | string | filter in ldap filter syntax
+$aAttributesToGet | array | flat array of attributes to fetch
+
+**Return:**
+
+  array
+
+---
+## `public function objUpdate($sDn, $aItem)`
+
+update an ldap object with given key-value array if the attribute (key) does not exist it will be created. this requires a ldap bind with master/ admin account
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sDn | string | full DN where to update the item
+$aItem | array | updated entry
+
+**Return:**
+
+  boolean
+
+---
+## `public function objDelete($sDn)`
+
+delete an ldap object this requires a ldap bind with master/ admin account
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sDn | string | full DN to remove
+
+**Return:**
+
+  boolean
+
+---
+## `public function objDeleteAttr($sDn, $aItem)`
+
+delete attributes of an ldap object this requires a ldap bind with master/ admin account
+
+TODO: Test me
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sDn | string | DN
+$aItem | string | item to remove
+
+**Return:**
+
+  boolean
+
+---
+## `public function objectAttributeExists($sDn, $sAttribute)`
+
+check if an attribute exists in a DN
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sDn | string | DN
+$sAttribute | string | attribute name to check
+$sAttrValue | string | value to check
+
+**Return:**
+
+  boolean
+
+---
+## `public function objectAttributeAndValueExist($sDn, $sAttribute, $sAttrValue)`
+
+check if an attribute and value exist in a DN
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sDn | string | DN
+$sAttribute | string | attribute name to check
+$sAttrValue | string | value to check
+
+**Return:**
+
+  boolean
+
+---
+## `public function objectAttributeAndValueMustExist($sDn, $sAttribute, $sAttrValue)`
+
+check an attribute and value; it will be created if it does not exist this requires a ldap bind with master/ admin account
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sDn | string | dn to update
+$sAttribute | string | attribute name to check
+$sAttrValue | string | value to check
+
+**Return:**
+
+  boolean
+
+---
+## `public function userAdd($aItem, $sDn = false)`
+
+create a new user item this requires a ldap bind with master/ admin account
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$aItem | array | ldap properties
+$sDn | string | optional DN where to create the user
+
+**Return:**
+
+  boolean
+
+---
+## `public function userDelete($sUserDn)`
+
+delete a user this requires a ldap bind with master/ admin account
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sUser | string | user to update
+$sPW | string | new password to set
+
+**Return:**
+
+  boolean
+
+---
+## `public function userUpdate($aItem)`
+
+update an ldap object this requires a ldap bind with master/ admin account
+
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$aItem | array | new user data to update
+
+**Return:**
+
+  boolean
+
+---
+## `public function verifyPassword($sUser, $sPW)`
+
+verify user and password
+**Parameters:**
+
+Var | Type | Desciption
+--  |--    |--
+$sUser | string | username or email
+$sPW | string | password
+
+**Return:**
+
+  boolean
+
+<!-- END DOC-COMMENT -->
\ No newline at end of file
diff --git a/docs/_update_docblocs.sh b/docs/_update_docblocs.sh
new file mode 100755
index 0000000000000000000000000000000000000000..11c7faadb547d998abfa4965c6870429d83ef5d7
--- /dev/null
+++ b/docs/_update_docblocs.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+cd "$( dirname "$0")" || exit 1
+docblox2md -v 30_Methods.md
diff --git a/docs/style.css b/docs/style.css
index 02b2415b02181d56d377762e0cac369c011c03d4..909562cb91d2a8335f4470332ef1e07bdb2ee44c 100644
--- a/docs/style.css
+++ b/docs/style.css
@@ -1,11 +1,12 @@
 /*
 
     patch css elements of daux.io blue theme
+    version 2022-05-13
 
 */
 
 
-/* ---------- vars ---------- */
+/* ---------- vars ---------- */ 
 
 :root{
 
@@ -27,14 +28,24 @@
 
     --h1: rgba(40,60,80,0.8);
     --h1-bottom: 1px solid rgba(40,60,80,0.1);
-    --h2: rgba(40,60,80,0.5);
-    --h3: rgba(40,60,80,0.3);
+    --h2: #468;
+    --h3: #579;
 
 }
 
 /* ---------- tags ---------- */
 
-body, *{color: var(--color); }
+a.Brand::before {
+	background: rgb(255,0,51);
+	color: #fff;
+    font-family: arial;
+	font-weight: bold;
+	padding: 0.5em 0.3em;
+	content: 'IML';
+    margin-right: 0.4em;
+}
+
+body, *{color: var(--color);}
 body{background: var(--bg-body);}