Projet

Général

Profil

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

root / drupal7 / sites / all / modules / ldap / ldap_user / ldap_user.module @ be58a50c

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
      case 'all':
229
        $attributes[$ldap_server->user_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->user_attr]); // array($ldap_server->user_attr, 0, NULL);
230
        $attributes[$ldap_server->mail_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->mail_attr]);
231
        if ($ldap_server->picture_attr) {
232
          $attributes[$ldap_server->picture_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->picture_attr]);
233
        }
234
        if ($ldap_server->unique_persistent_attr) {
235
          $attributes[$ldap_server->unique_persistent_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->unique_persistent_attr]);
236
        }
237
        if ($ldap_server->mail_template) {
238
          ldap_servers_token_extract_attributes($attributes,  $ldap_server->mail_template);
239
        }
240
      break;
241
    }
242

    
243
    $ldap_context = empty($params['ldap_context']) ? NULL : $params['ldap_context'];
244
    $direction = empty($params['direction']) ? $ldap_user_conf->ldapContextToProvDirection($ldap_context) : $params['direction'];
245
    $attributes_required_by_user_module_mappings = $ldap_user_conf->getLdapUserRequiredAttributes($direction, $ldap_context);
246
    $attributes = array_merge($attributes_required_by_user_module_mappings, $attributes);
247

    
248
  }
249
}
250

    
251
/**
252
 * Implements hook_ldap_user_attrs_list_alter().
253
 */
254
function ldap_user_ldap_user_attrs_list_alter(&$available_user_attrs, &$params) {
255

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

    
258
  $ldap_user_conf = $params['ldap_user_conf'];
259
  $direction = isset($params['direction']) ? $params['direction'] : LDAP_USER_PROV_DIRECTION_NONE;
260

    
261
  if ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
262
    $available_user_attrs['[property.name]'] =  array(
263
      'name' => 'Property: Username',
264
      'source' => '',
265
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
266
      'enabled' => TRUE,
267
      'prov_events' => array(LDAP_USER_EVENT_CREATE_LDAP_ENTRY, LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY),
268
      'config_module' => 'ldap_user',
269
      'prov_module' => 'ldap_user',
270
      'configurable_to_ldap' => TRUE,
271
      );
272

    
273
    $available_user_attrs['[property.mail]'] =  array(
274
      'name' => 'Property: Email',
275
      'source' => '',
276
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
277
      'enabled' => TRUE,
278
      'prov_events' => array(LDAP_USER_EVENT_CREATE_LDAP_ENTRY, LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY),
279
      'config_module' => 'ldap_user',
280
      'prov_module' => 'ldap_user',
281
      'configurable_to_ldap' => TRUE,
282
    );
283

    
284
    $available_user_attrs['[property.picture]'] =  array(
285
      'name' => 'Property: picture',
286
      'source' => '',
287
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
288
      'enabled' => TRUE,
289
      'prov_events' => array(LDAP_USER_EVENT_CREATE_LDAP_ENTRY, LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY),
290
      'config_module' => 'ldap_user',
291
      'prov_module' => 'ldap_user',
292
      'configurable_to_ldap' => TRUE,
293
    );
294

    
295
    $available_user_attrs['[property.uid]'] =  array(
296
      'name' => 'Property: Drupal User Id (uid)',
297
      'source' => '',
298
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
299
      'enabled' => TRUE,
300
      'prov_events' => array(LDAP_USER_EVENT_CREATE_LDAP_ENTRY, LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY),
301
      'config_module' => 'ldap_user',
302
      'prov_module' => 'ldap_user',
303
      'configurable_to_ldap' => TRUE,
304
    );
305

    
306
  }
307

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

    
327
  $available_user_attrs['[property.timezone]'] = $available_user_attrs['[property.timezone]'] + array(
328
    'name' => 'Property: User Timezone',
329
    'configurable_to_drupal' => 1,
330
    'configurable_to_ldap' => 1,
331
    'enabled' => FALSE,
332
    'config_module' => 'ldap_user',
333
    'prov_module' => 'ldap_user',
334
  );
335

    
336
  $available_user_attrs['[property.signature]'] = $available_user_attrs['[property.signature]'] + array(
337
    'name' => 'Property: User Signature',
338
    'configurable_to_drupal' => 1,
339
    'configurable_to_ldap' => 1,
340
    'enabled' => FALSE,
341
    'config_module' => 'ldap_user',
342
    'prov_module' => 'ldap_user',
343
  );
344

    
345
  // 2. Drupal user fields
346
  $user_fields = field_info_instances('user', 'user');
347
  foreach ($user_fields as $field_name => $field_instance) {
348
    $field_id = "[field.$field_name]";
349
    if (!isset($available_user_attrs[$field_id]) || !is_array($available_user_attrs[$field_id])) {
350
      $available_user_attrs[$field_id] = array();
351
    }
352

    
353
    $available_user_attrs[$field_id] = $available_user_attrs[$field_id] + array(
354
      'name' => t('Field') . ': ' . $field_instance['label'],
355
      'configurable_to_drupal' => 1,
356
      'configurable_to_ldap' => 1,
357
      'enabled' => FALSE,
358
      'config_module' => 'ldap_user',
359
      'prov_module' => 'ldap_user',
360
    );
361
  }
