Projet

Général

Profil

Paste
Télécharger (47 ko) Statistiques
| Branche: | Révision:

root / htmltest / sites / all / modules / ldap / ldap_user / ldap_user.module @ dd54aff9

1
<?php
2

    
3
/**
4
 * @file
5
 * Module for the LDAP User Entity
6
 *
7
 */
8

    
9
define('LDAP_USER_DRUPAL_HELP_URL', 'http://drupal.org/node/997082');
10

    
11
// configurable drupal acct provision triggers
12
define('LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE', 1);
13
define('LDAP_USER_DRUPAL_USER_PROV_ON_AUTHENTICATE', 2);
14
define('LDAP_USER_DRUPAL_USER_PROV_ON_ALLOW_MANUAL_CREATE', 3);
15

    
16
// configurable ldap entry provision triggers
17
define('LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE', 6);
18
define('LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE', 7);
19
define('LDAP_USER_LDAP_ENTRY_DELETE_ON_USER_DELETE', 8);
20

    
21
// provisioning events (events are triggered by triggers)
22
define('LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER', 1);
23
define('LDAP_USER_EVENT_CREATE_DRUPAL_USER', 2);
24
define('LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY', 3);
25
define('LDAP_USER_EVENT_CREATE_LDAP_ENTRY', 4);
26
define('LDAP_USER_EVENT_LDAP_ASSOCIATE_DRUPAL_ACCT', 5);
27

    
28
// results of ldap entry provisioning
29
define('LDAP_USER_PROVISION_LDAP_ENTRY_EXISTS', 1);
30
define('LDAP_USER_PROVISION_LDAP_ENTRY_CREATE_FAILED', 2);
31
define('LDAP_USER_PROVISION_LDAP_ENTRY_SYNCH_FAILED', 3);
32

    
33
// options for what to do when existing non ldap associated Drupal account conflicts with ldap account
34
define('LDAP_USER_CONFLICT_LOG', 1);
35
define('LDAP_USER_CONFLICT_RESOLVE', 2);
36
define('LDAP_USER_CONFLICT_RESOLVE_DEFAULT', 2);
37

    
38
// options for dealing with manual account creation that conflict with ldap entries
39
define('LDAP_USER_MANUAL_ACCT_CONFLICT_REJECT', 1);
40
define('LDAP_USER_MANUAL_ACCT_CONFLICT_LDAP_ASSOCIATE', 2);
41
define('LDAP_USER_MANUAL_ACCT_CONFLICT_SHOW_OPTION_ON_FORM', 3);
42
define('LDAP_USER_MANUAL_ACCT_CONFLICT_NO_LDAP_ASSOCIATE', 4);
43

    
44
// options for account creation behavior
45
define('LDAP_USER_ACCT_CREATION_LDAP_BEHAVIOR', 4);
46
define('LDAP_USER_ACCT_CREATION_USER_SETTINGS_FOR_LDAP', 1);
47
define('LDAP_USER_ACCT_CREATION_LDAP_BEHAVIOR_DEFAULT', 4);
48

    
49
// provision directions
50
define('LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER', 1);
51
define('LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY', 2);
52
define('LDAP_USER_PROV_DIRECTION_NONE', 3);
53
define('LDAP_USER_PROV_DIRECTION_ALL', 4);
54

    
55
define('LDAP_USER_PROV_RESULT_NO_ERROR', 0);
56
define('LDAP_USER_PROV_RESULT_NO_PWD', 1);
57
define('LDAP_USER_PROV_RESULT_BAD_PARAMS', 2);
58

    
59
define('LDAP_USER_NO_SERVER_SID', 0); // need to avoid conflicting with server ids
60
define('LDAP_USER_TEST_FORM_PATH', 'admin/config/people/ldap/user/test');
61
define('LDAP_USER_WS_USER_PATH', 'ldap/user/ws');
62

    
63
// Machine name for the setting to provision from last authentication server.
64
define('LDAP_USER_AUTH_SERVER_SID', 'ldap_last_authserv');
65
define('LDAP_USER_SESSION_PROV_SID', 'ldap_user_session_prov_sid');
66

    
67
/**
68
 * Implements hook_menu().
69
 */
70
function ldap_user_menu() {
71
  $items = array();
72

    
73
  $items['admin/config/people/ldap/user'] = array(
74
    'title' => '3. User',
75
    'description' => 'Settings related to user provisioning and data synching between ldap and drupal users.',
76
    'page callback' => 'drupal_get_form',
77
    'page arguments' => array('ldap_user_admin_form'),
78
    'access arguments' => array('administer site configuration'),
79
    'type' => MENU_LOCAL_TASK,
80
    'weight' => 2,
81
    'file' => 'ldap_user.admin.inc',
82
  );
83

    
84
  $items[LDAP_USER_TEST_FORM_PATH] = array(
85
    'title' => 'Test LDAP User Functionality for a given user.',
86
    'description' => '',
87
    'page callback' => 'drupal_get_form',
88
    'page arguments' => array('ldap_user_test_form'),
89
    'access arguments' => array('administer site configuration'),
90
    'file' => 'ldap_user.test_form.inc',
91
    'type' => MENU_LOCAL_ACTION,
92
  );
93

    
94
 // $ws_arg_start = count(explode('/', LDAP_USER_WS_USER_PATH));
95
// $items[LDAP_USER_WS_USER_PATH] = array(
96
//   'title' => 'Webservice Path',
97
 //   'page callback' => 'ldap_user_ws',
98
 //   'page arguments' => array($ws_arg_start, $ws_arg_start + 1, $ws_arg_start + 2, $ws_arg_start + 3),
99
 //   'access arguments' => array('view content'),
100
 //   'file' => 'ldap_user.ws.inc',
101
 // );
102

    
103
  return $items;
104
}
105

    
106
/**
107
 * function ldap_user_ws_urls_item_list() {
108
  module_load_include('inc', 'ldap_user', 'ldap_user.ws');
109
  return _ldap_user_ws_urls_item_list();
110
}
111
*/
112

    
113
/**
114
 * Implements hook_init().
115
 */
116
function ldap_user_init() {
117
  ldap_user_ldap_provision_semaphore(NULL, NULL, NULL, TRUE); // reset for simpletest page load behavior
118
}
119

    
120
/**
121
 * Implements hook_theme().
122
 */
123
function ldap_user_theme() {
124
  return array('ldap_user_conf_form' => array(
125
    'render element' => 'form',
126
    'file' => 'ldap_user.theme.inc'
127
    ),
128
  );
129
}
130

    
131
/**
132
 * Implements hook_cron().
133
 */
134
function ldap_user_cron() {
135
  $ldap_user_conf = ldap_user_conf();
136
  if ($ldap_user_conf->orphanedDrupalAcctBehavior != 'ldap_user_orphan_do_not_check') {
137
    module_load_include('inc', 'ldap_user', 'ldap_user.cron');
138
    $result = _ldap_user_orphans($ldap_user_conf);
139
    if ($result !== TRUE) {
140
      watchdog('ldap_user', 'LDAP User check for orphaned ldap provisioned Drupal accounts failed', array(), WATCHDOG_ERROR);
141
    }
142
  }
143
}
144

    
145
/**
146
 * Implements hook_mail().
147
 */
