easy_upnp 0.3.2 → 0.4.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7e627952f646058b6e52e0e07dd1d41e3537239d
4
- data.tar.gz: ff1632d0686e54b5af395bdee11d355d0af23020
3
+ metadata.gz: 14a33377666a3b363416fdc8080e4bf411f2574d
4
+ data.tar.gz: b6c87a73312c8c4002b9d4d1206518f2f43c199a
5
5
  SHA512:
6
- metadata.gz: 7b3b414baf2608cbb3b1a86fae78b1cf4081c8610ad65c1ec7dbcc7cc29d0746cbd87e96c1c3dc2051dfa69d5569913dc2dadf0c7a29da0423edcbb8885ad8a9
7
- data.tar.gz: 3a494127415a59897a9573d6c0af584980c88dce64c971f6a16b05ac43d0264ed7279d6ef0fe01a8f44279a073e53f47a7c422bcf7c569acb0fa41d2c270db9c
6
+ metadata.gz: dcd63c1ca7bd1060112f5da3e12b8b05f8b8ab34053e3f57e93eb4c67e0015ce1d33d54505d7374c19c0e7c2d893cd95e129f8f5bce9fbaabe29de0659777d2d
7
+ data.tar.gz: ef39cf1f54bbb336e53df619f62f9a181f7f5050baec03e83e7495cddf809052d45af2caf1fb958493c5fbc87b792f9bad1fa8b9b28c0d503002a3e17887fadd
@@ -0,0 +1,125 @@
1
+ module EasyUpnp
2
+ class ArgumentValidator
3
+ class Builder
4
+ def initialize(&block)
5
+ @validators = {}
6
+ block.call(self) if block
7
+ end
8
+
9
+ def in_range(min, max, step = 1)
10
+ add_validator(RangeValidator.new((min..max).step(step)))
11
+ end
12
+
13
+ def allowed_values(*values)
14
+ add_validator(AllowedValueValidator.new(*values))
15
+ end
16
+
17
+ def type(type)
18
+ add_validator(TypeValidator.new(type))
19
+ end
20
+
21
+ def add_validator(validator)
22
+ @validators[validator.class] = validator
23
+ end
24
+
25
+ def build
26
+ ArgumentValidator.new(@validators)
27
+ end
28
+ end
29
+
30
+ class RangeValidator
31
+ attr_reader :range
32
+
33
+ def initialize(range)
34
+ @range = range
35
+ end
36
+
37
+ def validate(value)
38
+ if !@range.include?(value)
39
+ raise ArgumentError, "#{value} is not in allowed range of values: #{@range.inspect}"
40
+ end
41
+ end
42
+ end
43
+
44
+ class AllowedValueValidator
45
+ attr_reader :allowed_values
46
+
47
+ def initialize(*allowed_values)
48
+ @allowed_values = allowed_values
49
+ end
50
+
51
+ def validate(value)
52
+ if !@allowed_values.include?(value)
53
+ raise ArgumentError, "#{value} is not in list of allowed values: #{@allowed_values.inspect}"
54
+ end
55
+ end
56
+ end
57
+
58
+ class TypeValidator
59
+ # Valid UPnP types for each ruby class
60
+ RUBY_TYPE_TO_UPNP_TYPE = {
61
+ Float: %w{r4 r8 number fixed.14.4 float},
62
+ Integer: %w{ui1 ui2 ui4 i1 i2 i4 int},
63
+ String: %w{char string bin.base64 bin.hex uri uuid},
64
+ TrueClass: %w{bool boolean},
65
+ FalseClass: %w{bool boolean},
66
+ DateTime: %w{date dateTime dateTime.tz time time.tz},
67
+ Time: %w{date dateTime dateTime.tz time time.tz},
68
+ Date: %w{date dateTime time}
69
+ }
70
+
71
+ # Inversion of RUBY_TYPE_TO_UPNP_TYPE.
72
+ UPNP_TYPE_VALID_CLASSES = Hash[
73
+ RUBY_TYPE_TO_UPNP_TYPE.map { |k,v|
74
+ k = Kernel.const_get(k)
75
+ v.map { |x| [x, k] }
76
+ }.reduce({}) { |a,i|
77
+ Hash[i].each { |x,y| a[x] ||= []; a[x] << y }
78
+ a
79
+ }
80
+ ]
81
+
82
+ attr_reader :valid_classes
83
+
84
+ def initialize(type)
85
+ @valid_classes = UPNP_TYPE_VALID_CLASSES[type]
86
+ raise ArgumentError, "Unrecognized UPnP type: #{type}" if @valid_classes.nil?
87
+ end
88
+
89
+ def validate(value)
90
+ if !@valid_classes.any? { |x| value.is_a?(x) }
91
+ raise ArgumentError, "#{value} is the wrong type. Should be one of: #{@valid_classes.inspect}"
92
+ end
93
+ end
94
+ end
95
+
96
+ def initialize(validators)
97
+ @validators = validators
98
+ end
99
+
100
+ def validate(value)
101
+ @validators.each { |_, v| v.validate(value) }
102
+ true
103
+ end
104
+
105
+ def required_class
106
+ return nil unless @validators[TypeValidator]
107
+ c = @validators[TypeValidator].valid_classes
108
+ c.size == 1 ? c.first : c
109
+ end
110
+
111
+ def allowed_values
112
+ return nil unless @validators[AllowedValueValidator]
113
+ @validators[AllowedValueValidator].allowed_values
114
+ end
115
+
116
+ def valid_range
117
+ return nil unless @validators[RangeValidator]
118
+ @validators[RangeValidator].range
119
+ end
120
+
121
+ def self.build(&block)
122
+ Builder.new(&block).build
123
+ end
124
+ end
125
+ end
@@ -3,6 +3,7 @@ require 'open-uri'
3
3
  require 'nori'
