import BaseHTTPServer import SimpleHTTPServer import os import sys import urllib, urlparse import posixpath import StringIO import re import shutil import threading import time import socket import Reporter import ConfigParser # Keys replaced by server. kReportColRE = re.compile('') kReportColRepl = '
' traceback.print_exc(e,file=s) print >>s,'' self.status = s.getvalue() class ScanViewServer(BaseHTTPServer.HTTPServer): def __init__(self, address, handler, root, reporters, options): BaseHTTPServer.HTTPServer.__init__(self, address, handler) self.root = root self.reporters = reporters self.options = options self.halted = False self.config = None self.load_config() def load_config(self): self.config = ConfigParser.RawConfigParser() # Add defaults self.config.add_section('ScanView') for r in self.reporters: self.config.add_section(r.getName()) for p in r.getParameterNames(): self.config.set(r.getName(), p, '') # Ignore parse errors try: self.config.read([kConfigPath]) except: pass # Save on exit import atexit atexit.register(lambda: self.save_config()) def save_config(self): # Ignore errors (only called on exit). try: f = open(kConfigPath,'w') self.config.write(f) f.close() except: pass def halt(self): self.halted = True if self.options.debug: print >>sys.stderr, "%s: SERVER: halting." % (sys.argv[0],) def serve_forever(self): while not self.halted: if self.options.debug > 1: print >>sys.stderr, "%s: SERVER: waiting..." % (sys.argv[0],) try: self.handle_request() except OSError,e: print 'OSError',e.errno def finish_request(self, request, client_address): if self.options.autoReload: import ScanView self.RequestHandlerClass = reload(ScanView).ScanViewRequestHandler BaseHTTPServer.HTTPServer.finish_request(self, request, client_address) def handle_error(self, request, client_address): # Ignore socket errors info = sys.exc_info() if info and isinstance(info[1], socket.error): if self.options.debug > 1: print >>sys.stderr, "%s: SERVER: ignored socket error." % (sys.argv[0],) return BaseHTTPServer.HTTPServer.handle_error(self, request, client_address) # Borrowed from Quixote, with simplifications. def parse_query(qs, fields=None): if fields is None: fields = {} for chunk in filter(None, qs.split('&')): if '=' not in chunk: name = chunk value = '' else: name, value = chunk.split('=', 1) name = urllib.unquote(name.replace('+', ' ')) value = urllib.unquote(value.replace('+', ' ')) fields[name] = value return fields class ScanViewRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): server_version = "ScanViewServer/" + __version__ dynamic_mtime = time.time() def do_HEAD(self): try: SimpleHTTPServer.SimpleHTTPRequestHandler.do_HEAD(self) except Exception,e: self.handle_exception(e) def do_GET(self): try: SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) except Exception,e: self.handle_exception(e) def do_POST(self): """Serve a POST request.""" try: length = self.headers.getheader('content-length') or "0" try: length = int(length) except: length = 0 content = self.rfile.read(length) fields = parse_query(content) f = self.send_head(fields) if f: self.copyfile(f, self.wfile) f.close() except Exception,e: self.handle_exception(e) def log_message(self, format, *args): if self.server.options.debug: sys.stderr.write("%s: SERVER: %s - - [%s] %s\n" % (sys.argv[0], self.address_string(), self.log_date_time_string(), format%args)) def load_report(self, report): path = os.path.join(self.server.root, 'report-%s.html'%report) data = open(path).read() keys = {} for item in kBugKeyValueRE.finditer(data): k,v = item.groups() keys[k] = v return keys def handle_exception(self, exc): import traceback s = StringIO.StringIO() print >>s, "INTERNAL ERROR\n" traceback.print_exc(exc, s) f = self.send_string(s.getvalue(), 'text/plain') if f: self.copyfile(f, self.wfile) f.close() def submit_bug(self): title = self.fields.get('title') description = self.fields.get('description') report = self.fields.get('report') reporterIndex = self.fields.get('reporter') # Type check form parameters. reportPath = posixpath.join(self.server.root, 'report-%s.html' % report) if not posixpath.exists(reportPath): return (False, "Invalid report ID.") if not title: return (False, "Missing title.") if not description: return (False, "Missing description.") try: reporterIndex = int(reporterIndex) except: return (False, "Invalid report method.") # Get the reporter and parameters. reporter = self.server.reporters[reporterIndex] parameters = {} for o in reporter.getParameterNames(): name = '%s_%s'%(reporter.getName(),o) if name not in self.fields: return (False, 'Missing field "%s" for %s report method.'%(name, reporter.getName())) parameters[o] = self.fields[name] # Update config defaults. self.server.config.set('ScanView', 'reporter', reporterIndex) for o in reporter.getParameterNames(): self.server.config.set(reporter.getName(), o, parameters[o]) # Create the report. bug = Reporter.BugReport(title, description, [reportPath]) # Kick off a reporting thread. t = ReporterThread(bug, reporter, parameters, self.server) t.start() # Wait for thread to die... while t.isAlive(): time.sleep(.25) submitStatus = t.status return (t.success, t.status) def send_report_submit(self): report = self.fields.get('report') title = self.fields.get('title') description = self.fields.get('description') res,message = self.submit_bug() if res: statusClass = 'SubmitOk' statusName = 'Succeeded' else: statusClass = 'SubmitFail' statusName = 'Failed' result = """