annotate upmana/mercurial/hgweb/server.py @ 39:ed322725b928 ornery-orc tip

Traipse 'OpenRPG' {110114-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 Fri, 14 Jan 2011 05:24:52 -0600
parents ff154cf3350c
children
rev   line source
28
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1 # hgweb/server.py - The standalone hg web server.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
2 #
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
5 #
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
6 # This software may be used and distributed according to the terms of the
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
7 # GNU General Public License version 2, incorporated herein by reference.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
8
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
9 import os, sys, errno, urllib, BaseHTTPServer, socket, SocketServer, traceback
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
10 from upmana.mercurial import hg, util, error
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
11 from hgweb_mod import hgweb
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
12 from hgwebdir_mod import hgwebdir
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
13 from upmana.mercurial.i18n import _
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
14
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
15 def _splitURI(uri):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
16 """ Return path and query splited from uri
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
17
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
18 Just like CGI environment, the path is unquoted, the query is
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
19 not.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
20 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
21 if '?' in uri:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
22 path, query = uri.split('?', 1)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
23 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
24 path, query = uri, ''
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
25 return urllib.unquote(path), query
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
26
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
27 class _error_logger(object):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
28 def __init__(self, handler):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
29 self.handler = handler
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
30 def flush(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
31 pass
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
32 def write(self, str):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
33 self.writelines(str.split('\n'))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
34 def writelines(self, seq):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
35 for msg in seq:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
36 self.handler.log_error("HG error: %s", msg)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
37
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
38 class _hgwebhandler(object, BaseHTTPServer.BaseHTTPRequestHandler):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
39
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
40 url_scheme = 'http'
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
41
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
42 def __init__(self, *args, **kargs):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
43 self.protocol_version = 'HTTP/1.1'
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
44 BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kargs)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
45
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
46 def _log_any(self, fp, format, *args):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
47 fp.write("%s - - [%s] %s\n" % (self.client_address[0],
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
48 self.log_date_time_string(),
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
49 format % args))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
50 fp.flush()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
51
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
52 def log_error(self, format, *args):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
53 self._log_any(self.server.errorlog, format, *args)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
54
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
55 def log_message(self, format, *args):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
56 self._log_any(self.server.accesslog, format, *args)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
57
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
58 def do_write(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
59 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
60 self.do_hgweb()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
61 except socket.error, inst:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
62 if inst[0] != errno.EPIPE:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
63 raise
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
64
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
65 def do_POST(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
66 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
67 self.do_write()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
68 except StandardError:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
69 self._start_response("500 Internal Server Error", [])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
70 self._write("Internal Server Error")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
71 tb = "".join(traceback.format_exception(*sys.exc_info()))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
72 self.log_error("Exception happened during processing "
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
73 "request '%s':\n%s", self.path, tb)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
74
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
75 def do_GET(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
76 self.do_POST()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
77
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
78 def do_hgweb(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
79 path, query = _splitURI(self.path)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
80
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
81 env = {}
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
82 env['GATEWAY_INTERFACE'] = 'CGI/1.1'
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
83 env['REQUEST_METHOD'] = self.command
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
84 env['SERVER_NAME'] = self.server.server_name
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
85 env['SERVER_PORT'] = str(self.server.server_port)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
86 env['REQUEST_URI'] = self.path
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
87 env['SCRIPT_NAME'] = self.server.prefix
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
88 env['PATH_INFO'] = path[len(self.server.prefix):]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
89 env['REMOTE_HOST'] = self.client_address[0]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
90 env['REMOTE_ADDR'] = self.client_address[0]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
91 if query:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
92 env['QUERY_STRING'] = query
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
93
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
94 if self.headers.typeheader is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
95 env['CONTENT_TYPE'] = self.headers.type
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
96 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
97 env['CONTENT_TYPE'] = self.headers.typeheader
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
98 length = self.headers.getheader('content-length')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
99 if length:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
100 env['CONTENT_LENGTH'] = length
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
101 for header in [h for h in self.headers.keys()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
102 if h not in ('content-type', 'content-length')]:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
103 hkey = 'HTTP_' + header.replace('-', '_').upper()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
104 hval = self.headers.getheader(header)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
105 hval = hval.replace('\n', '').strip()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
106 if hval:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
107 env[hkey] = hval
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
108 env['SERVER_PROTOCOL'] = self.request_version
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
109 env['wsgi.version'] = (1, 0)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
110 env['wsgi.url_scheme'] = self.url_scheme
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
111 env['wsgi.input'] = self.rfile
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
112 env['wsgi.errors'] = _error_logger(self)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
113 env['wsgi.multithread'] = isinstance(self.server,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
114 SocketServer.ThreadingMixIn)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
115 env['wsgi.multiprocess'] = isinstance(self.server,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
116 SocketServer.ForkingMixIn)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
117 env['wsgi.run_once'] = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
118
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
119 self.close_connection = True
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
120 self.saved_status = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
121 self.saved_headers = []
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
122 self.sent_headers = False
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
123 self.length = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
124 for chunk in self.server.application(env, self._start_response):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
125 self._write(chunk)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
126
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
127 def send_headers(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
128 if not self.saved_status:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
129 raise AssertionError("Sending headers before "
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
130 "start_response() called")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
131 saved_status = self.saved_status.split(None, 1)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
132 saved_status[0] = int(saved_status[0])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
133 self.send_response(*saved_status)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
134 should_close = True
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
135 for h in self.saved_headers:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
136 self.send_header(*h)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
137 if h[0].lower() == 'content-length':
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
138 should_close = False
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
139 self.length = int(h[1])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
140 # The value of the Connection header is a list of case-insensitive
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
141 # tokens separated by commas and optional whitespace.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
142 if 'close' in [token.strip().lower() for token in
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
143 self.headers.get('connection', '').split(',')]:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
144 should_close = True
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
145 if should_close:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
146 self.send_header('Connection', 'close')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
147 self.close_connection = should_close
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
148 self.end_headers()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
149 self.sent_headers = True
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
150
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
151 def _start_response(self, http_status, headers, exc_info=None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
152 code, msg = http_status.split(None, 1)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
153 code = int(code)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
154 self.saved_status = http_status
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
155 bad_headers = ('connection', 'transfer-encoding')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
156 self.saved_headers = [h for h in headers
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
157 if h[0].lower() not in bad_headers]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
158 return self._write
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
159
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
160 def _write(self, data):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
161 if not self.saved_status:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
162 raise AssertionError("data written before start_response() called")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
163 elif not self.sent_headers:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
164 self.send_headers()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
165 if self.length is not None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
166 if len(data) > self.length:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
167 raise AssertionError("Content-length header sent, but more "
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
168 "bytes than specified are being written.")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
169 self.length = self.length - len(data)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
170 self.wfile.write(data)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
171 self.wfile.flush()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
172
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
173 class _shgwebhandler(_hgwebhandler):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
174
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
175 url_scheme = 'https'
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
176
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
177 def setup(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
178 self.connection = self.request
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
179 self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
180 self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
181
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
182 def do_write(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
183 from OpenSSL.SSL import SysCallError
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
184 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
185 super(_shgwebhandler, self).do_write()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
186 except SysCallError, inst:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
187 if inst.args[0] != errno.EPIPE:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
188 raise
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
189
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
190 def handle_one_request(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
191 from OpenSSL.SSL import SysCallError, ZeroReturnError
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
192 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
193 super(_shgwebhandler, self).handle_one_request()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
194 except (SysCallError, ZeroReturnError):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
195 self.close_connection = True
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
196 pass
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
197
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
198 def create_server(ui, repo):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
199 use_threads = True
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
200
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
201 def openlog(opt, default):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
202 if opt and opt != '-':
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
203 return open(opt, 'a')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
204 return default
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
205
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
206 if repo is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
207 myui = ui
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
208 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
209 myui = repo.ui
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
210 address = myui.config("web", "address", "")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
211 port = int(myui.config("web", "port", 8000))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
212 prefix = myui.config("web", "prefix", "")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
213 if prefix:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
214 prefix = "/" + prefix.strip("/")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
215 use_ipv6 = myui.configbool("web", "ipv6")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
216 webdir_conf = myui.config("web", "webdir_conf")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
217 ssl_cert = myui.config("web", "certificate")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
218 accesslog = openlog(myui.config("web", "accesslog", "-"), sys.stdout)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
219 errorlog = openlog(myui.config("web", "errorlog", "-"), sys.stderr)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
220
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
221 if use_threads:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
222 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
223 from threading import activeCount
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
224 except ImportError:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
225 use_threads = False
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
226
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
227 if use_threads:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
228 _mixin = SocketServer.ThreadingMixIn
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
229 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
230 if hasattr(os, "fork"):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
231 _mixin = SocketServer.ForkingMixIn
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
232 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
233 class _mixin:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
234 pass
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
235
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
236 class MercurialHTTPServer(object, _mixin, BaseHTTPServer.HTTPServer):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
237
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
238 # SO_REUSEADDR has broken semantics on windows
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
239 if os.name == 'nt':
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
240 allow_reuse_address = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
241
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
242 def __init__(self, *args, **kargs):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
243 BaseHTTPServer.HTTPServer.__init__(self, *args, **kargs)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
244 self.accesslog = accesslog
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
245 self.errorlog = errorlog
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
246 self.daemon_threads = True
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
247 def make_handler():
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
248 if webdir_conf:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
249 hgwebobj = hgwebdir(webdir_conf, ui)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
250 elif repo is not None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
251 hgwebobj = hgweb(hg.repository(repo.ui, repo.root))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
252 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
253 raise error.RepoError(_("There is no Mercurial repository"
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
254 " here (.hg not found)"))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
255 return hgwebobj
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
256 self.application = make_handler()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
257
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
258 if ssl_cert:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
259 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
260 from OpenSSL import SSL
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
261 ctx = SSL.Context(SSL.SSLv23_METHOD)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
262 except ImportError:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
263 raise util.Abort(_("SSL support is unavailable"))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
264 ctx.use_privatekey_file(ssl_cert)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
265 ctx.use_certificate_file(ssl_cert)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
266 sock = socket.socket(self.address_family, self.socket_type)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
267 self.socket = SSL.Connection(ctx, sock)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
268 self.server_bind()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
269 self.server_activate()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
270
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
271 self.addr, self.port = self.socket.getsockname()[0:2]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
272 self.prefix = prefix
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
273 self.fqaddr = socket.getfqdn(address)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
274
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
275 class IPv6HTTPServer(MercurialHTTPServer):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
276 address_family = getattr(socket, 'AF_INET6', None)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
277
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
278 def __init__(self, *args, **kwargs):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
279 if self.address_family is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
280 raise error.RepoError(_('IPv6 is not available on this system'))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
281 super(IPv6HTTPServer, self).__init__(*args, **kwargs)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
282
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
283 if ssl_cert:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
284 handler = _shgwebhandler
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
285 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
286 handler = _hgwebhandler
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
287
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
288 # ugly hack due to python issue5853 (for threaded use)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
289 import mimetypes; mimetypes.init()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
290
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
291 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
292 if use_ipv6:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
293 return IPv6HTTPServer((address, port), handler)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
294 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
295 return MercurialHTTPServer((address, port), handler)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
296 except socket.error, inst:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
297 raise util.Abort(_("cannot start server at '%s:%d': %s")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
298 % (address, port, inst.args[1]))