148
function ldap_user_mail($key, &$message, $params) {
149
  switch ($key) {
150
    case 'orphaned_accounts':
151
      $message['subject'] =  variable_get('site_name') . ' ' . t('Orphaned LDAP Users');
152
      $message['body'][] =  t('The following !count Drupal users no longer have
153
        corresponding LDAP Entries.  Perhaps they have been removed from the LDAP
154
        and should be removed:', array('!count' => count($params['accounts'])))
155
        . "\n\n" . t('username,mail,edit url') . "\n" .
156
        join("\n", $params['accounts']);
157
      break;
158
  }
159
}
160

    
161

    
162
/**
163
 * Implements hook_ldap_derived_user_name_alter().
164
 */
165
function ldap_user_ldap_derived_user_name_alter(&$name, $ldap_user) {
166
   // alter $name in some way here
167

    
168
}
169

    
170

    
171
function ldap_user_conf_cache_clear() {
172
  $discard = ldap_user_conf('admin', TRUE);
173
  $discard = ldap_user_conf(NULL, TRUE);
174
  ldap_user_ldap_provision_semaphore(NULL, NULL, NULL, TRUE);
175
}
176

    
177
/**
178
 * get ldapUserConf or ldapUserConfAdmin object
179
 *
180
 * @param enum $type is 'admin' for ldapUserConfAdmin object or NULL for ldapUserConf object
181
 * @param boolean $resect clear static cache of object.
182
 *
183
 * @return object ldapUserConf or ldapUserConfAdmin object
184
 */
185
function ldap_user_conf($type = NULL, $reset = FALSE) {
186
  static $ldap_user_conf;
187
  static $ldap_user_conf_admin;
188

    
189
  if ($type == 'admin' && ($reset || !is_object($ldap_user_conf_admin))) {
190
    ldap_servers_module_load_include('php', 'ldap_user', 'LdapUserConfAdmin.class');
191
    $ldap_user_conf_admin = new LdapUserConfAdmin();
192
  }
193
  elseif ($type != 'admin' && ($reset || !is_object($ldap_user_conf))) {
194
    ldap_servers_module_load_include('php', 'ldap_user', 'LdapUserConf.class');
195
    $ldap_user_conf = new LdapUserConf();
196
  }
197

    
198
  return ($type == 'admin') ? $ldap_user_conf_admin : $ldap_user_conf;
199
}
200

    
201

    
202
/**
203
 * Implements hook_ldap_attributes_needed_alter().
204
 */
205
function ldap_user_ldap_attributes_needed_alter(&$attributes, $params) {
206

    
207
  if (isset($params['sid']) && $params['sid']) { // puid attributes are server specific
208
    if (is_scalar($params['sid'])) {
209
      $ldap_server = ldap_servers_get_servers($params['sid'], 'enabled', TRUE);
210
    }
211
    else {
212
      $ldap_server = $params['sid'];
213
    }
214

    
215
    if ($ldap_server === FALSE) { // failed to find enabled server
216
      return;
217
    }
218

    
219
    $ldap_user_conf = ldap_user_conf();
220
    if (!isset($attributes['dn'])) {
221
      $attributes['dn'] = array();
222
    }
223
    $attributes['dn'] = ldap_servers_set_attribute_map($attributes['dn']); // force dn "attribute" to exist
224
    switch ($params['ldap_context']) { // Add the attributes required by the user configuration when provisioning drupal users
225
      case 'ldap_user_insert_drupal_user':
226
      case 'ldap_user_update_drupal_user':
227
      case 'ldap_user_ldap_associate':
228
        $attributes[$ldap_server->user_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->user_attr]); // array($ldap_server->user_attr, 0, NULL);
229
        $attributes[$ldap_server->mail_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->mail_attr]);
230
        $attributes[$ldap_server->picture_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->picture_attr]);
231
        $attributes[$ldap_server->unique_persistent_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->unique_persistent_attr]);
232
        if ($ldap_server->mail_template) {
233
          ldap_servers_token_extract_attributes($attributes,  $ldap_server->mail_template);
234
        }
235
      break;
236
    }
237

    
238
    $ldap_context = empty($params['ldap_context']) ? NULL : $params['ldap_context'];
239
    $direction = empty($params['direction']) ? $ldap_user_conf->ldapContextToProvDirection($ldap_context) : $params['direction'];
240
    $attributes_required_by_user_module_mappings = $ldap_user_conf->getLdapUserRequiredAttributes($direction, $ldap_context);
241
    $attributes = array_merge($attributes_required_by_user_module_mappings, $attributes);
242

    
243
  }
244
}
245

    
246
/**
247
 * Implements hook_ldap_user_attrs_list_alter().
248
 */
249
function ldap_user_ldap_user_attrs_list_alter(&$available_user_attrs, &$params) {
250

    
251
  $sid = (isset($params['ldap_server']) && is_object($params['ldap_server'])) ? $params['ldap_server']->sid : LDAP_USER_NO_SERVER_SID;
252

    
253
  $ldap_user_conf = $params['ldap_user_conf'];
254
  $direction = isset($params['direction']) ? $params['direction'] : LDAP_USER_PROV_DIRECTION_NONE;
255

    
256
  if ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
257
    $available_user_attrs['[property.name]'] =  array(
258
      'name' => 'Property: Username',
259
      'source' => '',
260
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
261
      'enabled' => TRUE,
262
      'prov_events' => array(LDAP_USER_EVENT_CREATE_LDAP_ENTRY, LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY),
263
      'config_module' => 'ldap_user',
264
      'prov_module' => 'ldap_user',
265
      'configurable_to_ldap' => TRUE,
266
      );
267

    
268
    $available_user_attrs['[property.mail]'] =  array(
269
      'name' => 'Property: Email',
270
      'source' => '',
271
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
272
      'enabled' => TRUE,
273
      'prov_events' => array(LDAP_USER_EVENT_CREATE_LDAP_ENTRY, LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY),
274
      'config_module' => 'ldap_user',
275
      'prov_module' => 'ldap_user',
276
      'configurable_to_ldap' => TRUE,
277
    );
278

    
279
    $available_user_attrs['[property.picture]'] =  array(
280
      'name' => 'Property: picture',
281
      'source' => '',
282
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
283
      'enabled' => TRUE,
284
      'prov_events' => array(LDAP_USER_EVENT_CREATE_LDAP_ENTRY, LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY),
285
      'config_module' => 'ldap_user',
286
      'prov_module' => 'ldap_user',
287
      'configurable_to_ldap' => TRUE,
288
    );
289

    
290
    $available_user_attrs['[property.uid]'] =  array(
291
      'name' => 'Property: Drupal User Id (uid)',
292
      'source' => '',
293
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
294
      'enabled' => TRUE,
295
      'prov_events' => array(LDAP_USER_EVENT_CREATE_LDAP_ENTRY, LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY),
296
      'config_module' => 'ldap_user',
297
      'prov_module' => 'ldap_user',
298
      'configurable_to_ldap' => TRUE,
299
    );
300

    
301
  }
302

    
303
  // 1. Drupal user properties
304
  // 1.a make sure empty array are present so array + function works
305
  foreach (array('property.status', 'property.timezone', 'property.signature') as $i => $property_id) {
306
    $property_token = '[' . $property_id . ']';
307
    if (!isset($available_user_attrs[$property_token]) || !is_array($available_user_attrs[$property_token])) {
308
      $available_user_attrs[$property_token] = array();
309
    }
310
  }
