/[drupal]/contributions/modules/ldap_addressbook/ldap_addressbook.module
ViewVC logotype

Contents of /contributions/modules/ldap_addressbook/ldap_addressbook.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.3 - (show annotations) (download) (as text)
Thu Apr 20 07:21:28 2006 UTC (3 years, 7 months ago) by chx
Branch: MAIN
CVS Tags: DRUPAL-4-7--1-0, HEAD
Branch point for: DRUPAL-5, DRUPAL-4-7
Changes since 1.2: +2 -2 lines
File MIME type: text/x-php
after_build fix
1 <?php //Dear emacs, please make this buffer -*- php -*-
2
3 // $Id: ldap_addressbook.module,v 1.2 2006/03/28 20:15:19 rabello Exp $
4
5 /**
6 * @file
7 * A module for drupal to maintain an addressbook with LDAP as backend.
8 *
9 * Copyright (C) 2005 Ola Thoresen
10 * Copyright (C) 2006 Andre dos Anjos
11 *
12 * This file is part of the ldap_addresbook module for Drupal.
13 *
14 * The ldap_addressbook module is free software; you can redistribute it
15 * and/or modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of the License,
17 * or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful, but WITHOUT
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
22 * more details.
23 *
24 * You should have received a copy of the GNU General Public License along with
25 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
26 * Place, Suite 330, Boston, MA 02111-1307 USA
27 **/
28
29 /**
30 * @todo Ideas to be implemented (difficulty from 1 to 5, being 5 the
31 * hardest):
32 *
33 * # Import and export to LDIF format (you will have to write a set of
34 * functions to do that [difficulty 4];
35 *
36 * # Import entries from other addressbooks according to a filter. [difficulty
37 * 4];
38 *
39 * # Implement configurable renaming of LDAP fields by the user with i18n
40 * translation possible [difficulty 3];
41 *
42 * # Make sure all strings can be translated by the means of the t() function
43 * [difficulty 1];
44 *
45 * # Trust garbage collection to be executed by cron() instead of by your
46 * functions [difficult 1, just requires extensive testing].
47 *
48 * # Place a "contact" entry under the "create content" menu so the whole
49 * addressbook seems integrated within drupal [difficulty 4];
50 *
51 * # Integrated the Adressbook Search into drupal's search facility
52 * [difficulty 5];
53 **/
54
55 require_once("LDAPDirectory.inc");
56 require_once("Format.inc");
57
58 /**
59 * Implementation of hook_help().
60 *
61 * I should probably write some more helpful info here
62 *
63 **/
64 function ldap_addressbook_help($section) {
65 switch ($section) {
66 case 'admin/modules#description':
67 return t('An addressbook with a LDAP based backend');
68 }
69 }
70
71 /**
72 * Implementation of hook_perm().
73 *
74 * This is the thinking behind permissions for this module:
75 * # Users that can change the LDAP server settings and know its passwords
76 * should get the "Administer" permission;
77 * # Users that can edit and change the entries in the addressbook should get
78 * the "Edit" permission. Please note that users that can administer the LDAP
79 * server settings will naturally get permission to edit the LDAP server, but
80 * <b>not</b> the contrary.
81 * # Users that can only view the addressbook entries, should get the "Search"
82 * permission. Please note that users that have either the "Edit" permission
83 * or the "Administer" permission should automatically gain "Search"
84 * permissions.
85 **/
86 function ldap_addressbook_perm() {
87 return array('Administer LDAP addressbook module',
88 'Edit LDAP addressbook',
89 'Search LDAP addressbook',
90 'Have private LDAP addressbook');
91 }
92
93 /**
94 * A helper to determine how to compute the permissions for a given user.
95 *
96 * @param $op The operation to be performed. Possible values: "admin", "edit",
97 * "search", which match the hook_perm() above.
98 **/
99 function _ldap_addressbook_allow($op='search') {
100
101 //The permission logic
102 $can_admin = user_access('Administer LDAP addressbook module');
103 if ($op == 'admin') return $can_admin;
104 $can_edit = $can_admin || user_access('Edit LDAP addressbook');
105 if ($op == 'edit') return $can_edit;
106 if ($op == 'search')
107 return $can_edit || user_access('Search LDAP addressbook');
108
109 //if you get here, I'm sorry, you don't have any permission to do anything
110 //else! Print something!
111 drupal_set_message
112 ('Calling _ldap_addressbook_allow($op='.$op.') is strange!', error);
113 return FALSE;
114 }
115
116 /**
117 * Implementation of hook_menu().
118 **/
119 function ldap_addressbook_menu($may_cache) {
120 $dir = new DrupalDirectory();
121 $items = array();
122
123 if ($may_cache) {
124
125 // $may_cache is normally set when there are changes in the page that need
126 // refreshing the menus. An example is when you change the themes of a
127 // page or logout/login. In any other cases, these entries are saved on
128 // the DB(?) and then used without reading this code. If you don't like
129 // this behavior, move these lines to the else{} clause bellow.
130
131 // To test that this is called with a theme change or upon logout/login,
132 // uncomment the line bellow.
133 //trigger_error('hook_menu() called with $may_cache = TRUE!');
134
135 $items[] = array('path' => $dir->module_name() . '/new',
136 'title' => t('new contact'),
137 'callback' => '_menu_ldap_addressbook_new',
138 'access' => _ldap_addressbook_allow('edit'),
139 'type' => MENU_CALLBACK,
140 'weight' => 5);
141
142 $items[] = array('path' => $dir->module_name() . '/search',
143 'title' => t('search addressbook'),
144 'callback' => '_menu_ldap_addressbook_search',
145 'access' => _ldap_addressbook_allow('search'),
146 'type' => MENU_CALLBACK);
147
148 }
149
150 else {
151
152 // This is the default callback, that launches the tabbed view. No
153 // arguments required, just the function that gets the first argument
154 // and tries to view the LDAP entry. This item is uncacheable since it
155 // might change quite dynamically.
156 $top_title = t('view');
157 if (arg(2)) $top_title = t('Contact ').arg(3).t(' (at ').arg(2).t(' addressbook)');
158 $items[] = array('path' => $dir->module_name().'/node',
159 'title' => $top_title,
160 'callback' => '_menu_ldap_addressbook_view',
161 'access' => _ldap_addressbook_allow('search'),
162 'type' => MENU_CALLBACK);
163
164 $items[] = array('path' => 'admin/settings/'.$dir->module_name(),
165 'title' => t('ldap_addressbook'),
166 'callback' => '_lab_settings',
167 'access' => _ldap_addressbook_allow('admin'),
168 'type' => MENU_NORMAL_ITEM);
169
170 if (arg(2)) {
171
172 // This is used if you click in the 'view' tab on the
173 // 'view/edit/delete' contact display. It is the first to pop up
174 // (default tab) and stays to the left of the tabbed panel. This item
175 // is uncacheable since it might change quite dynamically.
176 $items[] = array('path' => $dir->module_name().'/node/'.arg(2).'/'.arg(3).'/view',
177 'title' => t('view'),
178 'callback' => '_menu_ldap_addressbook_view',
179 'access' => _ldap_addressbook_allow('search'),
180 'type' => MENU_LOCAL_TASK,
181 'weight' => -10);
182
183 // This is used if you click in the 'edit' tab on the
184 // 'view/edit/delete' contact display. It is the second to pop up and
185 // stays in the middle of the tabbed panel. This item is uncacheable
186 // since it might change quite dynamically.
187 $items[] = array('path' => $dir->module_name().'/node/'.arg(2).'/'.arg(3).'/edit',
188 'title' => t('edit'),
189 'callback' => '_menu_ldap_addressbook_edit',
190 'access' => _ldap_addressbook_allow('edit'),
191 'type' => MENU_LOCAL_TASK,
192 'weight' => -5);
193
194 // This is used if you click in the 'delete' tab on the
195 // 'view/edit/delete' contact display. It is the third to pop up and
196 // stays to the right of the tabbed panel. This item is uncacheable
197 // since it might change quite dynamically.
198 $items[] = array('path' => $dir->module_name().'/node/'.arg(2).'/'.arg(3).'/delete',
199 'title' => t('delete'),
200 'callback' => '_menu_ldap_addressbook_delete',
201 'access' => _ldap_addressbook_allow('edit'),
202 'type' => MENU_LOCAL_TASK,
203 'weight' => 0);
204 }
205
206 }
207
208 return $items;
209 }
210
211 /**
212 * Implementation of hook_settings() in an specialized way to be able to catch
213 * the password validation correctly.
214 *
215 * This hook sets-up a form for the user to fill in the default properties of
216 * the LDAP server and the user accounts needed to connect to the addressbook.
217 **/
218 function _lab_settings() {
219 if (!_ldap_addressbook_allow('admin')) drupal_access_denied();
220
221 $dir = new DrupalDirectory();
222
223 $form = array();
224
225 /**
226 * SERVER SETTINGS
227 */
228 $form['server'] = array('#type' => 'fieldset',
229 '#title' => t('Server settings'),
230 '#collapsible' => TRUE,
231 '#collapsed' => TRUE);
232
233 $form['server']['ldap_addressbook_host'] =
234 array('#type' => 'textfield',
235 '#title' => t('Host'),
236 '#default_value' => $dir->host,
237 '#required' => TRUE,
238 '#size' => 30,
239 '#maxlength' => 128,
240 '#description' =>
241 t('The name of the host running the LDAP server.'));
242 $form['server']['ldap_addressbook_port'] =
243 array('#type' => 'textfield',
244 '#title' => t('Port'),
245 '#default_value' => $dir->port,
246 '#required' => TRUE,
247 '#size' => 5,
248 '#maxlength' => 10,
249 '#description' => t('The TCP to use for the server'));
250 $options = array('2' => t('Version 2'), '3' => t('Version 3'));
251 $form['server']['ldap_addressbook_version'] =
252 array('#type' => 'select',
253 '#title' => t('LDAP version'),
254 '#default_value' => $dir->proto,
255 '#options' => $options,
256 '#description' => t('The LDAP protocol version to use.'));
257 // $hash_options = array('clear' => t('clear text'),
258 // 'crypt' => t('crypt'),
259 // 'sha' => t('sha'),
260 // 'ssha' => t('ssha'),
261 // 'md5' => t('md5'),
262 // 'smd5' => t('smd5'));
263 // $form['server']['ldap_addressbook_password_hash'] =
264 // array('#type' => 'select',
265 // '#title' => t('LDAP password hashing'),
266 // '#default_value' => $dir->password_hash(),
267 // '#options' => $hash_options,
268 // '#description' => t('Defines the hash algorithm to be used when storing the passwords on the drupal database. This will <b>not</b> prevent the passwords to be transmitted from your web browser to the server running drupal in clear-text, but after that, all transactions involving the password (namely the connection to the LDAP server) will go on encrypted.'));
269 $form['server']['ldap_addressbook_tmp'] =
270 array('#type' => 'textfield',
271 '#title' => t('Temporary directory'),
272 '#default_value' => $dir->tmp_path(),
273 '#required' => TRUE,
274 '#size' => 60,
275 '#maxlength' => 128,
276 '#after_build' => array('system_check_directory'),
277 '#description' => t('The name of a temporary directory, <b>relative to you drupal installation</b>, where I\'ll temporarily store user jpeg files (a.k.a avatars), if necessary. It is not necessary <b>not</b> to prepend or append slashes (/).'));
278
279 /**
280 * ADDRESSBOOK SETTINGS
281 */
282 $form['addressbook'] = array('#type' => 'fieldset',
283 '#title' => t('Addressbook settings'),
284 '#collapsible' => TRUE,
285 '#collapsed' => TRUE,
286 '#description' => t('These settings control the location and access of the information inside the server.'));
287 $form['addressbook']['ldap_addressbook_base'] =
288 array('#type' => 'textfield',
289 '#title' => t('DN of the addressbook'),
290 '#default_value' => $dir->dir,
291 '#required' => TRUE,
292 '#size' => 60,
293 '#maxlength' => 128,
294 '#description' => t('The base distinguished name of the addressbook'));
295 $ldap_user = $dir->user();
296 $form['addressbook']['ldap_addressbook_user'] =
297 array('#type' => 'textfield',
298 '#title' => t('DN of an authenticated LDAP user'),
299 '#default_value' => $ldap_user->dn,
300 '#required' => TRUE,
301 '#size' => 60,
302 '#maxlength' => 128,
303 '#description' => t('User distinguished name (DN) with read and write access to the addressbook DN'));
304
305 $form['addressbook']['user_pass1'] =
306 array('#type' => 'password', '#default_value' => '',
307 '#size' => 15, '#maxlength' => 30,
308 '#prefix' => '<div class="container-inline">',
309 '#title' => t('User password'));
310 $form['addressbook']['user_pass2'] =
311 array('#type' => 'password', '#default_value' => '',
312 '#size' => 15, '#maxlength' => 30, '#suffix' => '</div>',
313 '#description' => t('Fill in both fields. A blank value does <b>not</b> reset the password.'));
314 $form['addressbook']['user_passwd_reset'] =
315 array('#type' => 'checkbox', '#default_value' => 0,
316 '#title' => t('User password reset'),
317 '#description' => t('Check it to erase the password from the database.'));
318
319 $form['addressbook']['ldap_addressbook_anonymous'] =
320 array('#type' => 'checkbox',
321 '#title' => t('Bind anonymously for read-only operations'),
322 '#default_value' => $dir->read_anonymously(),
323 '#description' => t('If I should try to bind anomymously for read-only operations, check this box. The authenticated user will <b>not</b> be used in this case.'));
324 $form['addressbook']['ldap_addressbook_private_template'] =
325 array('#type' => 'textfield',
326 '#title' => 'User (private) addressbook',
327 '#default_value' => $dir->userbook_template(),
328 '#size' => 60,
329 '#maxlength' => 128,
330 '#description' => t('If the users are allowed to have private addressbooks they can input data that other users cannot see, specify the template string of the DN for these private addressbooks here. The \'%s\' string will be substitued by the user name.'));
331
332 /**
333 * FORMAT SETTINGS
334 */
335 $form['format'] = array('#type' => 'fieldset',
336 '#title' => t('Formatting settings'),
337 '#collapsible' => TRUE,
338 '#collapsed' => TRUE,
339 '#description' => t('These settings control how your contacts are displayed when you conduct searches or specific entry displays.'));
340 $form['format']['ldap_addressbook_fields'] =
341 array('#type' => 'textfield',
342 '#title' => t('Fields of interest'),
343 '#default_value' => implode(' ', $dir->fields()),
344 '#required' => TRUE,
345 '#size' => 80,
346 '#maxlength' => 256,
347 '#description' => t('The list of fields of importance in this addressbook. The individual elements should be separated by <b>spaces</b>. These are the elements that the module will allow you to set or unset in your addressbook.'));
348 $form['format']['ldap_addressbook_summary'] =
349 array('#type' => 'textfield',
350 '#title' => t('Fields for summaries'),
351 '#default_value' => implode(' ', $dir->summary_fields()),
352 '#required' => TRUE,
353 '#size' => 80,
354 '#maxlength' => 256,
355 '#description' => t('The list of fields you want to see on directory summaries where multiple entries are shown at the same time. The individual elements should be separated by <b>spaces</b>. The common use of these fields is when displaying search results with more than 1 entry.'));
356 $form['format']['ldap_addressbook_jpeg_size'] =
357 array('#type' => 'textfield',
358 '#title' => t('Maximum photo size'),
359 '#default_value' => $dir->maximum_jpeg_size(),
360 '#size' => 10,
361 '#maxlength' => 16,
362 '#description' => t('The maximum geometrical size (in pixels) for the jpeg file to be used for user pictures (avatar) in the LDAP addressbook. Larger photos will be rescaled to this value. Smaller photos will be expanded to this size, proportionally.'));
363
364 $form['submit'] =
365 array('#type' => 'submit', '#value' => t('Save configuration'));
366 $form['reset'] =
367 array('#type' => 'submit', '#value' => t('Reset to defaults'));
368 return drupal_get_form('_lab_settings', $form);
369 }
370
371 /**
372 * Validates the administrative settings.
373 *
374 * @param $form_id This form identifier
375 * @param $form_values The values collected on the form
376 */
377 function _lab_settings_validate($form_id, $form_values) {
378 if ($form_values['user_pass1'] != $form_values['user_pass2']) {
379 form_set_error('user_pass1', 'Passwords for the read/write user do not match!');
380 form_set_error('user_pass2');
381 }
382 // else if (!empty($form_values['user_pass1'])) {
383 // //test the hashing
384 // $hash = _lab_hash($form_values['user_pass1'],
385 // $form_values['ldap_addressbook_password_hash']);
386 // if (!$hash) form_set_error('ldap_addressbook_password_hash');
387 // }
388
389 //implement host checking?
390 }
391
392 /**
393 * Submits the administrative settings.
394 *
395 * @param $form_id This form identifier
396 * @param $form_values The values collected on the form
397 */
398 function _lab_settings_submit($form_id, $form_values) {
399 if (!_ldap_addressbook_allow('admin')) drupal_access_denied();
400
401 if ($_POST['op'] == t('Save configuration')) {
402 $dir = new DrupalDirectory();
403 //takes care of most entries in one shot
404 foreach ($form_values as $k => $v) {
405 if (strpos($k, $dir->module_name()) === 0) variable_set($k, $v);
406 }
407 //now let's see the password fields
408 if ($form_values['user_passwd_reset']) {
409 drupal_set_message(t('Reseting read-write user password'));
410 variable_del('ldap_addressbook_user_pass');
411 }
412 if (!empty($form_values['user_pass1']))
413 variable_set('ldap_addressbook_user_pass', $form_values['user_pass1']);
414 drupal_set_message(t('The configuration options have been saved.'));
415 }
416 else if ($_POST['op'] == t('Reset to defaults')) {
417 $dir = new DrupalDirectory();
418 //takes care of most entries in one shot
419 foreach ($form_values as $k => $v)
420 if (strpos($k, $dir->module_name()) === 0) variable_del($k);
421 variable_del('ldap_addressbook_user_pass');
422 drupal_set_message(t('The configuration options have been reset to their default values.'));
423 }
424 else {
425 drupal_set_message(t('I do not recognize operation '.$_POST['op']),
426 'error');
427 drupal_set_message(t('The settings have not been saved because of the errors.'), 'error');
428 return;
429 }
430 return;
431 }
432
433 /**
434 * Implementation of hook_block().
435 *
436 * A simple block that will allow you to search the addressbook
437 *
438 **/
439 function ldap_addressbook_block($op = 'list', $delta = 0) {
440 if ($op == 'list') {
441 $block[0]['info'] = t('Search LDAP addressbook');
442 return $block;
443 }
444 else {
445 if (($op == 'view') && _ldap_addressbook_allow('search')) {
446 switch ($delta) {
447 case 0:
448 $block['subject'] = t('addressbook');
449 $form = array();
450 $form['ldap_search_string'] = array('#type' => 'textfield',
451 '#title' => '',
452 '#default_value' => "",
453 '#size' => 18,
454 '#maxlength' => 128);
455 $form[] = array('#type' => 'submit', '#value' => t('Search'));
456 $form[] = array('#type' => 'submit', '#value' => t('Create'));
457 $block['content'] = drupal_get_form
458 ('_ldap_addressbook_block_search', $form);
459 return $block;
460 }
461 }
462 }
463 return;
464 }
465
466 /**
467 * What to do when the user clicks the submission button
468 **/
469 function _ldap_addressbook_block_search_submit($form_id,
470 $form_values) {
471 $dir = new DrupalDirectory();
472 if ($_POST['op'] == t('Search')) {
473 drupal_goto($dir->module_name().'/search/all/'.
474 $form_values['ldap_search_string']);
475 }
476 else if ($_POST['op'] == t('Create')) {
477 drupal_goto($dir->module_name().'/new');
478 }
479 }
480
481 /**
482 * Remove old jpeg photos in a drupal-visible temporary directory. This cannot
483 * be `/tmp' unless that is mapped to the web server.
484 **/
485 function _ldap_addressbook_remove_garbage() {
486 $dir = new DrupalDirectory();
487 $glob= $dir->tmp_path().'/'.$dir->module_name().'*';
488 foreach (glob($glob) as $filename) unlink($filename);
489 }
490
491 /*
492 * Prints, in an orderly and standardized fashion, the results of a query to
493 * the addressbook. This function is called when the user calls the module root
494 * ('ldap_addressbook') or when executing a query in the form of
495 * ('ldap_addressbook/search/...'). The extra parameters are passed to this
496 * function.
497 *
498 * @param $privacy The default is to search globally. If this variable is set
499 * to either private or global than the search will only happen on that
500 * scope.
501 * @param $what The search term
502 * @param $sort The sorting criteria for the results
503 *
504 * @see DrupalDirectory::search()
505 **/
506 function _menu_ldap_addressbook_search
507 ($privacy="all", $what='*', $sort='cn') {
508
509 if (!_ldap_addressbook_allow('search')) {
510 drupal_access_denied();
511 return;
512 }
513
514 if ($privacy == 'private' && !user_access('Have private LDAP addressbook')) {
515 drupal_access_denied();
516 return;
517 }
518
519 if ($privacy != 'private' && $privacy != 'global' && $privacy != 'all') {
520 drupal_access_denied();
521 return;
522 }
523
524 //@todo remove this call
525 //do the garbage collection first. This might become a problem since we
526 //could be removing images from other users, but...
527 _ldap_addressbook_remove_garbage();
528
529 $dir = new DrupalDirectory();
530 $output = '';
531
532 //if there was something posted, that has preference over the parameters
533 if (isset($_POST['edit']) && isset($_POST['edit']['ldap_search_string'])
534 && ! empty($_POST['edit']['ldap_search_string']))
535 $what = $_POST['ldap_search_string'];
536
537 if ($what != '*') {
538 $output .= t("Searching for") . " $what...<br />";
539
540 //compose a search filter that searches through all relevant fields
541 //configured.
542 $filter = '(|';
543 foreach ($dir->fields() as $field) $filter .= "($field=*$what*)";
544 $filter .= ')';
545 }
546 else {
547 $output .= t("Displaying all entries...<br />");
548 $filter = "";
549 }
550
551 $info = $dir->search($filter, array($sort), $dir->summary_fields(),
552 $privacy);
553
554 if (count($info['global']) == 0 && count($info['private']) == 0)
555 $output = t("Searching $privacy addressbook(s) has found no matching entries found for key `$what'.");
556
557 else if (count($info['global']) == 1 && count($info['private']) == 0) {
558 //redirect to view page!
559 drupal_goto($dir->module_name().'/node/global/'.$info['global'][0]["cn"][0].'/view');
560 }
561
562 else if (count($info['global']) == 0 && count($info['private']) == 1) {
563 //redirect to view page!
564 drupal_goto($dir->module_name().'/node/private/'.$info['private'][0]["cn"][0].'/view');
565 }
566
567 else { //count is >= 1 for both
568 if (count($info['private']) > 0) {
569 $output .= '<h2>Private addressbook contacts</h2>';
570 $output .= _lab_multi_view($info['private'], $dir->summary_fields(),
571 $dir->module_name(), $dir->tmp_path(),
572 _ldap_addressbook_allow('edit'), 'private');
573 }
574 if (count($info['global']) > 0) {
575 $output .= '<h2>Global addressbook contacts</h2>';
576 $output .= _lab_multi_view($info['global'], $dir->summary_fields(),
577 $dir->module_name(), $dir->tmp_path(),
578 _ldap_addressbook_allow('edit'), 'global');
579 }
580 }
581
582 return $output;
583 }
584
585 /**
586 * Present a form for which the user can create a new entry in the LDAP
587 * addressbook.
588 **/
589 function _menu_ldap_addressbook_new() {
590 if (!_ldap_addressbook_allow('edit')) drupal_access_denied();
591
592 $dir = new DrupalDirectory();
593
594 $form = array('#type' => 'fieldset',
595 '#title' => t('new contact'),
596 '#collapsible' => FALSE);
597
598 //All fields are automatically written, except the name fields since this
599 //will compose the CN entry for this new contact.
600 $form['givenname'] = array('#type' => 'textfield',
601 '#title' => _lat('givenname'),
602 '#size' => 40, '#maxlength' => 128,
603 '#required' => TRUE);
604 $form['sn'] = array('#type' => 'textfield',
605 '#title' => _lat('sn'),
606 '#size' => 40, '#maxlength' => 128,
607 '#required' => TRUE);
608
609 $special = array('givenname', 'sn', 'jpegphoto', 'cn');
610
611 foreach ($dir->fields() as $field) {
612 $lfield = strtolower($field);
613 if (in_array($field, $special)) continue;
614 $form["$field"] = array('#type' => 'textfield',
615 '#title' => _lat($field),
616 '#size' => 60, '#maxlength' => 128);
617 }
618 if (in_array('jpegphoto', $dir->fields())) {
619 $form['jpegphoto'] = array('#type' => 'file',
620 '#title' => _lat('jpegphoto'));
621 }
622
623 if ($dir->private_book()) {
624 $form['private'] = array('#type' => 'checkbox',
625 '#title' => t('On private addressbook'),
626 '#description' => t('Check this box to include this new entry in your private addressbook instead of the global one.'));
627 }
628
629 $form[] = array('#type' => 'submit', '#value' => t('Create new contact'));
630 //this function call also defines the official name of this form
631 return drupal_get_form('_ldap_addressbook_new', $form);
632 }
633
634 /**
635 * Validates the new LDAP addressbook entry
636 *
637 * @param $form_id The identifier for this form
638 * @param $form_values The values set by the user
639 **/
640 function _ldap_addressbook_new_validate($form_id, $form_values) {
641 if ($form_values['givenname'] == '') {
642 form_set_error('givenname', t('You must set the first name of the new contact.'));
643 }
644 if ($form_values['sn'] == '') {
645 form_set_error('sn', t('You must set the last name of the new contact.'));
646 }
647 }
648
649 /**
650 * Submits the new LDAP addressbook entry (after validation).
651 *
652 * @param $form_id The identifier for this form
653 * @param $form_values The values set by the user
654 **/
655 function _ldap_addressbook_new_submit($form_id, $form_values) {
656
657 //@todo Remove this call from here. Already have cron job...
658 //do the garbage collection first. This might become a problem since we
659 //could be removing images from other users, but...
660 _ldap_addressbook_remove_garbage();
661
662 $dir = new DrupalDirectory();
663 foreach ($form_values as $k => $v) {
664 //just to avoid extra form fields...
665 if (!in_array($k, $dir->fields()) or $k == '0') continue;
666 if ($k != 'jpegphoto' and empty($v)) continue;
667 //check for jpeg photos, rescale and set
668 if ($k == 'jpegphoto') {
669 if (count($_FILES) != 0) {
670 $jpeg = _ldap_addressbook_jpeg_stream();
671 if (!empty($jpeg)) $info['jpegPhoto'] = $jpeg;
672 }
673 }
674 else $info[$k] = $v;
675 }
676
677 //checks the privacy
678 $privacy = 'global';
679 if (in_array('private', array_keys($form_values)) && $form_values['private']) {
680 $privacy = 'private';
681 }
682
683 if (!$dir->add($info, $privacy)) drupal_goto($dir->module_name()."/new");
684 else {
685 $cn = $info['givenname'].' '.$info['sn'];
686 drupal_set_message(t("Successfuly added LDAP addressbook entry $cn"));
687 drupal_goto($dir->module_name()."/node/$privacy/$cn/view");
688 }
689 return;
690 }
691
692 /**
693 * Present a form for which the user can delete an existing entry in the LDAP
694 * addressbook. If this function is called without any parameters, a listing
695 * with all entries should be presented, together with check boxes for
696 * deleting entries.
697 *
698 * @param $privacy The addressbook at which this entry is. Can be 'private' or
699 * 'global' and is obligatory.
700 * @param $cn The unique common name of the entry you want to delete
701 **/
702 function _menu_ldap_addressbook_delete($privacy=NULL, $cn=NULL) {
703 if (!_ldap_addressbook_allow('edit')) {
704 drupal_access_denied();
705 return;
706 }
707
708 //make sure we are not getting called via a tab entry
709 if (arg(2)) $privacy=arg(2);
710 if (arg(3)) $cn=arg(3);
711
712 if (!$privacy) {
713 drupal_set_message(t('I cannot edit a node without knowing the addressbook you are refering to. Use "global" or "private" as qualifiers to your query. Redirecting to search...'), 'error');
714 drupal_goto($dir->module_name().'/search');
715 }
716
717 if ($privacy == 'private' && !user_access('Have private LDAP addressbook')) {
718 drupal_access_denied();
719 return;
720 }
721
722 if ($privacy != 'global' && $privacy != 'private') {
723 drupal_access_denied();
724 return;
725 }
726
727 if (!$cn) {
728 drupal_set_message(t("No name was given as parameter, redirecting to $privacy search..."), 'error');
729 drupal_goto($dir->module_name()."/search/$privacy");
730 }
731
732 $dir = new DrupalDirectory();
733 $info = $dir->get_one($privacy, $cn);
734 if (!$info) {
735 drupal_set_message('Invalid CN parameter, redirecting to search...');
736 drupal_goto($dir->module_name()."/search/$privacy");
737 }
738
739 //All fields are automatically written, except the name fields since this
740 //will compose the CN entry for this new contact.
741 $output = '';
742 if(array_key_exists('jpegphoto', $info)) {
743 $name_entry = array('data' => '<h2>'.$cn.'</h2>');
744 $imagefilename =
745 _lab_rescale($info['jpegphoto'][0], 50, $tmp_path, $path);
746 if (!$imagefilename) {
747 $output .= '[Corrupted image]';
748 }
749 else {
750 $output .= theme_image($imagefilename, '['.$cn.'\'s photo]',
751 '['.$cn.'\'s photo]');
752 }
753 }
754 $output .= '<h2>Confirm deletion of contact '.$info['cn'][0].'?</h2><br/>';
755 $form = array('#type' => 'fieldset',
756 '#title' => t('Confirm LDAP contact deletion?'),
757 '#collapsible' => FALSE);
758 $form['cn'] = array('#type' => 'hidden', '#value' => $info['cn'][0]);
759 $form['privacy'] = array('#type' => 'hidden', '#value' => $privacy);
760 $form[] = array('#type' => 'submit',
761 '#value' => t('Delete contact'));
762 //this function call also defines the official name of this form
763 $output .= drupal_get_form('_ldap_addressbook_delete', $form);
764 return $output;
765 }
766
767 /**
768 * Submits the new LDAP addressbook entry (after validation)
769 *
770 * @param $form_id The identifier for this form
771 * @param $form_values The values set by the user
772 **/
773 function _ldap_addressbook_delete_submit($form_id, $form_values) {
774 $dir = new DrupalDirectory();
775 $cn = $form_values['cn'];
776 $privacy = $form_values['privacy'];
777 if (!$dir->delete($cn, $privacy)) {
778 drupal_set_message(t('I could not delete the LDAP addressbook entry `'.
779 $cn."'"), 'error');
780 drupal_goto("ldap_addressbook/node/$privacy/$cn/view");
781 }
782 else {
783 drupal_set_message(t('Successfuly deleted LDAP addressbook entry `'.
784 $cn."'"));
785 drupal_goto('ldap_addressbook/search/all/'.$cn);
786 }
787 return;
788 }
789
790 /**
791 * Presents a form for which the user can edit an existing entry in the LDAP
792 * addressbook, based on the cn attribute given as parameter
793 *
794 * @param $privacy The addressbook where the entry to be edited is. Can take
795 * two values: 'global' or 'private'.
796 * @param $cn The unique common name of the entry you want to delete
797 **/
798 function _menu_ldap_addressbook_edit($privacy=NULL, $cn=NULL) {
799 if (!_ldap_addressbook_allow('edit')) {
800 drupal_access_denied();
801 return;
802 }
803
804 //make sure we are not getting called via a tab entry
805 if (arg(2)) $privacy=arg(2);
806 if (arg(3)) $cn=arg(3);
807
808 if (!$privacy) {
809 drupal_set_message(t('I cannot edit a node without knowing the addressbook you are refering to. Use "global" or "private" as qualifiers to your query. Redirecting to search...'), 'error');
810 drupal_goto($dir->module_name().'/search/global');
811 }
812
813 if ($privacy == 'private' && !user_access('Have private LDAP addressbook')) {
814 drupal_access_denied();
815 return;
816 }
817
818 if ($privacy != 'global' && $privacy != 'private') {
819 drupal_access_denied();
820 return;
821 }
822
823 if (!$cn) {
824 drupal_set_message(t('No name was given as parameter, redirecting to search...'), 'error');
825 drupal_goto($dir->module_name()."/search/$privacy");
826 }
827
828 $dir = new DrupalDirectory();
829
830 $info = $dir->get_one($privacy, $cn);
831 if (!info) {
832 drupal_set_message(t("Cannot find a <b>single</b> entry matching '$cn'"),
833 'error');
834 return;
835 }
836
837 //All fields are automatically written, except the name fields since this
838 //will compose the CN entry for this new contact.
839 $form['#attributes'] = array('enctype' => 'multipart/form-data');
840 $form['cn'] = array('#type' => hidden, '#value' => $info['cn'][0]);
841 $form['givenname'] = array('#type' => 'textfield',
842 '#title' => _lat('givenname'),
843 '#default_value' =>
844 $info['givenname'][0],
845 '#size' => 40, '#maxlength' => 128);
846 $form['sn'] = array('#type' => 'textfield',
847 '#title' => _lat('sn'),
848 '#default_value' => $info['sn'][0],
849 '#size' => 40, '#maxlength' => 128);
850 $special = array('givenname', 'sn', 'jpegphoto', 'cn');
851 foreach ($dir->fields() as $field) {
852 $lfield = strtolower($field);
853 if (in_array($field, $special)) continue;
854 $default = '';
855 if (array_key_exists($field, $info))
856 $default = $info[$field][0];
857 if (array_key_exists($lfield, $info))
858 $default = $info[$lfield][0];
859 $form["$field"] = array('#type' => 'textfield',
860 '#title' => _lat($field),
861 '#default_value' => $default,
862 '#size' => 60, '#maxlength' => 128);
863 }
864 if (in_array('jpegphoto', $dir->fields())) {
865 if (!empty($info['jpegphoto'][0])) {
866 $imagefilename =
867 _lab_rescale($info['jpegphoto'][0], 50,
868 $dir->tmp_path(), $dir->module_name());
869 $form['old_image'] = array('#value' => theme_image($imagefilename,
870 t("$cn's photo"),
871 t("$cn's photo")));
872 $form['jpegphoto_reset'] = array('#type' => 'checkbox',
873 '#title' => t('Remove this photo from the addressbook'),
874 '#default_value' => 0);
875 }
876 $form['jpegphoto'] = array('#type' => 'file',
877 '#title' => _lat('jpegphoto'));
878 }
879
880 $form[] = array('#type' => 'submit', '#value' => t('Submit changes'));
881 //this function call also defines the official name of this form
882 return drupal_get_form('_ldap_addressbook_edit', $form);
883 }
884
885 /**
886 * Validates the new LDAP addressbook entry
887 *
888 * @param $form_id The identifier for this form
889 * @param $form_values The values set by the user
890 **/
891 function _ldap_addressbook_edit_validate($form_id, $form_values) {
892 if ($form_values['givenname'] == '') {
893 form_set_error('', t('You must set the first name of the new contact.'));
894 }
895 if ($form_values['sn'] == '') {
896 form_set_error('', t('You must set the last name of the new contact.'));
897 }
898 }
899
900 /**
901 * Implements the hook_cron().
902 **/
903 function ldap_addressbook_cron() {
904 //do the garbage collection first. This might become a problem since we
905 //could be removing images from other users, but...
906 _ldap_addressbook_remove_garbage();
907 }
908
909 /**
910 * Prepares a stream to upload a jpeg into the LDAP server
911 *
912 * @param $field The name of the form field that contained the entry for the
913 * file.
914 **/
915 function _ldap_addressbook_jpeg_stream ($field='edit') {
916 $dir = new DrupalDirectory();
917 $upfile = current($_FILES[$field]['tmp_name']);
918 $jpeg_to_ldap = _lab_rescale_file($upfile, $dir->maximum_jpeg_size(),
919 $dir->tmp_path(), $dir->module_name());
920 if (!$jpeg_to_ldap) return FALSE;
921 //trigger_error('jpeg was rescaled and sits at '.$jpeg_to_ldap);
922 unlink($upfile); //delete old upload
923 $jpeg_file = fopen($jpeg_to_ldap, 'rb');
924 $jpeg_stream = fread($jpeg_file, filesize($jpeg_to_ldap));
925 fclose($jpeg_file);
926 unlink($jpeg_to_ldap); //delete rescaled jpeg
927 return $jpeg_stream;
928 }
929
930 /**
931 * Submits the new LDAP addressbook entry (after validation)
932 *
933 * @param $form_id The identifier for this form
934 * @param $form_values The values set by the user
935 **/
936 function _ldap_addressbook_edit_submit($form_id, $form_values) {
937 $dir = new DrupalDirectory();
938 $cn = $form_values['cn'];
939 $newcn = $form_values['givenname'].' '.$form_values['sn'];
940 $info = $dir->get_one($cn); //pre-populate
941
942 //just to safe guard us
943 if (!isset($form_values['jpegphoto_reset']))
944 $form_values['jpegphoto_reset'] = 0;
945
946 foreach ($form_values as $k => $v) {
947 //just to avoid extra form fields...
948 if ((! in_array($k, $dir->fields())) or $k == '0') continue;
949 if ($k != 'jpegphoto') {
950 if (empty($v)) $info[$k] = array();
951 else $info[$k] = $v;
952 }
953 else {
954 if (count($_FILES) != 0 && !$form_values['jpegphoto_reset']) {
955 $jpeg = _ldap_addressbook_jpeg_stream();
956 if (!empty($jpeg)) $info['jpegphoto'] = $jpeg;
957 }
958 }
959 }
960 //check the jpeg photo reset
961 if ($form_values['jpegphoto_reset']) $info['jpegphoto'] = array();
962
963 //unset the object class
964 unset($info['objectclass']);
965 if (!$dir->modify($info)) drupal_goto($dir->module_name()."/node/$cn/edit");
966 drupal_goto($dir->module_name()."/node/$newcn/view");
967 }
968
969 /**
970 * Present a table at which the user can view an existing entry in the LDAP
971 * addressbook, based on the cn attribute given as parameter
972 *
973 * @param $privacy The default is to search globally. If this variable is set
974 * to either private or global than the search will only happen on that
975 * scope.
976 * @param $cn The unique common name of the entry you want to delete
977 **/
978 function _menu_ldap_addressbook_view($privacy=NULL, $cn=NULL) {
979 if (!_ldap_addressbook_allow('search')) {
980 drupal_access_denied();
981 return;
982 }
983
984 //@todo Remove this call
985 //do the garbage collection first. This might become a problem since we
986 //could be removing images from other users, but...
987 _ldap_addressbook_remove_garbage();
988
989 //make sure we are not getting called via a tab entry
990 if (arg(2)) $privacy=arg(2);
991 if (arg(3)) $cn=arg(3);
992
993 if (!$privacy) {
994 drupal_set_message(t('I cannot display a node without knowing the addressbook you are refering to. Use "global" or "private" as qualifiers to your query. Redirecting to search...'), 'error');
995 drupal_goto($dir->module_name().'/search/global');
996 }
997
998 if ($privacy == 'private' && !user_access('Have private LDAP addressbook')) {
999 drupal_access_denied();
1000 return;
1001 }
1002
1003 if ($privacy != 'global' && $privacy != 'private') {
1004 drupal_access_denied();
1005 return;
1006 }
1007
1008 if (!$cn) {
1009 drupal_set_message(t('No name was given as parameter, redirecting to search...'), 'error');
1010 drupal_goto($dir->module_name()."/search/$privacy");
1011 }
1012
1013 $dir = new DrupalDirectory();
1014 $info = $dir->get_one($privacy, $cn);
1015 if (! $info) {
1016 drupal_set_message(t("No entry with CN=$cn was found in $privacy context"));
1017 drupal_goto('');
1018 }
1019 return _lab_view($info, $dir->fields(),
1020 $dir->module_name(), $dir->tmp_path());
1021 }
1022
1023 ?>

  ViewVC Help
Powered by ViewVC 1.1.2