diff -r 5b37998e522e -r 162c1de6545a web/lib/Zend/Ldap/Ldif/Encoder.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/lib/Zend/Ldap/Ldif/Encoder.php Fri Mar 11 15:05:35 2011 +0100 @@ -0,0 +1,304 @@ + true, + 'version' => 1, + 'wrap' => 78 + ); + + /** + * @var boolean + */ + protected $_versionWritten = false; + + /** + * Constructor. + * + * @param array $options Additional options used during encoding + * @return void + */ + protected function __construct(array $options = array()) + { + $this->_options = array_merge($this->_options, $options); + } + + /** + * Decodes the string $string into an array of LDIF items + * + * @param string $string + * @return array + */ + public static function decode($string) + { + $encoder = new self(array()); + return $encoder->_decode($string); + } + + /** + * Decodes the string $string into an array of LDIF items + * + * @param string $string + * @return array + */ + protected function _decode($string) + { + $items = array(); + $item = array(); + $last = null; + foreach (explode("\n", $string) as $line) { + $line = rtrim($line, "\x09\x0A\x0D\x00\x0B"); + $matches = array(); + if (substr($line, 0, 1) === ' ' && $last !== null) { + $last[2] .= substr($line, 1); + } else if (substr($line, 0, 1) === '#') { + continue; + } else if (preg_match('/^([a-z0-9;-]+)(:[:<]?\s*)([^:<]*)$/i', $line, $matches)) { + $name = strtolower($matches[1]); + $type = trim($matches[2]); + $value = $matches[3]; + if ($last !== null) { + $this->_pushAttribute($last, $item); + } + if ($name === 'version') { + continue; + } else if (count($item) > 0 && $name === 'dn') { + $items[] = $item; + $item = array(); + $last = null; + } + $last = array($name, $type, $value); + } else if (trim($line) === '') { + continue; + } + } + if ($last !== null) { + $this->_pushAttribute($last, $item); + } + $items[] = $item; + return (count($items)>1) ? $items : $items[0]; + } + + /** + * Pushes a decoded attribute to the stack + * + * @param array $attribute + * @param array $entry + */ + protected function _pushAttribute(array $attribute, array &$entry) + { + $name = $attribute[0]; + $type = $attribute[1]; + $value = $attribute[2]; + if ($type === '::') { + $value = base64_decode($value); + } + if ($name === 'dn') { + $entry[$name] = $value; + } else if (isset($entry[$name]) && $value !== '') { + $entry[$name][] = $value; + } else { + $entry[$name] = ($value !== '') ? array($value) : array(); + } + } + + /** + * Encode $value into a LDIF representation + * + * @param mixed $value The value to be encoded + * @param array $options Additional options used during encoding + * @return string The encoded value + */ + public static function encode($value, array $options = array()) + { + $encoder = new self($options); + return $encoder->_encode($value); + } + + /** + * Recursive driver which determines the type of value to be encoded + * and then dispatches to the appropriate method. + * + * @param mixed $value The value to be encoded + * @return string Encoded value + */ + protected function _encode($value) + { + if (is_scalar($value)) { + return $this->_encodeString($value); + } else if (is_array($value)) { + return $this->_encodeAttributes($value); + } else if ($value instanceof Zend_Ldap_Node) { + return $value->toLdif($this->_options); + } + return null; + } + + /** + * Encodes $string according to RFC2849 + * + * @link http://www.faqs.org/rfcs/rfc2849.html + * + * @param string $string + * @param boolen $base64 + * @return string + */ + protected function _encodeString($string, &$base64 = null) + { + $string = (string)$string; + if (!is_numeric($string) && empty($string)) { + return ''; + } + + /* + * SAFE-INIT-CHAR = %x01-09 / %x0B-0C / %x0E-1F / + * %x21-39 / %x3B / %x3D-7F + * ; any value <= 127 except NUL, LF, CR, + * ; SPACE, colon (":", ASCII 58 decimal) + * ; and less-than ("<" , ASCII 60 decimal) + * + */ + $unsafe_init_char = array(0, 10, 13, 32, 58, 60); + /* + * SAFE-CHAR = %x01-09 / %x0B-0C / %x0E-7F + * ; any value <= 127 decimal except NUL, LF, + * ; and CR + */ + $unsafe_char = array(0, 10, 13); + + $base64 = false; + for ($i = 0; $i < strlen($string); $i++) { + $char = ord(substr($string, $i, 1)); + if ($char >= 127) { + $base64 = true; + break; + } else if ($i === 0 && in_array($char, $unsafe_init_char)) { + $base64 = true; + break; + } else if (in_array($char, $unsafe_char)) { + $base64 = true; + break; + } + } + // Test for ending space + if (substr($string, -1) == ' ') { + $base64 = true; + } + + if ($base64 === true) { + $string = base64_encode($string); + } + + return $string; + } + + /** + * Encodes an attribute with $name and $value according to RFC2849 + * + * @link http://www.faqs.org/rfcs/rfc2849.html + * + * @param string $name + * @param array|string $value + * @return string + */ + protected function _encodeAttribute($name, $value) + { + if (!is_array($value)) { + $value = array($value); + } + + $output = ''; + + if (count($value) < 1) { + return $name . ': '; + } + + foreach ($value as $v) { + $base64 = null; + $v = $this->_encodeString($v, $base64); + $attribute = $name . ':'; + if ($base64 === true) { + $attribute .= ': ' . $v; + } else { + $attribute .= ' ' . $v; + } + if (isset($this->_options['wrap']) && strlen($attribute) > $this->_options['wrap']) { + $attribute = trim(chunk_split($attribute, $this->_options['wrap'], PHP_EOL . ' ')); + } + $output .= $attribute . PHP_EOL; + } + return trim($output, PHP_EOL); + } + + /** + * Encodes a collection of attributes according to RFC2849 + * + * @link http://www.faqs.org/rfcs/rfc2849.html + * + * @param array $attributes + * @return string + */ + protected function _encodeAttributes(array $attributes) + { + $string = ''; + $attributes = array_change_key_case($attributes, CASE_LOWER); + if (!$this->_versionWritten && array_key_exists('dn', $attributes) && isset($this->_options['version']) + && array_key_exists('objectclass', $attributes)) { + $string .= sprintf('version: %d', $this->_options['version']) . PHP_EOL; + $this->_versionWritten = true; + } + + if (isset($this->_options['sort']) && $this->_options['sort'] === true) { + ksort($attributes, SORT_STRING); + if (array_key_exists('objectclass', $attributes)) { + $oc = $attributes['objectclass']; + unset($attributes['objectclass']); + $attributes = array_merge(array('objectclass' => $oc), $attributes); + } + if (array_key_exists('dn', $attributes)) { + $dn = $attributes['dn']; + unset($attributes['dn']); + $attributes = array_merge(array('dn' => $dn), $attributes); + } + } + foreach ($attributes as $key => $value) { + $string .= $this->_encodeAttribute($key, $value) . PHP_EOL; + } + return trim($string, PHP_EOL); + } +} \ No newline at end of file