watobo 0.9.11 → 0.9.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/CHANGELOG +12 -0
  2. data/bin/watobo +9 -1
  3. data/lib/watobo/adapters/data_store.rb +14 -1
  4. data/lib/watobo/adapters/file/file_store.rb +33 -0
  5. data/lib/watobo/core/active_check.rb +3 -2
  6. data/lib/watobo/core/project.rb +6 -2
  7. data/lib/watobo/core/scanner.rb +7 -1
  8. data/lib/watobo/core/session.rb +3 -1
  9. data/lib/watobo/gui/checkboxtree.rb +243 -101
  10. data/lib/watobo/gui/checks_policy_frame.rb +60 -22
  11. data/lib/watobo/gui/dashboard.rb +25 -4
  12. data/lib/watobo/gui/findings_tree.rb +35 -46
  13. data/lib/watobo/gui/full_scan_dialog.rb +2 -1
  14. data/lib/watobo/gui/fuzzer_gui.rb +1 -1
  15. data/lib/watobo/gui/interceptor_settings_dialog.rb +1 -1
  16. data/lib/watobo/gui/log_viewer.rb +3 -1
  17. data/lib/watobo/gui/main_window.rb +9 -9
  18. data/lib/watobo/gui/manual_request_editor.rb +11 -1
  19. data/lib/watobo/gui/progress_window.rb +16 -6
  20. data/lib/watobo/gui/quick_scan_dialog.rb +5 -5
  21. data/lib/watobo/gui/templates/plugin2.rb +13 -26
  22. data/lib/watobo/mixins/shapers.rb +4 -2
  23. data/lib/watobo.rb +1 -1
  24. data/modules/active/Apache/mod_status.rb +4 -3
  25. data/modules/active/sap/its_commands.rb +1 -1
  26. data/modules/active/sap/its_service_parameter.rb +1 -1
  27. data/modules/active/siebel/siebel_apps.rb +184 -0
  28. data/modules/passive/disclosure_domino.rb +82 -0
  29. data/modules/passive/form_spotter.rb +2 -1
  30. data/plugins/catalog/catalog.rb +63 -25
  31. data/plugins/crawler/gui/crawler_gui.rb +8 -6
  32. data/plugins/crawler/gui/general_settings_frame.rb +4 -4
  33. data/plugins/crawler/lib/grabber.rb +2 -2
  34. data/plugins/filefinder/dbs/hbci.db +1 -0
  35. data/plugins/filefinder/dbs/well_known.db +4 -0
  36. data/plugins/filefinder/filefinder.rb +11 -8
  37. data/plugins/sqlmap/gui/main.rb +17 -5
  38. data/plugins/sslchecker/gui/cipher_table.rb +1 -1
  39. data/plugins/sslchecker/gui/gui.rb +33 -14
  40. metadata +5 -2
data/CHANGELOG CHANGED
@@ -1,3 +1,15 @@
1
+ = Version 0.9.12
2
+ == NEW
3
+ * [Module] Siebel Checks: Enumeration of default apps and files, e.g. base.txt
4
+ * [Module] PassiveCheck filtering Domino DB names
5
+ * [GUI] added De-Select-All buttons to scan policy
6
+ * [GUI] finding details menu available at finding-class level
7
+
8
+ == Fixes
9
+ * crash when pasting data (Linux)
10
+ * crash on starting full scan dialog
11
+ * minor issue when adding a new db-path to catalog scanner plugin
12
+
1
13
  = Version 0.9.11
2
14
  == NEW
3
15
  * [FileFinder] pimped the interface, added save-settings
data/bin/watobo CHANGED
@@ -1,2 +1,10 @@
1
1
  #!/bin/ruby
2
- puts "Please use the command watobo_gui.rb to start watobo."
2
+ # this is just a little wrapper to start watobo with another command than watobo_gui.rb
3
+ if $0 == __FILE__
4
+ inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")) # this is the same as rubygems would do
5
+ $: << inc_path
6
+ end
7
+
8
+ path = File.dirname(File.expand_path(__FILE__))
9
+ require File.join(path, "watobo_gui")
10
+
@@ -20,7 +20,13 @@
20
20
  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
21
  # .
22
22
  module Watobo
23
- class DataStore
23
+ class DataStore
24
+
25
+ @engine = nil
26
+
27
+ def self.engine
28
+ @engine
29
+ end
24
30
 
