123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- <?php
-
- /**
- +-----------------------------------------------------------------------+
- | Roundcube/rcube_ldap_generic.php |
- | |
- | This file is part of the Roundcube Webmail client |
- | Copyright (C) 2006-2014, The Roundcube Dev Team |
- | Copyright (C) 2012-2015, Kolab Systems AG |
- | |
- | Licensed under the GNU General Public License version 3 or |
- | any later version with exceptions for skins & plugins. |
- | See the README file for a full license statement. |
- | |
- | PURPOSE: |
- | Provide basic functionality for accessing LDAP directories |
- | |
- +-----------------------------------------------------------------------+
- | Author: Thomas Bruederli <roundcube@gmail.com> |
- | Aleksander Machniak <machniak@kolabsys.com> |
- +-----------------------------------------------------------------------+
- */
-
- /**
- * Model class to access an LDAP directories
- *
- * @package Framework
- * @subpackage LDAP
- */
- class rcube_ldap_generic extends Net_LDAP3
- {
- /** private properties */
- protected $cache = null;
- protected $attributes = array('dn');
- protected $error;
-
- function __construct($config = null)
- {
- parent::__construct($config);
-
- $this->config_set('log_hook', array($this, 'log'));
- }
-
- /**
- * Establish a connection to the LDAP server
- */
- public function connect($host = null)
- {
- // Net_LDAP3 does not support IDNA yet
- // also parse_host() here is very Roundcube specific
- $host = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host));
-
- return parent::connect($host);
- }
-
- /**
- * Get a specific LDAP entry, identified by its DN
- *
- * @param string $dn Record identifier
- * @param array $attributes Attributes to return
- *
- * @return array Hash array
- */
- function get_entry($dn, $attributes = array())
- {
- return parent::get_entry($dn, !empty($attributes) ? $attributes : $this->attributes);
- }
-
- /**
- * Prints debug/error info to the log
- */
- public function log($level, $msg)
- {
- $msg = implode("\n", $msg);
-
- switch ($level) {
- case LOG_DEBUG:
- case LOG_INFO:
- case LOG_NOTICE:
- if ($this->config['debug']) {
- rcube::write_log('ldap', $msg);
- }
- break;
-
- case LOG_EMERGE:
- case LOG_ALERT:
- case LOG_CRIT:
- rcube::raise_error($msg, true, true);
- break;
-
- case LOG_ERR:
- case LOG_WARNING:
- $this->error = $msg;
- rcube::raise_error($msg, true, false);
- break;
- }
- }
-
- /**
- * Returns the last LDAP error occurred
- *
- * @return mixed Error message string or null if no error occured
- */
- function get_error()
- {
- return $this->error;
- }
-
- /**
- * @deprecated
- */
- public function set_debug($dbg = true)
- {
- $this->config['debug'] = (bool) $dbg;
- }
-
- /**
- * @deprecated
- */
- public function set_cache($cache_engine)
- {
- $this->config['cache'] = $cache_engine;
- }
-
- /**
- * @deprecated
- */
- public static function scope2func($scope, &$ns_function = null)
- {
- return self::scope_to_function($scope, $ns_function);
- }
-
- /**
- * @deprecated
- */
- public function set_config($opt, $val = null)
- {
- $this->config_set($opt, $val);
- }
-
- /**
- * @deprecated
- */
- public function add($dn, $entry)
- {
- return $this->add_entry($dn, $entry);
- }
-
- /**
- * @deprecated
- */
- public function delete($dn)
- {
- return $this->delete_entry($dn);
- }
-
- /**
- * Wrapper for ldap_mod_replace()
- *
- * @see ldap_mod_replace()
- */
- public function mod_replace($dn, $entry)
- {
- $this->_debug("C: Replace $dn: ".print_r($entry, true));
-
- if (!ldap_mod_replace($this->conn, $dn, $entry)) {
- $this->_error("ldap_mod_replace() failed with " . ldap_error($this->conn));
- return false;
- }
-
- $this->_debug("S: OK");
- return true;
- }
-
- /**
- * Wrapper for ldap_mod_add()
- *
- * @see ldap_mod_add()
- */
- public function mod_add($dn, $entry)
- {
- $this->_debug("C: Add $dn: ".print_r($entry, true));
-
- if (!ldap_mod_add($this->conn, $dn, $entry)) {
- $this->_error("ldap_mod_add() failed with " . ldap_error($this->conn));
- return false;
- }
-
- $this->_debug("S: OK");
- return true;
- }
-
- /**
- * Wrapper for ldap_mod_del()
- *
- * @see ldap_mod_del()
- */
- public function mod_del($dn, $entry)
- {
- $this->_debug("C: Delete $dn: ".print_r($entry, true));
-
- if (!ldap_mod_del($this->conn, $dn, $entry)) {
- $this->_error("ldap_mod_del() failed with " . ldap_error($this->conn));
- return false;
- }
-
- $this->_debug("S: OK");
- return true;
- }
-
- /**
- * Wrapper for ldap_rename()
- *
- * @see ldap_rename()
- */
- public function rename($dn, $newrdn, $newparent = null, $deleteoldrdn = true)
- {
- $this->_debug("C: Rename $dn to $newrdn");
-
- if (!ldap_rename($this->conn, $dn, $newrdn, $newparent, $deleteoldrdn)) {
- $this->_error("ldap_rename() failed with " . ldap_error($this->conn));
- return false;
- }
-
- $this->_debug("S: OK");
- return true;
- }
-
- /**
- * Wrapper for ldap_list() + ldap_get_entries()
- *
- * @see ldap_list()
- * @see ldap_get_entries()
- */
- public function list_entries($dn, $filter, $attributes = array('dn'))
- {
- $list = array();
- $this->_debug("C: List $dn [{$filter}]");
-
- if ($result = ldap_list($this->conn, $dn, $filter, $attributes)) {
- $list = ldap_get_entries($this->conn, $result);
-
- if ($list === false) {
- $this->_error("ldap_get_entries() failed with " . ldap_error($this->conn));
- return array();
- }
-
- $count = $list['count'];
- unset($list['count']);
-
- $this->_debug("S: $count record(s)");
- }
- else {
- $this->_error("ldap_list() failed with " . ldap_error($this->conn));
- }
-
- return $list;
- }
-
- /**
- * Wrapper for ldap_read() + ldap_get_entries()
- *
- * @see ldap_read()
- * @see ldap_get_entries()
- */
- public function read_entries($dn, $filter, $attributes = null)
- {
- $this->_debug("C: Read $dn [{$filter}]");
-
- if ($this->conn && $dn) {
- $result = @ldap_read($this->conn, $dn, $filter, $attributes, 0, (int)$this->config['sizelimit'], (int)$this->config['timelimit']);
- if ($result === false) {
- $this->_error("ldap_read() failed with " . ldap_error($this->conn));
- return false;
- }
-
- $this->_debug("S: OK");
- return ldap_get_entries($this->conn, $result);
- }
-
- return false;
- }
-
- /**
- * Turn an LDAP entry into a regular PHP array with attributes as keys.
- *
- * @param array $entry Attributes array as retrieved from ldap_get_attributes() or ldap_get_entries()
- * @param bool $flat Convert one-element-array values into strings (not implemented)
- *
- * @return array Hash array with attributes as keys
- */
- public static function normalize_entry($entry, $flat = false)
- {
- if (!isset($entry['count'])) {
- return $entry;
- }
-
- $rec = array();
-
- for ($i=0; $i < $entry['count']; $i++) {
- $attr = $entry[$i];
- if ($entry[$attr]['count'] == 1) {
- switch ($attr) {
- case 'objectclass':
- $rec[$attr] = array(strtolower($entry[$attr][0]));
- break;
- default:
- $rec[$attr] = $entry[$attr][0];
- break;
- }
- }
- else {
- for ($j=0; $j < $entry[$attr]['count']; $j++) {
- $rec[$attr][$j] = $entry[$attr][$j];
- }
- }
- }
-
- return $rec;
- }
-
- /**
- * Compose an LDAP filter string matching all words from the search string
- * in the given list of attributes.
- *
- * @param string $value Search value
- * @param mixed $attrs List of LDAP attributes to search
- * @param int $mode Matching mode:
- * 0 - partial (*abc*),
- * 1 - strict (=),
- * 2 - prefix (abc*)
- * @return string LDAP filter
- */
- public static function fulltext_search_filter($value, $attributes, $mode = 1)
- {
- if (empty($attributes)) {
- $attributes = array('cn');
- }
-
- $groups = array();
- $value = str_replace('*', '', $value);
- $words = $mode == 0 ? rcube_utils::tokenize_string($value, 1) : array($value);
-
- // set wildcards
- $wp = $ws = '';
- if ($mode != 1) {
- $ws = '*';
- $wp = !$mode ? '*' : '';
- }
-
- // search each word in all listed attributes
- foreach ($words as $word) {
- $parts = array();
- foreach ($attributes as $attr) {
- $parts[] = "($attr=$wp" . self::quote_string($word) . "$ws)";
- }
- $groups[] = '(|' . join('', $parts) . ')';
- }
-
- return count($groups) > 1 ? '(&' . join('', $groups) . ')' : join('', $groups);
- }
- }
-
- // for backward compat.
- class rcube_ldap_result extends Net_LDAP3_Result {}
|