1#!/usr/bin/ruby 2# iExploder Web Server (using webrick) 3# 4# Copyright 2010 Thomas Stromberg - All Rights Reserved. 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17 18require 'cgi' 19require 'webrick' 20require 'optparse' 21require './iexploder.rb' 22 23include WEBrick 24 25$INSTANCE = nil 26$last_page_requested = [Time.now().to_i, 0] 27 28# Main CGI - Pass requests to iexploder 29class IEServlet < HTTPServlet::AbstractServlet 30 def do_GET(request, response) 31 ie = $INSTANCE.dup 32 ie.test_num = request.query['t'].to_i || 0 33 ie.subtest_data = request.query['s'] || nil 34 ie.random_mode = request.query['r'] 35 ie.lookup_mode = request.query['l'] 36 ie.claimed_browser = request.query['b'] || nil 37 ie.stop_num = request.query['x'] || nil 38 user_agent = request['User-agent'] || 'unknown' 39 raw_user_agent = user_agent.dup 40 41 # Shorten the user-agent displayed 42 user_agent.gsub!('Mozilla/5.0', '') 43 user_agent.gsub!('X11; ', '') 44 user_agent.gsub!('Macintosh; ', '') 45 user_agent.gsub!(' U;', '') 46 user_agent.gsub!(/^ +/, '') 47 user_agent.gsub!(' (KHTML, like Gecko)', '') 48 if user_agent =~ /Chrome/ 49 user_agent.gsub!(/Safari\/[\d\.]+/, '') 50 end 51 ie.browser = user_agent 52 ie.setRandomSeed() 53 # If we are a dependency image, fiddle with the headers! 54 mime_type = request.query['m'] 55 headers = [] 56 if mime_type 57 for (key, value) in ie.buildHeaders(mime_type) 58 headers << "#{key}[#{value.length}]" 59 response[key] = value 60 end 61 response.body = ie.buildMediaFile(mime_type) 62 else 63 response['Content-Type'] = 'text/html' 64 response.body = ie.buildPage() 65 end 66 67 details = "?t=#{ie.test_num}" 68 if ie.subtest_data 69 details << "&s=#{ie.subtest_data}" 70 end 71 if ie.random_mode 72 details << "&r=1" 73 end 74 if ie.lookup_mode 75 details << "&l=#{ie.lookup_mode}" 76 end 77 if mime_type 78 details << "&m=#{mime_type}" 79 else 80 $last_page_requested = [Time.now().to_i, request.unparsed_uri, CGI.escape(user_agent)] 81 end 82 printf("%-45.45s %s\n", details, user_agent) 83 if headers.length > 0 84 printf("%-45.45s %s\n", "Headers for #{mime_type}:", headers.join(', ')) 85 end 86 end 87end 88 89 90# Simple form 91class IEForm < HTTPServlet::AbstractServlet 92 def do_GET(request, response) 93 response['Content-Type'] = 'text/html' 94 response.body = File.read("index.html") 95 end 96end 97 98class IELogo < HTTPServlet::AbstractServlet 99 def do_GET(request, response) 100 response['Content-Type'] = 'image/png' 101 response.body = File.read("media/bug.png") 102 end 103end 104 105class NoPage < HTTPServlet::AbstractServlet 106 def do_GET(request, response) 107 response.body = 'OHAI' 108 end 109end 110 111class LastPage < HTTPServlet::AbstractServlet 112 def do_GET(request, response) 113 response.body = $last_page_requested.join(' ') 114 end 115end 116 117 118def start_server(port, config_path, log_path) 119 puts "* iExploder #{$VERSION} is loading (config=#{config_path}, port=#{port})" 120 puts "=" * 80 121 $INSTANCE = IExploder.new(config_path) 122 warn_logger = Log.new($stderr, Log::WARN) 123 config = YAML::load(File.open(config_path)) 124 if not log_path 125 log_path = config['access_log_path'] 126 end 127 puts "- Setting up logging to #{log_path}" 128 access_log_stream = Log.new(log_path) 129 access_log = [[ access_log_stream, AccessLog::COMMON_LOG_FORMAT ]] 130 s = WEBrick::HTTPServer.new(:Port => port, :Logger => warn_logger, :AccessLog => access_log) 131 s.mount("/", IEForm) 132 s.mount("/favicon.ico", NoPage) 133 s.mount("/media/bug.png", IELogo) 134 s.mount("/iexploder.cgi", IEServlet) 135 s.mount("/last_page.cgi", LastPage) 136 ['INT', 'TERM'].each {|signal| trap(signal) { puts "SERVER SHUTDOWN: #{signal}"; s.shutdown }} 137 puts "- iExploder is at http://127.0.0.1:#{port}" 138 s.start 139 puts "" 140 puts "Goodbye! Have a fantastic day." 141end 142 143 144 145if $0 == __FILE__ 146 options = { 147 :port => 3100, 148 :config_path => 'config.yaml', 149 :log_path => nil 150 } 151 152 optparse = OptionParser.new do|opts| 153 opts.banner = "Usage: webserver.rb [options]" 154 opts.on( '-p', '--port NUM', 'Listen on TCP port NUM' ) { |port| options[:port] = port } 155 opts.on( '-c', '--config PATH', 'Use PATH for configuration file' ) { |path| options[:config_path] = path } 156 opts.on( '-l', '--log PATH', 'Use PATH for log file' ) { |path| options[:log_path] = path } 157 opts.on( '-h', '--help', 'Display this screen' ) { puts opts; exit } 158 end 159 optparse.parse! 160 start_server(options[:port], options[:config_path], options[:log_path]) 161end 162