Функция PHP ldap_add для вывода специальных символов ldap в синтаксисе DN
Я пытаюсь добавить некоторых пользователей в свой 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';
}
Ответы
Ответ 1
EDIT Январь 2013: добавлена поддержка экранирования ведущих/конечных пробелов в строках DN, за RFC 4514. Благодаря Eugenio для указания этой проблемы.
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;
}
}
Итак, вы бы сделали:
$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';
}
Ответ 2
PHP 5.6 Betastrong > выпустила ldap_escape()
в последнее время и действует, однако эта версия не производство готово в настоящее время, вы можете использовать его для своих целей развития на данный момент.
Ответ 3
Просто, если вы еще не на PHP 5.6, вы можете зеркально отобразить точную функцию PHP 5.6 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
Ответ 4
Эти символы должны быть экранированы, чтобы быть частью данных различающегося имени или относительного различающегося имени. Избегайте символа (как и во всех LDAP) с шестнадцатеричной цифрой обратной косой черты, например \2a
. Все остальное не соответствовало бы документам стандартов. См. RFC4514 для получения более подробной информации о строчном представлении отличительных имен.