362

    
363

    
364
  if (!$ldap_user_conf->provisionsDrupalAccountsFromLdap) {
365
    $available_user_attrs['[property.mail]']['config_module'] = 'ldap_user';
366
    $available_user_attrs['[property.name]']['config_module'] = 'ldap_user';
367
    $available_user_attrs['[property.picture]']['config_module'] = 'ldap_user';
368
  }
369

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

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

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

    
406
  }
407

    
408
  //this is where need to be added to arrays
409
  if (!empty($ldap_user_conf->ldapUserSynchMappings[$direction])) {
410

    
411
    foreach ($ldap_user_conf->ldapUserSynchMappings[$direction] as $target_token => $mapping) {
412
      if ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER && isset($mapping['user_attr'])) {
413
        $key = $mapping['user_attr'];
414
      }
415
      elseif ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY && isset($mapping['ldap_attr'])) {
416
        $key = $mapping['ldap_attr'];
417
      }
418
      else {
419
        continue;
420
      }
421

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

    
436
    }
437

    
438
  }
439

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

    
443

    
444
}
445
/**
446
 * Implements hook_help().
447
 */
448

    
449
function ldap_user_help($path, $arg) {
450

    
451
  $ldap_user_help = t('LDAP user configuration determines how and when
452
    Drupal accounts are created based on LDAP data and which user fields
453
    are derived and synched to and from LDAP. See !helplink.',
454
    array(
455
      '!helplink' => l(LDAP_USER_DRUPAL_HELP_URL, LDAP_USER_DRUPAL_HELP_URL),
456
    ));
457

    
458
  switch ($path) {
459
    case 'admin/config/people/ldap/user':
460
      $output = '<p>' . $ldap_user_help . '</p>';
461
      return $output;
462

    
463
    case 'admin/help#ldap_user':
464
      $output = '<p>' . $ldap_user_help . '</p>';
465
      return $output;
466
  }
467
}
468

    
469

    
470
/**
471
 * Implements hook_form_FORM_ID_alter(). for user_login_block
472
 */
473
function ldap_user_form_user_login_block_alter(&$form, &$form_state) {
474
  array_unshift($form['#validate'], 'ldap_user_grab_password_validate');
475
}
476

    
477
/**
478
 * Implements hook_form_FORM_ID_alter(). for user_login_form
479
 */
480
function ldap_user_form_user_login_alter(&$form, $form_state) {
481
  array_unshift($form['#validate'], 'ldap_user_grab_password_validate');
482
}
483

    
484
/**
485
 * Implements hook_form_FORM_ID_alter(). for user_register_form
486
 */
487
function ldap_user_form_user_profile_form_alter(&$form, $form_state) {
488
  array_unshift($form['#submit'], 'ldap_user_grab_password_validate');
489
}
490

    
491
/**
492
* Implements hook_form_FORM_ID_alter(). for password_policy_password_tab
493
*/
494
function ldap_user_form_password_policy_password_tab_alter(&$form, &$form_state) {
495
  array_unshift($form['#validate'], 'ldap_user_grab_password_validate');
496
}
497

    
498
/**
499
* Implements hook_form_FORM_ID_alter(). for user-pass-reset form. Useful for
500
* sites where this is the form ID for a user to intially set their password
501
* (user clicks an emailed registration link, is prompted to set their password).
502
*/
503
function ldap_user_form_user_pass_reset_alter(&$form, &$form_state) {
504
  array_unshift($form['#validate'], 'ldap_user_grab_password_validate');
505
}
506

    
507
/**
508
 * store password from logon forms in ldap_user_ldap_provision_pwd static variable
509
 * for use in provisioning to ldap
510
 */
511
function ldap_user_grab_password_validate($form, &$form_state) {
512

    
513
   // This is not a login form but profile form and user is inserting password to update email
514
  if (!empty($form_state['values']['current_pass_required_values'])) {
515
    if (!empty($form_state['values']['current_pass']) && empty($form_state['values']['pass'])) {
516
      ldap_user_ldap_provision_pwd('set', $form_state['values']['current_pass']);
517
    }
518
    // Or this is a profile form where the user is updating their own password
519
    elseif (!empty($form_state['values']['pass'])) {
520
        ldap_user_ldap_provision_pwd('set', $form_state['values']['pass']);
521
    }
522
  }
523
  // otherwise a logon form
524
  elseif (!empty($form_state['values']['pass'])) {
525
    ldap_user_ldap_provision_pwd('set', $form_state['values']['pass']);
526
  }
527

    
528
}
529

    
530

    
531

    
532

    
533
/**
534
 * Implements hook_form_FORM_ID_alter(). for user_register_form
535
 */
