radiusrb 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'ipaddr_extensions'
4
+
5
+ group :development do
6
+ gem "shoulda", ">= 0"
7
+ gem "bundler", "~> 1.0.0"
8
+ gem "jeweler", "~> 1.6.4"
9
+ gem "rcov", ">= 0"
10
+ gem "rdoc", ">= 2.4.2"
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,30 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ ipaddr_extensions (2012.1.13)
6
+ jeweler (1.6.4)
7
+ bundler (~> 1.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ json (1.6.5)
11
+ rake (0.9.2.2)
12
+ rcov (1.0.0)
13
+ rdoc (3.12)
14
+ json (~> 1.4)
15
+ shoulda (3.0.1)
16
+ shoulda-context (~> 1.0.0)
17
+ shoulda-matchers (~> 1.0.0)
18
+ shoulda-context (1.0.0)
19
+ shoulda-matchers (1.0.0)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ bundler (~> 1.0.0)
26
+ ipaddr_extensions
27
+ jeweler (~> 1.6.4)
28
+ rcov
29
+ rdoc (>= 2.4.2)
30
+ shoulda
data/LICENSE.txt ADDED
@@ -0,0 +1,15 @@
1
+ Copyright (c) 2011 Davide Guerri <davide.guerri@gmail.com>
2
+
3
+ This program is free software; you can redistribute it and/or
4
+ modify it under the terms of the GNU General Public License
5
+ as published by the Free Software Foundation; either version 3
6
+ of the License, or (at your option) any later version.
7
+
8
+ This program is distributed in the hope that it will be useful,
9
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ GNU General Public License for more details.
12
+
13
+ You should have received a copy of the GNU General Public License
14
+ along with this program; if not, write to the Free Software
15
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -0,0 +1,207 @@
1
+ #
2
+ # This file contains dictionary translations for parsing
3
+ # requests and generating responses. All transactions are
4
+ # composed of Attribute/Value Pairs. The value of each attribute
5
+ # is specified as one of 4 data types. Valid data types are:
6
+ #
7
+ # string - 0-253 octets
8
+ # ipaddr - 4 octets in network byte order
9
+ # integer - 32 bit value in big endian order (high byte first)
10
+ # date - 32 bit value in big endian order - seconds since
11
+ # 00:00:00 GMT, Jan. 1, 1970
12
+ #
13
+ # Enumerated values are stored in the user file with dictionary
14
+ # VALUE translations for easy administration.
15
+ #
16
+ # Example:
17
+ #
18
+ # ATTRIBUTE VALUE
19
+ # --------------- -----
20
+ # Framed-Protocol = PPP
21
+ # 7 = 1 (integer encoding)
22
+ #
23
+
24
+
25
+
26
+ #
27
+ # Proper names for everything - use this instead of the above
28
+ #
29
+ ATTRIBUTE User-Name 1 string
30
+ ATTRIBUTE User-Password 2 string
31
+ ATTRIBUTE CHAP-Password 3 string
32
+ ATTRIBUTE NAS-IP-Address 4 ipaddr
33
+ ATTRIBUTE NAS-Port 5 integer
34
+ ATTRIBUTE Service-Type 6 integer
35
+ ATTRIBUTE Framed-Protocol 7 integer
36
+ ATTRIBUTE Framed-IP-Address 8 ipaddr
37
+ ATTRIBUTE Framed-IP-Netmask 9 ipaddr
38
+ ATTRIBUTE Framed-Routing 10 integer
39
+ ATTRIBUTE Filter-Id 11 string
40
+ ATTRIBUTE Framed-MTU 12 integer
41
+ ATTRIBUTE Framed-Compression 13 integer
42
+ ATTRIBUTE Login-IP-Host 14 ipaddr
43
+ ATTRIBUTE Login-Service 15 integer
44
+ ATTRIBUTE Login-TCP-Port 16 integer
45
+ ATTRIBUTE Reply-Message 18 string
46
+ ATTRIBUTE Callback-Number 19 string
47
+ ATTRIBUTE Callback-Id 20 string
48
+ ATTRIBUTE Expiration 21 date
49
+ ATTRIBUTE Framed-Route 22 string
50
+ ATTRIBUTE Framed-IPX-Network 23 ipaddr
51
+ ATTRIBUTE State 24 string
52
+ ATTRIBUTE Session-Timeout 27 integer
53
+ ATTRIBUTE Idle-Timeout 28 integer
54
+ ATTRIBUTE Termination-Action 29 integer
55
+ ATTRIBUTE Called-Station-Id 30 string
56
+ ATTRIBUTE Calling-Station-Id 31 string
57
+ ATTRIBUTE Acct-Status-Type 40 integer
58
+ ATTRIBUTE Acct-Delay-Time 41 integer
59
+ ATTRIBUTE Acct-Input-Octets 42 integer
60
+ ATTRIBUTE Acct-Output-Octets 43 integer
61
+ ATTRIBUTE Acct-Session-Id 44 string
62
+ ATTRIBUTE Acct-Authentic 45 integer
63
+ ATTRIBUTE Acct-Session-Time 46 integer
64
+ ATTRIBUTE Acct-Terminate-Cause 49 integer
65
+ ATTRIBUTE NAS-Port-Type 61 integer
66
+ ATTRIBUTE Port-Limit 62 integer
67
+
68
+
69
+ #
70
+ # Integer Translations
71
+ #
72
+
73
+ # User Types
74
+
75
+ VALUE Service-Type Login-User 1
76
+ VALUE Service-Type Framed-User 2
77
+ VALUE Service-Type Callback-Login-User 3
78
+ VALUE Service-Type Callback-Framed-User 4
79
+ VALUE Service-Type Outbound-User 5
80
+ VALUE Service-Type Administrative-User 6
81
+ VALUE Service-Type NAS-Prompt-User 7
82
+
83
+ # Framed Protocols
84
+
85
+ VALUE Framed-Protocol PPP 1
86
+ VALUE Framed-Protocol SLIP 2
87
+
88
+ # Framed Routing Values
89
+
90
+ VALUE Framed-Routing None 0
91
+ VALUE Framed-Routing Broadcast 1
92
+ VALUE Framed-Routing Listen 2
93
+ VALUE Framed-Routing Broadcast-Listen 3
94
+
95
+ # Framed Compression Types
96
+
97
+ VALUE Framed-Compression None 0
98
+ VALUE Framed-Compression Van-Jacobson-TCP-IP 1
99
+
100
+ # Login Services
101
+
102
+ VALUE Login-Service Telnet 0
103
+ VALUE Login-Service Rlogin 1
104
+ VALUE Login-Service TCP-Clear 2
105
+ VALUE Login-Service PortMaster 3
106
+
107
+ # Status Types
108
+
109
+ VALUE Acct-Status-Type Start 1
110
+ VALUE Acct-Status-Type Stop 2
111
+
112
+ # Authentication Types
113
+
114
+ VALUE Acct-Authentic RADIUS 1
115
+ VALUE Acct-Authentic Local 2
116
+ VALUE Acct-Authentic PowerLink128 100
117
+
118
+ # Termination Options
119
+
120
+ VALUE Termination-Action Default 0
121
+ VALUE Termination-Action RADIUS-Request 1
122
+
123
+ # NAS Port Types, available in ComOS 3.3.1 and later
124
+
125
+ VALUE NAS-Port-Type Async 0
126
+ VALUE NAS-Port-Type Sync 1
127
+ VALUE NAS-Port-Type ISDN 2
128
+ VALUE NAS-Port-Type ISDN-V120 3
129
+ VALUE NAS-Port-Type ISDN-V110 4
130
+
131
+ # Acct Terminate Causes, available in ComOS 3.3.2 and later
132
+
133
+ VALUE Acct-Terminate-Cause User-Request 1
134
+ VALUE Acct-Terminate-Cause Lost-Carrier 2
135
+ VALUE Acct-Terminate-Cause Lost-Service 3
136
+ VALUE Acct-Terminate-Cause Idle-Timeout 4
137
+ VALUE Acct-Terminate-Cause Session-Timeout 5
138
+ VALUE Acct-Terminate-Cause Admin-Reset 6
139
+ VALUE Acct-Terminate-Cause Admin-Reboot 7
140
+ VALUE Acct-Terminate-Cause Port-Error 8
141
+ VALUE Acct-Terminate-Cause NAS-Error 9
142
+ VALUE Acct-Terminate-Cause NAS-Request 10
143
+ VALUE Acct-Terminate-Cause NAS-Reboot 11
144
+ VALUE Acct-Terminate-Cause Port-Unneeded 12
145
+ VALUE Acct-Terminate-Cause Port-Preempted 13
146
+ VALUE Acct-Terminate-Cause Port-Suspended 14
147
+ VALUE Acct-Terminate-Cause Service-Unavailable 15
148
+ VALUE Acct-Terminate-Cause Callback 16
149
+ VALUE Acct-Terminate-Cause User-Error 17
150
+ VALUE Acct-Terminate-Cause Host-Request 18
151
+
152
+
153
+ #
154
+ # Obsolete names for backwards compatibility with older users files
155
+ # If you want RADIUS accounting logs to use the new names instead of
156
+ # these, move this section to the beginning of the dictionary file
157
+ # and kill and restart radiusd
158
+ # If you don't have a RADIUS 1.16 users file that you're still using,
159
+ # you can delete or ignore this section.
160
+ #
161
+ ATTRIBUTE Client-Id 4 ipaddr
162
+ ATTRIBUTE Client-Port-Id 5 integer
163
+ ATTRIBUTE User-Service-Type 6 integer
164
+ ATTRIBUTE Framed-Address 8 ipaddr
165
+ ATTRIBUTE Framed-Netmask 9 ipaddr
166
+ ATTRIBUTE Framed-Filter-Id 11 string
167
+ ATTRIBUTE Login-Host 14 ipaddr
168
+ ATTRIBUTE Login-Port 16 integer
169
+ ATTRIBUTE Old-Password 17 string
170
+ ATTRIBUTE Port-Message 18 string
171
+ ATTRIBUTE Dialback-No 19 string
172
+ ATTRIBUTE Dialback-Name 20 string
173
+ ATTRIBUTE Challenge-State 24 string
174
+ VALUE Service-Type Dialback-Login-User 3
175
+ VALUE Service-Type Dialback-Framed-User 4
176
+ VALUE Service-Type Shell-User 6
177
+ VALUE Framed-Compression Van-Jacobsen-TCP-IP 1
178
+ #VALUE Auth-Type Unix 1
179
+ #
180
+ # END of obsolete names for backwards compatibility
181
+ #
182
+
183
+ #
184
+ # Configuration Values
185
+ # uncomment out these two lines to turn account expiration on
186
+ #
187
+
188
+ #VALUE Server-Config Password-Expiration 30
189
+ #VALUE Server-Config Password-Warning 5
190
+
191
+ ##
192
+ ## VENDOR SPECIFIC ATTRIBUTES
193
+ ##
194
+ ## The following entries demonstrate the use of VSAs
195
+ ##
196
+
197
+ # cisco-avpair is used for various functions by cisco IOS. Most
198
+ # notably, it's used to create VPDN tunnels.
199
+ #
200
+ VENDORATTR 9 cisco-avpair 1 string
201
+
202
+ # This is a fake attribute to demonstrate how to write named-value
203
+ # attributes.
204
+ VENDORATTR 1 ibm-enum 254 integer
205
+ VENDORVALUE 1 ibm-enum value-1 1
206
+ VENDORVALUE 1 ibm-enum value-2 2
207
+ VENDORVALUE 1 ibm-enum value-3 3
data/README.rdoc ADDED
@@ -0,0 +1,74 @@
1
+ = RadiusRB
2
+
3
+ A ruby RADIUS client library that supports:
4
+
5
+ * Authentication
6
+ * Accounting
7
+ * Custom dictionaries
8
+ * Vendor Specific Attributes (Thanks to James Harton aka jamesotron)
9
+
10
+ RadiusRB is derived from from PJ Davis's Radiustar library (https://github.com/pjdavis/radiustar).
11
+
12
+ = Installation
13
+
14
+ # git clone git://github.com/dguerri/radiusrb.git
15
+ # cd radiusrb
16
+ # bundle install
17
+ # rake install
18
+
19
+ = Usage
20
+
21
+ require 'rubygems'
22
+ require 'radiusrb'
23
+
24
+ # Load dictionaries from freeradius directory
25
+ dict = RadiusRB::Dictionary.new('/usr/share/freeradius/')
26
+
27
+ # Lets get authenticated
28
+ auth_custom_attr = {
29
+ 'Framed-Address' => '127.0.0.1',
30
+ 'NAS-Port' => 0,
31
+ 'NAS-Port-Type' => 'Ethernet'
32
+ }
33
+
34
+ req = RadiusRB::Request.new('127.0.0.1', { :dict => dict })
35
+ reply = req.authenticate('John Doe', 'hello', 'testing123', auth_custom_attr)
36
+
37
+ if reply[:code] == 'Access-Accept'
38
+ req = RadiusRB::Request.new('127.0.0.1:1813', { :dict => dict })
39
+
40
+ acct_custom_attr = {
41
+ 'Framed-Address' => '127.0.0.1',
42
+ 'NAS-Port' => 0,
43
+ 'NAS-Port-Type' => 'Ethernet',
44
+ 'Acct-Session-Time' => 0
45
+ }
46
+
47
+ timings = Time.now
48
+ reply = req.accounting_start('John Doe', 'testing123', '123456', acct_custom_attr)
49
+
50
+ sleep(rand 5)
51
+ acct_custom_attr['Acct-Session-Time'] = Time.now - timings
52
+ reply = req.accounting_update('John Doe', 'testing123', '123456', acct_custom_attr)
53
+
54
+ sleep(rand 5)
55
+ acct_custom_attr['Acct-Session-Time'] = Time.now - timings
56
+ reply = req.accounting_stop('John Doe', 'testing123', '123456', acct_custom_attr)
57
+
58
+ end
59
+
60
+ == Contributing to RadiusRB
61
+
62
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
63
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
64
+ * Fork the project
65
+ * Start a feature/bugfix branch
66
+ * Commit and push until you are happy with your contribution
67
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
68
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
69
+
70
+ == Copyright
71
+
72
+ Copyright (c) 2011 Davide Guerri <davide.guerri@gmail.com>.
73
+ See LICENSE.txt for further details.
74
+
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ require './lib/radiusrb/version.rb'
16
+ Jeweler::Tasks.new do |gem|
17
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
18
+ gem.name = "radiusrb"
19
+ gem.homepage = "http://github.com/dguerri/radiusrb"
20
+ gem.license = "GPLv3"
21
+ gem.summary = %Q{RadiusRB, a ruby RADIUS client library}
22
+ gem.description = %Q{RadiusRB, a ruby RADIUS client library that supports: Authentication, Accounting, Custom dictionaries and Vendor Specific Attributes.}
23
+ gem.email = "davide.guerri@gmail.com"
24
+ gem.authors = ["Davide Guerri"]
25
+ gem.version = RadiusRB::Version::STRING
26
+ # dependencies defined in Gemfile
27
+ end
28
+ Jeweler::RubygemsDotOrgTasks.new
29
+
30
+ require 'rake/testtask'
31
+ Rake::TestTask.new(:test) do |test|
32
+ test.libs << 'lib' << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+
37
+ require 'rcov/rcovtask'
38
+ Rcov::RcovTask.new do |test|
39
+ test.libs << 'test'
40
+ test.pattern = 'test/**/test_*.rb'
41
+ test.verbose = true
42
+ test.rcov_opts << '--exclude "gems/*"'
43
+ end
44
+
45
+ task :default => :test
46
+
47
+ require 'rdoc/task'
48
+ RDoc::Task.new do |rdoc|
49
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "netflowfu #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
@@ -0,0 +1,77 @@
1
+ module RadiusRB
2
+
3
+ class AttributesCollection < Array
4
+
5
+ attr_accessor :vendor
6
+
7
+ def initialize vendor=nil
8
+ @collection = {}
9
+ @revcollection = {}
10
+ @vendor = vendor if vendor
11
+ end
12
+
13
+ def add(name, id, type)
14
+ if vendor?
15
+ @collection[name] ||= Attribute.new(name, id.to_i, type, @vendor)
16
+ else
17
+ @collection[name] ||= Attribute.new(name, id.to_i, type)
18
+ end
19
+ @revcollection[id.to_i] ||= @collection[name]
20
+ self << @collection[name]
21
+ end
22
+
23
+ def find_by_name(name)
24
+ @collection[name]
25
+ end
26
+
27
+ def find_by_id(id)
28
+ @revcollection[id]
29
+ end
30
+
31
+ def vendor?
32
+ !!@vendor
33
+ end
34
+
35
+ end
36
+
37
+ class Attribute
38
+
39
+ include RadiusRB
40
+
41
+ attr_reader :name, :id, :type, :vendor
42
+
43
+ def initialize(name, id, type, vendor=nil)
44
+ @values = ValuesCollection.new
45
+ @name = name
46
+ @id = id.to_i
47
+ @type = type
48
+ @vendor = vendor if vendor
49
+ end
50
+
51
+ def add_value(name, id)
52
+ @values.add(name, id.to_i)
53
+ end
54
+
55
+ def find_values_by_name(name)
56
+ @values.find_by_name(name)
57
+ end
58
+
59
+ def find_values_by_id(id)
60
+ @values.find_by_id(id.to_i)
61
+ end
62
+
63
+ def has_values?
64
+ !@values.empty?
65
+ end
66
+
67
+ def values
68
+ @values
69
+ end
70
+
71
+ def vendor?
72
+ !!@vendor
73
+ end
74
+
75
+ end
76
+
77
+ end
@@ -0,0 +1,43 @@
1
+ module RadiusRB
2
+
3
+ class ValuesCollection < Array
4
+
5
+ def initialize
6
+ @collection = {}
7
+ @revcollection = {}
8
+ end
9
+
10
+ def add(name, id)
11
+ @collection[name] ||= Value.new(name, id)
12
+ @revcollection[id.to_i] ||= @collection[name]
13
+ self << @collection[name]
14
+ end
15
+
16
+ def find_by_name(name)
17
+ @collection[name]
18
+ end
19
+
20
+ def find_by_id(id)
21
+ @revcollection[id]
22
+ end
23
+
24
+ def empty?
25
+ @collection.empty?
26
+ end
27
+
28
+ end
29
+
30
+ class Value
31
+
32
+ include RadiusRB
33
+
34
+ attr_accessor :name, :id
35
+
36
+ def initialize(name, id)
37
+ @name = name
38
+ @id = id.to_i
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,157 @@
1
+ # This file is part of the RadiusRB library for Ruby.
2
+ # Copyright (C) 2011 Davide Guerri <davide.guerri@gmail.com>
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 3
7
+ # of the License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ module RadiusRB
19
+
20
+ class Dictionary
21
+
22
+ include RadiusRB
23
+
24
+ DEFAULT_DICTIONARIES_PATH = ::File.join(::File.dirname(__FILE__), '..', '..', 'templates')
25
+
26
+ def initialize(initial_path = nil)
27
+ @attributes = AttributesCollection.new
28
+ @vendors = VendorCollection.new
29
+
30
+ read_files initial_path if initial_path
31
+ end
32
+
33
+ def read_files(path)
34
+ dict_files = File.join(path, "*")
35
+ Dir.glob(dict_files) { |file|
36
+ read_attributes(file)
37
+ }
38
+ Dir.glob(dict_files) { |file|
39
+ read_values(file)
40
+ }
41
+ end
42
+
43
+ def find_attribute_by_name(name)
44
+ @attributes.find_by_name(name)
45
+ end
46
+
47
+ def find_attribute_by_id(id)
48
+ @attributes.find_by_id(id)
49
+ end
50
+
51
+ def attribute_name_defined?(name)
52
+ !@attributes.find_by_name(name).nil?
53
+ end
54
+
55
+ def attribute_id_defined?(id)
56
+ !@attributes.find_by_id(id).nil?
57
+ end
58
+
59
+ def vendors
60
+ @vendors
61
+ end
62
+
63
+ def attributes
64
+ @attributes
65
+ end
66
+
67
+ def name
68
+ "Dictionary"
69
+ end
70
+
71
+ class << self
72
+
73
+ def default
74
+ new DEFAULT_DICTIONARIES_PATH
75
+ end
76
+
77
+ end
78
+
79
+ protected
80
+
81
+ def read_attributes(path)
82
+ file = File.open(path) do |f|
83
+ current_vendor = nil
84
+ f.each_line do |line|
85
+ next if line =~ /^\#/ # discard comments
86
+ split_line = line.split(/\s+/)
87
+ next if split_line == []
88
+ case split_line.first.upcase
89
+ when "ATTRIBUTE"
90
+ current_vendor.nil? ? set_attr(split_line) : set_vendor_attr(current_vendor, split_line)
91
+ when "VENDOR"
92
+ add_vendor(split_line)
93
+ when "BEGIN-VENDOR"
94
+ current_vendor = set_vendor(split_line)
95
+ when "END-VENDOR"
96
+ current_vendor = nil
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ def read_values(path)
103
+ file = File.open(path) do |f|
104
+ current_vendor = nil
105
+ f.each_line do |line|
106
+ next if line =~ /^\#/ # discard comments
107
+ split_line = line.split(/\s+/)
108
+ next if split_line == []
109
+ case split_line.first.upcase
110
+ when "VALUE"
111
+ if current_vendor.nil?
112
+ set_value(split_line)
113
+ else
114
+ begin
115
+ set_vendor_value(current_vendor, split_line)
116
+ rescue
117
+ set_value(split_line)
118
+ end
119
+ end
120
+ when "BEGIN-VENDOR"
121
+ current_vendor = set_vendor(split_line)
122
+ when "END-VENDOR"
123
+ current_vendor = nil
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ private
130
+
131
+ def set_attr(line)
132
+ @attributes.add(line[1], line[2], line[3])
133
+ end
134
+
135
+ def set_value(line)
136
+ @attributes.find_by_name(line[1]).add_value(line[2], line[3])
137
+ end
138
+
139
+ def add_vendor(line)
140
+ @vendors.add(line[2], line[1])
141
+ end
142
+
143
+ def set_vendor(line)
144
+ @vendors.find_by_name(line[1])
145
+ end
146
+
147
+ def set_vendor_attr(vendor, line)
148
+ vendor.add_attribute(line[1], line[2], line[3])
149
+ end
150
+
151
+ def set_vendor_value(vendor, line)
152
+ vendor.find_attribute_by_name(line[1]).add_value(line[2], line[3])
153
+ end
154
+
155
+ end
156
+
157
+ end