25
31
  def self.acquire(project_name, session_name)
26
32
  a = Watobo::Conf::Datastore.adapter
@@ -30,9 +36,16 @@ module Watobo
30
36
  else
31
37
  nil
32
38
  end
39
+ @engine = store
33
40
  store
34
41
  end
35
42
 
36
43
 
37
44
  end
45
+
46
+ def self.log(message, prefs={})
47
+ if DataStore.engine.respond_to? :logger
48
+ DataStore.engine.logger message, prefs
49
+ end
50
+ end
38
51
  end
@@ -149,6 +149,10 @@ module Watobo
149
149
  wsp = Watobo.workspace_path
150
150
  return false unless File.exist? wsp
151
151
  puts "* using workspace path: #{wsp}" if $DEBUG
152
+
153
+ @log_file = nil
154
+ @log_lock = Mutex.new
155
+
152
156
  @project_path = File.join(wsp, project_name)
153
157
  unless File.exist? @project_path
154
158
  puts "* create project path: #{@project_path}" if $DEBUG
@@ -193,6 +197,8 @@ module Watobo
193
197
  end
194
198
  end
195
199
  end
200
+
201
+ @log_file = File.join(@log_path, session_name + ".log")
196
202
 
197
203
  # @chat_files = get_file_list(@conversation_path, "*-chat")
198
204
  # @finding_files = get_file_list(@findings_path, "*-finding")
@@ -248,6 +254,33 @@ module Watobo
248
254
  s = Watobo::Utils.load_settings(project_file)
249
255
  s
250
256
 
257
+ end
258
+
259
+ def logger( message, prefs = {} )
260
+ opts = { :sender => "unknown", :level => Watobo::Constants::LOG_INFO }
261
+ opts.update prefs
262
+ return false if @log_file.nil?
263
+ begin
264
+ t = Time.now
265
+ now = t.strftime("%m/%d/%Y @ %H:%M:%S")
266
+ log_message = [ now ]
267
+ log_message << "#{opts[:sender]}"
268
+ if message.is_a? Array
269
+ log_message << message.join("\n| ")
270
+ log_message << "\n-"
271
+ else
272
+ log_message << message
273
+ end
274
+ @log_lock.synchronize do
275
+ File.open(@log_file,"a") do |lfh|
276
+ lfh.puts log_message.join("|")
277
+ end
278
+ end
279
+ rescue => bang
280
+ puts bang
281
+ end
282
+
283
+
251
284
  end
252
285
 
253
286
  private
@@ -55,10 +55,11 @@ module Watobo
55
55
  id_string << new_details[:title] if new_details[:title]
56
56
 
57
57
  if id_string == '' then
58
- id_string = rand(10000)
58
+ id_string = (Time.now.to_i + rand(10000)).to_s
59
59
  end
60
60
  #
61
61
  new_details[:fid] = Digest::MD5.hexdigest(id_string)
62
+ puts new_details[:fid] if $DEBUG
62
63
 
63
64
  new_details[:module] = self.class.to_s
64
65
  # new_details[:module] = Module.nesting[]
@@ -67,7 +68,7 @@ module Watobo
67
68
  new_details.delete(:chat)
68
69
 
69
70
  new_finding = Watobo::Finding.new(request, response, new_details)
70
- # puts new_finding
71
+ # puts new_finding
71
72
  notify(:new_finding, new_finding)
72
73
  }
73
74
  end
@@ -640,7 +640,7 @@ module Watobo
640
640
  :save_finding => true
641
641
  }
642
642
  options.update opts
643
- # puts "* add finding #{finding.details[:fid]}" if $DEBUG
643
+ puts "[Project] add finding #{finding.details[:fid]}" if $DEBUG
644
644
 
645
645
  @findings_count ||= Hash.new
646
646
  @findings_count[finding.details[:class]] = 0 unless @findings_count.has_key? finding.details[:class]
@@ -814,7 +814,11 @@ module Watobo
814
814
  # @active_checks = @settings[:active_checks]
815
815
  @settings[:active_checks].each do |am|
816
816
  ac = am.new(self)
817
- ac.subscribe(:new_finding){ |nf| addFinding(nf) }
817
+ # puts "subscribe to #{ac.class}"
818
+ ac.subscribe(:new_finding){ |nf|
819
+ # puts "[subscribe] new_finding"
820
+ addFinding(nf)
821
+ }
818
822
  @active_checks << ac
