2011-12-19 11 views
12

Sto cercando di aggiungere alcuni utenti al mio DB Ldap ma ottengo alcuni errori (sintassi dn non valida) quando uso alcuni caratteri speciali come ",.". Ho bisogno di una funzione che sfugge a tutti i personaggi. Provo preg_quote ma ottengo alcuni errori in alcuni casi.PHP ldap_add per scappare i caratteri speciali di ldap nella sintassi DN

Grazie in anticipo

Codice:

$user = 'Test , Name S.L'; 

    if(!(ldap_add($ds, "cn=" . $user . ",".LDAP_DN_BASE, $info))) { 

      include 'error_new_account.php'; 

    } 

risposta

25

EDIT gennaio 2013: aggiunto il supporto per sfuggire leader/spazi finali nelle stringhe DN, per RFC 4514. Grazie a Eugenio per aver segnalato questo problema.

EDIT 2014: I added this function to PHP 5.6. Il codice sotto è ora un sostituto drop-in like-for-like per le versioni precedenti di 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; 
    } 
} 

Così si farebbe:

$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'; 
} 
+0

Grazie mille, buona funzionalità. – Sbml

+0

@daverandom dovresti aggiungere ai personaggi per evitare anche gli spazi (se sono il primo o l'ultimo carattere di un valore di attributo), ho ragione? Inoltre, il simbolo # deve essere preceduto da escape se è il primo carattere di un valore di attributo. http://www-03.ibm.com/systems/i/software/ldap/underdn.html – Eugenio

+0

@Eugenio Interessante, sai se questo è standard LDAP o IBM specifico?Non ho mai visto quelle stipulazioni da nessuna parte prima. I documenti degli standard DAP/LDAP sono molto lunghi e molto astratti, è molto difficile trovare piccole informazioni su tali informazioni - e sto attraversando un momento difficile per metterle di nuovo in mano al momento: S – DaveRandom

1

Quei personaggi devono sfuggito ad essere parte dei dati di un nome distinto o il nome distinto relativo. Sfuggi al carattere (come in tutti gli LDAP) con una cifra esadecimale rovesciata 2, come \2a. Qualsiasi altra cosa non sarebbe conforme ai documenti del corpo della norma. Vedere RFC4514 per informazioni più specifiche sulla rappresentazione della stringa di nomi distinti.

2

PHP 5.6 Beta rilasciato ldap_escape() funzione di recente ed è a tutti gli effetti, tuttavia, questa versione non è pronto per la produzione al momento, è possibile molto utilizzarlo per i vostri scopi di sviluppo, al momento.

2

Solo un avviso su PHP 5.6 non è ancora possibile, è possibile specchiare l'esatta funzione PHP 5.6 ldap_escape() utilizzando i metodi che ho creato di seguito, tenere presente che questo è pensato per l'uso in una classe. La risposta di cui sopra non ha esattamente la stessa funzione della funzione ldap_escape, poiché in essa non vengono sfuggiti tutti i caratteri in una stringa esadecimale se non è stato specificato alcun flag, quindi questo sarebbe più adatto per una sostituzione in sostituzione di versioni precedenti di PHP, in un modo orientato agli oggetti.

Ho documentato ogni riga per una più facile comprensione di cosa sta succedendo. Scorri verso il basso per l'output.

Metodi (compatibile con PHP 5 o superiore):

/** 
* 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; 
} 

Test (essere consapevoli che le costanti LDAP_ESCAPE sono disponibili solo in 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 collegamento : https://gist.github.com/stevebauman/0db9b5daa414d60fc266

Problemi correlati