Projet

Général

Profil

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

root / drupal7 / sites / all / modules / ldap / ldap_servers / ldap_servers.tokens.inc @ bc175c27

1
<?php
2

    
3
/**
4
 * @file
5
 * collection of functions related to ldap tokens
6
 */
7

    
8
/**
9
 * @param string $attr_name such 'field_user_lname', 'name', 'mail', 'dn'
10
 * @param string $attr_type such as 'field', 'property', etc.  NULL for ldap attributes
11
 * @param string $attr_ordinal 0, 1, 2, etc.  not used in general
12
 *
13
 * @return string such as 'field.field_user_lname', 'samaccountname', etc.
14
 */
15
function ldap_servers_make_token($attr_name, $attr_type = NULL, $ordinal = NULL) {
16
  $inner_token = $attr_name;
17
  if ($attr_type) {
18
    $inner_token .= '.' . $attr_type;
19
  }
20
  if ($ordinal) {
21
    $inner_token .= ':' . $ordinal;
22
  }
23
  $token = LDAP_SERVERS_TOKEN_PRE . $inner_token . LDAP_SERVERS_TOKEN_POST;
24
  return $token;
25
}
26

    
27
/**
28
 * @param $user_attr_key of form <attr_type>.<attr_name>[:<instance>]
29
 *   such as field.lname, property.mail, field.aliases:2
30
 *
31
 * @return array array($attr_type, $attr_name, $attr_ordinal) such as array('field','field_user_lname', NULL)
32
 */
33
function ldap_servers_parse_user_attr_name($user_attr_key) {
34
  $user_attr_key = trim($user_attr_key, LDAP_SERVERS_TOKEN_PRE . LDAP_SERVERS_TOKEN_POST); // make sure no [] are on attribute
35
  $parts = explode('.', $user_attr_key);
36
  $attr_type = $parts[0];
37
  $attr_name = (isset($parts[1])) ? $parts[1] : FALSE;
38
  $attr_ordinal = FALSE;
39

    
40
  if ($attr_name) {
41
    $attr_name_parts = explode(':', $attr_name);
42
    if (isset($attr_name_parts[1])) {
43
      $attr_name = $attr_name_parts[0];
44
      $attr_ordinal = $attr_name_parts[1];
45
    }
46
  }
47
  return array($attr_type, $attr_name, $attr_ordinal);
48
}
49

    
50
/**
51
 * @param array $ldap_entry
52
 * @param string $text such as "[dn]", "[cn]@my.org", "[displayName] [sn]", "Drupal Provisioned"
53
 * @return string $text with tokens replaced or NULL if replacement not available
54
 */
55

    
56
function ldap_servers_token_replace($resource, $text, $resource_type = 'ldap_entry') { // user_account
57

    
58
  $desired_tokens = ldap_servers_token_tokens_needed_for_template($text);  // desired tokens are of form "cn","mail", etc.
59

    
60
  if (empty($desired_tokens)) {
61
    return $text; // if no tokens exist in text, return text itself.  It is literal value
62
  }
63

    
64
  switch ($resource_type) {
65
    case 'ldap_entry':
66
    $tokens = ldap_servers_token_tokenize_entry($resource, $desired_tokens, LDAP_SERVERS_TOKEN_PRE, LDAP_SERVERS_TOKEN_POST);
67
    break;
68

    
69
    case 'user_account':
70
    $tokens = ldap_servers_token_tokenize_user_account($resource, $desired_tokens, LDAP_SERVERS_TOKEN_PRE, LDAP_SERVERS_TOKEN_POST);
71
    break;
72
  }
73

    
74
  // add lowercase tokens to avoid case sensitivity
75
  foreach ($tokens as $attribute => $value) {
76
    $tokens[drupal_strtolower($attribute)] = $value;
77
  }
78

    
79
  // If $text is not present as an attribute key, insert it and set the key's value to an empty string.
80
  if (!array_key_exists(drupal_strtolower($text), $tokens)) {
81
    $tokens[$text] = '';
82
    $tokens[drupal_strtolower($text)] = '';
83
  }
84

    
85
  $attributes = array_keys($tokens); //array of attributes (sn, givenname, etc)
86
  $values = array_values($tokens); //array of attribute values (Lincoln, Abe, etc)
87
  $result = str_replace($attributes, $values, $text);
88

    
89
  $result = preg_replace('/\[[^\]]*]/', '', $result);  // strip out any unreplaced tokens
90
  return ($result == '') ? NULL : $result; // return NULL if $result is empty, else $result
91
}
92

    
93
/**
94
 * @param array $attributes array of attributes passed by reference
95
 * @param string $text with tokens in it
96
 *
97
 * by reference return add ldap attribute triplet $attribute_maps[<attr_name>] = (<attr_name>, <ordinal>, <data_type>) to $attributes
98
 */
