watobo 0.9.20 → 0.9.21

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 (51) hide show
  1. data/CHANGELOG.md +54 -2
  2. data/README.md +1 -1
  3. data/config/scanner.yml +1 -0
  4. data/custom-views/prettify-json.rb +19 -0
  5. data/lib/watobo/adapters/file/marshal_store.rb +297 -0
  6. data/lib/watobo/adapters.rb +2 -1
  7. data/lib/watobo/core/active_check.rb +4 -0
  8. data/lib/watobo/core/chat.rb +8 -0
  9. data/lib/watobo/core/chats.rb +2 -1
  10. data/lib/watobo/core/cookie.rb +3 -3
  11. data/lib/watobo/core/finding.rb +7 -0
  12. data/lib/watobo/core/request.rb +3 -3
  13. data/lib/watobo/core/session.rb +6 -2
  14. data/lib/watobo/framework/init_modules.rb +18 -16
  15. data/lib/watobo/gui/conversation_table.rb +13 -16
  16. data/lib/watobo/gui/conversation_table_ctrl2.rb +1 -0
  17. data/lib/watobo/gui/custom_viewer.rb +101 -76
  18. data/lib/watobo/gui/define_scope_frame.rb +44 -10
  19. data/lib/watobo/gui/edit_scope_dialog.rb +1 -1
  20. data/lib/watobo/gui/fuzzer_gui.rb +61 -23
  21. data/lib/watobo/gui/main_window.rb +1 -1
  22. data/lib/watobo/gui/scanner_settings_dialog.rb +15 -0
  23. data/lib/watobo/http/data/json.rb +6 -0
  24. data/lib/watobo/interceptor/html/favicon.ico +0 -0
  25. data/lib/watobo/interceptor/html/index.html +13 -0
  26. data/lib/watobo/interceptor/proxy.rb +70 -18
  27. data/lib/watobo/mixins/httpparser.rb +26 -16
  28. data/lib/watobo/mixins/shapers.rb +49 -5
  29. data/lib/watobo/mixins/transcoders.rb +8 -8
  30. data/lib/watobo/sockets/connection.rb +1 -1
  31. data/lib/watobo/utils/load_chat.rb +62 -0
  32. data/lib/watobo/utils/response_hash.rb +3 -3
  33. data/lib/watobo.rb +1 -1
  34. data/modules/active/cq5/cq5_default_selectors.rb +116 -0
  35. data/modules/active/cq5/cqp_user_enumeration.rb +134 -0
  36. data/modules/active/struts2/include_params_ognl.rb +1 -1
  37. data/modules/active/xml/xml_xxe.rb +6 -1
  38. data/modules/passive/disclosure_domino.rb +1 -1
  39. data/modules/passive/in_script_parameter.rb +9 -4
  40. data/plugins/aem/aem.rb +21 -0
  41. data/plugins/aem/gui/main.rb +128 -0
  42. data/plugins/aem/gui/tree_view.rb +180 -0
  43. data/plugins/aem/icons/aem.ico +0 -0
  44. data/plugins/aem/lib/agent.rb +140 -0
  45. data/plugins/aem/lib/dispatcher.rb +53 -0
  46. data/plugins/aem/lib/engine.rb +187 -0
  47. data/plugins/filefinder/dbs/cq5.db +23 -0
  48. data/plugins/filefinder/dbs/subs-big.lst +44 -44
  49. data/plugins/filefinder/filefinder.rb +4 -4
  50. data/plugins/sqlmap/lib/sqlmap_ctrl.rb +11 -10
  51. metadata +16 -2
@@ -35,9 +35,9 @@ module Watobo#:nodoc: all
35
35
  @name = prefs[:name]
36
36
  @value = prefs[:value]
37
37
  else
38
- puts "= NEW COOKIE ="
39
- puts prefs
40
- puts prefs.class
38
+ # puts "= NEW COOKIE ="
39
+ # puts prefs
40
+ # puts prefs.class
41
41
  chunks = prefs.split(";")
42
42
  # first chunk
43
43
  @name, @value = chunks.first.split(":").last.split("=")
@@ -45,6 +45,13 @@ module Watobo#:nodoc: all
45
45
  return @details[name]
46
46
  end
47
47
  super
