ruby-amt 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/AUTHORS +1 -0
  2. data/COPYING +15 -0
  3. data/ChangeLog +392 -0
  4. data/GPL +674 -0
  5. data/Rakefile +292 -0
  6. data/VERSION +1 -0
  7. data/doc/default.css +211 -0
  8. data/doc/default.template +78 -0
  9. data/doc/documentation.page +40 -0
  10. data/doc/img/bg.jpg +0 -0
  11. data/doc/img/image.jpg +0 -0
  12. data/doc/img/line.jpg +0 -0
  13. data/doc/img/shadow.jpg +0 -0
  14. data/doc/index.page +61 -0
  15. data/doc/installation.page +115 -0
  16. data/doc/news.page +25 -0
  17. data/doc/news/release_0_1_0.page +16 -0
  18. data/doc/virtual +2 -0
  19. data/lib/amt/pt_status.rb +59 -0
  20. data/lib/amt/service.rb +16 -0
  21. data/lib/amt/service/basic.rb +159 -0
  22. data/lib/amt/service/hardware_asset.rb +83 -0
  23. data/lib/amt/service/hardware_asset/amt_information_table.rb +49 -0
  24. data/lib/amt/service/hardware_asset/asset.rb +118 -0
  25. data/lib/amt/service/hardware_asset/baseboard.rb +31 -0
  26. data/lib/amt/service/hardware_asset/bios.rb +65 -0
  27. data/lib/amt/service/hardware_asset/computer_system.rb +30 -0
  28. data/lib/amt/service/hardware_asset/fru.rb +37 -0
  29. data/lib/amt/service/hardware_asset/media_device.rb +63 -0
  30. data/lib/amt/service/hardware_asset/memory_module.rb +91 -0
  31. data/lib/amt/service/hardware_asset/portable_battery.rb +80 -0
  32. data/lib/amt/service/hardware_asset/processor.rb +123 -0
  33. data/lib/amt/service/hardware_asset/vpro_verification_table.rb +120 -0
  34. data/lib/amt/service/network_administration.rb +181 -0
  35. data/lib/amt/service/network_administration/structures.rb +29 -0
  36. data/lib/amt/service/remote_control.rb +73 -0
  37. data/lib/amt/service/remote_control/structures.rb +120 -0
  38. data/lib/amt/service/security_administration.rb +430 -0
  39. data/lib/amt/service/security_administration/structures.rb +117 -0
  40. data/lib/amt/system.rb +134 -0
  41. data/lib/amt/utility.rb +33 -0
  42. data/lib/amt/utility/bit_struct.rb +164 -0
  43. data/lib/amt/utility/enum.rb +119 -0
  44. data/lib/amt/version.rb +8 -0
  45. data/setup.rb +1585 -0
  46. metadata +125 -0
