watobo 0.9.9.pre3 → 0.9.9
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.
- data/.yardopts +24 -0
- data/CHANGELOG +17 -7
- data/README +4 -60
- data/bin/nfq_server.rb +191 -0
- data/config/interceptor.yml +2 -6
- data/lib/watobo/adapters/data_store.rb +1 -1
- data/lib/watobo/adapters/file/file_store.rb +50 -33
- data/lib/watobo/ca.rb +22 -0
- data/lib/watobo/config.rb +6 -0
- data/lib/watobo/core/ca.rb +411 -0
- data/lib/watobo/core/cert_store.rb +56 -0
- data/lib/watobo/core/forwarding_proxy.rb +38 -0
- data/lib/watobo/core/http_socket.rb +18 -0
- data/lib/watobo/core/intercept_carver.rb +179 -0
- data/lib/watobo/core/intercept_filter.rb +257 -0
- data/lib/watobo/core/interceptor.rb +342 -79
- data/lib/watobo/core/netfilter_queue.rb +191 -0
- data/lib/watobo/core/project.rb +84 -138
- data/lib/watobo/core/proxy.rb +61 -0
- data/lib/watobo/core/request.rb +40 -0
- data/lib/watobo/core/response.rb +30 -0
- data/lib/watobo/core/scanner.rb +64 -58
- data/lib/watobo/core/session.rb +70 -77
- data/lib/watobo/core.rb +1 -1
- data/lib/watobo/framework/create_project.rb +25 -10
- data/lib/watobo/framework/init.rb +13 -0
- data/lib/watobo/gui/browser_preview.rb +5 -4
- data/lib/watobo/gui/checks_policy_frame.rb +1 -0
- data/lib/watobo/gui/client_cert_dialog.rb +11 -6
- data/lib/watobo/gui/conversation_table.rb +7 -4
- data/lib/watobo/gui/fuzzer_gui.rb +9 -11
- data/lib/watobo/gui/intercept_filter_dialog.rb +210 -0
- data/lib/watobo/gui/interceptor_gui.rb +59 -21
- data/lib/watobo/gui/interceptor_settings_dialog.rb +39 -5
- data/lib/watobo/gui/list_box.rb +2 -1
- data/lib/watobo/gui/log_viewer.rb +79 -5
- data/lib/watobo/gui/main_window.rb +159 -113
- data/lib/watobo/gui/manual_request_editor.rb +11 -5
- data/lib/watobo/gui/mixins/subscriber.rb +47 -0
- data/lib/watobo/gui/project_wizzard.rb +3 -3
- data/lib/watobo/gui/proxy_dialog.rb +17 -18
- data/lib/watobo/gui/request_editor.rb +1 -1
- data/lib/watobo/gui/rewrite_filters_dialog.rb +416 -0
- data/lib/watobo/gui/rewrite_rules_dialog.rb +394 -0
- data/lib/watobo/gui/scanner_settings_dialog.rb +9 -6
- data/lib/watobo/gui/session_management_dialog.rb +33 -23
- data/lib/watobo/gui/sites_tree.rb +5 -6
- data/lib/watobo/gui/status_bar.rb +101 -49
- data/lib/watobo/gui/table_editor.rb +1 -1
- data/lib/watobo/gui/templates/plugin2.rb +23 -27
- data/lib/watobo/gui/utils/save_default_settings.rb +9 -9
- data/lib/watobo/gui/utils/save_proxy_settings.rb +25 -9
- data/lib/watobo/gui/utils/save_scanner_settings.rb +10 -7
- data/lib/watobo/gui/utils/session_history.rb +1 -1
- data/lib/watobo/gui/www_auth_dialog.rb +25 -21
- data/lib/watobo/gui.rb +3 -1
- data/lib/watobo/mixins/httpparser.rb +47 -40
- data/lib/watobo/mixins/request_parser.rb +126 -41
- data/lib/watobo/mixins/shapers.rb +124 -15
- data/lib/watobo/utils/hexprint.rb +31 -0
- data/lib/watobo/utils/load_chat.rb +2 -0
- data/lib/watobo/utils/response_builder.rb +111 -0
- data/lib/watobo.rb +4 -1
- data/modules/active/discovery/http_methods.rb +6 -4
- data/modules/active/fileinclusion/lfi_simple.rb +3 -3
- data/modules/active/sqlinjection/sqli_timing.rb +6 -6
- data/modules/passive/redirectionz.rb +5 -6
- data/plugins/catalog/catalog.rb +240 -56
- data/plugins/catalog/db_tests +1 -6483
- data/plugins/catalog/db_variables +2 -29
- data/plugins/crawler/gui/auth_frame.rb +15 -3
- data/plugins/crawler/gui/crawler_gui.rb +24 -0
- data/plugins/crawler/gui/hooks_frame.rb +7 -2
- data/plugins/crawler/gui/settings_tabbook.rb +4 -0
- data/plugins/crawler/gui.rb +3 -3
- data/plugins/crawler/lib/engine.rb +1 -1
- data/plugins/filefinder/filefinder.rb +21 -17
- data/plugins/sqlmap/bin/test.rb +100 -0
- data/plugins/sqlmap/gui/main.rb +227 -0
- data/plugins/sqlmap/gui/options_frame.rb +119 -0
- data/plugins/sqlmap/gui.rb +27 -0
- data/plugins/sqlmap/icons/sqlmap.ico +0 -0
- data/plugins/sqlmap/lib/sqlmap_ctrl.rb +116 -0
- data/plugins/sqlmap/sqlmap.rb +26 -0
- data/plugins/sslchecker/gui/gui.rb +45 -30
- metadata +32 -9
- data/certificates/cert.pem +0 -19
- data/certificates/privkey.pem +0 -15
- data/certificates/watobo_dh.key +0 -5
- data/lib/watobo/core/simple_ca.rb +0 -393
|
@@ -996,12 +996,10 @@ module Watobo
|
|
|
996
996
|
scan_prefs[:check_online] = false
|
|
997
997
|
# check if logging all scan chat
|
|
998
998
|
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
end
|
|
1004
|
-
|
|
999
|
+
if @logScanChats.checked?
|
|
1000
|
+
scan_prefs[:scanlog_name] = @log_dir_dt.value unless @log_dir_dt.value.empty?
|
|
1001
|
+
end
|
|
1002
|
+
|
|
1005
1003
|
@scanner = Watobo::Scanner2.new(chat_list, check_list, @project.passive_checks, scan_prefs)
|
|
1006
1004
|
@pbar.total = @scanner.numTotalChecks
|
|
1007
1005
|
@pbar.progress = 0
|
|
@@ -1136,29 +1134,29 @@ puts "run scanner"
|
|
|
1136
1134
|
if @logScanChats.checked? then
|
|
1137
1135
|
@log_dir_text.enabled = true
|
|
1138
1136
|
@log_dir_label.enabled = true
|
|
1139
|
-
|
|
1137
|
+
# @log_dir_btn.enable
|
|
1140
1138
|
else
|
|
1141
1139
|
@log_dir_text.enabled = false
|
|
1142
1140
|
@log_dir_label.enabled = false
|
|
1143
|
-
|
|
1141
|
+
# @log_dir_btn.disable
|
|
1144
1142
|
end
|
|
1145
1143
|
end
|
|
1146
1144
|
|
|
1147
1145
|
|
|
1148
1146
|
@log_dir_dt = FXDataTarget.new('')
|
|
1149
1147
|
# @log_dir_dt.value = @project.scanLogDirectory() if File.exist?(@project.scanLogDirectory())
|
|
1150
|
-
@log_dir_label = FXLabel.new(opt, "Scan
|
|
1148
|
+
@log_dir_label = FXLabel.new(opt, "Scan Name:" )
|
|
1151
1149
|
scanlog_frame = FXHorizontalFrame.new(opt,:opts => LAYOUT_FILL_X|LAYOUT_SIDE_TOP)
|
|
1152
1150
|
@log_dir_text = FXTextField.new(scanlog_frame, 20,
|
|
1153
1151
|
:target => @log_dir_dt, :selector => FXDataTarget::ID_VALUE,
|
|
1154
1152
|
:opts => TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN)
|
|
1155
1153
|
@log_dir_text.handle(self, FXSEL(SEL_UPDATE, 0), nil)
|
|
1156
|
-
|
|
1154
|
+
# @log_dir_btn = FXButton.new(scanlog_frame, "Change")
|
|
1157
1155
|
# @log_dir_btn.connect(SEL_COMMAND, method(:selectLogDirectory))
|
|
1158
1156
|
|
|
1159
1157
|
@log_dir_text.enabled = false
|
|
1160
1158
|
@log_dir_label.enabled = false
|
|
1161
|
-
|
|
1159
|
+
#@log_dir_btn.disable
|
|
1162
1160
|
|
|
1163
1161
|
|
|
1164
1162
|
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# .
|
|
2
|
+
# intercept_filter_dialog.rb
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2012 by siberas, http://www.siberas.de
|
|
5
|
+
#
|
|
6
|
+
# This file is part of WATOBO (Web Application Tool Box)
|
|
7
|
+
# http://watobo.sourceforge.com
|
|
8
|
+
#
|
|
9
|
+
# WATOBO is free software; you can redistribute it and/or modify
|
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
|
11
|
+
# the Free Software Foundation version 2 of the License.
|
|
12
|
+
#
|
|
13
|
+
# WATOBO is distributed in the hope that it will be useful,
|
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
+
# GNU General Public License for more details.
|
|
17
|
+
#
|
|
18
|
+
# You should have received a copy of the GNU General Public License
|
|
19
|
+
# along with WATOBO; if not, write to the Free Software
|
|
20
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
21
|
+
# .
|
|
22
|
+
module Watobo
|
|
23
|
+
module Gui
|
|
24
|
+
class InterceptFilterDialog < FXDialogBox
|
|
25
|
+
|
|
26
|
+
include Responder
|
|
27
|
+
def getRequestFilter()
|
|
28
|
+
@request_filter
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def getResponseFilter()
|
|
32
|
+
@response_filter
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def initialize(owner, settings = {} )
|
|
36
|
+
super(owner, "Rewrite Settings", DECOR_ALL, :width => 300, :height => 425)
|
|
37
|
+
|
|
38
|
+
@request_filter = { }
|
|
39
|
+
|
|
40
|
+
@response_filter = { }
|
|
41
|
+
|
|
42
|
+
@request_filter.update settings[:request_filter_settings]
|
|
43
|
+
@response_filter.update settings[:response_filter_settings]
|
|
44
|
+
|
|
45
|
+
FXMAPFUNC(SEL_COMMAND, ID_ACCEPT, :onAccept)
|
|
46
|
+
|
|
47
|
+
base_frame = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0)
|
|
48
|
+
@tabbook = FXTabBook.new(base_frame, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_RIGHT)
|
|
49
|
+
buttons_frame = FXHorizontalFrame.new(base_frame, :opts => LAYOUT_FILL_X)
|
|
50
|
+
@req_opt_tab = FXTabItem.new(@tabbook, "Request Options", nil)
|
|
51
|
+
frame = FXVerticalFrame.new(@tabbook, :opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
52
|
+
scroll_window = FXScrollWindow.new(frame, SCROLLERS_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
53
|
+
@req_opt_frame = FXVerticalFrame.new(scroll_window, :opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
54
|
+
|
|
55
|
+
@resp_opt_tab = FXTabItem.new(@tabbook, "Response Options", nil)
|
|
56
|
+
frame= FXVerticalFrame.new(@tabbook, :opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
57
|
+
scroll_window = FXScrollWindow.new(frame, SCROLLERS_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
58
|
+
@resp_opt_frame = FXVerticalFrame.new(scroll_window, :opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
59
|
+
|
|
60
|
+
initRequestFilterFrame()
|
|
61
|
+
updateRequestFilterFrame()
|
|
62
|
+
|
|
63
|
+
initResponseFilterFrame()
|
|
64
|
+
updateResponseFilterFrame()
|
|
65
|
+
|
|
66
|
+
@finishButton = FXButton.new(buttons_frame, "Accept" , nil, nil, :opts => BUTTON_NORMAL|LAYOUT_RIGHT)
|
|
67
|
+
@finishButton.enable
|
|
68
|
+
@finishButton.connect(SEL_COMMAND) do |sender, sel, item|
|
|
69
|
+
#self.handle(self, FXSEL(SEL_COMMAND, ID_CANCEL), nil)
|
|
70
|
+
self.handle(self, FXSEL(SEL_COMMAND, ID_ACCEPT), nil)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
@cancelButton = FXButton.new(buttons_frame, "Cancel" ,
|
|
74
|
+
:target => self, :selector => FXDialogBox::ID_CANCEL,
|
|
75
|
+
:opts => BUTTON_NORMAL|LAYOUT_RIGHT)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def onAccept(sender, sel, event)
|
|
81
|
+
#TODO: Check if regex is valid
|
|
82
|
+
@request_filter[:method_filter] = @method_filter_dt.value
|
|
83
|
+
@request_filter[:negate_method_filter] = @neg_method_filter_cb.checked?
|
|
84
|
+
@request_filter[:negate_url_filter] = @neg_url_filter_cb.checked?
|
|
85
|
+
@request_filter[:url_filter] = @url_filter_dt.value
|
|
86
|
+
@request_filter[:file_type_filter] = @ftype_filter_dt.value
|
|
87
|
+
@request_filter[:negate_file_type_filter] = @neg_ftype_filter_cb.checked?
|
|
88
|
+
|
|
89
|
+
@request_filter[:parms_filter] = @parms_filter_dt.value
|
|
90
|
+
@request_filter[:negate_parms_filter] = @neg_parms_filter_cb.checked?
|
|
91
|
+
|
|
92
|
+
@response_filter[:content_type_filter] = @content_type_filter_dt.value
|
|
93
|
+
@response_filter[:negate_content_type_filter] = @neg_ctype_filter_cb.checked?
|
|
94
|
+
|
|
95
|
+
@response_filter[:response_code_filter] = @rcode_filter_dt.value
|
|
96
|
+
@response_filter[:negate_response_code_filter] = @neg_rcode_filter_cb.checked?
|
|
97
|
+
|
|
98
|
+
getApp().stopModal(self, 1)
|
|
99
|
+
self.hide()
|
|
100
|
+
return 1
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def updateRequestFilterFrame()
|
|
104
|
+
@parms_filter.handle(self, FXSEL(SEL_UPDATE, 0), nil)
|
|
105
|
+
@url_filter.handle(self, FXSEL(SEL_UPDATE, 0), nil)
|
|
106
|
+
@ftype_filter.handle(self, FXSEL(SEL_UPDATE, 0), nil)
|
|
107
|
+
@method_filter.handle(self, FXSEL(SEL_UPDATE, 0), nil)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def updateResponseFilterFrame()
|
|
111
|
+
@content_type_filter.handle(self, FXSEL(SEL_UPDATE, 0), nil)
|
|
112
|
+
@rcode_filter.handle(self, FXSEL(SEL_UPDATE, 0), nil)
|
|
113
|
+
# @neg_rcode_filter_cb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
|
|
114
|
+
# @neg_ctype_filter_cb.handle(self, FXSEL(SEL_UPDATE, 0), nil)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def initResponseFilterFrame()
|
|
118
|
+
|
|
119
|
+
gbframe = FXGroupBox.new(@resp_opt_frame, "Content Type", LAYOUT_SIDE_RIGHT|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
120
|
+
frame = FXVerticalFrame.new(gbframe, :opts => LAYOUT_FILL_X, :padding => 0)
|
|
121
|
+
fxtext = FXText.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_WORDWRAP)
|
|
122
|
+
fxtext.backColor = fxtext.parent.backColor
|
|
123
|
+
fxtext.disable
|
|
124
|
+
text = "Regular expression for HTTP Content-Type. E.g., '(text|script)'"
|
|
125
|
+
fxtext.setText(text)
|
|
126
|
+
@content_type_filter_dt = FXDataTarget.new('')
|
|
127
|
+
@content_type_filter_dt.value = @response_filter[:content_type_filter]
|
|
128
|
+
@content_type_filter = FXTextField.new(frame, 20, :target => @content_type_filter_dt, :selector => FXDataTarget::ID_VALUE, :opts => TEXTFIELD_NORMAL|LAYOUT_SIDE_LEFT|LAYOUT_FILL_X)
|
|
129
|
+
@neg_ctype_filter_cb = FXCheckButton.new(frame, "Negate Filter", nil, 0, JUSTIFY_LEFT|JUSTIFY_TOP|ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
|
|
130
|
+
#@neg_method_filter_cb.checkState = false
|
|
131
|
+
@neg_ctype_filter_cb.checkState = @response_filter[:negate_content_type_filter]
|
|
132
|
+
|
|
133
|
+
gbframe = FXGroupBox.new(@resp_opt_frame, "Response Code", LAYOUT_SIDE_RIGHT|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
134
|
+
frame = FXVerticalFrame.new(gbframe, :opts => LAYOUT_FILL_X, :padding => 0)
|
|
135
|
+
fxtext = FXText.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_WORDWRAP)
|
|
136
|
+
fxtext.backColor = fxtext.parent.backColor
|
|
137
|
+
fxtext.disable
|
|
138
|
+
text = "Regular expression for HTTP Content-Type. E.g., '200'"
|
|
139
|
+
fxtext.setText(text)
|
|
140
|
+
@rcode_filter_dt = FXDataTarget.new('')
|
|
141
|
+
@rcode_filter_dt.value = @response_filter[:response_code_filter]
|
|
142
|
+
|
|
143
|
+
@rcode_filter = FXTextField.new(frame, 20, :target => @rcode_filter_dt, :selector => FXDataTarget::ID_VALUE, :opts => TEXTFIELD_NORMAL|LAYOUT_SIDE_LEFT|LAYOUT_FILL_X)
|
|
144
|
+
@neg_rcode_filter_cb = FXCheckButton.new(frame, "Negate Filter", nil, 0, JUSTIFY_LEFT|JUSTIFY_TOP|ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
|
|
145
|
+
#@neg_method_filter_cb.checkState = false
|
|
146
|
+
@neg_rcode_filter_cb.checkState = @response_filter[:negate_response_code_filter]
|
|
147
|
+
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def initRequestFilterFrame()
|
|
151
|
+
gbframe = FXGroupBox.new(@req_opt_frame, "URL Filter", LAYOUT_SIDE_RIGHT|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
152
|
+
frame = FXVerticalFrame.new(gbframe, :opts => LAYOUT_FILL_X, :padding => 0)
|
|
153
|
+
fxtext = FXText.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_WORDWRAP)
|
|
154
|
+
fxtext.backColor = fxtext.parent.backColor
|
|
155
|
+
fxtext.disable
|
|
156
|
+
text = "Regular Expression Filter For URL. E.g., '.*www.mysite.com.*login.php'"
|
|
157
|
+
fxtext.setText(text)
|
|
158
|
+
|
|
159
|
+
@url_filter_dt = FXDataTarget.new('')
|
|
160
|
+
@url_filter_dt.value = @request_filter[:url_filter]
|
|
161
|
+
@url_filter = FXTextField.new(frame, 20, :target => @url_filter_dt, :selector => FXDataTarget::ID_VALUE, :opts => TEXTFIELD_NORMAL|LAYOUT_SIDE_LEFT|LAYOUT_FILL_X)
|
|
162
|
+
@neg_url_filter_cb = FXCheckButton.new(frame, "Negate Filter", nil, 0, JUSTIFY_LEFT|JUSTIFY_TOP|ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
|
|
163
|
+
#@neg_url_filter_cb.checkState = false
|
|
164
|
+
@neg_url_filter_cb.checkState = @request_filter[:negate_url_filter]
|
|
165
|
+
|
|
166
|
+
gbframe = FXGroupBox.new(@req_opt_frame, "Method Filter", LAYOUT_SIDE_RIGHT|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
167
|
+
frame = FXVerticalFrame.new(gbframe, :opts => LAYOUT_FILL_X, :padding => 0)
|
|
168
|
+
fxtext = FXText.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_WORDWRAP)
|
|
169
|
+
fxtext.backColor = fxtext.parent.backColor
|
|
170
|
+
fxtext.disable
|
|
171
|
+
text = "Regular expression for HTTP method. E.g., '(get|PoSt)'"
|
|
172
|
+
fxtext.setText(text)
|
|
173
|
+
@method_filter_dt = FXDataTarget.new('')
|
|
174
|
+
@method_filter_dt.value = @request_filter[:method_filter]
|
|
175
|
+
@method_filter = FXTextField.new(frame, 20, :target => @method_filter_dt, :selector => FXDataTarget::ID_VALUE, :opts => TEXTFIELD_NORMAL|LAYOUT_SIDE_LEFT|LAYOUT_FILL_X)
|
|
176
|
+
@neg_method_filter_cb = FXCheckButton.new(frame, "Negate Filter", nil, 0, JUSTIFY_LEFT|JUSTIFY_TOP|ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
|
|
177
|
+
#@neg_method_filter_cb.checkState = false
|
|
178
|
+
@neg_method_filter_cb.checkState = @request_filter[:negate_method_filter]
|
|
179
|
+
|
|
180
|
+
gbframe = FXGroupBox.new(@req_opt_frame, "Parm Filter", LAYOUT_SIDE_RIGHT|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
181
|
+
frame = FXVerticalFrame.new(gbframe, :opts => LAYOUT_FILL_X, :padding => 0)
|
|
182
|
+
fxtext = FXText.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_WORDWRAP)
|
|
183
|
+
fxtext.backColor = fxtext.parent.backColor
|
|
184
|
+
fxtext.disable
|
|
185
|
+
text = "Regular Expression Filter For Parameter Names. E.g., for intercepting requests containing parameters beginning with 'act' use the regex pattern '^act.*' (without single quotes)"
|
|
186
|
+
fxtext.setText(text)
|
|
187
|
+
@parms_filter_dt = FXDataTarget.new('')
|
|
188
|
+
@parms_filter_dt.value = @request_filter[:parms_filter]
|
|
189
|
+
@parms_filter = FXTextField.new(frame, 20, :target => @parms_filter_dt, :selector => FXDataTarget::ID_VALUE, :opts => TEXTFIELD_NORMAL|LAYOUT_SIDE_LEFT|LAYOUT_FILL_X)
|
|
190
|
+
@neg_parms_filter_cb = FXCheckButton.new(frame, "Negate Filter", nil, 0, JUSTIFY_LEFT|JUSTIFY_TOP|ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
|
|
191
|
+
#@neg_parm_filter_cb.checkState = false
|
|
192
|
+
@neg_parms_filter_cb.checkState = @request_filter[:negate_parms_filter]
|
|
193
|
+
|
|
194
|
+
gbframe = FXGroupBox.new(@req_opt_frame, "File Type Filter", LAYOUT_SIDE_RIGHT|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
195
|
+
frame = FXVerticalFrame.new(gbframe, :opts => LAYOUT_FILL_X, :padding => 0)
|
|
196
|
+
fxtext = FXText.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_WORDWRAP)
|
|
197
|
+
fxtext.backColor = fxtext.parent.backColor
|
|
198
|
+
fxtext.disable
|
|
199
|
+
text = "Regular expression for file types by its extension. E.g., for intercepting requests where file type is PHP use '^php$' (without single quotes)"
|
|
200
|
+
fxtext.setText(text)
|
|
201
|
+
@ftype_filter_dt = FXDataTarget.new('')
|
|
202
|
+
@ftype_filter_dt.value = @request_filter[:file_type_filter]
|
|
203
|
+
@ftype_filter = FXTextField.new(frame, 20, :target => @ftype_filter_dt, :selector => FXDataTarget::ID_VALUE, :opts => TEXTFIELD_NORMAL|LAYOUT_SIDE_LEFT|LAYOUT_FILL_X)
|
|
204
|
+
@neg_ftype_filter_cb = FXCheckButton.new(frame, "Negate Filter", nil, 0, JUSTIFY_LEFT|JUSTIFY_TOP|ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
|
|
205
|
+
#@neg_parm_filter_cb.checkState = false
|
|
206
|
+
@neg_ftype_filter_cb.checkState = @request_filter[:negate_file_type_filter]
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
@@ -24,6 +24,7 @@ module Watobo
|
|
|
24
24
|
class InterceptEditor < FXVerticalFrame
|
|
25
25
|
|
|
26
26
|
include Watobo::Constants
|
|
27
|
+
include Watobo::Interceptor
|
|
27
28
|
include Watobo::Gui::Utils
|
|
28
29
|
|
|
29
30
|
def initialize(owner, opts)
|
|
@@ -411,6 +412,7 @@ module Watobo
|
|
|
411
412
|
|
|
412
413
|
include Responder
|
|
413
414
|
include Watobo
|
|
415
|
+
include Watobo::Interceptor
|
|
414
416
|
include Watobo::Gui::Icons
|
|
415
417
|
def execute
|
|
416
418
|
create
|
|
@@ -465,13 +467,13 @@ module Watobo
|
|
|
465
467
|
end
|
|
466
468
|
end
|
|
467
469
|
|
|
468
|
-
def initialize(owner,
|
|
470
|
+
def initialize(owner, opts)
|
|
469
471
|
# Invoke base class initialize function first
|
|
470
472
|
|
|
471
473
|
super( owner, 'Interceptor', nil, nil, DECOR_ALL|DECOR_TITLE|DECOR_BORDER|DECOR_RESIZE, 0, 0, 600, 400, 0, 0, 0, 0, 0, 0)
|
|
472
474
|
self.connect(SEL_CLOSE, method(:onClose))
|
|
473
475
|
self.icon = ICON_INTERCEPTOR
|
|
474
|
-
|
|
476
|
+
#@interceptor = interceptor
|
|
475
477
|
|
|
476
478
|
@request_list = []
|
|
477
479
|
@response_list = []
|
|
@@ -491,23 +493,39 @@ module Watobo
|
|
|
491
493
|
#log_frame = FXVerticalFrame.new(mr_splitter, :opts => LAYOUT_FILL_X|LAYOUT_SIDE_BOTTOM,:height => 100)
|
|
492
494
|
|
|
493
495
|
filter_frame = FXVerticalFrame.new(top_splitter, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y||LAYOUT_FIX_HEIGHT|LAYOUT_BOTTOM)
|
|
494
|
-
|
|
495
|
-
|
|
496
|
+
gbframe = FXGroupBox.new(filter_frame, "Intercept", LAYOUT_SIDE_RIGHT|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
497
|
+
frame = FXVerticalFrame.new(gbframe, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0)
|
|
498
|
+
# FXLabel.new(filter_frame, "Intercept:" )
|
|
499
|
+
@intercept_request = FXCheckButton.new(frame, "Requests", nil, 0,
|
|
496
500
|
ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
|
|
497
501
|
@intercept_request.connect(SEL_COMMAND, method(:onInterceptChanged))
|
|
498
502
|
|
|
499
|
-
@intercept_response = FXCheckButton.new(
|
|
503
|
+
@intercept_response = FXCheckButton.new(frame, "Response", nil, 0,
|
|
500
504
|
ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
|
|
501
505
|
@intercept_response.connect(SEL_COMMAND, method(:onInterceptChanged))
|
|
502
|
-
|
|
503
|
-
@filter_options_btn = FXButton.new(filter_frame, "Filter Options", nil, nil, 0, FRAME_RAISED|FRAME_THICK|LAYOUT_LEFT)
|
|
506
|
+
@filter_options_btn = FXButton.new(frame, "Options", nil, nil, 0, FRAME_RAISED|FRAME_THICK|LAYOUT_LEFT)
|
|
504
507
|
@filter_options_btn.connect(SEL_COMMAND, method(:onBtnFilterOptions))
|
|
508
|
+
|
|
509
|
+
gbframe = FXGroupBox.new(filter_frame, "Rewrite", LAYOUT_SIDE_RIGHT|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
510
|
+
frame = FXVerticalFrame.new(gbframe, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0)
|
|
511
|
+
#FXLabel.new(filter_frame, "Rewrite:" )
|
|
512
|
+
@rewrite_request = FXCheckButton.new(frame, "Requests", nil, 0,
|
|
513
|
+
ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
|
|
514
|
+
@rewrite_request.connect(SEL_COMMAND, method(:onInterceptChanged))
|
|
515
|
+
|
|
516
|
+
@rewrite_response = FXCheckButton.new(frame, "Response", nil, 0,
|
|
517
|
+
ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
|
|
518
|
+
@rewrite_response.connect(SEL_COMMAND, method(:onInterceptChanged))
|
|
519
|
+
|
|
520
|
+
@rewrite_options_btn = FXButton.new(frame, "Options", nil, nil, 0, FRAME_RAISED|FRAME_THICK|LAYOUT_LEFT)
|
|
521
|
+
@rewrite_options_btn.connect(SEL_COMMAND){ open_rewrite_options_dialog }
|
|
522
|
+
|
|
505
523
|
#@intercept_request.checkState = false
|
|
506
524
|
#@intercept_response.checkState = false
|
|
507
|
-
|
|
525
|
+
if Watobo::Interceptor.active?
|
|
508
526
|
|
|
509
|
-
@intercept_request.checkState =
|
|
510
|
-
@intercept_response.checkState =
|
|
527
|
+
@intercept_request.checkState = Watobo::Interceptor.intercept_requests?
|
|
528
|
+
@intercept_response.checkState = Watobo::Interceptor.intercept_requests?
|
|
511
529
|
end
|
|
512
530
|
|
|
513
531
|
view_frame = FXVerticalFrame.new(top_splitter, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y||LAYOUT_FIX_HEIGHT|LAYOUT_BOTTOM)
|
|
@@ -702,7 +720,7 @@ end
|
|
|
702
720
|
|
|
703
721
|
# def onHide
|
|
704
722
|
# # puts "* hiding interceptor"
|
|
705
|
-
#
|
|
723
|
+
# Watobo::Interceptor.intercept_mode = INTERCEPT_NONE
|
|
706
724
|
# @mutex.synchronize {
|
|
707
725
|
# @cv.signal
|
|
708
726
|
# }
|
|
@@ -711,7 +729,8 @@ end
|
|
|
711
729
|
def onClose(sender, sel, ptr)
|
|
712
730
|
puts "* closing Interceptor UI"
|
|
713
731
|
puts "+ stop intercepting"
|
|
714
|
-
|
|
732
|
+
Watobo::Interceptor.intercept_mode = INTERCEPT_NONE
|
|
733
|
+
Watobo::Interceptor.rewrite_mode = REWRITE_NONE
|
|
715
734
|
puts "+ release all interceptions"
|
|
716
735
|
releaseAll()
|
|
717
736
|
#getApp().stopModal(self, 1)
|
|
@@ -756,24 +775,41 @@ end
|
|
|
756
775
|
def onBtnFilterOptions(sender, sel, ptr)
|
|
757
776
|
|
|
758
777
|
dlg = Watobo::Gui::InterceptorFilterSettingsDialog.new( self,
|
|
759
|
-
:request_filter_settings =>
|
|
760
|
-
:response_filter_settings =>
|
|
778
|
+
:request_filter_settings => Interceptor.proxy.getRequestFilter(),
|
|
779
|
+
:response_filter_settings => Interceptor.proxy.getResponseFilter()
|
|
761
780
|
)
|
|
762
781
|
if dlg.execute != 0 then
|
|
763
782
|
# TODO: Apply interceptor settings
|
|
764
|
-
|
|
765
|
-
|
|
783
|
+
Interceptor.proxy.setRequestFilter(dlg.getRequestFilter)
|
|
784
|
+
Interceptor.proxy.setResponseFilter(dlg.getResponseFilter)
|
|
766
785
|
end
|
|
767
786
|
|
|
768
787
|
end
|
|
788
|
+
|
|
789
|
+
def open_rewrite_options_dialog
|
|
790
|
+
dlg = Watobo::Gui::RewriteRulesDialog.new( self )
|
|
791
|
+
if dlg.execute != 0 then
|
|
792
|
+
# TODO: Apply interceptor settings
|
|
793
|
+
Interceptor::RequestCarver.set_carving_rules dlg.request_rules
|
|
794
|
+
Interceptor::ResponseCarver.set_carving_rules dlg.response_rules
|
|
795
|
+
end
|
|
796
|
+
end
|
|
769
797
|
|
|
770
798
|
def onInterceptChanged(sender, sel, ptr)
|
|
771
799
|
begin
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
800
|
+
# unless @interceptor.nil? then
|
|
801
|
+
mode = @intercept_response.checked? ? INTERCEPT_RESPONSE : 0
|
|
802
|
+
mode |= @intercept_request.checked? ? INTERCEPT_REQUEST : 0
|
|
803
|
+
#Watobo::Interceptor.intercept_mode = @intercept_response.checked? ? INTERCEPT_RESPONSE : 0
|
|
804
|
+
# Watobo::Interceptor.intercept_mode |= @intercept_request.checked? ? INTERCEPT_REQUEST : 0
|
|
805
|
+
#puts Watobo::Interceptor.intercept_mode
|
|
806
|
+
# puts "New Proxy Mode: #{mode}"
|
|
807
|
+
Watobo::Interceptor.intercept_mode = mode
|
|
808
|
+
|
|
809
|
+
mode = @rewrite_request.checked? ? REWRITE_REQUEST : 0
|
|
810
|
+
mode |= @rewrite_response.checked? ? REWRITE_RESPONSE : 0
|
|
811
|
+
Watobo::Interceptor.rewrite_mode = mode
|
|
812
|
+
# end
|
|
777
813
|
rescue => bang
|
|
778
814
|
puts bang
|
|
779
815
|
puts bang.backtrace if $DEBUG
|
|
@@ -785,6 +821,8 @@ end
|
|
|
785
821
|
class InterceptorFilterSettingsDialog < FXDialogBox
|
|
786
822
|
|
|
787
823
|
include Responder
|
|
824
|
+
include Watobo::Interceptor
|
|
825
|
+
|
|
788
826
|
def getRequestFilter()
|
|
789
827
|
@request_filter
|
|
790
828
|
end
|
|
@@ -23,10 +23,15 @@ module Watobo
|
|
|
23
23
|
module Gui
|
|
24
24
|
|
|
25
25
|
class InterceptorSettingsFrame < FXVerticalFrame
|
|
26
|
+
|
|
26
27
|
|
|
27
28
|
def getSettings()
|
|
28
29
|
settings = Hash.new
|
|
29
30
|
settings[:port] = @port_dt.value
|
|
31
|
+
settings[:bind_addr] = @bind_addr_dt.value
|
|
32
|
+
mode = Watobo::Interceptor::MODE_REGULAR
|
|
33
|
+
mode = Watobo::Interceptor::MODE_TRANSPARENT if @transparent_mode_chk.checked?
|
|
34
|
+
settings[:proxy_mode] = mode
|
|
30
35
|
|
|
31
36
|
|
|
32
37
|
|
|
@@ -42,6 +47,10 @@ module Watobo
|
|
|
42
47
|
return settings
|
|
43
48
|
end
|
|
44
49
|
|
|
50
|
+
def transparent_mode?
|
|
51
|
+
@transparent_mode_chk.checked?
|
|
52
|
+
end
|
|
53
|
+
|
|
45
54
|
def addItem(list_box, item)
|
|
46
55
|
if item != "" then
|
|
47
56
|
list_item = list_box.appendItem("#{item}")
|
|
@@ -63,12 +72,34 @@ module Watobo
|
|
|
63
72
|
#@settings = interceptor_settings
|
|
64
73
|
scroller = FXScrollWindow.new(self, :opts => SCROLLERS_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
65
74
|
scroll_area = FXVerticalFrame.new(scroller, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
75
|
+
gbox = FXGroupBox.new(scroll_area, "Transparent Mode", LAYOUT_SIDE_RIGHT|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
76
|
+
gbox_frame = FXVerticalFrame.new(gbox, :opts => LAYOUT_SIDE_TOP)
|
|
77
|
+
@transparent_mode_chk = FXCheckButton.new(gbox_frame, "enable", nil, 0, ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP|LAYOUT_LEFT)
|
|
78
|
+
@transparent_mode_chk.setCheck false
|
|
79
|
+
if RUBY_PLATFORM =~ /linux|bsd|solaris|hpux|darwin/i
|
|
80
|
+
@transparent_mode_chk.setCheck true if Watobo::Conf::Interceptor.proxy_mode == Watobo::Interceptor::MODE_TRANSPARENT
|
|
81
|
+
else
|
|
82
|
+
@transparent_mode_chk.disable
|
|
83
|
+
note = FXLabel.new(gbox_frame, "Transparent Mode Not Available On This Platform.")
|
|
84
|
+
note.textColor = FXColor::Red
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
gbox = FXGroupBox.new(scroll_area, "Listener", LAYOUT_SIDE_RIGHT|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
89
|
+
#gbox_frame = FXVerticalFrame.new(gbox, :opts => LAYOUT_SIDE_TOP|PACK_UNIFORM_WIDTH)
|
|
90
|
+
frame = FXMatrix.new(gbox, 2, :opts => MATRIX_BY_COLUMNS|LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
91
|
+
|
|
92
|
+
# frame = FXHorizontalFrame.new(gbox_frame, :opts => LAYOUT_FILL_X)
|
|
93
|
+
FXLabel.new(frame, "Bind Address:")
|
|
94
|
+
@bind_addr_dt = FXDataTarget.new(0)
|
|
95
|
+
#@port_dt.value = @settings[:port]
|
|
96
|
+
@bind_addr_dt.value = Watobo::Conf::Interceptor.bind_addr
|
|
97
|
+
bind_addr_txt = FXTextField.new(frame, 15, @bind_addr_dt, FXDataTarget::ID_VALUE, :opts => JUSTIFY_RIGHT|FRAME_GROOVE|FRAME_SUNKEN)
|
|
98
|
+
bind_addr_txt .handle(self, FXSEL(SEL_UPDATE, 0), nil)
|
|
69
99
|
|
|
70
|
-
|
|
71
|
-
|
|
100
|
+
|
|
101
|
+
# frame = FXHorizontalFrame.new(gbox_frame, :opts => LAYOUT_FILL_X)
|
|
102
|
+
FXLabel.new(frame, "Port:")
|
|
72
103
|
@port_dt = FXDataTarget.new(0)
|
|
73
104
|
#@port_dt.value = @settings[:port]
|
|
74
105
|
@port_dt.value = Watobo::Conf::Interceptor.port
|
|
@@ -151,6 +182,9 @@ module Watobo
|
|
|
151
182
|
include Responder
|
|
152
183
|
attr :interceptor_settings
|
|
153
184
|
|
|
185
|
+
def transparent?
|
|
186
|
+
@interceptorSettingsFrame.transparent_mode?
|
|
187
|
+
end
|
|
154
188
|
|
|
155
189
|
def onAccept(sender, sel, event)
|
|
156
190
|
|
data/lib/watobo/gui/list_box.rb
CHANGED
|
@@ -83,7 +83,8 @@ module Watobo
|
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
input_frame = FXHorizontalFrame.new(frame, :opts => LAYOUT_FILL_X)
|
|
86
|
-
|
|
86
|
+
#@text = FXTextField.new(input_frame, 20, :target => @expath_dt, :selector => FXDataTarget::ID_VALUE, :opts => TEXTFIELD_NORMAL|LAYOUT_SIDE_LEFT|LAYOUT_FILL_X)
|
|
87
|
+
@text = FXTextField.new(input_frame, 20, nil, 0, :opts => TEXTFIELD_NORMAL|LAYOUT_SIDE_LEFT|LAYOUT_FILL_X)
|
|
87
88
|
@rem_btn = FXButton.new(input_frame, "Remove" , :opts => BUTTON_NORMAL|BUTTON_DEFAULT|LAYOUT_RIGHT)
|
|
88
89
|
@add_btn = FXButton.new(input_frame, "Add" , :opts => BUTTON_NORMAL|BUTTON_DEFAULT|LAYOUT_RIGHT)
|
|
89
90
|
|
|
@@ -23,10 +23,84 @@ module Watobo
|
|
|
23
23
|
module Gui
|
|
24
24
|
class LogViewer < FXVerticalFrame
|
|
25
25
|
|
|
26
|
+
include Watobo::Constants
|
|
27
|
+
def purge_logs
|
|
28
|
+
begin
|
|
29
|
+
@log_text_lock.synchronize do
|
|
30
|
+
@textbox.setText('')
|
|
31
|
+
# @textbox.makePositionVisible 0
|
|
32
|
+
end
|
|
33
|
+
rescue => bang
|
|
34
|
+
puts "! Could not purge logs"
|
|
35
|
+
puts bang
|
|
36
|
+
puts bang.backtrace if $DEBUG
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def log(log_level, msg )
|
|
41
|
+
|
|
42
|
+
t = Time.now
|
|
43
|
+
now = t.strftime("%m/%d/%Y @ %H:%M:%S")
|
|
44
|
+
|
|
45
|
+
begin
|
|
46
|
+
log_text = case log_level
|
|
47
|
+
when LOG_INFO
|
|
48
|
+
"#{now}: #{msg}\n"
|
|
49
|
+
else
|
|
50
|
+
""
|
|
51
|
+
end
|
|
52
|
+
@log_queue << log_text
|
|
53
|
+
rescue => bang
|
|
54
|
+
puts bang
|
|
55
|
+
puts bang.backtrace if $DEBUG
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def initialize(parent, mode = nil, opts)
|
|
60
|
+
opts[:padding]=0
|
|
61
|
+
@mode = :insert if mode.nil?
|
|
62
|
+
|
|
63
|
+
super(parent, opts)
|
|
64
|
+
|
|
65
|
+
@log_queue = Queue.new
|
|
66
|
+
|
|
67
|
+
@log_text_lock = Mutex.new
|
|
68
|
+
|
|
69
|
+
@textbox = FXText.new(self, nil, 0, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
70
|
+
@textbox.editable = false
|
|
71
|
+
start_update_timer
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def start_update_timer
|
|
77
|
+
@timer = FXApp.instance.addTimeout( 150, :repeat => true) {
|
|
78
|
+
#print @log_queue.length
|
|
79
|
+
if @log_queue.length > 0
|
|
80
|
+
msg = @log_queue.deq
|
|
81
|
+
if @mode == :insert
|
|
82
|
+
@log_text_lock.synchronize do
|
|
83
|
+
@textbox.insertText(0,msg)
|
|
84
|
+
end
|
|
85
|
+
else
|
|
86
|
+
@log_text_lock.synchronize do
|
|
87
|
+
@textbox.appendText(msg)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
@textbox.handle(self, FXSEL(SEL_UPDATE, 0), nil)
|
|
91
|
+
end
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class LogViewer_UNUSED < FXVerticalFrame
|
|
99
|
+
|
|
26
100
|
include Watobo::Constants
|
|
27
101
|
def purge
|
|
28
102
|
@lock.synchronize do
|
|
29
|
-
@
|
|
103
|
+
@textbox.text = ''
|
|
30
104
|
end
|
|
31
105
|
end
|
|
32
106
|
|
|
@@ -65,9 +139,9 @@ module Watobo
|
|
|
65
139
|
unless @log_message.empty?
|
|
66
140
|
case @mode
|
|
67
141
|
when :insert
|
|
68
|
-
@
|
|
142
|
+
@textbox.insertText(0,@log_message)
|
|
69
143
|
when :append
|
|
70
|
-
@
|
|
144
|
+
@textbox.appendText(@log_message)
|
|
71
145
|
end
|
|
72
146
|
end
|
|
73
147
|
@log_message = nil
|
|
@@ -94,8 +168,8 @@ module Watobo
|
|
|
94
168
|
|
|
95
169
|
#self.connect(SEL_CLOSE, method(:onClose))
|
|
96
170
|
|
|
97
|
-
@
|
|
98
|
-
@
|
|
171
|
+
@textbox = FXText.new(self, nil, 0, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
172
|
+
@textbox.editable = false
|
|
99
173
|
start_update_timer
|
|
100
174
|
end
|
|
101
175
|
|