4
4
 
5
5
  require_relative 'logger'
6
+ require_relative 'argument_validator'
6
7
 
7
8
  module EasyUpnp
8
9
  class DeviceControlPoint
@@ -10,7 +11,8 @@ module EasyUpnp
10
11
 
11
12
  class Options
12
13
  DEFAULTS = {
13
- advanced_typecasting: true
14
+ advanced_typecasting: true,
15
+ validate_arguments: false
14
16
  }
15
17
 
16
18
  attr_reader :options
@@ -57,11 +59,29 @@ module EasyUpnp
57
59
  definition_xml.remove_namespaces!
58
60
 
59
61
  service_methods = []
62
+ service_methods_args = {}
60
63
  definition_xml.xpath('//actionList/action').map do |action|
61
- service_methods.push define_action(action)
64
+ service_methods.push(define_action(action))
65
+
66
+ name = action.xpath('name').text
67
+ args = {}
68
+ action.xpath('argumentList/argument').map do |arg|
69
+ arg_name = arg.xpath('name').text
70
+ arg_ref = arg.xpath('relatedStateVariable').text
71
+ args[arg_name.to_sym] = arg_ref.to_sym
72
+ end
73
+ service_methods_args[name.to_sym] = args
74
+ end
75
+
76
+ arg_validators = {}
77
+ definition_xml.xpath('//serviceStateTable/stateVariable').map do |var|
78
+ name = var.xpath('name').text
79
+ arg_validators[name.to_sym] = extract_validators(var)
62
80
  end
63
81
 
64
82
  @service_methods = service_methods
83
+ @service_methods_args = service_methods_args
84
+ @arg_validators = arg_validators
65
85
  end
66
86
 
67
87
  def to_params
@@ -111,8 +131,38 @@ module EasyUpnp
111
131
  end
112
132
  end
113
133
 
134
+ def arg_validator(method, arg)
135
+ method_args = @service_methods_args[method.to_sym]
136
+ raise ArgumentError, "Unknown method: #{method}" if method_args.nil?
137
+
138
+ arg_ref = method_args[arg.to_sym]
139
+ raise ArgumentValidator, "Unknown argument: #{arg}" if arg_ref.nil?
140
+
141
+ @arg_validators[arg_ref]
142
+ end
143
+
114
144
  private
115
145
 
146
+ def extract_validators(var)
147
+ ArgumentValidator.build do |v|
148
+ v.type(var.xpath('dataType').text)
149
+
150
+ if (range = var.xpath('allowedValueRange')).any?
151
+ min = range.xpath('minimum').text
152
+ max = range.xpath('maximum').text
153
+ step = range.xpath('step')
154
+ step = step.any? ? step.text : 1
155
+
156
+ v.in_range(min.to_i, max.to_i, step.to_i)
157
+ end
158
+
159
+ if (list = var.xpath('allowedValueList')).any?
160
+ allowed_values = list.xpath('allowedValue').map { |x| x.text }
161
+ v.allowed_values(*allowed_values)
162
+ end
163
+ end
164
+ end
165
+
116
166
  def define_action(action)
117
167
  action = Nori.new.parse(action.to_xml)['action']
118
168
  action_name = action['name']
@@ -138,6 +188,16 @@ module EasyUpnp
138
188
  " Supported args: #{input_args}"
139
189
  end
140
190
 
191
+ if @options.validate_arguments
192
+ args_hash.each { |k,v|
193
+ begin
194
+ arg_validator(action['name'], k).validate(v)
195
+ rescue ArgumentError => e
196
+ raise ArgumentError, "Invalid value for argument #{k}: #{e}"
197
+ end
198
+ }
199
+ end
200
+
141
201
  attrs = {
142
202
  soap_action: "#{@urn}##{action_name}",
143
203
  attributes: {
@@ -1,3 +1,3 @@
1
1
  module EasyUpnp
2
- VERSION = '0.3.2'
2
+ VERSION = '0.4.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_upnp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Mullins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-01 00:00:00.000000000 Z
11
+ date: 2016-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -94,6 +94,7 @@ files:
94
94
  - Rakefile
95
95
  - bin/upnp-list
96
96
  - easy_upnp.gemspec
97
+ - lib/easy_upnp/argument_validator.rb
97
98
  - lib/easy_upnp/device_control_point.rb
98
99
  - lib/easy_upnp/logger.rb
99
100
  - lib/easy_upnp/ssdp_searcher.rb