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