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 |
9 import os |
10 from mercurial import ui, hg, hook, error, encoding, templater, util, repoview |
10 from mercurial import ui, hg, hook, error, encoding, templater, util, repoview |
|
11 from mercurial.templatefilters import websub |
|
12 from mercurial.i18n import _ |
11 from common import get_stat, ErrorResponse, permhooks, caching |
13 from common import get_stat, ErrorResponse, permhooks, caching |
12 from common import HTTP_OK, HTTP_NOT_MODIFIED, HTTP_BAD_REQUEST |
14 from common import HTTP_OK, HTTP_NOT_MODIFIED, HTTP_BAD_REQUEST |
13 from common import HTTP_NOT_FOUND, HTTP_SERVER_ERROR |
15 from common import HTTP_NOT_FOUND, HTTP_SERVER_ERROR |
14 from request import wsgirequest |
16 from request import wsgirequest |
15 import webcommands, protocol, webutil |
17 import webcommands, protocol, webutil, re |
16 |
18 |
17 perms = { |
19 perms = { |
18 'changegroup': 'pull', |
20 'changegroup': 'pull', |
19 'changegroupsubset': 'pull', |
21 'changegroupsubset': 'pull', |
20 'getbundle': 'pull', |
22 'getbundle': 'pull', |
71 self.archives = 'zip', 'gz', 'bz2' |
73 self.archives = 'zip', 'gz', 'bz2' |
72 self.stripecount = 1 |
74 self.stripecount = 1 |
73 # a repo owner may set web.templates in .hg/hgrc to get any file |
75 # a repo owner may set web.templates in .hg/hgrc to get any file |
74 # readable by the user running the CGI script |
76 # readable by the user running the CGI script |
75 self.templatepath = self.config('web', 'templates') |
77 self.templatepath = self.config('web', 'templates') |
|
78 self.websubtable = self.loadwebsub() |
76 |
79 |
77 # The CGI scripts are often run by a user different from the repo owner. |
80 # The CGI scripts are often run by a user different from the repo owner. |
78 # Trust the settings from the .hg/hgrc files by default. |
81 # Trust the settings from the .hg/hgrc files by default. |
79 def config(self, section, name, default=None, untrusted=True): |
82 def config(self, section, name, default=None, untrusted=True): |
80 return self.repo.ui.config(section, name, default, |
83 return self.repo.ui.config(section, name, default, |
256 if inst.code == HTTP_NOT_MODIFIED: |
259 if inst.code == HTTP_NOT_MODIFIED: |
257 # Not allowed to return a body on a 304 |
260 # Not allowed to return a body on a 304 |
258 return [''] |
261 return [''] |
259 return tmpl('error', error=inst.message) |
262 return tmpl('error', error=inst.message) |
260 |
263 |
|
264 def loadwebsub(self): |
|
265 websubtable = [] |
|
266 websubdefs = self.repo.ui.configitems('websub') |
|
267 for key, pattern in websubdefs: |
|
268 # grab the delimiter from the character after the "s" |
|
269 unesc = pattern[1] |
|
270 delim = re.escape(unesc) |
|
271 |
|
272 # identify portions of the pattern, taking care to avoid escaped |
|
273 # delimiters. the replace format and flags are optional, but |
|
274 # delimiters are required. |
|
275 match = re.match( |
|
276 r'^s%s(.+)(?:(?<=\\\\)|(?<!\\))%s(.*)%s([ilmsux])*$' |
|
277 % (delim, delim, delim), pattern) |
|
278 if not match: |
|
279 self.repo.ui.warn(_("websub: invalid pattern for %s: %s\n") |
|
280 % (key, pattern)) |
|
281 continue |
|
282 |
|
283 # we need to unescape the delimiter for regexp and format |
|
284 delim_re = re.compile(r'(?<!\\)\\%s' % delim) |
|
285 regexp = delim_re.sub(unesc, match.group(1)) |
|
286 format = delim_re.sub(unesc, match.group(2)) |
|
287 |
|
288 # the pattern allows for 6 regexp flags, so set them if necessary |
|
289 flagin = match.group(3) |
|
290 flags = 0 |
|
291 if flagin: |
|
292 for flag in flagin.upper(): |
|
293 flags |= re.__dict__[flag] |
|
294 |
|
295 try: |
|
296 regexp = re.compile(regexp, flags) |
|
297 websubtable.append((regexp, format)) |
|
298 except re.error: |
|
299 self.repo.ui.warn(_("websub: invalid regexp for %s: %s\n") |
|
300 % (key, regexp)) |
|
301 return websubtable |
|
302 |
261 def templater(self, req): |
303 def templater(self, req): |
262 |
304 |
263 # determine scheme, port and server name |
305 # determine scheme, port and server name |
264 # this is needed to create absolute urls |
306 # this is needed to create absolute urls |
265 |
307 |
309 if not self.reponame: |
351 if not self.reponame: |
310 self.reponame = (self.config("web", "name") |
352 self.reponame = (self.config("web", "name") |
311 or req.env.get('REPO_NAME') |
353 or req.env.get('REPO_NAME') |
312 or req.url.strip('/') or self.repo.root) |
354 or req.url.strip('/') or self.repo.root) |
313 |
355 |
|
356 def websubfilter(text): |
|
357 return websub(text, self.websubtable) |
|
358 |
314 # create the templater |
359 # create the templater |
315 |
360 |
316 tmpl = templater.templater(mapfile, |
361 tmpl = templater.templater(mapfile, |
|
362 filters={"websub": websubfilter}, |
317 defaults={"url": req.url, |
363 defaults={"url": req.url, |
318 "logourl": logourl, |
364 "logourl": logourl, |
319 "logoimg": logoimg, |
365 "logoimg": logoimg, |
320 "staticurl": staticurl, |
366 "staticurl": staticurl, |
321 "urlbase": urlbase, |
367 "urlbase": urlbase, |