99
function ldap_servers_token_extract_attributes(&$attribute_maps, $text) {
100
  $tokens = ldap_servers_token_tokens_needed_for_template($text);
101
  foreach ($tokens as $token) {
102
    $token = str_replace(array(LDAP_SERVERS_TOKEN_PRE, LDAP_SERVERS_TOKEN_POST), array('', ''), $token);
103
    $parts = explode(LDAP_SERVERS_TOKEN_DEL, $token);
104
    $ordinal = (isset($parts[1]) && $parts[1]) ? $parts[1] : 0;
105
    $attr_name = $parts[0];
106
    $source_data_type = NULL;
107

    
108
    $parts2 = explode(LDAP_SERVERS_TOKEN_MODIFIER_DEL, $attr_name);
109
    if (count($parts2) > 1) {
110
      $attr_name = $parts2[0];
111
      $conversion = $parts2[1];
112
    }
113
    else {
114
      $conversion = NULL;
115
    }
116
    $attribute_maps[$attr_name] = ldap_servers_set_attribute_map(@$attribute_maps[$attr_name], $conversion, array($ordinal => NULL));
117
  }
118
}
119

    
120
/**
121
 * @param string $token or token expression with singular token in it, eg. [dn], [dn;binary], [titles:0;binary] [cn]@mycompany.com
122
 *
123
 *
124
 *
125
 * @return array(<attr_name>, <ordinal>, <conversion>)
126
 */
127
function ldap_servers_token_extract_parts($token) {
128
  $attributes = array();
129
  ldap_servers_token_extract_attributes($attributes, $token);
130
  if (is_array($attributes)) {
131
    $keys = array_keys($attributes);
132
    $attr_name = $keys[0];
133
    $attr_data = $attributes[$attr_name];
134
    $ordinals = array_keys($attr_data['values']);
135
    $ordinal = $ordinals[0];
136
    return array($attr_name, $ordinal, $attr_data['conversion']);
137
  }
138
  else {
139
    return array(NULL, NULL, NULL);
140
  }
141

    
142
}
143

    
144

    
145

    
146
/**
147
 * Turn an ldap entry into a token array suitable for the t() function
148
 * @param ldap entry array $ldap_entry
149
 * @param string prefix token prefix such as !,%,[
150
 * @param string suffix token suffix such as ]
151
 * @param $token_keys either an array of key names such as array('cn', 'dn') or string 'all' to return all tokens.
152
 * @return token array suitable for t() functions of with lowercase keys as exemplified below
153

    
154

    
155
$ldap_entry should be in form of single entry returned from ldap_search() function:
156

    
157
    'dn' => 'cn=jdoe,ou=campus accounts,ou=toledo campus,dc=ad,dc=myuniversity,dc=edu',
158
    'mail' => array( 0 => 'jdoe@myuniversity.edu', 'count' => 1),
159
    'sAMAccountName' => array( 0 => 'jdoe', 'count' => 1),
160

    
161
should return tokens such as:
162

    
163
    -- from dn attribute
164
    [cn] = jdoe
165
    [cn:0] = jdoe
166
    [cn:last] => jdoe
167
    [cn:reverse:0] = jdoe
168
    [ou] = campus accounts
169
    [ou:0] = campus accounts
170
    [ou:1] = toledo campus
171
    [ou:last] = toledo campus
172
    [ou:reverse:0] = toledo campus
173
    [ou:reverse:1] = campus accounts
174
    [dc] = ad
175
    [dc:0] = ad
176
    [dc:1] = myuniversity
177
    [dc:2] = edu
178
    [dc:last] = edu
179
    [dc:reverse:0] = edu
180
    [dc:reverse:1] = myuniversity
181
    [dc:reverse:2] = ad
182

    
183
    -- from other attributes
184
    [mail] = jdoe@myuniversity.edu
185
    [mail:0] = jdoe@myuniversity.edu
186
    [mail:last] = jdoe@myuniversity.edu
187
    [samaccountname] = jdoe
188
    [samaccountname:0] = jdoe
189
    [samaccountname:last] = jdoe
190

    
191
    [guid:0;base64_encode] = apply base64_encode() function to value
192
    [guid:0;bin2hex] = apply bin2hex() function to value
193
    [guid:0;msguid] = apply ldap_servers_msguid() function to value
194
    [guid:0;binary] = apply ldap_servers_binary() function to value. this is the most generic binary function
195

    
196
 */
