watobo 0.9.13 → 0.9.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -19,7 +19,7 @@
19
19
  # along with WATOBO; if not, write to the Free Software
20
20
  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
21
  # .
22
- # @private
22
+ # @private
23
23
  module Watobo#:nodoc: all
24
24
  module Interceptor
25
25
  #
@@ -31,17 +31,16 @@ module Watobo#:nodoc: all
31
31
 
32
32
  attr_accessor :proxy_mode
33
33
 
34
- attr_accessor :contentLength
35
- attr_accessor :contentTypes
34
+ # attr_accessor :contentLength
35
+ #attr_accessor :contentTypes
36
36
  attr_accessor :target
37
- attr :www_auth
37
+ #attr :www_auth
38
38
  attr_accessor :client_certificates
39
-
40
39
  def self.transparent?
41
40
  return true if ( Watobo::Conf::Interceptor.proxy_mode & Watobo::Interceptor::MODE_TRANSPARENT ) > 0
42
41
  return false
43
42
  end
44
-
43
+
45
44
  def server
46
45
  @bind_addr
47
46
  end
@@ -91,7 +90,7 @@ module Watobo#:nodoc: all
91
90
  puts "[#{self.class}] stop"
92
91
  if @t_server.respond_to? :status
93
92
  puts @t_server.status
94
- Thread.kill @t_server
93
+ Thread.kill @t_server
95
94
  @intercept_srv.close
96
95
  end
97
96
  rescue IOError => bang
@@ -111,6 +110,7 @@ module Watobo#:nodoc: all
111
110
  end
112
111
 
113
112
  def start()
113
+ @wait_queue = Queue.new
114
114
 
115
115
  if transparent?
116
116
  Watobo::Interceptor::Transparent.start
@@ -136,25 +136,30 @@ module Watobo#:nodoc: all
136
136
 
137
137
  c_sock = Watobo::HTTPSocket::ClientSocket.connect(session)
138
138
  Thread.exit if c_sock.nil?
139
+ # loop for reusing client connections
140
+ max_loop = 0
139
141
  loop do
140
142
  flags = []
141
143
  begin
142
-
143
- request = c_sock.request
144
-
145
- if request.nil? or request.empty? then
144
+
145
+ # puts "#{c_sock} - read request"
146
+ request = c_sock.request
147
+ if request.nil? or request.empty? then
148
+ print "c/"
146
149
  c_sock.close
147
150
  Thread.exit
148
151
  end
149
- puts "*[I] #{request.url}"
152
+
153
+ url = ( request.url.to_s.length > 65 ) ? request.url.to_s.slice(0,65) + "..." : request.url.to_s
154
+ puts "\n[I] #{url}"
150
155
 
151
156
  rescue => bang
152
157
  puts "!!! Error reading client request "
153
158
  puts bang
154
159
  puts bang.backtrace
155
- puts request.class
160
+ # puts request.class
156
161
  # puts request
157
- closeSocket(c_sock)
162
+ c_sock.close
158
163
  Thread.exit
159
164
  #break
160
165
  end
@@ -164,18 +169,18 @@ module Watobo#:nodoc: all
164
169
  if request.first =~ /WATOBOPreview=([0-9a-zA-Z]*)/ then
165
170
 
166
171
  puts "* preview requested ..."
167
- puts request.url
172
+ # puts request.url
168
173
 
169
174
  hashid = $1
170
175
  response = @preview[hashid]
171
176
 
172
177
  if response then
173
178
  c_sock.write response.join
174
- closeSocket(c_sock)
179
+ c_sock.close
175
180
  end
176
181
  end
177
182
  #next
178
- Thread.current.exit
183
+ Thread.exit
179
184
  end
180
185
 
181
186
  request_intercepted = false
@@ -197,9 +202,9 @@ module Watobo#:nodoc: all
197
202
  #notify(:modify_request, request, Thread.current)
198
203
  Watobo.print_debug "send request to target"
199
204
  @target.addRequest(request, Thread.current)