819
823
  end
820
824
 
@@ -27,6 +27,7 @@ module Watobo
27
27
  attr :progress
28
28
 
29
29
  include Watobo::Constants
30
+
30
31
  def subscribe(event, &callback)
31
32
  (@event_dispatcher_listeners[event] ||= []) << callback
32
33
  end
@@ -264,11 +265,16 @@ module Watobo
264
265
  check.reset()
265
266
  if @prefs[:online_check] == false or siteAlive?(chat) then
266
267
  @check_list << Thread.new(check, chat, check_prefs){|m, c, p|
268
+ begin
267
269
  m_name = m.class.to_s.gsub(/.*::/,'')
268
270
  notify(:module_started, m_name)
269
271
  m.run_checks(c,p)
272
+ rescue => bang
273
+ puts bang
274
+ puts bang.backtrace
275
+ end
270
276
  notify(:logger, LOG_INFO, "finished checks: #{m.class} on chat #{c.id}")
271
- notify(:module_finished, m_name)
277
+ notify(:module_finished, m)
272
278
  }
273
279
  end
274
280
  end
@@ -37,6 +37,8 @@ include Watobo::Constants
37
37
  @@login_in_progress = false
38
38
  def subscribe(event, &callback)
39
39
  (@event_dispatcher_listeners[event] ||= []) << callback
40
+ puts "#{self} : #subscriptions -> #{event} :" + @event_dispatcher_listeners[event].length.to_s
41
+ puts @event_dispatcher_listeners[event].first
40
42
  end
41
43
 
42
44
  def clearEvents(event)
@@ -46,7 +48,7 @@ include Watobo::Constants
46
48
 
47
49
  def notify(event, *args)
48
50
  if @event_dispatcher_listeners[event]
49
- puts "NOTIFY: #{self}(:#{event}) [#{@event_dispatcher_listeners[event].length}]" if $DEBUG
51
+ # puts "NOTIFY: #{self}(:#{event}) [#{@event_dispatcher_listeners[event].length}]" if $DEBUG
50
52
  @event_dispatcher_listeners[event].each do |m|
51
53
  m.call(*args) if m.respond_to? :call
52
54
  end
@@ -19,20 +19,71 @@
19
19
  # along with WATOBO; if not, write to the Free Software
20
20
  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
21
  # .
22
+ if $0 == __FILE__
23
+ inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", ".."))
24
+ $: << inc_path
25
+
26
+ require 'watobo'
27
+ require 'watobo/gui'
28
+
29
+ require 'fox16'
30
+
31
+ include Fox
32
+ include Watobo::Constants
33
+
34
+ end
35
+
22
36
  module Watobo
23
37
  module Gui
24
38
  class CheckBoxTreeItem < FXTreeItem
25
39
  attr_accessor :checked
26
-
40
+
27
41
  include Watobo::Gui::Icons
28
- def initialize(text, checked, data)
29
- @checked = checked
30
- icon = ICON_CB_CHECKED
31
- icon = ICON_CB_UNCHECKED if not checked
32
- super(text, icon, icon, data)
42
+ def check
43
+ begin
44
+ @checked = true
45
+ self.setOpenIcon(ICON_CB_CHECKED)
46
+ self.setClosedIcon(ICON_CB_CHECKED)
47
+ # opened = true
48
+ rescue => bang
49
+ puts "!!!ERROR: could not uncheck item"
50
+ end
51
+ end
52
+
53
+ def uncheck
54
+ begin
55
+ @checked = false
56
+ self.setOpenIcon(ICON_CB_UNCHECKED)
57
+ self.setClosedIcon(ICON_CB_UNCHECKED)
58
+ #opened = false
59
+ rescue => bang
60
+ puts "!!!ERROR: could not uncheck item"
61
+ end
62
+ end
63
+
64
+ def toggle
65
+ if @checked
66
+ uncheck
67
+ else
68
+ check
69
+ end
70
+ end
71
+
72
+ def initialize(item_text, item_status, item_data)
73
+ super item_text
74
+ @checked = item_status
75
+ #icon = ICON_CB_CHECKED
76
+ #icon = ICON_CB_UNCHECKED if not status
77
+ #super(text, icon, icon, data)
78
+ # data = item_data
79
+ if @checked
80
+ check
81
+ else
82
+ uncheck
83
+ end
33
84
  end
