1: <?php
  2:   3:   4:   5:   6:   7:   8:   9:  10:  11: 
 12: class Ingo_Transport_Ldap extends Ingo_Transport
 13: {
 14:      15:  16:  17:  18: 
 19:     public function __construct($params = array())
 20:     {
 21:         if (!Horde_Util::extensionExists('ldap')) {
 22:             throw new Ingo_Exception(_("LDAP support is required but the LDAP module is not available or not loaded."));
 23:         }
 24: 
 25:         $default_params = array(
 26:             'hostspec' => 'localhost',
 27:             'port' => 389,
 28:             'script_attribute' => 'mailSieveRuleSource'
 29:         );
 30: 
 31:         parent::__construct(array_merge($default_params, $params));
 32:     }
 33: 
 34:      35:  36:  37:  38:  39:  40:  41:  42: 
 43:     protected function _substUser($templ)
 44:     {
 45:         $domain = '';
 46:         $username = $this->_params['username'];
 47: 
 48:         if (strpos($username, '@') !== false) {
 49:             list($username, $domain) = explode('@', $username);
 50:         }
 51:         $domain = implode(', dc=', explode('.', $domain));
 52:         if (!empty($domain)) {
 53:             $domain = 'dc=' . $domain;
 54:         }
 55: 
 56:         if (preg_match('/^\s|\s$|\s\s|[,+="\r\n<>#;]/', $username)) {
 57:             $username = '"' . str_replace('"', '\\"', $username) . '"';
 58:         }
 59: 
 60:         return str_replace(array('%u', '%d'),
 61:                            array($username, $domain),
 62:                            $templ);
 63:     }
 64: 
 65:      66:  67:  68:  69: 
 70:     protected function _connect()
 71:     {
 72:         if (!($ldapcn = @ldap_connect($this->_params['hostspec'],
 73:                                       $this->_params['port']))) {
 74:             throw new Ingo_Exception(_("Connection failure"));
 75:         }
 76: 
 77:         
 78:         if (!empty($this->_params['version'])) {
 79:             @ldap_set_option($ldapcn,
 80:                              LDAP_OPT_PROTOCOL_VERSION,
 81:                              $this->_params['version']);
 82:         }
 83: 
 84:         
 85:         if (!empty($this->_params['tls']) &&
 86:             !@ldap_start_tls($ldapcn)) {
 87:             throw new Ingo_Exception(sprintf(_("STARTTLS failed: (%s) %s"),
 88:                                      ldap_errno($ldapcn),
 89:                                      ldap_error($ldapcn)));
 90:         }
 91: 
 92:         
 93:         if (isset($this->_params['bind_dn'])) {
 94:             $bind_dn = $this->_substUser($this->_params['bind_dn']);
 95: 
 96:             $password = isset($this->_params['bind_password'])
 97:                 ? $this->_params['bind_password']
 98:                 : $this->_params['password'];
 99: 
100:             $bind_success = @ldap_bind($ldapcn, $bind_dn, $password);
101:         } else {
102:             $bind_success = @ldap_bind($ldapcn);
103:         }
104: 
105:         if ($bind_success) {
106:             return $ldapcn;
107:         }
108: 
109: 
110:         throw new Ingo_Exception(sprintf(_("Bind failed: (%s) %s"),
111:                                  ldap_errno($ldapcn),
112:                                  ldap_error($ldapcn)));
113:     }
114: 
115:     116: 117: 118: 119: 120: 121: 122: 123: 
124:     protected function _getScripts($ldapcn, &$userDN)
125:     {
126:         $attrs = array($this->_params['script_attribute'], 'dn');
127:         $filter = $this->_substUser($this->_params['script_filter']);
128: 
129:         
130:         $sr = @ldap_search($ldapcn, $this->_params['script_base'], $filter,
131:                            $attrs);
132:         if ($sr === false) {
133:             throw new Ingo_Exception(sprintf(_("Error retrieving current script: (%d) %s"),
134:                                      ldap_errno($ldapcn),
135:                                      ldap_error($ldapcn)));
136:         }
137: 
138:         if (@ldap_count_entries($ldapcn, $sr) != 1) {
139:             throw new Ingo_Exception(sprintf(_("Expected 1 object, got %d."),
140:                                      ldap_count_entries($ldapcn, $sr)));
141:         }
142: 
143:         $ent = @ldap_first_entry($ldapcn, $sr);
144:         if ($ent === false) {
145:             throw new Ingo_Exception(sprintf(_("Error retrieving current script: (%d) %s"),
146:                                      ldap_errno($ldapcn),
147:                                      ldap_error($ldapcn)));
148:         }
149: 
150:         
151:         $v = @ldap_get_dn($ldapcn, $ent);
152:         if ($v === false) {
153:             @ldap_free_result($sr);
154:             throw new Ingo_Exception(sprintf(_("Error retrieving current script: (%d) %s"),
155:                                      ldap_errno($ldapcn),
156:                                      ldap_error($ldapcn)));
157:         }
158:         $userDN = $v;
159: 
160:         
161:         $attrs = @ldap_get_attributes($ldapcn, $ent);
162:         @ldap_free_result($sr);
163:         if ($attrs === false) {
164:             throw new Ingo_Exception(sprintf(_("Error retrieving current script: (%d) %s"),
165:                                      ldap_errno($ldapcn),
166:                                      ldap_error($ldapcn)));
167:         }
168: 
169:         170: 
171:         $regexp = '/^' . preg_quote($this->_params['script_attribute'], '/') .
172:                   '(?:;.*)?$/i';
173:         unset($attrs['count']);
174:         foreach ($attrs as $name => $values) {
175:             if (preg_match($regexp, $name)) {
176:                 unset($values['count']);
177:                 return array_values($values);
178:             }
179:         }
180: 
181:         return array();
182:     }
183: 
184:     185: 186: 187: 188: 189: 190: 191: 192: 193: 
194:     protected function setScriptActive($script, $additional = array())
195:     {
196:         $ldapcn = $this->_connect();
197:         $values = $this->_getScripts($ldapcn, $userDN);
198: 
199:         $found = false;
200:         foreach ($values as $i => $value) {
201:             if (strpos($value, "# Sieve Filter\n") !== false) {
202:                 if (empty($script)) {
203:                     unset($values[$i]);
204:                 } else {
205:                     $values[$i] = $script;
206:                 }
207:                 $found = true;
208:                 break;
209:             }
210:         }
211: 
212:         if (!$found && !empty($script)) {
213:             $values[] = $script;
214:         }
215: 
216:         $replace = array(Horde_String::lower($this->_params['script_attribute']) => $values);
217:         $r = empty($values)
218:             ? @ldap_mod_del($ldapcn, $userDN, $replace)
219:             : @ldap_mod_replace($ldapcn, $userDN, $replace);
220: 
221:         if (!$r) {
222:             throw new Ingo_Exception(sprintf(_("Activating the script for \"%s\" failed: (%d) %s"),
223:                                      $userDN,
224:                                      ldap_errno($ldapcn),
225:                                      ldap_error($ldapcn)));
226:         }
227: 
228:         @ldap_close($ldapcn);
229:     }
230: 
231:     232: 233: 234: 235: 236: 237: 
238:     public function getScript()
239:     {
240:         $ldapcn = $this->_connect();
241:         $values = $this->_getScripts($ldapcn, $userDN);
242: 
243:         $script = '';
244:         foreach ($values as $value) {
245:             if (strpos($value, "# Sieve Filter\n") !== false) {
246:                 $script = $value;
247:                 break;
248:             }
249:         }
250: 
251:         @ldap_close($ldapcn);
252:         return $script;
253:     }
254: 
255: }
256: