watobo 0.9.21 → 0.9.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +46 -1
- data/bin/nfq_server.rb +0 -9
- data/bin/watobo_gui.rb +3 -13
- data/custom-views/prettify-json.rb +9 -18
- data/icons/watobo.ico +0 -0
- data/icons/watobo.ico.old +0 -0
- data/lib/watobo.rb +10 -19
- data/lib/watobo/adapters.rb +5 -14
- data/lib/watobo/adapters/data_store.rb +50 -59
- data/lib/watobo/adapters/file/file_store.rb +287 -296
- data/lib/watobo/adapters/file/marshal_store.rb +293 -296
- data/lib/watobo/adapters/session_store.rb +5 -14
- data/lib/watobo/ca.rb +1 -10
- data/lib/watobo/config.rb +197 -206
- data/lib/watobo/constants.rb +0 -9
- data/lib/watobo/core.rb +3 -12
- data/lib/watobo/core/active_check.rb +72 -135
- data/lib/watobo/core/active_checks.rb +49 -58
- data/lib/watobo/core/ca.rb +369 -389
- data/lib/watobo/core/cert_store.rb +34 -43
- data/lib/watobo/core/chat.rb +92 -101
- data/lib/watobo/core/chats.rb +271 -280
- data/lib/watobo/core/client_cert_store.rb +106 -35
- data/lib/watobo/core/conversation.rb +48 -57
- data/lib/watobo/core/cookie.rb +23 -32
- data/lib/watobo/core/egress_handlers.rb +98 -0
- data/lib/watobo/core/finding.rb +66 -75
- data/lib/watobo/core/findings.rb +107 -114
- data/lib/watobo/core/forwarding_proxy.rb +13 -22
- data/lib/watobo/core/fuzz_gen.rb +0 -9
- data/lib/watobo/core/intercept_carver.rb +166 -177
- data/lib/watobo/core/intercept_filter.rb +235 -244
- data/lib/watobo/core/interceptor.rb +98 -107
- data/lib/watobo/core/min_class.rb +4 -13
- data/lib/watobo/core/netfilter_queue.rb +170 -179
- data/lib/watobo/core/ott_cache.rb +132 -141
- data/lib/watobo/core/parameter.rb +43 -52
- data/lib/watobo/core/passive_check.rb +103 -102
- data/lib/watobo/core/passive_checks.rb +48 -57
- data/lib/watobo/core/passive_scanner.rb +54 -55
- data/lib/watobo/core/plugin.rb +11 -20
- data/lib/watobo/core/project.rb +3 -9
- data/lib/watobo/core/proxy.rb +43 -52
- data/lib/watobo/core/request.rb +125 -123
- data/lib/watobo/core/response.rb +44 -53
- data/lib/watobo/core/scanner.rb +0 -9
- data/lib/watobo/core/scanner3.rb +405 -414
- data/lib/watobo/core/scope.rb +83 -92
- data/lib/watobo/core/session.rb +1043 -1026
- data/lib/watobo/core/sid_cache.rb +98 -107
- data/lib/watobo/core/subscriber.rb +25 -34
- data/lib/watobo/defaults.rb +21 -30
- data/lib/watobo/external/diff/lcs.rb +0 -9
- data/lib/watobo/external/diff/lcs/array.rb +0 -9
- data/lib/watobo/external/diff/lcs/block.rb +0 -9
- data/lib/watobo/external/diff/lcs/callbacks.rb +0 -9
- data/lib/watobo/external/diff/lcs/change.rb +0 -9
- data/lib/watobo/external/diff/lcs/hunk.rb +0 -9
- data/lib/watobo/external/diff/lcs/ldiff.rb +0 -9
- data/lib/watobo/external/diff/lcs/string.rb +0 -9
- data/lib/watobo/externals.rb +6 -15
- data/lib/watobo/framework.rb +4 -13
- data/lib/watobo/framework/create_project.rb +60 -69
- data/lib/watobo/framework/init.rb +0 -9
- data/lib/watobo/framework/init_modules.rb +0 -9
- data/lib/watobo/framework/license_text.rb +28 -37
- data/lib/watobo/framework/load_chat.rb +13 -22
- data/lib/watobo/gui.rb +132 -123
- data/lib/watobo/gui/about_watobo.rb +0 -9
- data/lib/watobo/gui/browser_preview.rb +0 -9
- data/lib/watobo/gui/certificate_dialog.rb +0 -9
- data/lib/watobo/gui/chat_diff.rb +0 -9
- data/lib/watobo/gui/chatviewer_frame.rb +73 -72
- data/lib/watobo/gui/checkboxtree.rb +0 -9
- data/lib/watobo/gui/checks_policy_frame.rb +0 -9
- data/lib/watobo/gui/client_cert_dialog.rb +96 -87
- data/lib/watobo/gui/confirm_scan_dialog.rb +0 -9
- data/lib/watobo/gui/conversation_table.rb +158 -164
- data/lib/watobo/gui/conversation_table_ctrl.rb +207 -216
- data/lib/watobo/gui/conversation_table_ctrl2.rb +373 -382
- data/lib/watobo/gui/csrf_token_dialog.rb +0 -9
- data/lib/watobo/gui/custom_viewer.rb +374 -383
- data/lib/watobo/gui/dashboard.rb +296 -303
- data/lib/watobo/gui/define_scope_frame.rb +0 -9
- data/lib/watobo/gui/differ_frame.rb +215 -224
- data/lib/watobo/gui/edit_comment.rb +0 -9
- data/lib/watobo/gui/edit_scope_dialog.rb +0 -9
- data/lib/watobo/gui/export_dialog.rb +104 -113
- data/lib/watobo/gui/finding_info.rb +0 -9
- data/lib/watobo/gui/findings_tree.rb +210 -217
- data/lib/watobo/gui/full_scan_dialog.rb +0 -9
- data/lib/watobo/gui/fuzzer_gui.rb +1295 -1313
- data/lib/watobo/gui/fxsave_thread.rb +14 -0
- data/lib/watobo/gui/goto_url_dialog.rb +70 -79
- data/lib/watobo/gui/hex_viewer.rb +0 -9
- data/lib/watobo/gui/html_viewer.rb +287 -296
- data/lib/watobo/gui/intercept_filter_dialog.rb +188 -197
- data/lib/watobo/gui/interceptor_gui.rb +1041 -1051
- data/lib/watobo/gui/interceptor_settings_dialog.rb +0 -9
- data/lib/watobo/gui/json_viewer.rb +287 -0
- data/lib/watobo/gui/list_box.rb +101 -110
- data/lib/watobo/gui/log_file_viewer.rb +32 -41
- data/lib/watobo/gui/log_viewer.rb +83 -88
- data/lib/watobo/gui/login_wizzard.rb +0 -9
- data/lib/watobo/gui/main_window.rb +587 -618
- data/lib/watobo/gui/manual_request_editor.rb +620 -565
- data/lib/watobo/gui/master_pw_dialog.rb +0 -9
- data/lib/watobo/gui/mixins/gui_settings.rb +29 -38
- data/lib/watobo/gui/page_tree.rb +217 -226
- data/lib/watobo/gui/password_policy_dialog.rb +0 -9
- data/lib/watobo/gui/plugin_board.rb +0 -9
- data/lib/watobo/gui/preferences_dialog.rb +0 -9
- data/lib/watobo/gui/progress_window.rb +17 -27
- data/lib/watobo/gui/project_wizzard.rb +0 -9
- data/lib/watobo/gui/proxy_dialog.rb +1 -10
- data/lib/watobo/gui/quick_scan_dialog.rb +0 -9
- data/lib/watobo/gui/request_builder_frame.rb +102 -111
- data/lib/watobo/gui/request_editor.rb +181 -137
- data/lib/watobo/gui/rewrite_filters_dialog.rb +394 -403
- data/lib/watobo/gui/rewrite_rules_dialog.rb +372 -381
- data/lib/watobo/gui/save_chat_dialog.rb +140 -149
- data/lib/watobo/gui/scanner_settings_dialog.rb +0 -9
- data/lib/watobo/gui/select_chat_dialog.rb +0 -9
- data/lib/watobo/gui/session_management_dialog.rb +0 -9
- data/lib/watobo/gui/sites_tree.rb +0 -9
- data/lib/watobo/gui/status_bar.rb +0 -9
- data/lib/watobo/gui/table_editor.rb +0 -9
- data/lib/watobo/gui/tagless_viewer.rb +0 -9
- data/lib/watobo/gui/templates/plugin.rb +0 -9
- data/lib/watobo/gui/templates/plugin2.rb +92 -100
- data/lib/watobo/gui/templates/plugin_base.rb +144 -153
- data/lib/watobo/gui/text_viewer.rb +0 -9
- data/lib/watobo/gui/transcoder_window.rb +0 -9
- data/lib/watobo/gui/utils/gui_utils.rb +0 -9
- data/lib/watobo/gui/utils/init_icons.rb +86 -95
- data/lib/watobo/gui/utils/load_icons.rb +33 -42
- data/lib/watobo/gui/utils/load_plugins.rb +116 -119
- data/lib/watobo/gui/utils/master_password.rb +68 -77
- data/lib/watobo/gui/utils/save_default_settings.rb +113 -122
- data/lib/watobo/gui/utils/save_project_settings.rb +0 -9
- data/lib/watobo/gui/utils/save_proxy_settings.rb +41 -50
- data/lib/watobo/gui/utils/save_scanner_settings.rb +18 -27
- data/lib/watobo/gui/utils/session_history.rb +112 -121
- data/lib/watobo/gui/workspace_dialog.rb +0 -9
- data/lib/watobo/gui/www_auth_dialog.rb +0 -9
- data/lib/watobo/gui/xml_viewer_frame.rb +0 -9
- data/lib/watobo/http.rb +4 -13
- data/lib/watobo/http/cookies/cookies.rb +26 -35
- data/lib/watobo/http/data/data.rb +45 -54
- data/lib/watobo/http/data/json.rb +47 -55
- data/lib/watobo/http/url/url.rb +38 -47
- data/lib/watobo/http/xml/xml.rb +124 -130
- data/lib/watobo/interceptor.rb +3 -12
- data/lib/watobo/interceptor/proxy.rb +742 -739
- data/lib/watobo/interceptor/transparent.rb +22 -24
- data/lib/watobo/mixins.rb +10 -19
- data/lib/watobo/mixins/check_info.rb +27 -36
- data/lib/watobo/mixins/httpparser.rb +613 -637
- data/lib/watobo/mixins/request_parser.rb +88 -97
- data/lib/watobo/mixins/shapers.rb +515 -529
- data/lib/watobo/mixins/transcoders.rb +3 -11
- data/lib/watobo/parser.rb +1 -10
- data/lib/watobo/parser/html.rb +83 -92
- data/lib/watobo/patch_fxruby_setfocus.rb +26 -0
- data/lib/watobo/sockets.rb +3 -12
- data/lib/watobo/sockets/agent.rb +828 -837
- data/lib/watobo/sockets/client_socket.rb +308 -312
- data/lib/watobo/sockets/connection.rb +401 -410
- data/lib/watobo/sockets/http_socket.rb +11 -13
- data/lib/watobo/sockets/ntlm_auth.rb +129 -138
- data/lib/watobo/utils.rb +10 -19
- data/lib/watobo/utils/check_regex.rb +0 -9
- data/lib/watobo/utils/copy_object.rb +0 -9
- data/lib/watobo/utils/crypto.rb +0 -9
- data/lib/watobo/utils/expand_range.rb +23 -32
- data/lib/watobo/utils/export_xml.rb +97 -106
- data/lib/watobo/utils/file_management.rb +9 -11
- data/lib/watobo/utils/hexprint.rb +9 -18
- data/lib/watobo/utils/load_chat.rb +0 -9
- data/lib/watobo/utils/load_icon.rb +0 -9
- data/lib/watobo/utils/ntlm.rb +866 -875
- data/lib/watobo/utils/print_debug.rb +12 -21
- data/lib/watobo/utils/response_builder.rb +90 -99
- data/lib/watobo/utils/response_hash.rb +0 -9
- data/lib/watobo/utils/secure_eval.rb +0 -9
- data/lib/watobo/utils/strings.rb +10 -19
- data/lib/watobo/utils/text2request.rb +0 -9
- data/lib/watobo/utils/url.rb +23 -32
- data/lib/watobo/utils/utf16.rb +11 -20
- data/modules/active/Apache/mod_status.rb +0 -9
- data/modules/active/Apache/multiview.rb +151 -160
- data/modules/active/Flash/crossdomain.rb +0 -9
- data/modules/active/JWT/jwt_oauth2_none.rb +111 -0
- data/modules/active/cq5/cq5_default_selectors.rb +106 -115
- data/modules/active/cq5/cqp_user_enumeration.rb +125 -134
- data/modules/active/directories/dirwalker.rb +0 -9
- data/modules/active/discovery/fileextensions.rb +0 -9
- data/modules/active/discovery/http_methods.rb +0 -9
- data/modules/active/discovery/jsmapfiles.rb +79 -0
- data/modules/active/domino/domino_db.rb +68 -76
- data/modules/active/dotNET/custom_errors.rb +102 -111
- data/modules/active/dotNET/dotnet_files.rb +90 -99
- data/modules/active/fileinclusion/lfi_simple.rb +0 -9
- data/modules/active/jboss/jboss_basic.rb +0 -9
- data/modules/active/sap/business_objects.rb +51 -60
- data/modules/active/sap/its_commands.rb +0 -9
- data/modules/active/sap/its_service_parameter.rb +0 -9
- data/modules/active/sap/its_services.rb +0 -9
- data/modules/active/sap/its_xss.rb +0 -9
- data/modules/active/shell_shock/shell_shock.rb +139 -148
- data/modules/active/siebel/siebel_apps.rb +160 -169
- data/modules/active/sqlinjection/sql_boolean.rb +0 -9
- data/modules/active/sqlinjection/sql_numerical.rb +198 -0
- data/modules/active/sqlinjection/sqli_error.rb +0 -9
- data/modules/active/sqlinjection/sqli_timing.rb +220 -229
- data/modules/active/struts2/default_handler_ognl.rb +106 -115
- data/modules/active/struts2/include_params_ognl.rb +105 -114
- data/modules/active/xml/xml_xxe.rb +112 -123
- data/modules/active/xss/xss_ng.rb +214 -223
- data/modules/active/xss/xss_simple.rb +0 -9
- data/modules/passive/ajax.rb +68 -77
- data/modules/passive/autocomplete.rb +56 -65
- data/modules/passive/cookie_options.rb +0 -9
- data/modules/passive/cookie_xss.rb +0 -9
- data/modules/passive/detect_code.rb +0 -9
- data/modules/passive/detect_fileupload.rb +0 -9
- data/modules/passive/detect_infrastructure.rb +0 -9
- data/modules/passive/detect_one_time_tokens.rb +0 -9
- data/modules/passive/dirindexing.rb +0 -9
- data/modules/passive/disclosure_domino.rb +55 -64
- data/modules/passive/disclosure_emails.rb +0 -9
- data/modules/passive/disclosure_ipaddr.rb +55 -53
- data/modules/passive/filename_as_parameter.rb +0 -9
- data/modules/passive/form_spotter.rb +0 -9
- data/modules/passive/hidden_fields.rb +50 -59
- data/modules/passive/hotspots.rb +0 -9
- data/modules/passive/in_script_parameter.rb +0 -9
- data/modules/passive/json_web_token.rb +93 -0
- data/modules/passive/multiple_server_headers.rb +0 -9
- data/modules/passive/possible_login.rb +0 -9
- data/modules/passive/redirect_url.rb +0 -9
- data/modules/passive/redirectionz.rb +0 -9
- data/modules/passive/sap-headers.rb +56 -65
- data/modules/passive/xss_dom.rb +0 -9
- data/plugins/aem/aem.rb +11 -20
- data/plugins/aem/gui/main.rb +118 -127
- data/plugins/aem/gui/tree_view.rb +171 -180
- data/plugins/aem/lib/agent.rb +130 -138
- data/plugins/aem/lib/dispatcher.rb +45 -51
- data/plugins/aem/lib/engine.rb +177 -186
- data/plugins/catalog/catalog.rb +345 -355
- data/plugins/crawler/crawler.rb +4 -13
- data/plugins/crawler/gui.rb +5 -14
- data/plugins/crawler/gui/auth_frame.rb +270 -279
- data/plugins/crawler/gui/crawler_gui.rb +271 -276
- data/plugins/crawler/gui/general_settings_frame.rb +96 -105
- data/plugins/crawler/gui/hooks_frame.rb +80 -89
- data/plugins/crawler/gui/scope_frame.rb +50 -59
- data/plugins/crawler/gui/settings_tabbook.rb +38 -47
- data/plugins/crawler/gui/status_frame.rb +59 -68
- data/plugins/crawler/lib/bags.rb +18 -27
- data/plugins/crawler/lib/constants.rb +11 -20
- data/plugins/crawler/lib/engine.rb +488 -497
- data/plugins/crawler/lib/grabber.rb +68 -77
- data/plugins/crawler/lib/status.rb +71 -80
- data/plugins/crawler/lib/uri_mp.rb +12 -21
- data/plugins/filefinder/filefinder.rb +326 -333
- data/plugins/sqlmap/bin/test.rb +78 -87
- data/plugins/sqlmap/gui.rb +4 -13
- data/plugins/sqlmap/gui/main.rb +218 -227
- data/plugins/sqlmap/gui/options_frame.rb +97 -106
- data/plugins/sqlmap/lib/sqlmap_ctrl.rb +90 -100
- data/plugins/sqlmap/sqlmap.rb +2 -11
- data/plugins/sslchecker/cli/sslchecker_cli.rb +0 -9
- data/plugins/sslchecker/gui/cipher_table.rb +246 -254
- data/plugins/sslchecker/gui/gui.rb +258 -264
- data/plugins/sslchecker/gui/sslchecker.rb +4 -13
- data/plugins/sslchecker/lib/check.rb +127 -133
- data/plugins/wshell/gui/main.rb +119 -117
- data/plugins/wshell/lib/core.rb +38 -88
- data/plugins/wshell/wshell.rb +11 -20
- metadata +170 -164
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Watobo
|
|
2
|
+
def self.save_thread(ms=250, &block)
|
|
3
|
+
FXApp.instance.addTimeout(ms, :repeat => true, &block)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def self.save_thread_UNUSED(ms=250, &block)
|
|
7
|
+
Thread.new {
|
|
8
|
+
loop do
|
|
9
|
+
sleep 0.5
|
|
10
|
+
Watobo::Gui.application.runOnUiThread(&block)
|
|
11
|
+
end
|
|
12
|
+
}
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -1,80 +1,71 @@
|
|
|
1
|
-
#.
|
|
2
|
-
# goto_url_dialog.rb
|
|
3
|
-
#.
|
|
4
|
-
# Copyright 2014 by siberas, http://www.siberas.de
|
|
5
|
-
# This file is part of WATOBO (Web Application Tool Box) http://watobo.sourceforge.com
|
|
6
|
-
# WATOBO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License.
|
|
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
|
-
# 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
|
-
|
|
10
1
|
# @private
|
|
11
|
-
module Watobo#:nodoc: all
|
|
12
|
-
module Gui
|
|
13
|
-
class GotoUrlDialog < FXDialogBox
|
|
14
|
-
|
|
15
|
-
include Responder
|
|
16
|
-
|
|
17
|
-
attr :url_pattern
|
|
18
|
-
def initialize(owner, pattern=nil )
|
|
19
|
-
#super(owner, "Edit Target Scope", DECOR_TITLE|DECOR_BORDER, :width => 300, :height => 425)
|
|
20
|
-
super(owner, "Enter URL filter (regex):", DECOR_ALL, :width => 300, :height => 150)
|
|
21
|
-
|
|
22
|
-
FXMAPFUNC(SEL_COMMAND, ID_ACCEPT, :onAccept)
|
|
23
|
-
|
|
24
|
-
base_frame = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
25
|
-
@url_pattern = ""
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@pattern_field = FXTextField.new(base_frame, 40, :target => @pattern, :selector => FXDataTarget::ID_VALUE, :opts => TEXTFIELD_NORMAL|LAYOUT_SIDE_LEFT)
|
|
29
|
-
@pattern_field.setText(pattern) unless pattern.nil?
|
|
30
|
-
@pattern_field.setFocus()
|
|
31
|
-
@pattern_field.setDefault()
|
|
32
|
-
|
|
33
|
-
@pattern_field.connect(SEL_KEYPRESS) { |sender, sel, event|
|
|
34
|
-
if event.code == KEY_Tab
|
|
35
|
-
@finishButton.setFocus()
|
|
36
|
-
@finishButton.setDefault()
|
|
37
|
-
true
|
|
38
|
-
else
|
|
39
|
-
false
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
buttons_frame = FXHorizontalFrame.new(base_frame,
|
|
44
|
-
:opts => LAYOUT_FILL_X|LAYOUT_SIDE_TOP)
|
|
45
|
-
|
|
46
|
-
@finishButton = FXButton.new(buttons_frame, "Accept" , nil, nil, :opts => BUTTON_NORMAL|LAYOUT_RIGHT)
|
|
47
|
-
@finishButton.enable
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
@finishButton.connect(SEL_COMMAND) do |sender, sel, item|
|
|
51
|
-
#self.handle(self, FXSEL(SEL_COMMAND, ID_CANCEL), nil)
|
|
52
|
-
self.handle(self, FXSEL(SEL_COMMAND, ID_ACCEPT), nil)
|
|
53
|
-
true
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
@cancelButton = FXButton.new(buttons_frame, "Cancel" ,
|
|
57
|
-
:target => self, :selector => FXDialogBox::ID_CANCEL,
|
|
58
|
-
:opts => BUTTON_NORMAL|LAYOUT_RIGHT)
|
|
59
|
-
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
private
|
|
63
|
-
|
|
64
|
-
def onAccept(sender, sel, event)
|
|
65
|
-
begin
|
|
66
|
-
@url_pattern = @pattern_field.text
|
|
67
|
-
"regex_test".match(/#{@url_pattern}/)
|
|
68
|
-
rescue
|
|
69
|
-
@url_pattern = Regexp.quote @pattern_field.text
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Watobo::Scope.set @defineScopeFrame.getScope()
|
|
73
|
-
|
|
74
|
-
getApp().stopModal(self, 1)
|
|
75
|
-
self.hide()
|
|
76
|
-
return 0
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
2
|
+
module Watobo#:nodoc: all
|
|
3
|
+
module Gui
|
|
4
|
+
class GotoUrlDialog < FXDialogBox
|
|
5
|
+
|
|
6
|
+
include Responder
|
|
7
|
+
|
|
8
|
+
attr :url_pattern
|
|
9
|
+
def initialize(owner, pattern=nil )
|
|
10
|
+
#super(owner, "Edit Target Scope", DECOR_TITLE|DECOR_BORDER, :width => 300, :height => 425)
|
|
11
|
+
super(owner, "Enter URL filter (regex):", DECOR_ALL, :width => 300, :height => 150)
|
|
12
|
+
|
|
13
|
+
FXMAPFUNC(SEL_COMMAND, ID_ACCEPT, :onAccept)
|
|
14
|
+
|
|
15
|
+
base_frame = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
16
|
+
@url_pattern = ""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pattern_field = FXTextField.new(base_frame, 40, :target => @pattern, :selector => FXDataTarget::ID_VALUE, :opts => TEXTFIELD_NORMAL|LAYOUT_SIDE_LEFT)
|
|
20
|
+
@pattern_field.setText(pattern) unless pattern.nil?
|
|
21
|
+
@pattern_field.setFocus()
|
|
22
|
+
@pattern_field.setDefault()
|
|
23
|
+
|
|
24
|
+
@pattern_field.connect(SEL_KEYPRESS) { |sender, sel, event|
|
|
25
|
+
if event.code == KEY_Tab
|
|
26
|
+
@finishButton.setFocus()
|
|
27
|
+
@finishButton.setDefault()
|
|
28
|
+
true
|
|
29
|
+
else
|
|
30
|
+
false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
buttons_frame = FXHorizontalFrame.new(base_frame,
|
|
35
|
+
:opts => LAYOUT_FILL_X|LAYOUT_SIDE_TOP)
|
|
36
|
+
|
|
37
|
+
@finishButton = FXButton.new(buttons_frame, "Accept" , nil, nil, :opts => BUTTON_NORMAL|LAYOUT_RIGHT)
|
|
38
|
+
@finishButton.enable
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@finishButton.connect(SEL_COMMAND) do |sender, sel, item|
|
|
42
|
+
#self.handle(self, FXSEL(SEL_COMMAND, ID_CANCEL), nil)
|
|
43
|
+
self.handle(self, FXSEL(SEL_COMMAND, ID_ACCEPT), nil)
|
|
44
|
+
true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
@cancelButton = FXButton.new(buttons_frame, "Cancel" ,
|
|
48
|
+
:target => self, :selector => FXDialogBox::ID_CANCEL,
|
|
49
|
+
:opts => BUTTON_NORMAL|LAYOUT_RIGHT)
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def onAccept(sender, sel, event)
|
|
56
|
+
begin
|
|
57
|
+
@url_pattern = @pattern_field.text
|
|
58
|
+
"regex_test".match(/#{@url_pattern}/)
|
|
59
|
+
rescue
|
|
60
|
+
@url_pattern = Regexp.quote @pattern_field.text
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Watobo::Scope.set @defineScopeFrame.getScope()
|
|
64
|
+
|
|
65
|
+
getApp().stopModal(self, 1)
|
|
66
|
+
self.hide()
|
|
67
|
+
return 0
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
#.
|
|
2
|
-
# hex_viewer.rb
|
|
3
|
-
#.
|
|
4
|
-
# Copyright 2014 by siberas, http://www.siberas.de
|
|
5
|
-
# This file is part of WATOBO (Web Application Tool Box) http://watobo.sourceforge.com
|
|
6
|
-
# WATOBO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License.
|
|
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
|
-
# 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
|
-
|
|
10
1
|
# @private
|
|
11
2
|
module Watobo#:nodoc: all
|
|
12
3
|
module Gui
|
|
@@ -1,297 +1,288 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
#.
|
|
4
|
-
# Copyright 2014 by siberas, http://www.siberas.de
|
|
5
|
-
# This file is part of WATOBO (Web Application Tool Box) http://watobo.sourceforge.com
|
|
6
|
-
# WATOBO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License.
|
|
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
|
-
# 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
|
-
|
|
10
|
-
require 'fox16/scintilla'
|
|
11
|
-
|
|
1
|
+
require 'fox16/scintilla'
|
|
2
|
+
|
|
12
3
|
# @private
|
|
13
|
-
module Watobo#:nodoc: all
|
|
14
|
-
module Gui
|
|
15
|
-
class HTMLViewer < FXScintilla
|
|
16
|
-
attr_accessor :max_len
|
|
17
|
-
|
|
18
|
-
def search_text(text, &block)
|
|
19
|
-
matches = []
|
|
20
|
-
setTargetStart 0
|
|
21
|
-
setTargetEnd getLength
|
|
22
|
-
while searchInTarget(text.length, text) >= 0
|
|
23
|
-
pos = getTargetStart
|
|
24
|
-
setTargetStart pos+1
|
|
25
|
-
setTargetEnd getLength
|
|
26
|
-
yield pos if block_given?
|
|
27
|
-
matches << pos
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
matches
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def initialize(owner, opts)
|
|
35
|
-
super(owner, nil, 0, opts)
|
|
36
|
-
self.setLexer FXScintilla::SCLEX_HTML
|
|
37
|
-
self.setCodePage(FXScintilla::SC_CP_UTF8)
|
|
38
|
-
self.styleSetFont(FXScintilla::STYLE_DEFAULT, "fixed")
|
|
39
|
-
self.styleSetSize(FXScintilla::STYLE_DEFAULT, 9)
|
|
40
|
-
self.styleClearAll
|
|
41
|
-
self.styleSetFore(FXScintilla::SCE_P_DEFAULT, FXRGB(0x80, 0x80, 0x80) & 0xffffff)
|
|
42
|
-
self.styleSetFore(FXScintilla::SCE_P_COMMENTLINE, FXRGB(0x00, 0x7f, 0x00) & 0xffffff)
|
|
43
|
-
self.styleSetFore(FXScintilla::SCE_P_NUMBER, FXRGB(0x00, 0x7f, 0x7f) & 0xffffff)
|
|
44
|
-
self.styleSetFore(FXScintilla::SCE_P_STRING, FXRGB(0x7f, 0x00, 0x7f) & 0xffffff)
|
|
45
|
-
self.styleSetFore(FXScintilla::SCE_P_CHARACTER, FXRGB(0x7f, 0x00, 0x7f) & 0xffffff)
|
|
46
|
-
self.styleSetFore(FXScintilla::SCE_P_WORD, FXRGB(0x00, 0x00, 0x7f) & 0xffffff)
|
|
47
|
-
self.styleSetBold(FXScintilla::SCE_P_WORD, true)
|
|
48
|
-
self.styleSetFore(FXScintilla::SCE_P_TRIPLE, FXRGB(0x7f, 0x00, 0x00) & 0xffffff)
|
|
49
|
-
self.styleSetFore(FXScintilla::SCE_P_TRIPLEDOUBLE, FXRGB(0x7f, 0x00, 0x00) & 0xffffff)
|
|
50
|
-
self.styleSetFore(FXScintilla::SCE_P_CLASSNAME, FXRGB(0x00, 0x00, 0xff) & 0xffffff)
|
|
51
|
-
self.styleSetBold(FXScintilla::SCE_P_CLASSNAME, true)
|
|
52
|
-
self.styleSetFore(FXScintilla::SCE_P_DEFNAME, FXRGB(0x00, 0x7f, 0x7f) & 0xffffff)
|
|
53
|
-
self.styleSetBold(FXScintilla::SCE_P_DEFNAME, true)
|
|
54
|
-
self.styleSetBold(FXScintilla::SCE_P_OPERATOR, true)
|
|
55
|
-
self.styleSetFore(FXScintilla::SCE_P_IDENTIFIER, FXRGB(0x7f, 0x7f, 0x7f) & 0xffffff)
|
|
56
|
-
self.styleSetFore(FXScintilla::SCE_P_COMMENTBLOCK, FXRGB(0x7f, 0x7f, 0x7f) & 0xffffff)
|
|
57
|
-
self.styleSetFore(FXScintilla::SCE_P_STRINGEOL, FXRGB(0x00, 0x00, 0x00) & 0xffffff)
|
|
58
|
-
self.styleSetBack(FXScintilla::SCE_P_STRINGEOL, FXRGB(0xe0, 0xc0, 0xe0) & 0xffffff)
|
|
59
|
-
self.styleSetEOLFilled(FXScintilla::SCE_P_STRINGEOL, true)
|
|
60
|
-
self.styleSetFore(34, FXRGB(0x00, 0x00, 0xff) & 0xffffff)
|
|
61
|
-
self.styleSetBold(34, true)
|
|
62
|
-
self.styleSetFore(35, FXRGB(0xff, 0x00, 0x00) & 0xffffff)
|
|
63
|
-
self.styleSetBold(35, true)
|
|
64
|
-
@max_len = 0
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
class HTMLViewerFrame < FXVerticalFrame
|
|
69
|
-
|
|
70
|
-
attr_accessor :max_len
|
|
71
|
-
|
|
72
|
-
def setText(text, prefs={})
|
|
73
|
-
|
|
74
|
-
normalized_text = "- empty -"
|
|
75
|
-
if text.is_a? String
|
|
76
|
-
normalized_text = text.gsub(/[^[:print:]]/,".")
|
|
77
|
-
elsif text.respond_to? :has_body?
|
|
78
|
-
unless text.body.nil? or text.body.empty?
|
|
79
|
-
body = text.body.strip
|
|
80
|
-
if text.content_type =~ /(html|xml)/
|
|
81
|
-
doc = Nokogiri::XML(body, &:noblanks)
|
|
82
|
-
fbody = doc.to_xhtml( indent:3, indent_text:" ")
|
|
83
|
-
normalized_text = fbody.to_s
|
|
84
|
-
else
|
|
85
|
-
normalized_text = body
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
elsif text.is_a? Array
|
|
89
|
-
normalized_text = text.join
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
@text = normalized_text
|
|
93
|
-
|
|
94
|
-
# puts normalized_text
|
|
95
|
-
@html_viewer.setText(@text)
|
|
96
|
-
#@html_viewer.encodedFromUTF8(normalized_text)
|
|
97
|
-
|
|
98
|
-
@match_pos_label.text = "0/0"
|
|
99
|
-
@match_pos_label.textColor = 'grey'
|
|
100
|
-
|
|
101
|
-
@html_viewer.setTargetStart 0
|
|
102
|
-
@html_viewer.setTargetEnd @html_viewer.getLength
|
|
103
|
-
|
|
104
|
-
applyFilter() if @auto_apply_cbtn.checked?
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def highlight(pattern)
|
|
108
|
-
highlightPattern(pattern)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def getText
|
|
112
|
-
@html_viewer.to_s
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def initialize(owner, opts)
|
|
116
|
-
super(owner, opts)
|
|
117
|
-
|
|
118
|
-
@text_matches = []
|
|
119
|
-
|
|
120
|
-
@style = 2 # default style
|
|
121
|
-
@text = ''
|
|
122
|
-
@max_len = 5000
|
|
123
|
-
@filter_mode = SEL_TYPE_HIGHLIGHT
|
|
124
|
-
@match_pos = 0
|
|
125
|
-
|
|
126
|
-
text_view_header = FXHorizontalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_SIDE_BOTTOM|LAYOUT_FIX_HEIGHT,:height => 24, :padding => 0)
|
|
127
|
-
|
|
128
|
-
#@auto_apply_cbtn.connect(SEL_COMMAND, method(:onInterceptChanged))
|
|
129
|
-
|
|
130
|
-
pmatch_btn = FXButton.new(text_view_header, "<", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y)
|
|
131
|
-
@match_pos_label = FXLabel.new(text_view_header, "0/0", :opts => LAYOUT_FILL_Y)
|
|
132
|
-
@match_pos_label.textColor = 'grey'
|
|
133
|
-
pmatch_btn.connect(SEL_COMMAND) { gotoPrevMatch() }
|
|
134
|
-
nmatch_btn = FXButton.new(text_view_header, ">", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y)
|
|
135
|
-
nmatch_btn.connect(SEL_COMMAND) { gotoNextMatch() }
|
|
136
|
-
|
|
137
|
-
# @filter_text = FXTextField.new(text_view_header, 10,
|
|
138
|
-
# :target => @filter_dt, :selector => FXDataTarget::ID_VALUE,
|
|
139
|
-
# :opts => FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
140
|
-
|
|
141
|
-
@filter_text = FXComboBox.new(text_view_header, 20, nil, 0, FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
|
|
142
|
-
@filter_text.connect(SEL_COMMAND){
|
|
143
|
-
applyFilter()
|
|
144
|
-
addFilterHistory()
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
@filter_text.connect(SEL_CHANGED) {
|
|
148
|
-
applyFilter()
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
@auto_apply_cbtn = FXCheckButton.new(text_view_header, "auto-apply", nil, 0, ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP|LAYOUT_RIGHT|LAYOUT_FILL_Y)
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
text_box_frame = FXVerticalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding => 0)
|
|
155
|
-
|
|
156
|
-
@html_viewer = HTMLViewer.new(text_box_frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
157
|
-
#searchflags = FXScintilla::SCFIND_WHOLEWORD|FXScintilla::SCFIND_MATCHCASE|FXScintilla::SCFIND_REGEXP|FXScintilla::SCFIND_WORDSTART
|
|
158
|
-
@searchflags = FXScintilla::SCFIND_REGEXP
|
|
159
|
-
@html_viewer.setSearchFlags @searchflags
|
|
160
|
-
|
|
161
|
-
addHotkeyHandler(@html_viewer)
|
|
162
|
-
addHotkeyHandler(@filter_text)
|
|
163
|
-
|
|
164
|
-
# @filter_dt.connect(SEL_COMMAND) { applyFilter() }
|
|
165
|
-
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
def applyFilter
|
|
169
|
-
pattern = @filter_text.text
|
|
170
|
-
return if pattern.empty?
|
|
171
|
-
|
|
172
|
-
@match_pos_label.text = "0/0"
|
|
173
|
-
@match_pos_label.textColor = 'grey'
|
|
174
|
-
|
|
175
|
-
@text_matches = @html_viewer.search_text(pattern)
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if @text_matches.length > 0
|
|
179
|
-
@match_pos_label.textColor = 'black'
|
|
180
|
-
@match_pos_label.text = "1/#{@text_matches.length}"
|
|
181
|
-
|
|
182
|
-
show_match_pos(0)
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
private
|
|
188
|
-
|
|
189
|
-
def show_match_pos(match_pos=nil)
|
|
190
|
-
|
|
191
|
-
pos = match_pos.nil? ? 0 : match_pos
|
|
192
|
-
return false if @text_matches.empty?
|
|
193
|
-
return false if pos > @text_matches.length-1
|
|
194
|
-
@match_pos = pos
|
|
195
|
-
pattern = @filter_text.text
|
|
196
|
-
text_pos = @text_matches[pos]
|
|
197
|
-
@html_viewer.gotoPos text_pos
|
|
198
|
-
@html_viewer.setSel text_pos, text_pos+pattern.length
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
def show_next
|
|
202
|
-
if @match_pos < @text_matches.length-1
|
|
203
|
-
@match_pos += 1
|
|
204
|
-
show_match_pos @match_pos
|
|
205
|
-
return true
|
|
206
|
-
end
|
|
207
|
-
return false
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
def show_prev
|
|
211
|
-
if @match_pos > 0
|
|
212
|
-
@match_pos -= 1
|
|
213
|
-
show_match_pos @match_pos
|
|
214
|
-
return true
|
|
215
|
-
end
|
|
216
|
-
return false
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
def addFilterHistory()
|
|
221
|
-
text = @filter_text.text
|
|
222
|
-
return true if text == ''
|
|
223
|
-
has_item = false
|
|
224
|
-
@filter_text.each do |item, data|
|
|
225
|
-
has_item = true if data == text
|
|
226
|
-
end
|
|
227
|
-
@filter_text.appendItem(text, text) unless has_item == true
|
|
228
|
-
@filter_text.numVisible = @filter_text.numItems
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
def resetFilter
|
|
232
|
-
@match_pos_label.text = "0/0"
|
|
233
|
-
@match_pos_label.textColor = 'grey'
|
|
234
|
-
@filter_text.text = ''
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
def addHotkeyHandler(widget)
|
|
238
|
-
@ctrl_pressed = false
|
|
239
|
-
|
|
240
|
-
widget.connect(SEL_KEYPRESS) { |sender, sel, event|
|
|
241
|
-
state = false
|
|
242
|
-
@ctrl_pressed = true if event.code == KEY_Control_L or event.code == KEY_Control_R
|
|
243
|
-
# @shift_pressed = true if @ctrl_pressed and ( event.code == KEY_Shift_L or event.code == KEY_Shift_R )
|
|
244
|
-
if event.code == KEY_Return
|
|
245
|
-
highlight(@filter_text.text)
|
|
246
|
-
state = true # special handling of KEY_Return, because we don't want a linebreak in textbox.
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
if event.code == KEY_F1
|
|
250
|
-
|
|
251
|
-
unless event.moved?
|
|
252
|
-
FXMenuPane.new(self) do |menu_pane|
|
|
253
|
-
FXMenuCaption.new(menu_pane, "Hotkeys:")
|
|
254
|
-
FXMenuSeparator.new(menu_pane)
|
|
255
|
-
[ "<ctrl-r> - Reset Filter",
|
|
256
|
-
"<ctrl-n> - Goto Next",
|
|
257
|
-
"<ctrl-shift-n> - Goto Prev"
|
|
258
|
-
].each do |hk|
|
|
259
|
-
FXMenuCaption.new(menu_pane, hk).backColor = 'yellow'
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
menu_pane.create
|
|
263
|
-
menu_pane.popup(nil, event.root_x, event.root_y)
|
|
264
|
-
app.runModalWhileShown(menu_pane)
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
end
|
|
268
|
-
end
|
|
269
|
-
|
|
270
|
-
if @ctrl_pressed
|
|
271
|
-
case event.code
|
|
272
|
-
when KEY_n
|
|
273
|
-
if show_next
|
|
274
|
-
@match_pos_label.text = "#{@match_pos+1}/#{@text_matches.length}"
|
|
275
|
-
end
|
|
276
|
-
when KEY_N
|
|
277
|
-
if show_prev
|
|
278
|
-
@match_pos_label.text = "#{@match_pos+1}/#{@text_matches.length}"
|
|
279
|
-
end
|
|
280
|
-
when KEY_r
|
|
281
|
-
resetFilter()
|
|
282
|
-
|
|
283
|
-
end
|
|
284
|
-
end
|
|
285
|
-
state
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
widget.connect(SEL_KEYRELEASE) { |sender, sel, event|
|
|
289
|
-
@ctrl_pressed = false if event.code == KEY_Control_L or event.code == KEY_Control_R
|
|
290
|
-
false
|
|
291
|
-
}
|
|
292
|
-
end
|
|
293
|
-
|
|
294
|
-
end
|
|
295
|
-
end
|
|
296
|
-
end
|
|
297
|
-
|
|
4
|
+
module Watobo#:nodoc: all
|
|
5
|
+
module Gui
|
|
6
|
+
class HTMLViewer < FXScintilla
|
|
7
|
+
attr_accessor :max_len
|
|
8
|
+
|
|
9
|
+
def search_text(text, &block)
|
|
10
|
+
matches = []
|
|
11
|
+
setTargetStart 0
|
|
12
|
+
setTargetEnd getLength
|
|
13
|
+
while searchInTarget(text.length, text) >= 0
|
|
14
|
+
pos = getTargetStart
|
|
15
|
+
setTargetStart pos+1
|
|
16
|
+
setTargetEnd getLength
|
|
17
|
+
yield pos if block_given?
|
|
18
|
+
matches << pos
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
matches
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def initialize(owner, opts)
|
|
26
|
+
super(owner, nil, 0, opts)
|
|
27
|
+
self.setLexer FXScintilla::SCLEX_HTML
|
|
28
|
+
self.setCodePage(FXScintilla::SC_CP_UTF8)
|
|
29
|
+
self.styleSetFont(FXScintilla::STYLE_DEFAULT, "fixed")
|
|
30
|
+
self.styleSetSize(FXScintilla::STYLE_DEFAULT, 9)
|
|
31
|
+
self.styleClearAll
|
|
32
|
+
self.styleSetFore(FXScintilla::SCE_P_DEFAULT, FXRGB(0x80, 0x80, 0x80) & 0xffffff)
|
|
33
|
+
self.styleSetFore(FXScintilla::SCE_P_COMMENTLINE, FXRGB(0x00, 0x7f, 0x00) & 0xffffff)
|
|
34
|
+
self.styleSetFore(FXScintilla::SCE_P_NUMBER, FXRGB(0x00, 0x7f, 0x7f) & 0xffffff)
|
|
35
|
+
self.styleSetFore(FXScintilla::SCE_P_STRING, FXRGB(0x7f, 0x00, 0x7f) & 0xffffff)
|
|
36
|
+
self.styleSetFore(FXScintilla::SCE_P_CHARACTER, FXRGB(0x7f, 0x00, 0x7f) & 0xffffff)
|
|
37
|
+
self.styleSetFore(FXScintilla::SCE_P_WORD, FXRGB(0x00, 0x00, 0x7f) & 0xffffff)
|
|
38
|
+
self.styleSetBold(FXScintilla::SCE_P_WORD, true)
|
|
39
|
+
self.styleSetFore(FXScintilla::SCE_P_TRIPLE, FXRGB(0x7f, 0x00, 0x00) & 0xffffff)
|
|
40
|
+
self.styleSetFore(FXScintilla::SCE_P_TRIPLEDOUBLE, FXRGB(0x7f, 0x00, 0x00) & 0xffffff)
|
|
41
|
+
self.styleSetFore(FXScintilla::SCE_P_CLASSNAME, FXRGB(0x00, 0x00, 0xff) & 0xffffff)
|
|
42
|
+
self.styleSetBold(FXScintilla::SCE_P_CLASSNAME, true)
|
|
43
|
+
self.styleSetFore(FXScintilla::SCE_P_DEFNAME, FXRGB(0x00, 0x7f, 0x7f) & 0xffffff)
|
|
44
|
+
self.styleSetBold(FXScintilla::SCE_P_DEFNAME, true)
|
|
45
|
+
self.styleSetBold(FXScintilla::SCE_P_OPERATOR, true)
|
|
46
|
+
self.styleSetFore(FXScintilla::SCE_P_IDENTIFIER, FXRGB(0x7f, 0x7f, 0x7f) & 0xffffff)
|
|
47
|
+
self.styleSetFore(FXScintilla::SCE_P_COMMENTBLOCK, FXRGB(0x7f, 0x7f, 0x7f) & 0xffffff)
|
|
48
|
+
self.styleSetFore(FXScintilla::SCE_P_STRINGEOL, FXRGB(0x00, 0x00, 0x00) & 0xffffff)
|
|
49
|
+
self.styleSetBack(FXScintilla::SCE_P_STRINGEOL, FXRGB(0xe0, 0xc0, 0xe0) & 0xffffff)
|
|
50
|
+
self.styleSetEOLFilled(FXScintilla::SCE_P_STRINGEOL, true)
|
|
51
|
+
self.styleSetFore(34, FXRGB(0x00, 0x00, 0xff) & 0xffffff)
|
|
52
|
+
self.styleSetBold(34, true)
|
|
53
|
+
self.styleSetFore(35, FXRGB(0xff, 0x00, 0x00) & 0xffffff)
|
|
54
|
+
self.styleSetBold(35, true)
|
|
55
|
+
@max_len = 0
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class HTMLViewerFrame < FXVerticalFrame
|
|
60
|
+
|
|
61
|
+
attr_accessor :max_len
|
|
62
|
+
|
|
63
|
+
def setText(text, prefs={})
|
|
64
|
+
|
|
65
|
+
normalized_text = "- empty -"
|
|
66
|
+
if text.is_a? String
|
|
67
|
+
normalized_text = text.gsub(/[^[:print:]]/,".")
|
|
68
|
+
elsif text.respond_to? :has_body?
|
|
69
|
+
unless text.body.nil? or text.body.empty?
|
|
70
|
+
body = text.body.strip
|
|
71
|
+
if text.content_type =~ /(html|xml)/
|
|
72
|
+
doc = Nokogiri::XML(body, &:noblanks)
|
|
73
|
+
fbody = doc.to_xhtml( indent:3, indent_text:" ")
|
|
74
|
+
normalized_text = fbody.to_s
|
|
75
|
+
else
|
|
76
|
+
normalized_text = body
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
elsif text.is_a? Array
|
|
80
|
+
normalized_text = text.join
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
@text = normalized_text
|
|
84
|
+
|
|
85
|
+
# puts normalized_text
|
|
86
|
+
@html_viewer.setText(@text)
|
|
87
|
+
#@html_viewer.encodedFromUTF8(normalized_text)
|
|
88
|
+
|
|
89
|
+
@match_pos_label.text = "0/0"
|
|
90
|
+
@match_pos_label.textColor = 'grey'
|
|
91
|
+
|
|
92
|
+
@html_viewer.setTargetStart 0
|
|
93
|
+
@html_viewer.setTargetEnd @html_viewer.getLength
|
|
94
|
+
|
|
95
|
+
applyFilter() if @auto_apply_cbtn.checked?
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def highlight(pattern)
|
|
99
|
+
highlightPattern(pattern)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def getText
|
|
103
|
+
@html_viewer.to_s
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def initialize(owner, opts)
|
|
107
|
+
super(owner, opts)
|
|
108
|
+
|
|
109
|
+
@text_matches = []
|
|
110
|
+
|
|
111
|
+
@style = 2 # default style
|
|
112
|
+
@text = ''
|
|
113
|
+
@max_len = 5000
|
|
114
|
+
@filter_mode = SEL_TYPE_HIGHLIGHT
|
|
115
|
+
@match_pos = 0
|
|
116
|
+
|
|
117
|
+
text_view_header = FXHorizontalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_SIDE_BOTTOM|LAYOUT_FIX_HEIGHT,:height => 24, :padding => 0)
|
|
118
|
+
|
|
119
|
+
#@auto_apply_cbtn.connect(SEL_COMMAND, method(:onInterceptChanged))
|
|
120
|
+
|
|
121
|
+
pmatch_btn = FXButton.new(text_view_header, "<", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y)
|
|
122
|
+
@match_pos_label = FXLabel.new(text_view_header, "0/0", :opts => LAYOUT_FILL_Y)
|
|
123
|
+
@match_pos_label.textColor = 'grey'
|
|
124
|
+
pmatch_btn.connect(SEL_COMMAND) { gotoPrevMatch() }
|
|
125
|
+
nmatch_btn = FXButton.new(text_view_header, ">", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y)
|
|
126
|
+
nmatch_btn.connect(SEL_COMMAND) { gotoNextMatch() }
|
|
127
|
+
|
|
128
|
+
# @filter_text = FXTextField.new(text_view_header, 10,
|
|
129
|
+
# :target => @filter_dt, :selector => FXDataTarget::ID_VALUE,
|
|
130
|
+
# :opts => FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
131
|
+
|
|
132
|
+
@filter_text = FXComboBox.new(text_view_header, 20, nil, 0, FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
|
|
133
|
+
@filter_text.connect(SEL_COMMAND){
|
|
134
|
+
applyFilter()
|
|
135
|
+
addFilterHistory()
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@filter_text.connect(SEL_CHANGED) {
|
|
139
|
+
applyFilter()
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@auto_apply_cbtn = FXCheckButton.new(text_view_header, "auto-apply", nil, 0, ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP|LAYOUT_RIGHT|LAYOUT_FILL_Y)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
text_box_frame = FXVerticalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding => 0)
|
|
146
|
+
|
|
147
|
+
@html_viewer = HTMLViewer.new(text_box_frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
148
|
+
#searchflags = FXScintilla::SCFIND_WHOLEWORD|FXScintilla::SCFIND_MATCHCASE|FXScintilla::SCFIND_REGEXP|FXScintilla::SCFIND_WORDSTART
|
|
149
|
+
@searchflags = FXScintilla::SCFIND_REGEXP
|
|
150
|
+
@html_viewer.setSearchFlags @searchflags
|
|
151
|
+
|
|
152
|
+
addHotkeyHandler(@html_viewer)
|
|
153
|
+
addHotkeyHandler(@filter_text)
|
|
154
|
+
|
|
155
|
+
# @filter_dt.connect(SEL_COMMAND) { applyFilter() }
|
|
156
|
+
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def applyFilter
|
|
160
|
+
pattern = @filter_text.text
|
|
161
|
+
return if pattern.empty?
|
|
162
|
+
|
|
163
|
+
@match_pos_label.text = "0/0"
|
|
164
|
+
@match_pos_label.textColor = 'grey'
|
|
165
|
+
|
|
166
|
+
@text_matches = @html_viewer.search_text(pattern)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
if @text_matches.length > 0
|
|
170
|
+
@match_pos_label.textColor = 'black'
|
|
171
|
+
@match_pos_label.text = "1/#{@text_matches.length}"
|
|
172
|
+
|
|
173
|
+
show_match_pos(0)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
private
|
|
179
|
+
|
|
180
|
+
def show_match_pos(match_pos=nil)
|
|
181
|
+
|
|
182
|
+
pos = match_pos.nil? ? 0 : match_pos
|
|
183
|
+
return false if @text_matches.empty?
|
|
184
|
+
return false if pos > @text_matches.length-1
|
|
185
|
+
@match_pos = pos
|
|
186
|
+
pattern = @filter_text.text
|
|
187
|
+
text_pos = @text_matches[pos]
|
|
188
|
+
@html_viewer.gotoPos text_pos
|
|
189
|
+
@html_viewer.setSel text_pos, text_pos+pattern.length
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def show_next
|
|
193
|
+
if @match_pos < @text_matches.length-1
|
|
194
|
+
@match_pos += 1
|
|
195
|
+
show_match_pos @match_pos
|
|
196
|
+
return true
|
|
197
|
+
end
|
|
198
|
+
return false
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def show_prev
|
|
202
|
+
if @match_pos > 0
|
|
203
|
+
@match_pos -= 1
|
|
204
|
+
show_match_pos @match_pos
|
|
205
|
+
return true
|
|
206
|
+
end
|
|
207
|
+
return false
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def addFilterHistory()
|
|
212
|
+
text = @filter_text.text
|
|
213
|
+
return true if text == ''
|
|
214
|
+
has_item = false
|
|
215
|
+
@filter_text.each do |item, data|
|
|
216
|
+
has_item = true if data == text
|
|
217
|
+
end
|
|
218
|
+
@filter_text.appendItem(text, text) unless has_item == true
|
|
219
|
+
@filter_text.numVisible = @filter_text.numItems
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def resetFilter
|
|
223
|
+
@match_pos_label.text = "0/0"
|
|
224
|
+
@match_pos_label.textColor = 'grey'
|
|
225
|
+
@filter_text.text = ''
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def addHotkeyHandler(widget)
|
|
229
|
+
@ctrl_pressed = false
|
|
230
|
+
|
|
231
|
+
widget.connect(SEL_KEYPRESS) { |sender, sel, event|
|
|
232
|
+
state = false
|
|
233
|
+
@ctrl_pressed = true if event.code == KEY_Control_L or event.code == KEY_Control_R
|
|
234
|
+
# @shift_pressed = true if @ctrl_pressed and ( event.code == KEY_Shift_L or event.code == KEY_Shift_R )
|
|
235
|
+
if event.code == KEY_Return
|
|
236
|
+
highlight(@filter_text.text)
|
|
237
|
+
state = true # special handling of KEY_Return, because we don't want a linebreak in textbox.
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
if event.code == KEY_F1
|
|
241
|
+
|
|
242
|
+
unless event.moved?
|
|
243
|
+
FXMenuPane.new(self) do |menu_pane|
|
|
244
|
+
FXMenuCaption.new(menu_pane, "Hotkeys:")
|
|
245
|
+
FXMenuSeparator.new(menu_pane)
|
|
246
|
+
[ "<ctrl-r> - Reset Filter",
|
|
247
|
+
"<ctrl-n> - Goto Next",
|
|
248
|
+
"<ctrl-shift-n> - Goto Prev"
|
|
249
|
+
].each do |hk|
|
|
250
|
+
FXMenuCaption.new(menu_pane, hk).backColor = 'yellow'
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
menu_pane.create
|
|
254
|
+
menu_pane.popup(nil, event.root_x, event.root_y)
|
|
255
|
+
app.runModalWhileShown(menu_pane)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
if @ctrl_pressed
|
|
262
|
+
case event.code
|
|
263
|
+
when KEY_n
|
|
264
|
+
if show_next
|
|
265
|
+
@match_pos_label.text = "#{@match_pos+1}/#{@text_matches.length}"
|
|
266
|
+
end
|
|
267
|
+
when KEY_N
|
|
268
|
+
if show_prev
|
|
269
|
+
@match_pos_label.text = "#{@match_pos+1}/#{@text_matches.length}"
|
|
270
|
+
end
|
|
271
|
+
when KEY_r
|
|
272
|
+
resetFilter()
|
|
273
|
+
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
state
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
widget.connect(SEL_KEYRELEASE) { |sender, sel, event|
|
|
280
|
+
@ctrl_pressed = false if event.code == KEY_Control_L or event.code == KEY_Control_R
|
|
281
|
+
false
|
|
282
|
+
}
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|