200
- puts "* stopping thread: #{Thread.current} ..."
205
+ # puts "* stopping thread: #{Thread.current} ..."
201
206
  Thread.stop
202
- puts "* released thread: #{Thread.current}"
207
+ # puts "* released thread: #{Thread.current}"
203
208
  else
204
209
  p "! no target for editing request"
205
210
  end
@@ -213,13 +218,15 @@ module Watobo#:nodoc: all
213
218
  begin
214
219
 
215
220
  s_sock, req, resp = @sender.sendHTTPRequest(request, :update_sids => true, :update_session => false, :update_contentlength => true, :www_auth => @www_auth, :client_certificates => @client_certificates)
221
+
216
222
  if s_sock.nil? then
223
+ puts "s_sock is nil! bye, bye, ..."
217
224
  puts request if $DEBUG
218
225
  c_sock.write resp.join unless resp.nil?
219
226
  c_sock.close
220
227
  #Thread.kill Thread.current
221
228
  Thread.exit
222
- next
229
+ #next
223
230
  end
224
231
 
225
232
  rescue => bang
@@ -232,16 +239,22 @@ module Watobo#:nodoc: all
232
239
 
233
240
  # check if response should be passed throug
234
241
  #Thread.current.exit if isPassThrough?(req, resp, s_sock, c_sock)
242
+ if isPassThrough?(req, resp, s_sock, c_sock)
243
+ Watobo::HTTPSocket.close s_sock
244
+ c_sock.close
245
+ Thread.exit
246
+ end
235
247
  #p "no pass-through"
236
248
 
237
249
  begin
238
250
  # puts "* got response status: #{resp.status}"
239
251
  missing_credentials = false
240
252
  rs = resp.status
253
+ auth_type = AUTH_TYPE_NONE
241
254
  if rs =~ /^(401|407)/ then
242
255
  missing_credentials = true
243
256
 
244
- auth_type = AUTH_TYPE_NONE
257
+
245
258
  resp.each do |rl|
246
259
  if rl =~ /^(Proxy|WWW)-Authenticate: Basic/i
247
260
  auth_type = AUTH_TYPE_BASIC
@@ -272,11 +285,11 @@ module Watobo#:nodoc: all
272
285
  resp.fix_content_length
273
286
 
274
287
  end
275
- else
288
+ end
289
+ unless auth_type == AUTH_TYPE_UNKNOWN or req.method =~ /^head/i
276
290
  # don't try to read body if request method is HEAD
277
- unless req.method =~ /^head/i
278
291
  @sender.readHTTPBody(s_sock, resp, req, :update_sids => true)
279
- end
292
+ Watobo::HTTPSocket.close s_sock
280
293
  end
281
294
  rescue => bang
282
295
  puts "!!! could not send request !!!"
@@ -310,17 +323,29 @@ module Watobo#:nodoc: all
310
323
  end
311
324
 
312
325
  # puts ">> SEND TO CLIENT"
326
+ # puts ">>C<< - Close: #{request.connection_close?}"
327
+ #request.headers("Connection"){ |h| puts h }
328
+
313
329
  if missing_credentials
314
330
  resp.set_header("Connection", "close")
315
- c_sock.write resp.join
316
- c_sock.close
331
+ elsif request.connection_close? or resp.content_length < 0 or max_loop > 4
332
+ resp.set_header("Proxy-Connection","close")
333
+ resp.set_header("Connection","close")
317
334
  else
318
- c_sock.write resp.join
319
- end
320
- # puts resp.join
321
- # puts "-----"
322
- # closeSocket(c_sock)
323
-
335
+ resp.set_header("Connection","keep-alive")
336
+ resp.set_header("Keep-Alive", "max=4, timeout=120")
337
+ end
338
+
339
+ resp_data = resp.join
340
+ c_sock.write resp_data
341
+ c_sock.flush
342
+ # puts "= RESPONSE ="
343
+ # puts resp_data
344
+ # puts "---"
345
+ # puts resp_data.unpack("H*")[0]
346
+ # puts "==="
347
+ # puts
348
+
324
349
  rescue Errno::ECONNRESET