311
  //@todo make these merges so they don't override saved values such as 'enabled'
312
  $available_user_attrs['[property.status]'] = $available_user_attrs['[property.status]'] + array(
313
    'name' => 'Property: Acount Status',
314
    'configurable_to_drupal' => 1,
315
    'configurable_to_ldap' => 1,
316
    'user_tokens' => '1=enabled, 0=blocked.',
317
    'enabled' => FALSE,
318
    'config_module' => 'ldap_user',
319
    'prov_module' => 'ldap_user',
320
  );
321

    
322
  $available_user_attrs['[property.timezone]'] = $available_user_attrs['[property.timezone]'] + array(
323
    'name' => 'Property: User Timezone',
324
    'configurable_to_drupal' => 1,
325
    'configurable_to_ldap' => 1,
326
    'enabled' => FALSE,
327
    'config_module' => 'ldap_user',
328
    'prov_module' => 'ldap_user',
329
  );
330

    
331
  $available_user_attrs['[property.signature]'] = $available_user_attrs['[property.signature]'] + array(
332
    'name' => 'Property: User Signature',
333
    'configurable_to_drupal' => 1,
334
    'configurable_to_ldap' => 1,
335
    'enabled' => FALSE,
336
    'config_module' => 'ldap_user',
337
    'prov_module' => 'ldap_user',
338
  );
339

    
340
  // 2. Drupal user fields
341
  $user_fields = field_info_instances('user', 'user');
342
  foreach ($user_fields as $field_name => $field_instance) {
343
    $field_id = "[field.$field_name]";
344
    if (!isset($available_user_attrs[$field_id]) || !is_array($available_user_attrs[$field_id])) {
345
      $available_user_attrs[$field_id] = array();
346
    }
347

    
348
    $available_user_attrs[$field_id] = $available_user_attrs[$field_id] + array(
349
      'name' => t('Field') . ': ' . $field_instance['label'],
350
      'configurable_to_drupal' => 1,
351
      'configurable_to_ldap' => 1,
352
      'enabled' => FALSE,
353
      'config_module' => 'ldap_user',
354
      'prov_module' => 'ldap_user',
355
    );
356
  }
357

    
358

    
359
  if (!$ldap_user_conf->provisionsDrupalAccountsFromLdap) {
360
    $available_user_attrs['[property.mail]']['config_module'] = 'ldap_user';
361
    $available_user_attrs['[property.name]']['config_module'] = 'ldap_user';
362
    $available_user_attrs['[property.picture]']['config_module'] = 'ldap_user';
363
  }
364

    
365
  if ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
366
    $available_user_attrs['[password.random]'] =  array(
367
      'name' => 'Pwd: Random',
368
      'source' => '',
369
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
370
      'enabled' => TRUE,
371
      'prov_events' => array(LDAP_USER_EVENT_CREATE_LDAP_ENTRY, LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY),
372
      'config_module' => 'ldap_user',
373
      'prov_module' => 'ldap_user',
374
      'configurable_to_ldap' => TRUE,
375
    );
376

    
377
    // use user password when available fall back to random pwd
378
    $available_user_attrs['[password.user-random]'] =  array(
379
      'name' => 'Pwd: User or Random',
380
      'source' => '',
381
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
382
      'enabled' => TRUE,
383
      'prov_events' => array(LDAP_USER_EVENT_CREATE_LDAP_ENTRY, LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY),
384
      'config_module' => 'ldap_user',
385
      'prov_module' => 'ldap_user',
386
      'configurable_to_ldap' => TRUE,
387
    );
388

    
389
    // use user password, do not modify if unavailable
390
    $available_user_attrs['[password.user-only]'] = array(
391
        'name' => 'Pwd: User Only',
392
        'source' => '',
393
        'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
394
        'enabled' => TRUE,
395
        'prov_events' => array(LDAP_USER_EVENT_CREATE_LDAP_ENTRY, LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY),
396
        'config_module' => 'ldap_user',
397
        'prov_module' => 'ldap_user',
398
        'configurable_to_ldap' => TRUE,
399
      );
400

    
401
  }
402

    
403
  //this is where need to be added to arrays
404
  if (!empty($ldap_user_conf->ldapUserSynchMappings[$direction])) {
405

    
406
    foreach ($ldap_user_conf->ldapUserSynchMappings[$direction] as $target_token => $mapping) {
407
      if ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER && isset($mapping['user_attr'])) {
408
        $key = $mapping['user_attr'];
409
      }
410
      elseif ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY && isset($mapping['ldap_attr'])) {
411
        $key = $mapping['ldap_attr'];
412
      }
413
      else {
414
        continue;
415
      }
416

    
417
      foreach (array('ldap_attr', 'user_attr', 'convert', 'direction', 'enabled', 'prov_events') as $k) {
418
        if (isset($mapping[$k])) {
419
          $available_user_attrs[$key][$k] = $mapping[$k];
420
        }
421
        else {
422
          $available_user_attrs[$key][$k] = NULL;
423
        }
424
        $available_user_attrs[$key]['config_module'] = 'ldap_user';
425
        $available_user_attrs[$key]['prov_module'] = 'ldap_user';
426
      }
427
      if ($mapping['user_attr'] == 'user_tokens') {
428
        $available_user_attrs['user_attr'] = $mapping['user_tokens'];
429
      }
430

    
431
    }
432

    
433
  }
434

    
435
   // 3. profile2 fields
436
  // 4. $user->data array.   will need to be added manually.  perhaps better not to implement this at all?
437

    
438

    
439
}
440
/**
441
 * Implements hook_help().
442
 */
443

    
444
function ldap_user_help($path, $arg) {
445

    
446
  $ldap_user_help = t('LDAP user configuration determines how and when
447
    Drupal accounts are created based on LDAP data and which user fields
448
    are derived and synched to and from LDAP. See !helplink.',
449
    array(
450
      '!helplink' => l(LDAP_USER_DRUPAL_HELP_URL, LDAP_USER_DRUPAL_HELP_URL),
451
    ));
452

    
453
  switch ($path) {
454
    case 'admin/config/people/ldap/user':
455
      $output = '<p>' . $ldap_user_help . '</p>';
456
      return $output;
457

    
458
    case 'admin/help#ldap_user':
459
      $output = '<p>' . $ldap_user_help . '</p>';
460
      return $output;
461
  }
462
}
463

    
464

    
465
/**
466
 * Implements hook_form_FORM_ID_alter(). for user_login_block
467
 */
468
function ldap_user_form_user_login_block_alter(&$form, &$form_state) {
469
  array_unshift($form['#validate'], 'ldap_user_grab_password_validate');
470
}
471

    
472
/**
473
 * Implements hook_form_FORM_ID_alter(). for user_login_form
474
 */
475
function ldap_user_form_user_login_alter(&$form, $form_state) {
476
  array_unshift($form['#validate'], 'ldap_user_grab_password_validate');
477
}
478

    
479
/**
480
 * Implements hook_form_FORM_ID_alter(). for user_register_form
481
 */
