12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)"""Test server for generating nested iframes with different sites. 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Very simple python server for creating a bunch of iframes. The page generation 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)is randomized based on query parameters. See the __init__ function of the 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Params class for a description of the parameters. 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)This server relies on gevent. On Ubuntu, install it via: 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sudo apt-get install python-gevent 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Run the server using 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) python iframe_server.py 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)To use the server, run chrome as follows: 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) google-chrome --host-resolver-rules='map *.invalid 127.0.0.1' 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Change 127.0.0.1 to be the IP of the machine this server is running on. Then 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)in this chrome instance, navigate to any domain in .invalid 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)(eg., http://1.invalid:8090) to run this test. 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)""" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import colorsys 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import copy 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import random 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import urllib 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import urlparse 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from gevent import pywsgi # pylint: disable=F0401 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MAIN_PAGE = """ 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)<html> 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) <head> 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) <style> 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) body { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) background-color: %(color)s; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) </style> 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) </head> 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) <body> 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) <center> 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) <h1><a href="%(url)s">%(site)s</a></h1> 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) <p><small>%(url)s</small> 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) </center> 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) <br /> 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) %(iframe_html)s 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) </body> 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)</html> 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)""" 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IFRAME_FRAGMENT = """ 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)<iframe src="%(src)s" width="%(width)s" height="%(height)s"> 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)</iframe> 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)""" 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class Params(object): 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Simple object for holding parameters""" 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __init__(self, query_dict): 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Basic params: 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # nframes is how many frames per page. 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # nsites is how many sites to random choose out of. 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # depth is how deep to make the frame tree 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # pattern specifies how the sites are layed out per depth. An empty string 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # uses a random N = [0, nsites] each time to generate a N.invalid URL. 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Otherwise sepcify with single letters like 'ABCA' and frame 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # A.invalid will embed B.invalid will embed C.invalid will embed A. 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # jitter is the amount of randomness applied to nframes and nsites. 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Should be from [0,1]. 0.0 means no jitter. 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # size_jitter is like jitter, but for width and height. 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.nframes = int(query_dict.get('nframes', [4] )[0]) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.nsites = int(query_dict.get('nsites', [10] )[0]) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.depth = int(query_dict.get('depth', [1] )[0]) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.jitter = float(query_dict.get('jitter', [0] )[0]) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.size_jitter = float(query_dict.get('size_jitter', [0.5] )[0]) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.pattern = query_dict.get('pattern', [''] )[0] 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.pattern_pos = int(query_dict.get('pattern_pos', [0] )[0]) 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Size parameters. Values are percentages. 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.width = int(query_dict.get('width', [60])[0]) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.height = int(query_dict.get('height', [50])[0]) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Pass the random seed so our pages are reproduceable. 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.seed = int(query_dict.get('seed', 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) [random.randint(0, 2147483647)])[0]) 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def get_site(urlpath): 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Takes a urlparse object and finds its approximate site. 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Site is defined as registered domain name + scheme. We approximate 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registered domain name by preserving the last 2 elements of the DNS 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) name. This breaks for domains like co.uk. 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) no_port = urlpath.netloc.split(':')[0] 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host_parts = no_port.split('.') 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) site_host = '.'.join(host_parts[-2:]) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return '%s://%s' % (urlpath.scheme, site_host) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def generate_host(rand, params): 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Generates the host to be used as an iframes source. 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Uses the .invalid domain to ensure DNS will not resolve to any real 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) address. 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if params.pattern: 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host = params.pattern[params.pattern_pos] 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.pattern_pos = (params.pattern_pos + 1) % len(params.pattern) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host = rand.randint(1, apply_jitter(rand, params.jitter, params.nsites)) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return '%s.invalid' % host 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def apply_jitter(rand, jitter, n): 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Reduce n by random amount from [0, jitter]. Ensures result is >=1.""" 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if jitter <= 0.001: 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return n 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v = n - int(n * rand.uniform(0, jitter)) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if v: 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return v 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 1 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def get_color_for_site(site): 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Generate a stable (and pretty-ish) color for a site.""" 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) val = hash(site) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # The constants below are arbitrary chosen emperically to look "pretty." 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # HSV is used because it is easier to control the color than RGB. 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Reducing the H to 0.6 produces a good range of colors. Preserving 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # > 0.5 saturation and value means the colors won't be too washed out. 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) h = (val % 100)/100.0 * 0.6 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) s = 1.0 - (int(val/100) % 100)/200. 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) v = 1.0 - (int(val/10000) % 100)/200.0 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (r, g, b) = colorsys.hsv_to_rgb(h, s, v) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 'rgb(%d, %d, %d)' % (int(r * 255), int(g * 255), int(b * 255)) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def make_src(scheme, netloc, path, params): 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Constructs the src url that will recreate the given params.""" 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if path == '/': 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) path = '' 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return '%(scheme)s://%(netloc)s%(path)s?%(params)s' % { 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'scheme': scheme, 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'netloc': netloc, 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'path': path, 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'params': urllib.urlencode(params.__dict__), 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def make_iframe_html(urlpath, params): 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Produces the HTML fragment for the iframe.""" 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (params.depth <= 0): 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return '' 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Ensure a stable random number per iframe. 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rand = random.Random() 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rand.seed(params.seed) 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) netloc_paths = urlpath.netloc.split(':') 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) netloc_paths[0] = generate_host(rand, params) 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) width = apply_jitter(rand, params.size_jitter, params.width) 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) height = apply_jitter(rand, params.size_jitter, params.height) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iframe_params = { 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'src': make_src(urlpath.scheme, ':'.join(netloc_paths), 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) urlpath.path, params), 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'width': '%d%%' % width, 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'height': '%d%%' % height, 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return IFRAME_FRAGMENT % iframe_params 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def create_html(environ): 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Creates the current HTML page. Also parses out query parameters.""" 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) urlpath = urlparse.urlparse('%s://%s%s?%s' % ( 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) environ['wsgi.url_scheme'], 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) environ['HTTP_HOST'], 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) environ['PATH_INFO'], 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) environ['QUERY_STRING'])) 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) site = get_site(urlpath) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params = Params(urlparse.parse_qs(urlpath.query)) 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rand = random.Random() 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rand.seed(params.seed) 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iframe_htmls = [] 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for frame in xrange(0, apply_jitter(rand, params.jitter, params.nframes)): 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Copy current parameters into iframe and make modifications 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # for the recursive generation. 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iframe_params = copy.copy(params) 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iframe_params.depth = params.depth - 1 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Base the new seed off the current seed, but have it skip enough that 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # different frame trees are unlikely to collide. Numbers and skips 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # not chosen in any scientific manner at all. 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iframe_params.seed = params.seed + (frame + 1) * ( 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1000000 + params.depth + 333) 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iframe_htmls.append(make_iframe_html(urlpath, iframe_params)) 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) template_params = dict(params.__dict__) 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) template_params.update({ 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'color': get_color_for_site(site), 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'iframe_html': '\n'.join(iframe_htmls), 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'site': site, 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'url': make_src(urlpath.scheme, urlpath.netloc, urlpath.path, params), 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }) 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return MAIN_PAGE % template_params 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def application(environ, start_response): 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) start_response('200 OK', [('Content-Type', 'text/html')]) 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if environ['PATH_INFO'] == '/favicon.ico': 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) yield '' 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) yield create_html(environ) 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)server = pywsgi.WSGIServer(('', 8090), application) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)server.serve_forever() 225