325
350
  print "x"
326
351
  # puts "!!! ERROR (Reset): reading body"
@@ -337,11 +362,19 @@ module Watobo#:nodoc: all
337
362
  #return
338
363
  end
339
364
 
340
- chat = Chat.new(request.copy, resp.copy, :source => CHAT_SOURCE_INTERCEPT)
341
- # notify(:new_interception, chat)
365
+ chat = Chat.new(request.copy, resp.copy, :source => CHAT_SOURCE_INTERCEPT)
366
+
342
367
  Watobo::Chats.add chat
343
- Thread.current.exit if missing_credentials
344
- end
368
+
369
+
370
+ if missing_credentials or request.connection_close? or resp.content_length < 0 or max_loop > 4
371
+ c_sock.close
372
+ Thread.exit
373
+ end
374
+ print "o"
375
+ max_loop += 1
376
+
377
+ end
345
378
  }
346
379
 
347
380
  end
@@ -400,24 +433,7 @@ end
400
433
  @preview = Hash.new
401
434
  @preview['ProxyTest'] = ["HTTP/1.0 200 OK\r\nServer: Watobo-Interceptor\r\nConnection: close\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n<html><body>PROXY_OK</body></html>"]
402
435
 
403
- # p @settings[:certificate_path]
404
- # p @settings[:cert_file]
405
- # p @settings[:key_file]
406
- # crt_path = Watobo::Conf::Interceptor.certificate_path
407
- # crt_file = Watobo::Conf::Interceptor.cert_file
408
- # key_file = Watobo::Conf::Interceptor.key_file
409
- # dh_key_file = Watobo::Conf::Interceptor.dh_key_file
410
-
411
- # crt_filename = File.join(Watobo.base_directory, crt_path, crt_file)
412
- # key_filename = File.join(Watobo.base_directory, crt_path, key_file)
413
-
414
- # @ctx = OpenSSL::SSL::SSLContext.new('SSLv23_server')
415
- # @cert = OpenSSL::X509::Certificate.new(File.read(crt_filename))
416
- # @key = OpenSSL::PKey::RSA.new(File.read(key_filename))
417
-
418
- #@dh_key = OpenSSL::PKey::DH.new(File.read(dh_filename))
419
436
  @dh_key = Watobo::CA.dh_key
420
- # @ctx.ciphers = nil # ['TLSv1/SSLv3', 56, 56 ]
421
437
 
422
438
  rescue => bang
423
439
  puts "!!!could not read certificate files:"
@@ -548,7 +564,7 @@ end
548
564
  end
549
565
  end
550
566
  return false if match_ctype == false
551
- puts "* pass ctype filter"
567
+ #puts "* pass ctype filter"
552
568
  match_rcode = true
553
569
  rcode_filter = @response_filter_settings[:response_code_filter]
554
570
  negate = @response_filter_settings[:negate_response_code_filter]
@@ -564,7 +580,7 @@ end
564
580
  end
565
581
  end
566
582
  return false if match_rcode == false
567
- puts "* pass rcode filter"
583
+ #puts "* pass rcode filter"
568
584
  true
569
585
  end
570
586
 
@@ -574,10 +590,9 @@ end
574
590
  #
575
591
  #
576
592
  def pass_through(server, client, maxbytes = 0)
577
- buf = ''
578
- print "[~"
593
+
579
594
  bytes_read = 0
580
- while buf
595
+ while 1
581
596
  begin
582
597
  #timeout(2) do
583
598
  buf = nil
@@ -586,18 +601,25 @@ end
586
601
  rescue EOFError
587
602
  #client.write buf if buf
588
603
  #print "~]"
604
+ # msg = "\n[pass_through] EOF - "
605
+ # msg += buf.nil? ? "nil" : buf.size
606
+ # puts msg
589
607
  return if buf.nil?