536
function ldap_user_form_user_register_form_alter(&$form, $form_state) {
537

    
538
  array_unshift($form['#submit'], 'ldap_user_grab_password_validate');
539

    
540
  if (!user_access('administer users')) {
541
    return;
542
  }
543
  $ldap_user_conf = ldap_user_conf();
544
  if ($ldap_user_conf->disableAdminPasswordField == TRUE) {
545
    $form['account']['pass']['#type'] = 'value';
546
    $form['account']['pass']['#value'] = user_password(20);
547
    $form['account']['pass_disabled']['#type'] = 'fieldset';
548
    $form['account']['pass_disabled']['#title'] = t('Password');
549
    $form['account']['pass_disabled'][]['#markup'] = 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.');
550
  }
551

    
552
  $ldap_fieldset = array();
553
  $options = array(
554
    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.'),
555
    LDAP_USER_MANUAL_ACCT_CONFLICT_NO_LDAP_ASSOCIATE => t('Do not make this an LDAP Associated account.'),
556
  );
557
  $ldap_fieldset['ldap_user_association'] = array(
558
    '#type' => 'radios',
559
    '#options' => $options,
560
    '#required' => FALSE,
561
    '#title' => t('LDAP Entry Association.'),
562
  );
563

    
564
  if ($ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE)) {
565
    $ldap_fieldset['ldap_user_association']['#disabled'] = TRUE;
566
    $ldap_fieldset['ldap_user_association']['#description'] =  t('Since "Create
567
      or Synch to Drupal user anytime a Drupal user account is created or updated"
568
      is selected at admin/config/people/ldap/user, this option will have no
569
      effect so its disabled.');
570
  }
571
  elseif ($ldap_user_conf->manualAccountConflict != LDAP_USER_MANUAL_ACCT_CONFLICT_SHOW_OPTION_ON_FORM) {
572
    $ldap_fieldset['ldap_user_association']['#disabled'] = TRUE;
573
    $ldap_fieldset['ldap_user_association']['#description'] =  t('To enable
574
      this an LDAP server must be selected for provisioning to Drupal in
575
      admin/config/people/ldap/user and "Show option on user create form..." must be selected.');
576
  }
577

    
578
  $ldap_fieldset['ldap_user_create_ldap_acct'] = array(
579
    '#type' => 'checkbox',
580
    '#title' => t('Create corresponding LDAP entry.'),
581
  );
582
  if (!$ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_DRUPAL_USER_PROV_ON_ALLOW_MANUAL_CREATE)) {
583
    $ldap_fieldset['ldap_user_create_ldap_acct']['#disabled'] = TRUE;
584
    $ldap_fieldset['ldap_user_create_ldap_acct']['#description'] = t('To enable
585
      this an LDAP server must be selected for provisioning to Drupal in
586
      admin/config/people/ldap/user and manual creation of LDAP accounts
587
      must be enabled also.');
588
  }
589

    
590
  if (count($ldap_fieldset) > 0) {
591
    $form['ldap_user_fields'] = $ldap_fieldset;
592
    $form['ldap_user_fields']['#type'] = 'fieldset';
593
    $form['ldap_user_fields']['#title'] =  t('LDAP Options');
594
    $form['ldap_user_fields']['#collapsible'] =  TRUE;
595
    $form['ldap_user_fields']['#collapsed'] =  FALSE;
596
  }
597

    
598
  $form['#validate'][] = 'ldap_user_form_register_form_validate';
599
  $form['#submit'][] = 'ldap_user_form_register_form_submit2';
600

    
601
}
602

    
603

    
604
function ldap_user_form_register_form_validate($form, &$form_state) {
605

    
606
  $values = $form_state['values'];
607
  $user_ldap_entry = NULL;
608
  $drupal_username = $form_state['values']['name'];
609

    
610
  if ($values['ldap_user_association'] == LDAP_USER_MANUAL_ACCT_CONFLICT_NO_LDAP_ASSOCIATE) {
611
    $form_state['values']['ldap_user_ldap_exclude'][LANGUAGE_NONE][0]['value'] = 1;
612
  }
613

    
614
  // if corresponding ldap account doesn't exist and provision not selected and make ldap associated is selected, throw error
615
  if (!@$values['ldap_user_create_ldap_acct'] && @$values['ldap_user_association'] == LDAP_USER_MANUAL_ACCT_CONFLICT_LDAP_ASSOCIATE) {
616
    $ldap_user_conf = ldap_user_conf();
617
    $ldap_user = ldap_servers_get_user_ldap_data($drupal_username, $ldap_user_conf->ldapEntryProvisionServer, 'ldap_user_prov_to_drupal');
618
    if (!$ldap_user) {
619

    
620
      form_set_error('ldap_user_association', t('User %name does not have a corresponding LDAP Entry (dn).
621
        Under LDAP options, you may NOT select "Make this an LDAP Associated Account"', array('%name' => $drupal_username)));
622
    }
623
  }
624

    
625
  // if trying to provision and ldap account and one already exists, throw error.
626
  if (@$values['ldap_user_create_ldap_acct']) {
627
    $ldap_user_conf = ldap_user_conf();
628
    $ldap_user = ldap_servers_get_user_ldap_data($drupal_username, $ldap_user_conf->ldapEntryProvisionServer, 'ldap_user_prov_to_ldap');
629
    if ($ldap_user) {
630
      $tokens = array('%dn' => $ldap_user['dn'], '%name' => $drupal_username);
631
      form_set_error('ldap_user_create_ldap_acct', t('User %name already has a corresponding LDAP Entry (%dn).
632
        Uncheck "Create corresponding LDAP entry" to allow this Drupal user to be created.  Select
633
        "Make this an LDAP associated account" to associate this account with the ldap entry.', $tokens));
634
    }
635
  }
636
}
637

    
638

    
639
/** called after user_register_form_submit **/
640
function ldap_user_form_register_form_submit2($form, &$form_state) {
641

    
642
  $values = $form_state['values'];
643
  $ldap_user_association_set = FALSE;
644

    
645
  if (@$values['ldap_user_create_ldap_acct']) {
646
    if ($account = user_load_by_name($values['name'])) {
647
      $ldap_user_conf = ldap_user_conf();
648
      $ldap_provision_entry = $ldap_user_conf->getProvisionRelatedLdapEntry($account);
649
      if (!$ldap_provision_entry) {
650
        $provision_result = $ldap_user_conf->provisionLdapEntry($account);
651
      }
652
      else {
653
        $ldap_user_association_set = TRUE;
654
      }
655
    }
656
    else {
657
      // don't do anything here.  If account is not created, other user module warnings will exist
658
    }
659
  }
660

    
661
  if ($ldap_user_association_set || @$values['ldap_user_association'] == LDAP_USER_MANUAL_ACCT_CONFLICT_LDAP_ASSOCIATE) {
662
    $ldap_user_conf = ldap_user_conf();
663
    $ldap_user_conf->ldapAssociateDrupalAccount($form_state['values']['name']);
664
  }
665

    
666
}
667

    
668
/**
669
 * @param stdClass $account as drupal user object
670
 * @param array $edit is a drupal user edit array
671
 * @param enum int $direction indicating which directions to test for association
672
 *
673
 *
674
 * @return boolean TRUE if user should be excluded from ldap provision/synching
675
 */
676

    
677
function ldap_user_ldap_exclude($account = NULL, $edit = NULL, $direction = LDAP_USER_PROV_DIRECTION_ALL) {
678
  // always exclude user 1
679
  if (is_object($account) && isset($account->uid) && $account->uid == 1) {
680
    return TRUE;
681
  }
682

    
683
  // exclude users who have the field ldap_user_ldap_exclude set to 1
684
  if (is_object($account) && isset($account->ldap_user_ldap_exclude[LANGUAGE_NONE][0]['value'])
685
    && $account->ldap_user_ldap_exclude[LANGUAGE_NONE][0]['value'] == 1) {
686
    return TRUE;
687
  }
688

    
689
  // exclude new users who have the value set to 1 in their $edit array
690
  if (is_array($edit) && isset($edit['ldap_user_ldap_exclude'][LANGUAGE_NONE][0]['value'])
691
    && $edit['ldap_user_ldap_exclude'][LANGUAGE_NONE][0]['value'] == 1) {
692
    return TRUE;
693
  }
694

    
695
  // everyone else is fine
696
  return FALSE;
697

    
698
}
699

    
700
/**
701
 * @param stdClass $account as drupal user object
702
 * @param enum int $direction indicating which directions to test for association
703
 *   LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER signifies test if drupal account has been provisioned or synched from ldap
704
 *   LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY signifies test if ldap account has been provisioned or synched from drupal
705
 *   NULL signifies check for either direction
706
 *
707
 * @return boolean if user is ldap associated
708
 */
709
function ldap_user_is_ldap_associated($account, $direction = NULL) {
710

    
711
  $to_drupal_user = FALSE;
712
  $to_ldap_entry = FALSE;
713

    
714
  if ($direction === NULL || $direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) {
715

    
716
    if (property_exists($account, 'ldap_user_current_dn') && !empty($account->ldap_user_current_dn[LANGUAGE_NONE][0]['value'])) {
717
      $to_drupal_user = TRUE;
718
    }
719
    elseif (isset($account->uid)) {
720
      $authname = ldap_user_get_authname($account);
721
      $to_drupal_user = (boolean)$authname;
722
    }
723
  }
724

    
725
  if ($direction === NULL || $direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
726
    if (property_exists($account, 'ldap_user_prov_entries') && !empty($account->ldap_user_prov_entries[LANGUAGE_NONE][0]['value'])) {
727
      $to_ldap_entry = TRUE;
728
    }
729
  }
730

    
731
  if ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) {
732
    return $to_drupal_user;
733
  }
734
  elseif ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
735
    return $to_ldap_entry;
736
  }
737
  else {
738
    return ($to_ldap_entry || $to_drupal_user);
739
  }
740

    
741

    
742

    
743

    
744
}
745
/**
746
 * api function for synching
747
 * note: does no checking if synching is enabled or configured for a given context
748
 */
749

    
750
function ldap_user_synch_to_drupal($username, $prov_event = LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER, $ldap_user = NULL) {
751

    
752
  $ldap_user_conf = ldap_user_conf();
753
  $account = user_load_by_name($username);
754
  $user_edit = array();
755
  $ldap_user_conf->synchToDrupalAccount($account, $user_edit, $prov_event, $ldap_user, TRUE);
756

    
757
}
758

    
759
/**
760
 * api function for ldap associated user provisioning
761
 * note: does no checking if synching is enabled or configured for a given context
762
 */
763
function ldap_user_provision_to_drupal($ldap_user, $user_edit = array()) {
764

    
765
  $sid = $ldap_user['sid'];
766
  $ldap_user_conf = ldap_user_conf();
767
  $account = NULL;
768
  $ldap_user_conf->provisionDrupalAccount($account, $user_edit, $ldap_user, TRUE);
769

    
770
}
771

    
772

    
773
/**
774
 * function to:
775
 *   -- store user entered password during pageload
776
 *   and protect unencrypted user password from other modules
777
 *
778
 *   @param enum string $action 'get' | 'set'
779
 *   @param string | FALSE $value as user entered password
780
 */
781
function ldap_user_ldap_provision_pwd($action, $value = NULL, $reset = FALSE) {
782

    
783
  //$calling_function = FALSE;
784
  //if (function_exists('debug_backtrace') && $backtrace = debug_backtrace()) { //   {
785
  //  $calling_function = $backtrace[1]['function'];
786
  //}
787

    
788
  static $current_user_pass;
789

    
790
  if ($reset) {
791
    $current_user_pass = NULL;
792
  }
793

    
794
  if ($action == 'set') {
795
    $current_user_pass = $value;
796
  }
797
  elseif ($action == 'get' && $current_user_pass) {
798
       // && (!$calling_function || $calling_function == 'ldap_servers_token_tokenize_user_account')
799
    return $current_user_pass;
800
  }
801
  else {
802
    return FALSE;
803
  }
804

    
805
}
806

    
807

    
808

    
809
/**
810
 * function to avoid multiple synch or provision in same page load (if desired)
811
 *
812
 *   @param enum string $action 'synch' | 'provision' | 'set_page_load_key' | NULL
813
 *   @param enum string $op = 'set' or 'get'
814
 *   @value mixed value associate with $op.
815
 */
816

    
817

    
818
function ldap_user_ldap_provision_semaphore($action, $op, $value = NULL, $reset = FALSE) {
819

    
820
  $calling_function = FALSE;
821
  if (function_exists('debug_backtrace') && $backtrace = debug_backtrace()) { //   {
822
    $calling_function = $backtrace[1]['function'];
823
  }
824

    
825
  static $ldap_accts;
826
  static $intialized;
827

    
828
  if ($reset || !$intialized) {
829
    $ldap_accts = array();
830
    $intialized = TRUE;
831
  }
832

    
833
   // mark that the given drupal user has had ldap entry synched or provisioned on this page load.
834
  if ($op == 'set') {
835
    if ($action && $value) {
836
      $ldap_accts[$action][$value] = TRUE;
837
    }
838
    return;
839
  }
840

    
841
  // has the given drupal user x action (synch or provision) been executed.
842
  if ($op == 'get') {
843
    if ($action && $value && isset($ldap_accts[$action][$value])) {
844
      return $ldap_accts[$action][$value];
845
    }
846
    else {
847
      return FALSE;
848
    }
849
  }
850

    
851
}
852

    
853

    
854
/**
855
 * Implements hook_user_login().
856
 */
857
function ldap_user_user_login(&$edit, $account) {
858

    
859
  if (ldap_user_ldap_exclude($account, $edit)) {
860
    return;
861
  }
862
  $ldap_user_conf = ldap_user_conf();
863
  $user_edit = array();
864

    
865
  ldap_user_reset_provision_server($ldap_user_conf, $account);
866

    
867
   // provision or synch to ldap, not both
868
  $provision_result = array('status' => 'none');
869

    
870
   // provision to ldap
871
  // if ($account->access == 0 && $account->login != 0) {} check for first time user
872
  if (
873
      $ldap_user_conf->provisionsLdapEntriesFromDrupalUsers
874
      && ldap_user_ldap_provision_semaphore('provision', 'get', $account->name) === FALSE
875
      && !$ldap_user_conf->getProvisionRelatedLdapEntry($account)
876
      && $ldap_user_conf->ldapEntryProvisionServer
877
      && $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE)
878
      ) {
879
    $provision_result = $ldap_user_conf->provisionLdapEntry($account);
880
    if ($provision_result['status'] == 'success') {
881
      ldap_user_ldap_provision_semaphore('provision', 'set', $account->name);
882
    }
883
  }
884
  // don't synch if just provisioned
885
  if (
886
    $ldap_user_conf->provisionsLdapEntriesFromDrupalUsers
887
    && ldap_user_ldap_provision_semaphore('synch', 'get' , $account->name) === FALSE
888
    && $provision_result['status'] != 'success'
889
    && $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE)
890
    ) {
891
    $bool_result = $ldap_user_conf->synchToLdapEntry($account, $user_edit);
892
    if ($bool_result) {
893
      ldap_user_ldap_provision_semaphore('synch', 'set', $account->name);
894
    }
895
  }
896

    
897
  $prov_enabled = $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE);
898

    
899
  // Provision from LDAP if a new account was not just provisioned from LDAP
900
  if (ldap_user_ldap_provision_semaphore('drupal_created', 'get', $account->name) === FALSE) {
901
    if ($ldap_user_conf->provisionsDrupalAccountsFromLdap && in_array(LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER, array_keys($ldap_user_conf->provisionsDrupalEvents))) {
902
      $ldap_user = ldap_servers_get_user_ldap_data($account->name, $ldap_user_conf->drupalAcctProvisionServer, 'ldap_user_prov_to_drupal');
903
      if ($ldap_user) {
904
        $ldap_server = ldap_servers_get_servers($ldap_user_conf->drupalAcctProvisionServer, NULL, TRUE);
905
        $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));
906
        if (empty($account->picture->fid)) { // see #1973352 and #935592
907
          $account2 = user_load($account->uid);
908
          $account->picture = $account2->picture;
909
        }
910
        $account = user_save($account, $user_edit, 'ldap_user');
911
      }
912
    }
