##// END OF EJS Templates
hgwebdir: reduce memory usage for index generation...
Wagner Bruna -
r13436:b391c0c9 stable
parent child Browse files
Show More
@@ -1,368 +1,370 b''
1 # hgweb/hgwebdir_mod.py - Web interface for a directory of repositories.
1 # hgweb/hgwebdir_mod.py - Web interface for a directory of repositories.
2 #
2 #
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 import os, re, time, urlparse
9 import os, re, time, urlparse
10 from mercurial.i18n import _
10 from mercurial.i18n import _
11 from mercurial import ui, hg, util, templater
11 from mercurial import ui, hg, util, templater
12 from mercurial import error, encoding
12 from mercurial import error, encoding
13 from common import ErrorResponse, get_mtime, staticfile, paritygen, \
13 from common import ErrorResponse, get_mtime, staticfile, paritygen, \
14 get_contact, HTTP_OK, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
14 get_contact, HTTP_OK, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
15 from hgweb_mod import hgweb
15 from hgweb_mod import hgweb
16 from request import wsgirequest
16 from request import wsgirequest
17 import webutil
17 import webutil
18
18
19 def cleannames(items):
19 def cleannames(items):
20 return [(util.pconvert(name).strip('/'), path) for name, path in items]
20 return [(util.pconvert(name).strip('/'), path) for name, path in items]
21
21
22 def findrepos(paths):
22 def findrepos(paths):
23 repos = []
23 repos = []
24 for prefix, root in cleannames(paths):
24 for prefix, root in cleannames(paths):
25 roothead, roottail = os.path.split(root)
25 roothead, roottail = os.path.split(root)
26 # "foo = /bar/*" makes every subrepo of /bar/ to be
26 # "foo = /bar/*" makes every subrepo of /bar/ to be
27 # mounted as foo/subrepo
27 # mounted as foo/subrepo
28 # and "foo = /bar/**" also recurses into the subdirectories,
28 # and "foo = /bar/**" also recurses into the subdirectories,
29 # remember to use it without working dir.
29 # remember to use it without working dir.
30 try:
30 try:
31 recurse = {'*': False, '**': True}[roottail]
31 recurse = {'*': False, '**': True}[roottail]
32 except KeyError:
32 except KeyError:
33 repos.append((prefix, root))
33 repos.append((prefix, root))
34 continue
34 continue
35 roothead = os.path.normpath(os.path.abspath(roothead))
35 roothead = os.path.normpath(os.path.abspath(roothead))
36 paths = util.walkrepos(roothead, followsym=True, recurse=recurse)
36 paths = util.walkrepos(roothead, followsym=True, recurse=recurse)
37 repos.extend(urlrepos(prefix, roothead, paths))
37 repos.extend(urlrepos(prefix, roothead, paths))
38 return repos
38 return repos
39
39
40 def urlrepos(prefix, roothead, paths):
40 def urlrepos(prefix, roothead, paths):
41 """yield url paths and filesystem paths from a list of repo paths
41 """yield url paths and filesystem paths from a list of repo paths
42
42
43 >>> list(urlrepos('hg', '/opt', ['/opt/r', '/opt/r/r', '/opt']))
43 >>> list(urlrepos('hg', '/opt', ['/opt/r', '/opt/r/r', '/opt']))
44 [('hg/r', '/opt/r'), ('hg/r/r', '/opt/r/r'), ('hg', '/opt')]
44 [('hg/r', '/opt/r'), ('hg/r/r', '/opt/r/r'), ('hg', '/opt')]
45 >>> list(urlrepos('', '/opt', ['/opt/r', '/opt/r/r', '/opt']))
45 >>> list(urlrepos('', '/opt', ['/opt/r', '/opt/r/r', '/opt']))
46 [('r', '/opt/r'), ('r/r', '/opt/r/r'), ('', '/opt')]
46 [('r', '/opt/r'), ('r/r', '/opt/r/r'), ('', '/opt')]
47 """
47 """
48 for path in paths:
48 for path in paths:
49 path = os.path.normpath(path)
49 path = os.path.normpath(path)
50 yield (prefix + '/' +
50 yield (prefix + '/' +
51 util.pconvert(path[len(roothead):]).lstrip('/')).strip('/'), path
51 util.pconvert(path[len(roothead):]).lstrip('/')).strip('/'), path
52
52
53 class hgwebdir(object):
53 class hgwebdir(object):
54 refreshinterval = 20
54 refreshinterval = 20
55
55
56 def __init__(self, conf, baseui=None):
56 def __init__(self, conf, baseui=None):
57 self.conf = conf
57 self.conf = conf
58 self.baseui = baseui
58 self.baseui = baseui
59 self.lastrefresh = 0
59 self.lastrefresh = 0
60 self.motd = None
60 self.motd = None
61 self.refresh()
61 self.refresh()
62
62
63 def refresh(self):
63 def refresh(self):
64 if self.lastrefresh + self.refreshinterval > time.time():
64 if self.lastrefresh + self.refreshinterval > time.time():
65 return
65 return
66
66
67 if self.baseui:
67 if self.baseui:
68 u = self.baseui.copy()
68 u = self.baseui.copy()
69 else:
69 else:
70 u = ui.ui()
70 u = ui.ui()
71 u.setconfig('ui', 'report_untrusted', 'off')
71 u.setconfig('ui', 'report_untrusted', 'off')
72 u.setconfig('ui', 'interactive', 'off')
72 u.setconfig('ui', 'interactive', 'off')
73
73
74 if not isinstance(self.conf, (dict, list, tuple)):
74 if not isinstance(self.conf, (dict, list, tuple)):
75 map = {'paths': 'hgweb-paths'}
75 map = {'paths': 'hgweb-paths'}
76 if not os.path.exists(self.conf):
76 if not os.path.exists(self.conf):
77 raise util.Abort(_('config file %s not found!') % self.conf)
77 raise util.Abort(_('config file %s not found!') % self.conf)
78 u.readconfig(self.conf, remap=map, trust=True)
78 u.readconfig(self.conf, remap=map, trust=True)
79 paths = u.configitems('hgweb-paths')
79 paths = u.configitems('hgweb-paths')
80 elif isinstance(self.conf, (list, tuple)):
80 elif isinstance(self.conf, (list, tuple)):
81 paths = self.conf
81 paths = self.conf
82 elif isinstance(self.conf, dict):
82 elif isinstance(self.conf, dict):
83 paths = self.conf.items()
83 paths = self.conf.items()
84
84
85 repos = findrepos(paths)
85 repos = findrepos(paths)
86 for prefix, root in u.configitems('collections'):
86 for prefix, root in u.configitems('collections'):
87 prefix = util.pconvert(prefix)
87 prefix = util.pconvert(prefix)
88 for path in util.walkrepos(root, followsym=True):
88 for path in util.walkrepos(root, followsym=True):
89 repo = os.path.normpath(path)
89 repo = os.path.normpath(path)
90 name = util.pconvert(repo)
90 name = util.pconvert(repo)
91 if name.startswith(prefix):
91 if name.startswith(prefix):
92 name = name[len(prefix):]
92 name = name[len(prefix):]
93 repos.append((name.lstrip('/'), repo))
93 repos.append((name.lstrip('/'), repo))
94
94
95 self.repos = repos
95 self.repos = repos
96 self.ui = u
96 self.ui = u
97 encoding.encoding = self.ui.config('web', 'encoding',
97 encoding.encoding = self.ui.config('web', 'encoding',
98 encoding.encoding)
98 encoding.encoding)
99 self.style = self.ui.config('web', 'style', 'paper')
99 self.style = self.ui.config('web', 'style', 'paper')
100 self.templatepath = self.ui.config('web', 'templates', None)
100 self.templatepath = self.ui.config('web', 'templates', None)
101 self.stripecount = self.ui.config('web', 'stripes', 1)
101 self.stripecount = self.ui.config('web', 'stripes', 1)
102 if self.stripecount:
102 if self.stripecount:
103 self.stripecount = int(self.stripecount)
103 self.stripecount = int(self.stripecount)
104 self._baseurl = self.ui.config('web', 'baseurl')
104 self._baseurl = self.ui.config('web', 'baseurl')
105 self.lastrefresh = time.time()
105 self.lastrefresh = time.time()
106
106
107 def run(self):
107 def run(self):
108 if not os.environ.get('GATEWAY_INTERFACE', '').startswith("CGI/1."):
108 if not os.environ.get('GATEWAY_INTERFACE', '').startswith("CGI/1."):
109 raise RuntimeError("This function is only intended to be "
109 raise RuntimeError("This function is only intended to be "
110 "called while running as a CGI script.")
110 "called while running as a CGI script.")
111 import mercurial.hgweb.wsgicgi as wsgicgi
111 import mercurial.hgweb.wsgicgi as wsgicgi
112 wsgicgi.launch(self)
112 wsgicgi.launch(self)
113
113
114 def __call__(self, env, respond):
114 def __call__(self, env, respond):
115 req = wsgirequest(env, respond)
115 req = wsgirequest(env, respond)
116 return self.run_wsgi(req)
116 return self.run_wsgi(req)
117
117
118 def read_allowed(self, ui, req):
118 def read_allowed(self, ui, req):
119 """Check allow_read and deny_read config options of a repo's ui object
119 """Check allow_read and deny_read config options of a repo's ui object
120 to determine user permissions. By default, with neither option set (or
120 to determine user permissions. By default, with neither option set (or
121 both empty), allow all users to read the repo. There are two ways a
121 both empty), allow all users to read the repo. There are two ways a
122 user can be denied read access: (1) deny_read is not empty, and the
122 user can be denied read access: (1) deny_read is not empty, and the
123 user is unauthenticated or deny_read contains user (or *), and (2)
123 user is unauthenticated or deny_read contains user (or *), and (2)
124 allow_read is not empty and the user is not in allow_read. Return True
124 allow_read is not empty and the user is not in allow_read. Return True
125 if user is allowed to read the repo, else return False."""
125 if user is allowed to read the repo, else return False."""
126
126
127 user = req.env.get('REMOTE_USER')
127 user = req.env.get('REMOTE_USER')
128
128
129 deny_read = ui.configlist('web', 'deny_read', untrusted=True)
129 deny_read = ui.configlist('web', 'deny_read', untrusted=True)
130 if deny_read and (not user or deny_read == ['*'] or user in deny_read):
130 if deny_read and (not user or deny_read == ['*'] or user in deny_read):
131 return False
131 return False
132
132
133 allow_read = ui.configlist('web', 'allow_read', untrusted=True)
133 allow_read = ui.configlist('web', 'allow_read', untrusted=True)
134 # by default, allow reading if no allow_read option has been set
134 # by default, allow reading if no allow_read option has been set
135 if (not allow_read) or (allow_read == ['*']) or (user in allow_read):
135 if (not allow_read) or (allow_read == ['*']) or (user in allow_read):
136 return True
136 return True
137
137
138 return False
138 return False
139
139
140 def run_wsgi(self, req):
140 def run_wsgi(self, req):
141 try:
141 try:
142 try:
142 try:
143 self.refresh()
143 self.refresh()
144
144
145 virtual = req.env.get("PATH_INFO", "").strip('/')
145 virtual = req.env.get("PATH_INFO", "").strip('/')
146 tmpl = self.templater(req)
146 tmpl = self.templater(req)
147 ctype = tmpl('mimetype', encoding=encoding.encoding)
147 ctype = tmpl('mimetype', encoding=encoding.encoding)
148 ctype = templater.stringify(ctype)
148 ctype = templater.stringify(ctype)
149
149
150 # a static file
150 # a static file
151 if virtual.startswith('static/') or 'static' in req.form:
151 if virtual.startswith('static/') or 'static' in req.form:
152 if virtual.startswith('static/'):
152 if virtual.startswith('static/'):
153 fname = virtual[7:]
153 fname = virtual[7:]
154 else:
154 else:
155 fname = req.form['static'][0]
155 fname = req.form['static'][0]
156 static = templater.templatepath('static')
156 static = templater.templatepath('static')
157 return (staticfile(static, fname, req),)
157 return (staticfile(static, fname, req),)
158
158
159 # top-level index
159 # top-level index
160 elif not virtual:
160 elif not virtual:
161 req.respond(HTTP_OK, ctype)
161 req.respond(HTTP_OK, ctype)
162 return self.makeindex(req, tmpl)
162 return self.makeindex(req, tmpl)
163
163
164 # nested indexes and hgwebs
164 # nested indexes and hgwebs
165
165
166 repos = dict(self.repos)
166 repos = dict(self.repos)
167 virtualrepo = virtual
167 virtualrepo = virtual
168 while virtualrepo:
168 while virtualrepo:
169 real = repos.get(virtualrepo)
169 real = repos.get(virtualrepo)
170 if real:
170 if real:
171 req.env['REPO_NAME'] = virtualrepo
171 req.env['REPO_NAME'] = virtualrepo
172 try:
172 try:
173 repo = hg.repository(self.ui, real)
173 repo = hg.repository(self.ui, real)
174 return hgweb(repo).run_wsgi(req)
174 return hgweb(repo).run_wsgi(req)
175 except IOError, inst:
175 except IOError, inst:
176 msg = inst.strerror
176 msg = inst.strerror
177 raise ErrorResponse(HTTP_SERVER_ERROR, msg)
177 raise ErrorResponse(HTTP_SERVER_ERROR, msg)
178 except error.RepoError, inst:
178 except error.RepoError, inst:
179 raise ErrorResponse(HTTP_SERVER_ERROR, str(inst))
179 raise ErrorResponse(HTTP_SERVER_ERROR, str(inst))
180
180
181 up = virtualrepo.rfind('/')
181 up = virtualrepo.rfind('/')
182 if up < 0:
182 if up < 0:
183 break
183 break
184 virtualrepo = virtualrepo[:up]
184 virtualrepo = virtualrepo[:up]
185
185
186 # browse subdirectories
186 # browse subdirectories
187 subdir = virtual + '/'
187 subdir = virtual + '/'
188 if [r for r in repos if r.startswith(subdir)]:
188 if [r for r in repos if r.startswith(subdir)]:
189 req.respond(HTTP_OK, ctype)
189 req.respond(HTTP_OK, ctype)
190 return self.makeindex(req, tmpl, subdir)
190 return self.makeindex(req, tmpl, subdir)
191
191
192 # prefixes not found
192 # prefixes not found
193 req.respond(HTTP_NOT_FOUND, ctype)
193 req.respond(HTTP_NOT_FOUND, ctype)
194 return tmpl("notfound", repo=virtual)
194 return tmpl("notfound", repo=virtual)
195
195
196 except ErrorResponse, err:
196 except ErrorResponse, err:
197 req.respond(err, ctype)
197 req.respond(err, ctype)
198 return tmpl('error', error=err.message or '')
198 return tmpl('error', error=err.message or '')
199 finally:
199 finally:
200 tmpl = None
200 tmpl = None
201
201
202 def makeindex(self, req, tmpl, subdir=""):
202 def makeindex(self, req, tmpl, subdir=""):
203
203
204 def archivelist(ui, nodeid, url):
204 def archivelist(ui, nodeid, url):
205 allowed = ui.configlist("web", "allow_archive", untrusted=True)
205 allowed = ui.configlist("web", "allow_archive", untrusted=True)
206 archives = []
206 for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]:
207 for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]:
207 if i[0] in allowed or ui.configbool("web", "allow" + i[0],
208 if i[0] in allowed or ui.configbool("web", "allow" + i[0],
208 untrusted=True):
209 untrusted=True):
209 yield {"type" : i[0], "extension": i[1],
210 archives.append({"type" : i[0], "extension": i[1],
210 "node": nodeid, "url": url}
211 "node": nodeid, "url": url})
212 return archives
211
213
212 def rawentries(subdir="", **map):
214 def rawentries(subdir="", **map):
213
215
214 descend = self.ui.configbool('web', 'descend', True)
216 descend = self.ui.configbool('web', 'descend', True)
215 for name, path in self.repos:
217 for name, path in self.repos:
216
218
217 if not name.startswith(subdir):
219 if not name.startswith(subdir):
218 continue
220 continue
219 name = name[len(subdir):]
221 name = name[len(subdir):]
220 if not descend and '/' in name:
222 if not descend and '/' in name:
221 continue
223 continue
222
224
223 u = self.ui.copy()
225 u = self.ui.copy()
224 try:
226 try:
225 u.readconfig(os.path.join(path, '.hg', 'hgrc'))
227 u.readconfig(os.path.join(path, '.hg', 'hgrc'))
226 except Exception, e:
228 except Exception, e:
227 u.warn(_('error reading %s/.hg/hgrc: %s\n') % (path, e))
229 u.warn(_('error reading %s/.hg/hgrc: %s\n') % (path, e))
228 continue
230 continue
229 def get(section, name, default=None):
231 def get(section, name, default=None):
230 return u.config(section, name, default, untrusted=True)
232 return u.config(section, name, default, untrusted=True)
231
233
232 if u.configbool("web", "hidden", untrusted=True):
234 if u.configbool("web", "hidden", untrusted=True):
233 continue
235 continue
234
236
235 if not self.read_allowed(u, req):
237 if not self.read_allowed(u, req):
236 continue
238 continue
237
239
238 parts = [name]
240 parts = [name]
239 if 'PATH_INFO' in req.env:
241 if 'PATH_INFO' in req.env:
240 parts.insert(0, req.env['PATH_INFO'].rstrip('/'))
242 parts.insert(0, req.env['PATH_INFO'].rstrip('/'))
241 if req.env['SCRIPT_NAME']:
243 if req.env['SCRIPT_NAME']:
242 parts.insert(0, req.env['SCRIPT_NAME'])
244 parts.insert(0, req.env['SCRIPT_NAME'])
243 url = re.sub(r'/+', '/', '/'.join(parts) + '/')
245 url = re.sub(r'/+', '/', '/'.join(parts) + '/')
244
246
245 # update time with local timezone
247 # update time with local timezone
246 try:
248 try:
247 r = hg.repository(self.ui, path)
249 r = hg.repository(self.ui, path)
248 except error.RepoError:
250 except error.RepoError:
249 u.warn(_('error accessing repository at %s\n') % path)
251 u.warn(_('error accessing repository at %s\n') % path)
250 continue
252 continue
251 try:
253 try:
252 d = (get_mtime(r.spath), util.makedate()[1])
254 d = (get_mtime(r.spath), util.makedate()[1])
253 except OSError:
255 except OSError:
254 continue
256 continue
255
257
256 contact = get_contact(get)
258 contact = get_contact(get)
257 description = get("web", "description", "")
259 description = get("web", "description", "")
258 name = get("web", "name", name)
260 name = get("web", "name", name)
259 row = dict(contact=contact or "unknown",
261 row = dict(contact=contact or "unknown",
260 contact_sort=contact.upper() or "unknown",
262 contact_sort=contact.upper() or "unknown",
261 name=name,
263 name=name,
262 name_sort=name,
264 name_sort=name,
263 url=url,
265 url=url,
264 description=description or "unknown",
266 description=description or "unknown",
265 description_sort=description.upper() or "unknown",
267 description_sort=description.upper() or "unknown",
266 lastchange=d,
268 lastchange=d,
267 lastchange_sort=d[1]-d[0],
269 lastchange_sort=d[1]-d[0],
268 archives=archivelist(u, "tip", url))
270 archives=archivelist(u, "tip", url))
269 yield row
271 yield row
270
272
271 sortdefault = None, False
273 sortdefault = None, False
272 def entries(sortcolumn="", descending=False, subdir="", **map):
274 def entries(sortcolumn="", descending=False, subdir="", **map):
273 rows = rawentries(subdir=subdir, **map)
275 rows = rawentries(subdir=subdir, **map)
274
276
275 if sortcolumn and sortdefault != (sortcolumn, descending):
277 if sortcolumn and sortdefault != (sortcolumn, descending):
276 sortkey = '%s_sort' % sortcolumn
278 sortkey = '%s_sort' % sortcolumn
277 rows = sorted(rows, key=lambda x: x[sortkey],
279 rows = sorted(rows, key=lambda x: x[sortkey],
278 reverse=descending)
280 reverse=descending)
279 for row, parity in zip(rows, paritygen(self.stripecount)):
281 for row, parity in zip(rows, paritygen(self.stripecount)):
280 row['parity'] = parity
282 row['parity'] = parity
281 yield row
283 yield row
282
284
283 self.refresh()
285 self.refresh()
284 sortable = ["name", "description", "contact", "lastchange"]
286 sortable = ["name", "description", "contact", "lastchange"]
285 sortcolumn, descending = sortdefault
287 sortcolumn, descending = sortdefault
286 if 'sort' in req.form:
288 if 'sort' in req.form:
287 sortcolumn = req.form['sort'][0]
289 sortcolumn = req.form['sort'][0]
288 descending = sortcolumn.startswith('-')
290 descending = sortcolumn.startswith('-')
289 if descending:
291 if descending:
290 sortcolumn = sortcolumn[1:]
292 sortcolumn = sortcolumn[1:]
291 if sortcolumn not in sortable:
293 if sortcolumn not in sortable:
292 sortcolumn = ""
294 sortcolumn = ""
293
295
294 sort = [("sort_%s" % column,
296 sort = [("sort_%s" % column,
295 "%s%s" % ((not descending and column == sortcolumn)
297 "%s%s" % ((not descending and column == sortcolumn)
296 and "-" or "", column))
298 and "-" or "", column))
297 for column in sortable]
299 for column in sortable]
298
300
299 self.refresh()
301 self.refresh()
300 self.updatereqenv(req.env)
302 self.updatereqenv(req.env)
301
303
302 return tmpl("index", entries=entries, subdir=subdir,
304 return tmpl("index", entries=entries, subdir=subdir,
303 sortcolumn=sortcolumn, descending=descending,
305 sortcolumn=sortcolumn, descending=descending,
304 **dict(sort))
306 **dict(sort))
305
307
306 def templater(self, req):
308 def templater(self, req):
307
309
308 def header(**map):
310 def header(**map):
309 yield tmpl('header', encoding=encoding.encoding, **map)
311 yield tmpl('header', encoding=encoding.encoding, **map)
310
312
311 def footer(**map):
313 def footer(**map):
312 yield tmpl("footer", **map)
314 yield tmpl("footer", **map)
313
315
314 def motd(**map):
316 def motd(**map):
315 if self.motd is not None:
317 if self.motd is not None:
316 yield self.motd
318 yield self.motd
317 else:
319 else:
318 yield config('web', 'motd', '')
320 yield config('web', 'motd', '')
319
321
320 def config(section, name, default=None, untrusted=True):
322 def config(section, name, default=None, untrusted=True):
321 return self.ui.config(section, name, default, untrusted)
323 return self.ui.config(section, name, default, untrusted)
322
324
323 self.updatereqenv(req.env)
325 self.updatereqenv(req.env)
324
326
325 url = req.env.get('SCRIPT_NAME', '')
327 url = req.env.get('SCRIPT_NAME', '')
326 if not url.endswith('/'):
328 if not url.endswith('/'):
327 url += '/'
329 url += '/'
328
330
329 vars = {}
331 vars = {}
330 styles = (
332 styles = (
331 req.form.get('style', [None])[0],
333 req.form.get('style', [None])[0],
332 config('web', 'style'),
334 config('web', 'style'),
333 'paper'
335 'paper'
334 )
336 )
335 style, mapfile = templater.stylemap(styles, self.templatepath)
337 style, mapfile = templater.stylemap(styles, self.templatepath)
336 if style == styles[0]:
338 if style == styles[0]:
337 vars['style'] = style
339 vars['style'] = style
338
340
339 start = url[-1] == '?' and '&' or '?'
341 start = url[-1] == '?' and '&' or '?'
340 sessionvars = webutil.sessionvars(vars, start)
342 sessionvars = webutil.sessionvars(vars, start)
341 staticurl = config('web', 'staticurl') or url + 'static/'
343 staticurl = config('web', 'staticurl') or url + 'static/'
342 if not staticurl.endswith('/'):
344 if not staticurl.endswith('/'):
343 staticurl += '/'
345 staticurl += '/'
344
346
345 tmpl = templater.templater(mapfile,
347 tmpl = templater.templater(mapfile,
346 defaults={"header": header,
348 defaults={"header": header,
347 "footer": footer,
349 "footer": footer,
348 "motd": motd,
350 "motd": motd,
349 "url": url,
351 "url": url,
350 "staticurl": staticurl,
352 "staticurl": staticurl,
351 "sessionvars": sessionvars})
353 "sessionvars": sessionvars})
352 return tmpl
354 return tmpl
353
355
354 def updatereqenv(self, env):
356 def updatereqenv(self, env):
355 def splitnetloc(netloc):
357 def splitnetloc(netloc):
356 if ':' in netloc:
358 if ':' in netloc:
357 return netloc.split(':', 1)
359 return netloc.split(':', 1)
358 else:
360 else:
359 return (netloc, None)
361 return (netloc, None)
360
362
361 if self._baseurl is not None:
363 if self._baseurl is not None:
362 urlcomp = urlparse.urlparse(self._baseurl)
364 urlcomp = urlparse.urlparse(self._baseurl)
363 host, port = splitnetloc(urlcomp[1])
365 host, port = splitnetloc(urlcomp[1])
364 path = urlcomp[2]
366 path = urlcomp[2]
365 env['SERVER_NAME'] = host
367 env['SERVER_NAME'] = host
366 if port:
368 if port:
367 env['SERVER_PORT'] = port
369 env['SERVER_PORT'] = port
368 env['SCRIPT_NAME'] = path
370 env['SCRIPT_NAME'] = path
General Comments 0
You need to be logged in to leave comments. Login now