@@ -0,0 +1,83 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'amt/service/basic'
4
+ require 'amt/utility'
5
+
6
+ module AMT
7
+
8
+ module Service
9
+
10
+ # AMT Service for retrieving information about the hardware assets of the AMT device.
11
+ class HardwareAsset < Basic
12
+
13
+ autoload :Asset, 'amt/service/hardware_asset/asset'
14
+ autoload :Bios, 'amt/service/hardware_asset/bios'
15
+ autoload :ComputerSystem, 'amt/service/hardware_asset/computer_system'
16
+ autoload :Baseboard, 'amt/service/hardware_asset/baseboard'
17
+ autoload :Processor, 'amt/service/hardware_asset/processor'
18
+ autoload :MemoryModule, 'amt/service/hardware_asset/memory_module'
19
+ autoload :MediaDevice, 'amt/service/hardware_asset/media_device'
20
+ autoload :PortableBattery, 'amt/service/hardware_asset/portable_battery'
21
+ autoload :VproVerificationTable, 'amt/service/hardware_asset/vpro_verification_table'
22
+ autoload :AmtInformationTable, 'amt/service/hardware_asset/amt_information_table'
23
+
24
+
25
+ # Available asset types.
26
+ class AssetType < AMT::Utility::Enum
27
+ multi_add(2 => :bios, 3 => :computer_system, 4 => :baseboard, 5 => :processor,
28
+ 6 => :memory_module, 7 => :fru, 8 => :media_device, 9 => :portable_battery,
29
+ 10 => :vpro_verification_table, 11 => :amt_information_table)
30
+ end
31
+
32
+
33
+ # Return an array of supported hardware asset type names.
34
+ #
35
+ # All API supported asset type names are available as values in the ASSET_TYPES hash.
36
+ #
37
+ # Supported by AMT 1.0 and later.
38
+ def enumerate_asset_types
39
+ soap_call("EnumerateAssetTypes", 'Status').process do |node|
40
+ node.xpath('./ns:AssetTypes/ns:AssetType/text()').collect {|at| AssetType.for(at.to_i)}
41
+ end
42
+ end
43
+
44
+
45
+ ASSET_TYPE_CLASS = {
46
+ 2 => :Bios,
47
+ 3 => :ComputerSystem,
48
+ 4 => :Baseboard,
49
+ 5 => :Processor,
50
+ 6 => :MemoryModule,
51
+ 7 => :FRU,
52
+ 8 => :MediaDevice,
53
+ 9 => :PortableBattery,
54
+ 10 => :VproVerificationTable,
55
+ 11 => :AmtInformationTable
56
+ } #:nodoc:
57
+
58
+ # Return an array of all hardware asset data identified by the asset type +asset_type+.
59
+ #
60
+ # [+asset_type+] Can either be the numerical asset type, an asset type name or an instance of
61
+ # AssetType.
62
+ #
63
+ # The class of the returned values is different for every +asset_type+. See Bios,
64
+ # ComputerSystem, Baseboard, Processor, MemoryModule, FRU, MediaDevice, PortableBattery,
65
+ # VproVerificationTable and AmtInformationTable.
66
+ #
67
+ # Supported by AMT 1.0 and later.
68
+ def get_asset_data(asset_type)
69
+ soap_call("GetAssetData", 'Status') do |msg|
70
+ msg.add('ns:AssetType', AssetType.for(asset_type).value)
71
+ end.process do |node|
72
+ node.xpath('./ns:AssetData/ns:AssetData').collect do |anode|
73
+ data = anode.xpath('./ns:AssetData/text()').to_s.unpack('m*').first
74
+ self.class.const_get(ASSET_TYPE_CLASS[anode.xpath('./ns:AssetType/text()').to_i]).new(data)
75
+ end
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+
83
+ end
@@ -0,0 +1,49 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'amt/utility'
4
+ require 'amt/service/hardware_asset'
5
+
6
+ module AMT
7
+ module Service
8
+ class HardwareAsset
9
+
10
+
11
+ # Represents a structure with information about AMT capabilities.
12
+ #
13
+ # Available fields:
14
+ #
15
+ # [+amt_supported?+] +true+ if Intel AMT is supported.
16
+ # [+amt_enabled?+] +true+ if Intel AMT is enabled.
17
+ # [+ider_enabled?+] +true+ if IDE redirection is enabled.
18
+ # [+sol_enabled?+] +true+ if Serial Over Lan capability is enabled.
19
+ # [+network_enabled?+] +true+ if the network interface of the AMT device is enabled.
20
+ # [+extended_data+] OEM specific data.
21
+ # [+oem_capabilities+] OEM specific AMT capabilities (an instance of OemCapabilities).
22
+ class AmtInformationTable < Asset
23
+
24
+ # Defines a set of bit flags that indicate the features the AMT additional supports.
25
+ class OemCapabilities < AMT::Utility::BitStruct
26
+ boolean 24, :ider_supported, 'IDE Redirection Supported'
27
+ boolean 25, :sol_supported, 'Serial over LAN Supported'
28
+ boolean 26, :bios_reflash_supported, 'BIOS reflash supported'
29
+ boolean 27, :bios_setup_supported, 'BIOS boot into setup screen supported'
30
+ boolean 28, :bios_pause_supported, 'BIOS pause before booting operating system supported'
31
+ boolean 29, :no_floppy_boot, 'BIOS does not support boot from Floppy'
32
+ boolean 30, :no_cd_boot, 'BIOS does not support boot from CD device'
33
+ end
34
+
35
+ set_unpack_data "IC6Ix2", 16, [[:amt_supported, :boolean], [:amt_enabled, :boolean], [:ider_enabled, :boolean],
36
+ [:sol_enabled, :boolean], [:network_enabled, :boolean], :extended_data,
37
+ :oem_capabilities]
38
+
39
+ def init_data(data) #:nodoc:
40
+ super
41
+ @oem_capabilities = OemCapabilities.new(@oem_capabilities)
42
+ end
43
+ private :init_data
44
+
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,118 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module AMT
4
+ module Service
5
+ class HardwareAsset
6
+
7
+ # Utility base class which provides methods for easily unpacking the byte stream returned by
8
+ # AMT::Service::HardwareAsset#get_asset_data.
9
+ #
10
+ # Each asset class is derived from this class.
11
+ class Asset
12
+
13
+ # Set the +code+ that is used to unpack the byte stream data. +size+ is the expected (and
14
+ # fixed) size of the byte stream. +repr+ is an array of fields (or arrays when you also want
15
+ # to specify the field type and optionally field data) and should be matched to the order of
16
+ # the unpacked data.
17
+ #
18
+ # If +repr+ is specified, an accessor method for each field is created.
19
+ def self.set_unpack_data(code, size, repr = nil)
20
+ @code = code
21
+ @size = size
22
+ @repr = repr
23
+ if !repr.nil?
24
+ repr.each do |field, repr, repr_data|
25
+ define_method(repr == :boolean ? field.to_s + "?" : field) { instance_variable_get("@#{field}".intern) }
26
+ end
27
+ end
28
+ end
29
+
30
+ # Return the byte stream unpack code for the specific asset class.
31
+ def self.unpack_code
32
+ @code
33
+ end
34
+
35
+ # Return the predetermined size of the byte stream for the specific asset class.
36
+ def self.unpack_size
37
+ @size
38
+ end
39
+
40
+ # Return the byte stream representation data if set.
41
+ def self.unpack_repr
42
+ @repr
43
+ end
44
+
45
+ # The version of the asset structure.
46
+ attr_reader :structure_version
47
+
48
+
49
+ # Use the data from the byte stream +stream+ to set all needed values.
50
+ def initialize(stream)
51
+ if stream.size != self.class.unpack_size
52
+ raise ArgumentError, "The given byte stream has invalid length (#{stream.size} != #{self.class.unpack_size})"
53
+ end
54
+ sv, *rest = *stream.unpack(self.class.unpack_code)
55
+ @structure_version = as_structure_version(sv)
56
+ if @structure_version != '1.0'
57
+ raise ArgumentError, "Only Asset structures with version 1.0 are supported (got #{@structure_version})"
58
+ end
59
+ init_data(rest)
60
+ end
61
+
62
+ private
63
+
64
+ # Initialize all fields specified in <tt>Asset.unpack_repr</tt> with the data from the
65
+ # stream.
66
+ def init_data(data)
67
+ self.class.unpack_repr.each_with_index do |(field, repr, repr_data), index|
68
+ value = if repr.nil? then (data[index].kind_of?(String) ? data[index].strip : data[index])
69
+ elsif repr == :raw then data[index]
70
+ elsif repr == :date then as_date(data[index])
71
+ elsif repr == :uuid then as_uuid(data[index])
72
+ elsif repr == :boolean then as_boolean(data[index])
73
+ elsif repr == :enum then as_enum(data[index], repr_data)
74
+ elsif repr == :struct then as_bit_struct(data[index], repr_data)
75
+ elsif repr.kind_of?(Proc) then repr.call(data[index])
76
+ else raise ArgumentError, "Unsupported asset field representation: #{repr}"
77
+ end
78
+ instance_variable_set("@#{field}".intern, value)
79
+ end
80
+ end
81
+
82
+ # Treat +data+ as if it were a structure version field and extract the structure version.
83
+ def as_structure_version(data)
84
+ [data].pack('I').unpack("ss").join('.')
85
+ end
86
+
87
+ # Treat +data+ as if it were a string containing a date in the form mm/dd/yyyy and extract
88
+ # the date.
89
+ def as_date(data)
90
+ month, day, year = data.scan(/(\d\d)\/(\d\d)\/(\d\d\d\d)/).first
91
+ Date.new(year.to_i, month.to_i, day.to_i)
92
+ end
93
+
94
+ # Treat +data+ as boolean, ie. as value +true+ if it is +1+ and +false+ otherwise.
95
+ def as_boolean(data)
96
+ data.to_i == 1
97
+ end
98
+
99
+ # Treat +data+ as enumeration of type +enum_type+.
100
+ def as_enum(data, enum_type)
101
+ enum_type.for(data)
102
+ end
103
+
104
+ # Treat +data+ as BitStruct of type +bit_struct_type+.
105
+ def as_bit_struct(data, bit_struct_type)
106
+ bit_struct_type.new(data)
107
+ end
108
+
109
+ # Treat +data+ as an UUID.
110
+ def as_uuid(data)
111
+ AMT::Utility.binary_to_uuid(data)
112
+ end
113
+
114
+ end
115
+
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'amt/service/hardware_asset'
4
+
5
+ module AMT
6
+ module Service
7
+ class HardwareAsset
8
+
9
+ # Represents the baseboard of the computer system managed by the AMT device.
10
+ #
11
+ # There is at most one instance of this class in the hardware asset inventory of each AMT
12
+ # device.
13
+ #
14
+ # Available fields:
15
+ #
16
+ # [+manufacturer+] The name of the manufacturer of the baseboard.
17
+ # [+product+] The name of the baseboard.
18
+ # [+version+] The version of the baseboard.
19
+ # [+serial_number+] The serial number of the baseboard.
20
+ # [+asset_tag+] The asset tag string of the baseboard.
21
+ # [+replaceable?+] If the baseboard is replaceable, then +true+, else +false+.
22
+ class Baseboard < Asset
23
+
24
+ set_unpack_data "IZ65Z65Z65Z65Z65Cx2", 332, [:manufacturer, :product, :version, :serial_number,
25
+ :asset_tag, [:replaceable, :boolean]]
26
+
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,65 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'amt/utility'
4
+ require 'amt/service/hardware_asset'
5
+
6
+ module AMT
7
+ module Service
8
+ class HardwareAsset
9
+
10
+ # Represents the BIOS of the AMT device.
11
+ #
12
+ # There is at most one instance of this class in the hardware asset inventory of each AMT
13
+ # device.
14
+ #
15
+ # Available fields:
16
+ #
17
+ # [+vendor+] The name of the BIOS vendor.
18
+ # [+version+] The version of the system BIOS image.
19
+ # [+release_date+] The release date of the system BIOS image.
20
+ # [+characteristics+] Defines which functions the BIOS supports (an instance of
21
+ # Characteristics).
22
+ class Bios < Asset
23
+
24
+ # Defines a set of bit flags that indicate the features the BIOS supports.
25
+ class Characteristics < AMT::Utility::BitStruct
26
+ boolean 2, :unknown, 'Unknown'
27
+ boolean 3, :bios_characteristics_not_supported, 'BIOS Characteristics Not Supported'
28
+ boolean 4, :isa_supported, 'ISA is supported'
29
+ boolean 5, :mca_supported, 'MCA is supported'
30
+ boolean 6, :eisa_supported, 'EISA is supported'
31
+ boolean 7, :pci_supported, 'PCI is supported'
32
+ boolean 8, :pc_card_supported, 'PC Card (PCMCIA) is supported'
33
+ boolean 9, :pnp_supported, 'Plug and Play is supported'
34
+ boolean 10, :apm_supported, 'APM is supported'
35
+ boolean 11, :bios_upgradeable, 'BIOS is Upgradeable (Flash)'
36
+ boolean 12, :bios_shadowing_allowed, 'BIOS shadowing is allowed'
37
+ boolean 13, :vl_vesa_supported, 'VL-VESA is supported'
38
+ boolean 14, :escd_supported, 'ESCD support is available'
39
+ boolean 15, :boot_from_CD_supported, 'Boot from CD is supported'
40
+ boolean 16, :selectable_boot_supported, 'Selectable Boot is supported'
41
+ boolean 17, :bios_rom_socketed, 'BIOS ROM is socketed '
42
+ boolean 18, :boot_from_PC_card_supported, 'Boot From PC Card (PCMCIA) is supported'
43
+ boolean 19, :edd_spec_supported, 'EDD (Enhanced Disk Drive) Specification is supported'
44
+ boolean 20, :int13h_floppy_for_NEC_9800_supported, 'Int 13h - Japanese Floppy for NEC 9800 1.2mb (3.5", 1k Bytes/Sector, 360 RPM) is supported'
45
+ boolean 21, :int13h_floppy_for_Toshiba_supported, 'Int 13h - Japanese Floppy for Toshiba 1.2mb (3.5", 360 RPM) is supported'
46
+ boolean 22, :int13h_5_25_in_360_kb_floppy_supported, 'Int 13h - 5.25" / 360 KB Floppy Services are supported'
47
+ boolean 23, :int13h_5_25_in_1_2_mb_floppy_supported, 'Int 13h - 5.25" /1.2MB Floppy Services are supported'
48
+ boolean 24, :int13h_3_5_in_720_kb_floppy_supported, 'Int 13h - 3.5" / 720 KB Floppy Services are supported'
49
+ boolean 25, :int13h_3_5_in_2_88_mb_floppy_supported, 'Int 13h - 3.5" / 2.88 MB Floppy Services are supported'
50
+ boolean 26, :int5h_print_screen_services_supported, 'Int 5h, Print Screen Service is supported'
51
+ boolean 27, :int9h_8042_keyboard_services_supported, 'Int 9h, 8042 Keyboard services are supported'
52
+ boolean 28, :int14h_serial_services_supported, 'Int 14h, Serial Services are supported'
53
+ boolean 29, :int17h_printer_services_supported, 'Int 17h, Printer Services are supported'
54
+ boolean 30, :int10h_CGA_and_mono_video_supported, 'Int 10h, CGA/Mono Video Services are supported'
55
+ boolean 31, :nec_pc_98, 'NEC PC-98'
56
+ end
57
+
58
+ set_unpack_data "IZ65Z65Z65xI", 204, [:vendor, :version, [:release_date, :date],
59
+ [:characteristics, :struct, Characteristics]]
60
+
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'amt/service/hardware_asset'
4
+
5
+ module AMT
6
+ module Service
7
+ class HardwareAsset
8
+
9
+ # Represents the computer system that is managed by AMT device.
10
+ #
11
+ # There is at most one instance of this class in the hardware asset inventory of each AMT
12
+ # device.
13
+ #
14
+ # Available fields:
15
+ #
16
+ # [+manufacturer+] The name of the system manufacturer.
17
+ # [+product+] The name of the system product.
18
+ # [+version+] The version of the system product.
19
+ # [+serial_number+] The serial number of the system.
20
+ # [+uuid+] The UUID (Universal Unique ID) of the system. If it contains only +ff+, then the
21
+ # UUID is not present but setable. If it contains only +00+, then it is not present.
22
+ class ComputerSystem < Asset
23
+
24
+ set_unpack_data "IZ65Z65Z65Z65H32", 280, [:manufacturer, :product, :version, :serial_number, [:uuid, :uuid]]
25
+
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'amt/service/hardware_asset'
4
+
5
+ module AMT
6
+ module Service
7
+ class HardwareAsset
8
+
9
+ # Represents a PCI/AGP add-in device of the system managed by the AMT device.
10
+ #
11
+ # There is at most one instance of this class for every PCI or AGP FRU in the hardware asset
12
+ # inventory of each AMT device.
13
+ #
14
+ # Available fields:
15
+ #
16
+ # [+vendor_id+] The value in the Vendor ID configuration space register.
17
+ # [+device_id+] The value in the Device ID configuration space register.
18
+ # [+revision_id+] The value in the Revision ID configuration space register.
19
+ # [+prog_if+] The value in the Programming Interface byte in the Class Code configuration
20
+ # space register
21
+ # [+subclass+] The value in the Subclass byte in the Class Code configuration space register.
22
+ # [+base_class+] The value in the Base Class byte in the Class Code configuration space
23
+ # register.
24
+ # [+subvendor_id+] The value in the Subvendor ID configuration space register.
25
+ # [+subsystem_id+] The value in the Subsystem ID configuration space register.
26
+ # [+device_location+] The bus and slot number where the device is installed.
27
+ class FRU < Asset
28
+
29
+ set_unpack_data "ISSCCCCSSSx2", 20, [:vendor_id, :device_id, :revision_id, :prog_if, :subclass, :base_class,
30
+ :subvendor_id, :subsystem_id, :device_location]
31
+
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,63 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'amt/utility'
4
+ require 'amt/service/hardware_asset'
5
+
6
+ module AMT
7
+ module Service
8
+ class HardwareAsset
9
+
10
+ # Represents an IDE/SATA device of the system managed by the AMT device.
11
+ #
12
+ # There is at most one instance of this class for every physical media device in the hardware
13
+ # asset inventory of each AMT device.
14
+ #
15
+ # Available fields:
16
+ #
17
+ # [+model_number+] The model number of the media device.
18
+ # [+serial_number+] The serial number of the media device.
19
+ # [+capabilities+] The capabilities of the media device (an instance of Capabilities).
20
+ # [+max_media_size+] The maximum size in bytes of supported media.
21
+ class MediaDevice < Asset
22
+
23
+ # The capabilities of a media device.
24
+ class Capabilities < AMT::Utility::BitStruct
25
+ boolean 0, :smart_fs_supported, 'SMART feature set supported'
26
+ boolean 1, :security_mode_fs_supporte, 'Security Mode feature set supported'
27
+ boolean 2, :removable_media_fs_supported, 'Removable Media feature set supported'
28
+ boolean 3, :power_management_fs_supported, 'Power Management feature set supported'
29
+ boolean 4, :packet_command_fs_supported, 'PACKET Command feature set supported'
30
+ boolean 5, :write_cache_supported, 'write cache supported'
31
+ boolean 6, :look_ahead_supported, 'look-ahead supported'
32
+ boolean 7, :release_interrupt_supported, 'release interrupt supported'
33
+ boolean 8, :service_interrupt_supported, 'SERVICE interrupt supported'
34
+ boolean 9, :device_reset_command_supported, 'DEVICE RESET command supported'
35
+ boolean 10, :host_protected_area_fs_supported, 'Host Protected Area feature set supported'
36
+ boolean 12, :write_buffer_command_supported, 'WRITE BUFFER command supported'
37
+ boolean 13, :read_buffer_command_supported, 'READ BUFFER command supported'
38
+ boolean 15, :nop_command_supported, 'NOP command supported'
39
+ boolean 16, :download_microcode_command_supported, 'DOWNLOAD MICROCODE command supported'
40
+ boolean 17, :read_write_dma_queued_supported, 'READ/WRITE DMA QUEUED supported'
41
+ boolean 18, :cfa_fs_supported, 'CFA feature set supported'
42
+ boolean 19, :advanced_power_management_fs_supported, 'Advanced Power Management feature set supported'
43
+ boolean 20, :remove_media_status_notification_fs_supported, 'Removable Media Status Notification feature set supported'
44
+ end
45
+
46
+ set_unpack_data "IA40A20a6a8x2", 80, [:model_number, :serial_number, [:capabilities, :raw],
47
+ [:max_media_size, lambda {|d|
48
+ low, high = d.unpack("II")
49
+ (high << 32) + low
50
+ }]]
51
+
52
+ def init_data(data) # :nodoc:
53
+ super
54
+ first, second, last = *@capabilities.unpack("SSS")
55
+ @capabilities = Capabilities.new((first << 32) + (second << 16) + last)
56
+ end
57
+ private :init_data
58
+
59
+ end
60
+
61
+ end
62
+ end
63
+ end