Project

General

Profile

Paste
Download (6.83 KB) Statistics
| Branch: | Revision:

root / drupal7 / sites / all / modules / uuid / uuid.inc @ bf6fb0ee

1
<?php
2

    
3
/**
4
 * @file
5
 * Handling of universally unique identifiers.
6
 */
7

    
8
/**
9
 * Pattern for detecting a valid UUID.
10
 */
11
define('UUID_PATTERN', '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}');
12

    
13
/**
14
 * Generates an universally unique identifier.
15
 *
16
 * This function first checks for the PECL alternative for generating
17
 * universally unique identifiers. If that doesn't exist, then it falls back on
18
 * PHP for generating that.
19
 *
20
 * @return string
21
 *   An UUID, made up of 32 hex digits and 4 hyphens.
22
 */
23
function uuid_generate() {
24
  $callback = drupal_static(__FUNCTION__);
25

    
26
  if (empty($callback)) {
27
    if (function_exists('uuid_create') && !function_exists('uuid_make')) {
28
      $callback = '_uuid_generate_pecl';
29
    }
30
    elseif (function_exists('com_create_guid')) {
31
      $callback = '_uuid_generate_com';
32
    }
33
    else {
34
      $callback = '_uuid_generate_php';
35
    }
36
  }
37
  return $callback();
38
}
39

    
40
/**
41
 * Generates a version 5 compliant UUID.
42
 *
43
 * @param string $namespace
44
 *   Namespace UUID as a hex encoded string.
45
 * @param string $name
46
 *   The name for the generating the UUID.
47
 *
48
 * @return string
49
 *   UUID as a hex encoded string.
50
 *
51
 * @link http://www.php.net/manual/en/function.uniqid.php#94959 Code lifted from
52
 * PHP manual comment by Andrew Moore. @endlink
53
 */
54
function uuid_generate_v5($namespace, $name) {
55
  if (!uuid_is_valid($namespace)) {
56
    return FALSE;
57
  }
58

    
59
  // Get hexadecimal components of namespace.
60
  $nhex = str_replace(array('-', '{', '}'), '', $namespace);
61

    
62
  // Binary Value.
63
  $nstr = '';
64

    
65
  // Convert Namespace UUID to bits.
66
  for ($i = 0; $i < strlen($nhex); $i += 2) {
67
    $nstr .= chr(hexdec($nhex[$i] . $nhex[$i + 1]));
68
  }
69

    
70
  // Calculate hash value.
71
  $hash = sha1($nstr . $name);
72

    
73
  return sprintf('%08s-%04s-%04x-%04x-%12s',
74

    
75
    // 32 bits for "time_low".
76
    substr($hash, 0, 8),
77

    
78
    // 16 bits for "time_mid".
79
    substr($hash, 8, 4),
80

    
81
    // 16 bits for "time_hi_and_version",
82
    // four most significant bits holds version number 5.
83
    (hexdec(substr($hash, 12, 4)) & 0x0fff) | 0x5000,
84

    
85
    // 16 bits, 8 bits for "clk_seq_hi_res",
86
    // 8 bits for "clk_seq_low",
87
    // two most significant bits holds zero and one for variant DCE1.1.
88
    (hexdec(substr($hash, 16, 4)) & 0x3fff) | 0x8000,
89

    
90
    // 48 bits for "node".
91
    substr($hash, 20, 12)
92
  );
93
}
94

    
95
/**
96
 * Generate all missing UUIDs.
97
 */
98
function uuid_sync_all() {
99
  module_invoke_all('uuid_sync');
100
}
101

    
102
/**
103
 * Generates a UUID URI for an entity.
104
 *
105
 * @param object $entity
106
 *   The entity to use for generating the UUID URI.
107
 * @param string $entity_type
108
 *   The type of entity being used.
109
 *
110
 * @return string
111
 *   The generated UUID URI or normal URI if entity doesn't support UUIDs.
112
 */
113
function uuid_entity_uuid_uri($entity, $entity_type) {
114
  $entity_info = entity_get_info($entity_type);
115

    
116
  if (empty($entity_info['uuid'])) {
117
    $uri = $entity_info['uri callback']($entity);
118
    return $uri['path'];
119
  }
120

    
121
  if (isset($entity_info['uuid uri callback'])) {
122
    return $entity_info['uuid uri callback']($entity);
123
  }
124

    
125
  return "uuid/{$entity_type}/" . $entity->{$entity_info['entity keys']['uuid']};
126
}
127

    
128
/**
129
 * Converts an ID URI string to an entity data array.
130
 *
131
 * @param string $uri
132
 *   The URI to convert.
133
 *
134
 * @return array
135
 *   The entity data.
136
 *
137
 * @see uuid_id_uri_array_to_data()
138
 */