197

    
198
function ldap_servers_token_tokenize_entry($ldap_entry, $token_keys = 'all', $pre = LDAP_SERVERS_TOKEN_PRE, $post = LDAP_SERVERS_TOKEN_POST) {
199

    
200
  $detailed_watchdog_log = variable_get('ldap_help_watchdog_detail', 0);
201
  $tokens = array();
202
  $watchdog_tokens = array();
203
  if (function_exists('debug_backtrace') && $backtrace = debug_backtrace()) {
204
    $watchdog_tokens['%calling_function'] = $backtrace[1]['function'];
205
  }
206
  if (!is_array($ldap_entry)) {
207
    if ($detailed_watchdog_log) {
208
      watchdog('ldap_servers', 'skipped tokenization of ldap entry because no ldap entry provided when called from %calling_function.', $watchdog_tokens, WATCHDOG_DEBUG);
209
    }
210
    return $tokens; // empty array
211
  }
212
      
213
  // add lowercase keyed entries to ldap array
214
  foreach ($ldap_entry as $key => $values) {
215
    $ldap_entry[drupal_strtolower($key)] = $values;
216
  }
217

    
218
  // 1. tokenize dn
219
  $dn_parts = ldap_explode_dn($ldap_entry['dn'], 0); // escapes attribute values, need to be unescaped later.
220
  unset($dn_parts['count']);
221
  $parts_count = array();
222
  $parts_last_value = array();
223
  foreach ($dn_parts as $pair) {
224
    list($attr_name, $attr_value) = explode('=', $pair);
225
    $attr_value = ldap_pear_unescape_dn_value($attr_value);
226
    try {
227
      $attr_value = check_plain($attr_value);
228
    }
229
    catch (Exception $e) {
230
      if ($detailed_watchdog_log) {
231
        $watchdog_tokens['%attr_name'] = $attr_name;
232
        watchdog('ldap_servers', 'skipped tokenization of attribute %attr_name because the value would not pass check_plain function.', $watchdog_tokens, WATCHDOG_DEBUG);
233
      }
234
      continue; // don't tokenize data that can't pass check_plain
235
    }
236
    if (!isset($parts_count[$attr_name])) {
237
      $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . $post] = $attr_value;
238
      $parts_count[$attr_name] = 0;
239
    }
240
    $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . (int)$parts_count[$attr_name] . $post] = $attr_value;
241

    
242
    $parts_last_value[$attr_name] = $attr_value;
243
    $parts_count[$attr_name]++;
244
  }
245

    
246
  // Add the parts in reverse order to reflect the hierarchy.
247
  foreach ($parts_count as $part => $count) {
248
    $part = strtolower($part);
249
    for ($i = 0; $i < $count; $i++) {
250
      $reverse_position = $count - $i - 1;
251
      $tokens[$pre . $part . LDAP_SERVERS_TOKEN_DEL . 'reverse' . LDAP_SERVERS_TOKEN_DEL . $reverse_position . $post] = $tokens[$pre . $part . LDAP_SERVERS_TOKEN_DEL . $i . $post];
252
    }
253
  }
254

    
255
  foreach ($parts_count as $attr_name => $count) {
256
    $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . 'last' . $post] = $parts_last_value[$attr_name];
257
  }
258

    
259
  // tokenize other attributes
260
  if ($token_keys == 'all') {
261
    $token_keys = array_keys($ldap_entry);
262
    $token_keys = array_filter($token_keys, "is_string");
263
    foreach ($token_keys as $attr_name) {
264
      $attr_value = $ldap_entry[$attr_name];
265
      if (is_array($attr_value) && is_scalar($attr_value[0]) && $attr_value['count'] == 1) {
266
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . $post] = check_plain($attr_value[0]);
267
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . '0' . $post] = check_plain($attr_value[0]);
268
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . 'last' . $post] = check_plain($attr_value[0]);
269
      }
270
      elseif (is_array($attr_value) && $attr_value['count'] > 1) {
271
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . 'last' . $post] = check_plain($attr_value[$attr_value['count'] - 1]);
272
        for ($i = 0; $i < $attr_value['count']; $i++) {
273
          $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . $i . $post] = check_plain($attr_value[$i]);
274
        }
275
      }
