openvas-cli 0.1.1 → 0.2.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 (42) hide show
  1. data/Gemfile +2 -0
  2. data/Gemfile.lock +50 -0
  3. data/VERSION +1 -1
  4. data/lib/openvas-cli/configuration.rb +25 -0
  5. data/lib/openvas-cli/conn_addin.rb +27 -0
  6. data/lib/openvas-cli/immutable_children_validator.rb +15 -0
  7. data/lib/openvas-cli/vas_administrator.rb +7 -0
  8. data/lib/openvas-cli/vas_base.rb +20 -30
  9. data/lib/openvas-cli/vas_config.rb +127 -0
  10. data/lib/openvas-cli/vas_connection.rb +140 -0
  11. data/lib/openvas-cli/vas_exceptions.rb +9 -7
  12. data/lib/openvas-cli/vas_lsc_credential.rb +110 -0
  13. data/lib/openvas-cli/vas_nvt.rb +64 -64
  14. data/lib/openvas-cli/vas_nvt_family.rb +39 -30
  15. data/lib/openvas-cli/vas_override.rb +6 -4
  16. data/lib/openvas-cli/vas_period.rb +89 -0
  17. data/lib/openvas-cli/vas_preference.rb +139 -49
  18. data/lib/openvas-cli/vas_report.rb +110 -103
  19. data/lib/openvas-cli/vas_result.rb +90 -89
  20. data/lib/openvas-cli/vas_schedule.rb +163 -55
  21. data/lib/openvas-cli/vas_target.rb +200 -23
  22. data/lib/openvas-cli/vas_task.rb +229 -30
  23. data/lib/openvas-cli/vas_task_progress.rb +29 -0
  24. data/lib/openvas-cli/xml_addin.rb +34 -0
  25. data/lib/openvas_cli.rb +19 -0
  26. data/openvas-cli.gemspec +28 -6
  27. data/spec/openvas-cli/vas_administrator_spec.rb +6 -0
  28. data/spec/openvas-cli/vas_config_spec.rb +81 -0
  29. data/spec/openvas-cli/vas_lsc_credential_spec.rb +72 -0
  30. data/spec/openvas-cli/vas_nvt_family_spec.rb +7 -5
  31. data/spec/openvas-cli/vas_nvt_spec.rb +30 -26
  32. data/spec/openvas-cli/vas_period_spec.rb +7 -0
  33. data/spec/openvas-cli/vas_preference_spec.rb +23 -21
  34. data/spec/openvas-cli/vas_report_spec.rb +65 -63
  35. data/spec/openvas-cli/vas_result_spec.rb +94 -93
  36. data/spec/openvas-cli/vas_schedule_spec.rb +154 -57
  37. data/spec/openvas-cli/vas_target_spec.rb +140 -28
  38. data/spec/openvas-cli/vas_task_spec.rb +92 -11
  39. data/spec/spec_helper.rb +15 -5
  40. metadata +72 -24
  41. data/lib/openvas-cli/openvas-cli.rb +0 -273
  42. data/spec/openvas-cli/openvas-cli_spec.rb +0 -45
@@ -1,118 +1,125 @@
1
1
  require 'vas_base'
2
2
 
