require 'socket' city = ARGV.shift req = ARGV.shift # optional forced request delay = 5 # init one new connection every X seconds # default request choice SUBQ = %w[/ / / /ind /tra /sec /env /com] $use_socks = ENV['USE_SOCKS'] || true if $use_socks # address of a socks4a port sockh, sockp = 'localhost', 9050 else sockh, sockp = "#{city}.miniville.fr", 80 end $use_proxy = ENV['USE_PROXY'] || false if $use_proxy prerq = "http://#{city}.miniville.fr" get_proxy = proc { sockh = 'proxy.kikoo' sockp = 3128 } else prerq = '' end class TCPSocket attr_accessor :created end # initialize a socket, send requests cnct = proc { get_proxy[] if $use_proxy buf = '' s = TCPSocket.open sockh, sockp if $use_socks # connect through socks desth, destp = "#{city}.miniville.fr", 80 buf << 4 # version buf << 1 # connect (2 = bind) buf << (destp.to_i >> 8) << (destp.to_i & 255) # port bigend buf << 0 << 0 << 0 << 1 # destip, 0.0.0.1 == 'sock_do_dns' buf << 0 # socks credentials buf << desth << 0 # target (strz) end if not req # use dynamic choice file if available nq = File.read('miniville-nextrq').split rescue nil # else use default nq = SUBQ if not nq or nq.empty? # random along possibilities subq = nq[rand(nq.length)] else # use forced if set subq = req end # setup http headers hdrs = {} hdrs['Host'] = "#{city}.miniville.fr" hdrs['User-Agent'] = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0' hdrs['Accept'] = 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5' hdrs['Connection'] = 'keep-alive' hdrs['Keep-Alive'] = 300 hdrs['Accept-Encoding'] = 'gzip,deflate' hdrs['Accept-Language'] = 'en' # 1st cx buf << ["GET #{prerq}#{subq} HTTP/1.1", *hdrs.map { |k, v| "#{k}: #{v}" }].join("\r\n") << "\r\n\r\n" # 2nd cx: set cookie from 1 (hardcoded) hdrs['Cookie'] = 'X-Ref-Ok=1; X-MV-Referer=' + "http://#{city}.miniville.fr/".gsub(/[^a-z.\/]/) { |c| '%%%02x' % c[0] } if subq != '/' buf << ["GET #{prerq}#{subq} HTTP/1.1", *hdrs.map { |k, v| "#{k}: #{v}" }].join("\r\n") << "\r\n\r\n" end # close connection, emul redirect from /req to / hdrs['Connection'] = 'Close' buf << ["GET #{prerq}/ HTTP/1.1", *hdrs.map { |k, v| "#{k}: #{v}" }].join("\r\n") << "\r\n\r\n" # send pipelined requests s.write buf # set timeout information s.created = Time.now.to_f puts buf, ' -- ' if $DEBUG # return socket s } if $DEBUG buf = cnct[].read puts buf exit end ary = [] # array of pending connections run = true trap('INT') { trap('INT', 'DEFAULT') puts '', 'aborting' run = false } ary << cnct[] tlast = Time.now.to_f count = 0 while run or not ary.empty? if not ary.empty? and ary.first.created + 600 < Time.now.to_f # drop timeouted sockets ary.shift.close end if run and tlast + delay < Time.now.to_f # spawn new connection if delay passed ary << cnct[] if ary.length < 512 tlast += delay end r, w, e = IO.select(ary, nil, nil, 0.4) next if not r begin # read http response buf = r.first.readpartial(64*1024) # parse html buf = buf.scan(//m).join.gsub(/<.*?>/m, ' ').gsub(/\s+/, ' ') p buf if $VERBOSE and not buf.empty? # buf = "Population 305 Revenus 72000 \342\202\254 Chomage 0 % Transport 100 % Criminalit\303\251 2 % Pollution 0 %" if buf =~ /Population (\d+) .* Chomage (\d+) .* Transport (\d+) .* Crim.* (\d+) .* Pollution (\d+)/ pop, ind, tra, sec, env = $1.to_i, 2*$2.to_i, 2*(100-$3.to_i), 2*$4.to_i, 2*$5.to_i # next possible requests: farther from 1 = more likely nact = '/' nact << ' /ind' while (ind /= 2) > 0 and pop > 50 nact << ' /tra' while (tra /= 2) > 0 and pop > 100 nact << ' /sec' while (sec /= 2) > 0 and pop > 500 nact << ' /env' while (env /= 2) > 0 and pop > 500 nact << ' /com /' if pop > 1000 # 1 in 3 p nact if $VERBOSE File.open('miniville-nextrq', 'w') { |fd| fd.puts nact } else p buf if not buf.empty? and $VERBOSE end rescue EOFError # sock closed ary.delete(r.first).close count += 1 end # output $stderr.write "%03d %d\r" % [ary.length, count] end puts