Mercurial > hg > rc1
comparison plugins/acl/acl.php @ 0:1e000243b222
vanilla 1.3.3 distro, I hope
author | Charlie Root |
---|---|
date | Thu, 04 Jan 2018 15:50:29 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e000243b222 |
---|---|
1 <?php | |
2 | |
3 /** | |
4 * Folders Access Control Lists Management (RFC4314, RFC2086) | |
5 * | |
6 * @author Aleksander Machniak <alec@alec.pl> | |
7 * | |
8 * Copyright (C) 2011-2012, Kolab Systems AG | |
9 * | |
10 * This program is free software: you can redistribute it and/or modify | |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation, either version 3 of the License, or | |
13 * (at your option) any later version. | |
14 * | |
15 * This program is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU General Public License | |
21 * along with this program. If not, see http://www.gnu.org/licenses/. | |
22 */ | |
23 | |
24 class acl extends rcube_plugin | |
25 { | |
26 public $task = 'settings|addressbook|calendar'; | |
27 | |
28 private $rc; | |
29 private $supported = null; | |
30 private $mbox; | |
31 private $ldap; | |
32 private $specials = array('anyone', 'anonymous'); | |
33 | |
34 /** | |
35 * Plugin initialization | |
36 */ | |
37 function init() | |
38 { | |
39 $this->rc = rcmail::get_instance(); | |
40 | |
41 // Register hooks | |
42 $this->add_hook('folder_form', array($this, 'folder_form')); | |
43 // kolab_addressbook plugin | |
44 $this->add_hook('addressbook_form', array($this, 'folder_form')); | |
45 $this->add_hook('calendar_form_kolab', array($this, 'folder_form')); | |
46 // Plugin actions | |
47 $this->register_action('plugin.acl', array($this, 'acl_actions')); | |
48 $this->register_action('plugin.acl-autocomplete', array($this, 'acl_autocomplete')); | |
49 } | |
50 | |
51 /** | |
52 * Handler for plugin actions (AJAX) | |
53 */ | |
54 function acl_actions() | |
55 { | |
56 $action = trim(rcube_utils::get_input_value('_act', rcube_utils::INPUT_GPC)); | |
57 | |
58 // Connect to IMAP | |
59 $this->rc->storage_init(); | |
60 | |
61 // Load localization and configuration | |
62 $this->add_texts('localization/'); | |
63 $this->load_config(); | |
64 | |
65 if ($action == 'save') { | |
66 $this->action_save(); | |
67 } | |
68 else if ($action == 'delete') { | |
69 $this->action_delete(); | |
70 } | |
71 else if ($action == 'list') { | |
72 $this->action_list(); | |
73 } | |
74 | |
75 // Only AJAX actions | |
76 $this->rc->output->send(); | |
77 } | |
78 | |
79 /** | |
80 * Handler for user login autocomplete request | |
81 */ | |
82 function acl_autocomplete() | |
83 { | |
84 $this->load_config(); | |
85 | |
86 $search = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GPC, true); | |
87 $reqid = rcube_utils::get_input_value('_reqid', rcube_utils::INPUT_GPC); | |
88 $users = array(); | |
89 $keys = array(); | |
90 | |
91 if ($this->init_ldap()) { | |
92 $max = (int) $this->rc->config->get('autocomplete_max', 15); | |
93 $mode = (int) $this->rc->config->get('addressbook_search_mode'); | |
94 | |
95 $this->ldap->set_pagesize($max); | |
96 $result = $this->ldap->search('*', $search, $mode); | |
97 | |
98 foreach ($result->records as $record) { | |
99 $user = $record['uid']; | |
100 | |
101 if (is_array($user)) { | |
102 $user = array_filter($user); | |
103 $user = $user[0]; | |
104 } | |
105 | |
106 if ($user) { | |
107 $display = rcube_addressbook::compose_search_name($record); | |
108 $user = array('name' => $user, 'display' => $display); | |
109 $users[] = $user; | |
110 $keys[] = $display ?: $user['name']; | |
111 } | |
112 } | |
113 | |
114 if ($this->rc->config->get('acl_groups')) { | |
115 $prefix = $this->rc->config->get('acl_group_prefix'); | |
116 $group_field = $this->rc->config->get('acl_group_field', 'name'); | |
117 $result = $this->ldap->list_groups($search, $mode); | |
118 | |
119 foreach ($result as $record) { | |
120 $group = $record['name']; | |
121 $group_id = is_array($record[$group_field]) ? $record[$group_field][0] : $record[$group_field]; | |
122 | |
123 if ($group) { | |
124 $users[] = array('name' => ($prefix ?: '') . $group_id, 'display' => $group, 'type' => 'group'); | |
125 $keys[] = $group; | |
126 } | |
127 } | |
128 } | |
129 } | |
130 | |
131 if (count($users)) { | |
132 // sort users index | |
133 asort($keys, SORT_LOCALE_STRING); | |
134 // re-sort users according to index | |
135 foreach ($keys as $idx => $val) { | |
136 $keys[$idx] = $users[$idx]; | |
137 } | |
138 $users = array_values($keys); | |
139 } | |
140 | |
141 $this->rc->output->command('ksearch_query_results', $users, $search, $reqid); | |
142 $this->rc->output->send(); | |
143 } | |
144 | |
145 /** | |
146 * Handler for 'folder_form' hook | |
147 * | |
148 * @param array $args Hook arguments array (form data) | |
149 * | |
150 * @return array Hook arguments array | |
151 */ | |
152 function folder_form($args) | |
153 { | |
154 $mbox_imap = $args['options']['name']; | |
155 $myrights = $args['options']['rights']; | |
156 | |
157 // Edited folder name (empty in create-folder mode) | |
158 if (!strlen($mbox_imap)) { | |
159 return $args; | |
160 } | |
161 /* | |
162 // Do nothing on protected folders (?) | |
163 if ($args['options']['protected']) { | |
164 return $args; | |
165 } | |
166 */ | |
167 // Get MYRIGHTS | |
168 if (empty($myrights)) { | |
169 return $args; | |
170 } | |
171 | |
172 // Load localization and include scripts | |
173 $this->load_config(); | |
174 $this->specials = $this->rc->config->get('acl_specials', $this->specials); | |
175 $this->add_texts('localization/', array('deleteconfirm', 'norights', | |
176 'nouser', 'deleting', 'saving', 'newuser', 'editperms')); | |
177 $this->rc->output->add_label('save', 'cancel'); | |
178 $this->include_script('acl.js'); | |
179 $this->rc->output->include_script('list.js'); | |
180 $this->include_stylesheet($this->local_skin_path().'/acl.css'); | |
181 | |
182 // add Info fieldset if it doesn't exist | |
183 if (!isset($args['form']['props']['fieldsets']['info'])) | |
184 $args['form']['props']['fieldsets']['info'] = array( | |
185 'name' => $this->rc->gettext('info'), | |
186 'content' => array()); | |
187 | |
188 // Display folder rights to 'Info' fieldset | |
189 $args['form']['props']['fieldsets']['info']['content']['myrights'] = array( | |
190 'label' => rcube::Q($this->gettext('myrights')), | |
191 'value' => $this->acl2text($myrights) | |
192 ); | |
193 | |
194 // Return if not folder admin | |
195 if (!in_array('a', $myrights)) { | |
196 return $args; | |
197 } | |
198 | |
199 // The 'Sharing' tab | |
200 $this->mbox = $mbox_imap; | |
201 $this->rc->output->set_env('acl_users_source', (bool) $this->rc->config->get('acl_users_source')); | |
202 $this->rc->output->set_env('mailbox', $mbox_imap); | |
203 $this->rc->output->add_handlers(array( | |
204 'acltable' => array($this, 'templ_table'), | |
205 'acluser' => array($this, 'templ_user'), | |
206 'aclrights' => array($this, 'templ_rights'), | |
207 )); | |
208 | |
209 $this->rc->output->set_env('autocomplete_max', (int)$this->rc->config->get('autocomplete_max', 15)); | |
210 $this->rc->output->set_env('autocomplete_min_length', $this->rc->config->get('autocomplete_min_length')); | |
211 $this->rc->output->add_label('autocompletechars', 'autocompletemore'); | |
212 | |
213 $args['form']['sharing'] = array( | |
214 'name' => rcube::Q($this->gettext('sharing')), | |
215 'content' => $this->rc->output->parse('acl.table', false, false), | |
216 ); | |
217 | |
218 return $args; | |
219 } | |
220 | |
221 /** | |
222 * Creates ACL rights table | |
223 * | |
224 * @param array $attrib Template object attributes | |
225 * | |
226 * @return string HTML Content | |
227 */ | |
228 function templ_table($attrib) | |
229 { | |
230 if (empty($attrib['id'])) | |
231 $attrib['id'] = 'acl-table'; | |
232 | |
233 $out = $this->list_rights($attrib); | |
234 | |
235 $this->rc->output->add_gui_object('acltable', $attrib['id']); | |
236 | |
237 return $out; | |
238 } | |
239 | |
240 /** | |
241 * Creates ACL rights form (rights list part) | |
242 * | |
243 * @param array $attrib Template object attributes | |
244 * | |
245 * @return string HTML Content | |
246 */ | |
247 function templ_rights($attrib) | |
248 { | |
249 // Get supported rights | |
250 $supported = $this->rights_supported(); | |
251 | |
252 // give plugins the opportunity to adjust this list | |
253 $data = $this->rc->plugins->exec_hook('acl_rights_supported', | |
254 array('rights' => $supported, 'folder' => $this->mbox, 'labels' => array())); | |
255 $supported = $data['rights']; | |
256 | |
257 // depending on server capability either use 'te' or 'd' for deleting msgs | |
258 $deleteright = implode(array_intersect(str_split('ted'), $supported)); | |
259 | |
260 $out = ''; | |
261 $ul = ''; | |
262 $input = new html_checkbox(); | |
263 | |
264 // Advanced rights | |
265 $attrib['id'] = 'advancedrights'; | |
266 foreach ($supported as $key => $val) { | |
267 $id = "acl$val"; | |
268 $ul .= html::tag('li', null, | |
269 $input->show('', array( | |
270 'name' => "acl[$val]", 'value' => $val, 'id' => $id)) | |
271 . html::label(array('for' => $id, 'title' => $this->gettext('longacl'.$val)), | |
272 $this->gettext('acl'.$val))); | |
273 } | |
274 | |
275 $out = html::tag('ul', $attrib, $ul, html::$common_attrib); | |
276 | |
277 // Simple rights | |
278 $ul = ''; | |
279 $attrib['id'] = 'simplerights'; | |
280 $items = array( | |
281 'read' => 'lrs', | |
282 'write' => 'wi', | |
283 'delete' => $deleteright, | |
284 'other' => preg_replace('/[lrswi'.$deleteright.']/', '', implode($supported)), | |
285 ); | |
286 | |
287 // give plugins the opportunity to adjust this list | |
288 $data = $this->rc->plugins->exec_hook('acl_rights_simple', | |
289 array('rights' => $items, 'folder' => $this->mbox, 'labels' => array(), 'titles' => array())); | |
290 | |
291 foreach ($data['rights'] as $key => $val) { | |
292 $id = "acl$key"; | |
293 $ul .= html::tag('li', null, | |
294 $input->show('', array( | |
295 'name' => "acl[$val]", 'value' => $val, 'id' => $id)) | |
296 . html::label(array('for' => $id, 'title' => $data['titles'][$key] ?: $this->gettext('longacl'.$key)), | |
297 $data['labels'][$key] ?: $this->gettext('acl'.$key))); | |
298 } | |
299 | |
300 $out .= "\n" . html::tag('ul', $attrib, $ul, html::$common_attrib); | |
301 | |
302 $this->rc->output->set_env('acl_items', $data['rights']); | |
303 | |
304 return $out; | |
305 } | |
306 | |
307 /** | |
308 * Creates ACL rights form (user part) | |
309 * | |
310 * @param array $attrib Template object attributes | |
311 * | |
312 * @return string HTML Content | |
313 */ | |
314 function templ_user($attrib) | |
315 { | |
316 // Create username input | |
317 $attrib['name'] = 'acluser'; | |
318 | |
319 $textfield = new html_inputfield($attrib); | |
320 | |
321 $fields['user'] = html::label(array('for' => $attrib['id']), $this->gettext('username')) | |
322 . ' ' . $textfield->show(); | |
323 | |
324 // Add special entries | |
325 if (!empty($this->specials)) { | |
326 foreach ($this->specials as $key) { | |
327 $fields[$key] = html::label(array('for' => 'id'.$key), $this->gettext($key)); | |
328 } | |
329 } | |
330 | |
331 $this->rc->output->set_env('acl_specials', $this->specials); | |
332 | |
333 // Create list with radio buttons | |
334 if (count($fields) > 1) { | |
335 $ul = ''; | |
336 $radio = new html_radiobutton(array('name' => 'usertype')); | |
337 foreach ($fields as $key => $val) { | |
338 $ul .= html::tag('li', null, $radio->show($key == 'user' ? 'user' : '', | |
339 array('value' => $key, 'id' => 'id'.$key)) | |
340 . $val); | |
341 } | |
342 | |
343 $out = html::tag('ul', array('id' => 'usertype', 'class' => $attrib['class']), $ul, html::$common_attrib); | |
344 } | |
345 // Display text input alone | |
346 else { | |
347 $out = $fields['user']; | |
348 } | |
349 | |
350 return $out; | |
351 } | |
352 | |
353 /** | |
354 * Creates ACL rights table | |
355 * | |
356 * @param array $attrib Template object attributes | |
357 * | |
358 * @return string HTML Content | |
359 */ | |
360 private function list_rights($attrib=array()) | |
361 { | |
362 // Get ACL for the folder | |
363 $acl = $this->rc->storage->get_acl($this->mbox); | |
364 | |
365 if (!is_array($acl)) { | |
366 $acl = array(); | |
367 } | |
368 | |
369 // Keep special entries (anyone/anonymous) on top of the list | |
370 if (!empty($this->specials) && !empty($acl)) { | |
371 foreach ($this->specials as $key) { | |
372 if (isset($acl[$key])) { | |
373 $acl_special[$key] = $acl[$key]; | |
374 unset($acl[$key]); | |
375 } | |
376 } | |
377 } | |
378 | |
379 // Sort the list by username | |
380 uksort($acl, 'strnatcasecmp'); | |
381 | |
382 if (!empty($acl_special)) { | |
383 $acl = array_merge($acl_special, $acl); | |
384 } | |
385 | |
386 // Get supported rights and build column names | |
387 $supported = $this->rights_supported(); | |
388 | |
389 // give plugins the opportunity to adjust this list | |
390 $data = $this->rc->plugins->exec_hook('acl_rights_supported', | |
391 array('rights' => $supported, 'folder' => $this->mbox, 'labels' => array())); | |
392 $supported = $data['rights']; | |
393 | |
394 // depending on server capability either use 'te' or 'd' for deleting msgs | |
395 $deleteright = implode(array_intersect(str_split('ted'), $supported)); | |
396 | |
397 // Use advanced or simple (grouped) rights | |
398 $advanced = $this->rc->config->get('acl_advanced_mode'); | |
399 | |
400 if ($advanced) { | |
401 $items = array(); | |
402 foreach ($supported as $sup) { | |
403 $items[$sup] = $sup; | |
404 } | |
405 } | |
406 else { | |
407 $items = array( | |
408 'read' => 'lrs', | |
409 'write' => 'wi', | |
410 'delete' => $deleteright, | |
411 'other' => preg_replace('/[lrswi'.$deleteright.']/', '', implode($supported)), | |
412 ); | |
413 | |
414 // give plugins the opportunity to adjust this list | |
415 $data = $this->rc->plugins->exec_hook('acl_rights_simple', | |
416 array('rights' => $items, 'folder' => $this->mbox, 'labels' => array())); | |
417 $items = $data['rights']; | |
418 } | |
419 | |
420 // Create the table | |
421 $attrib['noheader'] = true; | |
422 $table = new html_table($attrib); | |
423 | |
424 // Create table header | |
425 $table->add_header('user', $this->gettext('identifier')); | |
426 foreach (array_keys($items) as $key) { | |
427 $label = $data['labels'][$key] ?: $this->gettext('shortacl'.$key); | |
428 $table->add_header(array('class' => 'acl'.$key, 'title' => $label), $label); | |
429 } | |
430 | |
431 $js_table = array(); | |
432 foreach ($acl as $user => $rights) { | |
433 if ($this->rc->storage->conn->user == $user) { | |
434 continue; | |
435 } | |
436 | |
437 // filter out virtual rights (c or d) the server may return | |
438 $userrights = array_intersect($rights, $supported); | |
439 $userid = rcube_utils::html_identifier($user); | |
440 | |
441 if (!empty($this->specials) && in_array($user, $this->specials)) { | |
442 $user = $this->gettext($user); | |
443 } | |
444 | |
445 $table->add_row(array('id' => 'rcmrow'.$userid)); | |
446 $table->add('user', html::a(array('id' => 'rcmlinkrow'.$userid), rcube::Q($user))); | |
447 | |
448 foreach ($items as $key => $right) { | |
449 $in = $this->acl_compare($userrights, $right); | |
450 switch ($in) { | |
451 case 2: $class = 'enabled'; break; | |
452 case 1: $class = 'partial'; break; | |
453 default: $class = 'disabled'; break; | |
454 } | |
455 $table->add('acl' . $key . ' ' . $class, ''); | |
456 } | |
457 | |
458 $js_table[$userid] = implode($userrights); | |
459 } | |
460 | |
461 $this->rc->output->set_env('acl', $js_table); | |
462 $this->rc->output->set_env('acl_advanced', $advanced); | |
463 | |
464 $out = $table->show(); | |
465 | |
466 return $out; | |
467 } | |
468 | |
469 /** | |
470 * Handler for ACL update/create action | |
471 */ | |
472 private function action_save() | |
473 { | |
474 $mbox = trim(rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true)); // UTF7-IMAP | |
475 $user = trim(rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST)); | |
476 $acl = trim(rcube_utils::get_input_value('_acl', rcube_utils::INPUT_POST)); | |
477 $oldid = trim(rcube_utils::get_input_value('_old', rcube_utils::INPUT_POST)); | |
478 | |
479 $acl = array_intersect(str_split($acl), $this->rights_supported()); | |
480 $users = $oldid ? array($user) : explode(',', $user); | |
481 $result = 0; | |
482 | |
483 foreach ($users as $user) { | |
484 $user = trim($user); | |
485 $prefix = $this->rc->config->get('acl_groups') ? $this->rc->config->get('acl_group_prefix') : ''; | |
486 | |
487 if ($prefix && strpos($user, $prefix) === 0) { | |
488 $username = $user; | |
489 } | |
490 else if (!empty($this->specials) && in_array($user, $this->specials)) { | |
491 $username = $this->gettext($user); | |
492 } | |
493 else if (!empty($user)) { | |
494 if (!strpos($user, '@') && ($realm = $this->get_realm())) { | |
495 $user .= '@' . rcube_utils::idn_to_ascii(preg_replace('/^@/', '', $realm)); | |
496 } | |
497 $username = $user; | |
498 } | |
499 | |
500 if (!$acl || !$user || !strlen($mbox)) { | |
501 continue; | |
502 } | |
503 | |
504 $user = $this->mod_login($user); | |
505 $username = $this->mod_login($username); | |
506 | |
507 if ($user != $_SESSION['username'] && $username != $_SESSION['username']) { | |
508 if ($this->rc->storage->set_acl($mbox, $user, $acl)) { | |
509 $ret = array('id' => rcube_utils::html_identifier($user), | |
510 'username' => $username, 'acl' => implode($acl), 'old' => $oldid); | |
511 $this->rc->output->command('acl_update', $ret); | |
512 $result++; | |
513 } | |
514 } | |
515 } | |
516 | |
517 if ($result) { | |
518 $this->rc->output->show_message($oldid ? 'acl.updatesuccess' : 'acl.createsuccess', 'confirmation'); | |
519 } | |
520 else { | |
521 $this->rc->output->show_message($oldid ? 'acl.updateerror' : 'acl.createerror', 'error'); | |
522 } | |
523 } | |
524 | |
525 /** | |
526 * Handler for ACL delete action | |
527 */ | |
528 private function action_delete() | |
529 { | |
530 $mbox = trim(rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true)); //UTF7-IMAP | |
531 $user = trim(rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST)); | |
532 | |
533 $user = explode(',', $user); | |
534 | |
535 foreach ($user as $u) { | |
536 $u = trim($u); | |
537 if ($this->rc->storage->delete_acl($mbox, $u)) { | |
538 $this->rc->output->command('acl_remove_row', rcube_utils::html_identifier($u)); | |
539 } | |
540 else { | |
541 $error = true; | |
542 } | |
543 } | |
544 | |
545 if (!$error) { | |
546 $this->rc->output->show_message('acl.deletesuccess', 'confirmation'); | |
547 } | |
548 else { | |
549 $this->rc->output->show_message('acl.deleteerror', 'error'); | |
550 } | |
551 } | |
552 | |
553 /** | |
554 * Handler for ACL list update action (with display mode change) | |
555 */ | |
556 private function action_list() | |
557 { | |
558 if (in_array('acl_advanced_mode', (array)$this->rc->config->get('dont_override'))) { | |
559 return; | |
560 } | |
561 | |
562 $this->mbox = trim(rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true)); // UTF7-IMAP | |
563 $advanced = trim(rcube_utils::get_input_value('_mode', rcube_utils::INPUT_GPC)); | |
564 $advanced = $advanced == 'advanced'; | |
565 | |
566 // Save state in user preferences | |
567 $this->rc->user->save_prefs(array('acl_advanced_mode' => $advanced)); | |
568 | |
569 $out = $this->list_rights(); | |
570 | |
571 $out = preg_replace(array('/^<table[^>]+>/', '/<\/table>$/'), '', $out); | |
572 | |
573 $this->rc->output->command('acl_list_update', $out); | |
574 } | |
575 | |
576 /** | |
577 * Creates <UL> list with descriptive access rights | |
578 * | |
579 * @param array $rights MYRIGHTS result | |
580 * | |
581 * @return string HTML content | |
582 */ | |
583 function acl2text($rights) | |
584 { | |
585 if (empty($rights)) { | |
586 return ''; | |
587 } | |
588 | |
589 $supported = $this->rights_supported(); | |
590 $list = array(); | |
591 $attrib = array( | |
592 'name' => 'rcmyrights', | |
593 'style' => 'margin:0; padding:0 15px;', | |
594 ); | |
595 | |
596 foreach ($supported as $right) { | |
597 if (in_array($right, $rights)) { | |
598 $list[] = html::tag('li', null, rcube::Q($this->gettext('acl' . $right))); | |
599 } | |
600 } | |
601 | |
602 if (count($list) == count($supported)) | |
603 return rcube::Q($this->gettext('aclfull')); | |
604 | |
605 return html::tag('ul', $attrib, implode("\n", $list)); | |
606 } | |
607 | |
608 /** | |
609 * Compares two ACLs (according to supported rights) | |
610 * | |
611 * @param array $acl1 ACL rights array (or string) | |
612 * @param array $acl2 ACL rights array (or string) | |
613 * | |
614 * @param int Comparison result, 2 - full match, 1 - partial match, 0 - no match | |
615 */ | |
616 function acl_compare($acl1, $acl2) | |
617 { | |
618 if (!is_array($acl1)) $acl1 = str_split($acl1); | |
619 if (!is_array($acl2)) $acl2 = str_split($acl2); | |
620 | |
621 $rights = $this->rights_supported(); | |
622 | |
623 $acl1 = array_intersect($acl1, $rights); | |
624 $acl2 = array_intersect($acl2, $rights); | |
625 $res = array_intersect($acl1, $acl2); | |
626 | |
627 $cnt1 = count($res); | |
628 $cnt2 = count($acl2); | |
629 | |
630 if ($cnt1 == $cnt2) | |
631 return 2; | |
632 else if ($cnt1) | |
633 return 1; | |
634 else | |
635 return 0; | |
636 } | |
637 | |
638 /** | |
639 * Get list of supported access rights (according to RIGHTS capability) | |
640 * | |
641 * @return array List of supported access rights abbreviations | |
642 */ | |
643 function rights_supported() | |
644 { | |
645 if ($this->supported !== null) { | |
646 return $this->supported; | |
647 } | |
648 | |
649 $capa = $this->rc->storage->get_capability('RIGHTS'); | |
650 | |
651 if (is_array($capa)) { | |
652 $rights = strtolower($capa[0]); | |
653 } | |
654 else { | |
655 $rights = 'cd'; | |
656 } | |
657 | |
658 return $this->supported = str_split('lrswi' . $rights . 'pa'); | |
659 } | |
660 | |
661 /** | |
662 * Username realm detection. | |
663 * | |
664 * @return string Username realm (domain) | |
665 */ | |
666 private function get_realm() | |
667 { | |
668 // When user enters a username without domain part, realm | |
669 // allows to add it to the username (and display correct username in the table) | |
670 | |
671 if (isset($_SESSION['acl_username_realm'])) { | |
672 return $_SESSION['acl_username_realm']; | |
673 } | |
674 | |
675 // find realm in username of logged user (?) | |
676 list($name, $domain) = explode('@', $_SESSION['username']); | |
677 | |
678 // Use (always existent) ACL entry on the INBOX for the user to determine | |
679 // whether or not the user ID in ACL entries need to be qualified and how | |
680 // they would need to be qualified. | |
681 if (empty($domain)) { | |
682 $acl = $this->rc->storage->get_acl('INBOX'); | |
683 if (is_array($acl)) { | |
684 $regexp = '/^' . preg_quote($_SESSION['username'], '/') . '@(.*)$/'; | |
685 foreach (array_keys($acl) as $name) { | |
686 if (preg_match($regexp, $name, $matches)) { | |
687 $domain = $matches[1]; | |
688 break; | |
689 } | |
690 } | |
691 } | |
692 } | |
693 | |
694 return $_SESSION['acl_username_realm'] = $domain; | |
695 } | |
696 | |
697 /** | |
698 * Initializes autocomplete LDAP backend | |
699 */ | |
700 private function init_ldap() | |
701 { | |
702 if ($this->ldap) { | |
703 return $this->ldap->ready; | |
704 } | |
705 | |
706 // get LDAP config | |
707 $config = $this->rc->config->get('acl_users_source'); | |
708 | |
709 if (empty($config)) { | |
710 return false; | |
711 } | |
712 | |
713 // not an array, use configured ldap_public source | |
714 if (!is_array($config)) { | |
715 $ldap_config = (array) $this->rc->config->get('ldap_public'); | |
716 $config = $ldap_config[$config]; | |
717 } | |
718 | |
719 $uid_field = $this->rc->config->get('acl_users_field', 'mail'); | |
720 $filter = $this->rc->config->get('acl_users_filter'); | |
721 | |
722 if (empty($uid_field) || empty($config)) { | |
723 return false; | |
724 } | |
725 | |
726 // get name attribute | |
727 if (!empty($config['fieldmap'])) { | |
728 $name_field = $config['fieldmap']['name']; | |
729 } | |
730 // ... no fieldmap, use the old method | |
731 if (empty($name_field)) { | |
732 $name_field = $config['name_field']; | |
733 } | |
734 | |
735 // add UID field to fieldmap, so it will be returned in a record with name | |
736 $config['fieldmap']['name'] = $name_field; | |
737 $config['fieldmap']['uid'] = $uid_field; | |
738 | |
739 // search in UID and name fields | |
740 // $name_field can be in a form of <field>:<modifier> (#1490591) | |
741 $name_field = preg_replace('/:.*$/', '', $name_field); | |
742 $search = array_unique(array($name_field, $uid_field)); | |
743 | |
744 $config['search_fields'] = $search; | |
745 $config['required_fields'] = array($uid_field); | |
746 | |
747 // set search filter | |
748 if ($filter) { | |
749 $config['filter'] = $filter; | |
750 } | |
751 | |
752 // disable vlv | |
753 $config['vlv'] = false; | |
754 | |
755 // Initialize LDAP connection | |
756 $this->ldap = new rcube_ldap($config, | |
757 $this->rc->config->get('ldap_debug'), | |
758 $this->rc->config->mail_domain($_SESSION['imap_host'])); | |
759 | |
760 return $this->ldap->ready; | |
761 } | |
762 | |
763 /** | |
764 * Modify user login according to 'login_lc' setting | |
765 */ | |
766 protected function mod_login($user) | |
767 { | |
768 $login_lc = $this->rc->config->get('login_lc'); | |
769 | |
770 if ($login_lc === true || $login_lc == 2) { | |
771 $user = mb_strtolower($user); | |
772 } | |
773 // lowercase domain name | |
774 else if ($login_lc && strpos($user, '@')) { | |
775 list($local, $domain) = explode('@', $user); | |
776 $user = $local . '@' . mb_strtolower($domain); | |
777 } | |
778 | |
779 return $user; | |
780 } | |
781 } |