Overview

Packages

  • Horde
    • Icalendar
      • UnitTests
  • Ingo
    • UnitTests
  • None

Classes

  • Horde_Core_Ui_VarRenderer_Ingo
  • Ingo
  • Ingo_Api
  • Ingo_Exception
  • Ingo_Exception_Pear
  • Ingo_LoginTasks_SystemTask_Upgrade
  • Ingo_Script
  • Ingo_Script_Imap
  • Ingo_Script_Imap_Api
  • Ingo_Script_Imap_Live
  • Ingo_Script_Maildrop
  • Ingo_Script_Maildrop_Comment
  • Ingo_Script_Maildrop_Recipe
  • Ingo_Script_Maildrop_Variable
  • Ingo_Script_Procmail
  • Ingo_Script_Procmail_Comment
  • Ingo_Script_Procmail_Recipe
  • Ingo_Script_Procmail_Variable
  • Ingo_Script_Sieve
  • Ingo_Script_Sieve_Action
  • Ingo_Script_Sieve_Action_Addflag
  • Ingo_Script_Sieve_Action_Discard
  • Ingo_Script_Sieve_Action_Fileinto
  • Ingo_Script_Sieve_Action_Flag
  • Ingo_Script_Sieve_Action_Keep
  • Ingo_Script_Sieve_Action_Notify
  • Ingo_Script_Sieve_Action_Redirect
  • Ingo_Script_Sieve_Action_Reject
  • Ingo_Script_Sieve_Action_Removeflag
  • Ingo_Script_Sieve_Action_Stop
  • Ingo_Script_Sieve_Action_Vacation
  • Ingo_Script_Sieve_Comment
  • Ingo_Script_Sieve_Else
  • Ingo_Script_Sieve_Elsif
  • Ingo_Script_Sieve_If
  • Ingo_Script_Sieve_Test
  • Ingo_Script_Sieve_Test_Address
  • Ingo_Script_Sieve_Test_Allof
  • Ingo_Script_Sieve_Test_Anyof
  • Ingo_Script_Sieve_Test_Body
  • Ingo_Script_Sieve_Test_Exists
  • Ingo_Script_Sieve_Test_False
  • Ingo_Script_Sieve_Test_Header
  • Ingo_Script_Sieve_Test_Not
  • Ingo_Script_Sieve_Test_Relational
  • Ingo_Script_Sieve_Test_Size
  • Ingo_Script_Sieve_Test_True
  • Ingo_Storage
  • Ingo_Storage_Blacklist
  • Ingo_Storage_Filters
  • Ingo_Storage_Filters_Sql
  • Ingo_Storage_Forward
  • Ingo_Storage_Mock
  • Ingo_Storage_Prefs
  • Ingo_Storage_Rule
  • Ingo_Storage_Spam
  • Ingo_Storage_Sql
  • Ingo_Storage_Vacation
  • Ingo_Storage_VacationTest
  • Ingo_Storage_Whitelist
  • Ingo_Test
  • Ingo_Transport
  • Ingo_Transport_Ldap
  • Ingo_Transport_Null
  • Ingo_Transport_Sivtest
  • Ingo_Transport_Timsieved
  • Ingo_Transport_Vfs
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Ingo_Transport_Ldap implements the Sieve_Driver api to allow scripts to be
  4:  * installed and set active via an LDAP server.
  5:  *
  6:  * See the enclosed file LICENSE for license information (ASL).  If you
  7:  * did not receive this file, see http://www.horde.org/licenses/apache.
  8:  *
  9:  * @author  Jason M. Felice <jason.m.felice@gmail.com>
 10:  * @package Ingo
 11:  */
 12: class Ingo_Transport_Ldap extends Ingo_Transport
 13: {
 14:     /**
 15:      * Constructor.
 16:      *
 17:      * @throws Ingo_Exception
 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:      * Create a DN from a DN template.
 36:      * This is done by substituting the username for %u and the 'dc='
 37:      * components for %d.
 38:      *
 39:      * @param string $templ  The DN template (from the config).
 40:      *
 41:      * @return string  The resulting DN.
 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:      * Connect and bind to ldap server.
 67:      *
 68:      * @throws Ingo_Exception
 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:         /* Set the LDAP protocol version. */
 78:         if (!empty($this->_params['version'])) {
 79:             @ldap_set_option($ldapcn,
 80:                              LDAP_OPT_PROTOCOL_VERSION,
 81:                              $this->_params['version']);
 82:         }
 83: 
 84:         /* Start TLS if we're using it. */
 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:         /* Bind to the server. */
 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:      * Retrieve current user's scripts.
117:      *
118:      * @param resource $ldapcn  The connection to the LDAP server.
119:      * @param string $userDN    Set to the user object's real DN.
120:      *
121:      * @return array  Script sources list.
122:      * @throws Ingo_Exception
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:         /* Find the user object. */
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:         /* Retrieve the user's DN. */
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:         /* Retrieve the user's scripts. */
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:         /* Attribute can be in any case, and can have a ";binary"
170:          * specifier. */
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:      * Sets a script running on the backend.
186:      *
187:      * @todo No idea how to handle $additional.
188:      *
189:      * @param string $script     The filter script.
190:      * @param array $additional  Any additional scripts that need to uploaded.
191:      *
192:      * @throws Ingo_Exception
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:      * Returns the content of the currently active script.
233:      *
234:      * @return string  The complete ruleset of the specified user.
235:      *
236:      * @throws Ingo_Exception
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: 
API documentation generated by ApiGen