mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-30 00:38:54 -04:00

of the details of HTML rendering of form parameters, and also us with the ability to delegate other actions (such as in the filling in of default values) to specific parameter objects. llvm-svn: 56851
771 lines
25 KiB
Python
771 lines
25 KiB
Python
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 itertools
|
|
|
|
import Reporter
|
|
import ConfigParser
|
|
|
|
###
|
|
# Various patterns matched or replaced by server.
|
|
|
|
kReportFileRE = re.compile('(.*/)?report-(.*)\\.html')
|
|
|
|
kBugKeyValueRE = re.compile('<!-- BUG([^ ]*) (.*) -->')
|
|
|
|
# <!-- REPORTPROBLEM file="crashes/clang_crash_ndSGF9.mi" stderr="crashes/clang_crash_ndSGF9.mi.stderr.txt" info="crashes/clang_crash_ndSGF9.mi.info" -->
|
|
|
|
kReportCrashEntryRE = re.compile('<!-- REPORTPROBLEM (.*?)-->')
|
|
kReportCrashEntryKeyValueRE = re.compile(' ?([^=]+)="(.*?)"')
|
|
|
|
kReportReplacements = []
|
|
|
|
# Add custom javascript.
|
|
kReportReplacements.append((re.compile('<!-- SUMMARYENDHEAD -->'), """\
|
|
<script language="javascript" type="text/javascript">
|
|
function load(url) {
|
|
if (window.XMLHttpRequest) {
|
|
req = new XMLHttpRequest();
|
|
} else if (window.ActiveXObject) {
|
|
req = new ActiveXObject("Microsoft.XMLHTTP");
|
|
}
|
|
if (req != undefined) {
|
|
req.open("GET", url, true);
|
|
req.send("");
|
|
}
|
|
}
|
|
</script>"""))
|
|
|
|
# Insert additional columns.
|
|
kReportReplacements.append((re.compile('<!-- REPORTBUGCOL -->'),
|
|
'<td></td><td></td>'))
|
|
|
|
# Insert report bug and open file links.
|
|
kReportReplacements.append((re.compile('<!-- REPORTBUG id="report-(.*)\\.html" -->'),
|
|
('<td class="Button"><a href="report/\\1">Report Bug</a></td>' +
|
|
'<td class="Button"><a href="javascript:load(\'open/\\1\')">Open File</a></td>')))
|
|
|
|
kReportReplacements.append((re.compile('<!-- REPORTHEADER -->'),
|
|
'<h3><a href="/">Summary</a> > Report %(report)s</h3>'))
|
|
|
|
kReportReplacements.append((re.compile('<!-- REPORTSUMMARYEXTRA -->'),
|
|
'<td class="Button"><a href="report/%(report)s">Report Bug</a></td>'))
|
|
|
|
# Insert report crashes link.
|
|
|
|
# Disabled for the time being until we decide exactly when this should
|
|
# be enabled. Also the radar reporter needs to be fixed to report
|
|
# multiple files.
|
|
|
|
#kReportReplacements.append((re.compile('<!-- REPORTCRASHES -->'),
|
|
# '<br>These files will automatically be attached to ' +
|
|
# 'reports filed here: <a href="report_crashes">Report Crashes</a>.'))
|
|
|
|
###
|
|
# Other simple parameters
|
|
|
|
kResources = posixpath.join(posixpath.dirname(__file__), 'Resources')
|
|
kConfigPath = os.path.expanduser('~/.scanview.cfg')
|
|
|
|
###
|
|
|
|
__version__ = "0.1"
|
|
|
|
__all__ = ["create_server"]
|
|
|
|
class ReporterThread(threading.Thread):
|
|
def __init__(self, report, reporter, parameters, server):
|
|
threading.Thread.__init__(self)
|
|
self.report = report
|
|
self.server = server
|
|
self.reporter = reporter
|
|
self.parameters = parameters
|
|
self.success = False
|
|
self.status = None
|
|
|
|
def run(self):
|
|
result = None
|
|
try:
|
|
if self.server.options.debug:
|
|
print >>sys.stderr, "%s: SERVER: submitting bug."%(sys.argv[0],)
|
|
self.status = self.reporter.fileReport(self.report, self.parameters)
|
|
self.success = True
|
|
time.sleep(3)
|
|
if self.server.options.debug:
|
|
print >>sys.stderr, "%s: SERVER: submission complete."%(sys.argv[0],)
|
|
except Reporter.ReportFailure,e:
|
|
self.status = e.value
|
|
except Exception,e:
|
|
s = StringIO.StringIO()
|
|
import traceback
|
|
print >>s,'<b>Unhandled Exception</b><br><pre>'
|
|
traceback.print_exc(e,file=s)
|
|
print >>s,'</pre>'
|
|
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.getParameters():
|
|
self.config.set(r.getName(), p.getName(), '')
|
|
|
|
# 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('+', ' '))
|
|
item = fields.get(name)
|
|
if item is None:
|
|
fields[name] = [value]
|
|
else:
|
|
item.append(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 load_crashes(self):
|
|
path = posixpath.join(self.server.root, 'index.html')
|
|
data = open(path).read()
|
|
problems = []
|
|
for item in kReportCrashEntryRE.finditer(data):
|
|
fieldData = item.group(1)
|
|
fields = dict([i.groups() for i in
|
|
kReportCrashEntryKeyValueRE.finditer(fieldData)])
|
|
problems.append(fields)
|
|
return problems
|
|
|
|
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 get_scalar_field(self, name):
|
|
if name in self.fields:
|
|
return self.fields[name][0]
|
|
else:
|
|
return None
|
|
|
|
def submit_bug(self, c):
|
|
title = self.get_scalar_field('title')
|
|
description = self.get_scalar_field('description')
|
|
report = self.get_scalar_field('report')
|
|
reporterIndex = self.get_scalar_field('reporter')
|
|
files = []
|
|
for fileID in self.fields.get('files',[]):
|
|
try:
|
|
i = int(fileID)
|
|
except:
|
|
i = None
|
|
if i is None or i<0 or i>=len(c.files):
|
|
return (False, 'Invalid file ID')
|
|
files.append(c.files[i])
|
|
print files
|
|
|
|
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.getParameters():
|
|
name = '%s_%s'%(reporter.getName(),o.getName())
|
|
if name not in self.fields:
|
|
return (False,
|
|
'Missing field "%s" for %s report method.'%(name,
|
|
reporter.getName()))
|
|
parameters[o.getName()] = self.get_scalar_field(name)
|
|
|
|
# Update config defaults.
|
|
if report != 'None':
|
|
self.server.config.set('ScanView', 'reporter', reporterIndex)
|
|
for o in reporter.getParameters():
|
|
name = o.getName()
|
|
self.server.config.set(reporter.getName(), name, parameters[name])
|
|
|
|
# Create the report.
|
|
bug = Reporter.BugReport(title, description, files)
|
|
|
|
# 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):
|
|
print self.fields
|
|
report = self.get_scalar_field('report')
|
|
c = self.get_report_context(report)
|
|
if c.reportSource is None:
|
|
reportingFor = "Report Crashes > "
|
|
fileBug = """\
|
|
<a href="/report_crashes">File Bug</a> > """%locals()
|
|
else:
|
|
reportingFor = '<a href="/%s">Report %s</a> > ' % (c.reportSource,
|
|
report)
|
|
fileBug = '<a href="/report/%s">File Bug</a> > ' % report
|
|
title = self.get_scalar_field('title')
|
|
description = self.get_scalar_field('description')
|
|
|
|
res,message = self.submit_bug(c)
|
|
|
|
if res:
|
|
statusClass = 'SubmitOk'
|
|
statusName = 'Succeeded'
|
|
else:
|
|
statusClass = 'SubmitFail'
|
|
statusName = 'Failed'
|
|
|
|
result = """
|
|
<head>
|
|
<title>Bug Submission</title>
|
|
<link rel="stylesheet" type="text/css" href="/scanview.css" />
|
|
</head>
|
|
<body>
|
|
<h3>
|
|
<a href="/">Summary</a> >
|
|
%(reportingFor)s
|
|
%(fileBug)s
|
|
Submit</h3>
|
|
<form name="form" action="">
|
|
<table class="form">
|
|
<tr><td>
|
|
<table class="form_group">
|
|
<tr>
|
|
<td class="form_clabel">Title:</td>
|
|
<td class="form_value">
|
|
<input type="text" name="title" size="50" value="%(title)s" disabled>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="form_label">Description:</td>
|
|
<td class="form_value">
|
|
<textarea rows="10" cols="80" name="description" disabled>
|
|
%(description)s
|
|
</textarea>
|
|
</td>
|
|
</table>
|
|
</td></tr>
|
|
</table>
|
|
</form>
|
|
<h1 class="%(statusClass)s">Submission %(statusName)s</h1>
|
|
%(message)s
|
|
<p>
|
|
<hr>
|
|
<a href="/">Return to Summary</a>
|
|
</body>
|
|
</html>"""%locals()
|
|
return self.send_string(result)
|
|
|
|
def send_open_report(self, report):
|
|
try:
|
|
keys = self.load_report(report)
|
|
except IOError:
|
|
return self.send_error(400, 'Invalid report.')
|
|
|
|
file = keys.get('FILE')
|
|
if not file or not posixpath.exists(file):
|
|
return self.send_error(400, 'File does not exist: "%s"' % file)
|
|
|
|
import startfile
|
|
if self.server.options.debug:
|
|
print >>sys.stderr, '%s: SERVER: opening "%s"'%(sys.argv[0],
|
|
file)
|
|
|
|
status = startfile.open(file)
|
|
if status:
|
|
res = 'Opened: "%s"' % file
|
|
else:
|
|
res = 'Open failed: "%s"' % file
|
|
|
|
return self.send_string(res, 'text/plain')
|
|
|
|
def get_report_context(self, report):
|
|
class Context:
|
|
pass
|
|
if report is None or report == 'None':
|
|
data = self.load_crashes()
|
|
# Don't allow empty reports.
|
|
if not data:
|
|
raise ValueError, 'No crashes detected!'
|
|
c = Context()
|
|
c.title = 'clang static analyzer failures'
|
|
|
|
stderrSummary = ""
|
|
for item in data:
|
|
if 'stderr' in item:
|
|
path = posixpath.join(self.server.root, item['stderr'])
|
|
if os.path.exists(path):
|
|
lns = itertools.islice(open(path), 0, 10)
|
|
stderrSummary += '%s\n--\n%s' % (item.get('src',
|
|
'<unknown>'),
|
|
''.join(lns))
|
|
|
|
c.description = """\
|
|
The clang static analyzer failed on these inputs:
|
|
%s
|
|
|
|
STDERR Summary
|
|
--------------
|
|
%s
|
|
""" % ('\n'.join([item.get('src','<unknown>') for item in data]),
|
|
stderrSummary)
|
|
c.reportSource = None
|
|
c.navMarkup = "Report Crashes > "
|
|
c.files = []
|
|
for item in data:
|
|
c.files.append(item.get('src',''))
|
|
c.files.append(posixpath.join(self.server.root,
|
|
item.get('file','')))
|
|
c.files.append(posixpath.join(self.server.root,
|
|
item.get('clangfile','')))
|
|
c.files.append(posixpath.join(self.server.root,
|
|
item.get('stderr','')))
|
|
c.files.append(posixpath.join(self.server.root,
|
|
item.get('info','')))
|
|
# Just in case something failed, ignore files which don't
|
|
# exist.
|
|
c.files = [f for f in c.files
|
|
if os.path.exists(f) and os.path.isfile(f)]
|
|
else:
|
|
# Check that this is a valid report.
|
|
path = posixpath.join(self.server.root, 'report-%s.html' % report)
|
|
if not posixpath.exists(path):
|
|
raise ValueError, 'Invalid report ID'
|
|
keys = self.load_report(report)
|
|
c = Context()
|
|
c.title = keys.get('DESC','clang error (unrecognized')
|
|
c.description = """\
|
|
Bug reported by the clang static analyzer.
|
|
|
|
Description: %s
|
|
File: %s
|
|
Line: %s
|
|
"""%(c.title, keys.get('FILE','<unknown>'), keys.get('LINE', '<unknown>'))
|
|
c.reportSource = 'report-%s.html' % report
|
|
c.navMarkup = """<a href="/%s">Report %s</a> > """ % (c.reportSource,
|
|
report)
|
|
|
|
c.files = [path]
|
|
return c
|
|
|
|
def send_report(self, report, configOverrides=None):
|
|
def getConfigOption(section, field):
|
|
if (configOverrides is not None and
|
|
section in configOverrides and
|
|
field in configOverrides[section]):
|
|
return configOverrides[section][field]
|
|
return self.server.config.get(section, field)
|
|
|
|
# report is None is used for crashes
|
|
try:
|
|
c = self.get_report_context(report)
|
|
except ValueError, e:
|
|
return self.send_error(400, e.message)
|
|
|
|
title = c.title
|
|
description= c.description
|
|
reportingFor = c.navMarkup
|
|
if c.reportSource is None:
|
|
extraIFrame = ""
|
|
else:
|
|
extraIFrame = """\
|
|
<iframe src="/%s" width="100%%" height="40%%"
|
|
scrolling="auto" frameborder="1">
|
|
<a href="/%s">View Bug Report</a>
|
|
</iframe>""" % (c.reportSource, c.reportSource)
|
|
|
|
reporterSelections = []
|
|
reporterOptions = []
|
|
|
|
try:
|
|
active = int(getConfigOption('ScanView','reporter'))
|
|
except:
|
|
active = 0
|
|
for i,r in enumerate(self.server.reporters):
|
|
selected = (i == active)
|
|
if selected:
|
|
selectedStr = ' selected'
|
|
else:
|
|
selectedStr = ''
|
|
reporterSelections.append('<option value="%d"%s>%s</option>'%(i,selectedStr,r.getName()))
|
|
options = '\n'.join([ o.getHTML(r,title,getConfigOption) for o in r.getParameters()])
|
|
display = ('none','')[selected]
|
|
reporterOptions.append("""\
|
|
<tr id="%sReporterOptions" style="display:%s">
|
|
<td class="form_label">%s Options</td>
|
|
<td class="form_value">
|
|
<table class="form_inner_group">
|
|
%s
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
"""%(r.getName(),display,r.getName(),options))
|
|
reporterSelections = '\n'.join(reporterSelections)
|
|
reporterOptionsDivs = '\n'.join(reporterOptions)
|
|
reportersArray = '[%s]'%(','.join([`r.getName()` for r in self.server.reporters]))
|
|
|
|
if c.files:
|
|
fieldSize = min(5, len(c.files))
|
|
attachFileOptions = '\n'.join(["""\
|
|
<option value="%d" selected>%s</option>""" % (i,v) for i,v in enumerate(c.files)])
|
|
attachFileRow = """\
|
|
<tr>
|
|
<td class="form_label">Attach:</td>
|
|
<td class="form_value">
|
|
<select style="width:100%%" name="files" multiple size=%d>
|
|
%s
|
|
</select>
|
|
</td>
|
|
</tr>
|
|
""" % (min(5, len(c.files)), attachFileOptions)
|
|
else:
|
|
attachFileRow = ""
|
|
|
|
result = """<html>
|
|
<head>
|
|
<title>File Bug</title>
|
|
<link rel="stylesheet" type="text/css" href="/scanview.css" />
|
|
</head>
|
|
<script language="javascript" type="text/javascript">
|
|
var reporters = %(reportersArray)s;
|
|
function updateReporterOptions() {
|
|
index = document.getElementById('reporter').selectedIndex;
|
|
for (var i=0; i < reporters.length; ++i) {
|
|
o = document.getElementById(reporters[i] + "ReporterOptions");
|
|
if (i == index) {
|
|
o.style.display = "";
|
|
} else {
|
|
o.style.display = "none";
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<body onLoad="updateReporterOptions()">
|
|
<h3>
|
|
<a href="/">Summary</a> >
|
|
%(reportingFor)s
|
|
File Bug</h3>
|
|
<form name="form" action="/report_submit" method="post">
|
|
<input type="hidden" name="report" value="%(report)s">
|
|
|
|
<table class="form">
|
|
<tr><td>
|
|
<table class="form_group">
|
|
<tr>
|
|
<td class="form_clabel">Title:</td>
|
|
<td class="form_value">
|
|
<input type="text" name="title" size="50" value="%(title)s">
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="form_label">Description:</td>
|
|
<td class="form_value">
|
|
<textarea rows="10" cols="80" name="description">
|
|
%(description)s
|
|
</textarea>
|
|
</td>
|
|
</tr>
|
|
|
|
%(attachFileRow)s
|
|
|
|
</table>
|
|
<br>
|
|
<table class="form_group">
|
|
<tr>
|
|
<td class="form_clabel">Method:</td>
|
|
<td class="form_value">
|
|
<select id="reporter" name="reporter" onChange="updateReporterOptions()">
|
|
%(reporterSelections)s
|
|
</select>
|
|
</td>
|
|
</tr>
|
|
%(reporterOptionsDivs)s
|
|
</table>
|
|
<br>
|
|
</td></tr>
|
|
<tr><td class="form_submit">
|
|
<input align="right" type="submit" name="Submit" value="Submit">
|
|
</td></tr>
|
|
</table>
|
|
</form>
|
|
|
|
%(extraIFrame)s
|
|
|
|
</body>
|
|
</html>"""%locals()
|
|
|
|
return self.send_string(result)
|
|
|
|
def send_head(self, fields=None):
|
|
if (self.server.options.onlyServeLocal and
|
|
self.client_address[0] != '127.0.0.1'):
|
|
return self.send_error('401', 'Unauthorized host.')
|
|
|
|
if fields is None:
|
|
fields = {}
|
|
self.fields = fields
|
|
|
|
o = urlparse.urlparse(self.path)
|
|
self.fields = parse_query(o.query, fields)
|
|
path = posixpath.normpath(urllib.unquote(o.path))
|
|
|
|
# Split the components and strip the root prefix.
|
|
components = path.split('/')[1:]
|
|
|
|
# Special case some top-level entries.
|
|
if components:
|
|
name = components[0]
|
|
if len(components)==2:
|
|
if name=='report':
|
|
return self.send_report(components[1])
|
|
elif name=='open':
|
|
return self.send_open_report(components[1])
|
|
elif len(components)==1:
|
|
if name=='quit':
|
|
self.server.halt()
|
|
return self.send_string('Goodbye.', 'text/plain')
|
|
elif name=='report_submit':
|
|
return self.send_report_submit()
|
|
elif name=='report_crashes':
|
|
overrides = { 'ScanView' : {},
|
|
'Radar' : {},
|
|
'Email' : {} }
|
|
for i,r in enumerate(self.server.reporters):
|
|
if r.getName() == 'Radar':
|
|
overrides['ScanView']['reporter'] = i
|
|
break
|
|
overrides['Radar']['Component'] = 'llvm - checker'
|
|
overrides['Radar']['Component Version'] = 'X'
|
|
return self.send_report(None, overrides)
|
|
elif name=='favicon.ico':
|
|
return self.send_path(posixpath.join(kResources,'bugcatcher.ico'))
|
|
|
|
# Match directory entries.
|
|
if components[-1] == '':
|
|
components[-1] = 'index.html'
|
|
|
|
suffix = '/'.join(components)
|
|
|
|
# The summary may reference source files on disk using rooted
|
|
# paths. Make sure these resolve correctly for now.
|
|
# FIXME: This isn't a very good idea... we should probably
|
|
# mark rooted paths somehow.
|
|
if os.path.exists(posixpath.join('/', suffix)):
|
|
path = posixpath.join('/', suffix)
|
|
else:
|
|
path = posixpath.join(self.server.root, suffix)
|
|
|
|
if self.server.options.debug > 1:
|
|
print >>sys.stderr, '%s: SERVER: sending path "%s"'%(sys.argv[0],
|
|
path)
|
|
return self.send_path(path)
|
|
|
|
def send_404(self):
|
|
self.send_error(404, "File not found")
|
|
return None
|
|
|
|
def send_path(self, path):
|
|
ctype = self.guess_type(path)
|
|
if ctype.startswith('text/'):
|
|
# Patch file instead
|
|
return self.send_patched_file(path, ctype)
|
|
else:
|
|
mode = 'rb'
|
|
try:
|
|
f = open(path, mode)
|
|
except IOError:
|
|
return self.send_404()
|
|
return self.send_file(f, ctype)
|
|
|
|
def send_file(self, f, ctype):
|
|
# Patch files to add links, but skip binary files.
|
|
self.send_response(200)
|
|
self.send_header("Content-type", ctype)
|
|
fs = os.fstat(f.fileno())
|
|
self.send_header("Content-Length", str(fs[6]))
|
|
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
|
|
self.end_headers()
|
|
return f
|
|
|
|
def send_string(self, s, ctype='text/html', headers=True, mtime=None):
|
|
if headers:
|
|
self.send_response(200)
|
|
self.send_header("Content-type", ctype)
|
|
self.send_header("Content-Length", str(len(s)))
|
|
if mtime is None:
|
|
mtime = self.dynamic_mtime
|
|
self.send_header("Last-Modified", self.date_time_string(mtime))
|
|
self.end_headers()
|
|
return StringIO.StringIO(s)
|
|
|
|
def send_patched_file(self, path, ctype):
|
|
# Allow a very limited set of variables. This is pretty gross.
|
|
variables = {}
|
|
variables['report'] = ''
|
|
m = kReportFileRE.match(path)
|
|
if m:
|
|
variables['report'] = m.group(2)
|
|
|
|
try:
|
|
f = open(path,'r')
|
|
except IOError:
|
|
return self.send_404()
|
|
fs = os.fstat(f.fileno())
|
|
data = f.read()
|
|
for a,b in kReportReplacements:
|
|
data = a.sub(b % variables, data)
|
|
return self.send_string(data, ctype, mtime=fs.st_mtime)
|
|
|
|
|
|
def create_server(address, options, root):
|
|
import Reporter
|
|
|
|
reporters = Reporter.getReporters()
|
|
|
|
return ScanViewServer(address, ScanViewRequestHandler,
|
|
root,
|
|
reporters,
|
|
options)
|