| #!/usr/bin/env ruby |
| # iExploder Web Server (using webrick) |
| # |
| # Copyright 2010 Thomas Stromberg - All Rights Reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| require 'cgi' |
| require 'webrick' |
| require 'optparse' |
| require './iexploder.rb' |
| |
| include WEBrick |
| |
| $INSTANCE = nil |
| $last_page_requested = [Time.now().to_i, 0] |
| |
| # Main CGI - Pass requests to iexploder |
| class IEServlet < HTTPServlet::AbstractServlet |
| def do_GET(request, response) |
| ie = $INSTANCE.dup |
| ie.test_num = request.query['t'].to_i || 0 |
| ie.subtest_data = request.query['s'] || nil |
| ie.random_mode = request.query['r'] |
| ie.lookup_mode = request.query['l'] |
| ie.claimed_browser = request.query['b'] || nil |
| ie.stop_num = request.query['x'] || nil |
| user_agent = request['User-agent'] || 'unknown' |
| raw_user_agent = user_agent.dup |
| |
| # Shorten the user-agent displayed |
| user_agent.gsub!('Mozilla/5.0', '') |
| user_agent.gsub!('X11; ', '') |
| user_agent.gsub!('Macintosh; ', '') |
| user_agent.gsub!(' U;', '') |
| user_agent.gsub!(/^ +/, '') |
| user_agent.gsub!(' (KHTML, like Gecko)', '') |
| if user_agent =~ /Chrome/ |
| user_agent.gsub!(/Safari\/[\d\.]+/, '') |
| end |
| ie.browser = user_agent |
| ie.setRandomSeed() |
| # If we are a dependency image, fiddle with the headers! |
| mime_type = request.query['m'] |
| headers = [] |
| if mime_type |
| for (key, value) in ie.buildHeaders(mime_type) |
| headers << "#{key}[#{value.length}]" |
| response[key] = value |
| end |
| response.body = ie.buildMediaFile(mime_type) |
| else |
| response['Content-Type'] = 'text/html' |
| response.body = ie.buildPage() |
| end |
| |
| details = "?t=#{ie.test_num}" |
| if ie.subtest_data |
| details << "&s=#{ie.subtest_data}" |
| end |
| if ie.random_mode |
| details << "&r=1" |
| end |
| if ie.lookup_mode |
| details << "&l=#{ie.lookup_mode}" |
| end |
| if mime_type |
| details << "&m=#{mime_type}" |
| else |
| $last_page_requested = [Time.now().to_i, request.unparsed_uri, CGI.escape(user_agent)] |
| end |
| printf("%-45.45s %s\n", details, user_agent) |
| if headers.length > 0 |
| printf("%-45.45s %s\n", "Headers for #{mime_type}:", headers.join(', ')) |
| end |
| end |
| end |
| |
| |
| # Simple form |
| class IEForm < HTTPServlet::AbstractServlet |
| def do_GET(request, response) |
| response['Content-Type'] = 'text/html' |
| response.body = File.read("index.html") |
| end |
| end |
| |
| class IELogo < HTTPServlet::AbstractServlet |
| def do_GET(request, response) |
| response['Content-Type'] = 'image/png' |
| response.body = File.read("media/bug.png") |
| end |
| end |
| |
| class NoPage < HTTPServlet::AbstractServlet |
| def do_GET(request, response) |
| response.body = 'OHAI' |
| end |
| end |
| |
| class LastPage < HTTPServlet::AbstractServlet |
| def do_GET(request, response) |
| response.body = $last_page_requested.join(' ') |
| end |
| end |
| |
| |
| def start_server(port, config_path, log_path) |
| puts "* iExploder #{$VERSION} is loading (config=#{config_path}, port=#{port})" |
| puts "=" * 80 |
| $INSTANCE = IExploder.new(config_path) |
| warn_logger = Log.new($stderr, Log::WARN) |
| config = YAML::load(File.open(config_path)) |
| if not log_path |
| log_path = config['access_log_path'] |
| end |
| puts "- Setting up logging to #{log_path}" |
| access_log_stream = Log.new(log_path) |
| access_log = [[ access_log_stream, AccessLog::COMMON_LOG_FORMAT ]] |
| s = WEBrick::HTTPServer.new(:Port => port, :Logger => warn_logger, :AccessLog => access_log) |
| s.mount("/", IEForm) |
| s.mount("/favicon.ico", NoPage) |
| s.mount("/media/bug.png", IELogo) |
| s.mount("/iexploder.cgi", IEServlet) |
| s.mount("/last_page.cgi", LastPage) |
| ['INT', 'TERM'].each {|signal| trap(signal) { puts "SERVER SHUTDOWN: #{signal}"; s.shutdown }} |
| puts "- iExploder is at http://127.0.0.1:#{port}" |
| s.start |
| puts "" |
| puts "Goodbye! Have a fantastic day." |
| end |
| |
| |
| |
| if $0 == __FILE__ |
| options = { |
| :port => 3100, |
| :config_path => 'config.yaml', |
| :log_path => nil |
| } |
| |
| optparse = OptionParser.new do|opts| |
| opts.banner = "Usage: webserver.rb [options]" |
| opts.on( '-p', '--port NUM', 'Listen on TCP port NUM' ) { |port| options[:port] = port } |
| opts.on( '-c', '--config PATH', 'Use PATH for configuration file' ) { |path| options[:config_path] = path } |
| opts.on( '-l', '--log PATH', 'Use PATH for log file' ) { |path| options[:log_path] = path } |
| opts.on( '-h', '--help', 'Display this screen' ) { puts opts; exit } |
| end |
| optparse.parse! |
| start_server(options[:port], options[:config_path], options[:log_path]) |
| end |