facter 1.6.18 → 1.7.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of facter might be problematic. Click here for more details.

Files changed (126) hide show
  1. data/Gemfile +23 -8
  2. data/bin/facter +4 -1
  3. data/ext/build_defaults.yaml +1 -1
  4. data/ext/debian/changelog.erb +4 -22
  5. data/ext/debian/control +2 -2
  6. data/ext/project_data.yaml +1 -1
  7. data/ext/redhat/facter.spec.erb +10 -9
  8. data/install.rb +27 -53
  9. data/lib/facter.rb +23 -5
  10. data/lib/facter/application.rb +21 -0
  11. data/lib/facter/blockdevices.rb +105 -0
  12. data/lib/facter/domain.rb +19 -7
  13. data/lib/facter/filesystems.rb +38 -0
  14. data/lib/facter/hardwaremodel.rb +3 -2
  15. data/lib/facter/ipaddress6.rb +1 -2
  16. data/lib/facter/kernelrelease.rb +10 -2
  17. data/lib/facter/ldom.rb +47 -0
  18. data/lib/facter/macaddress.rb +1 -1
  19. data/lib/facter/manufacturer.rb +7 -1
  20. data/lib/facter/memory.rb +58 -160
  21. data/lib/facter/operatingsystem.rb +17 -2
  22. data/lib/facter/operatingsystemmajrelease.rb +33 -0
  23. data/lib/facter/operatingsystemrelease.rb +88 -37
  24. data/lib/facter/osfamily.rb +6 -2
  25. data/lib/facter/processor.rb +2 -2
  26. data/lib/facter/ps.rb +5 -0
  27. data/lib/facter/ssh.rb +50 -12
  28. data/lib/facter/util/cfpropertylist.rb +6 -0
  29. data/lib/facter/util/cfpropertylist/LICENSE +19 -0
  30. data/lib/facter/util/cfpropertylist/README +44 -0
  31. data/lib/facter/util/cfpropertylist/Rakefile +44 -0
  32. data/lib/facter/util/cfpropertylist/THANKS +7 -0
  33. data/lib/facter/util/cfpropertylist/lib/cfpropertylist.rb +6 -0
  34. data/lib/facter/util/cfpropertylist/lib/rbBinaryCFPropertyList.rb +562 -0
  35. data/lib/facter/util/cfpropertylist/lib/rbCFPlistError.rb +26 -0
  36. data/lib/facter/util/cfpropertylist/lib/rbCFPropertyList.rb +402 -0
  37. data/lib/facter/util/cfpropertylist/lib/rbCFTypes.rb +244 -0
  38. data/lib/facter/util/cfpropertylist/lib/rbLibXMLParser.rb +135 -0
  39. data/lib/facter/util/cfpropertylist/lib/rbNokogiriParser.rb +140 -0
  40. data/lib/facter/util/cfpropertylist/lib/rbREXMLParser.rb +136 -0
  41. data/lib/facter/util/collection.rb +36 -14
  42. data/lib/facter/util/composite_loader.rb +12 -0
  43. data/lib/facter/util/config.rb +36 -0
  44. data/lib/facter/util/confine.rb +1 -6
  45. data/lib/facter/util/directory_loader.rb +83 -0
  46. data/lib/facter/util/fact.rb +49 -42
  47. data/lib/facter/util/file_read.rb +32 -0
  48. data/lib/facter/util/ip.rb +2 -9
  49. data/lib/facter/util/loader.rb +16 -2
  50. data/lib/facter/util/macosx.rb +15 -2
  51. data/lib/facter/util/memory.rb +154 -27
  52. data/lib/facter/util/nothing_loader.rb +15 -0
  53. data/lib/facter/util/parser.rb +141 -0
  54. data/lib/facter/util/processor.rb +27 -35
  55. data/lib/facter/util/resolution.rb +97 -26
  56. data/lib/facter/util/solaris_zones.rb +153 -0
  57. data/lib/facter/util/virtual.rb +32 -3
  58. data/lib/facter/version.rb +72 -2
  59. data/lib/facter/virtual.rb +56 -3
  60. data/lib/facter/zfs_version.rb +10 -0
  61. data/lib/facter/zonename.rb +6 -0
  62. data/lib/facter/zones.rb +17 -0
  63. data/lib/facter/zpool_version.rb +10 -0
  64. data/spec/fixtures/ifconfig/ifconfig_net_tools_1.60.txt +19 -0
  65. data/spec/fixtures/ifconfig/ifconfig_ubuntu_1204.txt +16 -0
  66. data/spec/fixtures/ldom/ldom_v1 +6 -0
  67. data/spec/fixtures/unit/filesystems/linux +28 -0
  68. data/spec/fixtures/unit/util/manufacturer/intel_linux_dmidecode +549 -0
  69. data/spec/fixtures/unit/virtual/sysfs_dmi_entries_raw.txt +0 -0
  70. data/spec/fixtures/unit/zfs_version/freebsd_8.2 +14 -0
  71. data/spec/fixtures/unit/zfs_version/freebsd_9.0 +13 -0
  72. data/spec/fixtures/unit/zfs_version/linux-fuse_0.6.9 +14 -0
  73. data/spec/fixtures/unit/zfs_version/solaris_10 +10 -0
  74. data/spec/fixtures/unit/zfs_version/solaris_11 +12 -0
  75. data/spec/fixtures/unit/zpool_version/freebsd_8.2 +26 -0
  76. data/spec/fixtures/unit/zpool_version/freebsd_9.0 +38 -0
  77. data/spec/fixtures/unit/zpool_version/linux-fuse_0.6.9 +35 -0
  78. data/spec/fixtures/unit/zpool_version/solaris_10 +31 -0
  79. data/spec/fixtures/unit/zpool_version/solaris_11 +43 -0
  80. data/spec/integration/facter_spec.rb +12 -0
  81. data/spec/spec_helper.rb +9 -0
  82. data/spec/unit/architecture_spec.rb +1 -1
  83. data/spec/unit/blockdevices_spec.rb +109 -0
  84. data/spec/unit/domain_spec.rb +189 -81
  85. data/spec/unit/ec2_spec.rb +15 -8
  86. data/spec/unit/filesystems_spec.rb +50 -0
  87. data/spec/unit/hardwaremodel_spec.rb +8 -1
  88. data/spec/unit/id_spec.rb +6 -5
  89. data/spec/unit/ipaddress6_spec.rb +14 -2
  90. data/spec/unit/ipaddress_spec.rb +1 -1
  91. data/spec/unit/kernel_spec.rb +24 -0
  92. data/spec/unit/kernelmajversion_spec.rb +17 -0
  93. data/spec/unit/kernelrelease_spec.rb +53 -0
  94. data/spec/unit/kernelversion_spec.rb +32 -0
  95. data/spec/unit/ldom_spec.rb +74 -0
  96. data/spec/unit/macaddress_spec.rb +3 -1
  97. data/spec/unit/manufacturer_spec.rb +115 -0
  98. data/spec/unit/memory_spec.rb +442 -75
  99. data/spec/unit/operatingsystem_spec.rb +16 -2
  100. data/spec/unit/operatingsystemmajrelease_spec.rb +16 -0
  101. data/spec/unit/operatingsystemrelease_spec.rb +110 -1
  102. data/spec/unit/processor_spec.rb +22 -7
  103. data/spec/unit/ps_spec.rb +42 -0
  104. data/spec/unit/ssh_spec.rb +76 -0
  105. data/spec/unit/util/collection_spec.rb +94 -118
  106. data/spec/unit/util/config_spec.rb +36 -5
  107. data/spec/unit/util/confine_spec.rb +31 -43
  108. data/spec/unit/util/directory_loader_spec.rb +87 -0
  109. data/spec/unit/util/fact_spec.rb +37 -25
  110. data/spec/unit/util/file_read_spec.rb +29 -0
  111. data/spec/unit/util/ip_spec.rb +4 -2
  112. data/spec/unit/util/loader_spec.rb +102 -45
  113. data/spec/unit/util/macosx_spec.rb +40 -9
  114. data/spec/unit/util/manufacturer_spec.rb +12 -1
  115. data/spec/unit/util/parser_spec.rb +135 -0
  116. data/spec/unit/util/resolution_spec.rb +136 -4
  117. data/spec/unit/util/solaris_zones_spec.rb +127 -0
  118. data/spec/unit/util/virtual_spec.rb +54 -0
  119. data/spec/unit/version_spec.rb +42 -0
  120. data/spec/unit/virtual_spec.rb +102 -27
  121. data/spec/unit/zfs_version_spec.rb +76 -0
  122. data/spec/unit/zonename_spec.rb +14 -0
  123. data/spec/unit/zones_spec.rb +55 -0
  124. data/spec/unit/zpool_version_spec.rb +76 -0
  125. metadata +113 -11
  126. data/lib/facter/arp.rb +0 -28