3
- # Contains the details of a single OpenVAS report.
4
- class VasReport < VasBase
5
- attr_accessor :report_id
6
- attr_accessor :task_id
7
- attr_accessor :task_name
8
- attr_accessor :started_at
9
- # Overall Status Only
10
- attr_accessor :status
11
-
12
- validates :report_id, :presence => true, :UUID => true
13
- validates :task_id, :presence => true, :UUID => true
14
-
15
- # Pulls report details based off of the options passed. By default, pulls all
16
- # reports.
17
- # === Options:
18
- # [:report_id => [report_id]] Pulls a specific +report_id+. If the id provided is bogus, an empty set is returned.
19
- # [:filter => [array_of_filter_symbols]] Filters the report results by severity. Valid symbols are: [:high, :medium, :low, :log, :deubg].
20
- def self.get_all(options={})
21
- params = {}
22
- params[:report_id] = options[:report_id] if options[:report_id]
23
- if options[:filter]
24
- params[:levels] = ""
25
- options[:filter].each { |f|
26
- case f
27
- when :high
28
- params[:levels] += 'h'
29
- when :medium
30
- params[:levels] += 'm'
31
- when :low
32
- params[:levels] += 'l'
33
- when :log
34
- params[:levels] += 'g'
35
- when :debug
36
- params[:levels] += 'd'
3
+ module OpenvasCli
4
+ # Contains the details of a single OpenVAS report.
5
+ class VasReport < VasBase
6
+ attr_accessor :report_id
7
+ attr_accessor :task_id
8
+ attr_accessor :task_name
9
+ attr_accessor :started_at
10
+ # Overall Status Only
11
+ attr_accessor :status
12
+
13
+ validates :report_id, :presence => true, :UUID => true
14
+ validates :task_id, :presence => true, :UUID => true,
15
+ :unless => Proc.new { |report| report.empty? }
16
+
17
+ # Pulls report details based off of the options passed. By default, pulls all
18
+ # reports.
19
+ # === Options:
20
+ # [:report_id => [report_id]] Pulls a specific +report_id+. If the id provided is bogus, an empty set is returned.
21
+ # [:filter => [array_of_filter_symbols]] Filters the report results by severity. Valid symbols are: [:high, :medium, :low, :log, :deubg].
22
+ def self.get_all(options={})
23
+ params = {}
24
+ params[:report_id] = options[:report_id] if options[:report_id]
25
+ if options[:filter]
26
+ params[:levels] = ""
27
+ options[:filter].each { |f|
28
+ case f
29
+ when :high
30
+ params[:levels] += 'h'
31
+ when :medium
32
+ params[:levels] += 'm'
33
+ when :low
34
+ params[:levels] += 'l'
35
+ when :log
36
+ params[:levels] += 'g'
37
+ when :debug
38
+ params[:levels] += 'd'
39
+ end
40
+ }
41
+ end
42
+
43
+ req = Nokogiri::XML::Builder.new { |xml|
44
+ if params.empty?
45
+ xml.get_reports
46
+ else
47
+ xml.get_reports(params)
37
48
  end
38
49
  }
39
- end
40
-
41
- req = Nokogiri::XML::Builder.new { |xml|
42
- if params.empty?
43
- xml.get_reports
44
- else
45
- xml.get_reports(params)
50
+
51
+ begin
52
+ repts = connection.send_receive(req.doc)
53
+ rescue VasExceptions::CommandException => e
54
+ raise e unless e.message =~ /Failed to find/i
55
+ return []
46
56
  end
47
- }
48
-
49
- begin
50
- repts = client.send_receive(req.doc)
51
- rescue VasExceptions::CommandException => e
52
- raise e unless e.message =~ /Failed to find/i
53
- return []
54
- end
55
-
56
- ret = []
57
- repts.xpath('//report').each { |r|
58
- r_id = VasReport.new
59
- r_id.report_id = extract_value_from("@id", r)
60
- r_id.task_id = extract_value_from("task/@id", r)
61
- r_id.task_name = extract_value_from("task/name", r)
62
- r_id.status = extract_value_from("scan_run_status", r)
63
- r_id.started_at = extract_value_from("scan_start", r)
64
57
 
65
- r_id.result_count[:total] = extract_value_from("result_count/full", r).to_i
66
- r_id.result_count[:filtered] = extract_value_from("result_count/filtered", r).to_i
67
- r_id.result_count[:debug][:total] = extract_value_from("result_count/debug/full", r).to_i
68
- r_id.result_count[:debug][:filtered] = extract_value_from("result_count/debug/filtered", r).to_i
69
- r_id.result_count[:high][:total] = extract_value_from("result_count/hole/full", r).to_i
70
- r_id.result_count[:high][:filtered] = extract_value_from("result_count/hold/filtered", r).to_i
71
- r_id.result_count[:low][:total] = extract_value_from("result_count/info/full", r).to_i
72
- r_id.result_count[:low][:filtered] = extract_value_from("result_count/info/filtered", r).to_i
73
- r_id.result_count[:log][:total] = extract_value_from("result_count/log/full", r).to_i
74
- r_id.result_count[:log][:filtered] = extract_value_from("result_count/log/filtered", r).to_i
75
- r_id.result_count[:medium][:total] = extract_value_from("result_count/warning/full", r).to_i
76
- r_id.result_count[:medium][:filtered] = extract_value_from("result_count/warning/filtered", r).to_i
58
+ ret = []
59
+ repts.xpath('//report').each { |r|
60
+ r_id = VasReport.new
61
+ r_id.report_id = extract_value_from("@id", r)
62
+ r_id.task_id = extract_value_from("task/@id", r)
63
+ r_id.task_name = extract_value_from("task/name", r)
64
+ r_id.status = extract_value_from("scan_run_status", r)
65
+ r_id.started_at = extract_value_from("scan_start", r)
66
+
67
+ r_id.result_count[:total] = extract_value_from("result_count/full", r).to_i
68
+ r_id.result_count[:filtered] = extract_value_from("result_count/filtered", r).to_i
69
+ r_id.result_count[:debug][:total] = extract_value_from("result_count/debug/full", r).to_i
70
+ r_id.result_count[:debug][:filtered] = extract_value_from("result_count/debug/filtered", r).to_i
71
+ r_id.result_count[:high][:total] = extract_value_from("result_count/hole/full", r).to_i
72
+ r_id.result_count[:high][:filtered] = extract_value_from("result_count/hold/filtered", r).to_i
73
+ r_id.result_count[:low][:total] = extract_value_from("result_count/info/full", r).to_i
74
+ r_id.result_count[:low][:filtered] = extract_value_from("result_count/info/filtered", r).to_i
75
+ r_id.result_count[:log][:total] = extract_value_from("result_count/log/full", r).to_i
76
+ r_id.result_count[:log][:filtered] = extract_value_from("result_count/log/filtered", r).to_i
77
+ r_id.result_count[:medium][:total] = extract_value_from("result_count/warning/full", r).to_i
78
+ r_id.result_count[:medium][:filtered] = extract_value_from("result_count/warning/filtered", r).to_i
79
+
80
+ r.xpath("results/result").each { |result|
81
+ r_id.results << VasResult.parse_result_node(result)
82
+ }
83
+
84
+ ret << r_id
85
+ }
77
86
 
78
- r.xpath("results/result").each { |result|
79
- r_id.results << VasResult.parse_result_node(result)
87
+ ret
88
+ end
89
+
90
+ def to_xml
91
+ req = Nokogiri::XML::Builder.new { |xml|
92
+ xml.get_reports(:report_id => @report_id)
80
93
  }
81
94
 
82
- ret << r_id
83
- }
95
+ report = VasReport.connection.send_receive(req.doc)
96
+
97
+ report.at_xpath('//report').to_xml
98
+ end
84
99
 
85
- ret
86
- end
87
-
88
- def to_xml
89
- req = Nokogiri::XML::Builder.new { |xml|
90
- xml.get_reports(:report_id => @report_id)
91
- }
100
+ def task
101
+ @task ||= VasTask.get_all(:task_id => @task_id)[0]
102
+ end
103
+
104
+ def results
105
+ @results ||= []
106
+ end
92
107
 
93
- report = VasBase.client.send_receive(req.doc)
108
+ def result_count
109
+ unless @result_count
110
+ @result_count = {:total => 0, :filtered => 0,
111
+ :debug => {:total => 0, :filtered => 0},
112
+ :log => {:total => 0, :filtered => 0},
113
+ :low => {:total => 0, :filtered => 0},
114
+ :medium => {:total => 0, :filtered => 0},
115
+ :high => {:total => 0, :filtered => 0}
116
+ }
117
+ end
118
+ @result_count
119
+ end
94
120
 
95
- report.at_xpath('//report').to_xml
96
- end
97
-
98
- def task
99
- @task ||= VasTask.get_all(:task_id => @task_id)[0]
100
- end
101
-
102
- def results
103
- @results ||= []
104
- end
105
-
106
- def result_count
107
- unless @result_count
108
- @result_count = {:total => 0, :filtered => 0,
109
- :debug => {:total => 0, :filtered => 0},
110
- :log => {:total => 0, :filtered => 0},
111
- :low => {:total => 0, :filtered => 0},
112
- :medium => {:total => 0, :filtered => 0},
113
- :high => {:total => 0, :filtered => 0}
114
- }
121
+ def empty?
122
+ !(@result_count && @result_count[:total] > 0)
115
123
  end
116
- @result_count
117
124
  end
118
125
  end
@@ -1,102 +1,103 @@
1
1
  require 'vas_base'
2
2
  require 'vas_override'
3
3
 
4
- class VasResult < VasBase
5
- attr_accessor :result_id, :subnet, :host, :port, :rule_id, :threat,
6
- :description, :notes, :overrides, :task_id
7
-
8
- validates :result_id, :presence=>true, :UUID=>true
9
-
10
- def self.get_all(options = {})
11
- options[:sort_by] ||= :threat
12
-
13
- params = {:overrides => 0, :notes => 0}
14
- if options[:task_id]
15
- params[:task_id] = options[:task_id]
16
- params[:apply_overrides] = 1 if options[:apply_overrides]
17
- end
4
+ module OpenvasCli
5
+ class VasResult < VasBase
6
+ attr_accessor :result_id, :subnet, :host, :port, :rule_id, :threat,
7
+ :description, :notes, :overrides, :task_id
8
+
9
+ validates :result_id, :presence=>true, :UUID=>true
10
+
11
+ def self.get_all(options = {})
12
+ options[:sort_by] ||= :threat
13
+
14
+ params = {:overrides => 0, :notes => 0}
15
+ if options[:id]
16
+ params[:task_id] = options[:id]
17
+ params[:apply_overrides] = 1 if options[:apply_overrides]
18
+ end
18
19
 
19
- levels = []
20
- if options[:filter]
21
- options[:filter].each { |ft|
22
- case ft
23
- when :high
24
- levels << "High"
25
- when :medium
26
- levels << "Medium"
27
- when :low
28
- levels << "Low"
29
- when :log
30
- levels << "Log"
31
- when :debug
32
- levels << "Debug"
33
- end
34
- }
35
- end
36
- req = Nokogiri::XML::Builder.new { |xml|
37
- xml.get_results(params)
38
- }
39
- xml = client.send_receive(req.doc)
40
-
41
- results = {}
42
- xml.xpath("//result").each { |xr|
43
- id = extract_value_from("@id", xr)
44
- threat = extract_value_from("threat", xr)
45
- if (levels.empty? || levels.include?(threat)) && results.has_key?(id) == false
46
- res = parse_result_node(xr, options[:task_id])
47
- results[res.result_id] = res
20
+ levels = []
21
+ if options[:filter]
22
+ options[:filter].each { |ft|
23
+ case ft
24
+ when :high
25
+ levels << "High"
26
+ when :medium
27
+ levels << "Medium"
28
+ when :low
29
+ levels << "Low"
30
+ when :log
31
+ levels << "Log"
32
+ when :debug
33
+ levels << "Debug"
34
+ end
35
+ }
48
36
  end
49
- }
50
-
51
- ret = results.values
37
+ req = Nokogiri::XML::Builder.new { |xml|
38
+ xml.get_results(params)
39
+ }
40
+ xml = connection.send_receive(req.doc)
41
+
42
+ results = {}
43
+ xml.xpath("//result").each { |xr|
44
+ id = extract_value_from("@id", xr)
45
+ threat = extract_value_from("threat", xr)
46
+ if (levels.empty? || levels.include?(threat)) && results.has_key?(id) == false
47
+ res = parse_result_node(xr, options[:task_id])
48
+ results[res.result_id] = res
49
+ end
50
+ }
51
+
52
+ ret = results.values
52
53
 
53
- #Sort Results
54
- ret.sort!{ |a,b| a.result_id <=> b.result_id } if options[:sort_by] == :result_id
55
- ret.sort!{ |a,b| a.host <=> b.host } if options[:sort_by] == :host
56
- ret.sort!{ |a,b| a.rule_id <=> b.rule_id } if options[:sort_by] == :rule_id
57
- ret.sort!{ |a,b| a.subnet <=> b.subnet } if options[:sort_by] == :subnet
58
- ret.sort!{ |a,b| b.threat_level <=> a.threat_level } if options[:sort_by] == :threat
59
-
60
- #Fake Pagination
61
- if options[:start]
62
- if options[:count]
63
- ret = ret[options[:start], options[:count]]
64
- else
65
- ret = ret[options[:start], ret.length - options[:start]]
54
+ #Sort Results
55
+ ret.sort!{ |a,b| a.result_id <=> b.result_id } if options[:sort_by] == :result_id
56
+ ret.sort!{ |a,b| a.host <=> b.host } if options[:sort_by] == :host
57
+ ret.sort!{ |a,b| a.rule_id <=> b.rule_id } if options[:sort_by] == :rule_id
58
+ ret.sort!{ |a,b| a.subnet <=> b.subnet } if options[:sort_by] == :subnet
59
+ ret.sort!{ |a,b| b.threat_level <=> a.threat_level } if options[:sort_by] == :threat
60
+
61
+ #Fake Pagination
62
+ if options[:start]
63
+ if options[:count]
64
+ ret = ret[options[:start], options[:count]]
65
+ else
66
+ ret = ret[options[:start], ret.length - options[:start]]
67
+ end
66
68
  end
69
+
70
+ ret
67
71
  end
68
72
 
69
- ret
70
- end
71
-
72
- def self.parse_result_node(node, task_id = nil)
73
- res = VasResult.new
74
- res.result_id = extract_value_from("@id", node)
75
- res.threat = extract_value_from("threat", node)
76
- res.subnet = extract_value_from("subnet", node)
77
- res.host = extract_value_from("host", node)
78
- res.rule_id = extract_value_from("nvt/@oid", node)
79
- res.description = extract_value_from("description", node)
80
- res.task_id = task_id if task_id
73
+ def self.parse_result_node(node, task_id = nil)
74
+ res = VasResult.new
75
+ res.result_id = extract_value_from("@id", node)
76
+ res.threat = extract_value_from("threat", node)
77
+ res.subnet = extract_value_from("subnet", node)
78
+ res.host = extract_value_from("host", node)
79
+ res.rule_id = extract_value_from("nvt/@oid", node)
80
+ res.description = extract_value_from("description", node)
81
+ res.task_id = task_id if task_id
82
+
83
+ res
84
+ end
81
85
 
82
- res
83
- end
84
-
85
- def threat_level
86
- case @threat
87
- when "High"
88
- 5
89
- when "Medium"
90
- 4
91
- when "Low"
92
- 3
93
- when "Log"
94
- 2
95
- when "Debug"
96
- 1
97
- else
98
- 0
86
+ def threat_level
87
+ case @threat
88
+ when "High"
89
+ 5
90
+ when "Medium"
91
+ 4
92
+ when "Low"
93
+ 3
94
+ when "Log"
95
+ 2
96
+ when "Debug"
97
+ 1
98
+ else
99
+ 0
100
+ end
99
101
  end
100
102
  end
101
-
102
103
  end
@@ -1,63 +1,171 @@
1
1
  require 'vas_base'
2
+ require 'time'
2
3
 
3
- class VasSchedule < VasBase
4
- attr_accessor :schedule_id, :name, :comment, :first_time, :next_time,
5
- :period, :period_months, :duration, :in_use, :task_ids
6
-
7
- validates :schedule_id, :presence => true, :UUID => true
8
-
9
- def self.get_all(options = {})
10
-
11
- manual_sort = false
12
- params = {:details => '1'}
13
- params[:schedule_id] = options[:schedule_id] if options[:schedule_id]
14
- case options[:sort_by]
15
- when :schedule_id
16
- params[:sort_field] = 'id'
17
- when :next_time
18
- manual_sort = true
19
- when :first_time
20
- params[:first_time] = 'first_time'
21
- else
22
- params[:sort_field] = 'name'
23
- end
24
-
25
- req = Nokogiri::XML::Builder.new { |xml|
26
- xml.get_schedules(params)
27
- }
28
-
29
- schedules = client.send_receive(req.doc)
30
-
31
- ret = []
32
- schedules.xpath("//schedule").each { |s|
33
- sch = VasSchedule.new
34
- sch.schedule_id = extract_value_from("@id", s)
35
- sch.name = extract_value_from("name", s)
36
- sch.comment = extract_value_from("comment", s)
37
- t_time = extract_value_from("first_time", s)
38
- sch.first_time = Time.parse(t_time) unless t_time == ""
39
- t_time = extract_value_from("next_time", s)
40
- sch.next_time = Time.parse(t_time) unless t_time == "" or t_time == "done"
41
- sch.period = extract_value_from("period", s).to_i
42
- sch.period_months = extract_value_from("period_months", s).to_i
43
- t_time = extract_value_from("duration", s)
44
- unless t_time == ""
45
- sch.duration = t_time.to_i unless t_time == 0
46
- end
47
- sch.in_use = extract_value_from("in_use", s).to_i > 0
48
- sch.task_ids = []
49
- s.xpath('tasks/task/@id') { |t|
50
- sch.task_ids << t.value
4
+ module OpenvasCli
5
+ class VasSchedule < VasBase
6
+ attr_reader :name
7
+ attr_reader :comment
8
+ attr_reader :first_time
9
+ attr_accessor :next_time
10
+ attr_reader :period
11
+ attr_accessor :duration
12
+ attr_accessor :in_use
13
+ attr_accessor :task_ids
14
+
15
+ validates :id, :UUID => true, :if => Proc.new { |s| s.id }
16
+ validates :name, :presence => true, :length => { :minimum => 1 }
17
+ validates :first_time, :presence => true
18
+
19
+ define_attribute_methods [:name, :comment, :first_time, :period]
20
+
21
+ def initialize(params = {})
22
+ @name = params[:name] if params[:name]
23
+ @comment = params[:comment] if params[:comment]
24
+ @first_time = params[:first_time] if params[:first_time]
25
+ @period = params[:period] if params[:period]
26
+ reset_changes
27
+ end
28
+
29
+ def changed?
30
+ local_changes = false
31
+ local_changes = @period.changed? if @period
32
+
33
+ local_changes || super
34
+ end
35
+
36
+ def name=(v)
37
+ name_will_change! unless @name == v
38
+ @name = v
39
+ end
40
+
41
+ def comment=(v)
42
+ comment_will_change! unless @comment == v
43
+ @comment = v
44
+ end
45
+
46
+ def first_time=(v)
47
+ first_time_will_change! unless @first_time == v
48
+ @first_time = v
49
+ end
50
+
51
+ def period=(v)
52
+ period_will_change! unless @period == v
53
+ @period = v
54
+ end
55
+
56
+ def destroy!
57
+ return unless @id
58
+
59
+ req = Nokogiri::XML::Builder.new { |xml|
60
+ xml.delete_schedule(:schedule_id => @id)
51
61
  }
52
- ret << sch
53
- }
54
-
55
- if manual_sort
56
- if options[:sort_by] == :next_time
57
- ret.sort!{ |a,b| a.next_time <=> b.next_time }
62
+
63
+ VasSchedule.connection.send_receive(req.doc)
64
+ @id = nil
65
+ reset_changes
66
+ end
67
+
68
+ def save!
69
+ return unless changed? || @id == nil
70
+
71
+ if @id
72
+ destroy!
58
73
  end
74
+
75
+ req = Nokogiri::XML::Builder.new { |xml|
76
+ xml.create_schedule {
77
+ xml.name { xml.text(@name) }
78
+ xml.comment { xml.text(@comment) } if @comment
79
+ xml.first_time {
80
+ xml.minute { xml.text(@first_time.min) }
81
+ xml.hour { xml.text(@first_time.hour) }
82
+ xml.day_of_month { xml.text(@first_time.day) }
83
+ xml.month { xml.text(@first_time.month) }
84
+ xml.year { xml.text(@first_time.year) }
85
+ }
86
+ xml.duration { xml.text(@duration ? @duration : 0) }
87
+ xml.period {
88
+ if @period
89
+ xml.text(@period.number)
90
+ xml.unit { xml.text(@period.period.to_s) }
91
+ else
92
+ xml.text(0)
93
+ xml.unit { xml.text("second") }
94
+ end
95
+ }
96
+ }
97
+ }
98
+
99
+ resp = VasSchedule.connection.send_receive(req.doc)
100
+ @id = VasSchedule.extract_value_from("/create_schedule_response/@id", resp) unless @id
101
+ reset_changes
59
102
  end
60
103
 
61
- ret
104
+ def self.get_all(options = {})
105
+
106
+ manual_sort = false
107
+ params = {:details => '1'}
108
+ params[:schedule_id] = options[:id] if options[:id]
109
+ case options[:sort_by]
110
+ when :schedule_id
111
+ params[:sort_field] = 'id'
112
+ when :next_time
113
+ manual_sort = true
114
+ when :first_time
115
+ params[:first_time] = 'first_time'
116
+ else
117
+ params[:sort_field] = 'name'
118
+ end
119
+
120
+ req = Nokogiri::XML::Builder.new { |xml|
121
+ xml.get_schedules(params)
122
+ }
123
+ ret = []
124
+
125
+ begin
126
+ schedules = connection.send_receive(req.doc)
127
+ schedules.xpath("//schedule").each { |s|
128
+ sch = VasSchedule.new
129
+ sch.id = extract_value_from("@id", s)
130
+ sch.name = extract_value_from("name", s)
131
+ sch.comment = extract_value_from("comment", s)
132
+ t_time = extract_value_from("first_time", s)
133
+ sch.first_time = Time.parse(t_time) unless t_time == ""
134
+ t_time = extract_value_from("next_time", s)
135
+ sch.next_time = Time.parse(t_time) unless t_time == "" or t_time == "done"
136
+
137
+ period_num = extract_value_from("period", s).to_i
138
+ if period_num > 0
139
+ sch.period = VasPeriod.from_seconds(period_num)
140
+ end
141
+
142
+ period_num = extract_value_from("period_months", s).to_i
143
+ if period_num > 0
144
+ sch.period = VasPeriod.from_months(period_num)
145
+ end
146
+
147
+ t_time = extract_value_from("duration", s)
148
+ unless t_time == ""
149
+ sch.duration = t_time.to_i unless t_time == 0
150
+ end
151
+
152
+ sch.in_use = extract_value_from("in_use", s).to_i > 0
153
+ sch.task_ids = []
154
+ s.xpath('tasks/task/@id') { |t|
155
+ sch.task_ids << t.value
156
+ }
157
+ ret << sch
158
+ }
159
+
160
+ if manual_sort
161
+ if options[:sort_by] == :next_time
162
+ ret.sort!{ |a,b| a.next_time <=> b.next_time }
163
+ end
164
+ end
165
+ rescue VasExceptions::CommandException => e
166
+ raise e unless e.message =~ /Failed to find schedule/i
167
+ end
168
+ ret
169
+ end
62
170
  end
63
171
  end