uuidtools 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (6) hide show
  1. data/CHANGELOG +2 -0
  2. data/README +10 -0
  3. data/install.rb +30 -0
  4. data/lib/uuidtools.rb +513 -0
  5. data/rakefile +112 -0
  6. metadata +46 -0
@@ -0,0 +1,2 @@
1
+ == UUIDTools 0.0.1
2
+ * parsing and generation of UUIDs implemented
data/README ADDED
@@ -0,0 +1,10 @@
1
+ UUIDTools was designed to be a simple library for generating any
2
+ of the various types of UUIDs.
3
+
4
+ == Example
5
+ UUID.md5_create(UUID_DNS_NAMESPACE, "www.widgets.com")
6
+ => #<UUID:0x287576 UUID:3d813cbb-47fb-32ba-91df-831e1593ac29>
7
+ UUID.sha1_create(UUID_DNS_NAMESPACE, "www.widgets.com")
8
+ => #<UUID:0x2a0116 UUID:21f7f8de-8051-5b89-8680-0195ef798b6a>
9
+ UUID.timestamp_create
10
+ => #<UUID:0x2adfdc UUID:64a5189c-25b3-11da-a97b-00c04fd430c8>
@@ -0,0 +1,30 @@
1
+ require 'rbconfig'
2
+ require 'find'
3
+ require 'ftools'
4
+
5
+ include Config
6
+
7
+ # this was adapted from rdoc's install.rb by ways of Log4r
8
+
9
+ $sitedir = CONFIG["sitelibdir"]
10
+ unless $sitedir
11
+ version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"]
12
+ $libdir = File.join(CONFIG["libdir"], "ruby", version)
13
+ $sitedir = $:.find {|x| x =~ /site_ruby/ }
14
+ if !$sitedir
15
+ $sitedir = File.join($libdir, "site_ruby")
16
+ elsif $sitedir !~ Regexp.quote(version)
17
+ $sitedir = File.join($sitedir, version)
18
+ end
19
+ end
20
+
21
+ # the acual gruntwork
22
+ Dir.chdir("lib")
23
+
24
+ Find.find("uuidtools.rb") { |f|
25
+ if f[-3..-1] == ".rb"
26
+ File::install(f, File.join($sitedir, *f.split(/\//)), 0644, true)
27
+ else
28
+ File::makedirs(File.join($sitedir, *f.split(/\//)))
29
+ end
30
+ }
@@ -0,0 +1,513 @@
1
+ #--
2
+ # Copyright (c) 2005 Robert Aman
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ UUID_TOOLS_VERSION = "0.1.0"
25
+
26
+ $:.unshift(File.dirname(__FILE__))
27
+
28
+ require 'uri'
29
+ require 'time'
30
+ require 'thread'
31
+ require 'digest/sha1'
32
+ require 'digest/md5'
33
+
34
+ # Because it's impossible to hype a UUID generator on its genuine merits,
35
+ # I give you... Really bad ASCII art in the comments:
36
+ #
37
+ # ..´´´ .'´``´´.´´´´´´´´´`´´´´´´ ´. ´`` ..
38
+ # SaSS99SSUaSSUaUkdaUa0SSUSkUUSXSF2T0BHEKEHHKEEH59,:::::::::::;L":?C1;:::::?
39
+ # EKQBHEBWBQBWHKKHHHEWgEBKgqQKEBEdcMMMMMMMMMMMMNBU.«l:,..,..:1C,----,?"??»(r
40
+ # EWHKKEBBHKBWEEWQKWKHBWHHWWHq9aLD"MMMMMMMMMMMMH0r7tPTOtlti6v--......-.:9QQS
41
+ # BEKKWWKKHKKHBEBWEEqKEHKR6uvTAUhGlMMMMMMMMMMMe?,.,!,rE».-v8q"`--,.,-,.teNMH
42
+ # EEBBgBBKKHEWBgKHKKREB8ZrPahUahalOMMMMMMMMMMA;?:!!-,,"DTkBMMP"..,-.,-,hEMMK
43
+ # EKWHRHHWEBEBEBgKHR3tY000Ya0a00h:eMMMMMMMMMqu-.l;».--.hqMMMMNP'.,-.,,ASMMME
44
+ # HqBNRNNkWKBEHBAv?"TahA0FvUhUUhG"eMMMMMMMMM4)««::;--,.Z5MMMMM8O:---?0XMMMMH
45
+ # K9NWHHaHRSoorrl0aU0ahU0nh0hhA01lHMMMMMMMMND',,-..--.,44MMMMMMBR5L8RHMMMMMB
46
+ # WEBqE86tuu00hLCUUUAA0U0a0AAUdb?LMMMMMMMMMMe´-,,.--,.;DHMMMMMMMMMMMMMMMMMME
47
+ # F54Dh0kSaADUAtSDhhh0h00AAU0ThalDMMMMMMMMMMR7,-..--,«0HMMMMMMMMMMMMMMMMMMME
48
+ # GDa00hbaUhAh0L9ahahaaUUU0hYhX»CNMMMMMMMMMMHOo;.,..!uuaNMMMMMMMMMMMMMMMMMMB
49
+ # OA0Ah9haUAUADAhaUAhD9Uaah0UUZ?5MMMMMMMMMM8O-,.--,-,,,tAEMMMMMMMMMMMMMMMMMB
50
+ # 0UhhhXhUP0F0USUAASvFkh0AaAhq;1HMMMMMMMMMAL.--,..---,--?FHMMMMMMMMMMMMMMMME
51
+ # AAA4bShUuaahhA0ahTOa00AFrUaQ"ULkWWBMMNMge":-,.;,,l.--,,P4MMMMMMMMMMMMMMMMB
52
+ # 0UuZkUAh0hhaAaa0dehA0U0YDAS4JhjdLQRLehXP-??"».j,1l--,-,-9HMMMMMMMMMMMMMMMH
53
+ # AhZASaSSUU0aAa0UAAUUhAahUhb;uWEge5L4gaHG9R67t"tc7?;;;l":aPMMMMMMMMMMMMMMMH
54
+ # Ua0akXqUaU9aaUa00hAS0aAaUkutHMMMMMNKELBZCBHSMMMNBa2";,"rAFMMMMMMMMMMMMMMMB
55
+ # AhdtSqSUAhXFh0UhAD1oP00hAq"hMMMMMMMMMOZ:-""PTkgWENMMMNEKHXKgHMMMMMMMMMMMMH
56
+ # aaT6UU0UAUuDaaAaa?G8S0aaqLuMMMMMMMMMM6L,,--!-..,-,:?1LhWNNMMHEEQgHMMMMMMMH
57
+ # L6JuuuLuLu1uLuuLIJuTLLuuJ"UqR8RqXqq8q2u-:::-:::::---:-::Tju6Rq8qqeuUqRRqqA
58
+ # ´. . ´´.´.` ´.´...´..´.'´. ´'.´ `.´`´´´ ´.´´'.´ ´´´ `´.´ ´`'´´.´' '.´.´´´
59
+ # ´ ´
60
+
61
+ #= uuidtools.rb
62
+ #
63
+ # UUIDTools was designed to be a simple library for generating any
64
+ # of the various types of UUIDs.
65
+ #
66
+ #== Example
67
+ # UUID.md5_create(UUID_DNS_NAMESPACE, "www.widgets.com")
68
+ # => #<UUID:0x287576 UUID:3d813cbb-47fb-32ba-91df-831e1593ac29>
69
+ # UUID.sha1_create(UUID_DNS_NAMESPACE, "www.widgets.com")
70
+ # => #<UUID:0x2a0116 UUID:21f7f8de-8051-5b89-8680-0195ef798b6a>
71
+ # UUID.timestamp_create
72
+ # => #<UUID:0x2adfdc UUID:64a5189c-25b3-11da-a97b-00c04fd430c8>
73
+ class UUID
74
+ @@last_timestamp = nil
75
+ @@last_node_id = nil
76
+ @@last_clock_sequence = nil
77
+ @@state_file = nil
78
+ @@mutex = Mutex.new
79
+
80
+ def initialize(time_low, time_mid, time_hi_and_version,
81
+ clock_seq_hi_and_reserved, clock_seq_low, nodes)
82
+ unless time_low >= 0 && time_low < 4294967296
83
+ raise ArgumentError,
84
+ "Expected unsigned 32-bit number for time_low, got #{time_low}."
85
+ end
86
+ unless time_mid >= 0 && time_mid < 65536
87
+ raise ArgumentError,
88
+ "Expected unsigned 16-bit number for time_mid, got #{time_mid}."
89
+ end
90
+ unless time_hi_and_version >= 0 && time_hi_and_version < 65536
91
+ raise ArgumentError,
92
+ "Expected unsigned 16-bit number for time_hi_and_version, " +
93
+ "got #{time_hi_and_version}."
94
+ end
95
+ unless clock_seq_hi_and_reserved >= 0 && clock_seq_hi_and_reserved < 256
96
+ raise ArgumentError,
97
+ "Expected unsigned 8-bit number for clock_seq_hi_and_reserved, " +
98
+ "got #{clock_seq_hi_and_reserved}."
99
+ end
100
+ unless clock_seq_low >= 0 && clock_seq_low < 256
101
+ raise ArgumentError,
102
+ "Expected unsigned 8-bit number for clock_seq_low, " +
103
+ "got #{clock_seq_low}."
104
+ end
105
+ unless nodes.respond_to? :size
106
+ raise ArgumentError,
107
+ "Expected nodes to respond to :size."
108
+ end
109
+ unless nodes.size == 6
110
+ raise ArgumentError,
111
+ "Expected nodes to have size of 6."
112
+ end
113
+ for node in nodes
114
+ unless node >= 0 && node < 256
115
+ raise ArgumentError,
116
+ "Expected unsigned 8-bit number for each node, " +
117
+ "got #{node}."
118
+ end
119
+ end
120
+ @time_low = time_low
121
+ @time_mid = time_mid
122
+ @time_hi_and_version = time_hi_and_version
123
+ @clock_seq_hi_and_reserved = clock_seq_hi_and_reserved
124
+ @clock_seq_low = clock_seq_low
125
+ @nodes = nodes
126
+ end
127
+
128
+ attr_accessor :time_low
129
+ attr_accessor :time_mid
130
+ attr_accessor :time_hi_and_version
131
+ attr_accessor :clock_seq_hi_and_reserved
132
+ attr_accessor :clock_seq_low
133
+ attr_accessor :nodes
134
+
135
+ # Parses a UUID from a string.
136
+ def UUID.parse(uuid_string)
137
+ unless uuid_string.kind_of? String
138
+ raise ArgumentError,
139
+ "Expected String, got #{uuid_string.class.name} instead."
140
+ end
141
+ uuid_components = uuid_string.downcase.scan(
142
+ Regexp.new("^([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-" +
143
+ "([0-9a-f]{2})([0-9a-f]{2})-([0-9a-f]{12})$")).first
144
+ raise ArgumentError, "Invalid UUID format." if uuid_components.nil?
145
+ time_low = uuid_components[0].to_i(16)
146
+ time_mid = uuid_components[1].to_i(16)
147
+ time_hi_and_version = uuid_components[2].to_i(16)
148
+ clock_seq_hi_and_reserved = uuid_components[3].to_i(16)
149
+ clock_seq_low = uuid_components[4].to_i(16)
150
+ nodes = []
151
+ for i in 0..5
152
+ nodes << uuid_components[5][(i * 2)..(i * 2) + 1].to_i(16)
153
+ end
154
+ return UUID.new(time_low, time_mid, time_hi_and_version,
155
+ clock_seq_hi_and_reserved, clock_seq_low, nodes)
156
+ end
157
+
158
+ # Parses a UUID from a raw byte string.
159
+ def UUID.parse_raw(raw_string)
160
+ unless raw_string.kind_of? String
161
+ raise ArgumentError,
162
+ "Expected String, got #{raw_string.class.name} instead."
163
+ end
164
+ integer = UUID.convert_byte_string_to_int(raw_string)
165
+
166
+ time_low = (integer >> 96) & 0xFFFFFFFF
167
+ time_mid = (integer >> 80) & 0xFFFF
168
+ time_hi_and_version = (integer >> 64) & 0xFFFF
169
+ clock_seq_hi_and_reserved = (integer >> 56) & 0xFF
170
+ clock_seq_low = (integer >> 48) & 0xFF
171
+ nodes = []
172
+ for i in 0..5
173
+ nodes << ((integer >> (40 - (i * 8))) & 0xFF)
174
+ end
175
+ return UUID.new(time_low, time_mid, time_hi_and_version,
176
+ clock_seq_hi_and_reserved, clock_seq_low, nodes)
177
+ end
178
+
179
+ # Creates a UUID from a random value.
180
+ def UUID.random_create()
181
+ new_uuid = UUID.parse_raw(UUID.true_random)
182
+ new_uuid.time_hi_and_version &= 0x0FFF
183
+ new_uuid.time_hi_and_version |= (4 << 12)
184
+ new_uuid.clock_seq_hi_and_reserved &= 0x3F
185
+ new_uuid.clock_seq_hi_and_reserved |= 0x80
186
+ return new_uuid
187
+ end
188
+
189
+ # Creates a UUID from a timestamp.
190
+ def UUID.timestamp_create(timestamp=nil)
191
+ # We need a lock here to prevent two threads from ever
192
+ # getting the same timestamp.
193
+ @@mutex.synchronize do
194
+ # Always use GMT to generate UUIDs.
195
+ gmt_timestamp = Time.now.gmtime
196
+ # Convert to 100 nanosecond blocks
197
+ gmt_timestamp_100_nanoseconds = (gmt_timestamp.tv_sec * 10000000) +
198
+ (gmt_timestamp.tv_usec * 10) + 0x01B21DD213814000
199
+ nodes = UUID.get_mac_address.split(":").collect do |octet|
200
+ octet.to_i(16)
201
+ end
202
+ node_id = 0
203
+ for i in 0..5
204
+ node_id += (nodes[i] << (40 - (i * 8)))
205
+ end
206
+ clock_sequence = @@last_clock_sequence
207
+ if clock_sequence.nil?
208
+ clock_sequence = UUID.convert_byte_string_to_int(UUID.true_random)
209
+ end
210
+ if @@last_node_id != nil && @@last_node_id != node_id
211
+ # The node id has changed. Change the clock id.
212
+ clock_sequence = UUID.convert_byte_string_to_int(UUID.true_random)
213
+ elsif @@last_timestamp != nil &&
214
+ gmt_timestamp_100_nanoseconds < @@last_timestamp
215
+ clock_sequence = clock_sequence + 1
216
+ end
217
+ @@last_timestamp = gmt_timestamp_100_nanoseconds
218
+ @@last_node_id = node_id
219
+ @@last_clock_sequence = clock_sequence
220
+
221
+ time_low = gmt_timestamp_100_nanoseconds & 0xFFFFFFFF
222
+ time_mid = ((gmt_timestamp_100_nanoseconds >> 32) & 0xFFFF)
223
+ time_hi_and_version = ((gmt_timestamp_100_nanoseconds >> 48) & 0x0FFF)
224
+ time_hi_and_version |= (1 << 12)
225
+ clock_seq_low = clock_sequence & 0xFF;
226
+ clock_seq_hi_and_reserved = (clock_sequence & 0x3F00) >> 8
227
+ clock_seq_hi_and_reserved |= 0x80
228
+
229
+ return UUID.new(time_low, time_mid, time_hi_and_version,
230
+ clock_seq_hi_and_reserved, clock_seq_low, nodes)
231
+ end
232
+ end
233
+
234
+ # Creates a UUID using the MD5 hash. (Version 3)
235
+ def UUID.md5_create(namespace, name)
236
+ return UUID.create_from_hash(Digest::MD5, namespace, name)
237
+ end
238
+
239
+ # Creates a UUID using the SHA1 hash. (Version 5)
240
+ def UUID.sha1_create(namespace, name)
241
+ return UUID.create_from_hash(Digest::SHA1, namespace, name)
242
+ end
243
+
244
+ # This method applies only to version 1 UUIDs.
245
+ # Checks if the node ID was generated from a random number
246
+ # or from an IEEE 802 address (MAC address).
247
+ # Always returns false for UUIDs that aren't version 1.
248
+ # This should not be confused with version 4 UUIDs where
249
+ # more than just the node id is random.
250
+ def random_node_id?
251
+ return false if self.version != 1
252
+ return ((self.nodes.first & 0x01) == 1)
253
+ end
254
+
255
+ # Returns true if this UUID is the
256
+ # nil UUID (00000000-0000-0000-0000-000000000000).
257
+ def nil_uuid?
258
+ return false if self.time_low != 0
259
+ return false if self.time_mid != 0
260
+ return false if self.time_hi_and_version != 0
261
+ return false if self.clock_seq_hi_and_reserved != 0
262
+ return false if self.clock_seq_low != 0
263
+ self.nodes.each do |node|
264
+ return false if node != 0
265
+ end
266
+ return true
267
+ end
268
+
269
+ # Returns the UUID version type.
270
+ # Possible values:
271
+ # 1 - Time-based with unique or random host identifier
272
+ # 2 - DCE Security version (with POSIX UIDs)
273
+ # 3 - Name-based (MD5 hash)
274
+ # 4 - Random
275
+ # 5 - Name-based (SHA-1 hash)
276
+ def version
277
+ return (time_hi_and_version >> 12)
278
+ end
279
+
280
+ # Returns the UUID variant.
281
+ # Possible values:
282
+ # 0x000 - Reserved, NCS backward compatibility.
283
+ # 0x100 - The variant specified in this document.
284
+ # 0x110 - Reserved, Microsoft Corporation backward compatibility.
285
+ # 0x111 - Reserved for future definition.
286
+ def variant
287
+ variant_raw = (clock_seq_hi_and_reserved >> 5)
288
+ result = nil
289
+ if (variant_raw >> 2) == 0
290
+ result = 0x000
291
+ elsif (variant_raw >> 1) == 2
292
+ result = 0x100
293
+ else
294
+ result = variant_raw
295
+ end
296
+ return result
297
+ end
298
+
299
+ # Returns the IEEE 802 address used to generate this UUID or
300
+ # nil if a MAC address was not used.
301
+ def mac_address
302
+ return nil if self.version != 1
303
+ return nil if self.random_node_id?
304
+ return (self.nodes.collect do |node|
305
+ sprintf("%2.2x", node)
306
+ end).join(":")
307
+ end
308
+
309
+ # Returns the timestamp used to generate this UUID
310
+ def timestamp
311
+ return nil if self.version != 1
312
+ gmt_timestamp_100_nanoseconds = 0
313
+ gmt_timestamp_100_nanoseconds +=
314
+ ((self.time_hi_and_version & 0x0FFF) << 48)
315
+ gmt_timestamp_100_nanoseconds += (self.time_mid << 32)
316
+ gmt_timestamp_100_nanoseconds += self.time_low
317
+ return Time.at(
318
+ (gmt_timestamp_100_nanoseconds - 0x01B21DD213814000) / 10000000.0)
319
+ end
320
+
321
+ # Compares two UUIDs lexically
322
+ def <=>(other_uuid)
323
+ check = self.time_low <=> other_uuid.time_low
324
+ return check if check != 0
325
+ check = self.time_mid <=> other_uuid.time_mid
326
+ return check if check != 0
327
+ check = self.time_hi_and_version <=> other_uuid.time_hi_and_version
328
+ return check if check != 0
329
+ check = self.clock_seq_hi_and_reserved <=>
330
+ other_uuid.clock_seq_hi_and_reserved
331
+ return check if check != 0
332
+ check = self.clock_seq_low <=> other_uuid.clock_seq_low
333
+ return check if check != 0
334
+ for i in 0..5
335
+ if (self.nodes[i] < other_uuid.nodes[i])
336
+ return -1
337
+ end
338
+ if (self.nodes[i] > other_uuid.nodes[i])
339
+ return 1
340
+ end
341
+ end
342
+ return 0
343
+ end
344
+
345
+ # Returns a representation of the object's state
346
+ def inspect
347
+ return "#<UUID:0x#{self.object_id.to_s(16)} UUID:#{self.to_s}>"
348
+ end
349
+
350
+ # Returns the hex digest of the UUID object.
351
+ def hexdigest
352
+ return self.to_i.to_s(16)
353
+ end
354
+
355
+ # Returns the raw bytes that represent this UUID.
356
+ def raw
357
+ return UUID.convert_int_to_byte_string(self.to_i, 16)
358
+ end
359
+
360
+ # Returns a string representation for this UUID.
361
+ def to_s
362
+ result = sprintf("%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", @time_low, @time_mid,
363
+ @time_hi_and_version, @clock_seq_hi_and_reserved, @clock_seq_low);
364
+ for i in 0..5
365
+ result << sprintf("%2.2x", @nodes[i])
366
+ end
367
+ return result
368
+ end
369
+
370
+ # Returns an integer representation for this UUID.
371
+ def to_i
372
+ bytes = (time_low << 96) + (time_mid << 80) +
373
+ (time_hi_and_version << 64) + (clock_seq_hi_and_reserved << 56) +
374
+ (clock_seq_low << 48)
375
+ for i in 0..5
376
+ bytes += (nodes[i] << (40 - (i * 8)))
377
+ end
378
+ return bytes
379
+ end
380
+
381
+ # Returns a URI for this UUID.
382
+ def to_uri
383
+ return URI.parse(self.to_uri_string)
384
+ end
385
+
386
+ # Returns a URI string for this UUID.
387
+ def to_uri_string
388
+ return "urn:uuid:#{self.to_s}"
389
+ end
390
+
391
+ def UUID.create_from_hash(hash_class, namespace, name)
392
+ if hash_class == Digest::MD5
393
+ version = 3
394
+ elsif hash_class == Digest::SHA1
395
+ version = 5
396
+ else
397
+ raise ArgumentError,
398
+ "Expected Digest::SHA1 or Digest::MD5, got #{hash_class.name}."
399
+ end
400
+ hash = hash_class.new
401
+ hash.update(namespace.raw)
402
+ hash.update(name)
403
+ hash_string = hash.to_s[0..31]
404
+ new_uuid = UUID.parse("#{hash_string[0..7]}-#{hash_string[8..11]}-" +
405
+ "#{hash_string[12..15]}-#{hash_string[16..19]}-#{hash_string[20..31]}")
406
+
407
+ new_uuid.time_hi_and_version &= 0x0FFF
408
+ new_uuid.time_hi_and_version |= (version << 12)
409
+ new_uuid.clock_seq_hi_and_reserved &= 0x3F
410
+ new_uuid.clock_seq_hi_and_reserved |= 0x80
411
+ return new_uuid
412
+ end
413
+
414
+ # Returns the MAC address of the current computer's network card.
415
+ # Returns nil if a MAC address could not be found.
416
+ def UUID.get_mac_address
417
+ if RUBY_PLATFORM =~ /win/ && !(RUBY_PLATFORM =~ /darwin/)
418
+ begin
419
+ ifconfig_output = `ipconfig /all`
420
+ mac_addresses = ifconfig_output.scan(
421
+ Regexp.new("(#{(["[0-9A-F]{2}"] * 6).join("-")})"))
422
+ if mac_addresses.size > 0
423
+ return mac_addresses.first.first.downcase.gsub(/-/, ":")
424
+ end
425
+ rescue
426
+ end
427
+ else
428
+ begin
429
+ ifconfig_output = `ifconfig`
430
+ mac_addresses = ifconfig_output.scan(
431
+ Regexp.new("ether (#{(["[0-9a-f]{2}"] * 6).join(":")})"))
432
+ if mac_addresses.size == 0
433
+ ifconfig_output = `ifconfig | grep HWaddr | cut -c39-`
434
+ mac_addresses = ifconfig_output.scan(
435
+ Regexp.new("(#{(["[0-9a-f]{2}"] * 6).join(":")})"))
436
+ end
437
+ if mac_addresses.size == 0
438
+ ifconfig_output = `/sbin/ifconfig`
439
+ mac_addresses = ifconfig_output.scan(
440
+ Regexp.new("ether (#{(["[0-9a-f]{2}"] * 6).join(":")})"))
441
+ end
442
+ if mac_addresses.size == 0
443
+ ifconfig_output = `/sbin/ifconfig | grep HWaddr | cut -c39-`
444
+ mac_addresses = ifconfig_output.scan(
445
+ Regexp.new("(#{(["[0-9a-f]{2}"] * 6).join(":")})"))
446
+ end
447
+ if mac_addresses.size > 0
448
+ return mac_addresses.first.first
449
+ end
450
+ rescue
451
+ end
452
+ end
453
+ end
454
+
455
+ # Returns 128 bits of highly unpredictable data.
456
+ def UUID.true_random
457
+ require 'benchmark'
458
+ hash = Digest::SHA1.new
459
+ performance = Benchmark.measure do
460
+ hash.update(rand.to_s)
461
+ hash.update(srand.to_s)
462
+ hash.update(rand.to_s)
463
+ hash.update(srand.to_s)
464
+ hash.update(Time.now.to_s)
465
+ hash.update(rand.to_s)
466
+ hash.update(self.object_id.to_s)
467
+ hash.update(rand.to_s)
468
+ hash.update(hash.object_id.to_s)
469
+ hash.update(self.methods.inspect)
470
+ begin
471
+ random_device = nil
472
+ if File.exists? "/dev/urandom"
473
+ random_device = File.open "/dev/urandom", "r"
474
+ elsif File.exists? "/dev/random"
475
+ random_device = File.open "/dev/random", "r"
476
+ end
477
+ hash.update(random_device.read(20)) if random_device != nil
478
+ rescue
479
+ end
480
+ begin
481
+ srand(hash.to_s.to_i(16) >> 128)
482
+ rescue
483
+ end
484
+ hash.update(rand.to_s)
485
+ hash.update(UUID.true_random) if (rand(2) == 0)
486
+ end
487
+ hash.update(performance.real.to_s)
488
+ hash.update(performance.inspect)
489
+ return UUID.convert_int_to_byte_string(hash.to_s[4..35].to_i(16), 16)
490
+ end
491
+
492
+ def UUID.convert_int_to_byte_string(integer, size)
493
+ byte_string = ""
494
+ for i in 0..(size - 1)
495
+ byte_string << ((integer >> (((size - 1) - i) * 8)) & 0xFF)
496
+ end
497
+ return byte_string
498
+ end
499
+
500
+ def UUID.convert_byte_string_to_int(byte_string)
501
+ integer = 0
502
+ size = byte_string.size
503
+ for i in 0..(size - 1)
504
+ integer += (byte_string[i] << (((size - 1) - i) * 8))
505
+ end
506
+ return integer
507
+ end
508
+ end
509
+
510
+ UUID_DNS_NAMESPACE = UUID.parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
511
+ UUID_URL_NAMESPACE = UUID.parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
512
+ UUID_OID_NAMESPACE = UUID.parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
513
+ UUID_X500_NAMESPACE = UUID.parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
@@ -0,0 +1,112 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/contrib/rubyforgepublisher'
8
+
9
+ PKG_NAME = 'uuidtools'
10
+ PKG_VERSION = '0.1.0'
11
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
12
+
13
+ RELEASE_NAME = "REL #{PKG_VERSION}"
14
+
15
+ RUBY_FORGE_PROJECT = "uuidtools"
16
+ RUBY_FORGE_USER = "vacindak"
17
+
18
+ PKG_FILES = FileList[
19
+ "lib/**/*", "test/**/*", "examples/**/*", "doc/**/*", "[A-Z]*", "install.rb", "rakefile"
20
+ ].exclude(/\bCVS\b|~$/).exclude(/database\.yml/)
21
+
22
+ desc "Default Task"
23
+ task :default => [ :test_all ]
24
+
25
+ # Run the unit tests
26
+
27
+ Rake::TestTask.new("test_all") { |t|
28
+ t.libs << "test"
29
+ t.pattern = 'test/*_test.rb'
30
+ t.verbose = true
31
+ }
32
+
33
+ # Generate the RDoc documentation
34
+
35
+ Rake::RDocTask.new { |rdoc|
36
+ rdoc.rdoc_dir = 'doc'
37
+ rdoc.title = "UUID Tools -- universally unique id generation tools"
38
+ rdoc.options << '--line-numbers --inline-source --accessor cattr_accessor=object'
39
+ rdoc.template = "#{ENV['template']}.rb" if ENV['template']
40
+ rdoc.rdoc_files.include('README', 'CHANGELOG')
41
+ rdoc.rdoc_files.include('lib/**/*.rb')
42
+ }
43
+
44
+ # Create compressed packages
45
+
46
+ dist_dirs = [ "lib", "test" ]
47
+
48
+ spec = Gem::Specification.new do |s|
49
+ s.name = PKG_NAME
50
+ s.version = PKG_VERSION
51
+ s.summary = "Generation of UUIDs."
52
+ s.description = "Implements a simple system for generating UUIDs."
53
+
54
+ s.files = [ "rakefile", "install.rb", "README", "CHANGELOG" ]
55
+ dist_dirs.each do |dir|
56
+ s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if do |item|
57
+ item.include?( "\.svn" ) || item.include?( "database\.yml" )
58
+ end
59
+ end
60
+
61
+ s.require_path = 'lib'
62
+ s.autorequire = 'uuidtools'
63
+
64
+ s.has_rdoc = true
65
+ s.extra_rdoc_files = %w( README )
66
+ s.rdoc_options.concat ['--main', 'README']
67
+
68
+ s.author = "Bob Aman"
69
+ s.email = "bob@sporkmonger.com"
70
+ s.homepage = "http://sporkmonger.com/projects/uuidtools"
71
+ s.rubyforge_project = "uuidtools"
72
+ end
73
+
74
+ Rake::GemPackageTask.new(spec) do |p|
75
+ p.gem_spec = spec
76
+ p.need_tar = true
77
+ p.need_zip = true
78
+ end
79
+
80
+ task :lines do
81
+ lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
82
+
83
+ for file_name in FileList["lib/**/*.rb"]
84
+ f = File.open(file_name)
85
+
86
+ while line = f.gets
87
+ lines += 1
88
+ next if line =~ /^\s*$/
89
+ next if line =~ /^\s*#/
90
+ codelines += 1
91
+ end
92
+ puts "L: #{sprintf("%4d", lines)}, LOC #{sprintf("%4d", codelines)} | #{file_name}"
93
+
94
+ total_lines += lines
95
+ total_codelines += codelines
96
+
97
+ lines, codelines = 0, 0
98
+ end
99
+
100
+ puts "Total: Lines #{total_lines}, LOC #{total_codelines}"
101
+ end
102
+
103
+
104
+ # Publishing ------------------------------------------------------
105
+
106
+ desc "Publish the API documentation"
107
+ task :pdoc => [:rdoc] do
108
+ Rake::SshDirPublisher.new(
109
+ "vacindak@sporkmonger.com",
110
+ "public_html/projects/uuidtools/api",
111
+ "doc").upload
112
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: uuidtools
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2005-09-15 00:00:00 -04:00
8
+ summary: Generation of UUIDs.
9
+ require_paths:
10
+ - lib
11
+ email: bob@sporkmonger.com
12
+ homepage: http://sporkmonger.com/projects/uuidtools
13
+ rubyforge_project: uuidtools
14
+ description: Implements a simple system for generating UUIDs.
15
+ autorequire: uuidtools
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
25
+ version:
26
+ platform: ruby
27
+ signing_key:
28
+ cert_chain:
29
+ authors:
30
+ - Bob Aman
31
+ files:
32
+ - rakefile
33
+ - install.rb
34
+ - README
35
+ - CHANGELOG
36
+ - lib/uuidtools.rb
37
+ test_files: []
38
+ rdoc_options:
39
+ - "--main"
40
+ - README
41
+ extra_rdoc_files:
42
+ - README
43
+ executables: []
44
+ extensions: []
45
+ requirements: []
46
+ dependencies: []