34
85
  end
35
-
86
+
36
87
  class CheckBoxTreeList < FXTreeList
37
88
  include Watobo::Gui::Icons
38
89
  #------------------------------
@@ -42,51 +93,52 @@ module Watobo
42
93
  # :name => element_name, number of subtrees controlled via pipe-char, e.g. <level1>|<level2>|item
43
94
  # :enabled => true|false,
44
95
  # :data => object|string|...
45
- # }, {..} ]
46
- def createTree(elements)
96
+ # }, {..} ]
97
+ def elements=(elements)
47
98
  self.clearItems()
48
99
  elements.each do |e|
49
-
50
- # puts icon.class.to_s
100
+
101
+ # puts icon.class.to_s
51
102
  node = nil
52
103
  levels = e[:name].split('|')
53
- puts "Processing: #{e[:name]} > #{e[:data].class}" if $DEBUG
54
- levels.each do |l|
55
-
104
+ # puts "Processing: #{e[:name]} > #{e[:data].class}" if $DEBUG
105
+ levels.each_with_index do |l,i|
106
+ #puts "#{l} - #{l.class}"
56
107
  item = self.findItem(l, node, SEARCH_FORWARD|SEARCH_IGNORECASE)
57
-
108
+
58
109
  if item.nil? then
59
- new_item = CheckBoxTreeItem.new(l, e[:enabled], nil)
60
- # item = self.appendItem(node, l, ICON_CB_CHECKED, ICON_CB_CHECKED)
61
- item = self.appendItem(node, new_item)
62
- if e[:enabled] then
63
- self.openItem(item, false)
64
- else
65
- self.closeItem(item, false)
66
- end
110
+ # new_item = CheckBoxTreeItem.new(l, e[:enabled], nil)
111
+ new_item = CheckBoxTreeItem.new(l, e[:enabled], :none)
112
+ # item = self.appendItem(node, l, ICON_CB_CHECKED, ICON_CB_CHECKED)
113
+ item = self.appendItem(node, new_item)
114
+ # if e[:enabled] then
115
+ # self.openItem(item, false)
116
+ # else
117
+ # self.closeItem(item, false)
118
+ # end
67
119
  end
68
120
  node = item
69
- if l == levels.last then
121
+ if i == levels.length-1 then
70
122
  self.setItemData(item, e[:data])
71
123
  updateParent(item)
72
124
  end
73
-
125
+
74
126
  end
75
127
  end
76
128
  end
77
-
129
+
78
130
  def updateParent(child)
79
131
  parent = child.parent
80
132
  # count enabled childs
81
133
  return false if parent.nil?
82
134
  ec = 0
83
135
  parent.each do |item|
84
- #data = self.getItemData(item)
85
- #ec += 1 if data[:enabled]
136
+ #data = self.getItemData(item)
137
+ #ec += 1 if data[:enabled]
86
138
  ec += 1 if item.checked
87
139
  end
88
140
  if ec == 0 then
89
-
141
+
90
142
  # puts "no childs selected"
91
143
  icon = ICON_CB_UNCHECKED
92
144
  self.setItemData(parent, :none)
@@ -95,130 +147,220 @@ module Watobo
95
147
  icon = ICON_CB_CHECKED_ORANGE
96
148
  self.setItemData(parent, :partly)
97
149
  else
98
-
99
- # puts "all childs have been selected"
150
+
151
+ # puts "all childs have been selected"
100
152
  icon = ICON_CB_CHECKED
101
153
  self.setItemData(parent, :all)
102
154
  end
103
155
  self.setItemOpenIcon(parent, icon)
104
156
  self.setItemClosedIcon(parent, icon)
105
157
  end
106
-
107
- def toggleState(item)
108
- # data = self.getItemData(item)
109
- # if data[:enabled] then
110
- if item.checked then
111
- uncheckItem(item)
112
- else
113
- checkItem(item)
114
- end
115
- end
116
-
117
- def uncheckItem(item)
118
- begin
119
- #data = self.getItemData(item)
120
- #data[:enabled]= false
121
- item.checked = false
122
- self.setItemOpenIcon(item, ICON_CB_UNCHECKED)
123
- self.setItemClosedIcon(item, ICON_CB_UNCHECKED)
124
- #puts item.data.class
125
- rescue => bang
126
- puts "!!!ERROR: could not uncheck item"
127
- end
128
-
129
- end
130
-
131
-
132
- def getCheckedData(item = nil, data = nil)
158
+
159
+ def getCheckedData(item = nil, data = nil)
133
160
  data = [] if !data