482
function ldap_user_form_user_profile_form_alter(&$form, $form_state) {
483
  array_unshift($form['#submit'], 'ldap_user_grab_password_validate');
484
}
485

    
486
/**
487
* Implements hook_form_FORM_ID_alter(). for password_policy_password_tab
488
*/
489
function ldap_user_form_password_policy_password_tab_alter(&$form, &$form_state) {
490
  array_unshift($form['#validate'], 'ldap_user_grab_password_validate');
491
}
492

    
493
/**
494
 * store password from logon forms in ldap_user_ldap_provision_pwd static variable
495
 * for use in provisioning to ldap
496
 */
497
function ldap_user_grab_password_validate($form, &$form_state) {
498

    
499
   // This is not a login form but profile form and user is inserting password to update email
500
  if (!empty($form_state['values']['current_pass_required_values'])) {
501
    if (!empty($form_state['values']['current_pass']) && empty($form_state['values']['pass'])) {
502
      ldap_user_ldap_provision_pwd('set', $form_state['values']['current_pass']);
503
    }
504
    // Or this is a profile form where the user is updating their own password
505
    elseif (!empty($form_state['values']['pass'])) {
506
        ldap_user_ldap_provision_pwd('set', $form_state['values']['pass']);
507
    }
508
  }
509
  // otherwise a logon form
510
  elseif (!empty($form_state['values']['pass'])) {
511
    ldap_user_ldap_provision_pwd('set', $form_state['values']['pass']);
512
  }
513

    
514
}
515

    
516

    
517

    
518

    
519
/**
520
 * Implements hook_form_FORM_ID_alter(). for user_register_form
521
 */
