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.
- data/CHANGELOG.md +54 -2
- data/README.md +1 -1
- data/config/scanner.yml +1 -0
- data/custom-views/prettify-json.rb +19 -0
- data/lib/watobo/adapters/file/marshal_store.rb +297 -0
- data/lib/watobo/adapters.rb +2 -1
- data/lib/watobo/core/active_check.rb +4 -0
- data/lib/watobo/core/chat.rb +8 -0
- data/lib/watobo/core/chats.rb +2 -1
- data/lib/watobo/core/cookie.rb +3 -3
- data/lib/watobo/core/finding.rb +7 -0
- data/lib/watobo/core/request.rb +3 -3
- data/lib/watobo/core/session.rb +6 -2
- data/lib/watobo/framework/init_modules.rb +18 -16
- data/lib/watobo/gui/conversation_table.rb +13 -16
- data/lib/watobo/gui/conversation_table_ctrl2.rb +1 -0
- data/lib/watobo/gui/custom_viewer.rb +101 -76
- data/lib/watobo/gui/define_scope_frame.rb +44 -10
- data/lib/watobo/gui/edit_scope_dialog.rb +1 -1
- data/lib/watobo/gui/fuzzer_gui.rb +61 -23
- data/lib/watobo/gui/main_window.rb +1 -1
- data/lib/watobo/gui/scanner_settings_dialog.rb +15 -0
- data/lib/watobo/http/data/json.rb +6 -0
- data/lib/watobo/interceptor/html/favicon.ico +0 -0
- data/lib/watobo/interceptor/html/index.html +13 -0
- data/lib/watobo/interceptor/proxy.rb +70 -18
- data/lib/watobo/mixins/httpparser.rb +26 -16
- data/lib/watobo/mixins/shapers.rb +49 -5
- data/lib/watobo/mixins/transcoders.rb +8 -8
- data/lib/watobo/sockets/connection.rb +1 -1
- data/lib/watobo/utils/load_chat.rb +62 -0
- data/lib/watobo/utils/response_hash.rb +3 -3
- data/lib/watobo.rb +1 -1
- data/modules/active/cq5/cq5_default_selectors.rb +116 -0
- data/modules/active/cq5/cqp_user_enumeration.rb +134 -0
- data/modules/active/struts2/include_params_ognl.rb +1 -1
- data/modules/active/xml/xml_xxe.rb +6 -1
- data/modules/passive/disclosure_domino.rb +1 -1
- data/modules/passive/in_script_parameter.rb +9 -4
- data/plugins/aem/aem.rb +21 -0
- data/plugins/aem/gui/main.rb +128 -0
- data/plugins/aem/gui/tree_view.rb +180 -0
- data/plugins/aem/icons/aem.ico +0 -0
- data/plugins/aem/lib/agent.rb +140 -0
- data/plugins/aem/lib/dispatcher.rb +53 -0
- data/plugins/aem/lib/engine.rb +187 -0
- data/plugins/filefinder/dbs/cq5.db +23 -0
- data/plugins/filefinder/dbs/subs-big.lst +44 -44
- data/plugins/filefinder/filefinder.rb +4 -4
- data/plugins/sqlmap/lib/sqlmap_ctrl.rb +11 -10
- metadata +16 -2
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,55 @@
|
|
|
1
|
+
Version 0.9.21
|
|
2
|
+
===
|
|
3
|
+
|
|
4
|
+
News
|
|
5
|
+
---
|
|
6
|
+
**General**
|
|
7
|
+
|
|
8
|
+
* greatly increased speed of session import by using Marshal serialization instead of YAML for storing chats/findings.
|
|
9
|
+
|
|
10
|
+
**NOTE:** older formats will still work but they will be converted to .mrs files.
|
|
11
|
+
|
|
12
|
+
* added scanner setting 'ignore server errors' which (if enabled) will handle 5xx response codes as 'file does not exist'. It overrules custom error filters.
|
|
13
|
+
* introduced the watobo info page. accessible via http://watobo - where you can download the CA cert as well as some installation information
|
|
14
|
+
* the 'Define Target Scope' dialog now has a text filter
|
|
15
|
+
|
|
16
|
+
**Plugins**
|
|
17
|
+
|
|
18
|
+
* added Adobe Experience Manager Enumeration, crawles the site by using information of AEM/CQ5 json-Extensions
|
|
19
|
+
|
|
20
|
+
**Fuzzer**
|
|
21
|
+
|
|
22
|
+
* results are now saved in yaml format
|
|
23
|
+
|
|
24
|
+
**Modules**
|
|
25
|
+
|
|
26
|
+
* new CQ5 modules for selectors and extensions detection
|
|
27
|
+
* new CQ5 module for userenumeration via json and xml extensions
|
|
28
|
+
|
|
29
|
+
**CustomViewer**
|
|
30
|
+
|
|
31
|
+
* updating view after handler is loaded, no more tab/chat switch necessary
|
|
32
|
+
|
|
33
|
+
Fixes
|
|
34
|
+
---
|
|
35
|
+
**General**
|
|
36
|
+
|
|
37
|
+
* changed encoding in conversation table
|
|
38
|
+
* Response.header_value parsing
|
|
39
|
+
|
|
40
|
+
**Plugins**
|
|
41
|
+
|
|
42
|
+
* [sqlmap] enhanced path detection to also match 'sqlmap' without .py extension
|
|
43
|
+
|
|
44
|
+
**Fuzzer**
|
|
45
|
+
|
|
46
|
+
* multiple fixes in statistics view
|
|
47
|
+
|
|
48
|
+
**ConversationTable**
|
|
49
|
+
|
|
50
|
+
* fixed autoscroll checkbox, no more autoscrolling if unchecked
|
|
51
|
+
* fixed crash on Goto-Function (shift-g shortcut)
|
|
52
|
+
|
|
1
53
|
Version 0.9.20
|
|
2
54
|
===
|
|
3
55
|
|
|
@@ -36,12 +88,12 @@ News
|
|
|
36
88
|
|
|
37
89
|
**SSL-Checker**
|
|
38
90
|
|
|
39
|
-
* optimized ssl checks - but keep in
|
|
91
|
+
* optimized ssl checks - but keep in mind that the number of checked ciphers depends on your ruby version
|
|
40
92
|
|
|
41
93
|
Fixes
|
|
42
94
|
---
|
|
43
95
|
|
|
44
|
-
**
|
|
96
|
+
**General**
|
|
45
97
|
|
|
46
98
|
* post parameter values containing equal signs ('=') will no longer be truncated
|
|
47
99
|
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
WATOBO - THE Web Application Toolbox
|
|
2
2
|
===
|
|
3
|
-
|
|
3
|
+
WATABO is a security tool for testing web applications. It is intended to enable security professionals to perform efficient (semi-automated) web application security audits.
|
|
4
4
|
|
|
5
5
|
Most important features:
|
|
6
6
|
|
data/config/scanner.yml
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#.
|
|
2
|
+
# prettify-json.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
|
+
lambda{|response|
|
|
11
|
+
begin
|
|
12
|
+
jb = JSON.parse(response.body.to_s)
|
|
13
|
+
out = JSON.pretty_generate jb
|
|
14
|
+
rescue => bang
|
|
15
|
+
out = "Could prettify response :(\n\n"
|
|
16
|
+
out << bang.to_s
|
|
17
|
+
end
|
|
18
|
+
out
|
|
19
|
+
}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
#.
|
|
2
|
+
# marshal_store.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
|
+
# @private
|
|
11
|
+
module Watobo#:nodoc: all
|
|
12
|
+
class FileSessionStore < SessionStore
|
|
13
|
+
def num_chats
|
|
14
|
+
get_file_list(@conversation_path, "*-chat*").length
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def num_findings
|
|
18
|
+
get_file_list(@findings_path, "*-finding*").length
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def add_finding(finding)
|
|
22
|
+
return false unless finding.respond_to? :request
|
|
23
|
+
return false unless finding.respond_to? :response
|
|
24
|
+
|
|
25
|
+
finding_file = File.join("#{@findings_path}", "#{finding.id}-finding.mrs")
|
|
26
|
+
unless File.exists?(finding_file)
|
|
27
|
+
save_finding(finding_file, finding)
|
|
28
|
+
return true
|
|
29
|
+
end
|
|
30
|
+
false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def delete_finding(finding)
|
|
34
|
+
finding_file = File.join("#{@findings_path}", "#{finding.id}-finding")
|
|
35
|
+
File.delete finding_file if File.exist? finding_file
|
|
36
|
+
file = finding_file + ".yml"
|
|
37
|
+
File.delete file if File.exist? file
|
|
38
|
+
file = finding_file + ".mrs"
|
|
39
|
+
File.delete file if File.exist? file
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def save_finding(fname, finding)
|
|
44
|
+
File.open(fname, 'wb'){|f|
|
|
45
|
+
f.print Marshal::dump(finding.to_h)
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def update_finding(finding)
|
|
50
|
+
finding_file = File.join("#{@findings_path}", "#{finding.id}-finding.mrs")
|
|
51
|
+
|
|
52
|
+
if File.exists?(finding_file) then
|
|
53
|
+
save_finding(finding_file, finding)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# add_scan_log
|
|
59
|
+
# adds a chat to a specific log store, e.g. if you want to log scan results.
|
|
60
|
+
# needs a scan_name (STRING) as its destination which will be created
|
|
61
|
+
# if the scan name does not exist.
|
|
62
|
+
def add_scan_log(chat, scan_name = nil)
|
|
63
|
+
return false unless chat.respond_to? :request
|
|
64
|
+
return false unless chat.respond_to? :response
|
|
65
|
+
begin
|
|
66
|
+
|
|
67
|
+
return false if scan_name.nil?
|
|
68
|
+
return false if scan_name.empty?
|
|
69
|
+
|
|
70
|
+
scan_name_clean = scan_name.gsub(/[:\\\/\.]*/,"_")
|
|
71
|
+
# puts ">> scan_name"
|
|
72
|
+
path = File.join(@scanlog_path, scan_name_clean)
|
|
73
|
+
|
|
74
|
+
Dir.mkdir path unless File.exist? path
|
|
75
|
+
|
|
76
|
+
file = File.join( path, "log_" + Time.now.to_f.to_s + ".mrs")
|
|
77
|
+
|
|
78
|
+
unless File.exists?(file)
|
|
79
|
+
File.open(file, "wb") { |fh|
|
|
80
|
+
fh.print Marshal::dump(chat.to_h)
|
|
81
|
+
}
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
return true
|
|
85
|
+
rescue => bang
|
|
86
|
+
puts bang
|
|
87
|
+
puts bang.backtrace if $DEBUG
|
|
88
|
+
end
|
|
89
|
+
return false
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def add_chat(chat)
|
|
93
|
+
return false unless chat_valid? chat
|
|
94
|
+
chat_file = File.join("#{@conversation_path}", "#{chat.id}-chat.mrs")
|
|
95
|
+
|
|
96
|
+
unless File.exists?(chat_file)
|
|
97
|
+
File.open(chat_file, "wb") { |fh|
|
|
98
|
+
fh.print Marshal::dump(chat.to_h)
|
|
99
|
+
}
|
|
100
|
+
chat.file = chat_file
|
|
101
|
+
return true
|
|
102
|
+
end
|
|
103
|
+
return false
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def each_chat(&block)
|
|
107
|
+
list = get_file_list(@conversation_path, "*-chat*")
|
|
108
|
+
list.each do |fname|
|
|
109
|
+
#puts
|
|
110
|
+
chat = nil
|
|
111
|
+
if fname =~ /\.mrs$/
|
|
112
|
+
chat = Watobo::Utils.loadChatMarshal(fname)
|
|
113
|
+
elsif fname =~ /\.yml$/
|
|
114
|
+
chat = Watobo::Utils.loadChatYAML(fname) unless list.include?(fname.gsub(/yml$/,'mrs'))
|
|
115
|
+
end
|
|
116
|
+
next if chat.nil?
|
|
117
|
+
yield chat if block_given?
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def each_finding(&block)
|
|
122
|
+
list = get_file_list(@findings_path, "*-finding*")
|
|
123
|
+
list.each do |fname|
|
|
124
|
+
f = nil
|
|
125
|
+
if fname =~ /\.mrs$/
|
|
126
|
+
f = Watobo::Utils.loadFindingMarshal(fname)
|
|
127
|
+
elsif fname =~ /\.yml$/
|
|
128
|
+
f = Watobo::Utils.loadFindingYAML(fname) unless list.include?(fname.gsub(/yml$/,'mrs'))
|
|
129
|
+
end
|
|
130
|
+
next if f.nil?
|
|
131
|
+
yield f if block_given?
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def initialize(project_name, session_name)
|
|
136
|
+
|
|
137
|
+
wsp = Watobo.workspace_path
|
|
138
|
+
return false unless File.exist? wsp
|
|
139
|
+
puts "* using workspace path: #{wsp}" if $DEBUG
|
|
140
|
+
|
|
141
|
+
@log_file = nil
|
|
142
|
+
@log_lock = Mutex.new
|
|
143
|
+
|
|
144
|
+
@project_path = File.join(wsp, project_name)
|
|
145
|
+
unless File.exist? @project_path
|
|
146
|
+
puts "* create project path: #{@project_path}" if $DEBUG
|
|
147
|
+
Dir.mkdir(@project_path)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
@project_config_path = File.join(@project_path, ".config")
|
|
151
|
+
Dir.mkdir @project_config_path unless File.exist? @project_config_path
|
|
152
|
+
|
|
153
|
+
@session_path = File.join(@project_path, session_name)
|
|
154
|
+
|
|
155
|
+
unless File.exist? @session_path
|
|
156
|
+
puts "* create session path: #{@session_path}" if $DEBUG
|
|
157
|
+
Dir.mkdir(@session_path)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
@session_config_path = File.join(@session_path, ".config")
|
|
161
|
+
Dir.mkdir @session_config_path unless File.exist? @session_config_path
|
|
162
|
+
|
|
163
|
+
sext = Watobo::Conf::General.session_settings_file_ext
|
|
164
|
+
|
|
165
|
+
@session_file = File.join(@session_path, session_name + sext)
|
|
166
|
+
@project_file = File.join(@project_path, project_name + Watobo::Conf::General.project_settings_file_ext)
|
|
167
|
+
|
|
168
|
+
@conversation_path = File.expand_path(File.join(@session_path, Watobo::Conf::Datastore.conversations))
|
|
169
|
+
|
|
170
|
+
@findings_path = File.expand_path(File.join(@session_path, Watobo::Conf::Datastore.findings))
|
|
171
|
+
@log_path = File.expand_path(File.join(@session_path, Watobo::Conf::Datastore.event_logs_dir))
|
|
172
|
+
@scanlog_path = File.expand_path(File.join(@session_path, Watobo::Conf::Datastore.scan_logs_dir))
|
|
173
|
+
|
|
174
|
+
[ @conversation_path, @findings_path, @log_path, @scanlog_path ].each do |folder|
|
|
175
|
+
if not File.exists?(folder) then
|
|
176
|
+
puts "create path #{folder}"
|
|
177
|
+
begin
|
|
178
|
+
Dir.mkdir(folder)
|
|
179
|
+
rescue SystemCallError => bang
|
|
180
|
+
puts "!!!ERROR:"
|
|
181
|
+
puts bang
|
|
182
|
+
rescue => bang
|
|
183
|
+
puts "!!!ERROR:"
|
|
184
|
+
puts bang
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
@log_file = File.join(@log_path, session_name + ".log")
|
|
190
|
+
|
|
191
|
+
# @chat_files = get_file_list(@conversation_path, "*-chat")
|
|
192
|
+
# @finding_files = get_file_list(@findings_path, "*-finding")
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def save_session_settings(group, session_settings)
|
|
196
|
+
# puts ">> save_session_settings <<"
|
|
197
|
+
file = Watobo::Utils.snakecase group.gsub(/\.yml/,'')
|
|
198
|
+
file << ".yml"
|
|
199
|
+
|
|
200
|
+
session_file = File.join(@session_config_path, file)
|
|
201
|
+
# puts "Dest.File: #{session_file}"
|
|
202
|
+
# puts session_settings.to_yaml
|
|
203
|
+
# puts "---"
|
|
204
|
+
Watobo::Utils.save_settings(session_file, session_settings)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def load_session_settings(group)
|
|
208
|
+
# puts ">> load_session_settings : #{group}"
|
|
209
|
+
file = Watobo::Utils.snakecase group.gsub(/\.yml/,'')
|
|
210
|
+
file << ".yml"
|
|
211
|
+
|
|
212
|
+
session_file = File.join(@session_config_path, file)
|
|
213
|
+
# puts "File: #{session_file}"
|
|
214
|
+
# puts "---"
|
|
215
|
+
|
|
216
|
+
s = Watobo::Utils.load_settings(session_file)
|
|
217
|
+
s
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def save_project_settings(group, project_settings)
|
|
221
|
+
# puts ">> save_project_settings : #{group}"
|
|
222
|
+
file = Watobo::Utils.snakecase group.gsub(/\.yml/,'')
|
|
223
|
+
file << ".yml"
|
|
224
|
+
|
|
225
|
+
project_file = File.join(@project_config_path, file)
|
|
226
|
+
# puts "Dest.File: #{project_file}"
|
|
227
|
+
# puts project_settings.to_yaml
|
|
228
|
+
# puts "---"
|
|
229
|
+
Watobo::Utils.save_settings(project_file, project_settings)
|
|
230
|
+
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def load_project_settings(group)
|
|
234
|
+
# puts ">> load_project_settings : #{group}"
|
|
235
|
+
file = Watobo::Utils.snakecase group.gsub(/\.yml/,'')
|
|
236
|
+
file << ".yml"
|
|
237
|
+
|
|
238
|
+
project_file = File.join(@project_config_path, file)
|
|
239
|
+
# puts "File: #{project_file}"
|
|
240
|
+
# puts "---"
|
|
241
|
+
|
|
242
|
+
s = Watobo::Utils.load_settings(project_file)
|
|
243
|
+
s
|
|
244
|
+
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def logs
|
|
248
|
+
l = ''
|
|
249
|
+
@log_lock.synchronize do
|
|
250
|
+
l = File.open(@log_file).read
|
|
251
|
+
end
|
|
252
|
+
l
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def logger( message, prefs = {} )
|
|
256
|
+
opts = { :sender => "unknown", :level => Watobo::Constants::LOG_INFO }
|
|
257
|
+
opts.update prefs
|
|
258
|
+
return false if @log_file.nil?
|
|
259
|
+
begin
|
|
260
|
+
t = Time.now
|
|
261
|
+
now = t.strftime("%m/%d/%Y @ %H:%M:%S")
|
|
262
|
+
log_message = [ now ]
|
|
263
|
+
log_message << "#{opts[:sender]}"
|
|
264
|
+
if message.is_a? Array
|
|
265
|
+
log_message << message.join("\n| ")
|
|
266
|
+
log_message << "\n-"
|
|
267
|
+
else
|
|
268
|
+
log_message << message
|
|
269
|
+
end
|
|
270
|
+
@log_lock.synchronize do
|
|
271
|
+
File.open(@log_file,"a") do |lfh|
|
|
272
|
+
lfh.puts log_message.join("|")
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
rescue => bang
|
|
276
|
+
puts bang
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
private
|
|
282
|
+
|
|
283
|
+
def chat_valid?(chat)
|
|
284
|
+
return false unless chat.respond_to? :request
|
|
285
|
+
return false unless chat.respond_to? :response
|
|
286
|
+
true
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def get_file_list(path, pattern)
|
|
290
|
+
fl = Dir["#{path}/#{pattern}"].sort_by{ |x| File.basename(x).sub(/[^0-9]*/,'').to_i }
|
|
291
|
+
|
|
292
|
+
fl
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
end
|
data/lib/watobo/adapters.rb
CHANGED
|
@@ -250,6 +250,10 @@ module Watobo#:nodoc: all
|
|
|
250
250
|
return false if status.empty?
|
|
251
251
|
return true, t_request, t_response if status =~ /^403/
|
|
252
252
|
return false, t_request, t_response if status =~ /^40\d/
|
|
253
|
+
if status =~ /^50\d/
|
|
254
|
+
# puts "* ignore server errors #{Watobo::Conf::Scanner.ignore_server_errors.class}"
|
|
255
|
+
return false, t_request, t_response if Watobo::Conf::Scanner.ignore_server_errors
|
|
256
|
+
end
|
|
253
257
|
|
|
254
258
|
#puts @settings[:custom_error_patterns]
|
|
255
259
|
|
data/lib/watobo/core/chat.rb
CHANGED
data/lib/watobo/core/chats.rb
CHANGED
|
@@ -53,7 +53,8 @@ module Watobo#:nodoc: all
|
|
|
53
53
|
matches = []
|
|
54
54
|
@chats.each do |c|
|
|
55
55
|
if c.request.site == site then
|
|
56
|
-
matches.push c if o[:dir] == c.request.dir
|
|
56
|
+
matches.push c if o[:dir] == c.request.dir
|
|
57
|
+
yield c if block_given?
|
|
57
58
|
end
|
|
58
59
|
return matches if o[:max_count] > 0 and matches.length >= o[:max_count]
|
|
59
60
|
end
|