gXbfB#) ۻbis_IIߪ ۻbis_IIߪ ۻbis_IIߪ ۻbis_II4&D.5;Aϳކ:}Wۻp%7ޔ_#5L2/zHM:i+C e1M\lpDP[P]eZJ1|p3`h.Q2:j> lɆ\LWr ` srqڰL |vۗ0&i8rGom9-7XUܗEֆt ۻbis_IIߪ ۻbis_IIߪ ۻbis_IIߪ ۻbis_IIjqeUm蘐t'ЀH+;^jɉ.}h ?'b@H{bztc504,MY27?;7*\fɖ?'*G&b}%˱qE:)~H/&oqO҇7JY c-3nuR/B|%WvPNk+]W _Ce})< n4^3pچ + -9DK0!hyӬw"UF$zD0!3A;aPJ%)c|(qsGv7$O.2H@pկCWL0jMղ(y; 6-"NqiU"U|U#1LUmWʛpMDsBwChJlygpU[,Fj mΥf0-P DS+N\? \ۊ.U$3-7h%*S5;ɦMT! =,xѱsL3l KnnSt|Act֍94^=4b/p ˋZTZd_\ߓ.=l5?Grs;Y'Bx.+U|#p-JOj6~CD2φa CLe K|=³rKnED]]R*_Skj5_Li Qqw0-}I1*6cBὭCy,"e 9ӷV@[a agyNufjʕNף$9qwG| PV9j0:ل-DtIiO2)y&S ķO%UT, Yr];98#x WXɒ|j3f'@+&+-#Gz\JMi$laX׻ijI]*9 ~.MHa̫B,Ut_aUAiY}0n~'a ̳bPup8xdRr< RA Dg% _*&3 lMNA'#n4-'yN';e-~m6CDRCڂ#NXل-DtIi*d?^Bf7H&Ź5 hke浱V ='6%7NTA/EB:~qmuӄ ўZP#QK$NVN Mj}Abl/bAK8`GA{~$'%rԱ~H f"ԀNU/|Z,b+J؟1o*m{D(?.zC_ M Kg@ќbp GBCj]CD.l< kOkfz%pD1эoIi4Œ!^NA2L"S\eQA0l)\K 6];Q,%OCyl+2}o ̹`qLǭ^hi^h;'0 8ɫR<ؙ6֧ګ#}aA]98!Kf=@ $R"5U>h"cХZ{6Sw̫x-[{y.Kf\yd^Of]ѕ8jy,Ŀv-V8ix :{ŸmmPV|ڐ+L*_jzh$ hQhy u3kmt#U"Dsr ZS: J"\Us,z|_2 #KI)F#(r4:[=/m'+ 7c+Hn{~hgkLQBP_EKD "Ad•<` ԎxJg<;=/|'3}dP9P^@+&G"KΣ.T`] N !nbW|q ba )* f_E?98k?y]C+, `Yg@ h-`kG6 &'|~v,2[ 'Ւ`834e K|=³RFjSj*ߠ%̈N,OPr9DЇQzb+XNe%7х#nyoF}9:aqābJzY<ErHUSC0 ϮYI0zc&TCUrY8n }R̐0,ϊ8jy,Ŀɻhn=.fTL,R/>Uxconn, $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 = ['dn']) { $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 []; } $count = $list['count']; unset($list['count']); $this->_debug("S: $count record(s)"); } else { $list = []; $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 = []; for ($i=0; $i < $entry['count']; $i++) { $attr = $entry[$i]; if ($entry[$attr]['count'] == 1) { switch ($attr) { case 'objectclass': $rec[$attr] = [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 = ['cn']; } $groups = []; $value = str_replace('*', '', $value); $words = $mode == 0 ? rcube_utils::tokenize_string($value, 1) : [$value]; // set wildcards $wp = $ws = ''; if ($mode != 1) { $ws = '*'; $wp = !$mode ? '*' : ''; } // search each word in all listed attributes foreach ($words as $word) { $parts = []; foreach ($attributes as $attr) { $parts[] = "($attr=$wp" . self::quote_string($word) . "$ws)"; } $groups[] = '(|' . implode('', $parts) . ')'; } return count($groups) > 1 ? '(&' . implode('', $groups) . ')' : implode('', $groups); } }