913
  }
914

    
915
}
916

    
917

    
918
/**
919
 * Implements hook_user_insert().
920
 *
921
 */
922
function ldap_user_user_insert(&$user_edit, $account, $category) {
923

    
924
  global $user;
925
  $not_associated = ldap_user_ldap_exclude($account, $user_edit);
926
  $new_account_request = (boolean)($user->uid == 0 && $account->access == 0 && $account->login == 0); // check for first time user
927
  $already_provisioned_to_ldap = ldap_user_ldap_provision_semaphore('provision', 'get' , $account->name);
928
  $already_synched_to_ldap = ldap_user_ldap_provision_semaphore('synch', 'user_action_query' , $account->name);
929
  if ($not_associated || $already_synched_to_ldap || $already_synched_to_ldap || $new_account_request) {
930
    return;
931
  }
932

    
933
  $ldap_user_conf = ldap_user_conf();
934
  /**
935
   * in hook_user_insert, account is already created, so never call provisionDrupalAccount(), just
936
   * synchToDrupalAccount(), even if action is 'provision'
937
   */
938
  $empty_user_edit = array();
939
  if ($account->status && $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE)) {
940
    $ldap_user_conf->synchToDrupalAccount($account, $empty_user_edit, LDAP_USER_EVENT_CREATE_DRUPAL_USER, NULL, TRUE);
941
  }
