Projet

Général

Profil

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

root / drupal7 / sites / all / modules / ldap / ldap_user / ldap_user.module @ 5136ce55

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
        $attributes[$ldap_server->picture_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->picture_attr]);
232
        $attributes[$ldap_server->unique_persistent_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->unique_persistent_attr]);
233
        if ($ldap_server->mail_template) {
234
          ldap_servers_token_extract_attributes($attributes,  $ldap_server->mail_template);
235
        }
236
      break;
237
    }
238

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

    
244
  }
245
}
246

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

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

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

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

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

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

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

    
302
  }
303

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

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

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

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

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

    
359

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

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

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

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

    
402
  }
403

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

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

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

    
432
    }
433

    
434
  }
435

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

    
439

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

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

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

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

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

    
465

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

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

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

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

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

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

    
515
}
516

    
517

    
518

    
519

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

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

    
527
  if (!user_access('administer users')) {
528
    return;
529
  }
530
  $ldap_user_conf = ldap_user_conf();
531
  if ($ldap_user_conf->disableAdminPasswordField == TRUE) {
532
    $form['account']['pass']['#type'] = 'value';
533
    $form['account']['pass']['#value'] = user_password(20);
534
    $form['account']['pass_disabled']['#type'] = 'fieldset';
535
    $form['account']['pass_disabled']['#title'] = t('Password');
536
    $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.');
537
  }
538

    
539
  $ldap_fieldset = array();
540
  $options = array(
541
    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.'),
542
    LDAP_USER_MANUAL_ACCT_CONFLICT_NO_LDAP_ASSOCIATE => t('Do not make this an LDAP Associated account.'),
543
  );
544
  $ldap_fieldset['ldap_user_association'] = array(
545
    '#type' => 'radios',
546
    '#options' => $options,
547
    '#required' => FALSE,
548
    '#title' => t('LDAP Entry Association.'),
549
  );
550

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

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

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

    
585
  $form['#validate'][] = 'ldap_user_form_register_form_validate';
586
  $form['#submit'][] = 'ldap_user_form_register_form_submit2';
587

    
588
}
589

    
590

    
591
function ldap_user_form_register_form_validate($form, &$form_state) {
592

    
593
  $values = $form_state['values'];
594
  $user_ldap_entry = NULL;
595
  $drupal_username = $form_state['values']['name'];
596

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

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

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

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

    
625

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

    
629
  $values = $form_state['values'];
630
  $ldap_user_association_set = FALSE;
631

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

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

    
653
}
654

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

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

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

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

    
682
  // everyone else is fine
683
  return FALSE;
684

    
685
}
686

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

    
697
function ldap_user_is_ldap_associated($account, $direction = NULL) {
698

    
699
  $to_drupal_user = FALSE;
700
  $to_ldap_entry = FALSE;
701

    
702
  if ($direction === NULL || $direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) {
703

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

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

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

    
729

    
730

    
731

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

    
738
function ldap_user_synch_to_drupal($username, $prov_event = LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER, $ldap_user = NULL) {
739

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

    
745
}
746

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

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

    
758
}
759

    
760

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

    
770

    
771
function ldap_user_ldap_provision_pwd($action, $value = NULL, $reset = FALSE) {
772

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

    
778
  static $current_user_pass;
779

    
780
  if ($reset) {
781
    $current_user_pass = NULL;
782
  }
783

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

    
795
}
796

    
797

    
798

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

    
807

    
808
function ldap_user_ldap_provision_semaphore($action, $op, $value = NULL, $reset = FALSE) {
809

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

    
815
  static $ldap_accts;
816
  static $intialized;
817

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

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

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

    
841
}
842

    
843

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

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

    
855
  ldap_user_reset_provision_server($ldap_user_conf, $account);
856

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

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

    
887
  $prov_enabled = $ldap_user_conf->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE);
888

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

    
905
}
906

    
907

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

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

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

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

    
953
/**
954
 * Implements hook_user_update()
955
 */
956

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

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

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

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

    
997
}
998

    
999
 /**
1000
 * Implements hook_user_presave()
1001
 */
1002

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

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

    
1020
  ldap_user_reset_provision_server($ldap_user_conf, $account);
1021

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

    
1036
}
1037

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

    
1053

    
1054

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

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

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

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

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

    
1107
  $main_widget = array();
1108

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

    
1118
  return $element;
1119
}
1120

    
1121
function ldap_user_synch_triggers_key_values() {
1122

    
1123
  return array(
1124
    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".'),
1125
    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).'),
1126
    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'),
1127
    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.'),
1128
    LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE => t('On creation or synch of an LDAP entry when a user authenticates.'),
1129
    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.'),
1130
  );
1131

    
1132
}
1133

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

    
1143
}
1144

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

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

    
1158

    
1159

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

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

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

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

    
1192

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

    
1199
      // @todo: 3. tokenize profile 2
1200
    }
1201

    
1202
  }
1203

    
1204
  return $tokens;
1205
}
1206

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

    
1216
  function ldap_user_load_user_acct_and_entity($user_id, $user_id_type = 'username') {
1217

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

    
1232
    return array($account, $user_entity);
1233

    
1234
  }
1235

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

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

    
1262
  $authname = NULL;
1263
  $uid = NULL;
1264

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

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

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

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

    
1300
  return $cache[$uid];
1301
}
1302

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