Я пытаюсь добавить некоторых пользователей в свой Ldap DB, но я получаю некоторые ошибки (недопустимый синтаксис dn), когда я использую некоторые специальные символы, такие как «,.». Мне нужна функция, которая позволяет избежать всех символов. Я пытаюсь preg_quote, но в некоторых случаях получаю некоторые ошибки.
заранее спасибо
Код:
$user = 'Test , Name S.L'; if(!(ldap_add($ds, "cn=" . $user . ",".LDAP_DN_BASE, $info))) { include 'error_new_account.php'; }
EDIT Январь 2013: добавлена поддержка экранирования ведущих / конечных пробелов в DN-строках, по RFC 4514 . Спасибо Евгению за то, что он указал на эту проблему.
EDIT 2014: Я добавил эту функцию в PHP 5.6 . Нижеприведенный код теперь похож на замену для более ранних версий PHP.
if (!function_exists('ldap_escape')) { define('LDAP_ESCAPE_FILTER', 0x01); define('LDAP_ESCAPE_DN', 0x02); /** * @param string $subject The subject string * @param string $ignore Set of characters to leave untouched * @param int $flags Any combination of LDAP_ESCAPE_* flags to indicate the * set(s) of characters to escape. * @return string */ function ldap_escape($subject, $ignore = '', $flags = 0) { static $charMaps = array( LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"), LDAP_ESCAPE_DN => array('\\', ',', '=', '+', '<', '>', ';', '"', '#'), ); // Pre-process the char maps on first call if (!isset($charMaps[0])) { $charMaps[0] = array(); for ($i = 0; $i < 256; $i++) { $charMaps[0][chr($i)] = sprintf('\\%02x', $i);; } for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_FILTER]); $i < $l; $i++) { $chr = $charMaps[LDAP_ESCAPE_FILTER][$i]; unset($charMaps[LDAP_ESCAPE_FILTER][$i]); $charMaps[LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr]; } for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_DN]); $i < $l; $i++) { $chr = $charMaps[LDAP_ESCAPE_DN][$i]; unset($charMaps[LDAP_ESCAPE_DN][$i]); $charMaps[LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr]; } } // Create the base char map to escape $flags = (int)$flags; $charMap = array(); if ($flags & LDAP_ESCAPE_FILTER) { $charMap += $charMaps[LDAP_ESCAPE_FILTER]; } if ($flags & LDAP_ESCAPE_DN) { $charMap += $charMaps[LDAP_ESCAPE_DN]; } if (!$charMap) { $charMap = $charMaps[0]; } // Remove any chars to ignore from the list $ignore = (string)$ignore; for ($i = 0, $l = strlen($ignore); $i < $l; $i++) { unset($charMap[$ignore[$i]]); } // Do the main replacement $result = strtr($subject, $charMap); // Encode leading/trailing spaces if LDAP_ESCAPE_DN is passed if ($flags & LDAP_ESCAPE_DN) { if ($result[0] === ' ') { $result = '\\20' . substr($result, 1); } if ($result[strlen($result) - 1] === ' ') { $result = substr($result, 0, -1) . '\\20'; } } return $result; } }
неif (!function_exists('ldap_escape')) { define('LDAP_ESCAPE_FILTER', 0x01); define('LDAP_ESCAPE_DN', 0x02); /** * @param string $subject The subject string * @param string $ignore Set of characters to leave untouched * @param int $flags Any combination of LDAP_ESCAPE_* flags to indicate the * set(s) of characters to escape. * @return string */ function ldap_escape($subject, $ignore = '', $flags = 0) { static $charMaps = array( LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"), LDAP_ESCAPE_DN => array('\\', ',', '=', '+', '<', '>', ';', '"', '#'), ); // Pre-process the char maps on first call if (!isset($charMaps[0])) { $charMaps[0] = array(); for ($i = 0; $i < 256; $i++) { $charMaps[0][chr($i)] = sprintf('\\%02x', $i);; } for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_FILTER]); $i < $l; $i++) { $chr = $charMaps[LDAP_ESCAPE_FILTER][$i]; unset($charMaps[LDAP_ESCAPE_FILTER][$i]); $charMaps[LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr]; } for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_DN]); $i < $l; $i++) { $chr = $charMaps[LDAP_ESCAPE_DN][$i]; unset($charMaps[LDAP_ESCAPE_DN][$i]); $charMaps[LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr]; } } // Create the base char map to escape $flags = (int)$flags; $charMap = array(); if ($flags & LDAP_ESCAPE_FILTER) { $charMap += $charMaps[LDAP_ESCAPE_FILTER]; } if ($flags & LDAP_ESCAPE_DN) { $charMap += $charMaps[LDAP_ESCAPE_DN]; } if (!$charMap) { $charMap = $charMaps[0]; } // Remove any chars to ignore from the list $ignore = (string)$ignore; for ($i = 0, $l = strlen($ignore); $i < $l; $i++) { unset($charMap[$ignore[$i]]); } // Do the main replacement $result = strtr($subject, $charMap); // Encode leading/trailing spaces if LDAP_ESCAPE_DN is passed if ($flags & LDAP_ESCAPE_DN) { if ($result[0] === ' ') { $result = '\\20' . substr($result, 1); } if ($result[strlen($result) - 1] === ' ') { $result = substr($result, 0, -1) . '\\20'; } } return $result; } }
отображенийif (!function_exists('ldap_escape')) { define('LDAP_ESCAPE_FILTER', 0x01); define('LDAP_ESCAPE_DN', 0x02); /** * @param string $subject The subject string * @param string $ignore Set of characters to leave untouched * @param int $flags Any combination of LDAP_ESCAPE_* flags to indicate the * set(s) of characters to escape. * @return string */ function ldap_escape($subject, $ignore = '', $flags = 0) { static $charMaps = array( LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"), LDAP_ESCAPE_DN => array('\\', ',', '=', '+', '<', '>', ';', '"', '#'), ); // Pre-process the char maps on first call if (!isset($charMaps[0])) { $charMaps[0] = array(); for ($i = 0; $i < 256; $i++) { $charMaps[0][chr($i)] = sprintf('\\%02x', $i);; } for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_FILTER]); $i < $l; $i++) { $chr = $charMaps[LDAP_ESCAPE_FILTER][$i]; unset($charMaps[LDAP_ESCAPE_FILTER][$i]); $charMaps[LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr]; } for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_DN]); $i < $l; $i++) { $chr = $charMaps[LDAP_ESCAPE_DN][$i]; unset($charMaps[LDAP_ESCAPE_DN][$i]); $charMaps[LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr]; } } // Create the base char map to escape $flags = (int)$flags; $charMap = array(); if ($flags & LDAP_ESCAPE_FILTER) { $charMap += $charMaps[LDAP_ESCAPE_FILTER]; } if ($flags & LDAP_ESCAPE_DN) { $charMap += $charMaps[LDAP_ESCAPE_DN]; } if (!$charMap) { $charMap = $charMaps[0]; } // Remove any chars to ignore from the list $ignore = (string)$ignore; for ($i = 0, $l = strlen($ignore); $i < $l; $i++) { unset($charMap[$ignore[$i]]); } // Do the main replacement $result = strtr($subject, $charMap); // Encode leading/trailing spaces if LDAP_ESCAPE_DN is passed if ($flags & LDAP_ESCAPE_DN) { if ($result[0] === ' ') { $result = '\\20' . substr($result, 1); } if ($result[strlen($result) - 1] === ' ') { $result = substr($result, 0, -1) . '\\20'; } } return $result; } }
неif (!function_exists('ldap_escape')) { define('LDAP_ESCAPE_FILTER', 0x01); define('LDAP_ESCAPE_DN', 0x02); /** * @param string $subject The subject string * @param string $ignore Set of characters to leave untouched * @param int $flags Any combination of LDAP_ESCAPE_* flags to indicate the * set(s) of characters to escape. * @return string */ function ldap_escape($subject, $ignore = '', $flags = 0) { static $charMaps = array( LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"), LDAP_ESCAPE_DN => array('\\', ',', '=', '+', '<', '>', ';', '"', '#'), ); // Pre-process the char maps on first call if (!isset($charMaps[0])) { $charMaps[0] = array(); for ($i = 0; $i < 256; $i++) { $charMaps[0][chr($i)] = sprintf('\\%02x', $i);; } for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_FILTER]); $i < $l; $i++) { $chr = $charMaps[LDAP_ESCAPE_FILTER][$i]; unset($charMaps[LDAP_ESCAPE_FILTER][$i]); $charMaps[LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr]; } for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_DN]); $i < $l; $i++) { $chr = $charMaps[LDAP_ESCAPE_DN][$i]; unset($charMaps[LDAP_ESCAPE_DN][$i]); $charMaps[LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr]; } } // Create the base char map to escape $flags = (int)$flags; $charMap = array(); if ($flags & LDAP_ESCAPE_FILTER) { $charMap += $charMaps[LDAP_ESCAPE_FILTER]; } if ($flags & LDAP_ESCAPE_DN) { $charMap += $charMaps[LDAP_ESCAPE_DN]; } if (!$charMap) { $charMap = $charMaps[0]; } // Remove any chars to ignore from the list $ignore = (string)$ignore; for ($i = 0, $l = strlen($ignore); $i < $l; $i++) { unset($charMap[$ignore[$i]]); } // Do the main replacement $result = strtr($subject, $charMap); // Encode leading/trailing spaces if LDAP_ESCAPE_DN is passed if ($flags & LDAP_ESCAPE_DN) { if ($result[0] === ' ') { $result = '\\20' . substr($result, 1); } if ($result[strlen($result) - 1] === ' ') { $result = substr($result, 0, -1) . '\\20'; } } return $result; } }
отображенийif (!function_exists('ldap_escape')) { define('LDAP_ESCAPE_FILTER', 0x01); define('LDAP_ESCAPE_DN', 0x02); /** * @param string $subject The subject string * @param string $ignore Set of characters to leave untouched * @param int $flags Any combination of LDAP_ESCAPE_* flags to indicate the * set(s) of characters to escape. * @return string */ function ldap_escape($subject, $ignore = '', $flags = 0) { static $charMaps = array( LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"), LDAP_ESCAPE_DN => array('\\', ',', '=', '+', '<', '>', ';', '"', '#'), ); // Pre-process the char maps on first call if (!isset($charMaps[0])) { $charMaps[0] = array(); for ($i = 0; $i < 256; $i++) { $charMaps[0][chr($i)] = sprintf('\\%02x', $i);; } for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_FILTER]); $i < $l; $i++) { $chr = $charMaps[LDAP_ESCAPE_FILTER][$i]; unset($charMaps[LDAP_ESCAPE_FILTER][$i]); $charMaps[LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr]; } for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_DN]); $i < $l; $i++) { $chr = $charMaps[LDAP_ESCAPE_DN][$i]; unset($charMaps[LDAP_ESCAPE_DN][$i]); $charMaps[LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr]; } } // Create the base char map to escape $flags = (int)$flags; $charMap = array(); if ($flags & LDAP_ESCAPE_FILTER) { $charMap += $charMaps[LDAP_ESCAPE_FILTER]; } if ($flags & LDAP_ESCAPE_DN) { $charMap += $charMaps[LDAP_ESCAPE_DN]; } if (!$charMap) { $charMap = $charMaps[0]; } // Remove any chars to ignore from the list $ignore = (string)$ignore; for ($i = 0, $l = strlen($ignore); $i < $l; $i++) { unset($charMap[$ignore[$i]]); } // Do the main replacement $result = strtr($subject, $charMap); // Encode leading/trailing spaces if LDAP_ESCAPE_DN is passed if ($flags & LDAP_ESCAPE_DN) { if ($result[0] === ' ') { $result = '\\20' . substr($result, 1); } if ($result[strlen($result) - 1] === ' ') { $result = substr($result, 0, -1) . '\\20'; } } return $result; } }
сif (!function_exists('ldap_escape')) { define('LDAP_ESCAPE_FILTER', 0x01); define('LDAP_ESCAPE_DN', 0x02); /** * @param string $subject The subject string * @param string $ignore Set of characters to leave untouched * @param int $flags Any combination of LDAP_ESCAPE_* flags to indicate the * set(s) of characters to escape. * @return string */ function ldap_escape($subject, $ignore = '', $flags = 0) { static $charMaps = array( LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"), LDAP_ESCAPE_DN => array('\\', ',', '=', '+', '<', '>', ';', '"', '#'), ); // Pre-process the char maps on first call if (!isset($charMaps[0])) { $charMaps[0] = array(); for ($i = 0; $i < 256; $i++) { $charMaps[0][chr($i)] = sprintf('\\%02x', $i);; } for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_FILTER]); $i < $l; $i++) { $chr = $charMaps[LDAP_ESCAPE_FILTER][$i]; unset($charMaps[LDAP_ESCAPE_FILTER][$i]); $charMaps[LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr]; } for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_DN]); $i < $l; $i++) { $chr = $charMaps[LDAP_ESCAPE_DN][$i]; unset($charMaps[LDAP_ESCAPE_DN][$i]); $charMaps[LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr]; } } // Create the base char map to escape $flags = (int)$flags; $charMap = array(); if ($flags & LDAP_ESCAPE_FILTER) { $charMap += $charMaps[LDAP_ESCAPE_FILTER]; } if ($flags & LDAP_ESCAPE_DN) { $charMap += $charMaps[LDAP_ESCAPE_DN]; } if (!$charMap) { $charMap = $charMaps[0]; } // Remove any chars to ignore from the list $ignore = (string)$ignore; for ($i = 0, $l = strlen($ignore); $i < $l; $i++) { unset($charMap[$ignore[$i]]); } // Do the main replacement $result = strtr($subject, $charMap); // Encode leading/trailing spaces if LDAP_ESCAPE_DN is passed if ($flags & LDAP_ESCAPE_DN) { if ($result[0] === ' ') { $result = '\\20' . substr($result, 1); } if ($result[strlen($result) - 1] === ' ') { $result = substr($result, 0, -1) . '\\20'; } } return $result; } }
Таким образом, вы бы сделали:
$user = 'Test , Name S.L'; $cn = ldap_escape($user, '', LDAP_ESCAPE_DN); if (!ldap_add($ds, "cn={$cn}," . LDAP_DN_BASE, $info)) { include 'error_new_account.php'; }
PHP 5.6 Beta ldap_escape()
выпустила ldap_escape()
и она действует. Однако эта версия в настоящее время не готова к производству, вы можете использовать ее для своих целей развития на данный момент.
Эти символы должны скрываться, чтобы быть частью данных различающегося имени или относительного отличительного имени. Выйдите из символа (как и во всех LDAP) с шестнадцатеричной цифрой обратной косой черты, например \2a
. Все остальное не соответствовало бы документам стандартов. См. RFC4514 для получения более подробной информации о строчном представлении отличительных имен.
Просто ldap_escape()
если вы еще не на PHP 5.6, вы можете зеркально ldap_escape()
точную функцию PHP 5.6 ldap_escape()
используя методы, созданные мной ниже, помните, что это предназначено для использования в классе. Вышеупомянутый ответ не выполняет точно так же, как функция ldap_escape
, так как в нем не ldap_escape
все символы в шестнадцатеричную строку, если флаги не указаны, поэтому это было бы более подходящим для замены более ранних версий PHP, объектно-ориентированным способом.
Я документировал каждую строку для более легкого понимания того, что происходит. Прокрутите вниз для вывода.
Методы (совместимые с PHP 5 или выше):
/** * Escapes the inserted value for LDAP. * * @param string $value The value to escape * @param string $ignore The characters to ignore * @param int $flags The PHP flag to use * * @return bool|string */ public function escapeManual($value, $ignore = '*', $flags = 0) { /* * If a flag was supplied, we'll send the value * off to be escaped using the PHP flag values * and return the result. */ if($flags) { return $this->escapeWithFlags($value, $ignore, $flags); } // Convert ignore string into an array $ignores = str_split($ignore); // Convert the value to a hex string $hex = bin2hex($value); /* * Separate the string, with the hex length of 2, * and place a backslash on the end of each section */ $value = chunk_split($hex, 2, "\\"); /* * We'll append a backslash at the front of the string * and remove the ending backslash of the string */ $value = "\\" . substr($value, 0, -1); // Go through each character to ignore foreach($ignores as $charToIgnore) { // Convert the characterToIgnore to a hex $hexed = bin2hex($charToIgnore); // Replace the hexed variant with the original character $value = str_replace("\\" . $hexed, $charToIgnore, $value); } // Finally we can return the escaped value return $value; } /** * Escapes the inserted value with flags. Supplying either 1 * or 2 into the flags parameter will escape only certain values * * * @param string $value The value to escape * @param string $ignore The characters to ignore * @param int $flags The PHP flag to use * @return bool|string */ public function escapeWithFlags($value, $ignore = '*', $flags = 0) { // Convert ignore string into an array $ignores = str_split($ignore); $escapeFilter = ['\\', '*', '(', ')']; $escapeDn = ['\\', ',', '=', '+', '<', '>', ';', '"', '#']; switch($flags) { case 1: // Int 1 equals to LDAP_ESCAPE_FILTER $escapes = $escapeFilter; break; case 2: // Int 2 equals to LDAP_ESCAPE_DN $escapes = $escapeDn; break; case 3: // If both LDAP_ESCAPE_FILTER and LDAP_ESCAPE_DN are used $escapes = array_merge($escapeFilter, $escapeDn); break; default: // Customize your own default return value return false; } foreach($escapes as $escape) { // Make sure the escaped value isn't inside the ignore array if( ! in_array($escape, $ignores)) { $hexed = chunk_split(bin2hex($escape), 2, "\\"); $hexed = "\\" . substr($hexed, 0, -1); $value = str_replace($escape, $hexed, $value); } } return $value; }
Тесты (помните, что константы LDAP_ESCAPE доступны только в PHP 5.6):
// Value to escape $value = 'testing=+<>"";:#()*\x00'; $php = ldap_escape($value, $ignore = '*'); $man = $this->escapeManual($value, $ignore = '*'); echo $php; // \74\65\73\74\69\6e\67\3d\2b\3c\3e\22\22\3b\3a\23\28\29*\5c\78\30\30 echo $man; // \74\65\73\74\69\6e\67\3d\2b\3c\3e\22\22\3b\3a\23\28\29*\5c\78\30\30 $php = ldap_escape($value, $ignore = '*', LDAP_ESCAPE_DN); $man = $this->escapeManual($value, $ignore = '*', LDAP_ESCAPE_DN); echo $php; // testing\3d\2b\3c\3e\22\22\3b:\23()*\5cx00 echo $man; // testing\3d\2b\3c\3e\22\22\3b:\23()*\5cx00 $php = ldap_escape($value, $ignore = '*', LDAP_ESCAPE_FILTER); $man = $this->escapeManual($value, $ignore = '*', LDAP_ESCAPE_FILTER); echo $php; // testing=+<>"";:#\28\29*\5cx00 echo $man; // testing=+<>"";:#\28\29*\5cx00
Github Gist: https://gist.github.com/stevebauman/0db9b5daa414d60fc266