942

    
943
  if ($ldap_user_conf->provisionsLdapEntriesFromDrupalUsers) {
944
    $prov_enabled = $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE);
945
    if ($prov_enabled) {
946
      $ldap_provision_entry = $ldap_user_conf->getProvisionRelatedLdapEntry($account);
947
      if (!$ldap_provision_entry) {
948
        $provision_result = $ldap_user_conf->provisionLdapEntry($account);
949
        if ($provision_result['status'] == 'success') {
950
          ldap_user_ldap_provision_semaphore('provision', 'set', $account->name);
951
        }
952
       }
953
      elseif ($ldap_provision_entry) {
954
        $bool_result = $ldap_user_conf->synchToLdapEntry($account, $user_edit);
955
        if ($bool_result) {
956
          ldap_user_ldap_provision_semaphore('synch', 'set', $account->name);
957
        }
958
      }
959
    }
960
  }
961
}
962

    
963
/**
964
 * Implements hook_user_update()
965
 */
966

    
967
function ldap_user_user_update(&$user_edit, $account, $category) {
968
  //debug("ldap_user_user_update, category=$category"); debug($user_edit); debug($account); // ldap_user_user_insert, category='. $category . 'account->status = ' . $account->status);
969
  if (ldap_user_ldap_exclude($account, $user_edit)) {
970
    return;
971
  }
972

    
973
  $ldap_user_conf = ldap_user_conf();
974
  // check for provisioning to LDAP; this will normally occur on hook_user_insert or other event when drupal user is created.
975
  if ($ldap_user_conf->provisionsLdapEntriesFromDrupalUsers &&
976
      $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE)) {
977

    
978
    $already_provisioned_to_ldap = ldap_user_ldap_provision_semaphore('provision', 'get' , $account->name);
979
    $already_synched_to_ldap = ldap_user_ldap_provision_semaphore('synch', 'get' , $account->name);
980
    if ($already_provisioned_to_ldap || $already_synched_to_ldap) {
981
      return;
982
    }
983

    
984
    $provision_result = array('status' => 'none');
985
    // always check if provisioning to ldap has already occurred this page load
986
    $ldap_entry = $ldap_user_conf->getProvisionRelatedLdapEntry($account);
987
    if (!$ldap_entry) { //{
988
      $provision_result = $ldap_user_conf->provisionLdapEntry($account);
989
      if ($provision_result['status'] == 'success') {
990
        ldap_user_ldap_provision_semaphore('provision', 'set', $account->name);
991
      }
992
    }
993
    // synch if not just provisioned and enabled
994
    if ($provision_result['status'] != 'success' ) {
995
      // always check if provisioing to ldap has already occurred this page load
996
      $provision_enabled = $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE);
997
      $ldap_entry = $ldap_user_conf->getProvisionRelatedLdapEntry($account);
998
      if ($provision_enabled && $ldap_entry) {
999
        $bool_result = $ldap_user_conf->synchToLdapEntry($account, $user_edit);
1000
        if ($bool_result) {
1001
          ldap_user_ldap_provision_semaphore('synch', 'set', $account->name);
1002
        }
1003
      }
1004
    }
