summaryrefslogtreecommitdiff
path: root/http2
diff options
context:
space:
mode:
authorDiego Roversi <diegor@tiscali.it>2019-09-08 18:12:27 +0200
committerDiego Roversi <diegor@tiscali.it>2019-09-08 18:12:27 +0200
commit1d9925c287b318ec21343e2682b51ab6a36ae8db (patch)
tree17d1c0ac21eea6f291146520afa8381db4586fb4 /http2
initial commit from cvs 1.6.2
Diffstat (limited to 'http2')
-rw-r--r--http2/.cvsignore2
-rw-r--r--http2/config.txt1
-rw-r--r--http2/data/bab.pngbin0 -> 1902 bytes
-rw-r--r--http2/data/baub.pngbin0 -> 1736 bytes
-rw-r--r--http2/data/beab.pngbin0 -> 1677 bytes
-rw-r--r--http2/data/beb.pngbin0 -> 1587 bytes
-rw-r--r--http2/data/biab.pngbin0 -> 1679 bytes
-rw-r--r--http2/data/bib.pngbin0 -> 1655 bytes
-rw-r--r--http2/data/biob.pngbin0 -> 1531 bytes
-rw-r--r--http2/data/bob.pngbin0 -> 1682 bytes
-rw-r--r--http2/data/boob.pngbin0 -> 1617 bytes
-rw-r--r--http2/data/bub.pngbin0 -> 1490 bytes
-rw-r--r--http2/data/byb.pngbin0 -> 2592 bytes
-rw-r--r--http2/data/checked.pngbin0 -> 1032 bytes
-rw-r--r--http2/data/close.pngbin0 -> 478 bytes
-rw-r--r--http2/data/confirm.html34
-rw-r--r--http2/data/disabled.pngbin0 -> 814 bytes
-rw-r--r--http2/data/hat1.pngbin0 -> 202 bytes
-rw-r--r--http2/data/hat2.pngbin0 -> 310 bytes
-rw-r--r--http2/data/header.pngbin0 -> 11619 bytes
-rw-r--r--http2/data/index.html292
-rw-r--r--http2/data/lbab.pngbin0 -> 2592 bytes
-rw-r--r--http2/data/lbeb.pngbin0 -> 1583 bytes
-rw-r--r--http2/data/lbib.pngbin0 -> 1663 bytes
-rw-r--r--http2/data/lbiob.pngbin0 -> 1520 bytes
-rw-r--r--http2/data/name.html189
-rw-r--r--http2/data/new.html271
-rw-r--r--http2/data/options.html285
-rw-r--r--http2/data/sfbob.pngbin0 -> 1785 bytes
-rw-r--r--http2/data/sfbub.pngbin0 -> 1664 bytes
-rw-r--r--http2/data/stop.html101
-rw-r--r--http2/data/unchecked.pngbin0 -> 327 bytes
-rw-r--r--http2/data/wave1.pngbin0 -> 307 bytes
-rw-r--r--http2/data/wave2.pngbin0 -> 327 bytes
-rw-r--r--http2/data/wave3.pngbin0 -> 313 bytes
-rw-r--r--http2/header.pngbin0 -> 11619 bytes
-rw-r--r--http2/httppages.py705
-rwxr-xr-xhttp2/sf/bb12.py274
-rw-r--r--http2/sf/sfbub.pngbin0 -> 1664 bytes
-rw-r--r--http2/sf/started.html44
40 files changed, 2198 insertions, 0 deletions
diff --git a/http2/.cvsignore b/http2/.cvsignore
new file mode 100644
index 0000000..5be8cea
--- /dev/null
+++ b/http2/.cvsignore
@@ -0,0 +1,2 @@
+*.py[co]
+config.txt
diff --git a/http2/config.txt b/http2/config.txt
new file mode 100644
index 0000000..0af71a3
--- /dev/null
+++ b/http2/config.txt
@@ -0,0 +1 @@
+{'queen': {}, '*': {'finalboard': '100', 'beginboard': '1', 'extralife': '50000', 'autoreset': 'n', 'lvlend': 'y', 'lifegainlimit': '1', 'metapublish': 'y', 'limit': 'n', 'file': 'levels/Levels.bin', 'time': '1567957746.48', 'lives': '3', 'stepboard': '1'}}
diff --git a/http2/data/bab.png b/http2/data/bab.png
new file mode 100644
index 0000000..b97b8fc
--- /dev/null
+++ b/http2/data/bab.png
Binary files differ
diff --git a/http2/data/baub.png b/http2/data/baub.png
new file mode 100644
index 0000000..8d85660
--- /dev/null
+++ b/http2/data/baub.png
Binary files differ
diff --git a/http2/data/beab.png b/http2/data/beab.png
new file mode 100644
index 0000000..443d20a
--- /dev/null
+++ b/http2/data/beab.png
Binary files differ
diff --git a/http2/data/beb.png b/http2/data/beb.png
new file mode 100644
index 0000000..8aa3368
--- /dev/null
+++ b/http2/data/beb.png
Binary files differ
diff --git a/http2/data/biab.png b/http2/data/biab.png
new file mode 100644
index 0000000..9de577d
--- /dev/null
+++ b/http2/data/biab.png
Binary files differ
diff --git a/http2/data/bib.png b/http2/data/bib.png
new file mode 100644
index 0000000..c2ec110
--- /dev/null
+++ b/http2/data/bib.png
Binary files differ
diff --git a/http2/data/biob.png b/http2/data/biob.png
new file mode 100644
index 0000000..211e023
--- /dev/null
+++ b/http2/data/biob.png
Binary files differ
diff --git a/http2/data/bob.png b/http2/data/bob.png
new file mode 100644
index 0000000..f01ca02
--- /dev/null
+++ b/http2/data/bob.png
Binary files differ
diff --git a/http2/data/boob.png b/http2/data/boob.png
new file mode 100644
index 0000000..eef411a
--- /dev/null
+++ b/http2/data/boob.png
Binary files differ
diff --git a/http2/data/bub.png b/http2/data/bub.png
new file mode 100644
index 0000000..22742de
--- /dev/null
+++ b/http2/data/bub.png
Binary files differ
diff --git a/http2/data/byb.png b/http2/data/byb.png
new file mode 100644
index 0000000..716988b
--- /dev/null
+++ b/http2/data/byb.png
Binary files differ
diff --git a/http2/data/checked.png b/http2/data/checked.png
new file mode 100644
index 0000000..df0201c
--- /dev/null
+++ b/http2/data/checked.png
Binary files differ
diff --git a/http2/data/close.png b/http2/data/close.png
new file mode 100644
index 0000000..6d9534b
--- /dev/null
+++ b/http2/data/close.png
Binary files differ
diff --git a/http2/data/confirm.html b/http2/data/confirm.html
new file mode 100644
index 0000000..928764d
--- /dev/null
+++ b/http2/data/confirm.html
@@ -0,0 +1,34 @@
+<html>
+<head>
+<meta http-equiv="Pragma" content="no-cache">
+<meta http-equiv="Cache-Control" content="no-cache">
+<meta http-equiv="Expires" content="0">
+<title>See you</title>
+</head>
+<body text="#000000" bgcolor="#C04040" link="#800000" vlink="#800000" alink="#800000">
+
+<h1>Confirmation</h1>
+
+<p>%(count > 1 and ('There are %d clients'%count) or 'There is a client')s
+still connected to your server.</p>
+
+<p>Are you sure you want to stop the server now?
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+<img src="lbab.png">
+</p>
+
+<br>
+
+<table width="100%%" border=0>
+<tr><td bgcolor="#FF8080">
+<table border=0>
+<tr><td>
+<a href="index.html"><strong>&lt;&lt;&lt; Cancel</strong></a>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+<a href="stop.html?really=y"><strong>Yes, Really Quit &gt;&gt;&gt;</strong></a>
+</td></tr>
+</table>
+</td></tr>
+</table>
+
+</body></html>
diff --git a/http2/data/disabled.png b/http2/data/disabled.png
new file mode 100644
index 0000000..922c394
--- /dev/null
+++ b/http2/data/disabled.png
Binary files differ
diff --git a/http2/data/hat1.png b/http2/data/hat1.png
new file mode 100644
index 0000000..b3684d1
--- /dev/null
+++ b/http2/data/hat1.png
Binary files differ
diff --git a/http2/data/hat2.png b/http2/data/hat2.png
new file mode 100644
index 0000000..6494580
--- /dev/null
+++ b/http2/data/hat2.png
Binary files differ
diff --git a/http2/data/header.png b/http2/data/header.png
new file mode 100644
index 0000000..c9a8566
--- /dev/null
+++ b/http2/data/header.png
Binary files differ
diff --git a/http2/data/index.html b/http2/data/index.html
new file mode 100644
index 0000000..08dcc2f
--- /dev/null
+++ b/http2/data/index.html
@@ -0,0 +1,292 @@
+<html>
+<head>
+<meta http-equiv="Pragma" content="no-cache">
+<meta http-equiv="Cache-Control" content="no-cache">
+<meta http-equiv="Expires" content="0">
+<title>The Bub's Brothers</title>
+</head>
+<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#000099" alink="#FF0000">
+&nbsp;
+<center><table cellspacing=0 cellpadding=0 border=0 width="95%%">
+
+%(
+externaltarget = running and ' target="new"' or ''
+)s
+
+
+<tr>
+<td width="6%%" bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+<td width="6%%" bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF"><a href="stop.html?time=%(tim)s"><img src="close.png" width=17 height=17>&nbsp;<font color="#FF0000" size=+1>Stop this program</font></a></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#F0E0E0">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#E0C0C0" align="center"><font size=+3><strong>The Bub's Brothers</strong></font></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#F0E0E0">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" align="right">
+ <a href="http://bub-n-bros.sourceforge.net"%(externaltarget)s>Web Home page</a> -
+ <a href="name.html">Player Names &amp; Teams</a> -
+ <a href="options.html?time=%(tim)s">Configuration</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" background="wave1.png"><font size=+3>&nbsp;</font></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td>
+ <table width="100%%" cellpadding=7>
+ <tr>
+ <td width="20%%" bgcolor="#000080" align="center"><font size=+1 color="#FFFF00"><strong>New game</strong></font></td>
+ <td bgcolor="#C0C0FF">
+ <table border=0>
+ <tr>
+ <td width=48><img src="%(juststarted and 'sfbob.png' or 'bob.png')s"></td>
+ <td>%(
+if running:
+ print '<form name="S" action="index.html" method="get">'
+ print '<input type=hidden name="time" value="%s">' % tim
+ print '<table width="100%" border=0><tr><td><p><strong>'
+ if juststarted:
+ print 'Server started!'
+ elif justconnected:
+ print 'Playing'
+ elif count == 0:
+ print 'No client is connected to your server at the moment.'
+ elif count == 1:
+ print 'One connected client.'
+ else:
+ print '%d connected clients.' % count
+ print '</strong></p></td>'
+ print '<td align="center"><input type=submit value="Update on connected clients"></td>'
+ print '</tr></table></form>'
+ print '<p><strong><a href="join.html?host=%s&port=%s&httpport=%s&time=%s">' % (running[0][0], running[0][1], self.httpport, tim),
+ print 'Join your own game now</a></strong> at <strong>%s:%s</strong></p>' % (
+ running[0])
+##if metapublish:
+## import time
+## print '<p><a href="register.html?a=%s">' % time.time()
+## if self.globaloptions.metapublish == 'y':
+## self.has_been_published = 1
+## metaquery = metaquery or []
+## metaquery.insert(0, 'desc='+fndesc)
+## s = 'a=' + metapublish
+## if s not in metaquery:
+## metaquery.insert(0, s)
+## print 'Register again',
+## else:
+## print 'Register (after all)',
+## print 'your server to the SourceForge meta-server</a><br>'
+## print '<a href="register.html?d=%s">' % time.time()
+## print 'Unregister your server</a>',
+## print '<font size=-1>(it is unregistered automatically after some time',
+## print 'when other people cannot find it, or',
+## print 'if you stop it with the link <font color="#FF2000">Stop this program</font> at the top of the page)</font></p>'
+)s
+<form name="n" action="new.html" method="get">
+<input type=hidden name="time" value="%(tim)s">
+%(
+if self.Game:
+ print '<input type=submit',
+ if running:
+ print 'value="Start another game">'
+ else:
+ print 'value="Start a new game">'
+else:
+ print 'You need the <a href="http://bub-n-bros.sourceforge.net/download.html">complete version</a> to start a new game.<br><font size=-1>With this version you can only connect to existing servers and <font color="#FF0000">only over fast links!</font></font>'
+)s
+</form>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" background="wave3.png"><font size=+3>&nbsp;</font></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td>%(
+servers = self.getlocalservers()[:]
+
+found = []
+def show((addr, (info, ping)), found=found):
+ import socket
+ infolst = info.split(':') or ['?']
+ if len(infolst) >= 3:
+ httpport = infolst.pop(2)
+ else:
+ httpport = 'off'
+ print '<a href="join.html?host=%s&port=%d&httpport=%s&time=%s">' % (
+ addr[0], addr[1], httpport, tim)
+ host, port = addr
+ #host = socket.gethostbyaddr(host)[0]
+ if ping is not None:
+ infolst.append('ping: %dms' % int(ping*1000))
+ if (addr, infolst[0]) == running:
+ infolst.append('this is your own server')
+ found.append(1)
+ infolst = map(htmlquote, infolst)
+ print '<strong>%s:%s</strong></a> playing <strong>%s</strong>' % (
+ host, port, infolst[0])
+ if len(infolst) > 1:
+ print '&nbsp;(%s)' % ' &middot; &middot; '.join(infolst[1:])
+
+if servers is None:
+ rowspan = 1
+else:
+ rowspan = (len(servers) or 1)+1
+)s
+<table width="100%%" cellpadding=7><tr>
+ <td width="20%%" bgcolor="#FF0080" align="center" rowspan="%(rowspan)s">
+ <font size=+1 color="#FFFF00">
+ <strong>Local games</strong>
+ </font>
+ </td>
+ <td bgcolor="#FFC0C0">
+%(
+if servers is not None:
+ if servers:
+ show(servers[0])
+ else:
+ print "(no server found)"
+ print '</td></tr>'
+ for s in servers[1:]:
+ print '<tr><td bgcolor="#FFC0C0">'
+ show(s)
+ print '</td></tr>'
+ print '<tr><td bgcolor="#FFC0C0">'
+)s
+ <table border=0><tr>
+ <td width=48><img src="boob.png"></td>
+ <td>
+%(
+if running and not found:
+ import hostchooser, gamesrv
+ if gamesrv.displaysockport(gamesrv.openpingsocket()) != hostchooser.UDP_PORT:
+ print '<p><font size=-1>Note: your server does not appear in this list'
+ print 'because the UDP port %d is already in use (is another Bub &amp; Bob server running on this machine?).' % hostchooser.UDP_PORT
+ print 'Use the full server address <strong>%s:%s</strong></font></p>' % running[0]
+)s
+ <form name="L" action="index.html" method="get">
+ <input type=hidden name="time" value="%(tim)s">
+ <input type=submit value="Search again for local servers">
+ </form>
+ </td>
+ </tr></table>
+ <p><form name="J" action="join.html" method="get">
+ <input type=hidden name="time" value="%(tim)s">
+ Or connect to server:
+ <input type=text name="host" size=25>
+ (<code>host</code> or <code>host:port</code>)
+ <input type=submit value="Go">
+ </form></p>
+ </td>
+</tr></table>
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" background="wave2.png"><font size=+3>&nbsp;</font></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td>
+ <table width="100%%" cellpadding=7>
+ <tr>
+ <td width="20%%" bgcolor="#008000" align="center"><font size=+1 color="#FFFF00"><strong>Internet games</strong></font></td>
+ <td bgcolor="#C0FFCC">
+ <table border=0>
+ <tr>
+ <td width=48><img src="bub.png"></td>
+ <td><p><a href="%(self.metaserverpage(headers))s">Go to the Internet servers page</a></p>
+ <p><font size=-1>Don't forget to <a href="name.html">give a name</a>
+ to your dragons before you join a server!
+ </font></p></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000" align="center"><img src="header.png"></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+
+</table></center>
+
+
+</body>
+</html>
diff --git a/http2/data/lbab.png b/http2/data/lbab.png
new file mode 100644
index 0000000..24fd915
--- /dev/null
+++ b/http2/data/lbab.png
Binary files differ
diff --git a/http2/data/lbeb.png b/http2/data/lbeb.png
new file mode 100644
index 0000000..a04a9e0
--- /dev/null
+++ b/http2/data/lbeb.png
Binary files differ
diff --git a/http2/data/lbib.png b/http2/data/lbib.png
new file mode 100644
index 0000000..191142a
--- /dev/null
+++ b/http2/data/lbib.png
Binary files differ
diff --git a/http2/data/lbiob.png b/http2/data/lbiob.png
new file mode 100644
index 0000000..afc809f
--- /dev/null
+++ b/http2/data/lbiob.png
Binary files differ
diff --git a/http2/data/name.html b/http2/data/name.html
new file mode 100644
index 0000000..dab24f9
--- /dev/null
+++ b/http2/data/name.html
@@ -0,0 +1,189 @@
+<html>
+<head>
+<meta http-equiv="Pragma" content="no-cache">
+<meta http-equiv="Cache-Control" content="no-cache">
+<meta http-equiv="Expires" content="0">
+<title>Name Bub's Brothers</title>
+</head>
+<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#000099" alink="#FF0000">
+&nbsp;
+
+<form name="n" action="name.html" method="get">
+<center>
+
+<table CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH="95%%">
+
+<tr>
+<td width="6%%" bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000" colspan="3">&nbsp;</td>
+<td width="6%%" bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000" colspan="3">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" colspan="3">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#F0E0E0" colspan="3">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#E0C0C0" align="center" colspan="3"><font size=+3><strong>Player Names</strong></font></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#F0E0E0" colspan="3">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" colspan="3">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" colspan="3" align="right">
+ <a href="index.html?time=%(time.time())s">Back to the main page</a>
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" colspan="3" background="wave1.png"><font size=+3>&nbsp;</font></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+
+%(
+buttons = {
+0: """
+""",
+1: """
+"""}
+for id, img, bgcolor in [
+ (0, 'bub.png', '#c0ffc0'),
+ (1, 'bob.png', '#c0c0ff'),
+ (2,'boob.png', '#ffc0c0'),
+ (3, 'beb.png', '#ffc000'),
+ (4,'biob.png', '#ffff00'),
+ (5, 'bab.png', '#c04040'),
+ (6, 'bib.png', '#c0c0c0'),
+ (7,'baub.png', '#fc60ff'),
+ (8,'beab.png', '#4fa4ff'),
+ (9,'biab.png', '#0ab237'),
+ ]:
+ keyid = "player%d" % id
+ playername = options.get(keyid) or ''
+ playername = playername.strip()
+ for team in [1,2]:
+ if playername.endswith('(%d)' % team):
+ playername = playername[:-3].strip()
+ break
+ else:
+ team = 'off'
+ def nameval(value, team=team, teamid="team%d" % id):
+ s = 'value="%s"' % (value,)
+ if team == value:
+ s += ' selected'
+ return s
+ print """
+<tr>
+ <td bgcolor="#000000">&nbsp;</td>
+ <td bgcolor="%s" align="right" width="35%%"><img src="%s"></td>
+ <td bgcolor="%s" align="center" width="10%%"><input type=text size=16 name="%s" value="%s"></td>
+ <td bgcolor="%s" align="left">&nbsp;&nbsp;
+ <select name="team%d">
+ <option %s>no team<option %s>Team 1<option %s>Team 2</select>
+ </td>
+ <td bgcolor="#000000">&nbsp;</td>
+</tr>
+""" % (bgcolor, img, bgcolor, keyid, playername,
+ bgcolor, id, nameval('off'), nameval(1), nameval(2))
+)s
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" colspan="3">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td colspan=3 align="center" valign="top" bgcolor="#FFFFFF">
+<input type=submit name="s" value=" Save ">&nbsp;&nbsp;&nbsp;
+<input type=submit name="f" value=" Fill in missing names ">&nbsp;&nbsp;&nbsp;
+<input type=submit name="c" value=" Clear ">
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" colspan="3">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#F0E0E0" colspan="3">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#E0C0C0" colspan="3">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#F0E0E0" colspan="3">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" colspan="3">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000" colspan="3" align="center"><img src="header.png"></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000" colspan="3">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+
+</table>
+
+
+</center>
+</form>
+
+</body>
+</html>
diff --git a/http2/data/new.html b/http2/data/new.html
new file mode 100644
index 0000000..1709c8d
--- /dev/null
+++ b/http2/data/new.html
@@ -0,0 +1,271 @@
+<html>
+<head>
+<meta http-equiv="Pragma" content="no-cache">
+<meta http-equiv="Cache-Control" content="no-cache">
+<meta http-equiv="Expires" content="0">
+<title>New Bub's Brothers Server</title>
+</head>
+<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#000099" alink="#FF0000">
+&nbsp;
+
+<form name="n" action="run.html" method="get">
+<input type=hidden name="time" value="%(time.time())s">
+
+%(
+def nameval(name, value, default=0, options=options):
+ s = getattr(options, name)
+ if s == value or (default and not s):
+ s = 'checked '
+ else:
+ s = ''
+ return s + 'name="%s" value="%s"' % (name, value)
+)s
+
+<center>
+<table CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH="95%%">
+
+<tr>
+<td width="6%%" bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+<td width="6%%" bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#F0E0E0">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#E0C0C0" align="center"><font size=+3><strong>New Server</strong></font></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#F0E0E0">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" align="right">
+ <a href="index.html?time=%(time.time())s">Back to the main page</a>
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" background="wave1.png"><font size=+3>&nbsp;</font></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td>
+ <table width="100%%" cellpadding=7>
+ <tr>
+ <td width="20%%" bgcolor="#000080" align="center"><font size=+1 color="#FFFF00"><strong>Level file</strong></font></td>
+ <td bgcolor="#C0C0FF">
+ <table border=0>
+ <tr>
+ <td width=48><img src="bob.png"></td>
+ <td><select name="file">%(
+for displayname, filename in Game.FnListBoards():
+ print '<option',
+ if filename == str(options.file):
+ print 'selected',
+ print 'value="%s">' % htmlquote(filename), htmlquote(displayname)
+)s</select>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td>
+ <table width="100%%" cellpadding=7>
+ <tr>
+ <td width="20%%" bgcolor="#000080" align="center"><font size=+1 color="#FFFF00"><strong>Levels to play</strong></font></td>
+ <td bgcolor="#C0C0FF">
+ Start at level <input type=text name="beginboard" size=3 value="%(options.beginboard or 1)s">
+and go on ...
+ </td>
+ <td bgcolor="#C0C0FF">
+
+ <input type=radio %(nameval("lvlend", "y", 1))s>&nbsp;to the end of the level file</input><br>
+ <input type=radio %(nameval("lvlend", "n"))s>&nbsp;to</input> level <input type=text name="finalboard" size=3 value="%(options.finalboard or 100)s"><br>
+ skipping levels:
+ <select name="stepboard"> %(
+steps = [
+ (1, 'none'),
+ (2, 'by steps of 2 (skip every other level)')]
+for i in range(3, 10) + range(10, 30, 5):
+ steps.append((i, 'by steps of %d levels' % i))
+for i, text in steps:
+ print '<option',
+ if str(i) == str(options.stepboard):
+ print 'selected',
+ print 'value="%d">' % i, text
+)s</select>
+ </td>
+ </tr>
+ </table>
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td>
+ <table width="100%%" cellpadding=7>
+ <tr>
+ <td width="20%%" bgcolor="#000080" align="center"><font size=+1 color="#FFFF00"><strong>Limited lives</strong></font></td>
+ <td bgcolor="#C0C0FF">
+ <input type=radio %(nameval("limit", "n", 1))s>&nbsp;no limited lives --- just run for points!</input><br>
+ <input type=radio %(nameval("limit", "y"))s>&nbsp;limit</input> to <input type=text name="lives" size=3 value="%(options.lives or 3)s"> lives (with an extra life for each <input type=text name="extralife" size=7 value="%(options.extralife or 50000)s"> points)<br>
+ <input type=checkbox %(nameval("limitlifegain", "y"))s>&nbsp;limit lifegain to max. <input type=text name="lifegainlimit" size=3 value="%(options.lifegainlimit or 1)s"> life per level
+ </td>
+ </tr>
+ </table>
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td>
+ <table width="100%%" cellpadding=7>
+ <tr>
+ <td width="20%%" bgcolor="#000080" align="center"><font size=+1 color="#FFFF00"><strong>Permanent server</strong></font></td>
+ <td bgcolor="#C0C0FF">
+ <input type=checkbox %(nameval("autoreset", "y"))s>&nbsp;Automatically restart the server after the end is reached, forever</input><br>
+ <font size=-1>Non-permanent servers time out after 2 hours of inactivity</font>
+ </td>
+ </tr>
+ </table>
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td>
+ <table width="100%%" cellpadding=7>
+ <tr>
+ <td width="20%%" bgcolor="#008000" align="center"><font size=+1 color="#FFFF00"><strong>Internet game</strong></font></td>
+ <td bgcolor="#C0FFC0">
+ <table border=0>
+ <tr>
+ <td width=48><img src="sfbub.png"></td>
+ <td><p><input type=checkbox %(nameval("metapublish", "y", 1))s>&nbsp;register the server on the Bub-'n-Bros meta-server, allowing it to appear on everybody's Internet Games list</input></p></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" align="center">
+<input type=submit value=" Start Server ">
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+%(
+if running: print '''
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" align="center">
+<strong><font color="#FF0000">Note:</font> this will replace the server already running on this machine.</strong>
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+''')s
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#F0E0E0">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#E0C0C0">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#F0E0E0">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000" align="center"><img src="header.png"></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+
+</table></center>
+</form>
+
+</body>
+</html>
diff --git a/http2/data/options.html b/http2/data/options.html
new file mode 100644
index 0000000..8ded787
--- /dev/null
+++ b/http2/data/options.html
@@ -0,0 +1,285 @@
+<html>
+<head>
+<meta http-equiv="Pragma" content="no-cache">
+<meta http-equiv="Cache-Control" content="no-cache">
+<meta http-equiv="Expires" content="0">
+<title>Settings - The Bub's Brothers</title></head>
+<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#000099" alink="#FF0000">
+&nbsp;
+
+%(
+def nameval(type, name, value=None, default=None, mangling=1, options=options):
+ if mangling:
+ name = mode.unique_id() + '_' + name
+ s = getattr(options, name) or default
+ checked = s == value
+ if type == 'option':
+ return 'option %svalue="%s"' % (checked and 'selected ' or '', value)
+ elif type == 'select':
+ return 'select name="%s"' % name
+ elif type == 'text':
+ return 'input type=text name="%s" value="%s"' % (
+ name, htmlquote(s))
+ else:
+ return 'input type=%s %sname="%s" value="%s"' % (
+ type, checked and 'checked ' or '', name, value)
+
+def begingroup(text, fgcolor, bgcolor, lightbgcolor, img, nbitems):
+ global groupinfo
+ print '<tr>'
+ print '<td width="20%"',
+ print 'rowspan="%d" bgcolor="%s" align="center">' % (nbitems or 1, bgcolor)
+ print '<font size=+1 color="%s"><strong>%s</strong></font>' % (fgcolor, text)
+ print '</td>'
+ groupinfo = [lightbgcolor, bgcolor, fgcolor, 0, 0, img]
+ if not nbitems:
+ begingroupitem()
+ endgroupitem()
+def begingroupitem(highlight=0):
+ if groupinfo[4]:
+ print '<tr>'
+ groupinfo[4] += 1
+ groupinfo[3] = highlight
+ print '<td width="80%%" bgcolor="%s">' % groupinfo[highlight]
+ print '<table width="100%" border=0><tr>'
+def endgroupitem():
+ print '<td width=40 align="right" valign="top">'
+ if groupinfo[3]:
+ print '<img src="%s">' % groupinfo[-1]
+ print '</td></tr></table>'
+ print '</td></tr>'
+def endgroup():
+ pass
+
+def beginmode():
+ highlight = mode in currentmodes
+ begingroupitem(highlight)
+
+ print '<td width=36 align="right" valign="center">'
+ err = mode.imperror()
+ if highlight:
+ url = None
+ err = err or "selected"
+ print '<img alt="selected" src="checked.png">'
+ elif err:
+ url = None
+ print '<img alt="%s" src="disabled.png">' % err
+ else:
+ url = "options.html?%s=%s&savetime=%s" % (mode.prefix, mode.name,
+ time.time())
+ err = "select"
+ print '<a href="%s"><img alt="select" src="unchecked.png"></a>' % url
+ print '</td>'
+
+ print '<td width="20%" valign="center">'
+ if url: print '<a href="%s">' % url,
+ print htmlquote(err),
+ if url: print '</a>',
+ print '</td>'
+
+ print '<td width="80%"><font size=+1><strong>',
+ print htmlquote(mode.name),
+ print '</strong></font>'
+ if mode.url:
+ print '&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp;&nbsp;<a href="%s"><i>web site</i></a>' % mode.url
+ print '<br>'
+ print htmlquote(mode.descr)
+ return highlight
+
+def beginmodeoptions():
+ print '<br>'
+ print '<table border=0><tr><td>'
+
+def endmodeoptions():
+ print '</td><td align="center" valign="bottom">'
+ print '<input type=submit value=" Save ">'
+ print '</td></tr></table>'
+
+def endmode():
+ print '</td>'
+ endgroupitem()
+
+def modeitems(modelist):
+ global mode
+ for mode in modelist:
+ if beginmode():
+ txt = mode.htmloptionstext(nameval)
+ if txt:
+ beginmodeoptions()
+ print txt
+ endmodeoptions()
+ endmode()
+)s
+
+
+<center><table CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH="95%%">
+
+<tr>
+<td width="6%%" bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+<td width="6%%" bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#E0E0D0">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#D0D0D0">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#C0C0C0" align="center"><font size=+3><strong>Settings</strong></font></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#D0D0D0">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#E0E0D0">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#E0E0D0" align="right">
+ <a href="http://bub-n-bros.sourceforge.net/help.html">Technical documentation</a> -
+ <a href="index.html?time=%(time.time())s">Back to the main page</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#E0E0D0">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#E0E0D0">
+
+<form name="options" action="options.html" method="get">
+<input type=hidden name="savetime" value="%(time.time())s">
+<table border=0 cellspacing=4>
+
+
+
+%(
+graphicmodes = self.graphicmodeslist()
+currentmodes = self.localmodes()
+begingroup('Display driver', '#800000', '#FFC000', '#C0C0C0',
+ 'lbeb.png', len(graphicmodes))
+modeitems(graphicmodes)
+endgroup()
+)s
+
+<tr><td>&nbsp;</td><td>&nbsp;</td></tr>
+
+
+
+%(
+soundmodes = self.soundmodeslist()
+java = graphicmodes[0] in currentmodes
+begingroup('Sound driver', '#800000', '#FFFF00', '#C0C0C0',
+ 'lbiob.png', java and 1 or len(soundmodes))
+if java:
+ begingroupitem(1)
+ print '<td><font size=-1>Java Applet always does sounds, but',
+ print 'background music is not implemented</font></td>'
+ endgroupitem()
+else:
+ modeitems(soundmodes)
+endgroup()
+)s
+
+<tr><td>&nbsp;</td><td>&nbsp;</td></tr>
+
+%(
+begingroup('Network options', '#004000', '#80FF00', None, 'lbib.png', 1)
+begingroupitem(1)
+)s
+<td>
+ <table border=0><tr>
+ <td>
+ <p>Network ports are automatically assigned, but you can optionally choose fixed
+ ones and let them in through your firewall. <font size=-1>Clients using the
+ "Internet games" meta-server can usually connect even through firewalls.
+ Moreover servers can re-route UDP traffic to clients behind firewalls over TCP.
+%(
+if java:
+ print "These settings don't apply to the Java applet."
+)s </font></p>
+
+ <p>TCP game server port: <%(nameval("text", "port_LISTEN", default="", mangling=0))s><br>
+ HTTP server port: <%(nameval("text", "port_HTTP", default="", mangling=0))s></p>
+
+ <p>Client incoming UDP port (or <code>host:port</code> if redirected): <%(nameval("text", "port_CLIENT", default="", mangling=0))s><br>
+ <%(nameval("radio", "datachannel", "ucp", mangling=0))s>always UDP</input>
+ <%(nameval("radio", "datachannel", "tcp", mangling=0))s>no UDP, only TCP</input>
+ <%(nameval("radio", "datachannel", "auto", default="auto", mangling=0))s>Auto-detect</input><br>
+ Client incoming TCP port (metaserver-directed back-connections): <%(nameval("text", "port_BACK", default="", mangling=0))s></p>
+ </td>
+ <td width=12></td>
+ <td align="center" valign="bottom">
+ <a href="http://bub-n-bros.sourceforge.net/help.html#port">Help!</a><br><br>
+ <input type=submit value=" Save ">
+ </td>
+ </tr></table>
+</td>
+%(
+endgroupitem()
+endgroup()
+)s
+
+</table>
+</form>
+
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#E0E0D0">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#E0E0D0" align="right">
+<form name="reset" action="options.html" method="get">
+ <input type=hidden name="time" value="%(time.time())s">
+ <input type=submit name="reset" value=" Restore all defaults ">
+</form>
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+
+</table></center>
+
+</body>
+</html>
diff --git a/http2/data/sfbob.png b/http2/data/sfbob.png
new file mode 100644
index 0000000..388d446
--- /dev/null
+++ b/http2/data/sfbob.png
Binary files differ
diff --git a/http2/data/sfbub.png b/http2/data/sfbub.png
new file mode 100644
index 0000000..142f3b3
--- /dev/null
+++ b/http2/data/sfbub.png
Binary files differ
diff --git a/http2/data/stop.html b/http2/data/stop.html
new file mode 100644
index 0000000..464ed36
--- /dev/null
+++ b/http2/data/stop.html
@@ -0,0 +1,101 @@
+<html>
+<head>
+<meta http-equiv="Pragma" content="no-cache">
+<meta http-equiv="Cache-Control" content="no-cache">
+<meta http-equiv="Expires" content="0">
+<title>See you</title>
+</head>
+<body text="#000000" bgcolor="#C04040" link="#0000EE" vlink="#000099" alink="#FF0000">
+
+<br>
+<table width="100%%" border=0>
+<tr>
+ <td width="90%%" bgcolor="#800000" align="right"><font color="#FFFF00" size=+1><strong><i>See you !</i>&nbsp;&nbsp;&nbsp;</strong></font></td>
+ <td width="48" align="center"><img src="lbab.png"></td>
+</form>
+</tr>
+</table>
+
+<br>
+<br>
+<hr><br>
+<center><table width="70%%" cellspacing=0 cellpadding=0 border=0>
+
+<tr>
+<td width="3%%" bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000" align="center"><img src="header.png"></td>
+<td width="3%%" bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" align="center">
+<i>I hope you enjoyed this game!</i>
+<br><br>
+<a href="http://bub-n-bros.sourceforge.net"><i>http://bub-n-bros.sourceforge.net</i></a>
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF" align="center">
+Almost all sprite images, sounds, background musics and
+some of the levels are directly taken from the MacOS version of
+Bub & Bob 1 by McSebi, and redistributed with his gracious
+permission.
+Most graphics have been improved or remade by David Gowers.
+
+<br><br>
+ <a href="http://www.mcsebi.de">http://www.mcsebi.de</a>
+<br><br>
+
+</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#FFFFFF">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#E0E0FF"><br>
+<h2 align="center">Authors</h2>
+
+<ul>
+<li>Programming: Armin Rigo
+<li>Art: David Gowers, based on graphics from McSebi
+<li>Levels: Gio & Odie & Michel-St&eacute;phane & Armin
+<li>Special thanks: Odie & Brachamutanda
+<li>Beta-testers: IMA Connection
+</ul>
+
+<br></td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+<tr>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+<td bgcolor="#000000">&nbsp;</td>
+</tr>
+
+</table></center>
+
+</body>
+</html>
diff --git a/http2/data/unchecked.png b/http2/data/unchecked.png
new file mode 100644
index 0000000..0b20e95
--- /dev/null
+++ b/http2/data/unchecked.png
Binary files differ
diff --git a/http2/data/wave1.png b/http2/data/wave1.png
new file mode 100644
index 0000000..3424216
--- /dev/null
+++ b/http2/data/wave1.png
Binary files differ
diff --git a/http2/data/wave2.png b/http2/data/wave2.png
new file mode 100644
index 0000000..758f47d
--- /dev/null
+++ b/http2/data/wave2.png
Binary files differ
diff --git a/http2/data/wave3.png b/http2/data/wave3.png
new file mode 100644
index 0000000..93fd6d3
--- /dev/null
+++ b/http2/data/wave3.png
Binary files differ
diff --git a/http2/header.png b/http2/header.png
new file mode 100644
index 0000000..c9a8566
--- /dev/null
+++ b/http2/header.png
Binary files differ
diff --git a/http2/httppages.py b/http2/httppages.py
new file mode 100644
index 0000000..3f90093
--- /dev/null
+++ b/http2/httppages.py
@@ -0,0 +1,705 @@
+import os, sys, random
+from cStringIO import StringIO
+import socket, time
+
+PLAYERNAMES = ['Bub', 'Bob', 'Boob', 'Beb',
+ 'Biob', 'Bab', 'Bib',
+ 'Baub', 'Beab', 'Biab']
+
+try:
+ FILE = __file__
+except NameError:
+ FILE = sys.argv[0]
+LOCALDIR = os.path.abspath(os.path.dirname(FILE))
+
+sys.path.insert(0, os.path.abspath(os.path.join(LOCALDIR, os.pardir)))
+sys.path.insert(0, os.path.abspath(os.path.join(LOCALDIR, os.pardir,'common')))
+import gamesrv, httpserver, hostchooser
+from metaserver import metaclient
+from httpserver import HTTPRequestError
+
+
+class Options:
+ def __init__(self, dict={}):
+ self.update(dict)
+ def dict(self):
+ return self.__dict__.copy()
+ def update(self, dict):
+ self.__dict__.update(dict)
+ def copy(self):
+ return Options(self.__dict__)
+ def clear(self):
+ self.__dict__.clear()
+ def __getattr__(self, attr):
+ if not attr.startswith('_'):
+ return None
+ else:
+ raise AttributeError, attr
+
+
+class PageServer:
+ CONFIGFILE = 'config.txt'
+ localservers = None
+
+ def __init__(self, Game):
+ self.Game = Game
+ self.seed = hex(random.randrange(0x1000, 0x10000))
+ #self.unique_actions = {}
+ self.localhost = gamesrv.HOSTNAME
+ self.filename = os.path.join(LOCALDIR, self.CONFIGFILE)
+ data = self.loadoptionfile()
+ self.globaloptions = Options(data.get('*', {}))
+ self.localoptions = Options(data.get(self.localhost, {}))
+ self.reloadports()
+ #self.inetserverlist = None
+ #self.inetservers = {}
+ #self.has_been_published = 0
+
+ def registerpages(self):
+ prefix = '%s/' % self.seed
+ #httpserver.register('controlcenter.html', self.controlcenterloader)
+ httpserver.register(prefix, self.indexloader)
+ httpserver.register(prefix+'index.html', self.indexloader)
+ #httpserver.register(prefix+'list.html', self.listloader)
+ httpserver.register(prefix+'new.html', self.newloader)
+ httpserver.register(prefix+'run.html', self.runloader)
+ httpserver.register(prefix+'stop.html', self.stoploader)
+ httpserver.register(prefix+'join.html', self.joinloader)
+ #httpserver.register(prefix+'register.html',self.registerloader)
+ httpserver.register(prefix+'options.html', self.optionsloader)
+ httpserver.register(prefix+'name.html', self.nameloader)
+ for fn in os.listdir(os.path.join(LOCALDIR, 'data')):
+ path = prefix + fn
+ if not httpserver.is_registered(path):
+ httpserver.register(path, httpserver.fileloader(
+ os.path.join(LOCALDIR, 'data', fn)))
+
+ def opensocket(self):
+ hs = gamesrv.openhttpsocket()
+ if hs is None:
+ return 0
+ self.httpport = port = gamesrv.displaysockport(hs)
+ self.indexurl = 'http://127.0.0.1:%d/%s/' % (port, self.seed)
+ if self.Game:
+ print self.Game.FnDesc,
+ print 'server is ready at', self.indexurl
+ return 1
+
+ def getlocalservers(self):
+ if self.localservers is None:
+ self.searchlocalservers()
+ return self.localservers
+
+ def searchlocalservers(self):
+ servers = hostchooser.find_servers().items()
+ servers = filter(self.filterserver, servers)
+ servers.sort()
+ self.localservers = servers
+
+## def parse_inetserv(self, s):
+## try:
+## host, port, udpport, httpport = s.split(':')
+## return host, int(port), int(udpport)
+## except (ValueError, IndexError):
+## return None, None, None
+
+## def getinetservers(self):
+## if self.inetserverlist is None:
+## return None
+## result = []
+## for s in self.inetserverlist:
+## host, port, udpport = self.parse_inetserv(s)
+## addr = host, port
+## if addr in self.inetservers:
+## result.append((addr, self.inetservers[addr]))
+## return result
+
+## def setinetserverlist(self, lst):
+## self.inetserverlist = lst
+
+## def checkinetserverlist(self):
+## ulist = []
+## for s in self.inetserverlist:
+## host, port, udpport = self.parse_inetserv(s)
+## if host is not None:
+## ulist.append((host, udpport))
+## srvs = hostchooser.find_servers(ulist, delay=0.8)
+## self.inetservers = {}
+## for srv in srvs.items():
+## if not self.filterserver(srv):
+## continue
+## (host, port), info = srv
+## try:
+## host = socket.gethostbyaddr(host)[0]
+## except socket.error:
+## pass
+## self.inetservers[host, port] = info
+## #print 'hostchooser:', self.inetserverlist, '->', self.inetservers
+
+ def filterserver(self, ((host, port), info)):
+ for c in host+str(port):
+ if c not in "-.0123456789:@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_abcdefghijklmnopqrstuvwxyz":
+ return 0
+ return 1
+
+## def statusservers(self):
+## result = [], []
+## for s in self.inetserverlist:
+## host, port, udpport = self.parse_inetserv(s)
+## addr = host, port
+## found = addr in self.inetservers
+## result[found].append(s)
+## return result
+
+ def loadoptionfile(self):
+ try:
+ f = open(self.filename, 'r')
+ data = f.read().strip()
+ f.close()
+ except IOError:
+ data = None
+ return eval(data or '{}', {}, {})
+
+ def saveoptions(self):
+ data = self.loadoptionfile()
+ data['*'] = self.globaloptions.dict()
+ data[self.localhost] = self.localoptions.dict()
+ try:
+ f = open(self.filename, 'w')
+ print >> f, `data`
+ f.close()
+ except IOError, e:
+ print >> sys.stderr, "! Cannot save config file: " + str(e)
+
+ def reloadports(self):
+ import msgstruct
+ msgstruct.PORTS.clear()
+ for key, value in self.localoptions.dict().items():
+ if key.startswith('port_'):
+ key = key[5:]
+ if key == 'CLIENT' and type(value) == str and ':' in value:
+ udphostname, value = value.split(':')
+ msgstruct.PORTS['sendudpto'] = udphostname
+ try:
+ value = int(value)
+ except:
+ continue
+ msgstruct.PORTS[key] = value
+
+ def startgame(self):
+ self.reloadports()
+ options = self.globaloptions
+ kwds = {}
+ if options.beginboard is not None:
+ kwds['beginboard'] = int(options.beginboard)
+ if options.lvlend is not None and options.lvlend.startswith('n'):
+ kwds['finalboard'] = int(options.finalboard)
+ if options.stepboard is not None:
+ kwds['stepboard'] = int(options.stepboard)
+ if options.limit is not None and options.limit.startswith('y'):
+ kwds['limitlives'] = int(options.lives)
+ if options.limitlifegain is not None:
+ kwds['lifegainlimit'] = int(options.lifegainlimit)
+ if options.extralife is not None:
+ kwds['extralife'] = int(options.extralife)
+ if options.autoreset is not None:
+ kwds['autoreset'] = options.autoreset.startswith('y')
+ if options.metapublish is not None:
+ kwds['metaserver'] = options.metapublish.startswith('y')
+ self.Game(options.file, **kwds)
+
+ ### loaders ###
+
+ def metaserverpage(self, headers):
+ metaserver_url = metaclient.METASERVER_URL
+ myhost = my_host(headers)
+ joinurl = quote_plus('%s/%s' % (myhost, self.seed))
+ return metaserver_url + '?join=%s&time=%s' % (joinurl, time.time())
+
+ def mainpage(self, headers, juststarted=0, justconnected=0):
+ running = my_server()
+ count = len(gamesrv.clients)
+ tim = time.time()
+ #if running:
+ # metapublish = my_server_meta_address()
+ # fndesc = quote_plus(gamesrv.game.FnDesc)
+ #else:
+ # metapublish = None
+ return httpserver.load(os.path.join(LOCALDIR, 'data', 'index.html'),
+ 'text/html', locals=locals())
+
+ def indexloader(self, headers, cheat=[], **options):
+ if cheat:
+ import __builtin__
+ for c in cheat:
+ getattr(__builtin__, '__cheat')(c)
+ else:
+ self.localservers = None
+ return self.mainpage(headers, juststarted=('juststarted' in options))
+
+ def controlcenterloader(self, headers, **options):
+ host = headers['remote host']
+ host = socket.gethostbyname(host)
+ if host != '127.0.0.1':
+ raise HTTPRequestError, "Access denied"
+ return None, self.indexurl
+
+## def listloader(self, headers, s=[], **options):
+## self.setinetserverlist(s)
+## self.checkinetserverlist()
+## query = []
+## missing, found = self.statusservers()
+## for s in missing:
+## query.append('d=' + s)
+## for s in found:
+## query.append('a=' + s)
+## return self.mainpage(headers, query)
+
+ def newloader(self, headers, **options):
+ if not self.Game:
+ raise HTTPRequestError, "Complete bub-n-bros installation needed"
+ locals = {
+ 'Game': self.Game,
+ 'options': self.globaloptions,
+ 'running': gamesrv.game is not None,
+ }
+ return httpserver.load(os.path.join(LOCALDIR, 'data', 'new.html'),
+ 'text/html', locals=locals)
+
+ def runloader(self, headers, **options):
+ self.globaloptions.metapublish = 'n'
+ self.globaloptions.autoreset = 'n'
+ for key, value in options.items():
+ if len(value) == 1:
+ setattr(self.globaloptions, key, value[0])
+ self.saveoptions()
+ self.startgame()
+ return None, 'index.html?juststarted=%s' % time.time()
+
+ def stoploader(self, headers, really=[], **options):
+ count = len(gamesrv.clients)
+ if count == 0 or really:
+ locals = {
+ 'self': self,
+ #'metaserver': METASERVER,
+ #'metapublish': gamesrv.game and my_server_meta_address(),
+ #'localdir': LOCALDIR,
+ }
+ gamesrv.closeeverything()
+ return httpserver.load(os.path.join(LOCALDIR, 'data', 'stop.html'),
+ 'text/html', locals=locals)
+ else:
+ locals = {
+ 'count': count,
+ }
+ return httpserver.load(os.path.join(LOCALDIR, 'data', 'confirm.html'),
+ 'text/html', locals=locals)
+
+## def registerloader(self, headers, a=[], d=[], **options):
+## if a: # the lists 'a' and 'd' contain dummies !!
+## self.globaloptions.metapublish = 'y'
+## self.has_been_published = 1
+## kwd = 'a'
+## else:
+## self.globaloptions.metapublish = 'n'
+## kwd = 'd'
+## url = "%s?cmd=register&%s=%s" % (METASERVER,
+## kwd, my_server_meta_address())
+## if a and gamesrv.game:
+## url += '&desc=' + quote_plus(gamesrv.game.FnDesc)
+## return None, url
+
+ def joinloader(self, headers, host=[], port=[], httpport=[],
+ m=[], **options):
+ args = self.buildclientoptions()
+ assert len(host) == 1
+ host = host[0]
+ if len(port) == 1:
+ port = port[0]
+ else:
+ try:
+ host, port = host.split(':')
+ except:
+ port = None
+ if args is None:
+ # redirect to the Java applet
+ try:
+ httpport = int(httpport[0])
+ except (ValueError, IndexError):
+ if port:
+ raise HTTPRequestError, "This server is not running HTTP."
+ else:
+ raise HTTPRequestError, "Sorry, I cannot connect the Java applet to a server using this field."
+ return None, 'http://%s:%s/' % (host, httpport)
+
+ # now is a good time to generate the color files if we can
+ file = os.path.join(LOCALDIR, os.pardir, 'bubbob', 'images',
+ 'buildcolors.py')
+ if os.path.exists(file):
+ g = {'__name__': '__auto__', '__file__': file}
+ execfile(file, g)
+
+ if port:
+ address = '%s:%s' % (host, port)
+ else:
+ address = host
+ nbclients = len(gamesrv.clients)
+ script = os.path.join(LOCALDIR, os.pardir, 'display', 'Client.py')
+ script = no_quote_worries(script)
+ if m:
+ args.insert(0, '-m')
+ args = [script] + args + [address]
+ schedule_launch(args)
+ if m:
+ time.sleep(0.5)
+ s = 'Connecting to %s.' % address
+ return None, self.metaserverpage(headers) + '&head=' + quote_plus(s)
+ #elif my_server_address() == address:
+ # endtime = time.time() + 3.0
+ # while gamesrv.recursiveloop(endtime, []):
+ # if len(gamesrv.clients) > nbclients:
+ # break
+ return self.mainpage(headers, justconnected=1)
+
+ def optionsloader(self, headers, reset=[], savetime=[], **options):
+ if reset:
+ self.localoptions.clear()
+ self.globaloptions.clear()
+ self.saveoptions()
+ elif savetime:
+ self.localoptions.port_CLIENT = None
+ self.localoptions.port_LISTEN = None
+ self.localoptions.port_HTTP = None
+ for key, value in options.items():
+ setattr(self.localoptions, key, value[0])
+ self.saveoptions()
+ locals = {
+ 'self' : self,
+ 'options': self.localoptions,
+ }
+ return httpserver.load(os.path.join(LOCALDIR, 'data', 'options.html'),
+ 'text/html', locals=locals)
+
+ def nameloader(self, headers, **options):
+ MAX = len(PLAYERNAMES)
+ if options:
+ anyname = None
+ for id in range(MAX):
+ keyid = 'player%d' % id
+ if keyid in options:
+ value = options[keyid][0]
+ anyname = anyname or value
+ teamid = 'team%d' % id
+ if teamid in options:
+ team = options[teamid][0]
+ if len(team) == 1:
+ value = '%s (%s)' % (value, team)
+ setattr(self.localoptions, keyid, value)
+ if 'c' in options:
+ for id in range(MAX):
+ keyid = 'player%d' % id
+ try:
+ delattr(self.localoptions, keyid)
+ except AttributeError:
+ pass
+ if 'f' in options:
+ for id in range(MAX):
+ keyid = 'player%d' % id
+ if not getattr(self.localoptions, keyid):
+ setattr(self.localoptions, keyid,
+ anyname or PLAYERNAMES[id])
+ else:
+ anyname = getattr(self.localoptions, keyid)
+ self.saveoptions()
+ if 's' in options:
+ return self.mainpage(headers)
+ locals = {
+ 'options': self.localoptions.dict(),
+ }
+ return httpserver.load(os.path.join(LOCALDIR, 'data', 'name.html'),
+ 'text/html', locals=locals)
+
+ def graphicmodeslist(self):
+ try:
+ return self.GraphicModesList
+ except AttributeError:
+ import display.modes
+ self.GraphicModesList = display.modes.graphicmodeslist()
+ javamode = display.modes.GraphicMode(
+ 'java', 'Java Applet (for Java browsers)', [])
+ javamode.low_priority = 1
+ javamode.getmodule = lambda : None
+ self.GraphicModesList.insert(0, javamode)
+ return self.GraphicModesList
+
+ def soundmodeslist(self):
+ try:
+ return self.SoundModesList
+ except AttributeError:
+ import display.modes
+ self.SoundModesList = display.modes.soundmodeslist()
+ return self.SoundModesList
+
+ def localmodes(self):
+ import display.modes
+ currentmodes = []
+ options = self.localoptions
+ for name, lst in [(options.dpy_, self.graphicmodeslist()),
+ (options.snd_, self.soundmodeslist())]:
+ try:
+ mode = display.modes.findmode(name, lst)
+ except KeyError:
+ try:
+ mode = display.modes.findmode(None, lst)
+ except KeyError, e:
+ print >> sys.stderr, str(e) # no mode!
+ mode = None
+ currentmodes.append(mode)
+ return currentmodes
+
+ def buildclientoptions(self):
+ dpy, snd = self.localmodes()
+ if dpy.getmodule() is None:
+ return None # redirect to the Java applet
+ if dpy is None or snd is None:
+ raise HTTPRequestError, "No installed graphics or sounds drivers. See the settings page."
+ options = self.localoptions
+ result = ['--cfg='+no_quote_worries(self.filename)]
+ for key, value in options.dict().items():
+ if key.startswith('port_') and value:
+ result.append('--port')
+ result.append('%s=%s' % (key[5:], value))
+ if options.datachannel == 'tcp': result.append('--tcp')
+ if options.datachannel == 'udp': result.append('--udp')
+ if options.music == 'no': result.append('--music=no')
+ for optname, mode in [('--display', dpy),
+ ('--sound', snd)]:
+ result.append(optname + '=' + mode.name)
+ uid = mode.unique_id() + '_'
+ for key, value in options.dict().items():
+ if key.startswith(uid):
+ result.append('--%s=%s' % (key[len(uid):], value))
+ return result
+
+def my_host(headers):
+ return headers.get('host') or httpserver.my_host()
+
+def my_server():
+ if gamesrv.game:
+ s = gamesrv.opentcpsocket()
+ return ((gamesrv.HOSTNAME, gamesrv.displaysockport(s)),
+ gamesrv.game.FnDesc)
+ else:
+ return None
+
+def my_server_address():
+ running = my_server()
+ if running:
+ (host, port), info = running
+ return '%s:%d' % (host, port)
+ else:
+ return None
+
+##def my_server_meta_address():
+## s = gamesrv.opentcpsocket()
+## ps = gamesrv.openpingsocket()
+## hs = gamesrv.openhttpsocket()
+## fullname = gamesrv.HOSTNAME
+## try:
+## fullname = socket.gethostbyaddr(fullname)[0]
+## except socket.error:
+## pass
+## return '%s:%s:%s:%s' % (fullname,
+## gamesrv.displaysockport(s),
+## gamesrv.displaysockport(ps),
+## gamesrv.displaysockport(hs))
+
+##def meta_register():
+## # Note: this tries to open a direct HTTP connection to the meta-server
+## # which may not work if the proxy is not configured in $http_proxy
+## try:
+## import urllib
+## except ImportError:
+## print >> sys.stderr, "cannot register with the meta-server: Python's urllib missing"
+## return
+## print "registering with the meta-server...",
+## sys.stdout.flush()
+## addr = my_server_meta_address()
+## try:
+## f = urllib.urlopen('%s?a=%s&desc=%s' % (
+## METASERVER, addr, quote_plus(gamesrv.game.FnDesc)))
+## f.close()
+## except Exception, e:
+## print
+## print >> sys.stderr, "cannot contact the meta-server (check $http_proxy):"
+## print >> sys.stderr, "%s: %s" % (e.__class__.__name__, e)
+## else:
+## print "ok"
+## unregister_at_exit(addr)
+
+##def meta_unregister(addr):
+## import urllib
+## print "unregistering from the meta-server...",
+## sys.stdout.flush()
+## try:
+## f = urllib.urlopen(METASERVER + '?d=' + addr)
+## f.close()
+## except Exception, e:
+## print "failed"
+## else:
+## print "ok"
+
+##def unregister_at_exit(addr, firsttime=[1]):
+## if firsttime:
+## import atexit
+## atexit.register(meta_unregister, addr)
+## del firsttime[:]
+
+QuoteTranslation = {}
+for c in ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ 'abcdefghijklmnopqrstuvwxyz'
+ '0123456789' '_.-'):
+ QuoteTranslation[c] = c
+del c
+QuoteTranslation[' '] = '+'
+
+def quote_plus(s):
+ """Quote the query fragment of a URL; replacing ' ' with '+'"""
+ getter = QuoteTranslation.get
+ return ''.join([getter(c, '%%%02X' % ord(c)) for c in s])
+
+
+def main(Game, save_url_to=None, quiet=0):
+ #gamesrv.openpingsocket(0) # try to reserve the standard UDP port
+ srv = PageServer(Game)
+ srv.registerpages()
+ if not srv.opensocket():
+ print >> sys.stderr, "server aborted."
+ sys.exit(1)
+ if quiet:
+ if Game:
+ Game.Quiet = 1
+ import stdlog
+ f = stdlog.LogFile()
+ if f:
+ print "Logging to", f.filename
+ sys.stdout = sys.stderr = f
+ if save_url_to:
+ data = srv.indexurl + '\n'
+ def try_to_unlink(fn):
+ try:
+ os.unlink(fn)
+ except:
+ pass
+ import atexit
+ atexit.register(try_to_unlink, save_url_to)
+ try:
+ fno = os.open(save_url_to, os.O_CREAT | os.O_TRUNC | os.O_WRONLY,
+ 0600)
+ if os.write(fno, data) != len(data):
+ raise OSError
+ os.close(fno)
+ except:
+ f = open(save_url_to, 'w')
+ f.write(data)
+ f.close()
+ #if webbrowser:
+ # srv.launchbrowser()
+
+
+# ____________________________________________________________
+# Hack hack hack - workaround for the fact that on Windows
+# the socket is inherited by the subprocess, which is quite
+# bad because it keeps the browser-server connexion alive
+# and the browser gets confused
+
+
+def schedule_launch(args):
+ httpserver.actions_when_finished.append(lambda args=args: launch(args))
+
+def launch(args):
+ # platform-specific hacks
+ print 'Running client -> ', ' '.join(args)
+ if 0: # OLD CODE sys.platform == 'darwin': # must start as a UI process
+ import tempfile
+ cmdname = tempfile.mktemp('_BubBob.py')
+ f = open(cmdname, 'w')
+ print >> f, 'import sys, os'
+ print >> f, 'try: os.unlink(%r)' % cmdname
+ print >> f, 'except OSError: pass'
+ print >> f, 'sys.argv[:] = %r' % (args,)
+ print >> f, '__file__ = %r' % cmdname
+ print >> f, 'execfile(%r)' % args[0]
+ f.close()
+ os.system('/usr/bin/open -a PythonLauncher "%s"' % cmdname)
+ else:
+ args.insert(0, sys.executable)
+ # try to close the open fds first
+ if hasattr(os, 'fork'):
+ try:
+ from resource import getrlimit, RLIMIT_NOFILE, error
+ except ImportError:
+ pass
+ else:
+ try:
+ soft, hard = getrlimit(RLIMIT_NOFILE)
+ except error:
+ pass
+ else:
+ if os.fork():
+ return # in parent -- done, continue
+ # in child
+ for fd in range(3, min(16384, hard)):
+ try:
+ os.close(fd)
+ except OSError:
+ pass
+ os.execv(args[0], args)
+ # this point should never be reached
+ # fall-back
+ # (quoting sucks on Windows) ** 42
+ if sys.platform == 'win32':
+ args[0] = '"%s"' % (args[0],)
+ if hasattr(os, 'P_DETACH'):
+ mode = os.P_DETACH
+ elif hasattr(os, 'P_NOWAIT0'):
+ mode = os.P_NOWAIT0
+ else:
+ mode = os.P_NOWAIT
+ os.spawnv(mode, sys.executable, args)
+
+if sys.platform != "win32":
+ def no_quote_worries(s):
+ return s
+else:
+ def no_quote_worries(s): # quoting !&?+*:-(
+ s = os.path.normpath(os.path.abspath(s))
+ absroot = os.path.join(LOCALDIR, os.pardir)
+ absroot = os.path.normpath(os.path.abspath(absroot))
+ ROOTDIR = os.curdir
+ while os.path.normpath(os.path.abspath(ROOTDIR)) != absroot:
+ if ROOTDIR == os.curdir:
+ ROOTDIR = os.pardir
+ else:
+ ROOTDIR = os.path.join(ROOTDIR, os.pardir)
+ if len(ROOTDIR) > 200:
+ # cannot find relative path! try with absolute one anyway
+ ROOTDIR = absroot
+ break
+ assert s.startswith(absroot)
+ if absroot.endswith(os.sep): # 'C:\'
+ absroot = absroot[:-1]
+ assert s[len(absroot)] == os.sep
+ relpath = s[len(absroot)+1:]
+ result = os.path.join(ROOTDIR, relpath)
+ print "no_quote_worries %r => %r" % (s, result)
+ return result
+
+
+if __name__ == '__main__':
+ if (len(sys.argv) != 3 or sys.argv[1] != '--quiet' or
+ not sys.argv[2].startswith('--saveurlto=')):
+ print >> sys.stderr, "This script should only be launched by BubBob.py."
+ sys.exit(2)
+ main(None, sys.argv[2][len('--saveurlto='):], quiet=1)
+ gamesrv.mainloop()
diff --git a/http2/sf/bb12.py b/http2/sf/bb12.py
new file mode 100755
index 0000000..7ea6e6e
--- /dev/null
+++ b/http2/sf/bb12.py
@@ -0,0 +1,274 @@
+#! /usr/bin/python
+
+import cgi, os, string, time
+form = cgi.FieldStorage()
+
+def txtfilter(s):
+ l = filter(lambda c: c in "!$*,-.0123456789:@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}", s)
+ return string.join(l, '')
+
+def identity(s):
+ return s
+
+def fieldlist(name, filter=txtfilter):
+ result = []
+ if form.has_key(name):
+ field = form[name]
+ if type(field) is type([]):
+ for f in field:
+ result.append(filter(f.value))
+ else:
+ result.append(filter(field.value))
+ return result
+
+def goodmatch(addr1, addr2):
+ l1 = string.split(addr1, '.')
+ if len(l1) >= 4: del l1[-1]
+ l2 = string.split(addr2, '.')
+ if len(l2) >= 4: del l2[-1]
+ return l1 == l2
+
+
+class Entry:
+ Notice = ''
+ FIELDS = [('server', 128), ('desc', 128), ('icon', 64),
+ ('orig', 64), ('dele1', 64), ('dele2', 64)]
+
+ def __init__(self, f):
+ self.pos = f.tell()
+ for fname, flen in self.FIELDS:
+ s = f.read(flen)
+ if not s:
+ self.filled = 0
+ break
+ setattr(self, fname, string.rstrip(s))
+ else:
+ self.filled = 1
+
+ def __nonzero__(self):
+ return self.filled
+
+ def write(self, f):
+ if not getattr(self, 'icon', ''):
+ try:
+ import random
+ lst = os.listdir('../htdocs/images')
+ except:
+ pass
+ else:
+ lst = filter(lambda x: x[-4:]=='.png' and 'A'<=x[0]<='Z', lst)
+ if lst:
+ self.icon = random.choice(lst)
+ f.seek(self.pos)
+ for fname, flen in self.FIELDS:
+ data = getattr(self, fname, '')[:flen]
+ f.write(data + ' '*(flen-len(data)))
+
+
+def main():
+ DATABASE = 'servers'
+ SIZEMAX = 65536
+ Serv = 0
+ Orig = 1
+ Dele1 = 2
+ REMOTE_ADDR = os.environ['REMOTE_ADDR']
+ REMOTE_ID = REMOTE_ADDR + time.strftime('@%d%m', time.localtime(time.time()))
+ OPS = {}
+
+ for srv in fieldlist('d'):
+ OPS[srv] = 'd'
+ for srv in fieldlist('a'):
+ OPS[srv] = 'a'
+ desc = (fieldlist('desc', identity) or [''])[0]
+
+ f = open(DATABASE, 'r+b')
+ freelist = []
+ published = []
+ while 1:
+ e = Entry(f)
+ if not e:
+ break
+ if e.server:
+ if OPS.get(e.server) == 'a':
+ validdesc = desc and goodmatch(REMOTE_ADDR, e.orig)
+ if e.dele1 or e.dele2 or (validdesc and desc != e.desc):
+ e.dele1 = e.dele2 = '' # re-enable server
+ if validdesc: e.desc = desc
+ e.write(f)
+ del OPS[e.server]
+ elif OPS.get(e.server) == 'd':
+ if goodmatch(REMOTE_ADDR, e.orig) or (
+ REMOTE_ID != e.dele1 and REMOTE_ID != e.dele2):
+ if goodmatch(REMOTE_ADDR, e.orig):
+ e.server = '' # remove server
+ elif e.dele1 == '':
+ e.dele1 = REMOTE_ID
+ elif e.dele2 == '':
+ e.dele2 = REMOTE_ID
+ else:
+ e.server = '' # remove server
+ e.write(f)
+ Entry.Notice = 'd'
+ if e.server:
+ published.append((e.pos, e))
+ else:
+ freelist.append(e)
+
+ for srv, action in OPS.items():
+ if action == 'a':
+ if freelist:
+ e = freelist[-1]
+ del freelist[-1]
+ else:
+ f.seek(0, 2)
+ e = Entry(f)
+ if e.pos >= SIZEMAX:
+ raise Exception("Sorry, server database too big")
+ hostname = string.split(srv, ':')[0]
+ if '.' not in hostname:
+ Entry.Notice = 'Server hostname "%s" incomplete.' % hostname
+ else:
+ import socket
+ try:
+ result = socket.gethostbyaddr(hostname)
+ except socket.error, e:
+ Entry.Notice = ('%s: %s' % (hostname, e))
+ else:
+ if result[0] == 'projects.sourceforge.net': # ????
+ Entry.Notice = ('Server hostname "%s" does not exist.' %
+ hostname)
+ else:
+ e.server = srv
+ e.icon = ''
+ e.desc = desc
+ e.orig = REMOTE_ADDR
+ e.dele1 = e.dele2 = ''
+ e.write(f)
+ published.append((e.pos, e))
+ Entry.Notice = 'a'
+
+ f.close()
+
+ published.sort()
+ return map(lambda (pos, e): e, published)
+
+
+def publish_list(serverlist):
+ url = (fieldlist('url', identity) or ['http://127.0.0.1:8000'])[0]
+ query = []
+ for s in fieldlist('redirected'):
+ query.append('redirected=' + s)
+ for s in serverlist:
+ query.append('s=' + txtfilter(s.server))
+ url = url + '?' + string.join(query, '&')
+ for s in fieldlist('frag'):
+ url = url + '#' + s
+ print 'Content-Type: text/html'
+ print 'Location:', url
+ print
+ print '<html><head></head><body>'
+ print 'Please <a href="%s">click here</a> to continue.' % url
+ print '</body></html>'
+
+def publish_default(serverlist):
+ import htmlentitydefs
+ text_to_html = {}
+ for key, value in htmlentitydefs.entitydefs.items():
+ text_to_html[value] = '&' + key + ';'
+ for i in range(32):
+ text_to_html[chr(i)] = '?'
+ def htmlquote(s, getter=text_to_html.get):
+ lst = []
+ for c in s: lst.append(getter(c, c))
+ return string.join(lst, '')
+
+ REMOTE_ADDR = os.environ['REMOTE_ADDR']
+ f = open('started.html', 'r')
+ header, row, footer = string.split(f.read(), '\\')
+ f.close()
+ import sys
+ print 'Content-Type: text/html'
+ print
+ sys.stdout.write(header % "List of registered Internet Servers")
+ counter = 0
+ for s in serverlist:
+ if s.icon:
+ s1 = '<img width=32 height=32 src="/images/%s">' % s.icon
+ else:
+ s1 = ''
+ lst = string.split(txtfilter(s.server), ':')
+ hostname, port, udpport, httpport = (lst+['?','?','?','?'])[:4]
+ s2 = '<strong>%s</strong>' % hostname
+ try:
+ int(httpport)
+ except ValueError:
+ pass
+ else:
+ s2 = '<a href="http://%s:%s/">%s:%s</a>' % (hostname, httpport,
+ s2, port)
+ s2 = '<font size=+1>' + s2 + '</font>'
+ if s.desc:
+ s2 = s2 + '&nbsp;&nbsp;&nbsp;playing&nbsp;&nbsp;<strong>%s</strong>' % htmlquote(s.desc)
+ if goodmatch(REMOTE_ADDR, s.orig):
+ s2 = s2 + '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="bb12.py?d=%s"><i>(if this server is dead, click here to remove it)</i></a>' % s.server
+ sys.stdout.write(row % (s1, ('#C0D0D0', '#E0D0A8')[counter&1], s2))
+ counter = counter + 1
+ if not serverlist:
+ sys.stdout.write(row % ('', '#FFFFFF', 'There is no registered server at the moment.'))
+ sys.stdout.write(footer % "If your browser understands Java, you can click on a server to join the game. Note however that you will still need to install the whole Python client to benefit from the background musics, as this feature is missing from the Java client.<br><br>This list might contain already-dead servers; such 'zombies' disappear after some time.")
+
+def publish_raw(serverlist):
+ print 'Content-Type: text/plain'
+ print
+ print 'Raw list produced for', os.environ['REMOTE_ADDR']
+ print
+ for s in serverlist:
+ print repr((s.server, s.desc, s.icon, s.orig))
+
+def publish_img(serverlist):
+ import sys
+ print 'Content-Type: image/png'
+ print
+ f = open('sfbub.png', 'rb')
+ sys.stdout.write(f.read())
+ f.close()
+
+def publish_register(serverlist):
+ if Entry.Notice == 'a':
+ banner = 'The game server is now registered to SourceForge.'
+ elif Entry.Notice == 'd':
+ banner = ('Server <font color="#FF8000">unregistered</font> '
+ 'from SourceForge.')
+ elif Entry.Notice == '':
+ if fieldlist('a'):
+ banner = "The game server is already registered to SourceForge."
+ elif fieldlist('d'):
+ banner = 'The game server was <font color="#FF8000">already absent</font> from SourceForge.'
+ else:
+ publish_default(serverlist)
+ return
+ else: # errors
+ banner = ('%s<br><br>' % Entry.Notice +
+ 'If you are behind a firewall or NAT device (e.g. ADSL routers) you can still make your server reachable but it requires manual configuration. (Instructions not available yet -- sorry)')
+ f = open('started.html', 'r')
+ header, row, footer = string.split(f.read(), '\\')
+ f.close()
+ import sys
+ print 'Content-Type: text/html'
+ print
+ sys.stdout.write(header % banner)
+ sys.stdout.write(footer % 'Press <a href="javascript: back()">Back</a> to come back to the main page.')
+
+
+try:
+ slist = main()
+ cmd = (fieldlist('cmd') or ['?'])[0]
+ publish = globals().get('publish_'+cmd, publish_default)
+ publish(slist)
+except:
+ import traceback, sys
+ print "Content-Type: text/plain"
+ print
+ print "ERROR REPORT"
+ print
+ traceback.print_exc(file=sys.stdout)
diff --git a/http2/sf/sfbub.png b/http2/sf/sfbub.png
new file mode 100644
index 0000000..142f3b3
--- /dev/null
+++ b/http2/sf/sfbub.png
Binary files differ
diff --git a/http2/sf/started.html b/http2/sf/started.html
new file mode 100644
index 0000000..14c24e3
--- /dev/null
+++ b/http2/sf/started.html
@@ -0,0 +1,44 @@
+<html>
+<head><title>The (old) Bub's Brothers on SourceForge</title>
+</head>
+<body text="#000000" bgcolor="#C0FFC0" link="#0000EE" vlink="#000099" alink="#FF0000">
+
+<h1>The (old) Bub's Brothers on SourceForge</h1>
+
+<br>
+
+<h2>This meta-server is now obsolete</h2>
+<p>It has never been too useful because nowadays everybody is behind firewalls and NAT translation devices (e.g. ADSL routers). So:</p>
+<p><strong>There is a much better meta-server <a href="http://ctpug.org.za:8050/">somewhere else</a> that works with the <a href="http://bub-n-bros.sourceforge.net/download.html">next version of Bub-n-bros</a>. Upgrade to Bub-n-bros 1.3 and enjoy !</strong></p>
+<p>This page is left here just in case it is useful to someone, but you should really update if you want to enjoy a cool meta-server <code>:-)</code></p>
+
+<br><hr><br><hr><br>
+
+<table width="100%%" border=0 cellspacing=6>
+<tr>
+ <td width="10%%" align="center"><img src="../images/sfbub.png"></td>
+ <td width="90%%" bgcolor="#008000"><font color="#FFFF00" size=+1><strong>&nbsp;&nbsp;&nbsp;%s</strong></font></td>
+</form>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td>&nbsp;</td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td bgcolor="#FFFFFF"><table width="100%%" border=0 cellspacing=5>
+\
+<tr><td align="right">%s&nbsp;&nbsp;&nbsp;</td>
+<td bgcolor="%s" valign="center">&nbsp;&nbsp;&nbsp;&nbsp;%s</td>
+</tr>
+\
+ </table></td>
+</tr>
+
+</table>
+<br><hr><br>
+<p><font size=-1>%s</font></p>
+<p align="right"><a href="http://sourceforge.net"><img src="http://sourceforge.net/sflogo.php?group_id=72187&amp;type=2" width="125" height="37" border="0" alt="SourceForge.net Logo" /></a></p>
+</body></html>