Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/hgweb/common.py @ 31444:2daeab02b4b1
hgweb: explicitly tests for None
Changeset 7dafa8d0e006 removed the mutable default value, but did not explicitly
tested for None. Such implicit testing can introduce semantic and performance
issue. We move to an explicit testing for None as recommended by PEP8:
https://www.python.org/dev/peps/pep-0008/#programming-recommendations
author | Pierre-Yves David <pierre-yves.david@ens-lyon.org> |
---|---|
date | Wed, 15 Mar 2017 15:11:04 -0700 |
parents | 7dafa8d0e006 |
children | 161a87ed456e |
rev | line source |
---|---|
2391
d351a3be3371
Fixing up comment headers for split up code.
Eric Hopper <hopper@omnifarious.org>
parents:
2356
diff
changeset
|
1 # hgweb/common.py - Utility functions needed by hgweb_mod and hgwebdir_mod |
131 | 2 # |
238
3b92f8fe47ae
hgweb.py: kill #! line, clean up copyright notice
mpm@selenic.com
parents:
222
diff
changeset
|
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net> |
2859 | 4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com> |
131 | 5 # |
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
7966
diff
changeset
|
6 # This software may be used and distributed according to the terms of the |
10263 | 7 # GNU General Public License version 2 or any later version. |
131 | 8 |
27046
37fcfe52c68c
hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
27044
diff
changeset
|
9 from __future__ import absolute_import |
37fcfe52c68c
hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
27044
diff
changeset
|
10 |
30766
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
11 import base64 |
27046
37fcfe52c68c
hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
27044
diff
changeset
|
12 import errno |
37fcfe52c68c
hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
27044
diff
changeset
|
13 import mimetypes |
37fcfe52c68c
hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents:
27044
diff
changeset
|
14 import os |
30766
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
15 import uuid |
5561
22713dce19f6
hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents:
4462
diff
changeset
|
16 |
30620
bb77654dc7ae
py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29566
diff
changeset
|
17 from .. import ( |
30641
f1c9fafcbf46
py3: replace os.environ with encoding.environ (part 3 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30630
diff
changeset
|
18 encoding, |
30620
bb77654dc7ae
py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29566
diff
changeset
|
19 pycompat, |
bb77654dc7ae
py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29566
diff
changeset
|
20 util, |
bb77654dc7ae
py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29566
diff
changeset
|
21 ) |
29566
075146e85bb6
py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29491
diff
changeset
|
22 |
075146e85bb6
py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29491
diff
changeset
|
23 httpserver = util.httpserver |
075146e85bb6
py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29491
diff
changeset
|
24 |
5993
948a41e77902
hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5930
diff
changeset
|
25 HTTP_OK = 200 |
12183
f64b416b0ac8
hgweb: support very simple caching model (issue1845)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10264
diff
changeset
|
26 HTTP_NOT_MODIFIED = 304 |
5993
948a41e77902
hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5930
diff
changeset
|
27 HTTP_BAD_REQUEST = 400 |
6926
57b954d8d003
hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
6924
diff
changeset
|
28 HTTP_UNAUTHORIZED = 401 |
7029
b84d27386285
hgweb: Respond with HTTP 403 for disabled archive types instead of 404
Rocco Rutte <pdmef@gmx.net>
parents:
6926
diff
changeset
|
29 HTTP_FORBIDDEN = 403 |
5993
948a41e77902
hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5930
diff
changeset
|
30 HTTP_NOT_FOUND = 404 |
6926
57b954d8d003
hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
6924
diff
changeset
|
31 HTTP_METHOD_NOT_ALLOWED = 405 |
5993
948a41e77902
hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5930
diff
changeset
|
32 HTTP_SERVER_ERROR = 500 |
948a41e77902
hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5930
diff
changeset
|
33 |
9910
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
34 |
19032
7d31f2e42a8a
hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
18645
diff
changeset
|
35 def ismember(ui, username, userlist): |
7d31f2e42a8a
hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
18645
diff
changeset
|
36 """Check if username is a member of userlist. |
7d31f2e42a8a
hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
18645
diff
changeset
|
37 |
7d31f2e42a8a
hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
18645
diff
changeset
|
38 If userlist has a single '*' member, all users are considered members. |
19951
d51c4d85ec23
spelling: random spell checker fixes
Mads Kiilerich <madski@unity3d.com>
parents:
19032
diff
changeset
|
39 Can be overridden by extensions to provide more complex authorization |
19032
7d31f2e42a8a
hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
18645
diff
changeset
|
40 schemes. |
7d31f2e42a8a
hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
18645
diff
changeset
|
41 """ |
7d31f2e42a8a
hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
18645
diff
changeset
|
42 return userlist == ['*'] or username in userlist |
7d31f2e42a8a
hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
18645
diff
changeset
|
43 |
9910
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
44 def checkauthz(hgweb, req, op): |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
45 '''Check permission for operation based on request data (including |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
46 authentication info). Return if op allowed, else raise an ErrorResponse |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
47 exception.''' |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
48 |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
49 user = req.env.get('REMOTE_USER') |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
50 |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
51 deny_read = hgweb.configlist('web', 'deny_read') |
19032
7d31f2e42a8a
hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
18645
diff
changeset
|
52 if deny_read and (not user or ismember(hgweb.repo.ui, user, deny_read)): |
9910
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
53 raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized') |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
54 |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
55 allow_read = hgweb.configlist('web', 'allow_read') |
19032
7d31f2e42a8a
hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
18645
diff
changeset
|
56 if allow_read and (not ismember(hgweb.repo.ui, user, allow_read)): |
9910
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
57 raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized') |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
58 |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
59 if op == 'pull' and not hgweb.allowpull: |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
60 raise ErrorResponse(HTTP_UNAUTHORIZED, 'pull not authorized') |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
61 elif op == 'pull' or op is None: # op is None for interface requests |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
62 return |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
63 |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
64 # enforce that you can only push using POST requests |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
65 if req.env['REQUEST_METHOD'] != 'POST': |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
66 msg = 'push requires POST request' |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
67 raise ErrorResponse(HTTP_METHOD_NOT_ALLOWED, msg) |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
68 |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
69 # require ssl by default for pushing, auth info cannot be sniffed |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
70 # and replayed |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
71 scheme = req.env.get('wsgi.url_scheme') |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
72 if hgweb.configbool('web', 'push_ssl', True) and scheme != 'https': |
17456
59a168019255
hgweb: respond 403 forbidden for ssl required error
Yuya Nishihara <yuya@tcha.org>
parents:
16687
diff
changeset
|
73 raise ErrorResponse(HTTP_FORBIDDEN, 'ssl required') |
9910
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
74 |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
75 deny = hgweb.configlist('web', 'deny_push') |
19032
7d31f2e42a8a
hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
18645
diff
changeset
|
76 if deny and (not user or ismember(hgweb.repo.ui, user, deny)): |
9910
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
77 raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized') |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
78 |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
79 allow = hgweb.configlist('web', 'allow_push') |
19032
7d31f2e42a8a
hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
18645
diff
changeset
|
80 if not (allow and ismember(hgweb.repo.ui, user, allow)): |
9910
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
81 raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized') |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
82 |
14058
3233b39d756f
hgweb: initialize permhooks at definition time
Martin Geisler <mg@lazybytes.net>
parents:
13959
diff
changeset
|
83 # Hooks for hgweb permission checks; extensions can add hooks here. |
3233b39d756f
hgweb: initialize permhooks at definition time
Martin Geisler <mg@lazybytes.net>
parents:
13959
diff
changeset
|
84 # Each hook is invoked like this: hook(hgweb, request, operation), |
3233b39d756f
hgweb: initialize permhooks at definition time
Martin Geisler <mg@lazybytes.net>
parents:
13959
diff
changeset
|
85 # where operation is either read, pull or push. Hooks should either |
3233b39d756f
hgweb: initialize permhooks at definition time
Martin Geisler <mg@lazybytes.net>
parents:
13959
diff
changeset
|
86 # raise an ErrorResponse exception, or just return. |
3233b39d756f
hgweb: initialize permhooks at definition time
Martin Geisler <mg@lazybytes.net>
parents:
13959
diff
changeset
|
87 # |
3233b39d756f
hgweb: initialize permhooks at definition time
Martin Geisler <mg@lazybytes.net>
parents:
13959
diff
changeset
|
88 # It is possible to do both authentication and authorization through |
3233b39d756f
hgweb: initialize permhooks at definition time
Martin Geisler <mg@lazybytes.net>
parents:
13959
diff
changeset
|
89 # this. |
3233b39d756f
hgweb: initialize permhooks at definition time
Martin Geisler <mg@lazybytes.net>
parents:
13959
diff
changeset
|
90 permhooks = [checkauthz] |
9910
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
91 |
6f92997dbdca
hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents:
9694
diff
changeset
|
92 |
5561
22713dce19f6
hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents:
4462
diff
changeset
|
93 class ErrorResponse(Exception): |
31399
7dafa8d0e006
hgweb: don't use mutable default argument value
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30766
diff
changeset
|
94 def __init__(self, code, message=None, headers=None): |
13444
75f5f312df5f
hgweb: give ErrorResponse a descriptive string/Exception representation
Mads Kiilerich <mads@kiilerich.com>
parents:
13400
diff
changeset
|
95 if message is None: |
75f5f312df5f
hgweb: give ErrorResponse a descriptive string/Exception representation
Mads Kiilerich <mads@kiilerich.com>
parents:
13400
diff
changeset
|
96 message = _statusmessage(code) |
26200 | 97 Exception.__init__(self, message) |
5561
22713dce19f6
hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents:
4462
diff
changeset
|
98 self.code = code |
31444
2daeab02b4b1
hgweb: explicitly tests for None
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31399
diff
changeset
|
99 if headers is None: |
2daeab02b4b1
hgweb: explicitly tests for None
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31399
diff
changeset
|
100 headers = [] |
2daeab02b4b1
hgweb: explicitly tests for None
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31399
diff
changeset
|
101 self.headers = headers |
5563
d61fea133f2d
hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents:
5561
diff
changeset
|
102 |
13570
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
103 class continuereader(object): |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
104 def __init__(self, f, write): |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
105 self.f = f |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
106 self._write = write |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
107 self.continued = False |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
108 |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
109 def read(self, amt=-1): |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
110 if not self.continued: |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
111 self.continued = True |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
112 self._write('HTTP/1.1 100 Continue\r\n\r\n') |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
113 return self.f.read(amt) |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
114 |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
115 def __getattr__(self, attr): |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
116 if attr in ('close', 'readline', 'readlines', '__iter__'): |
617a87cb7eb2
hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents:
13444
diff
changeset
|
117 return getattr(self.f, attr) |
16687
e34106fa0dc3
cleanup: "raise SomeException()" -> "raise SomeException"
Brodie Rao <brodie@sf.io>
parents:
14058
diff
changeset
|
118 raise AttributeError |
5563
d61fea133f2d
hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents:
5561
diff
changeset
|
119 |
d61fea133f2d
hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents:
5561
diff
changeset
|
120 def _statusmessage(code): |
29566
075146e85bb6
py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29491
diff
changeset
|
121 responses = httpserver.basehttprequesthandler.responses |
5563
d61fea133f2d
hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents:
5561
diff
changeset
|
122 return responses.get(code, ('Error', 'Unknown error'))[0] |
5760
0145f9afb0e7
Removed tabs and trailing whitespace in python files
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5563
diff
changeset
|
123 |
9694
8269fe2d48f6
hgweb: send proper error messages to the client
Sune Foldager <cryo@cyanite.org>
parents:
9031
diff
changeset
|
124 def statusmessage(code, message=None): |
8269fe2d48f6
hgweb: send proper error messages to the client
Sune Foldager <cryo@cyanite.org>
parents:
9031
diff
changeset
|
125 return '%d %s' % (code, message or _statusmessage(code)) |
131 | 126 |
25717
46e2c57026bc
hgweb: drop the default argument for get_stat
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25660
diff
changeset
|
127 def get_stat(spath, fn): |
46e2c57026bc
hgweb: drop the default argument for get_stat
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25660
diff
changeset
|
128 """stat fn if it exists, spath otherwise""" |
22577
a111e460318a
hgweb: refresh hgweb.repo on phase change (issue4061)
Anton Shestakov <engored@ya.ru>
parents:
19951
diff
changeset
|
129 cl_path = os.path.join(spath, fn) |
3853
c0b449154a90
switch to the .hg/store layout, fix the tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3276
diff
changeset
|
130 if os.path.exists(cl_path): |
13958
71f51cc71652
hgweb: detect change based on changelog size too
Martin Geisler <mg@lazybytes.net>
parents:
13444
diff
changeset
|
131 return os.stat(cl_path) |
1418
68f81ba07b2a
Make hgweb work when the repository is empty (no 00changelog.i)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1416
diff
changeset
|
132 else: |
13958
71f51cc71652
hgweb: detect change based on changelog size too
Martin Geisler <mg@lazybytes.net>
parents:
13444
diff
changeset
|
133 return os.stat(spath) |
71f51cc71652
hgweb: detect change based on changelog size too
Martin Geisler <mg@lazybytes.net>
parents:
13444
diff
changeset
|
134 |
71f51cc71652
hgweb: detect change based on changelog size too
Martin Geisler <mg@lazybytes.net>
parents:
13444
diff
changeset
|
135 def get_mtime(spath): |
25717
46e2c57026bc
hgweb: drop the default argument for get_stat
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25660
diff
changeset
|
136 return get_stat(spath, "00changelog.i").st_mtime |
1418
68f81ba07b2a
Make hgweb work when the repository is empty (no 00changelog.i)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
1416
diff
changeset
|
137 |
2514
419c42223bee
Really fix http headers for web UI and issue 254.
Eric Hopper <hopper@omnifarious.org>
parents:
2391
diff
changeset
|
138 def staticfile(directory, fname, req): |
5930
c301f15c965a
send conservatively capitalized HTTP headers
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5779
diff
changeset
|
139 """return a file inside directory with guessed Content-Type header |
1825
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
140 |
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
141 fname always uses '/' as directory separator and isn't allowed to |
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
142 contain unusual path components. |
5930
c301f15c965a
send conservatively capitalized HTTP headers
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5779
diff
changeset
|
143 Content-Type is guessed using the mimetypes module. |
1825
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
144 Return an empty string if fname is illegal or file not found. |
1793
83c6d8355909
Allow serving static files from hgwebdir to fix CSS and favicon.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1792
diff
changeset
|
145 |
1825
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
146 """ |
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
147 parts = fname.split('/') |
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
148 for part in parts: |
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
149 if (part in ('', os.curdir, os.pardir) or |
30620
bb77654dc7ae
py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29566
diff
changeset
|
150 pycompat.ossep in part or |
30630
bcf4a975f93d
py3: replace os.altsep with pycompat.altsep
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30620
diff
changeset
|
151 pycompat.osaltsep is not None and pycompat.osaltsep in part): |
18645
76ff3a715cf2
hgweb: simplify internal staticfile return codes
Mads Kiilerich <mads@kiilerich.com>
parents:
18352
diff
changeset
|
152 return |
7288
9c399c53469d
Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents:
7107
diff
changeset
|
153 fpath = os.path.join(*parts) |
9c399c53469d
Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents:
7107
diff
changeset
|
154 if isinstance(directory, str): |
9c399c53469d
Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents:
7107
diff
changeset
|
155 directory = [directory] |
9c399c53469d
Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents:
7107
diff
changeset
|
156 for d in directory: |
9c399c53469d
Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents:
7107
diff
changeset
|
157 path = os.path.join(d, fpath) |
9c399c53469d
Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents:
7107
diff
changeset
|
158 if os.path.exists(path): |
9c399c53469d
Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents:
7107
diff
changeset
|
159 break |
1793
83c6d8355909
Allow serving static files from hgwebdir to fix CSS and favicon.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1792
diff
changeset
|
160 try: |
1825
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
161 os.stat(path) |
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
162 ct = mimetypes.guess_type(path)[0] or "text/plain" |
13400
14f3795a5ed7
explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
12183
diff
changeset
|
163 fp = open(path, 'rb') |
14f3795a5ed7
explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
12183
diff
changeset
|
164 data = fp.read() |
14f3795a5ed7
explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
12183
diff
changeset
|
165 fp.close() |
18352
e33b9b92a200
hgweb: pass the actual response body to request.response, not just the length
Mads Kiilerich <mads@kiilerich.com>
parents:
17456
diff
changeset
|
166 req.respond(HTTP_OK, ct, body=data) |
5561
22713dce19f6
hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents:
4462
diff
changeset
|
167 except TypeError: |
8761
0289f384e1e5
Generally replace "file name" with "filename" in help and comments.
timeless <timeless@gmail.com>
parents:
8225
diff
changeset
|
168 raise ErrorResponse(HTTP_SERVER_ERROR, 'illegal filename') |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
22577
diff
changeset
|
169 except OSError as err: |
5561
22713dce19f6
hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents:
4462
diff
changeset
|
170 if err.errno == errno.ENOENT: |
5993
948a41e77902
hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5930
diff
changeset
|
171 raise ErrorResponse(HTTP_NOT_FOUND) |
5561
22713dce19f6
hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents:
4462
diff
changeset
|
172 else: |
5993
948a41e77902
hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5930
diff
changeset
|
173 raise ErrorResponse(HTTP_SERVER_ERROR, err.strerror) |
3276
db9d2a624521
hgweb: Search templates in templatepath/style/map, too, using a common function.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
3244
diff
changeset
|
174 |
4462
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
175 def paritygen(stripecount, offset=0): |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
176 """count parity of horizontal stripes for easier reading""" |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
177 if stripecount and offset: |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
178 # account for offset, e.g. due to building the list in reverse |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
179 count = (stripecount + offset) % stripecount |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
180 parity = (stripecount + offset) / stripecount & 1 |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
181 else: |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
182 count = 0 |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
183 parity = 0 |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
184 while True: |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
185 yield parity |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
186 count += 1 |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
187 if stripecount and count >= stripecount: |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
188 parity = 1 - parity |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
189 count = 0 |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
190 |
5779
e9f68860d5ed
Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5760
diff
changeset
|
191 def get_contact(config): |
e9f68860d5ed
Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5760
diff
changeset
|
192 """Return repo contact information or empty string. |
e9f68860d5ed
Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5760
diff
changeset
|
193 |
e9f68860d5ed
Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5760
diff
changeset
|
194 web.contact is the primary source, but if that is not set, try |
e9f68860d5ed
Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5760
diff
changeset
|
195 ui.username or $EMAIL as a fallback to display something useful. |
e9f68860d5ed
Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5760
diff
changeset
|
196 """ |
e9f68860d5ed
Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5760
diff
changeset
|
197 return (config("web", "contact") or |
e9f68860d5ed
Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5760
diff
changeset
|
198 config("ui", "username") or |
30641
f1c9fafcbf46
py3: replace os.environ with encoding.environ (part 3 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30630
diff
changeset
|
199 encoding.environ.get("EMAIL") or "") |
12183
f64b416b0ac8
hgweb: support very simple caching model (issue1845)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10264
diff
changeset
|
200 |
f64b416b0ac8
hgweb: support very simple caching model (issue1845)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10264
diff
changeset
|
201 def caching(web, req): |
29491
7f0498bd284e
hgweb: emit a valid, weak ETag
Anton Shestakov <av6@dwimlabs.net>
parents:
27046
diff
changeset
|
202 tag = 'W/"%s"' % web.mtime |
12183
f64b416b0ac8
hgweb: support very simple caching model (issue1845)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10264
diff
changeset
|
203 if req.env.get('HTTP_IF_NONE_MATCH') == tag: |
f64b416b0ac8
hgweb: support very simple caching model (issue1845)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10264
diff
changeset
|
204 raise ErrorResponse(HTTP_NOT_MODIFIED) |
f64b416b0ac8
hgweb: support very simple caching model (issue1845)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10264
diff
changeset
|
205 req.headers.append(('ETag', tag)) |
30766
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
206 |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
207 def cspvalues(ui): |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
208 """Obtain the Content-Security-Policy header and nonce value. |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
209 |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
210 Returns a 2-tuple of the CSP header value and the nonce value. |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
211 |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
212 First value is ``None`` if CSP isn't enabled. Second value is ``None`` |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
213 if CSP isn't enabled or if the CSP header doesn't need a nonce. |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
214 """ |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
215 # Don't allow untrusted CSP setting since it be disable protections |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
216 # from a trusted/global source. |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
217 csp = ui.config('web', 'csp', untrusted=False) |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
218 nonce = None |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
219 |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
220 if csp and '%nonce%' in csp: |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
221 nonce = base64.urlsafe_b64encode(uuid.uuid4().bytes).rstrip('=') |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
222 csp = csp.replace('%nonce%', nonce) |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
223 |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30641
diff
changeset
|
224 return csp, nonce |