1005
  }
1006

    
1007
}
1008

    
1009
 /**
1010
 * Implements hook_user_presave()
1011
 */
1012

    
1013
function ldap_user_user_presave(&$user_edit, $account, $category) {
1014
 //debug("ldap_user_user_presave, category=$category"); debug($user_edit); debug($account); // ldap_user_user_insert, category='. $category . 'account->status = ' . $account->status);
1015

    
1016
  if (ldap_user_ldap_exclude($account, $user_edit)) {
1017
    return;
1018
  }
1019
  if (isset($account->name)) {
1020
    $drupal_username = $account->name;
1021
  }
1022
  elseif (!empty($user_edit['name'])) {
1023
    $drupal_username = $user_edit['name'];
1024
  }
1025
  else {
1026
    return;
1027
  }
1028
  $ldap_user_conf = ldap_user_conf();
1029

    
1030
  ldap_user_reset_provision_server($ldap_user_conf, $account);
1031

    
1032
  // check for provisioning to drupal and override synched user fields/props
1033
  // Provision from LDAP if a new account was not just provisioned from LDAP
1034
  if (ldap_user_ldap_provision_semaphore('drupal_created', 'get', $drupal_username) === FALSE) {
1035
    if ($ldap_user_conf->provisionsDrupalAccountsFromLdap && in_array(LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER, array_keys($ldap_user_conf->provisionsDrupalEvents))) {
1036
      if ($ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE)) {
1037
        if (ldap_user_is_ldap_associated($account, LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER)) {
1038
          $ldap_user = ldap_servers_get_user_ldap_data($drupal_username, $ldap_user_conf->drupalAcctProvisionServer, 'ldap_user_prov_to_drupal');
1039
          $ldap_server = ldap_servers_get_servers($ldap_user_conf->drupalAcctProvisionServer, NULL, TRUE);
1040
          $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));
1041
        }
1042
      }