590
608
  rescue Errno::ECONNRESET
591
609
  # puts "!!! ERROR (Reset): reading body"
592
610
  # puts "* last data seen on socket: #{buf}"
593
- print "R"
611
+ # msg = "!R - "
612
+ # msg += buf.nil? ? "nil" : buf.size
613
+ # msg << " !\n"
614
+ # puts msg
615
+
594
616
  return if buf.nil?
595
617
  rescue Timeout::Error
596
618
  #puts "!!! ERROR (Timeout): reading body"
597
619
  #puts "* last data seen on socket:"
598
620
  #client.write buf if buf
599
621
  print "T"
600
- return if buf.nil?
622
+ return
601
623
  rescue => bang
602
624
  puts "!!! could not read body !!!"
603
625
  puts bang
@@ -611,25 +633,24 @@ end
611
633
 
612
634
  begin
613
635
  return if buf.nil?
614
- print "~"
636
+ # print "~"
615
637
  client.write buf
616
638
  bytes_read += buf.length
617
- # puts "##{bytes_read} of #{maxbytes}"
639
+ # puts "#{server} #{bytes_read} of #{maxbytes}"
618
640
  if maxbytes > 0 and bytes_read >= maxbytes
619
- print "~]"
620
- return
641
+ #print "~]"
642
+ return
621
643
  end
622
-
623
644
  rescue Errno::ECONNRESET
624
- print "~x]"
645
+ #print "~x]"
625
646
  # puts "!!! ERROR (Reset): reading body"
626
647
  # puts "* last data seen on socket: #{buf}"
627
648
  return
628
649
  rescue Errno::ECONNABORTED
629
- print "~x]"
650
+ # print "~x]"
630
651
  return
631
652
  rescue Errno::EPIPE
632
- print "~x]"
653
+ # print "~x]"
633
654
  return
634
655
  rescue => bang
635
656
  puts "!!! client communication broken !!!"
@@ -642,8 +663,7 @@ end
642
663
  end
643
664
 
644
665
  def transparent?
645
- return true if ( @proxy_mode & Watobo::Interceptor::MODE_TRANSPARENT ) > 0
646
- return false
666
+ ( @proxy_mode & Watobo::Interceptor::MODE_TRANSPARENT ) > 0
647
667
  end
648
668
 
649
669
  def read_request(socket)
@@ -809,6 +829,7 @@ end
809
829
 
810
830
  def isPassThrough?(request, response, s_sock, c_sock)
811
831
  begin
832
+ # return false if true
812
833
  reason = nil
813
834
  clen = response.content_length
814
835
  # no pass-through necessary if request method is HEAD
@@ -816,19 +837,25 @@ end
816
837
 
817
838
  if matchContentType?(response.content_type) then
818
839
  # first forward headers
819
- c_sock.write response.join
840
+ #c_sock.write response.join
820
841
  reason = []
821
842
  reason.push "---> WATOBO: PASS_THROUGH <---"
822
843
  reason.push "Reason: Content-Type = #{response.content_type}"
823
844
  elsif clen > @contentLength
824
845
  # puts "PASS-THROUGH: #{response.content_length}"
825
- c_sock.write response.join
846
+ #c_sock.write response.join
826
847
  reason = []
827
848
  reason.push "---> WATOBO: PASS_THROUGH <---"
828
849
  reason.push "Reason: Content-Length > #{@contentLength} (#{response.content_length})"
829
850
  end
830
851
 
831
852
  return false if reason.nil?
853
+
854
+ response.remove_header("Keep-Alive")
855
+ response.set_header("Connection", "close")
856
+
857
+ c_sock.write response.join
858
+
832
859
  reason.push "* DO MANUAL REQUEST TO GET FULL RESPONSE *"
833
860
  response.push reason.join("\n")
834
861
  chat = Watobo::Chat.new(request, response, :source => CHAT_SOURCE_INTERCEPT)
@@ -837,45 +864,16 @@ end
837
864
 