48
+ end
49
+
50
+ def to_h
51
+ h = { :details => @details }
52
+ h[:request] = @request.to_a
53
+ h[:response] = @response.to_a
54
+ h
48
55
  end
49
56
 
50
57
  def initialize(request, response, details = {})
@@ -124,7 +124,7 @@ module Watobo#:nodoc: all
124
124
  elsif r.is_a? String
125
125
  if r =~ /^http/
126
126
  uri = URI.parse r
127
- self << "GET #{uri.to_s} HTTP/1.0\r\n"
127
+ self << "GET #{uri.to_s} HTTP/1.1\r\n"
128
128
  self << "Host: #{uri.host}\r\n"
129
129
  else
130
130
  r.extend Watobo::Mixins::RequestParser
@@ -134,8 +134,8 @@ module Watobo#:nodoc: all
134
134
  end
135
135
  self.extend Watobo::Mixin::Parser::Url
136
136
  self.extend Watobo::Mixin::Parser::Web10
137
- self.extend Watobo::Mixin::Shaper::Web10
138
-
137
+ self.extend Watobo::Mixin::Shaper::Web10
138
+
139
139
  @url = Watobo::HTTP::Url.new(self)
140
140
  case self.content_type
141
141
  when /www-form/i
@@ -92,7 +92,11 @@ module Watobo#:nodoc: all
92
92
  #---------------------------------------
93
93
  # request.removeHeader("^Proxy-Connection") #if not use_proxy
94
94
  # request.removeHeader("^Connection") #if not use_proxy
95
- #request.removeHeader("^Accept-Encoding")
95
+
96
+ # !!!
97
+ # remove Accept-Encoding header
98
+ # otherwise we won't get the content-length information for pass-through feature
99
+ request.removeHeader("^Accept-Encoding")
96
100
  # If-Modified-Since: Tue, 28 Oct 2008 11:06:43 GMT
97
101
  # If-None-Match: W/"3975-1225192003000"
98
102
  # request.removeHeader("^If-")
@@ -1117,7 +1121,7 @@ end
1117
1121
  return nil
1118
1122
  end
1119
1123
 
1120
- header = [ "HTTP/1.1 200 OK\r\n", "Server: WATOBO\r\n", "Content-Length: #{msg.length.to_i}\r\n", "Content-Type: text/html\r\n", "\r\n", "#{msg}" ] unless msg.nil?
1124
+ header = [ "HTTP/1.1 502 Bad Gateway\r\n", "Server: WATOBO\r\n", "Content-Length: #{msg.length.to_i}\r\n", "Content-Type: text/html\r\n", "\r\n", "#{msg}" ] unless msg.nil?
1121
1125
 
1122
1126
  response = Watobo::Response.new header
1123
1127
  # update_sids(header)
@@ -7,7 +7,7 @@
7
7
  # WATOBO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8
8
  # You should have received a copy of the GNU General Public License along with WATOBO; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9
9
 
10
- # @private
10
+ # @private
11
11
  module Watobo#:nodoc: all
12
12
 
13
13
  private
@@ -36,14 +36,14 @@ module Watobo#:nodoc: all
36
36
  # notify(:logger, LOG_DEBUG, "#{modules} loaded.")
37
37
 
38
38
  rescue => bang
39
- puts "!!!"
40
- puts bang
39
+ puts "!!!"
40
+ puts bang
41
41
  end
42
42
  end
43
43
  passive_modules
44
44
  end
45
-
46
- def self.init_passive_modules(filter='')
45
+
46
+ def self.init_passive_modules(filter='')
47
47
  # puts "get passive modules from path #{@settings[:module_path]}/passive"
48
48
  passive_modules = []
49
49
 
@@ -52,25 +52,24 @@ module Watobo#:nodoc: all
52
52
  mod = File.basename(mod_file)
53
53
 
54
54
  load mod_file
55
- rescue => bang
56
- puts "!!!"
57
- puts bang
55
+ rescue => bang
56
+ puts "!!!"
57
+ puts bang
58
58
  end
59
59
  end
60
-
60
+
61
61
  Watobo::Modules::Passive.constants.each do |m|
62
62
  begin
63
63
  class_constant = Watobo::Modules::Passive.const_get(m)
64
64
  passive_modules.push class_constant
65
65
  rescue => bang
66
- puts "!!!"
67
- puts bang
66
+ puts "!!!"
67
+ puts bang
68
68
  end