522
function ldap_user_form_user_register_form_alter(&$form, $form_state) {
523

    
524
  array_unshift($form['#submit'], 'ldap_user_grab_password_validate');
525

    
526
  if (!user_access('administer users')) {
527
    return;
528
  }
529
  $ldap_user_conf = ldap_user_conf();
530
  if ($ldap_user_conf->disableAdminPasswordField == TRUE) {
531
    $form['account']['pass']['#required'] = FALSE;
532
    $form['account']['pass']['#disabled'] = TRUE;
533
    $form['account']['pass']['#value'] = user_password(20);
534
    $form['account']['pass']['#description'] = t('An LDAP setting at /admin/config/people/ldap/user has disabled the password fields. Drupal will store a 20 character random password in the Drupal "users" table, and the user will login with their LDAP password.');
535
  }
536

    
537
  $ldap_fieldset = array();
538
  $options = array(
539
    LDAP_USER_MANUAL_ACCT_CONFLICT_LDAP_ASSOCIATE => t('Make this an LDAP Associated account.  If a related LDAP account can not be found, a validation error will appear and the account will not be created.'),
540
    LDAP_USER_MANUAL_ACCT_CONFLICT_NO_LDAP_ASSOCIATE => t('Do not make this an LDAP Associated account.'),
541
  );
542
  $ldap_fieldset['ldap_user_association'] = array(
543
    '#type' => 'radios',
544
    '#options' => $options,
545
    '#required' => FALSE,
546
    '#title' => t('LDAP Entry Association.'),
547
  );
548

    
549
  if ($ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE)) {
550
    $ldap_fieldset['ldap_user_association']['#disabled'] = TRUE;
551
    $ldap_fieldset['ldap_user_association']['#description'] =  t('Since "Create
552
      or Synch to Drupal user anytime a Drupal user account is created or updated"
553
      is selected at admin/config/people/ldap/user, this option will have no
554
      effect so its disabled.');
555
  }
556
  elseif ($ldap_user_conf->manualAccountConflict != LDAP_USER_MANUAL_ACCT_CONFLICT_SHOW_OPTION_ON_FORM) {
557
    $ldap_fieldset['ldap_user_association']['#disabled'] = TRUE;
558
    $ldap_fieldset['ldap_user_association']['#description'] =  t('To enable
559
      this an LDAP server must be selected for provisioning to Drupal in
560
      admin/config/people/ldap/user and "Show option on user create form..." must be selected.');
561
  }
562

    
563
  $ldap_fieldset['ldap_user_create_ldap_acct'] = array(
564
    '#type' => 'checkbox',
565
    '#title' => t('Create corresponding LDAP entry.'),
566
  );
567
  if (!$ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_DRUPAL_USER_PROV_ON_ALLOW_MANUAL_CREATE)) {
568
    $ldap_fieldset['ldap_user_create_ldap_acct']['#disabled'] = TRUE;
569
    $ldap_fieldset['ldap_user_create_ldap_acct']['#description'] = t('To enable
570
      this an LDAP server must be selected for provisioning to Drupal in
571
      admin/config/people/ldap/user and manual creation of LDAP accounts
572
      must be enabled also.');
573
  }
574

    
575
  if (count($ldap_fieldset) > 0) {
576
    $form['ldap_user_fields'] = $ldap_fieldset;
577
    $form['ldap_user_fields']['#type'] = 'fieldset';
578
    $form['ldap_user_fields']['#title'] =  t('LDAP Options');
579
    $form['ldap_user_fields']['#collapsible'] =  TRUE;
580
    $form['ldap_user_fields']['#collapsed'] =  FALSE;
581
  }
582

    
583
  $form['#validate'][] = 'ldap_user_form_register_form_validate';
584
  $form['#submit'][] = 'ldap_user_form_register_form_submit2';
585

    
586
}
587

    
588

    
589
function ldap_user_form_register_form_validate($form, &$form_state) {
590

    
591
  $values = $form_state['values'];
592
  $user_ldap_entry = NULL;
593
  $drupal_username = $form_state['values']['name'];
594

    
595
  if ($values['ldap_user_association'] == LDAP_USER_MANUAL_ACCT_CONFLICT_NO_LDAP_ASSOCIATE) {
596
    $form_state['values']['ldap_user_ldap_exclude']['und'][0]['value'] = 1;
597
  }
598

    
599
  // if corresponding ldap account doesn't exist and provision not selected and make ldap associated is selected, throw error
600
  if (!@$values['ldap_user_create_ldap_acct'] && @$values['ldap_user_association'] == LDAP_USER_MANUAL_ACCT_CONFLICT_LDAP_ASSOCIATE) {
601
    $ldap_user_conf = ldap_user_conf();
602
    $ldap_user = ldap_servers_get_user_ldap_data($drupal_username, $ldap_user_conf->ldapEntryProvisionServer, 'ldap_user_prov_to_drupal');
603
    if (!$ldap_user) {
604

    
605
      form_set_error('ldap_user_association', t('User %name does not have a corresponding LDAP Entry (dn).
606
        Under LDAP options, you may NOT select "Make this an LDAP Associated Account"', array('%name' => $drupal_username)));
607
    }
608
  }
609

    
610
  // if trying to provision and ldap account and one already exists, throw error.
611
  if (@$values['ldap_user_create_ldap_acct']) {
612
    $ldap_user_conf = ldap_user_conf();
613
    $ldap_user = ldap_servers_get_user_ldap_data($drupal_username, $ldap_user_conf->ldapEntryProvisionServer, 'ldap_user_prov_to_ldap');
614
    if ($ldap_user) {
615
      $tokens = array('%dn' => $ldap_user['dn'], '%name' => $drupal_username);
616
      form_set_error('ldap_user_create_ldap_acct', t('User %name already has a corresponding LDAP Entry (%dn).
617
        Uncheck "Create corresponding LDAP entry" to allow this Drupal user to be created.  Select
618
        "Make this an LDAP associated account" to associate this account with the ldap entry.', $tokens));
619
    }
620
  }
621
}
622

    
623

    
624
/** called after user_register_form_submit **/
625
function ldap_user_form_register_form_submit2($form, &$form_state) {
626

    
627
  $values = $form_state['values'];
628
  $ldap_user_association_set = FALSE;
629

    
630
  if (@$values['ldap_user_create_ldap_acct']) {
631
    if ($account = user_load_by_name($values['name'])) {
632
      $ldap_user_conf = ldap_user_conf();
633
      $ldap_provision_entry = $ldap_user_conf->getProvisionRelatedLdapEntry($account);
634
      if (!$ldap_provision_entry) {
635
        $provision_result = $ldap_user_conf->provisionLdapEntry($account);
636
      }
637
      else {
638
        $ldap_user_association_set = TRUE;
639
      }
640
    }
641
    else {
642
      // don't do anything here.  If account is not created, other user module warnings will exist
643
    }
644
  }
645

    
646
  if ($ldap_user_association_set || @$values['ldap_user_association'] == LDAP_USER_MANUAL_ACCT_CONFLICT_LDAP_ASSOCIATE) {
647
    $ldap_user_conf = ldap_user_conf();
648
    $ldap_user_conf->ldapAssociateDrupalAccount($form_state['values']['name']);
649
  }
650

    
651
}
652

    
653
/**
654
 * @param stdClass $account as drupal user object
655
 * @param array $edit is a drupal user edit array
656
 * @param enum int $direction indicating which directions to test for association
657
 *
658
 *
659
 * @return boolean TRUE if user should be excluded from ldap provision/synching
660
 */
661

    
662
function ldap_user_ldap_exclude($account = NULL, $edit = NULL, $direction = LDAP_USER_PROV_DIRECTION_ALL) {
663
  // always exclude user 1
664
  if (is_object($account) && isset($account->uid) && $account->uid == 1) {
665
    return TRUE;
666
  }
667

    
668
  // exclude users who have the field ldap_user_ldap_exclude set to 1
669
  if (is_object($account) && isset($account->ldap_user_ldap_exclude['und'][0]['value'])
670
    && $account->ldap_user_ldap_exclude[LANGUAGE_NONE][0]['value'] == 1) {
671
    return TRUE;
672
  }
673

    
674
  // exclude new users who have the value set to 1 in their $edit array
675
  if (is_array($edit) && isset($edit['ldap_user_ldap_exclude']['und'][0]['value'])
676
    && $edit['ldap_user_ldap_exclude'][LANGUAGE_NONE][0]['value'] == 1) {
677
    return TRUE;
678
  }
679

    
680
  // everyone else is fine
681
  return FALSE;
682

    
683
}
684

    
685
/**
686
 * @param stdClass $account as drupal user object
687
 * @param enum int $direction indicating which directions to test for association
688
 *   LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER signifies test if drupal account has been provisioned or synched from ldap
689
 *   LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY signifies test if ldap account has been provisioned or synched from drupal
690
 *   NULL signifies check for either direction
691
 *
692
 * @return boolean if user is ldap associated
693
 */
694

    
695
function ldap_user_is_ldap_associated($account, $direction = NULL) {
696

    
697
  $to_drupal_user = FALSE;
698
  $to_ldap_entry = FALSE;
699

    
700
  if ($direction === NULL || $direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) {
701

    
702
    if (property_exists($account, 'ldap_user_current_dn') && !empty($account->ldap_user_current_dn['und'][0]['value'])) {
703
      $to_drupal_user = TRUE;
704
    }
705
    elseif (isset($account->uid)) {
706
      $authname = ldap_user_get_authname($account->uid);
707
      $to_drupal_user = (boolean)$authname;
708
    }
709
  }
710

    
711
  if ($direction === NULL || $direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
712
    if (property_exists($account, 'ldap_user_prov_entries') && !empty($account->ldap_user_prov_entries['und'][0]['value'])) {
713
      $to_ldap_entry = TRUE;
714
    }
715
  }
716

    
717
  if ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) {
718
    return $to_drupal_user;
719
  }
720
  elseif ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
721
    return $to_ldap_entry;
722
  }
723
  else {
724
    return ($to_ldap_entry || $to_drupal_user);
725
  }
726

    
727

    
728

    
729

    
730
}
731
/**
732
 * api function for synching
733
 * note: does no checking if synching is enabled or configured for a given context
734
 */
735

    
736
function ldap_user_synch_to_drupal($username, $prov_event = LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER, $ldap_user = NULL) {
737

    
738
  $ldap_user_conf = ldap_user_conf();
739
  $account = user_load_by_name($username);
740
  $user_edit = array();
741
  $ldap_user_conf->synchToDrupalAccount($account, $user_edit, $prov_event, $ldap_user, TRUE);
742

    
743
}
744

    
745
/**
746
 * api function for ldap associated user provisioning
747
 * note: does no checking if synching is enabled or configured for a given context
748
 */
749
function ldap_user_provision_to_drupal($ldap_user, $user_edit = array()) {
750

    
751
  $sid = $ldap_user['sid'];
752
  $ldap_user_conf = ldap_user_conf();
753
  $account = NULL;
754
  $ldap_user_conf->provisionDrupalAccount($account, $user_edit, $ldap_user, TRUE);
755

    
756
}
757

    
758

    
759
/**
760
 * function to:
761
 *   -- store user entered password during pageload
762
 *   and protect unencrypted user password from other modules
763
 *
764
 *   @param enum string $action 'get' | 'set'
765
 *   @param string | FALE $value as user entered password
766
 */
767

    
768

    
769
function ldap_user_ldap_provision_pwd($action, $value = NULL, $reset = FALSE) {
770

    
771
  //$calling_function = FALSE;
772
  //if (function_exists('debug_backtrace') && $backtrace = debug_backtrace()) { //   {
773
  //  $calling_function = $backtrace[1]['function'];
774
  //}
775

    
776
  static $current_user_pass;
777

    
778
  if ($reset) {
779
    $current_user_pass = NULL;
780
  }
781

    
782
  if ($action == 'set') {
783
    $current_user_pass = $value;
784
  }
785
  elseif ($action == 'get' && $current_user_pass) {
786
       // && (!$calling_function || $calling_function == 'ldap_servers_token_tokenize_user_account')
787
    return $current_user_pass;
788
  }
789
  else {
790
    return FALSE;
791
  }
792

    
793
}
794

    
795

    
796

    
797
/**
798
 * function to avoid multiple synch or provision in same page load (if desired)
799
 *
800
 *   @param enum string $action 'synch' | 'provision' | 'set_page_load_key' | NULL
801
 *   @param enum string $op = 'set' or 'get'
802
 *   @value mixed value associate with $op.
803
 */
804

    
805

    
806
function ldap_user_ldap_provision_semaphore($action, $op, $value = NULL, $reset = FALSE) {
807

    
808
  $calling_function = FALSE;
809
  if (function_exists('debug_backtrace') && $backtrace = debug_backtrace()) { //   {
810
    $calling_function = $backtrace[1]['function'];
811
  }
812

    
813
  static $ldap_accts;
814
  static $intialized;
815

    
816
  if ($reset || !$intialized) {
817
    $ldap_accts = array();
818
    $intialized = TRUE;
819
  }
820

    
821
   // mark that the given drupal user has had ldap entry synched or provisioned on this page load.
822
  if ($op == 'set') {
823
    if ($action && $value) {
824
      $ldap_accts[$action][$value] = TRUE;
825
    }
826
    return;
827
  }
828

    
829
  // has the given drupal user x action (synch or provision) been executed.
830
  if ($op == 'get') {
831
    if ($action && $value && isset($ldap_accts[$action][$value])) {
832
      return $ldap_accts[$action][$value];
833
    }
834
    else {
835
      return FALSE;
836
    }
837
  }
838

    
839
}
840

    
841

    
842
/**
843
 * Implements hook_user_login().
844
 */
845
function ldap_user_user_login(&$edit, $account) {
846

    
847
  if (ldap_user_ldap_exclude($account, $edit)) {
848
    return;
849
  }
850
  $ldap_user_conf = ldap_user_conf();
851
  $user_edit = array();
852

    
853
  ldap_user_reset_provision_server($ldap_user_conf, $account);
854

    
855
   // provision or synch to ldap, not both
856
  $provision_result = array('status' => 'none');
857

    
858
   // provision to ldap
859
  // if ($account->access == 0 && $account->login != 0) {} check for first time user
860
  if (
861
      $ldap_user_conf->provisionsLdapEntriesFromDrupalUsers
862
      && ldap_user_ldap_provision_semaphore('provision', 'get', $account->name) === FALSE
863
      && !$ldap_user_conf->getProvisionRelatedLdapEntry($account)
864
      && $ldap_user_conf->ldapEntryProvisionServer
865
      && $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE)
866
      ) {
867
    $provision_result = $ldap_user_conf->provisionLdapEntry($account);
868
    if ($provision_result['status'] == 'success') {
869
      ldap_user_ldap_provision_semaphore('provision', 'set', $account->name);
870
    }
871
  }
872
  // don't synch if just provisioned
873
  if (
874
    $ldap_user_conf->provisionsLdapEntriesFromDrupalUsers
875
    && ldap_user_ldap_provision_semaphore('synch', 'get' , $account->name) === FALSE
876
    && $provision_result['status'] != 'success'
877
    && $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE)
878
    ) {
879
    $bool_result = $ldap_user_conf->synchToLdapEntry($account, $user_edit);
880
    if ($bool_result) {
881
      ldap_user_ldap_provision_semaphore('synch', 'set', $account->name);
882
    }
883
  }
884

    
885
  $prov_enabled = $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE);
886

    
887
  // Provision from LDAP if a new account was not just provisioned from LDAP
888
  if (ldap_user_ldap_provision_semaphore('drupal_created', 'get', $account->name) === FALSE) {
889
    if ($ldap_user_conf->provisionsDrupalAccountsFromLdap && in_array(LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER, array_keys($ldap_user_conf->provisionsDrupalEvents))) {
890
      $ldap_user = ldap_servers_get_user_ldap_data($account->name, $ldap_user_conf->drupalAcctProvisionServer, 'ldap_user_prov_to_drupal');
891
      if ($ldap_user) {
892
        $ldap_server = ldap_servers_get_servers($ldap_user_conf->drupalAcctProvisionServer, NULL, TRUE);
893
        $ldap_user_conf->entryToUserEdit($ldap_user, $user_edit, $ldap_server, LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, array(LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER));
894
        if (empty($account->picture->fid)) { // see #1973352 and #935592
895
          $account2 = user_load($account->uid);
896
          $account->picture = $account2->picture;
897
        }
898
        $account = user_save($account, $user_edit, 'ldap_user');
899
      }
900
    }
901
  }
902

    
903
}
904

    
905

    
906
/**
907
 * Implements hook_user_insert().
908
 *
909
 */
