annotate upmana/mercurial/hgweb/server.py @ 248:1df5912db00c beta tip

Traipse Beta 'OpenRPG' {101205-00} Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc's main goal is to offer more advanced features and enhance the productivity of the user. Update Summary (Closed) New Features: New to Map, can re-order Grid, Miniatures, and Whiteboard layer draw order New to Server GUI, can now clear log New Earthdawn Dieroller New IronClaw roller, sheet, and image New ShapeShifter PC Sheet Updates: Update to Warhammer PC Sheet. Rollers set as macros. Should work with little maintanence. Update to Browser Server window. Display rooms with ' " & cleaner Update to Server. Handles ' " & cleaner Update to Dieroller. Cleaner, more effecient expression system Update to Hidden Die plugin, allows for non standard dice rolls Update to location.py, allows for more portable references when starting Traipse Update to the Features node Fixes: Fix to InterParse that was causing an Infernal Loop with Namespace Internal Fix to XML data, removed old Minidom and switched to Element Tree Fix to Server that was causing eternal attempt to find a Server ID, in Register Rooms thread Fix to Server, removing wxPython dependencies where not needed Fix to metaservers.xml file not being created Fix to Single and Double quotes in Whiteboard text Fix to Background images not showing when using the Image Server Fix to Duplicate chat names appearing Fix to Server GUI's logging output Fix to FNB.COLORFUL_TABS bug Fix to Gametree for XSLT Sheets Fix to Gametree for locating gametree files Fix to Send to Chat from Gametree Fix to Gametree, renaming and remapping operates correctly Fix to aliaslib, prevents error caused when SafeHTML is sent None
author sirebral
date Sun, 05 Dec 2010 10:53:30 -0600
parents dcf4fbe09b70
children
rev   line source
135
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
1 # hgweb/server.py - The standalone hg web server.
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
2 #
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
5 #
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
6 # This software may be used and distributed according to the terms of the
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
7 # GNU General Public License version 2, incorporated herein by reference.
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
8
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
9 import os, sys, errno, urllib, BaseHTTPServer, socket, SocketServer, traceback
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
10 from upmana.mercurial import hg, util, error
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
11 from hgweb_mod import hgweb
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
12 from hgwebdir_mod import hgwebdir
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
13 from upmana.mercurial.i18n import _
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
14
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
15 def _splitURI(uri):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
16 """ Return path and query splited from uri
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
17
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
18 Just like CGI environment, the path is unquoted, the query is
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
19 not.
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
20 """
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
21 if '?' in uri:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
22 path, query = uri.split('?', 1)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
23 else:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
24 path, query = uri, ''
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
25 return urllib.unquote(path), query
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
26
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
27 class _error_logger(object):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
28 def __init__(self, handler):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
29 self.handler = handler
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
30 def flush(self):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
31 pass
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
32 def write(self, str):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
33 self.writelines(str.split('\n'))
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
34 def writelines(self, seq):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
35 for msg in seq:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
36 self.handler.log_error("HG error: %s", msg)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
37
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
38 class _hgwebhandler(object, BaseHTTPServer.BaseHTTPRequestHandler):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
39
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
40 url_scheme = 'http'
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
41
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
42 def __init__(self, *args, **kargs):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
43 self.protocol_version = 'HTTP/1.1'
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
44 BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kargs)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
45
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
46 def _log_any(self, fp, format, *args):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
47 fp.write("%s - - [%s] %s\n" % (self.client_address[0],
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
48 self.log_date_time_string(),
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
49 format % args))
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
50 fp.flush()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
51
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
52 def log_error(self, format, *args):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
53 self._log_any(self.server.errorlog, format, *args)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
54
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
55 def log_message(self, format, *args):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
56 self._log_any(self.server.accesslog, format, *args)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
57
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
58 def do_write(self):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
59 try:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
60 self.do_hgweb()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
61 except socket.error, inst:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
62 if inst[0] != errno.EPIPE:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
63 raise
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
64
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
65 def do_POST(self):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
66 try:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
67 self.do_write()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
68 except StandardError:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
69 self._start_response("500 Internal Server Error", [])
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
70 self._write("Internal Server Error")
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
71 tb = "".join(traceback.format_exception(*sys.exc_info()))
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
72 self.log_error("Exception happened during processing "
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
73 "request '%s':\n%s", self.path, tb)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
74
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
75 def do_GET(self):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
76 self.do_POST()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
77
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
78 def do_hgweb(self):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
79 path, query = _splitURI(self.path)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
80
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
81 env = {}
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
82 env['GATEWAY_INTERFACE'] = 'CGI/1.1'
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
83 env['REQUEST_METHOD'] = self.command
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
84 env['SERVER_NAME'] = self.server.server_name
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
85 env['SERVER_PORT'] = str(self.server.server_port)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
86 env['REQUEST_URI'] = self.path
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
87 env['SCRIPT_NAME'] = self.server.prefix
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
88 env['PATH_INFO'] = path[len(self.server.prefix):]
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
89 env['REMOTE_HOST'] = self.client_address[0]
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
90 env['REMOTE_ADDR'] = self.client_address[0]
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
91 if query:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
92 env['QUERY_STRING'] = query
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
93
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
94 if self.headers.typeheader is None:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
95 env['CONTENT_TYPE'] = self.headers.type
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
96 else:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
97 env['CONTENT_TYPE'] = self.headers.typeheader
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
98 length = self.headers.getheader('content-length')
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
99 if length:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
100 env['CONTENT_LENGTH'] = length
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
101 for header in [h for h in self.headers.keys()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
102 if h not in ('content-type', 'content-length')]:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
103 hkey = 'HTTP_' + header.replace('-', '_').upper()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
104 hval = self.headers.getheader(header)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
105 hval = hval.replace('\n', '').strip()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
106 if hval:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
107 env[hkey] = hval
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
108 env['SERVER_PROTOCOL'] = self.request_version
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
109 env['wsgi.version'] = (1, 0)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
110 env['wsgi.url_scheme'] = self.url_scheme
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
111 env['wsgi.input'] = self.rfile
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
112 env['wsgi.errors'] = _error_logger(self)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
113 env['wsgi.multithread'] = isinstance(self.server,
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
114 SocketServer.ThreadingMixIn)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
115 env['wsgi.multiprocess'] = isinstance(self.server,
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
116 SocketServer.ForkingMixIn)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
117 env['wsgi.run_once'] = 0
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
118
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
119 self.close_connection = True
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
120 self.saved_status = None
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
121 self.saved_headers = []
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
122 self.sent_headers = False
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
123 self.length = None
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
124 for chunk in self.server.application(env, self._start_response):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
125 self._write(chunk)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
126
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
127 def send_headers(self):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
128 if not self.saved_status:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
129 raise AssertionError("Sending headers before "
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
130 "start_response() called")
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
131 saved_status = self.saved_status.split(None, 1)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
132 saved_status[0] = int(saved_status[0])
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
133 self.send_response(*saved_status)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
134 should_close = True
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
135 for h in self.saved_headers:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
136 self.send_header(*h)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
137 if h[0].lower() == 'content-length':
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
138 should_close = False
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
139 self.length = int(h[1])
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
140 # The value of the Connection header is a list of case-insensitive
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
141 # tokens separated by commas and optional whitespace.
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
142 if 'close' in [token.strip().lower() for token in
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
143 self.headers.get('connection', '').split(',')]:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
144 should_close = True
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
145 if should_close:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
146 self.send_header('Connection', 'close')
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
147 self.close_connection = should_close
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
148 self.end_headers()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
149 self.sent_headers = True
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
150
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
151 def _start_response(self, http_status, headers, exc_info=None):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
152 code, msg = http_status.split(None, 1)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
153 code = int(code)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
154 self.saved_status = http_status
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
155 bad_headers = ('connection', 'transfer-encoding')
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
156 self.saved_headers = [h for h in headers
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
157 if h[0].lower() not in bad_headers]
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
158 return self._write
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
159
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
160 def _write(self, data):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
161 if not self.saved_status:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
162 raise AssertionError("data written before start_response() called")
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
163 elif not self.sent_headers:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
164 self.send_headers()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
165 if self.length is not None:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
166 if len(data) > self.length:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
167 raise AssertionError("Content-length header sent, but more "
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
168 "bytes than specified are being written.")
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
169 self.length = self.length - len(data)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
170 self.wfile.write(data)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
171 self.wfile.flush()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
172
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
173 class _shgwebhandler(_hgwebhandler):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
174
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
175 url_scheme = 'https'
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
176
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
177 def setup(self):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
178 self.connection = self.request
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
179 self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
180 self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
181
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
182 def do_write(self):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
183 from OpenSSL.SSL import SysCallError
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
184 try:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
185 super(_shgwebhandler, self).do_write()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
186 except SysCallError, inst:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
187 if inst.args[0] != errno.EPIPE:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
188 raise
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
189
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
190 def handle_one_request(self):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
191 from OpenSSL.SSL import SysCallError, ZeroReturnError
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
192 try:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
193 super(_shgwebhandler, self).handle_one_request()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
194 except (SysCallError, ZeroReturnError):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
195 self.close_connection = True
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
196 pass
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
197
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
198 def create_server(ui, repo):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
199 use_threads = True
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
200
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
201 def openlog(opt, default):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
202 if opt and opt != '-':
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
203 return open(opt, 'a')
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
204 return default
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
205
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
206 if repo is None:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
207 myui = ui
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
208 else:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
209 myui = repo.ui
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
210 address = myui.config("web", "address", "")
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
211 port = int(myui.config("web", "port", 8000))
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
212 prefix = myui.config("web", "prefix", "")
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
213 if prefix:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
214 prefix = "/" + prefix.strip("/")
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
215 use_ipv6 = myui.configbool("web", "ipv6")
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
216 webdir_conf = myui.config("web", "webdir_conf")
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
217 ssl_cert = myui.config("web", "certificate")
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
218 accesslog = openlog(myui.config("web", "accesslog", "-"), sys.stdout)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
219 errorlog = openlog(myui.config("web", "errorlog", "-"), sys.stderr)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
220
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
221 if use_threads:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
222 try:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
223 from threading import activeCount
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
224 except ImportError:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
225 use_threads = False
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
226
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
227 if use_threads:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
228 _mixin = SocketServer.ThreadingMixIn
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
229 else:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
230 if hasattr(os, "fork"):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
231 _mixin = SocketServer.ForkingMixIn
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
232 else:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
233 class _mixin:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
234 pass
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
235
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
236 class MercurialHTTPServer(object, _mixin, BaseHTTPServer.HTTPServer):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
237
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
238 # SO_REUSEADDR has broken semantics on windows
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
239 if os.name == 'nt':
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
240 allow_reuse_address = 0
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
241
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
242 def __init__(self, *args, **kargs):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
243 BaseHTTPServer.HTTPServer.__init__(self, *args, **kargs)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
244 self.accesslog = accesslog
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
245 self.errorlog = errorlog
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
246 self.daemon_threads = True
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
247 def make_handler():
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
248 if webdir_conf:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
249 hgwebobj = hgwebdir(webdir_conf, ui)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
250 elif repo is not None:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
251 hgwebobj = hgweb(hg.repository(repo.ui, repo.root))
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
252 else:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
253 raise error.RepoError(_("There is no Mercurial repository"
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
254 " here (.hg not found)"))
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
255 return hgwebobj
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
256 self.application = make_handler()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
257
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
258 if ssl_cert:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
259 try:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
260 from OpenSSL import SSL
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
261 ctx = SSL.Context(SSL.SSLv23_METHOD)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
262 except ImportError:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
263 raise util.Abort(_("SSL support is unavailable"))
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
264 ctx.use_privatekey_file(ssl_cert)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
265 ctx.use_certificate_file(ssl_cert)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
266 sock = socket.socket(self.address_family, self.socket_type)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
267 self.socket = SSL.Connection(ctx, sock)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
268 self.server_bind()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
269 self.server_activate()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
270
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
271 self.addr, self.port = self.socket.getsockname()[0:2]
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
272 self.prefix = prefix
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
273 self.fqaddr = socket.getfqdn(address)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
274
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
275 class IPv6HTTPServer(MercurialHTTPServer):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
276 address_family = getattr(socket, 'AF_INET6', None)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
277
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
278 def __init__(self, *args, **kwargs):
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
279 if self.address_family is None:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
280 raise error.RepoError(_('IPv6 is not available on this system'))
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
281 super(IPv6HTTPServer, self).__init__(*args, **kwargs)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
282
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
283 if ssl_cert:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
284 handler = _shgwebhandler
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
285 else:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
286 handler = _hgwebhandler
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
287
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
288 # ugly hack due to python issue5853 (for threaded use)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
289 import mimetypes; mimetypes.init()
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
290
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
291 try:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
292 if use_ipv6:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
293 return IPv6HTTPServer((address, port), handler)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
294 else:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
295 return MercurialHTTPServer((address, port), handler)
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
296 except socket.error, inst:
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
297 raise util.Abort(_("cannot start server at '%s:%d': %s")
dcf4fbe09b70 Traipse Beta 'OpenRPG' {091010-00}
sirebral
parents:
diff changeset
298 % (address, port, inst.args[1]))