69
69
  end
70
70
  passive_modules
71
71
  end
72
72
 
73
-
74
73
  def self.init_active_modules()
75
74
 
76
75
  active_path = Watobo.active_module_path
@@ -96,7 +95,10 @@ module Watobo#:nodoc: all
96
95
  # notify(:logger, LOG_INFO, "#{module_class} loaded.")
97
96
  active_checks.push class_constant
98
97
  rescue => bang
99
- puts bang
98
+ puts '---'
99
+ puts bang
100
+ puts "when loading module file #{mod_file}"
101
+ puts '---'
100
102
  # notify(:logger, LOG_DEBUG, "problems loading module: #{@settings[:module_path]}/active/#{group}/#{modules}")
101
103
  end
102
104
  end
@@ -125,9 +127,9 @@ module Watobo#:nodoc: all
125
127
  #@interface.log("#{modules} loaded.")
126
128
 
127
129
  rescue => bang
128
- puts bang
129
- #@interface.log("problems loading module: #{module_path}/#{group}/#{modules}")
130
- puts "problems loading module: #{filename}"
130
+ puts bang
131
+ #@interface.log("problems loading module: #{module_path}/#{group}/#{modules}")
132
+ puts "problems loading module: #{filename}"
131
133
  end
132
134
  end
133
135
  end
@@ -436,23 +436,19 @@ module Watobo#:nodoc: all
436
436
 
437
437
  parms = ""
438
438
  unless ps.empty?
439
- # parms = ps[0..50]
440
- # parms += "..." if ps.length > 50
439
+ ps_ascii = ps.force_encoding('ASCII-8BIT')
440
+
441
441
  if @url_decode == true
442
442
  if chat.request.content_type =~ /(json|xml)/
443
- parms = ps.unpack('C*').pack('U*')
444
- else
445
- parms = CGI.unescape(ps).unpack('C*').pack('U*')
443
+ parms = ps_ascii
444
+ else
445
+ parms = CGI.unescape(ps_ascii)
446
446
  end
447
447
  end
448
448
  parms.gsub!(/[^[:print:]]/,'.')
449
449
 
450
450
  end
451
451
 
452
- #if parms.length > 50
453
- # parms = parms[0..50] + "..."
454
- #end
455
-
456
452
  self.setItemText(lastRowIndex, index, parms)
457
453
  self.getItem(lastRowIndex, index).justify = FXTableItem::LEFT
458
454
 
@@ -478,7 +474,9 @@ module Watobo#:nodoc: all
478
474
  self.setItemData(lastRowIndex, 0, chat)
479
475
 
480
476
  #self.makePositionVisible(self.numRows-1, 0) if @autoscroll == true
481
- self.setPosition(self.xPosition, (self.viewportHeight - self.contentHeight - 20 ))
477
+ if @autoscroll == true
478
+ self.setPosition(self.xPosition, (self.viewportHeight - self.contentHeight - 20 ))
479
+ end
482
480
  end
483
481
 
484
482
  def update_table()
@@ -611,14 +609,13 @@ module Watobo#:nodoc: all
611
609
  else
612
610
  sel = ni
613
611
  end
614
- puts "neares: #{sel}"
615
- if sel >= 0
616
- selectRow(sel, false)
617
-
618
- setCurrentItem(sel, 2)
619
- makePositionVisible(i,2)
620
612
 
613
+ if sel >= 0
614
+ selectRow(sel, false)
615
+ setCurrentItem(sel, 2)
616
+ makePositionVisible(sel,2)
621
617
  end
618
+
622
619
  false
623
620
  end
624
621
 
@@ -296,6 +296,7 @@ module Watobo#:nodoc: all
296
296
  @table_option_autoscroll.setCheck(true)
297
297
 
298
298
  @table_option_autoscroll.connect(SEL_COMMAND){
299
+ puts "* Autoscroll >> #{@table_option_autoscroll.checked?.class}"
299
300
  @table.autoscroll = @table_option_autoscroll.checked?
300
301
  }
301
302
 
@@ -10,12 +10,99 @@
10
10
  # @private
11
11
  module Watobo#:nodoc: all
12
12
  module Gui