910
function ldap_user_user_insert(&$user_edit, $account, $category) {
911

    
912
  global $user;
913
  $not_associated = ldap_user_ldap_exclude($account, $user_edit);
914
  $new_account_request = (boolean)($user->uid == 0 && $account->access == 0 && $account->login == 0); // check for first time user
915
  $already_provisioned_to_ldap = ldap_user_ldap_provision_semaphore('provision', 'get' , $account->name);
916
  $already_synched_to_ldap = ldap_user_ldap_provision_semaphore('synch', 'user_action_query' , $account->name);
917
  if ($not_associated || $already_synched_to_ldap || $already_synched_to_ldap || $new_account_request) {
918
    return;
919
  }
920

    
921
  $ldap_user_conf = ldap_user_conf();
922
  /**
923
   * in hook_user_insert, account is already created, so never call provisionDrupalAccount(), just
924
   * synchToDrupalAccount(), even if action is 'provision'
925
   */
926
  $empty_user_edit = array();
927
  if ($account->status && $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE)) {
928
    $ldap_user_conf->synchToDrupalAccount($account, $empty_user_edit, LDAP_USER_EVENT_CREATE_DRUPAL_USER, NULL, TRUE);
929
  }
930

    
931
  if ($ldap_user_conf->provisionsLdapEntriesFromDrupalUsers) {
932
    $prov_enabled = $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE);
933
    if ($prov_enabled) {
934
      $ldap_provision_entry = $ldap_user_conf->getProvisionRelatedLdapEntry($account);
935
      if (!$ldap_provision_entry) {
936
        $provision_result = $ldap_user_conf->provisionLdapEntry($account);
937
        if ($provision_result['status'] == 'success') {
938
          ldap_user_ldap_provision_semaphore('provision', 'set', $account->name);
939
        }
940
       }
941
      elseif ($ldap_provision_entry) {
942
        $bool_result = $ldap_user_conf->synchToLdapEntry($account, $user_edit);
943
        if ($bool_result) {
944
          ldap_user_ldap_provision_semaphore('synch', 'set', $account->name);
945
        }
946
      }
947
    }
948
  }
949
}
950

    
951
/**
952
 * Implements hook_user_update()
953
 */
954

    
955
function ldap_user_user_update(&$user_edit, $account, $category) {
956
  //debug("ldap_user_user_update, category=$category"); debug($user_edit); debug($account); // ldap_user_user_insert, category='. $category . 'account->status = ' . $account->status);
957
  if (ldap_user_ldap_exclude($account, $user_edit)) {
958
    return;
959
  }
960

    
961
  $ldap_user_conf = ldap_user_conf();
962
  // check for provisioning to LDAP; this will normally occur on hook_user_insert or other event when drupal user is created.
963
  if ($ldap_user_conf->provisionsLdapEntriesFromDrupalUsers &&
964
      $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE)) {
965

    
966
    $already_provisioned_to_ldap = ldap_user_ldap_provision_semaphore('provision', 'get' , $account->name);
967
    $already_synched_to_ldap = ldap_user_ldap_provision_semaphore('synch', 'get' , $account->name);
968
    if ($already_provisioned_to_ldap || $already_synched_to_ldap) {
969
      return;
970
    }
971

    
972
    $provision_result = array('status' => 'none');
973
    // always check if provisioning to ldap has already occurred this page load
974
    $ldap_entry = $ldap_user_conf->getProvisionRelatedLdapEntry($account);
975
    if (!$ldap_entry) { //{
976
      $provision_result = $ldap_user_conf->provisionLdapEntry($account);
977
      if ($provision_result['status'] == 'success') {
978
        ldap_user_ldap_provision_semaphore('provision', 'set', $account->name);
979
      }
980
    }
981
    // synch if not just provisioned and enabled
982
    if ($provision_result['status'] != 'success' ) {
983
      // always check if provisioing to ldap has already occurred this page load
984
      $provision_enabled = $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE);
985
      $ldap_entry = $ldap_user_conf->getProvisionRelatedLdapEntry($account);
986
      if ($provision_enabled && $ldap_entry) {
987
        $bool_result = $ldap_user_conf->synchToLdapEntry($account, $user_edit);
988
        if ($bool_result) {
989
          ldap_user_ldap_provision_semaphore('synch', 'set', $account->name);
990
        }
991
      }
992
    }
