1ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao#!/usr/bin/env python 2ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 3ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao"""The clang static analyzer results viewer. 4ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao""" 5ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 6ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoimport sys 7ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoimport posixpath 8ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoimport thread 9ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoimport time 10ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoimport urllib 11ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoimport webbrowser 12ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 13ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao# How long to wait for server to start. 14ea285162342df160e7860e26528bc7110bc6c0cdShih-wei LiaokSleepTimeout = .05 15ea285162342df160e7860e26528bc7110bc6c0cdShih-wei LiaokMaxSleeps = int(60 / kSleepTimeout) 16ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 17ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao# Default server parameters 18ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 19ea285162342df160e7860e26528bc7110bc6c0cdShih-wei LiaokDefaultHost = '127.0.0.1' 20ea285162342df160e7860e26528bc7110bc6c0cdShih-wei LiaokDefaultPort = 8181 21ea285162342df160e7860e26528bc7110bc6c0cdShih-wei LiaokMaxPortsToTry = 100 22ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 23ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao### 24ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 25ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaodef url_is_up(url): 26ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao try: 27ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao o = urllib.urlopen(url) 28ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao except IOError: 29ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return False 30ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao o.close() 31ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return True 32ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 33ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaodef start_browser(port, options): 34ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao import urllib, webbrowser 35ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 36ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao url = 'http://%s:%d'%(options.host, port) 37ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 38ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # Wait for server to start... 39ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if options.debug: 40ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao sys.stderr.write('%s: Waiting for server.' % sys.argv[0]) 41ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao sys.stderr.flush() 42ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao for i in range(kMaxSleeps): 43ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if url_is_up(url): 44ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao break 45ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if options.debug: 46ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao sys.stderr.write('.') 47ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao sys.stderr.flush() 48ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao time.sleep(kSleepTimeout) 49ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao else: 50ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao print >>sys.stderr,'WARNING: Unable to detect that server started.' 51ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 52ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if options.debug: 53ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao print >>sys.stderr,'%s: Starting webbrowser...' % sys.argv[0] 54ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao webbrowser.open(url) 55ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 56ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaodef run(port, options, root): 57ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao import ScanView 58ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao try: 59ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao print 'Starting scan-view at: http://%s:%d'%(options.host, 60ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao port) 61ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao print ' Use Ctrl-C to exit.' 62ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao httpd = ScanView.create_server((options.host, port), 63ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao options, root) 64ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao httpd.serve_forever() 65ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao except KeyboardInterrupt: 66ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao pass 67ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 68ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaodef port_is_open(port): 69ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao import SocketServer 70ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao try: 71ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao t = SocketServer.TCPServer((kDefaultHost,port),None) 72ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao except: 73ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return False 74ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao t.server_close() 75ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao return True 76ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 77ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaodef main(): 78ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao from optparse import OptionParser 79ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao parser = OptionParser('usage: %prog [options] <results directory>') 80ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao parser.set_description(__doc__) 81ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao parser.add_option( 82ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao '--host', dest="host", default=kDefaultHost, type="string", 83ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao help="Host interface to listen on. (default=%s)" % kDefaultHost) 84ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao parser.add_option( 85ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao '--port', dest="port", default=None, type="int", 86ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao help="Port to listen on. (default=%s)" % kDefaultPort) 87ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao parser.add_option("--debug", dest="debug", default=0, 88ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao action="count", 89ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao help="Print additional debugging information.") 90ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao parser.add_option("--auto-reload", dest="autoReload", default=False, 91ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao action="store_true", 92ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao help="Automatically update module for each request.") 93ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao parser.add_option("--no-browser", dest="startBrowser", default=True, 94ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao action="store_false", 95ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao help="Don't open a webbrowser on startup.") 96ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao parser.add_option("--allow-all-hosts", dest="onlyServeLocal", default=True, 97ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao action="store_false", 98ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao help='Allow connections from any host (access restricted to "127.0.0.1" by default)') 99ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao (options, args) = parser.parse_args() 100ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 101ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if len(args) != 1: 102ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao parser.error('No results directory specified.') 103ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao root, = args 104ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 105ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # Make sure this directory is in a reasonable state to view. 106ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if not posixpath.exists(posixpath.join(root,'index.html')): 107ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao parser.error('Invalid directory, analysis results not found!') 108ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 109ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # Find an open port. We aren't particularly worried about race 110ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # conditions here. Note that if the user specified a port we only 111ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # use that one. 112ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if options.port is not None: 113ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao port = options.port 114ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao else: 115ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao for i in range(kMaxPortsToTry): 116ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if port_is_open(kDefaultPort + i): 117ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao port = kDefaultPort + i 118ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao break 119ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao else: 120ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao parser.error('Unable to find usable port in [%d,%d)'%(kDefaultPort, 121ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao kDefaultPort+kMaxPortsToTry)) 122ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 123ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # Kick off thread to wait for server and start web browser, if 124ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao # requested. 125ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao if options.startBrowser: 126ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao t = thread.start_new_thread(start_browser, (port,options)) 127ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 128ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao run(port, options, root) 129ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao 130ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liaoif __name__ == '__main__': 131ea285162342df160e7860e26528bc7110bc6c0cdShih-wei Liao main() 132