13
+
14
+ class ViewerHandlerCtrl < FXHorizontalFrame
15
+ attr :handler
16
+
17
+ def has_handler?
18
+ !@handler.nil?
19
+ end
20
+
21
+ def initialize(parent, opts = { :opts => LAYOUT_FILL_X|LAYOUT_SIDE_BOTTOM, :padding => 0 })
22
+ super parent, opts
23
+ @parent = parent
24
+ #handler_ctrl_frame = FXHorizontalFrame.new(self, :opts => LAYOUT_FILL_X, :padding => 0)
25
+ FXLabel.new(self, "View Handler:")
26
+ @handler_status_lbl = FXLabel.new(self, "None")
27
+ @handler_status_lbl.backColor = "red"
28
+ add_handler_btn = FXButton.new(self, "add", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y|LAYOUT_RIGHT)
29
+ add_handler_btn.connect(SEL_COMMAND){ add_handler }
30
+ reload_handler_btn = FXButton.new(self, "reload", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y|LAYOUT_RIGHT)
31
+ reload_handler_btn.connect(SEL_COMMAND){ load_handler(@handler_file) }
32
+ reset_handler_btn = FXButton.new(self, "reset", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y|LAYOUT_RIGHT)
33
+
34
+ reset_handler_btn.connect(SEL_COMMAND){
35
+ @handler = nil
36
+ @handler_file = nil
37
+ @handler_status_lbl.text = "None"
38
+ @handler_status_lbl.backColor = "red"
39
+ }
40
+ end
41
+
42
+
43
+ def add_handler
44
+ handler_filename = FXFileDialog.getOpenFilename(self, "Select handler file", @handler_path, "*.rb\n*")
45
+ if handler_filename != "" then
46
+ if File.exists?(handler_filename) then
47
+ @handler_file = handler_filename
48
+ @handler_path = File.dirname(handler_filename) + "/"
49
+ load_handler(handler_filename)
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+ def load_handler(file)
56
+ @handler = nil
57
+ @handler_status_lbl.text = "None"
58
+ @handler_status_lbl.backColor = "red"
59
+
60
+ return false if file.nil?
61
+ return false unless File.exist? file
62
+ begin
63
+ source = File.read(file)
64
+ #puts source
65
+ result = eval(source)
66
+ if result.respond_to? :call
67
+ @handler = result
68
+ @handler_status_lbl.text = "#{File.basename(file).gsub(/\.rb$/,'')}"
69
+ @handler_status_lbl.textColor = 'black'
70
+ @handler_status_lbl.backColor = 'green'
71
+ @parent.setText
72
+ end
73
+ return true
74
+
75
+ rescue SyntaxError, LocalJumpError, NameError => e
76
+ out = e.to_s
77
+ out << e.backtrace.join("\n")
78
+ rescue => bang
79
+ out = bang
80
+ out << bang.backtrace.join("\n")
81
+ end
82
+ puts out
83
+ return false
84
+ end
85
+
86
+ def call_handler(object)
87
+ return object if @handler.nil?
88
+ begin
89
+ result = @handler.call(object)
90
+ return result
91
+ rescue => bang
92
+ result = bang.to_s
93
+ result << bang.backtrace.join("\n")
94
+ return result
95
+ end
96
+
97
+ end
98
+ end
13
99
 
14
100
 
15
101
  class CustomViewer < FXVerticalFrame
16
- SEL_TYPE_GREP = 0
17
- SEL_TYPE_HIGHLIGHT = 1
102
+ SEL_TYPE_GREP = 0
103
+ SEL_TYPE_HIGHLIGHT = 1
18
104
  attr_accessor :max_len
105
+
19
106
  def style=(new_style)
20
107
  @simple_text_view.style = new_style
21
108
  end
@@ -24,13 +111,17 @@ module Watobo#:nodoc: all
24
111
  @simple_text_view.editable = value
25
112
  end
26
113
 
27
- def setText(text, prefs={})
114
+ def setText(object=nil, prefs={})
28
115
 
29
- normalized_text = text
30
- if text.is_a? Watobo::Request or text.is_a? Watobo::Response
31
- return false unless @handler.respond_to? :call
32
- result = call_handler(text)
33
- normalized_text = result
116
+ o = object.nil? ? @object : object
117
+ return false if o.nil?
118
+ @object = o
119
+ normalized_text = o.to_s
120
+ if o.is_a? Watobo::Request or o.is_a? Watobo::Response
121
+ if @handler_ctrl.has_handler?
122
+ result = @handler_ctrl.call_handler(o)
123
+ normalized_text = result
124
+ end
34
125
  else
