Mercurial > hg
annotate mercurial/hgweb/common.py @ 33702:033484935391
exchange: access requirements on repo instead of peer
As part of formalizing the peer interface, I audited for attribute
accesses for non-internal names to find API violations. This
uncovered the code changed in this commit.
localpeer.requirements is just an alias to the repo's requirements
attribute. So, change the code to get the data from the source
instead of relying on a one-off attribute in the localpeer type.
Differential Revision: https://phab.mercurial-scm.org/D265
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 05 Aug 2017 15:15:20 -0700 |
parents | 62f9679df1f2 |
children | d5b2beca16c0 |
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:
30636
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:
30636
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 |
30615
bb77654dc7ae
py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29566
diff
changeset
|
17 from .. import ( |
30636
f1c9fafcbf46
py3: replace os.environ with encoding.environ (part 3 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30625
diff
changeset
|
18 encoding, |
30615
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): |
31390
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 |
31435
2daeab02b4b1
hgweb: explicitly tests for None
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31390
diff
changeset
|
99 if headers is None: |
2daeab02b4b1
hgweb: explicitly tests for None
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31390
diff
changeset
|
100 headers = [] |
2daeab02b4b1
hgweb: explicitly tests for None
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
31390
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 |
31790
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
138 def ispathsafe(path): |
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
139 """Determine if a path is safe to use for filesystem access.""" |
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
140 parts = path.split('/') |
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
141 for part in parts: |
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
142 if (part in ('', os.curdir, os.pardir) or |
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
143 pycompat.ossep in part or |
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
144 pycompat.osaltsep is not None and pycompat.osaltsep in part): |
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
145 return False |
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
146 |
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
147 return True |
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
148 |
2514
419c42223bee
Really fix http headers for web UI and issue 254.
Eric Hopper <hopper@omnifarious.org>
parents:
2391
diff
changeset
|
149 def staticfile(directory, fname, req): |
5930
c301f15c965a
send conservatively capitalized HTTP headers
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5779
diff
changeset
|
150 """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
|
151 |
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
152 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
|
153 contain unusual path components. |
5930
c301f15c965a
send conservatively capitalized HTTP headers
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5779
diff
changeset
|
154 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
|
155 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
|
156 |
1825
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
157 """ |
31790
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
158 if not ispathsafe(fname): |
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
159 return |
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
160 |
62f9679df1f2
hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31789
diff
changeset
|
161 fpath = os.path.join(*fname.split('/')) |
7288
9c399c53469d
Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents:
7107
diff
changeset
|
162 if isinstance(directory, str): |
9c399c53469d
Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents:
7107
diff
changeset
|
163 directory = [directory] |
9c399c53469d
Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents:
7107
diff
changeset
|
164 for d in directory: |
9c399c53469d
Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents:
7107
diff
changeset
|
165 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
|
166 if os.path.exists(path): |
9c399c53469d
Allow per-file shadowing of static directory in templatepath
Brendan Cully <brendan@kublai.com>
parents:
7107
diff
changeset
|
167 break |
1793
83c6d8355909
Allow serving static files from hgwebdir to fix CSS and favicon.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1792
diff
changeset
|
168 try: |
1825
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
169 os.stat(path) |
a9343f9d7365
Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
1796
diff
changeset
|
170 ct = mimetypes.guess_type(path)[0] or "text/plain" |
31789
161a87ed456e
hgweb: use context manager for file I/O
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31435
diff
changeset
|
171 with open(path, 'rb') as fh: |
161a87ed456e
hgweb: use context manager for file I/O
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31435
diff
changeset
|
172 data = fh.read() |
161a87ed456e
hgweb: use context manager for file I/O
Gregory Szorc <gregory.szorc@gmail.com>
parents:
31435
diff
changeset
|
173 |
18352
e33b9b92a200
hgweb: pass the actual response body to request.response, not just the length
Mads Kiilerich <mads@kiilerich.com>
parents:
17456
diff
changeset
|
174 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
|
175 except TypeError: |
8761
0289f384e1e5
Generally replace "file name" with "filename" in help and comments.
timeless <timeless@gmail.com>
parents:
8225
diff
changeset
|
176 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
|
177 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
|
178 if err.errno == errno.ENOENT: |
5993
948a41e77902
hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5930
diff
changeset
|
179 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
|
180 else: |
5993
948a41e77902
hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5930
diff
changeset
|
181 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
|
182 |
4462
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
183 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
|
184 """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
|
185 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
|
186 # 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
|
187 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
|
188 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
|
189 else: |
12e4d9524951
hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4038
diff
changeset
|
190 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
|
191 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
|
192 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
|
193 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
|
194 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
|
195 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
|
196 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
|
197 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
|
198 |
5779
e9f68860d5ed
Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5760
diff
changeset
|
199 def get_contact(config): |
e9f68860d5ed
Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5760
diff
changeset
|
200 """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
|
201 |
e9f68860d5ed
Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5760
diff
changeset
|
202 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
|
203 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
|
204 """ |
e9f68860d5ed
Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
5760
diff
changeset
|
205 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
|
206 config("ui", "username") or |
30636
f1c9fafcbf46
py3: replace os.environ with encoding.environ (part 3 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30625
diff
changeset
|
207 encoding.environ.get("EMAIL") or "") |
12183
f64b416b0ac8
hgweb: support very simple caching model (issue1845)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10264
diff
changeset
|
208 |
f64b416b0ac8
hgweb: support very simple caching model (issue1845)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10264
diff
changeset
|
209 def caching(web, req): |
29491
7f0498bd284e
hgweb: emit a valid, weak ETag
Anton Shestakov <av6@dwimlabs.net>
parents:
27046
diff
changeset
|
210 tag = 'W/"%s"' % web.mtime |
12183
f64b416b0ac8
hgweb: support very simple caching model (issue1845)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10264
diff
changeset
|
211 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
|
212 raise ErrorResponse(HTTP_NOT_MODIFIED) |
f64b416b0ac8
hgweb: support very simple caching model (issue1845)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
10264
diff
changeset
|
213 req.headers.append(('ETag', tag)) |
30766
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
214 |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
215 def cspvalues(ui): |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
216 """Obtain the Content-Security-Policy header and nonce value. |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
217 |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
218 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:
30636
diff
changeset
|
219 |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
220 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:
30636
diff
changeset
|
221 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:
30636
diff
changeset
|
222 """ |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
223 # Don't allow untrusted CSP setting since it be disable protections |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
224 # from a trusted/global source. |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
225 csp = ui.config('web', 'csp', untrusted=False) |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
226 nonce = None |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
227 |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
228 if csp and '%nonce%' in csp: |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
229 nonce = base64.urlsafe_b64encode(uuid.uuid4().bytes).rstrip('=') |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
230 csp = csp.replace('%nonce%', nonce) |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
231 |
d7bf7d2bd5ab
hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30636
diff
changeset
|
232 return csp, nonce |