276
      elseif (is_scalar($attr_value)) {
277
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . $post] = check_plain($attr_value);
278
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . '0' . $post] = check_plain($attr_value);
279
        $tokens[$pre . ldap_server_massage_text($attr_name, 'attr_name', LDAP_SERVER_MASSAGE_TOKEN_REPLACE) . LDAP_SERVERS_TOKEN_DEL . 'last' . $post] = check_plain($attr_value);
280
      }
281
    }
282
  }
283
  else {
284
    foreach ($token_keys as $full_token_key) {
285
      // $token_key = 'dn', 'mail', 'mail:0', 'mail:last', 'dept:1', 'guid:0;tobase64etc.
286
      $value = NULL;
287

    
288
      $conversion = FALSE;
289
      $parts = explode(';', $full_token_key);
290
      if (count($parts) == 2) {
291
        $conversion = $parts[1];
292
        $token_key = $parts[0];
293
      }
294
      else {
295
        $token_key = $full_token_key;
296
      }
297

    
298
      $parts = explode(LDAP_SERVERS_TOKEN_DEL, $token_key);
299
      $attr_name = drupal_strtolower($parts[0]);
300
      $ordinal_key = isset($parts[1]) ? $parts[1] : 0;
301
      $i = NULL;
302

    
303
      if ($attr_name == 'dn' || !isset($ldap_entry[$attr_name])) { // don't use empty() since a 0, "", etc value may be a desired value
304
        continue;
305
      }
306
      else {
307
        $count = $ldap_entry[$attr_name]['count'];
308
        if ($ordinal_key === 'last') {
309
          $i = ($count > 0) ? $count - 1 : 0;
310
          $value = $ldap_entry[$attr_name][$i];
311
        }
312
        elseif (is_numeric($ordinal_key) || $ordinal_key == '0') {
313
          $value = $ldap_entry[$attr_name][$ordinal_key];
314
        }
315
        else {
316
          continue;  // don't add token if case not covered
317
        }
318
      }
319

    
320
      if ($conversion) {
321
        switch ($conversion) {
322

    
323
          case 'base64_encode':
324
            $value = base64_encode($value);
325
            break;
326

    
327
          case 'bin2hex':
328
            $value = bin2hex($value);
329
            break;
330

    
331
          case 'msguid':
332
            $value = ldap_servers_msguid($value);
333
            break;
334

    
335
          case 'binary':
336
            $value = ldap_servers_binary($value);
337
            break;
338
        }
339
      }
340

    
341

    
342
      $tokens[$pre . $full_token_key . $post] = $value;
343
      if ($full_token_key != drupal_strtolower($full_token_key)) {
344
        $tokens[$pre . drupal_strtolower($full_token_key) . $post] = $value;
345
      }
346
    }
347
  }
348

    
349
  // include the dn.  it will not be handled correctly by previous loops
350
  $tokens[$pre . 'dn' . $post] = check_plain($ldap_entry['dn']);
351
  return $tokens;
352
}
353

    
354
/**
355
 *
356
 * @param drupal user object $user_account
357
 * @param array or 'all' $token_keys 'all' signifies return
358
 *   all token/value pairs available; otherwise array lists
359
 *   token keys (e.g. property.name ...NOT [property.name])
360
 * @param string $pre prefix of token
361
 * @param string $post suffix of token
362
 *
363
 *
364
 * @return should return token/value pairs in array such as
365
 *   'status' => 1
366
 *   'uid' => 17
367
 */
