1e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarimport BaseHTTPServer
2e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarimport SimpleHTTPServer
3e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarimport os
4e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarimport sys
5e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarimport urllib, urlparse
6e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarimport posixpath
7e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarimport StringIO
8e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarimport re
9e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarimport shutil
10e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarimport threading
11e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarimport time
12e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarimport socket
137ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbarimport itertools
14e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
155472249ee4281673c63db466c8670f269803469aDaniel Dunbarimport Reporter
168dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbarimport ConfigParser
17e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
1817fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar###
1917fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar# Various patterns matched or replaced by server.
2017fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar
2117fded63f9dba691d517f5c6952344d87d6338bfDaniel DunbarkReportFileRE = re.compile('(.*/)?report-(.*)\\.html')
22e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
23e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel DunbarkBugKeyValueRE = re.compile('<!-- BUG([^ ]*) (.*) -->')
24e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
257ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar#  <!-- REPORTPROBLEM file="crashes/clang_crash_ndSGF9.mi" stderr="crashes/clang_crash_ndSGF9.mi.stderr.txt" info="crashes/clang_crash_ndSGF9.mi.info" -->
267ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
277ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel DunbarkReportCrashEntryRE = re.compile('<!-- REPORTPROBLEM (.*?)-->')
287ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel DunbarkReportCrashEntryKeyValueRE = re.compile(' ?([^=]+)="(.*?)"')
297ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
304d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel DunbarkReportReplacements = []
31cb028b0180b38c7d0404acb936d276ff050061c6Daniel Dunbar
324d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar# Add custom javascript.
334d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel DunbarkReportReplacements.append((re.compile('<!-- SUMMARYENDHEAD -->'), """\
344d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar<script language="javascript" type="text/javascript">
354d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbarfunction load(url) {
364d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar  if (window.XMLHttpRequest) {
374d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar    req = new XMLHttpRequest();
384d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar  } else if (window.ActiveXObject) {
394d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar    req = new ActiveXObject("Microsoft.XMLHTTP");
404d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar  }
414d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar  if (req != undefined) {
424d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar    req.open("GET", url, true);
434d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar    req.send("");
444d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar  }
454d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar}
464d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar</script>"""))
474d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar
484d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar# Insert additional columns.
494d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel DunbarkReportReplacements.append((re.compile('<!-- REPORTBUGCOL -->'),
504d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar                            '<td></td><td></td>'))
514d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar
524d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar# Insert report bug and open file links.
534d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel DunbarkReportReplacements.append((re.compile('<!-- REPORTBUG id="report-(.*)\\.html" -->'),
544d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar                            ('<td class="Button"><a href="report/\\1">Report Bug</a></td>' +
554d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar                             '<td class="Button"><a href="javascript:load(\'open/\\1\')">Open File</a></td>')))
564d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar
5717fded63f9dba691d517f5c6952344d87d6338bfDaniel DunbarkReportReplacements.append((re.compile('<!-- REPORTHEADER -->'),
5817fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar                                       '<h3><a href="/">Summary</a> > Report %(report)s</h3>'))
5917fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar
6017fded63f9dba691d517f5c6952344d87d6338bfDaniel DunbarkReportReplacements.append((re.compile('<!-- REPORTSUMMARYEXTRA -->'),
6117fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar                            '<td class="Button"><a href="report/%(report)s">Report Bug</a></td>'))
6217fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar
637ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar# Insert report crashes link.
647ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
65b5f9a4ea171931a2092aa466046251629c75e65bDaniel Dunbar# Disabled for the time being until we decide exactly when this should
66b5f9a4ea171931a2092aa466046251629c75e65bDaniel Dunbar# be enabled. Also the radar reporter needs to be fixed to report
67b5f9a4ea171931a2092aa466046251629c75e65bDaniel Dunbar# multiple files.
68b5f9a4ea171931a2092aa466046251629c75e65bDaniel Dunbar
69b5f9a4ea171931a2092aa466046251629c75e65bDaniel Dunbar#kReportReplacements.append((re.compile('<!-- REPORTCRASHES -->'),
70b5f9a4ea171931a2092aa466046251629c75e65bDaniel Dunbar#                            '<br>These files will automatically be attached to ' +
71b5f9a4ea171931a2092aa466046251629c75e65bDaniel Dunbar#                            'reports filed here: <a href="report_crashes">Report Crashes</a>.'))
727ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
734d20cf759d96ac194ae27aa81cb127cd0619d0ddDaniel Dunbar###
74b131c8ac7cc429416a2d6aaa0baccb2336883accDaniel Dunbar# Other simple parameters
75b131c8ac7cc429416a2d6aaa0baccb2336883accDaniel Dunbar
76b131c8ac7cc429416a2d6aaa0baccb2336883accDaniel DunbarkResources = posixpath.join(posixpath.dirname(__file__), 'Resources')
778dcd940c0f00530e0e8ca55be1193382e80227caDaniel DunbarkConfigPath = os.path.expanduser('~/.scanview.cfg')
78b131c8ac7cc429416a2d6aaa0baccb2336883accDaniel Dunbar
79e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar###
80e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
81e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar__version__ = "0.1"
82e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
83e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar__all__ = ["create_server"]
84e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
85e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarclass ReporterThread(threading.Thread):
86e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def __init__(self, report, reporter, parameters, server):
87e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        threading.Thread.__init__(self)
88e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.report = report
89e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.server = server
90e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.reporter = reporter
91e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.parameters = parameters
9247cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar        self.success = False
93e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.status = None
94e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
95e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def run(self):
96e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        result = None
97e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        try:
98e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            if self.server.options.debug:
99e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                print >>sys.stderr, "%s: SERVER: submitting bug."%(sys.argv[0],)
10047cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar            self.status = self.reporter.fileReport(self.report, self.parameters)
10147cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar            self.success = True
102e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            time.sleep(3)
103e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            if self.server.options.debug:
104e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                print >>sys.stderr, "%s: SERVER: submission complete."%(sys.argv[0],)
1055472249ee4281673c63db466c8670f269803469aDaniel Dunbar        except Reporter.ReportFailure,e:
10647cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar            self.status = e.value
107e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        except Exception,e:
108e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            s = StringIO.StringIO()
109e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            import traceback
11047cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar            print >>s,'<b>Unhandled Exception</b><br><pre>'
111e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            traceback.print_exc(e,file=s)
112e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            print >>s,'</pre>'
113e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            self.status = s.getvalue()
114e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
115e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarclass ScanViewServer(BaseHTTPServer.HTTPServer):
116e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def __init__(self, address, handler, root, reporters, options):
117e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        BaseHTTPServer.HTTPServer.__init__(self, address, handler)
118e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.root = root
119e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.reporters = reporters
120e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.options = options
121e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.halted = False
1228dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        self.config = None
1238dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        self.load_config()
124e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
1258dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar    def load_config(self):
1268dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        self.config = ConfigParser.RawConfigParser()
1278dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar
1288dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        # Add defaults
1298dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        self.config.add_section('ScanView')
1307ad535db066b6f5e31776f8a74b8f1e98b14cc7eDaniel Dunbar        for r in self.reporters:
1318dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            self.config.add_section(r.getName())
13219c8820134605ee6cc72a18624e56041952e9ae4Ted Kremenek            for p in r.getParameters():
133480bc342cd48896828dcf7443411e59d67aeb2aaTed Kremenek              if p.saveConfigValue():
13419c8820134605ee6cc72a18624e56041952e9ae4Ted Kremenek                self.config.set(r.getName(), p.getName(), '')
1358dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar
1368dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        # Ignore parse errors
1378dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        try:
1388dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            self.config.read([kConfigPath])
1398dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        except:
1408dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            pass
1418dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar
1428dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        # Save on exit
1438dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        import atexit
1448dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        atexit.register(lambda: self.save_config())
1458dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar
1468dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar    def save_config(self):
1478dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        # Ignore errors (only called on exit).
1488dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        try:
1498dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            f = open(kConfigPath,'w')
1508dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            self.config.write(f)
1518dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            f.close()
1528dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        except:
1538dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            pass
1548dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar
155e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def halt(self):
156e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.halted = True
157e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        if self.options.debug:
158e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            print >>sys.stderr, "%s: SERVER: halting." % (sys.argv[0],)
159e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
160e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def serve_forever(self):
161e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        while not self.halted:
162e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            if self.options.debug > 1:
163e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                print >>sys.stderr, "%s: SERVER: waiting..." % (sys.argv[0],)
164e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            try:
165e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                self.handle_request()
166e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            except OSError,e:
167e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                print 'OSError',e.errno
168e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
169cb028b0180b38c7d0404acb936d276ff050061c6Daniel Dunbar    def finish_request(self, request, client_address):
170cb028b0180b38c7d0404acb936d276ff050061c6Daniel Dunbar        if self.options.autoReload:
171cb028b0180b38c7d0404acb936d276ff050061c6Daniel Dunbar            import ScanView
172cb028b0180b38c7d0404acb936d276ff050061c6Daniel Dunbar            self.RequestHandlerClass = reload(ScanView).ScanViewRequestHandler
173cb028b0180b38c7d0404acb936d276ff050061c6Daniel Dunbar        BaseHTTPServer.HTTPServer.finish_request(self, request, client_address)
174cb028b0180b38c7d0404acb936d276ff050061c6Daniel Dunbar
175e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def handle_error(self, request, client_address):
176e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        # Ignore socket errors
177e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        info = sys.exc_info()
178e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        if info and isinstance(info[1], socket.error):
179e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            if self.options.debug > 1:
180e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                print >>sys.stderr, "%s: SERVER: ignored socket error." % (sys.argv[0],)
181e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            return
182cb028b0180b38c7d0404acb936d276ff050061c6Daniel Dunbar        BaseHTTPServer.HTTPServer.handle_error(self, request, client_address)
183e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
184e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar# Borrowed from Quixote, with simplifications.
185e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbardef parse_query(qs, fields=None):
186e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    if fields is None:
187e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        fields = {}
188e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    for chunk in filter(None, qs.split('&')):
189e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        if '=' not in chunk:
190e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            name = chunk
191e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            value = ''
192e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        else:
193e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            name, value = chunk.split('=', 1)
194e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        name = urllib.unquote(name.replace('+', ' '))
195e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        value = urllib.unquote(value.replace('+', ' '))
1967ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        item = fields.get(name)
1977ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        if item is None:
1987ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            fields[name] = [value]
1997ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        else:
2007ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            item.append(value)
201e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    return fields
202e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
203e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarclass ScanViewRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
204e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    server_version = "ScanViewServer/" + __version__
205cb028b0180b38c7d0404acb936d276ff050061c6Daniel Dunbar    dynamic_mtime = time.time()
206e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
207e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def do_HEAD(self):
208e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        try:
209e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            SimpleHTTPServer.SimpleHTTPRequestHandler.do_HEAD(self)
210e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        except Exception,e:
211e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            self.handle_exception(e)
212e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
213e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def do_GET(self):
214e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        try:
215e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
216e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        except Exception,e:
217e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            self.handle_exception(e)
218e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
219e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def do_POST(self):
220e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        """Serve a POST request."""
221e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        try:
222e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            length = self.headers.getheader('content-length') or "0"
223e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            try:
224e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                length = int(length)
225e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            except:
226e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                length = 0
227e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            content = self.rfile.read(length)
228e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            fields = parse_query(content)
229e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            f = self.send_head(fields)
230e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            if f:
231e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                self.copyfile(f, self.wfile)
232e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                f.close()
233e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        except Exception,e:
234e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            self.handle_exception(e)
235e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
236e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def log_message(self, format, *args):
237e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        if self.server.options.debug:
238e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            sys.stderr.write("%s: SERVER: %s - - [%s] %s\n" %
239e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                             (sys.argv[0],
240e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                              self.address_string(),
241e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                              self.log_date_time_string(),
242e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                              format%args))
243e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
244e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def load_report(self, report):
245e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        path = os.path.join(self.server.root, 'report-%s.html'%report)
246e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        data = open(path).read()
247e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        keys = {}
248e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        for item in kBugKeyValueRE.finditer(data):
249e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            k,v = item.groups()
250e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            keys[k] = v
251e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        return keys
252e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
2537ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar    def load_crashes(self):
2547ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        path = posixpath.join(self.server.root, 'index.html')
2557ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        data = open(path).read()
2567ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        problems = []
2577ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        for item in kReportCrashEntryRE.finditer(data):
2587ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            fieldData = item.group(1)
2597ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            fields = dict([i.groups() for i in
2607ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                           kReportCrashEntryKeyValueRE.finditer(fieldData)])
2617ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            problems.append(fields)
2627ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        return problems
2637ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
264e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def handle_exception(self, exc):
265e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        import traceback
266e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        s = StringIO.StringIO()
267e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        print >>s, "INTERNAL ERROR\n"
268e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        traceback.print_exc(exc, s)
269e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        f = self.send_string(s.getvalue(), 'text/plain')
270e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        if f:
271e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            self.copyfile(f, self.wfile)
272e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            f.close()
2737ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
2747ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar    def get_scalar_field(self, name):
2757ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        if name in self.fields:
2767ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            return self.fields[name][0]
2777ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        else:
2787ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            return None
2797ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
2807ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar    def submit_bug(self, c):
2817ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        title = self.get_scalar_field('title')
2827ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        description = self.get_scalar_field('description')
2837ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        report = self.get_scalar_field('report')
2847ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        reporterIndex = self.get_scalar_field('reporter')
2857ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        files = []
2867ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        for fileID in self.fields.get('files',[]):
2877ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            try:
2887ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                i = int(fileID)
2897ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            except:
2907ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                i = None
2917ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            if i is None or i<0 or i>=len(c.files):
2927ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                return (False, 'Invalid file ID')
2937ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            files.append(c.files[i])
2947ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
29547cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar        if not title:
29647cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar            return (False, "Missing title.")
29747cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar        if not description:
29847cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar            return (False, "Missing description.")
29947cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar        try:
3008dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            reporterIndex = int(reporterIndex)
30147cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar        except:
30247cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar            return (False, "Invalid report method.")
303e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
304e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        # Get the reporter and parameters.
3058dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        reporter = self.server.reporters[reporterIndex]
306e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        parameters = {}
30719c8820134605ee6cc72a18624e56041952e9ae4Ted Kremenek        for o in reporter.getParameters():
30819c8820134605ee6cc72a18624e56041952e9ae4Ted Kremenek            name = '%s_%s'%(reporter.getName(),o.getName())
30947cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar            if name not in self.fields:
31047cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar                return (False,
31147cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar                        'Missing field "%s" for %s report method.'%(name,
31247cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar                                                                    reporter.getName()))
31319c8820134605ee6cc72a18624e56041952e9ae4Ted Kremenek            parameters[o.getName()] = self.get_scalar_field(name)
314e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
3158dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        # Update config defaults.
3167ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        if report != 'None':
3177ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            self.server.config.set('ScanView', 'reporter', reporterIndex)
31819c8820134605ee6cc72a18624e56041952e9ae4Ted Kremenek            for o in reporter.getParameters():
319480bc342cd48896828dcf7443411e59d67aeb2aaTed Kremenek              if o.saveConfigValue():
32019c8820134605ee6cc72a18624e56041952e9ae4Ted Kremenek                name = o.getName()
32119c8820134605ee6cc72a18624e56041952e9ae4Ted Kremenek                self.server.config.set(reporter.getName(), name, parameters[name])
3228dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar
323e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        # Create the report.
3247ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        bug = Reporter.BugReport(title, description, files)
325e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
326e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        # Kick off a reporting thread.
32747cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar        t = ReporterThread(bug, reporter, parameters, self.server)
328e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        t.start()
329e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
330e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        # Wait for thread to die...
331e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        while t.isAlive():
332e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            time.sleep(.25)
333e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        submitStatus = t.status
334e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
33547cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar        return (t.success, t.status)
33647cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar
33747cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar    def send_report_submit(self):
3387ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        report = self.get_scalar_field('report')
3397ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        c = self.get_report_context(report)
3407ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        if c.reportSource is None:
3417ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            reportingFor = "Report Crashes > "
3427ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            fileBug = """\
3437ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar<a href="/report_crashes">File Bug</a> > """%locals()
3447ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        else:
3457ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            reportingFor = '<a href="/%s">Report %s</a> > ' % (c.reportSource,
3467ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                                                                   report)
3477ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            fileBug = '<a href="/report/%s">File Bug</a> > ' % report
3487ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        title = self.get_scalar_field('title')
3497ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        description = self.get_scalar_field('description')
35047cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar
3517ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        res,message = self.submit_bug(c)
35247cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar
35347cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar        if res:
35447cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar            statusClass = 'SubmitOk'
35547cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar            statusName = 'Succeeded'
35647cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar        else:
35747cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar            statusClass = 'SubmitFail'
35847cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar            statusName = 'Failed'
35947cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar
36047cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar        result = """
36147cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar<head>
362c2dd3459fede8e963e2e84a02d3083c4bc53c469Daniel Dunbar  <title>Bug Submission</title>
36347cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar  <link rel="stylesheet" type="text/css" href="/scanview.css" />
36447cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar</head>
36547cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar<body>
366c2dd3459fede8e963e2e84a02d3083c4bc53c469Daniel Dunbar<h3>
367c2dd3459fede8e963e2e84a02d3083c4bc53c469Daniel Dunbar<a href="/">Summary</a> >
3687ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar%(reportingFor)s
3697ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar%(fileBug)s
370c2dd3459fede8e963e2e84a02d3083c4bc53c469Daniel DunbarSubmit</h3>
37147cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar<form name="form" action="">
37247cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar<table class="form">
37347cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar<tr><td>
37447cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar<table class="form_group">
37547cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar<tr>
37647cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar  <td class="form_clabel">Title:</td>
37747cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar  <td class="form_value">
37847cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar    <input type="text" name="title" size="50" value="%(title)s" disabled>
37947cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar  </td>
38047cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar</tr>
38147cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar<tr>
38247cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar  <td class="form_label">Description:</td>
38347cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar  <td class="form_value">
38447cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar<textarea rows="10" cols="80" name="description" disabled>
38547cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar%(description)s
38647cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar</textarea>
38747cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar  </td>
38847cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar</table>
38947cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar</td></tr>
39047cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar</table>
39147cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar</form>
39247cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar<h1 class="%(statusClass)s">Submission %(statusName)s</h1>
39347cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar%(message)s
39447cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar<p>
395e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar<hr>
39647cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar<a href="/">Return to Summary</a>
397e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar</body>
39847cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar</html>"""%locals()
39947cceff13c109963735f3462f1226a8ae74a864bDaniel Dunbar        return self.send_string(result)
400e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
40128870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar    def send_open_report(self, report):
40228870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar        try:
40328870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar            keys = self.load_report(report)
40428870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar        except IOError:
40528870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar            return self.send_error(400, 'Invalid report.')
40628870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar
40728870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar        file = keys.get('FILE')
40828870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar        if not file or not posixpath.exists(file):
40928870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar            return self.send_error(400, 'File does not exist: "%s"' % file)
41028870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar
41128870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar        import startfile
41228870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar        if self.server.options.debug:
41328870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar            print >>sys.stderr, '%s: SERVER: opening "%s"'%(sys.argv[0],
41428870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar                                                            file)
41528870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar
41628870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar        status = startfile.open(file)
41728870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar        if status:
41828870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar            res = 'Opened: "%s"' % file
41928870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar        else:
42028870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar            res = 'Open failed: "%s"' % file
42128870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar
42228870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar        return self.send_string(res, 'text/plain')
42328870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar
4247ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar    def get_report_context(self, report):
4257ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        class Context:
4267ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            pass
4277ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        if report is None or report == 'None':
4287ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            data = self.load_crashes()
4297ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            # Don't allow empty reports.
4307ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            if not data:
4317ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                raise ValueError, 'No crashes detected!'
4327ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c = Context()
4337ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c.title = 'clang static analyzer failures'
4347ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
4357ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            stderrSummary = ""
4367ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            for item in data:
4377ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                if 'stderr' in item:
4387ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                    path = posixpath.join(self.server.root, item['stderr'])
4397ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                    if os.path.exists(path):
4407ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                        lns = itertools.islice(open(path), 0, 10)
4417ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                        stderrSummary += '%s\n--\n%s' % (item.get('src',
4427ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                                                                  '<unknown>'),
4437ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                                                         ''.join(lns))
4447ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
4457ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c.description = """\
4467ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel DunbarThe clang static analyzer failed on these inputs:
4477ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar%s
448e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
4497ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel DunbarSTDERR Summary
4507ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar--------------
4517ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar%s
4527ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar""" % ('\n'.join([item.get('src','<unknown>') for item in data]),
4537ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar       stderrSummary)
4547ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c.reportSource = None
4557ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c.navMarkup = "Report Crashes > "
4567ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c.files = []
4577ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            for item in data:
4587ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                c.files.append(item.get('src',''))
4597ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                c.files.append(posixpath.join(self.server.root,
4607ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                                              item.get('file','')))
4617ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                c.files.append(posixpath.join(self.server.root,
4627ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                                              item.get('clangfile','')))
4637ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                c.files.append(posixpath.join(self.server.root,
4647ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                                              item.get('stderr','')))
4657ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                c.files.append(posixpath.join(self.server.root,
4667ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                                              item.get('info','')))
4677ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            # Just in case something failed, ignore files which don't
4687ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            # exist.
4697ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c.files = [f for f in c.files
4707ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                       if os.path.exists(f) and os.path.isfile(f)]
4717ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        else:
4727ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            # Check that this is a valid report.
4737ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            path = posixpath.join(self.server.root, 'report-%s.html' % report)
4747ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            if not posixpath.exists(path):
4757ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                raise ValueError, 'Invalid report ID'
4767ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            keys = self.load_report(report)
4777ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c = Context()
4787ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c.title = keys.get('DESC','clang error (unrecognized')
4797ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c.description = """\
4807ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel DunbarBug reported by the clang static analyzer.
48125b51d06991ee3b60a24ba5d303973794401d527Daniel Dunbar
48225b51d06991ee3b60a24ba5d303973794401d527Daniel DunbarDescription: %s
48325b51d06991ee3b60a24ba5d303973794401d527Daniel DunbarFile: %s
48425b51d06991ee3b60a24ba5d303973794401d527Daniel DunbarLine: %s
4857ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar"""%(c.title, keys.get('FILE','<unknown>'), keys.get('LINE', '<unknown>'))
4867ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c.reportSource = 'report-%s.html' % report
4877ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c.navMarkup = """<a href="/%s">Report %s</a> > """ % (c.reportSource,
4887ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                                                                  report)
4897ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
4907ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c.files = [path]
4917ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        return c
4927ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
4937ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar    def send_report(self, report, configOverrides=None):
4947ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        def getConfigOption(section, field):
4957ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            if (configOverrides is not None and
4967ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                section in configOverrides and
4977ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                field in configOverrides[section]):
4987ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                return configOverrides[section][field]
4997ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            return self.server.config.get(section, field)
5007ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
5017ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        # report is None is used for crashes
5027ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        try:
5037ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            c = self.get_report_context(report)
5047ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        except ValueError, e:
5057ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            return self.send_error(400, e.message)
5067ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
5077ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        title = c.title
5087ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        description= c.description
5097ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        reportingFor = c.navMarkup
5107ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        if c.reportSource is None:
5117ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            extraIFrame = ""
5127ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        else:
5137ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            extraIFrame = """\
5147ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar<iframe src="/%s" width="100%%" height="40%%"
5157ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        scrolling="auto" frameborder="1">
5167ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar  <a href="/%s">View Bug Report</a>
5177ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar</iframe>""" % (c.reportSource, c.reportSource)
518e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
519e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        reporterSelections = []
520e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        reporterOptions = []
5217ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
5228dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        try:
5237ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            active = int(getConfigOption('ScanView','reporter'))
5248dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar        except:
5258dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            active = 0
526e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        for i,r in enumerate(self.server.reporters):
5278dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            selected = (i == active)
5288dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            if selected:
5298dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar                selectedStr = ' selected'
5308dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            else:
5318dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar                selectedStr = ''
5328dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            reporterSelections.append('<option value="%d"%s>%s</option>'%(i,selectedStr,r.getName()))
53319c8820134605ee6cc72a18624e56041952e9ae4Ted Kremenek            options = '\n'.join([ o.getHTML(r,title,getConfigOption) for o in r.getParameters()])
5348dcd940c0f00530e0e8ca55be1193382e80227caDaniel Dunbar            display = ('none','')[selected]
53578266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar            reporterOptions.append("""\
53678266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar<tr id="%sReporterOptions" style="display:%s">
53778266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  <td class="form_label">%s Options</td>
53878266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  <td class="form_value">
53978266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar    <table class="form_inner_group">
54078266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar%s
54178266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar    </table>
54278266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  </td>
54378266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar</tr>
54478266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar"""%(r.getName(),display,r.getName(),options))
545e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        reporterSelections = '\n'.join(reporterSelections)
546e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        reporterOptionsDivs = '\n'.join(reporterOptions)
547e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        reportersArray = '[%s]'%(','.join([`r.getName()` for r in self.server.reporters]))
548e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
5497ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        if c.files:
5507ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            fieldSize = min(5, len(c.files))
5517ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            attachFileOptions = '\n'.join(["""\
5527ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar<option value="%d" selected>%s</option>""" % (i,v) for i,v in enumerate(c.files)])
5537ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            attachFileRow = """\
5547ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar<tr>
5557ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar  <td class="form_label">Attach:</td>
5567ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar  <td class="form_value">
5577ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar<select style="width:100%%" name="files" multiple size=%d>
5587ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar%s
5597ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar</select>
5607ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar  </td>
5617ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar</tr>
5627ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar""" % (min(5, len(c.files)), attachFileOptions)
5637ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar        else:
5647ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar            attachFileRow = ""
5657ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
566e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        result = """<html>
567e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar<head>
568c2dd3459fede8e963e2e84a02d3083c4bc53c469Daniel Dunbar  <title>File Bug</title>
56978266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  <link rel="stylesheet" type="text/css" href="/scanview.css" />
570e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar</head>
571e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar<script language="javascript" type="text/javascript">
572e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarvar reporters = %(reportersArray)s;
573e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbarfunction updateReporterOptions() {
574e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar  index = document.getElementById('reporter').selectedIndex;
575e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar  for (var i=0; i < reporters.length; ++i) {
576e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    o = document.getElementById(reporters[i] + "ReporterOptions");
577e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    if (i == index) {
57878266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar      o.style.display = "";
579e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    } else {
580e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar      o.style.display = "none";
581e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    }
582e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar  }
583e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar}
584e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar</script>
5857345e4782e1218255cad13e7bab5f8104463500dDaniel Dunbar<body onLoad="updateReporterOptions()">
586c2dd3459fede8e963e2e84a02d3083c4bc53c469Daniel Dunbar<h3>
587c2dd3459fede8e963e2e84a02d3083c4bc53c469Daniel Dunbar<a href="/">Summary</a> >
5887ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar%(reportingFor)s
589c2dd3459fede8e963e2e84a02d3083c4bc53c469Daniel DunbarFile Bug</h3>
590e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar<form name="form" action="/report_submit" method="post">
59178266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar<input type="hidden" name="report" value="%(report)s">
59278266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar
59378266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar<table class="form">
59478266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar<tr><td>
59578266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar<table class="form_group">
59678266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar<tr>
59778266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  <td class="form_clabel">Title:</td>
59878266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  <td class="form_value">
5997ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar    <input type="text" name="title" size="50" value="%(title)s">
60078266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  </td>
60178266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar</tr>
60278266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar<tr>
60378266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  <td class="form_label">Description:</td>
60478266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  <td class="form_value">
605e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar<textarea rows="10" cols="80" name="description">
6067ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar%(description)s
60778266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar</textarea>
60878266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  </td>
6097ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar</tr>
6107ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
6117ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar%(attachFileRow)s
6127ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
61378266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar</table>
61478266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar<br>
61578266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar<table class="form_group">
61678266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar<tr>
61778266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  <td class="form_clabel">Method:</td>
61878266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  <td class="form_value">
61978266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar    <select id="reporter" name="reporter" onChange="updateReporterOptions()">
62078266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar    %(reporterSelections)s
62178266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar    </select>
62278266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  </td>
62378266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar</tr>
624e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar%(reporterOptionsDivs)s
62578266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar</table>
62678266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar<br>
62778266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar</td></tr>
62878266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar<tr><td class="form_submit">
62978266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar  <input align="right" type="submit" name="Submit" value="Submit">
63078266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar</td></tr>
63178266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar</table>
632e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar</form>
63325b51d06991ee3b60a24ba5d303973794401d527Daniel Dunbar
6347ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar%(extraIFrame)s
63525b51d06991ee3b60a24ba5d303973794401d527Daniel Dunbar
636e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar</body>
637e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar</html>"""%locals()
6387ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar
639e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        return self.send_string(result)
640e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
641e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def send_head(self, fields=None):
642f6a415fe4735debe6398aae241b873e332ada0dbDaniel Dunbar        if (self.server.options.onlyServeLocal and
643f6a415fe4735debe6398aae241b873e332ada0dbDaniel Dunbar            self.client_address[0] != '127.0.0.1'):
64457cbb0de091a05a6510f0a7278ee8da57a4d27fcTed Kremenek            return self.send_error(401, 'Unauthorized host.')
645f6a415fe4735debe6398aae241b873e332ada0dbDaniel Dunbar
646e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        if fields is None:
647e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            fields = {}
648e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.fields = fields
649e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
650e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        o = urlparse.urlparse(self.path)
651e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.fields = parse_query(o.query, fields)
652e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        path = posixpath.normpath(urllib.unquote(o.path))
653e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
654e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        # Split the components and strip the root prefix.
655e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        components = path.split('/')[1:]
656e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
657e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        # Special case some top-level entries.
658e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        if components:
659e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            name = components[0]
66078266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar            if len(components)==2:
66178266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar                if name=='report':
662e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                    return self.send_report(components[1])
66328870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar                elif name=='open':
66428870e141a2467c838d0554570904bcf53481b1cDaniel Dunbar                    return self.send_open_report(components[1])
66578266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar            elif len(components)==1:
66678266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar                if name=='quit':
66778266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar                    self.server.halt()
66878266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar                    return self.send_string('Goodbye.', 'text/plain')
66978266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar                elif name=='report_submit':
670e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                    return self.send_report_submit()
6717ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                elif name=='report_crashes':
6727ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                    overrides = { 'ScanView' : {},
6737ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                                  'Radar' : {},
6747ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                                  'Email' : {} }
6757ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                    for i,r in enumerate(self.server.reporters):
6767ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                        if r.getName() == 'Radar':
6777ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                            overrides['ScanView']['reporter'] = i
6787ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                            break
6797ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                    overrides['Radar']['Component'] = 'llvm - checker'
6807ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                    overrides['Radar']['Component Version'] = 'X'
6817ebe0ed4443428b47f04f97c86c78c1ba775cedbDaniel Dunbar                    return self.send_report(None, overrides)
68278266296fd201f0766b7e79319151bb4f9231e28Daniel Dunbar                elif name=='favicon.ico':
683b131c8ac7cc429416a2d6aaa0baccb2336883accDaniel Dunbar                    return self.send_path(posixpath.join(kResources,'bugcatcher.ico'))
684e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
685e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        # Match directory entries.
686e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        if components[-1] == '':
687e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            components[-1] = 'index.html'
688b131c8ac7cc429416a2d6aaa0baccb2336883accDaniel Dunbar
6891d75a3b8efb1b4233b3f431604efcd60da8623e4Jordan Rose        relpath = '/'.join(components)
6901d75a3b8efb1b4233b3f431604efcd60da8623e4Jordan Rose        path = posixpath.join(self.server.root, relpath)
691b131c8ac7cc429416a2d6aaa0baccb2336883accDaniel Dunbar
692e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        if self.server.options.debug > 1:
693e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            print >>sys.stderr, '%s: SERVER: sending path "%s"'%(sys.argv[0],
694e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                                                                 path)
695e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        return self.send_path(path)
696e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
697e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def send_404(self):
698e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.send_error(404, "File not found")
699e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        return None
700e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
701e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def send_path(self, path):
70244cbe67dc0e0a35c5369689710a25603ba67356fTed Kremenek        # If the requested path is outside the root directory, do not open it
7031d75a3b8efb1b4233b3f431604efcd60da8623e4Jordan Rose        rel = os.path.abspath(path)
7041d75a3b8efb1b4233b3f431604efcd60da8623e4Jordan Rose        if not rel.startswith(os.path.abspath(self.server.root)):
70544cbe67dc0e0a35c5369689710a25603ba67356fTed Kremenek          return self.send_404()
70644cbe67dc0e0a35c5369689710a25603ba67356fTed Kremenek
707e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        ctype = self.guess_type(path)
708e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        if ctype.startswith('text/'):
709e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            # Patch file instead
710e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            return self.send_patched_file(path, ctype)
711e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        else:
712e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            mode = 'rb'
713e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        try:
714e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            f = open(path, mode)
715e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        except IOError:
716e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            return self.send_404()
717e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        return self.send_file(f, ctype)
718e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
719e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def send_file(self, f, ctype):
720e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        # Patch files to add links, but skip binary files.
721e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.send_response(200)
722e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.send_header("Content-type", ctype)
723e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        fs = os.fstat(f.fileno())
724e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.send_header("Content-Length", str(fs[6]))
725e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
726e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        self.end_headers()
727e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        return f
728e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
729e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def send_string(self, s, ctype='text/html', headers=True, mtime=None):
730e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        if headers:
731e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            self.send_response(200)
732e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            self.send_header("Content-type", ctype)
733e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            self.send_header("Content-Length", str(len(s)))
734cb028b0180b38c7d0404acb936d276ff050061c6Daniel Dunbar            if mtime is None:
735cb028b0180b38c7d0404acb936d276ff050061c6Daniel Dunbar                mtime = self.dynamic_mtime
736cb028b0180b38c7d0404acb936d276ff050061c6Daniel Dunbar            self.send_header("Last-Modified", self.date_time_string(mtime))
737e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar            self.end_headers()
738e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        return StringIO.StringIO(s)
739e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
740e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    def send_patched_file(self, path, ctype):
74117fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar        # Allow a very limited set of variables. This is pretty gross.
74217fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar        variables = {}
74317fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar        variables['report'] = ''
74417fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar        m = kReportFileRE.match(path)
74517fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar        if m:
74617fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar            variables['report'] = m.group(2)
74717fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar
7487345e4782e1218255cad13e7bab5f8104463500dDaniel Dunbar        try:
7497345e4782e1218255cad13e7bab5f8104463500dDaniel Dunbar            f = open(path,'r')
7507345e4782e1218255cad13e7bab5f8104463500dDaniel Dunbar        except IOError:
7517345e4782e1218255cad13e7bab5f8104463500dDaniel Dunbar            return self.send_404()
752e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        fs = os.fstat(f.fileno())
753e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        data = f.read()
754cb028b0180b38c7d0404acb936d276ff050061c6Daniel Dunbar        for a,b in kReportReplacements:
75517fded63f9dba691d517f5c6952344d87d6338bfDaniel Dunbar            data = a.sub(b % variables, data)
756e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar        return self.send_string(data, ctype, mtime=fs.st_mtime)
757e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
758e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
7597ad535db066b6f5e31776f8a74b8f1e98b14cc7eDaniel Dunbardef create_server(address, options, root):
760e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    import Reporter
761e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
762e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar    reporters = Reporter.getReporters()
763e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar
7647ad535db066b6f5e31776f8a74b8f1e98b14cc7eDaniel Dunbar    return ScanViewServer(address, ScanViewRequestHandler,
765e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                          root,
766e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                          reporters,
767e33d3682b6f4ba798b9d8d6f395ac8003827c03bDaniel Dunbar                          options)
768