134
161
  item = self if !item
135
162
  item.each do |c|
136
- getCheckedData(c, data) if c.numChildren > 0
137
- data.push c.data if self.itemLeaf?(c) and c.checked
138
- end
139
- data
163
+ getCheckedData(c, data) if c.numChildren > 0
164
+ data.push c.data if self.itemLeaf?(c) and c.checked
165
+ end
166
+ data
140
167
  end
141
-
142
- def checkItem(item)
143
- begin
144
- #data = self.getItemData(item)
145
- #data[:enabled] = true
146
- item.checked = true
147
- self.setItemClosedIcon(item, ICON_CB_CHECKED)
148
- self.setItemOpenIcon(item, ICON_CB_CHECKED)
149
- # puts item.data.class
150
- rescue => bang
151
- puts "!!!ERROR: could not uncheck item"
168
+
169
+ def checkAll
170
+ self.each do |r|
171
+ r.check
172
+ setItemData(r,:all)
173
+ r.each do |c|
174
+ c.check
175
+ end
176
+ self.update
177
+ # checkAllChildren(r)
178
+ # openItem(child, true)
152
179
  end
153
180
  end
154
-
181
+
182
+ def uncheckAll
183
+ self.each do |r|
184
+ # uncheckItem(r)
185
+ r.uncheck
186
+ setItemData(r,:none)
187
+ r.each do |c|
188
+ c.uncheck
189
+ end
190
+ #uncheckAllChildren(r)
191
+ self.update
192
+ end
193
+ end
194
+
195
+
155
196
  def uncheckAllChildren(parent)
156
197
  parent.each do |child|
157
- uncheckItem(child)
198
+ #uncheckItem(child)
199
+ child.uncheck
158
200
  end
159
201
  end
160
-
202
+
161
203
  def checkAllChildren(parent)
162
204
  parent.each do |child|
163
- checkItem(child)
205
+ #checkItem(child)
206
+ child.check
207
+
164
208
  end
165
209
  end
166
-
210
+
167
211
  def initialize(parent)
168
-
212
+
169
213
  @parent = parent
170
214
  super(parent, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|
171
- TREELIST_SHOWS_LINES|
172
- TREELIST_SHOWS_BOXES|
173
- TREELIST_ROOT_BOXES|
174
- #TREELIST_EXTENDEDSELECT|
175
- TREELIST_MULTIPLESELECT
215
+ TREELIST_SHOWS_LINES|
216
+ TREELIST_SHOWS_BOXES|
217
+ TREELIST_ROOT_BOXES|
218
+ #TREELIST_EXTENDEDSELECT|
219
+ TREELIST_MULTIPLESELECT
176
220
  )
177
221
  #LAYOUT_TOP|LAYOUT_RIGHT|TREELIST_SHOWS_LINES|TREELIST_SHOWS_BOXES|TREELIST_ROOT_BOXES|TREELIST_EXTENDEDSELECT
178
-
222
+
179
223
  self.connect(SEL_COMMAND) do |sender, sel, item|
180
224
  if $DEBUG
181
- puts "Selected Item: #{item}"
225
+ puts "Selected Item: #{item}"
182
226
  if item.parent
183
227
  puts "Member Of: #{item.parent}"
184
- puts "Has Brothers: #{item.parent.numChildren}"
228
+ puts "Has Brothers: #{item.parent.numChildren}"
185
229
  end
186
230
  end
231
+
187
232
  if self.itemLeaf?(item) then
188
- toggleState(item)
233
+ #toggleState(item)
234
+ item.toggle
189
235
  updateParent(item)
190
236
  else
191
237
  data = self.getItemData(item)
238
+
192
239
  new_state = case data
193
- when :partly
240
+ when :partly
194
241
  # puts data
195
242
  icon = ICON_CB_UNCHECKED
196
243
  uncheckAllChildren(item)
197
244
  :none
198
- when :none
245
+ when :none
199
246
  # puts data