35
126
  return false
36
127
  end
@@ -64,6 +155,7 @@ module Watobo#:nodoc: all
64
155
 
65
156
  @style = 2 # default style
66
157
  @text = ''
158
+ @object = nil
67
159
  @max_len = 5000
68
160
  @filter_mode = SEL_TYPE_HIGHLIGHT
69
161
  @cur_match_pos = 0
@@ -74,20 +166,7 @@ module Watobo#:nodoc: all
74
166
  @handler_file = nil
75
167
  @handler_path = nil
76
168
 
77
- handler_ctrl_frame = FXHorizontalFrame.new(self, :opts => LAYOUT_FILL_X, :padding => 0)
78
- @handler_status_lbl = FXLabel.new(handler_ctrl_frame, "No handler!")
79
- @handler_status_lbl.textColor = "red"
80
- add_handler_btn = FXButton.new(handler_ctrl_frame, "add", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y|LAYOUT_RIGHT)
81
- add_handler_btn.connect(SEL_COMMAND){ add_handler }
82
- reload_handler_btn = FXButton.new(handler_ctrl_frame, "reload", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y|LAYOUT_RIGHT)
83
- reload_handler_btn.connect(SEL_COMMAND){ load_handler(@handler_file) }
84
- reset_handler_btn = FXButton.new(handler_ctrl_frame, "reset", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y|LAYOUT_RIGHT)
85
- reset_handler_btn.connect(SEL_COMMAND){
86
- @handler = nil
87
- @handler_file = nil
88
- @handler_status_lbl = FXLabel.new(handler_ctrl_frame, "No handler!")
89
- @handler_status_lbl.textColor = "red"
90
- }
169
+ @handler_ctrl = ViewerHandlerCtrl.new(self)
91
170
 
92
171
  text_view_header = FXHorizontalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_SIDE_BOTTOM|LAYOUT_FIX_HEIGHT,:height => 24, :padding => 0)
93
172
 
@@ -163,60 +242,6 @@ module Watobo#:nodoc: all
163
242
  end
164
243
 
165
244
  private
166
-
167
- def add_handler
168
-
169
- handler_filename = FXFileDialog.getOpenFilename(self, "Select handler file", @handler_path, "*.rb\n*")
170
- if handler_filename != "" then
171
- if File.exists?(handler_filename) then
172
- @handler_file = handler_filename
173
- @handler_path = File.dirname(handler_filename) + "/"
174
- load_handler(handler_filename)
175
- end
176
- end
177
-
178
- end
179
-
180
- def load_handler(file)
181
- @handler = nil
182
- @handler_status_lbl.text = "No handler!"
183
- @handler_status_lbl.textColor = "red"
184
-
185
- return false if file.nil?
186
- return false unless File.exist? file
187
- begin
188
- source = File.read(file)
189
- #puts source
190
- result = eval(source)
191
- if result.respond_to? :call
192
- @handler = result
193
- @handler_status_lbl.text = "Handler ready!"
194
- @handler_status_lbl.textColor = "green"
195
- end
196
- return true
197
-
198
- rescue SyntaxError, LocalJumpError, NameError => e
199
- out = e.to_s
200
- out << e.backtrace.join("\n")
201
- rescue => bang
202
- out = bang
203
- out << bang.backtrace.join("\n")
204
- end
205
- puts out
206
- return false
207
- end
208
-
209
- def call_handler(object)
210
- begin
211
- result = @handler.call(object)
212
- return result
213
- rescue => bang
214
- result = bang.to_s
215
- result << bang.backtrace.join("\n")
216
- return result
217
- end
218
-
219
- end
220
245
 
221
246
  def gotoNextMatch()
222
247
  @cur_match_pos += 1 if @cur_match_pos < @simple_text_view.numMatches-1
@@ -187,7 +187,7 @@ module Watobo#:nodoc: all
187
187
  class DefineScopeFrame < FXVerticalFrame
188
188
 
189
189
  def onDeselectAll(sender, sel, item)
190
- @scope.each do |site, val|
190
+ @cb_sites.each_key do |site|
191
191
  @cb_sites[site].setCheck(false)