838
865
  pass_through(s_sock, c_sock, clen)
839
866
  # puts "* Close Server Socket..."
840
- closeSocket(c_sock)
867
+ #closeSocket(c_sock)
841
868
  # puts "* Close Client Socket..."
842
- closeSocket(s_sock)
869
+ #closeSocket(s_sock)
843
870
  # puts "... done."
844
- true
845
- rescue => bang
846
- puts bang
847
- puts bang.backtrace if $DEBUG
848
- return false
849
- end
850
- end
851
-
852
- def notify(event, *args)
853
- if @event_dispatcher_listeners[event]
854
- @event_dispatcher_listeners[event].each do |m|
855
- m.call(*args) if m.respond_to? :call
856
- end
857
- end
858
- end
859
-
860
- def closeSocket(socket)
861
- #puts socket.class
862
- return false if socket.nil?
863
- begin
864
- #if socket.class.to_s =~ /SSLSocket/
865
- if socket.respond_to? :sysclose
866
- #socket.io.shutdown(2)
867
- socket.sysclose
868
- elsif socket.respond_to? :shutdown
869
- socket.shutdown(2)
870
- elsif socket.respond_to? :close
871
- socket.close
872
- end
873
871
  return true
874
872
  rescue => bang
875
873
  puts bang
876
874
  puts bang.backtrace if $DEBUG
877
875
  end
878
- false
876
+ return false
879
877
  end
880
878
 
881
879
  end
@@ -426,23 +426,7 @@ module Watobo#:nodoc: all
426
426
 
427
427
  end
428
428
 
429
- # def get_parm_names
430
-
431
- # parm_names=[]
432
- # parmlist=[]
433
- # parmlist.concat(get_parms)
434
-
435
- # parmlist.each do |p|
436
- # if p then
437
- # p.gsub!(/=.*/,'')
438
- # parm_names.push p
439
- # end
440
- # end
441
-
442
- # return parm_names
443
-
444
- # end
445
-
429
+
446
430
  def header_value(header_name)
447
431
  header_values =[]
448
432
  self.headers.each do |header|
@@ -593,6 +577,20 @@ def content_encoding
593
577
  def has_body?
594
578
  self.body.nil? ? false : true
595
579
  end
580
+
581
+ def __connection_close?
582
+ headers("Connection") do |h|
583
+ return true if h =~ /close/i
584
+ end
585
+ return false
586
+ end
587
+
588
+ def connection_close?
589
+ headers("Connection") do |h|
590
+ return false if h =~ /keep\-alive/i
591
+ end
592
+ return true
593
+ end
596
594
 
597
595
  def has_header?(name)
598
596
  self.each do |l|
@@ -708,6 +706,7 @@ end
708
706
  rescue => bang
709
707
  puts "! no headers available !".upcase
710
708
  puts bang
709
+ puts bang.backtrace
711
710
  if $DEBUG
712
711
  puts bang.backtrace
713
712
  puts self.to_yaml
@@ -186,10 +186,12 @@ module Watobo#:nodoc: all
186
186
 
187
187
  def removeHeader(header)
188
188
  begin