139
function uuid_id_uri_to_data($uri) {
140
  $parts = explode('/', $uri);
141
  return uuid_id_uri_array_to_data($parts);
142
}
143

    
144
/**
145
 * Converts a URI array to entity data array.
146
 *
147
 * @param array $uri
148
 *   The URI parts, often taken from arg().
149
 *
150
 * @return array
151
 *   The entity data.
152
 */
153
function uuid_id_uri_array_to_data($uri) {
154
  $data = array(
155
    'request' => $uri,
156
    'entity_type' => $uri[0],
157
    'id' => $uri[1],
158
  );
159

    
160
  drupal_alter('uuid_id_uri_data', $data);
161

    
162
  return $data;
163
}
164

    
165
/**
166
 * Converts a UUID URI string to an entity data array.
167
 *
168
 * @param string $uri
169
 *   The URI to convert.
170
 *
171
 * @return array
172
 *   The entity data.
173
 *
174
 * @see uuid_uri_array_to_data()
175
 */
176
function uuid_uri_to_data($uri, $strip_uuid = TRUE) {
177
  return uuid_uri_array_to_data(explode('/', $uri));
178
}
179

    
180
/**
181
 * Converts a URI array to entity data array.
182
 *
183
 * @param array $uri
184
 *   The URI parts, often taken from arg().
185
 *
186
 * @return array
187
 *   The entity data.
188
 */
189
function uuid_uri_array_to_data($uri, $strip_uuid = TRUE) {
190
  if ($strip_uuid) {
191
    array_shift($uri);
192
  }
193

    
194
  $data = array(
195
    'request' => $uri,
196
    'entity_type' => isset($uri[0]) ? $uri[0] : NULL,
197
    'uuid' => isset($uri[1]) ? $uri[1] : NULL,
198
  );
199

    
200
  drupal_alter('uuid_uri_data', $data);
201

    
202
  return $data;
203
}
204

    
205
/**
206
 * Generates a UUID using the Windows internal GUID generator.
207
 *
208
 * @see http://php.net/com_create_guid
209
 */
210
function _uuid_generate_com() {
211
  // Remove {} wrapper and make lower case to keep result consistent.
212
  return drupal_strtolower(trim(com_create_guid(), '{}'));
213
}
214

    
215
/**
216
 * Generates an universally unique identifier using the PECL extension.
217
 */
218
function _uuid_generate_pecl() {
219
  return uuid_create(UUID_TYPE_DEFAULT);
220
}
221

    
222
/**
223
 * Generates a UUID v4 (RFC 4122 section 4.4) using PHP code.
224
 *
225
 * @see http://www.rfc-editor.org/rfc/rfc4122.txt
226
 *
227
 * The UUID layout and fields are defined in section 4.1.2.
228
 *
229
 * Note that there are inconsistencies in the RFC with respect to
230
 * bit numbering. Network Order is correct, so the most significant bit
231
 * always appears first (in left-to-right sequence). See errata 3546:
232
 * http://www.rfc-editor.org/errata_search.php?rfc=4122&eid=3546
233
 *
234
 * Based on code from http://php.net/uniqid
235
 */
236
function _uuid_generate_php() {
237
  // We limit each generated number to 16 bits (maximum value 0xffff)
238
  // because mt_rand() returns a *signed* integer, and hence a 32-bit
239
  // value can only have a 31-bit magnitude. Constructing a 32-bit
240
  // number from two 16-bit random numbers guarantees that all 32 bits
241
  // are random.
242
  return sprintf('%04x%04x-%04x-4%03x-%04x-%04x%04x%04x',
243
    // 32 bits for "time_low".
244
    mt_rand(0, 0xffff), mt_rand(0, 0xffff),
245
    // 16 bits for "time_mid".
246
    mt_rand(0, 0xffff),
247
    // 12 bits after the initial 0100 (version 4) for "time_hi_and_version".
248
    mt_rand(0, 0x0fff),
249
    // 16 bits in total for "clk_seq_hi_res" and "clk_seq_low", with the
250
    // most significant 2 bits of clk_seq_hi_res set to '10'. We do a
251
    // bitwise OR of a random 14-bit value (maximum 0x3fff) with 0x8000
252
    // (a 16-bit integer with only the most significant bit set).
253
    mt_rand(0, 0x3fff) | 0x8000,
254
    // 48 bits for "node".
255
    mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
256
  );
257
}
258

    
259
// The if block avoids conflicts with PECL's uuid_is_valid().
260
if (!function_exists('uuid_is_valid')) {
261

    
262
  /**
263
   * Check that a string appears to be in the format of a UUID.
264
   *
265
   * @param string $uuid
266
   *   The string to test.
267
   *
268
   * @return bool
269
   *    TRUE if the string is well formed.
270
   */
271
  function uuid_is_valid($uuid) {
272
    return preg_match('/^' . UUID_PATTERN . '$/', $uuid);
273
  }
274

    
275
}