993
  }
994

    
995
}
996

    
997
 /**
998
 * Implements hook_user_presave()
999
 */
1000

    
1001
function ldap_user_user_presave(&$user_edit, $account, $category) {
1002
 //debug("ldap_user_user_presave, category=$category"); debug($user_edit); debug($account); // ldap_user_user_insert, category='. $category . 'account->status = ' . $account->status);
1003

    
1004
  if (ldap_user_ldap_exclude($account, $user_edit)) {
1005
    return;
1006
  }
1007
  if (isset($account->name)) {
1008
    $drupal_username = $account->name;
1009
  }
1010
  elseif (!empty($user_edit['name'])) {
1011
    $drupal_username = $user_edit['name'];
1012
  }
1013
  else {
1014
    return;
1015
  }
1016
  $ldap_user_conf = ldap_user_conf();
1017

    
1018
  ldap_user_reset_provision_server($ldap_user_conf, $account);
1019

    
1020
  // check for provisioning to drupal and override synched user fields/props
1021
  // Provision from LDAP if a new account was not just provisioned from LDAP
1022
  if (ldap_user_ldap_provision_semaphore('drupal_created', 'get', $drupal_username) === FALSE) {
1023
    if ($ldap_user_conf->provisionsDrupalAccountsFromLdap && in_array(LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER, array_keys($ldap_user_conf->provisionsDrupalEvents))) {
1024
      if ($ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE)) {
1025
        if (ldap_user_is_ldap_associated($account, LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER)) {
1026
          $ldap_user = ldap_servers_get_user_ldap_data($drupal_username, $ldap_user_conf->drupalAcctProvisionServer, 'ldap_user_prov_to_drupal');
1027
          $ldap_server = ldap_servers_get_servers($ldap_user_conf->drupalAcctProvisionServer, NULL, TRUE);
1028
          $ldap_user_conf->entryToUserEdit($ldap_user, $user_edit, $ldap_server, LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, array(LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER));
1029
        }
1030
      }
1031
    }
1032
  }
1033

    
1034
}
1035

    
1036
/**
1037
 * Implements hook_user_delete().
1038
 */
1039
function ldap_user_user_delete($account) {
1040
  // drupal user account is about to be deleted.
1041
  $ldap_user_conf = ldap_user_conf();
1042
  if (
1043
      $ldap_user_conf->provisionsLdapEntriesFromDrupalUsers
1044
      && $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_DELETE_ON_USER_DELETE)
1045
      ) {
1046
    $boolean_result = $ldap_user_conf->deleteProvisionedLdapEntries($account);
1047
    // no need to watchdog here, because fail in deleteProvisionedLdapEntries provides watchdog entry
1048
  }
1049
}
1050

    
1051

    
1052

    
1053
/**
1054
 * @return default value for field user->ldap_user_provisioned_sid
1055
 */
1056
function ldap_user_provisioned_sid_default($entity_type, $entity, $field, $instance, $langcode) {
1057
  return NULL;
1058
}
1059

    
1060
/**
1061
 * @return default value for field user->ldap_user_provisioned_sid
1062
 */
1063
function ldap_user_puid_default($entity_type, $entity, $field, $instance, $langcode) {
1064
  return NULL;
1065
}
1066
/**
1067
 * @return default value for field user->ldap_user_puid
1068
 */
1069
function ldap_user_puid_property_default($entity_type, $entity, $field, $instance, $langcode) {
1070
  return NULL;
1071
}
1072
/**
1073
 * @return default value for field user->ldap_user_dn
1074
 */
1075
function ldap_user_dn_default($entity_type, $entity, $field, $instance, $langcode) {
1076
  return NULL;
1077
}
1078

    
1079
/**
1080
 * Implements hook_field_widget_info().
1081
 * to provide field type for LDAP fields
1082
 */
1083
function ldap_user_field_widget_info() {
1084
  return array(
1085
    'ldap_user_hidden' => array(
1086
      'label' => t('Hidden Text Field'),
1087
      'field types' => array('text'),
1088
      'settings' => array(),
1089
    ),
1090
  );
1091
}
1092

    
1093
/**
1094
 * Implements hook_field_widget_settings_form().
1095
 */
1096
function ldap_user_field_widget_settings_form($field, $instance) {
1097
  return array();
1098
}
1099

    
1100
/**
1101
 * Implements hook_field_widget_form().
1102
 */
1103
function ldap_user_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
1104

    
1105
  $main_widget = array();
1106

    
1107
  switch ($instance['widget']['type']) {
1108
    case 'ldap_user_hidden':
1109
      $element['value'] = $element + array(
1110
        '#type' => 'hidden',
1111
        '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
1112
      );
1113
      break;
1114
  }
1115

    
1116
  return $element;
1117
}
1118

    
1119
function ldap_user_synch_triggers_key_values() {
1120

    
1121
  return array(
1122
    LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE => t('On synch to Drupal user create or update. Requires a server with binding method of "Service Account Bind" or "Anonymous Bind".'),
1123
    LDAP_USER_DRUPAL_USER_PROV_ON_AUTHENTICATE => t('On create or synch to Drupal user when successfully authenticated with LDAP credentials. (Requires LDAP Authentication module).'),
1124
    LDAP_USER_DRUPAL_USER_PROV_ON_ALLOW_MANUAL_CREATE => t('On manual creation of Drupal user from admin/people/create and "Create corresponding LDAP entry" is checked'),
1125
    LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE => t('On creation or synch of an LDAP entry when a Drupal account is created or updated. Only applied to accounts with a status of approved.'),
1126
    LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE => t('On creation or synch of an LDAP entry when a user authenticates.'),
1127
    LDAP_USER_LDAP_ENTRY_DELETE_ON_USER_DELETE => t('On deletion of an LDAP entry when the corresponding Drupal Account is deleted.  This only applies when the LDAP entry was provisioned by Drupal by the LDAP User module.'),
1128
  );
1129

    
1130
}
1131

    
1132
function ldap_user_all_events() {
1133
  return array(
1134
    LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER,
1135
    LDAP_USER_EVENT_CREATE_DRUPAL_USER,
1136
    LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY,
1137
    LDAP_USER_EVENT_CREATE_LDAP_ENTRY,
1138
    LDAP_USER_EVENT_LDAP_ASSOCIATE_DRUPAL_ACCT,
1139
  );
1140

    
1141
}
1142

    
1143
/**
1144
 * @param array $account
1145
 * @param string $text
1146
 * @return string text with tokens replaced
1147
 */