1043
    }
1044
  }
1045

    
1046
}
1047

    
1048
/**
1049
 * Implements hook_user_delete().
1050
 */
1051
function ldap_user_user_delete($account) {
1052
  // drupal user account is about to be deleted.
1053
  $ldap_user_conf = ldap_user_conf();
1054
  if (
1055
      $ldap_user_conf->provisionsLdapEntriesFromDrupalUsers
1056
      && $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_DELETE_ON_USER_DELETE)
1057
      ) {
1058
    $boolean_result = $ldap_user_conf->deleteProvisionedLdapEntries($account);
1059
    // no need to watchdog here, because fail in deleteProvisionedLdapEntries provides watchdog entry
1060
  }
1061
}
1062

    
1063

    
1064

    
1065
/**
1066
 * @return default value for field user->ldap_user_provisioned_sid
1067
 */
1068
function ldap_user_provisioned_sid_default($entity_type, $entity, $field, $instance, $langcode) {
1069
  return NULL;
1070
}
1071

    
1072
/**
1073
 * @return default value for field user->ldap_user_provisioned_sid
1074
 */
1075
function ldap_user_puid_default($entity_type, $entity, $field, $instance, $langcode) {
1076
  return NULL;
1077
}
1078
/**
1079
 * @return default value for field user->ldap_user_puid
1080
 */
1081
function ldap_user_puid_property_default($entity_type, $entity, $field, $instance, $langcode) {
1082
  return NULL;
1083
}
1084
/**
1085
 * @return default value for field user->ldap_user_dn
1086
 */
1087
function ldap_user_dn_default($entity_type, $entity, $field, $instance, $langcode) {
1088
  return NULL;
1089
}
1090

    
1091
/**
1092
 * Implements hook_field_widget_info().
1093
 * to provide field type for LDAP fields
1094
 */
1095
function ldap_user_field_widget_info() {
1096
  return array(
1097
    'ldap_user_hidden' => array(
1098
      'label' => t('Hidden Text Field'),
1099
      'field types' => array('text'),
1100
      'settings' => array(),
1101
    ),
1102
  );
1103
}
1104

    
1105
/**
1106
 * Implements hook_field_widget_settings_form().
1107
 */
1108
function ldap_user_field_widget_settings_form($field, $instance) {
1109
  return array();
1110
}
1111

    
1112
/**
1113
 * Implements hook_field_widget_form().
1114
 */
1115
function ldap_user_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
1116

    
1117
  $main_widget = array();
1118

    
1119
  switch ($instance['widget']['type']) {
1120
    case 'ldap_user_hidden':
1121
      $element['value'] = $element + array(
1122
        '#type' => 'hidden',
1123
        '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
1124
      );
1125
      break;
1126
  }
1127

    
1128
  return $element;
1129
}
1130

    
1131
function ldap_user_synch_triggers_key_values() {
1132

    
1133
  return array(
1134
    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".'),
1135
    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).'),
1136
    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'),
1137
    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.'),
1138
    LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE => t('On creation or synch of an LDAP entry when a user authenticates.'),
1139
    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.'),
1140
  );
1141

    
1142
}
1143

    
1144
function ldap_user_all_events() {
1145
  return array(
1146
    LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER,
1147
    LDAP_USER_EVENT_CREATE_DRUPAL_USER,
1148
    LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY,
1149
    LDAP_USER_EVENT_CREATE_LDAP_ENTRY,
1150
    LDAP_USER_EVENT_LDAP_ASSOCIATE_DRUPAL_ACCT,
1151
  );
1152

    
1153
}
1154

    
1155
/**
1156
 * @param array $account
1157
 * @param string $text
1158
 * @return string text with tokens replaced
1159
 */