189
- eoh_index = self.length
190
- eoh_index -= 1 unless self.body.nil?
191
-
192
- self.delete_if {|x| self.index(x) <= eoh_index and x =~ /#{header}/i }
189
+ matches = []
190
+ headers.each_with_index do |h,i|
191
+ matches << i if h =~ /#{header}/i
192
+ end
193
+ matches.map{ |m| self.delete_at(m) }
194
+
193
195
  rescue => bang
194
196
  puts bang
195
197
  puts bang.backtrace if $DEBUG
data/lib/watobo.rb CHANGED
@@ -39,6 +39,7 @@ require 'net/ntlm'
39
39
  require 'drb'
40
40
  require 'nokogiri'
41
41
  require 'stringio'
42
+ require 'mechanize'
42
43
 
43
44
  require 'watobo/constants'
44
45
  require 'watobo/utils'
@@ -56,10 +57,13 @@ require 'watobo/parser'
56
57
  require 'watobo/interceptor'
57
58
  require 'watobo/http_socket'
58
59
 
60
+ # WORKAROUND FOR LINUX :(
61
+ dont_know_why_REQUIRE_hangs = Mechanize.new
62
+
59
63
  # @private
60
64
  module Watobo#:nodoc: all #:nodoc: all
61
65
 
62
- VERSION = "0.9.13"
66
+ VERSION = "0.9.14"
63
67
 
64
68
  def self.base_directory
65
69
  @base_directory ||= ""
@@ -91,11 +91,8 @@ module Watobo#:nodoc: all
91
91
  old_cookies = chat.request.cookies.select do |rc|
92
92
  cookie_old = true
93
93
  chat.response.new_cookies do |nc|
94
- if rc =~ /^#{nc.name}/
95
- rc_name, rc_value = rc.split("=")
96
- cookie_old = false unless rc_value == nc.value
97
- end
98
- puts ":#{rc} - #{nc.name} - #{cookie_old}"
94
+ cookie_old = false unless rc.value == nc.value
95
+ #puts ":#{rc} - #{nc.name} - #{cookie_old}"
99
96
  end
100
97
  puts ":#{rc} >> #{cookie_old}"
101
98
  cookie_old
@@ -19,62 +19,7 @@
19
19
  # along with WATOBO; if not, write to the Free Software
20
20
  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
21
  # .
22
- begin
23
- require 'mechanize'
24
- rescue LoadError
25
- puts "To use the crawler plugin you must install the 'mechanize' gem."
26
- puts "Simply enter the command 'gem install mechanize'"
27
- end
28
-
29
-
30
-
31
-
32
- path = File.expand_path(File.dirname(__FILE__))
33
-
34
22
  %w( constants bags grabber engine uri_mp).each do |l|
35
- require File.join(path, "lib", l)
23
+ require_relative File.join("lib", l)
36
24
  end
37
25
 
38
- if $0 == __FILE__
39
- # @private
40
- module Watobo#:nodoc: all
41
- module Conf
42
- class Interceptor
43
- def self.port
44
- # 8081
45
- nil
46
- end
47
- end
48
- end
49
- end
50
-
51
- require 'yaml'
52
- if ARGV.length > 0
53
- url = ARGV[0]
54
- end
55
-
56
- hook = lambda{ |agent, request|
57
- begin
58
- puts request.class
59
- puts request.method
60
- puts request.methods.sort
61
-
62
- exit
63
- clean_jar = Mechanize::CookieJar.new
64
- agent.cookie_jar.each{|cookie|
65
- puts "Cookie: #{cookie.name}"
66
- clean_jar.add! cookie unless cookie.name =~ /^box/i
67
- }
68
- exit unless agent.cookie_jar.empty?(request.url.to_s)
69
- agent.cookie_jar = clean_jar
70
- rescue => bang
71
- puts bang
72
- puts bang.backtrace
73
- end
74
-
75
- }
76
- hook = nil
77
-
78
- crawler = Watobo::Crawler::Engine.new
79
- crawler.run(url, :pre_connect_hook => hook, :num_grabbers => 1 )
80
- end
@@ -266,15 +266,14 @@ module Watobo#:nodoc: all
266
266
  prefs.update general_settings
267
267
  prefs.update hook_settings
268
268
 
269
- # puts prefs.to_yaml
269
+ add_update_timer(250)
270
270
 
271
- Thread.new{
272
- url = @url_txt.text
273
- @crawler.run(url, prefs)
271
+ Thread.new(@url_txt.text,prefs){|turl,tprefs|
272
+ @crawler.run(turl, tprefs)
274
273
  }
275
274
 
276
275
  @start_button.text = 'Cancel'
277
- add_update_timer()
276
+
278
277
 
279
278
  rescue PasswordMatchError
280
279
  #puts "Passwords Don't Match!"