200
247
  icon = ICON_CB_CHECKED
201
248
  checkAllChildren(item)
202
249
  :all
203
- when :all
250
+ when :all
204
251
  # puts data
205
252
  icon = ICON_CB_UNCHECKED
206
253
  uncheckAllChildren(item)
207
254
  :none
208
255
  end
209
-
210
- self.setItemData(item, new_state)
211
- self.setItemClosedIcon(item, icon)
212
- self.setItemOpenIcon(item, icon)
256
+
257
+ self.setItemData(item, new_state)
258
+ self.setItemClosedIcon(item, icon)
259
+ self.setItemOpenIcon(item, icon)
213
260
  end
214
-
261
+
215
262
  self.killSelection()
216
- end
217
-
218
-
219
-
263
+ end
264
+
220
265
  end
221
266
  end
222
- #--
267
+ #--
223
268
  end
224
269
  end
270
+
271
+ ##########################
272
+
273
+ if $0 == __FILE__
274
+ module Watobo
275
+ module Gui
276
+
277
+ @application ||= FXApp.new('LayoutTester', 'FoxTest')
278
+ class TestGui < FXMainWindow
279
+ class TreeDlg < FXDialogBox
280
+
281
+ include Responder
282
+ def initialize(parent, project=nil, prefs={} )
283
+ super(parent, "CheckBox Dialog", DECOR_ALL, :width => 300, :height => 400)
284
+ FXMAPFUNC(SEL_COMMAND, ID_ACCEPT, :onAccept)
285
+ frame = FXVerticalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_GROOVE)
286
+ elements = []
287
+ num_root_nodes = 4
288
+ max_child_nodes = 4
289
+ num_root_nodes.times do |ri|
290
+ max_child_nodes.times do |si|
291
+ name = "root#{ri}|sub#{si}"
292
+ data = name + "-data"
293
+ e = { :name => name, :enabled => false, :data => data }
294
+ elements << e
295
+ end
296
+ end
297
+ @cbtree = CheckBoxTreeList.new(frame)
298
+ @cbtree.elements = elements
299
+
300
+ end
301
+ private
302
+
303
+ def onAccept(sender, sel, event)
304
+ puts "#{self} closed"
305
+
306
+ getApp().stopModal(self, 1)
307
+ self.hide()
308
+ return 1
309
+ end
310
+ end
311
+
312
+ def leave
313
+ d = @cbtree.getCheckedData
314
+ puts d.class
315
+ puts d
316
+ exit
317
+ end
318
+
319
+ def initialize(app)
320
+ # Call base class initializer first
321
+ super(app, "Test Application", :width => 800, :height => 600)
322
+ frame = FXVerticalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_GROOVE)
323
+
324
+ elements = []
325
+ num_root_nodes = 4
326
+ max_child_nodes = 4
327
+ num_root_nodes.times do |ri|
328
+ max_child_nodes.times do |si|
329
+ name = "root#{ri}|sub#{si}"
330
+ data = name + "-data"
331
+ e = { :name => name, :enabled => false, :data => data }
332
+ elements << e
333
+ end
334
+ end
335
+
336
+ @cbtree = CheckBoxTreeList.new(frame)
337
+ @cbtree.elements = elements
338
+
339
+ FXButton.new(frame, "Select All",:opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT).connect(SEL_COMMAND){ @cbtree.checkAll }
340
+ FXButton.new(frame, "Deselect All",:opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT).connect(SEL_COMMAND){ @cbtree.uncheckAll }
341
+
342
+ FXButton.new(frame, "Open TreeDialog",:opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT).connect(SEL_COMMAND){
343
+ dlg = TreeDlg.new(self)
344
+ if dlg.execute != 0 then
345
+ puts "* Dialog Finished"
346
+ else
347
+ puts "Dialog Canceled"
348
+ end
349
+ }
350
+
351
+ FXButton.new(frame, "Exit",:opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT).connect(SEL_COMMAND){ leave }
352
+ end
353
+
354
+ def create
355
+ super # Create the windows
356
+ show(PLACEMENT_SCREEN) # Make the main window appear
357
+ end
358
+ end
359
+ # application = FXApp.new('LayoutTester', 'FoxTest')
360
+ TestGui.new(@application)
361
+ @application.create
362
+ @application.run
363
+
364
+ end
365
+ end
366
+ end