368

    
369
function ldap_servers_token_tokenize_user_account($user_account, $token_keys = 'all', $pre = LDAP_SERVERS_TOKEN_PRE, $post = LDAP_SERVERS_TOKEN_POST) {
370

    
371
  $detailed_watchdog_log = variable_get('ldap_help_watchdog_detail', 0);
372
  $tokens = array();
373

    
374
  $user_entered_password_available = (boolean)ldap_user_ldap_provision_pwd('get');
375
  // ldapUserPwd((property_exists($user_account, 'ldapUserPwd') && $user_account->ldapUserPwd));
376

    
377
  if ($token_keys == 'all') {
378
    // add lowercase keyed entries to ldap array
379
    foreach ((array)$user_account as $property_name => $value) {
380
      if (is_scalar($value) && $property_name != 'password') {
381
        $token_keys[] = 'property.' . $property_name;
382
        if (drupal_strtolower($property_name) != $property_name) {
383
          $token_keys[] = 'property.' . drupal_strtolower($property_name);
384
        }
385
      }
386
      elseif (isset($user_account->{$attr_name}[LANGUAGE_NONE][0]['value']) && is_scalar($user_account->{$attr_name}[LANGUAGE_NONE][0]['value'])) {
387
        $token_keys[] = 'field.' . $property_name;
388
        if (drupal_strtolower($property_name) != $property_name) {
389
          $token_keys[] = 'field.' . drupal_strtolower($property_name);
390
        }
391
      }
392
      else {
393
        // field or property with no value, so no token can be generated
394
      }
395
    }
396
    $ldap_user_conf_admin = new LdapUserConfAdmin();
397
    if ($ldap_user_conf->setsLdapPassword) {
398
      $token_keys[] = 'password.random';
399
      $token_keys[] = 'password.user-random';
400
    }
401
  }
402

    
403
  foreach ($token_keys as $token_key) {
404
    $parts = explode('.', $token_key);
405
    $attr_type = $parts[0];
406
    $attr_name = $parts[1];
407
    $attr_conversion = (isset($parts[2])) ? $parts[2] : 'none';
408
    $value = FALSE;
409
    $skip = FALSE;
410

    
411
    switch ($attr_type) {
412
      case 'field':
413
        $value = @is_scalar($user_account->{$attr_name}[LANGUAGE_NONE][0]['value']) ? $user_account->{$attr_name}[LANGUAGE_NONE][0]['value'] : '';
414
      break;
415

    
416
      case 'property':
417
        $value = @is_scalar($user_account->{$attr_name}) ? $user_account->{$attr_name} : '';
418
      break;
419

    
420
      case 'password':
421

    
422
        switch ($attr_name) {
423

    
424
          case 'user':
425
          case 'user-only':
426
            $pwd = ldap_user_ldap_provision_pwd('get');
427
            $value = ($pwd) ? $pwd : NULL;
428
            break;
429

    
430
          case 'user-random':
431
            $pwd = ldap_user_ldap_provision_pwd('get');
432
            $value = ($pwd) ? $pwd : user_password();
433
            break;
434

    
435
          case 'random':
436
            $value = user_password();
437
            break;
438

    
439
        }
440
        if (empty($value)) {
441
          $skip = TRUE;
442
        }
443
      break;
444
    }
445

    
446
    if (!$skip) {
447

    
448
      switch ($attr_conversion) {
449

    
450
        case 'none':
451
          break;
452

    
453
        case 'to-md5':
454
          $value = "{MD5}" . base64_encode( pack( "H*", md5( $value ) ) );
455
          break;
456

    
457
        case 'to-lowercase':
458
          $value = drupal_strtolower($value);
459
          break;
460
      }
461

    
462
      $tokens[$pre . $token_key . $post] = ($attr_type == 'password') ? $value : check_plain($value);
463
      if ($token_key != drupal_strtolower($token_key)) {
464
        $tokens[$pre . drupal_strtolower($token_key) . $post] = ($attr_type == 'password') ? $value : check_plain($value);
465
      }
466
    }
467
  }
468
  return $tokens;
469
}
470

    
471
/**
472
 * @param string $template in form [cn]@myuniversity.edu
473
 * @return array of all tokens in the template such as array('cn')
474
 */
475
function ldap_servers_token_tokens_needed_for_template($template, $pre = LDAP_SERVERS_TOKEN_PRE, $post = LDAP_SERVERS_TOKEN_POST) {
476
  preg_match_all('/
477
    \[             # [ - pattern start
478
    ([^\[\]]*)  # match $type not containing whitespace : [ or ]
479
    \]             # ] - pattern end
480
    /x', $template, $matches);
481

    
482
  return @$matches[1];
483

    
484
}
485

    
486
function ldap_servers_token_show_sample_user_tokens($sid) {
487

    
488
  $ldap_server = ldap_servers_get_servers($sid, 'all', TRUE);
489
  $test_username = $ldap_server->testingDrupalUsername;
490
  if (!$test_username || ! (
491
    $ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_SERVICE_ACCT ||
492
    $ldap_server->bind_method == LDAP_SERVERS_BIND_METHOD_ANON
493
      )
494
    ) {
495
    return FALSE;
496
  }
497

    
498
  if ($ldap_user = $ldap_server->userUserNameToExistingLdapEntry($test_username)) {
499
    $table = theme('ldap_server_ldap_entry_table', array(
500
      'entry' => $ldap_user['attr'],
501
      'username' => $test_username,
502
      'dn' => $ldap_user['dn'],
503
      ));
504
  }
505
  else {
506
    $table = '<p>' . t('No sample user data found') . '</p>';
507
  }
508

    
509
  return $table;
510
}