Home | History | Annotate | Download | only in src
      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 
     18 require 'cgi'
     19 require 'webrick'
     20 require 'optparse'
     21 require './iexploder.rb'
     22 
     23 include WEBrick
     24 
     25 $INSTANCE = nil
     26 $last_page_requested = [Time.now().to_i, 0]
     27 
     28 # Main CGI - Pass requests to iexploder
     29 class 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
     87 end
     88 
     89 
     90 # Simple form
     91 class IEForm < HTTPServlet::AbstractServlet
     92   def do_GET(request, response)
     93     response['Content-Type'] = 'text/html'
     94     response.body = File.read("index.html")
     95   end
     96 end
     97 
     98 class 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
    103 end
    104 
    105 class NoPage < HTTPServlet::AbstractServlet
    106   def do_GET(request, response)
    107     response.body = 'OHAI'
    108   end
    109 end
    110 
    111 class LastPage < HTTPServlet::AbstractServlet
    112   def do_GET(request, response)
    113     response.body = $last_page_requested.join(' ')
    114   end
    115 end
    116 
    117 
    118 def 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."
    141 end
    142 
    143 
    144 
    145 if $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])
    161 end
    162