1148

    
1149
function ldap_user_token_replace($token, $account, $entity = NULL) {
1150
  $desired_tokens = ldap_servers_token_tokens_needed_for_template($token);
1151
  $tokens = ldap_user_token_tokenize_entry($account, $desired_tokens, LDAP_SERVERS_TOKEN_PRE, LDAP_SERVERS_TOKEN_POST, $entity);
1152
  $result = str_replace(array_keys($tokens), array_values($tokens), $token);
1153
  return $result;
1154
}
1155

    
1156

    
1157

    
1158
/**
1159
 * Turn an ldap entry into a token array suitable for the t() function
1160
 * @param drupal user object $account
1161
 * @param array $token_keys as list of token/value pairs to generate
1162
 * @param string prefix token prefix such as !,%,[
1163
 * @param string suffix token suffix such as ]
1164
 *
1165
 * @return token array suitable for t() functions of with lowercase keys as exemplified below
1166
 */
1167
function ldap_user_token_tokenize_entry($account, $token_keys, $pre = LDAP_SERVERS_TOKEN_PRE, $post = LDAP_SERVERS_TOKEN_POST, $user_entity = NULL) {
1168

    
1169
  $detailed_watchdog_log = variable_get('ldap_help_watchdog_detail', 0);
1170
  $tokens = array();
1171
  if (!$user_entity) {
1172
    list($discard, $user_entity) = ldap_user_load_user_acct_and_entity($account->uid, 'uid');
1173
  }
1174

    
1175
  foreach ($token_keys as $token_key) {
1176
    // target id is of form field.lname, property.mail, field.dept:0, etc.
1177
    list($type, $attr_ordinal) = explode('.', $token_key);
1178
    $parts = explode(':', $attr_ordinal);
1179
    $attr = $parts[0];
1180
    $ordinal = (count($parts) > 1) ? $parts[1] : 0;
1181
    $token = $pre . $token_key . $post;
1182
    switch ($type) {
1183

    
1184
      case 'field':
1185
        if (isset( $user_entity->{$attr}['und'][$ordinal]['value'])) {
1186
          $tokens[$token] = $user_entity->{$attr}['und'][$ordinal]['value'];
1187
        }
1188
      break;
1189

    
1190

    
1191
      case 'property':
1192
        if (property_exists($account, $attr)) {
1193
          $tokens[$token] = $account->{$attr};
1194
        }
1195
      break;
1196

    
1197
      // @todo: 3. tokenize profile 2
1198
    }
1199

    
1200
  }
1201

    
1202
  return $tokens;
1203
}
1204

    
1205
  /**
1206
   * load user $account and $entity, given uid or $username
1207
   *
1208
   * @param string $user_id is username or uid
1209
   * @param enum $user_id_type is 'username' or 'uid'
1210
   *
1211
   * return array $account and $user_entity
1212
   */
1213

    
1214
  function ldap_user_load_user_acct_and_entity($user_id, $user_id_type = 'username') {
1215

    
1216
    if ($user_id_type == 'username') {
1217
      $account = user_load_by_name($user_id);
1218
    }
1219
    else {
1220
      $account = user_load($user_id);
1221
    }
1222
    if ($account) {
1223
      $user_entities = entity_load('user', array($account->uid));
1224
      $user_entity = $user_entities[$account->uid];
1225
    }
1226
    else {
1227
      $user_entity = NULL;
1228
    }
1229

    
1230
    return array($account, $user_entity);
1231

    
1232
  }
1233

    
1234
/**
1235
 * Implements hook_ldap_servers_username_to_ldapname_alter
1236
 * - Set ldap name to auth name
1237
 */
1238
function ldap_user_ldap_servers_username_to_ldapname_alter(&$ldap_username, $drupal_username, $context) {
1239
  // Alter the name only if it has not been altered already, ie php eval code
1240
  if ($ldap_username == $drupal_username) {
1241
    $authname = ldap_user_get_authname($ldap_username);
1242
    if (!empty($authname)) {
1243
      $ldap_username = $authname;
1244
    }
1245
  }
1246
}
1247

    
1248
/**
1249
 * Returns LDAP authname from the authmap table for a variant input
1250
 *
1251
 * @param $data
1252
 *   A variant input. Allowed variable types:
1253
 *   - object: user account object
1254
 *   - integer: user id
1255
 *   - string: username
1256
 */
1257
function ldap_user_get_authname($data) {
1258
  $cache = &drupal_static(__FUNCTION__, array());
1259

    
1260
  $authname = NULL;
1261
  $uid = NULL;
1262

    
1263
  if (is_object($data)) {
1264
    // Object - set uid if object has uid and uid > 0
1265
    if (!empty($data->uid)) {
1266
      $uid = $data->uid;
1267
    }
1268
  }
1269
  elseif (is_numeric($data) && intval($data) == $data) {
1270
    // Integer - set uid number is an integer > 0
1271
    if ($data > 0) {
1272
      $uid = $data;
1273
    }
1274
  }
1275
  elseif (is_string($data)) {
1276
    // String - load account and set uid if uid > 0
1277
    $account = user_load_by_name($data);
1278
    if (!empty($account->uid)) {
1279
      $uid = $account->uid;
1280
    }
1281
  }
1282

    
1283
  // Exit if no uid found
1284
  if (empty($uid)) {
1285
    return NULL;
1286
  }
1287

    
1288
  // Run query if uid is not statically cached
1289
  if (!array_key_exists($uid, $cache)) {
1290
    $authname = db_query('SELECT authname FROM {authmap} WHERE uid = :uid AND module = :module', array(
1291
      ':uid' => $uid,
1292
      ':module' => 'ldap_user',
1293
    ))->fetchField();
1294

    
1295
    $cache[$uid] = !empty($authname) ? $authname : NULL;
1296
  }
1297

    
1298
  return $cache[$uid];
1299
}
1300

    
1301
/**
1302
 * Resets the drupalAcctProvisionServer if needed.
1303
 *
1304
 * Used when handling multi-domain authentication to set the provisioning
1305
 * server to be the server that last successfully authenticated the user.
1306
 *
1307
 * @param LdapUserConf $ldap_user_conf
1308
 *   The LDAP User Configuration object.
1309
 *
1310
 * @param object $account
1311
 *   The Drupal user account.
1312
 */
1313
function ldap_user_reset_provision_server($ldap_user_conf, $account) {
1314
  // Reset the Provision Server sid to the server that last authenticated the user.
1315
  if ($ldap_user_conf->drupalAcctProvisionServer == LDAP_USER_AUTH_SERVER_SID) {
1316
    $sid = FALSE;
1317
    if (isset($account->data['ldap_user']['init']['sid'])) {
1318
      $sid = $account->data['ldap_user']['init']['sid'];
1319
    }
1320
    else {
1321
      // Provisioning Server sid is not in the account object,
1322
      // see if we have a session variable with it.
1323
      $sid = isset($_SESSION[LDAP_USER_SESSION_PROV_SID]) ? $_SESSION[LDAP_USER_SESSION_PROV_SID] : FALSE;
1324
    }
1325
    if ($sid) {
1326
      $ldap_user_conf->drupalAcctProvisionServer = $sid;
1327
    }
1328
  }
1329
}