192
192
  @edit_btns[site].disable
193
193
  end
@@ -198,7 +198,7 @@ module Watobo#:nodoc: all
198
198
 
199
199
  def onSelectAll(sender, sel, item)
200
200
  sites = []
201
- @scope.each do |site, scope|
201
+ @cb_sites.each_key do |site|
202
202
  @cb_sites[site].setCheck(true)
203
203
  @edit_btns[site].enable
204
204
  end
@@ -266,6 +266,17 @@ EOF
266
266
  #btn.font = @font
267
267
  #btn.backColor = FXColor::White
268
268
  btn.justify = JUSTIFY_LEFT
269
+
270
+ quickFilterFrame = FXHorizontalFrame.new(self, LAYOUT_FILL_X)
271
+ FXLabel.new(quickFilterFrame, "Filter:", nil, :opts => LAYOUT_TOP|JUSTIFY_RIGHT)
272
+ filter_regexp = FXTextField.new(quickFilterFrame, 25, nil, 0, :opts => TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_LEFT)
273
+ filter_btn = FXButton.new(quickFilterFrame, "apply")
274
+
275
+ filter_regexp.connect(SEL_COMMAND){ list_sites(filter_regexp.text.strip) }
276
+ filter_btn.connect(SEL_COMMAND){ list_sites(filter_regexp.text.strip) }
277
+
278
+
279
+
269
280
  quickSelectFrame = FXHorizontalFrame.new(self, LAYOUT_FILL_X)
270
281
  @sel_all_btn = FXButton.new(quickSelectFrame, "Select All", nil, nil, 0, FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X)
271
282
  @sel_all_btn.connect(SEL_COMMAND, method(:onSelectAll))
@@ -275,18 +286,41 @@ EOF
275
286
 
276
287
  @desel_all_btn = FXButton.new(quickSelectFrame, "Deselect All", nil, nil, 0, FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X)
277
288
  @desel_all_btn.connect(SEL_COMMAND, method(:onDeselectAll))
278
- frame = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_GROOVE, :padding => 0)
289
+ frame = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_GROOVE, :padding => 0)
290
+
279
291
  sitesArea = FXScrollWindow.new(frame, SCROLLERS_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_Y)
280
- sitesFrame = FXVerticalFrame.new(sitesArea, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0)
281
- puts "list sites"
292
+ @sitesFrame = FXVerticalFrame.new(sitesArea, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0)
293
+
294
+ list_sites
295
+
296
+ updateFrame()
297
+ end
298
+
299
+ private
300
+
301
+ def list_sites(p='.*')
302
+ @cb_sites.clear
303
+ @edit_btns.clear
304
+ # clear container
305
+ @sitesFrame.each_child do |c|
306
+ @sitesFrame.removeChild c
307
+ end
308
+ @sitesFrame.recalc
309
+ @sitesFrame.update
310
+
311
+ pattern = p
312
+ pattern = '.*' if p.nil? or p.empty?
313
+
282
314
  sites = Watobo::Chats.sites()
283
- puts sites.length
315
+ sites.compact!
316
+
284
317
  sites.sort.each do |site|
285
- puts site
286
- site_frame = FXHorizontalFrame.new(sitesFrame, :opts => LAYOUT_FILL_X)
318
+ next unless site =~ /#{pattern}/
319
+ site_frame = FXHorizontalFrame.new(@sitesFrame, :opts => LAYOUT_FILL_X)
287
320
  b = FXCheckButton.new(site_frame, site, nil, 0, ICON_BEFORE_TEXT|LAYOUT_SIDE_LEFT)
288
321
  eb = FXButton.new(site_frame, "edit..", nil, nil, 0, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT)
289
322
  @edit_btns[site] = eb
323
+ site_frame.create if self.parent.created?
290
324
 
291
325
  b.connect(SEL_COMMAND){
292
326
  b.checked? ? @edit_btns[site].enable : @edit_btns[site].disable
@@ -316,11 +350,11 @@ EOF
316
350
  }
317
351
 
318
352
  end
319
- updateFrame()
353
+ @sitesFrame.recalc
354
+ @sitesFrame.update
320
355
  end
321
356
 
322
357
 
323
-
324
358
  end #EOC
325
359
  #--
326
360
  end