@@ -0,0 +1,26 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Exceptions used:
4
+ # CFPlistError:: General base exception
5
+ # CFFormatError:: Format error
6
+ # CFTypeError:: Type error
7
+ #
8
+ # Easy and simple :-)
9
+ #
10
+ # Author:: Christian Kruse (mailto:cjk@wwwtech.de)
11
+ # Copyright:: Copyright (c) 2010
12
+ # License:: MIT License
13
+
14
+ # general plist error. All exceptions thrown are derived from this class.
15
+ class CFPlistError < Exception
16
+ end
17
+
18
+ # Exception thrown when format errors occur
19
+ class CFFormatError < CFPlistError
20
+ end
21
+
22
+ # Exception thrown when type errors occur
23
+ class CFTypeError < CFPlistError
24
+ end
25
+
26
+ # eof
@@ -0,0 +1,402 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'kconv'
4
+ require 'date'
5
+ require 'time'
6
+
7
+ #
8
+ # Facter::Util::CFPropertyList implementation
9
+ #
10
+ # class to read, manipulate and write both XML and binary property list
11
+ # files (plist(5)) as defined by Apple. Have a look at Facter::Util::CFPropertyList::List
12
+ # for more documentation.
13
+ #
14
+ # == Example
15
+ # require 'cfpropertylist'
16
+ #
17
+ # # create a arbitrary data structure of basic data types
18
+ # data = {
19
+ # 'name' => 'John Doe',
20
+ # 'missing' => true,
21
+ # 'last_seen' => Time.now,
22
+ # 'friends' => ['Jane Doe','Julian Doe'],
23
+ # 'likes' => {
24
+ # 'me' => false
25
+ # }
26
+ # }
27
+ #
28
+ # # create Facter::Util::CFPropertyList::List object
29
+ # plist = Facter::Util::CFPropertyList::List.new
30
+ #
31
+ # # call Facter::Util::CFPropertyList.guess() to create corresponding CFType values
32
+ # # pass in optional :convert_unknown_to_string => true to convert things like symbols into strings.
33
+ # plist.value = Facter::Util::CFPropertyList.guess(data)
34
+ #
35
+ # # write plist to file
36
+ # plist.save("example.plist", Facter::Util::CFPropertyList::List::FORMAT_BINARY)
37
+ #
38
+ # # … later, read it again
39
+ # plist = Facter::Util::CFPropertyList::List.new(:file => "example.plist")
40
+ # data = Facter::Util::CFPropertyList.native_types(plist.value)
41
+ #
42
+ # Author:: Christian Kruse (mailto:cjk@wwwtech.de)
43
+ # Copyright:: Copyright (c) 2010
44
+ # License:: MIT License
45
+ module Facter::Util::CFPropertyList
46
+ # interface class for PList parsers
47
+ class ParserInterface
48
+ # load a plist
49
+ def load(opts={})
50
+ return ""
51
+ end
52
+
53
+ # convert a plist to string
54
+ def to_str(opts={})
55
+ return true
56
+ end
57
+ end
58
+
59
+ class XMLParserInterface < ParserInterface
60
+ def new_node(name)
61
+ end
62
+
63
+ def new_text(val)
64
+ end
65
+
66
+ def append_node(parent, child)
67
+ end
68
+ end
69
+ end
70
+
71
+ class String
72
+ unless("".respond_to?(:blob) && "".respond_to?(:blob=)) then
73
+ # The blob status of this string (to set to true if a binary string)
74
+ attr_accessor :blob
75
+ end
76
+
77
+ unless("".respond_to?(:blob?)) then
78
+ # Returns whether or not +str+ is a blob.
79
+ # @return [true,false] If true, this string contains binary data. If false, its a regular string
80
+ def blob?
81
+ blob
82
+ end
83
+ end
84
+
85
+ unless("".respond_to?(:bytesize)) then
86
+ def bytesize
87
+ self.length
88
+ end
89
+ end
90
+ end
91
+
92
+ dirname = File.dirname(__FILE__)
93
+ require dirname + '/rbCFPlistError.rb'
94
+ require dirname + '/rbCFTypes.rb'
95
+ require dirname + '/rbBinaryCFPropertyList.rb'
96
+
97
+ require 'iconv' unless "".respond_to?("encode")
98
+
99
+ begin
100
+ Enumerable::Enumerator.new([])
101
+ rescue NameError => e
102
+ module Enumerable
103
+ class Enumerator
104
+ end
105
+ end
106
+ end
107
+
108
+ begin
109
+ require dirname + '/rbLibXMLParser.rb'
110
+ try_nokogiri = false
111
+ rescue LoadError => e
112
+ try_nokogiri = true
113
+ end
114
+
115
+ if try_nokogiri then
116
+ begin
117
+ require dirname + '/rbNokogiriParser.rb'
118
+ rescue LoadError => e
119
+ require dirname + '/rbREXMLParser.rb'
120
+ end
121
+ end
122
+
123
+
124
+ module Facter::Util::CFPropertyList
125
+ # Create CFType hierarchy by guessing the correct CFType, e.g.
126
+ #
127
+ # x = {
128
+ # 'a' => ['b','c','d']
129
+ # }
130
+ # cftypes = Facter::Util::CFPropertyList.guess(x)
131
+ #
132
+ # pass optional options hash. Only possible value actually:
133
+ # +convert_unknown_to_string+:: Convert unknown objects to string calling to_str()
134
+ # +converter_method+:: Convert unknown objects to known objects calling +method_name+
135
+ #
136
+ # cftypes = Facter::Util::CFPropertyList.guess(x,:convert_unknown_to_string => true,:converter_method => :to_hash, :converter_with_opts => true)
137
+ def guess(object, options = {})
138
+ case object
139
+ when Fixnum, Integer then CFInteger.new(object)
140
+ when Float then CFReal.new(object)
141
+ when TrueClass, FalseClass then CFBoolean.new(object)
142
+
143
+ when String
144
+ object.blob? ? CFData.new(object, CFData::DATA_RAW) : CFString.new(object)
145
+
146
+ when Time, DateTime, Date then CFDate.new(object)
147
+
148
+ when Array, Enumerator, Enumerable::Enumerator
149
+ ary = Array.new
150
+ object.each do |o|
151
+ ary.push Facter::Util::CFPropertyList.guess(o, options)
152
+ end
153
+ CFArray.new(ary)
154
+
155
+ when Hash
156
+ hsh = Hash.new
157
+ object.each_pair do |k,v|
158
+ k = k.to_s if k.is_a?(Symbol)
159
+ hsh[k] = Facter::Util::CFPropertyList.guess(v, options)
160
+ end
161
+ CFDictionary.new(hsh)
162
+ else
163
+ case
164
+ when Object.const_defined?('BigDecimal') && object.is_a?(BigDecimal)
165
+ CFReal.new(object)
166
+ when object.respond_to?(:read)
167
+ CFData.new(object.read(), CFData::DATA_RAW)
168
+ when options[:converter_method] && object.respond_to?(options[:converter_method])
169
+ if options[:converter_with_opts]
170
+ Facter::Util::CFPropertyList.guess(object.send(options[:converter_method],options),options)
171
+ else
172
+ Facter::Util::CFPropertyList.guess(object.send(options[:converter_method]),options)
173
+ end
174
+ when options[:convert_unknown_to_string]
175
+ CFString.new(object.to_s)
176
+ else
177
+ raise CFTypeError.new("Unknown class #{object.class.to_s}. Try using :convert_unknown_to_string if you want to use unknown object types!")
178
+ end
179
+ end
180
+ end
181
+
182
+ # Converts a CFType hiercharchy to native Ruby types
183
+ def native_types(object,keys_as_symbols=false)
184
+ return if object.nil?
185
+
186
+ if(object.is_a?(CFDate) || object.is_a?(CFString) || object.is_a?(CFInteger) || object.is_a?(CFReal) || object.is_a?(CFBoolean)) then
187
+ return object.value
188
+ elsif(object.is_a?(CFData)) then
189
+ return object.decoded_value
190
+ elsif(object.is_a?(CFArray)) then
191
+ ary = []
192
+ object.value.each do
193
+ |v|
194
+ ary.push Facter::Util::CFPropertyList.native_types(v)
195
+ end
196
+
197
+ return ary
198
+ elsif(object.is_a?(CFDictionary)) then
199
+ hsh = {}
200
+ object.value.each_pair do
201
+ |k,v|
202
+ k = k.to_sym if keys_as_symbols
203
+ hsh[k] = Facter::Util::CFPropertyList.native_types(v)
204
+ end
205
+
206
+ return hsh
207
+ end
208
+ end
209
+
210
+ module_function :guess, :native_types
211
+
212
+ # Class representing a Facter::Util::CFPropertyList. Instanciate with #new
213
+ class List
214
+ # Format constant for binary format
215
+ FORMAT_BINARY = 1
216
+
217
+ # Format constant for XML format
218
+ FORMAT_XML = 2
219
+
220
+ # Format constant for automatic format recognizing
221
+ FORMAT_AUTO = 0
222
+
223
+ @@parsers = [Binary,XML]
224
+
225
+ # Path of PropertyList
226
+ attr_accessor :filename
227
+ # Path of PropertyList
228
+ attr_accessor :format
229
+ # the root value in the plist file
230
+ attr_accessor :value
231
+
232
+ # initialize a new Facter::Util::CFPropertyList, arguments are:
233
+ #
234
+ # :file:: Parse a file
235
+ # :format:: Format is one of FORMAT_BINARY or FORMAT_XML. Defaults to FORMAT_AUTO
236
+ # :data:: Parse a string
237
+ #
238
+ # All arguments are optional
239
+ def initialize(opts={})
240
+ @filename = opts[:file]
241
+ @format = opts[:format] || FORMAT_AUTO
242
+ @data = opts[:data]
243
+
244
+ load(@filename) unless @filename.nil?
245
+ load_str(@data) unless @data.nil?
246
+ end
247
+
248
+ # Load an XML PropertyList
249
+ # filename = nil:: The filename to read from; if nil, read from the file defined by instance variable +filename+
250
+ def load_xml(filename=nil)
251
+ load(filename,List::FORMAT_XML)
252
+ end
253
+
254
+ # read a binary plist file
255
+ # filename = nil:: The filename to read from; if nil, read from the file defined by instance variable +filename+
256
+ def load_binary(filename=nil)
257
+ load(filename,List::FORMAT_BINARY)
258
+ end
259
+
260
+ # load a plist from a XML string
261
+ # str:: The string containing the plist
262
+ def load_xml_str(str=nil)
263
+ load_str(str,List::FORMAT_XML)
264
+ end
265
+
266
+ # load a plist from a binary string
267
+ # str:: The string containing the plist
268
+ def load_binary_str(str=nil)
269
+ load_str(str,List::FORMAT_BINARY)
270
+ end
271
+
272
+ # load a plist from a string
273
+ # str = nil:: The string containing the plist
274
+ # format = nil:: The format of the plist
275
+ def load_str(str=nil,format=nil)
276
+ str = @data if str.nil?
277
+ format = @format if format.nil?
278
+
279
+ @value = {}
280
+ case format
281
+ when List::FORMAT_BINARY, List::FORMAT_XML then
282
+ prsr = @@parsers[format-1].new
283
+ @value = prsr.load({:data => str})
284
+
285
+ when List::FORMAT_AUTO then # what we now do is ugly, but neccessary to recognize the file format
286
+ filetype = str[0..5]
287
+ version = str[6..7]
288
+
289
+ prsr = nil
290
+ if filetype == "bplist" then
291
+ raise CFFormatError.new("Wong file version #{version}") unless version == "00"
292
+ prsr = Binary.new
293
+ else
294
+ prsr = XML.new
295
+ end
296
+
297
+ @value = prsr.load({:data => str})
298
+ end
299
+ end
300
+
301
+ # Read a plist file
302
+ # file = nil:: The filename of the file to read. If nil, use +filename+ instance variable
303
+ # format = nil:: The format of the plist file. Auto-detect if nil
304
+ def load(file=nil,format=nil)
305
+ file = @filename if file.nil?
306
+ format = @format if format.nil?
307
+ @value = {}
308
+
309
+ raise IOError.new("File #{file} not readable!") unless File.readable? file
310
+
311
+ case format
312
+ when List::FORMAT_BINARY, List::FORMAT_XML then
313
+ prsr = @@parsers[format-1].new
314
+ @value = prsr.load({:file => file})
315
+
316
+ when List::FORMAT_AUTO then # what we now do is ugly, but neccessary to recognize the file format
317
+ magic_number = IO.read(file,8)
318
+ filetype = magic_number[0..5]
319
+ version = magic_number[6..7]
320
+
321
+ prsr = nil
322
+ if filetype == "bplist" then
323
+ raise CFFormatError.new("Wong file version #{version}") unless version == "00"
324
+ prsr = Binary.new
325
+ else
326
+ prsr = XML.new
327
+ end
328
+
329
+ @value = prsr.load({:file => file})
330
+ end
331
+ end
332
+
333
+ # Serialize Facter::Util::CFPropertyList object to specified format and write it to file
334
+ # file = nil:: The filename of the file to write to. Uses +filename+ instance variable if nil
335
+ # format = nil:: The format to save in. Uses +format+ instance variable if nil
336
+ def save(file=nil,format=nil,opts={})
337
+ format = @format if format.nil?
338
+ file = @filename if file.nil?
339
+
340
+ raise CFFormatError.new("Format #{format} not supported, use List::FORMAT_BINARY or List::FORMAT_XML") if format != FORMAT_BINARY && format != FORMAT_XML
341
+
342
+ if(!File.exists?(file)) then
343
+ raise IOError.new("File #{file} not writable!") unless File.writable?(File.dirname(file))
344
+ elsif(!File.writable?(file)) then
345
+ raise IOError.new("File #{file} not writable!")
346
+ end
347
+
348
+ opts[:root] = @value
349
+ prsr = @@parsers[format-1].new
350
+ content = prsr.to_str(opts)
351
+
352
+ File.open(file, 'wb') {
353
+ |fd|
354
+ fd.write content
355
+ }
356
+ end
357
+
358
+ # convert plist to string
359
+ # format = List::FORMAT_BINARY:: The format to save the plist
360
+ # opts={}:: Pass parser options
361
+ def to_str(format=List::FORMAT_BINARY,opts={})
362
+ prsr = @@parsers[format-1].new
363
+ opts[:root] = @value
364
+ return prsr.to_str(opts)
365
+ end
366
+ end
367
+ end
368
+
369
+ class Array
370
+ # convert an array to plist format
371
+ def to_plist(options={})
372
+ options[:plist_format] ||= Facter::Util::CFPropertyList::List::FORMAT_BINARY
373
+
374
+ plist = Facter::Util::CFPropertyList::List.new
375
+ plist.value = Facter::Util::CFPropertyList.guess(self, options)
376
+ plist.to_str(options[:plist_format])
377
+ end
378
+ end
379
+
380
+ class Enumerator
381
+ # convert an array to plist format
382
+ def to_plist(options={})
383
+ options[:plist_format] ||= Facter::Util::CFPropertyList::List::FORMAT_BINARY
384
+
385
+ plist = Facter::Util::CFPropertyList::List.new
386
+ plist.value = Facter::Util::CFPropertyList.guess(self, options)
387
+ plist.to_str(options[:plist_format])
388
+ end
389
+ end
390
+
391
+ class Hash
392
+ # convert a hash to plist format
393
+ def to_plist(options={})
394
+ options[:plist_format] ||= Facter::Util::CFPropertyList::List::FORMAT_BINARY
395
+
396
+ plist = Facter::Util::CFPropertyList::List.new
397
+ plist.value = Facter::Util::CFPropertyList.guess(self, options)
398
+ plist.to_str(options[:plist_format])
399
+ end
400
+ end
401
+
402
+ # eof
@@ -0,0 +1,244 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # CFTypes, e.g. CFString, CFInteger
4
+ # needed to create unambiguous plists
5
+ #
6
+ # Author:: Christian Kruse (mailto:cjk@wwwtech.de)
7
+ # Copyright:: Copyright (c) 2009
8
+ # License:: MIT License
9
+
10
+ require 'base64'
11
+
12
+ module Facter::Util::CFPropertyList
13
+ # This class defines the base class for all CFType classes
14
+ #
15
+ class CFType
16
+ # value of the type
17
+ attr_accessor :value
18
+
19
+ def initialize(value=nil)
20
+ @value = value
21
+ end
22
+
23
+ def to_xml(parser)
24
+ end
25
+
26
+ def to_binary(bplist) end
27
+ end
28
+
29
+ # This class holds string values, both, UTF-8 and UTF-16BE
30
+ # It will convert the value to UTF-16BE if necessary (i.e. if non-ascii char contained)
31
+ class CFString < CFType
32
+ # convert to XML
33
+ def to_xml(parser)
34
+ n = parser.new_node('string')
35
+ n = parser.append_node(n, parser.new_text(@value)) unless @value.nil?
36
+ n
37
+ end
38
+
39
+ # convert to binary
40
+ def to_binary(bplist)
41
+ bplist.string_to_binary(@value);
42
+ end
43
+ end
44
+
45
+ # This class holds integer/fixnum values
46
+ class CFInteger < CFType
47
+ # convert to XML
48
+ def to_xml(parser)
49
+ n = parser.new_node('integer')
50
+ n = parser.append_node(n, parser.new_text(@value.to_s))
51
+ n
52
+ end
53
+
54
+ # convert to binary
55
+ def to_binary(bplist)
56
+ bplist.num_to_binary(self)
57
+ end
58
+ end
59
+
60
+ # This class holds float values
61
+ class CFReal < CFType
62
+ # convert to XML
63
+ def to_xml(parser)
64
+ n = parser.new_node('real')
65
+ n = parser.append_node(n, parser.new_text(@value.to_s))
66
+ n
67
+ end
68
+
69
+ # convert to binary
70
+ def to_binary(bplist)
71
+ bplist.num_to_binary(self)
72
+ end
73
+ end
74
+
75
+ # This class holds Time values. While Apple uses seconds since 2001,
76
+ # the rest of the world uses seconds since 1970. So if you access value
77
+ # directly, you get the Time class. If you access via get_value you either
78
+ # geht the timestamp or the Apple timestamp
79
+ class CFDate < CFType
80
+ TIMESTAMP_APPLE = 0
81
+ TIMESTAMP_UNIX = 1;
82
+ DATE_DIFF_APPLE_UNIX = 978307200
83
+
84
+ # create a XML date strimg from a time object
85
+ def CFDate.date_string(val)
86
+ # 2009-05-13T20:23:43Z
87
+ val.getutc.strftime("%Y-%m-%dT%H:%M:%SZ")
88
+ end
89
+
90
+ # parse a XML date string
91
+ def CFDate.parse_date(val)
92
+ # 2009-05-13T20:23:43Z
93
+ val =~ %r{^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$}
94
+ year,month,day,hour,min,sec = $1, $2, $3, $4, $5, $6
95
+ return Time.utc(year,month,day,hour,min,sec).getlocal
96
+ end
97
+
98
+ # set value to defined state
99
+ def initialize(value = nil,format=CFDate::TIMESTAMP_UNIX)
100
+ if(value.is_a?(Time) || value.nil?) then
101
+ @value = value.nil? ? Time.now : value
102
+ elsif value.instance_of? Date
103
+ @value = Time.utc(value.year, value.month, value.day, 0, 0, 0)
104
+ elsif value.instance_of? DateTime
105
+ @value = value.to_time.utc
106
+ else
107
+ set_value(value,format)
108
+ end
109
+ end
110
+
111
+ # set value with timestamp, either Apple or UNIX
112
+ def set_value(value,format=CFDate::TIMESTAMP_UNIX)
113
+ if(format == CFDate::TIMESTAMP_UNIX) then
114
+ @value = Time.at(value)
115
+ else
116
+ @value = Time.at(value + CFDate::DATE_DIFF_APPLE_UNIX)
117
+ end
118
+ end
119
+
120
+ # get timestamp, either UNIX or Apple timestamp
121
+ def get_value(format=CFDate::TIMESTAMP_UNIX)
122
+ if(format == CFDate::TIMESTAMP_UNIX) then
123
+ @value.to_i
124
+ else
125
+ @value.to_f - CFDate::DATE_DIFF_APPLE_UNIX
126
+ end
127
+ end
128
+
129
+ # convert to XML
130
+ def to_xml(parser)
131
+ n = parser.new_node('date')
132
+ n = parser.append_node(n, parser.new_text(CFDate::date_string(@value)))
133
+ n
134
+ end
135
+
136
+ # convert to binary
137
+ def to_binary(bplist)
138
+ bplist.date_to_binary(@value)
139
+ end
140
+ end
141
+
142
+ # This class contains a boolean value
143
+ class CFBoolean < CFType
144
+ # convert to XML
145
+ def to_xml(parser)
146
+ parser.new_node(@value ? 'true' : 'false')
147
+ end
148
+
149
+ # convert to binary
150
+ def to_binary(bplist)
151
+ bplist.bool_to_binary(@value);
152
+ end
153
+ end
154
+
155
+ # This class contains binary data values
156
+ class CFData < CFType
157
+ # Base64 encoded data
158
+ DATA_BASE64 = 0
159
+ # Raw data
160
+ DATA_RAW = 1
161
+
162
+ # set value to defined state, either base64 encoded or raw
163
+ def initialize(value=nil,format=DATA_BASE64)
164
+ if(format == DATA_RAW)
165
+ @raw_value = value
166
+ @raw_value.blob = true
167
+ else
168
+ @value = value
169
+ end
170
+ end
171
+
172
+ # get base64 encoded value
173
+ def encoded_value
174
+ @value ||= "\n#{Base64.encode64(@raw_value).gsub("\n", '').scan(/.{1,76}/).join("\n")}\n"
175
+ end
176
+
177
+ # get base64 decoded value
178
+ def decoded_value
179
+ @raw_value ||= String.new(Base64.decode64(@value))
180
+ @raw_value.blob = true
181
+ @raw_value
182
+ end
183
+
184
+ # convert to XML
185
+ def to_xml(parser)
186
+ n = parser.new_node('data')
187
+ n = parser.append_node(n, parser.new_text(encoded_value()))
188
+ n
189
+ end
190
+
191
+ # convert to binary
192
+ def to_binary(bplist)
193
+ bplist.data_to_binary(decoded_value())
194
+ end
195
+ end
196
+
197
+ # This class contains an array of values
198
+ class CFArray < CFType
199
+ # create a new array CFType
200
+ def initialize(val=[])
201
+ @value = val
202
+ end
203
+
204
+ # convert to XML
205
+ def to_xml(parser)
206
+ n = parser.new_node('array')
207
+ @value.each do |v|
208
+ n = parser.append_node(n, v.to_xml(parser))
209
+ end
210
+ n
211
+ end
212
+
213
+ # convert to binary
214
+ def to_binary(bplist)
215
+ bplist.array_to_binary(self)
216
+ end
217
+ end
218
+
219
+ # this class contains a hash of values
220
+ class CFDictionary < CFType
221
+ # Create new CFDictonary type.
222
+ def initialize(value={})
223
+ @value = value
224
+ end
225
+
226
+ # convert to XML
227
+ def to_xml(parser)
228
+ n = parser.new_node('dict')
229
+ @value.each_pair do |key, value|
230
+ k = parser.append_node(parser.new_node('key'), parser.new_text(key.to_s))
231
+ n = parser.append_node(n, k)
232
+ n = parser.append_node(n, value.to_xml(parser))
233
+ end
234
+ n
235
+ end
236
+
237
+ # convert to binary
238
+ def to_binary(bplist)
239
+ bplist.dict_to_binary(self)
240
+ end
241
+ end
242
+ end
243
+
244
+ # eof