1160

    
1161
function ldap_user_token_replace($token, $account, $entity = NULL) {
1162
  $desired_tokens = ldap_servers_token_tokens_needed_for_template($token);
1163
  $tokens = ldap_user_token_tokenize_entry($account, $desired_tokens, LDAP_SERVERS_TOKEN_PRE, LDAP_SERVERS_TOKEN_POST, $entity);
1164
  $result = str_replace(array_keys($tokens), array_values($tokens), $token);
1165
  return $result;
1166
}
1167

    
1168

    
1169

    
1170
/**
1171
 * Turn an ldap entry into a token array suitable for the t() function
1172
 * @param drupal user object $account
1173
 * @param array $token_keys as list of token/value pairs to generate
1174
 * @param string prefix token prefix such as !,%,[
1175
 * @param string suffix token suffix such as ]
1176
 *
1177
 * @return token array suitable for t() functions of with lowercase keys as exemplified below
1178
 */
1179
function ldap_user_token_tokenize_entry($account, $token_keys, $pre = LDAP_SERVERS_TOKEN_PRE, $post = LDAP_SERVERS_TOKEN_POST, $user_entity = NULL) {
1180

    
1181
  $detailed_watchdog_log = variable_get('ldap_help_watchdog_detail', 0);
1182
  $tokens = array();
1183
  if (!$user_entity) {
1184
    list($discard, $user_entity) = ldap_user_load_user_acct_and_entity($account->uid, 'uid');
1185
  }
1186

    
1187
  foreach ($token_keys as $token_key) {
1188
    // target id is of form field.lname, property.mail, field.dept:0, etc.
1189
    list($type, $attr_ordinal) = explode('.', $token_key);
1190
    $parts = explode(':', $attr_ordinal);
1191
    $attr = $parts[0];
1192
    $ordinal = (count($parts) > 1) ? $parts[1] : 0;
1193
    $token = $pre . $token_key . $post;
1194
    switch ($type) {
1195

    
1196
      case 'field':
1197
        if (isset( $user_entity->{$attr}[LANGUAGE_NONE][$ordinal]['value'])) {
1198
          $tokens[$token] = $user_entity->{$attr}[LANGUAGE_NONE][$ordinal]['value'];
1199
        }
1200
      break;
1201

    
1202

    
1203
      case 'property':
1204
        if (property_exists($account, $attr)) {
1205
          $tokens[$token] = $account->{$attr};
1206
        }
1207
      break;
1208

    
1209
      // @todo: 3. tokenize profile 2
1210
    }
1211

    
1212
  }
1213

    
1214
  return $tokens;
1215
}
1216

    
1217
  /**
1218
   * load user $account and $entity, given uid or $username
1219
   *
1220
   * @param string $user_id is username or uid
1221
   * @param enum $user_id_type is 'username' or 'uid'
1222
   *
1223
   * return array $account and $user_entity
1224
   */
1225

    
1226
  function ldap_user_load_user_acct_and_entity($user_id, $user_id_type = 'username') {
1227

    
1228
    if ($user_id_type == 'username') {
1229
      $account = user_load_by_name($user_id);
1230
    }
1231
    else {
1232
      $account = user_load($user_id);
1233
    }
1234
    if ($account) {
1235
      $user_entities = entity_load('user', array($account->uid));
1236
      $user_entity = $user_entities[$account->uid];
1237
    }
1238
    else {
1239
      $user_entity = NULL;
1240
    }
1241

    
1242
    return array($account, $user_entity);
1243

    
1244
  }
1245

    
1246
/**
1247
 * Implements hook_ldap_servers_username_to_ldapname_alter
1248
 * - Set ldap name to auth name
1249
 */
1250
function ldap_user_ldap_servers_username_to_ldapname_alter(&$ldap_username, $drupal_username, $context) {
1251
  // Alter the name only if it has not been altered already, ie php eval code
1252
  if ($ldap_username == $drupal_username) {
1253
    $authname = ldap_user_get_authname($ldap_username);
1254
    if (!empty($authname)) {
1255
      $ldap_username = $authname;
1256
    }
1257
  }
1258
}
1259

    
1260
/**
1261
 * Returns LDAP authname from the authmap table for a variant input.
1262
 *
1263
 * @param $data
1264
 *   A variant input. Allowed variable types:
1265
 *   - object: user account object
1266
 *   - string: username
1267
 *
1268
 * @return string|NULL
1269
 *   Returns the LDAP authname of the passed Drupal user.
1270
 */
1271
function ldap_user_get_authname($data) {
1272
  $cache = &drupal_static(__FUNCTION__, array());
1273

    
1274
  $authname = NULL;
1275
  $uid = NULL;
1276

    
1277
  if (is_object($data)) {
1278
    // Object - set uid if object has uid and uid > 0
1279
    if (!empty($data->uid)) {
1280
      $uid = $data->uid;
1281
    }
1282
  }
1283
  else {
1284
    // String - load account and set uid if uid > 0
1285
    $account = user_load_by_name($data);
1286
    if (!empty($account->uid)) {
1287
      $uid = $account->uid;
1288
    }
1289
  }
1290

    
1291
  // Exit if no uid found
1292
  if (empty($uid)) {
1293
    return NULL;
1294
  }
1295

    
1296
  // Run query if uid is not statically cached
1297
  if (!array_key_exists($uid, $cache)) {
1298
    $authname = db_query('SELECT authname FROM {authmap} WHERE uid = :uid AND module = :module', array(
1299
      ':uid' => $uid,
1300
      ':module' => 'ldap_user',
1301
    ))->fetchField();
1302

    
1303
    $cache[$uid] = !empty($authname) ? $authname : NULL;
1304
  }
1305

    
1306
  return $cache[$uid];
1307
}
1308

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