mercurial/hgweb/common.py
author Matt Harbison <matt_harbison@yahoo.com>
Sun, 20 Aug 2023 01:08:58 -0400
changeset 50856 7d54b877782e
parent 50479 4bddc2f72879
child 50952 18c8c18993f0
permissions -rw-r--r--
config: migrate `opts` to native kwargs
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
c9d51742471c moving hgweb to mercurial subdir
jake@edge2.net
parents:
diff changeset
     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>
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Raphaël Gomès <rgomes@octobus.net>
parents: 45957
diff changeset
     4
# Copyright 2005, 2006 Olivia Mackall <olivia@selenic.com>
131
c9d51742471c moving hgweb to mercurial subdir
jake@edge2.net
parents:
diff changeset
     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
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9694
diff changeset
     7
# GNU General Public License version 2 or any later version.
131
c9d51742471c moving hgweb to mercurial subdir
jake@edge2.net
parents:
diff changeset
     8
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 27044
diff changeset
     9
30766
d7bf7d2bd5ab hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30641
diff changeset
    10
import base64
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 27044
diff changeset
    11
import errno
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 27044
diff changeset
    12
import mimetypes
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 27044
diff changeset
    13
import os
36789
ffa3026d4196 cleanup: use stat_result[stat.ST_MTIME] instead of stat_result.st_mtime
Augie Fackler <augie@google.com>
parents: 36677
diff changeset
    14
import stat
5561
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
    15
50473
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    16
from ..i18n import _
43089
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
    17
from ..pycompat import (
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
    18
    getattr,
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
    19
    open,
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
    20
)
30620
bb77654dc7ae py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29566
diff changeset
    21
from .. import (
30641
f1c9fafcbf46 py3: replace os.environ with encoding.environ (part 3 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30630
diff changeset
    22
    encoding,
30620
bb77654dc7ae py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29566
diff changeset
    23
    pycompat,
50479
4bddc2f72879 hgweb: move ismember from `hgweb.common` to `scmutil`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50473
diff changeset
    24
    scmutil,
45398
dc9fe90bdbd5 hgweb: let staticfile() look up path from default location unless provided
Martin von Zweigbergk <martinvonz@google.com>
parents: 45327
diff changeset
    25
    templater,
30620
bb77654dc7ae py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29566
diff changeset
    26
    util,
bb77654dc7ae py3: replace os.sep with pycompat.ossep (part 3 of 4)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29566
diff changeset
    27
)
29566
075146e85bb6 py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29491
diff changeset
    28
075146e85bb6 py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29491
diff changeset
    29
httpserver = util.httpserver
075146e85bb6 py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29491
diff changeset
    30
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
    31
HTTP_OK = 200
37152
cc0a6ea95d98 lfs: add support for serving blob files
Matt Harbison <matt_harbison@yahoo.com>
parents: 37150
diff changeset
    32
HTTP_CREATED = 201
12183
f64b416b0ac8 hgweb: support very simple caching model (issue1845)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10264
diff changeset
    33
HTTP_NOT_MODIFIED = 304
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
    34
HTTP_BAD_REQUEST = 400
6926
57b954d8d003 hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6924
diff changeset
    35
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
    36
HTTP_FORBIDDEN = 403
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
    37
HTTP_NOT_FOUND = 404
6926
57b954d8d003 hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6924
diff changeset
    38
HTTP_METHOD_NOT_ALLOWED = 405
37693
31a0d47d69b3 lfs: update the HTTP status codes in error cases
Matt Harbison <matt_harbison@yahoo.com>
parents: 37152
diff changeset
    39
HTTP_NOT_ACCEPTABLE = 406
31a0d47d69b3 lfs: update the HTTP status codes in error cases
Matt Harbison <matt_harbison@yahoo.com>
parents: 37152
diff changeset
    40
HTTP_UNSUPPORTED_MEDIA_TYPE = 415
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
    41
HTTP_SERVER_ERROR = 500
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
    42
50479
4bddc2f72879 hgweb: move ismember from `hgweb.common` to `scmutil`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50473
diff changeset
    43
ismember = scmutil.ismember
19032
7d31f2e42a8a hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 18645
diff changeset
    44
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
    45
50473
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    46
def hashiddenaccess(repo, req):
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    47
    if bool(req.qsparams.get(b'access-hidden')):
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    48
        # Disable this by default for now. Main risk is to get critical
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    49
        # information exposed through this. This is expecially risky if
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    50
        # someone decided to make a changeset secret for good reason, but
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    51
        # its predecessors are still draft.
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    52
        #
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    53
        # The feature is currently experimental, so we can still decide to
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    54
        # change the default.
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    55
        ui = repo.ui
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    56
        allow = ui.configlist(b'experimental', b'server.allow-hidden-access')
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    57
        user = req.remoteuser
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    58
        if allow and ismember(ui, user, allow):
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    59
            return True
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    60
        else:
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    61
            msg = (
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    62
                _(
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    63
                    b'ignoring request to access hidden changeset by '
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    64
                    b'unauthorized user: %r\n'
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    65
                )
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    66
                % user
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    67
            )
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    68
            ui.warn(msg)
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    69
    return False
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    70
4077d6222cf1 hgweb: add support to explicitly access hidden changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49037
diff changeset
    71
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    72
def checkauthz(hgweb, req, op):
45957
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45400
diff changeset
    73
    """Check permission for operation based on request data (including
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    74
    authentication info). Return if op allowed, else raise an ErrorResponse
45957
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45400
diff changeset
    75
    exception."""
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    76
36883
02bea04b4c54 hgweb: transition permissions hooks to modern request type (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36879
diff changeset
    77
    user = req.remoteuser
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    78
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    79
    deny_read = hgweb.configlist(b'web', b'deny_read')
19032
7d31f2e42a8a hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 18645
diff changeset
    80
    if deny_read and (not user or ismember(hgweb.repo.ui, user, deny_read)):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    81
        raise ErrorResponse(HTTP_UNAUTHORIZED, b'read not authorized')
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    82
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    83
    allow_read = hgweb.configlist(b'web', b'allow_read')
19032
7d31f2e42a8a hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 18645
diff changeset
    84
    if allow_read and (not ismember(hgweb.repo.ui, user, allow_read)):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    85
        raise ErrorResponse(HTTP_UNAUTHORIZED, b'read not authorized')
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    86
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    87
    if op == b'pull' and not hgweb.allowpull:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    88
        raise ErrorResponse(HTTP_UNAUTHORIZED, b'pull not authorized')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    89
    elif op == b'pull' or op is None:  # op is None for interface requests
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    90
        return
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    91
37150
a2566597acb5 lfs: add basic routing for the server side wire protocol processing
Matt Harbison <matt_harbison@yahoo.com>
parents: 36883
diff changeset
    92
    # Allow LFS uploading via PUT requests
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    93
    if op == b'upload':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    94
        if req.method != b'PUT':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    95
            msg = b'upload requires PUT request'
37150
a2566597acb5 lfs: add basic routing for the server side wire protocol processing
Matt Harbison <matt_harbison@yahoo.com>
parents: 36883
diff changeset
    96
            raise ErrorResponse(HTTP_METHOD_NOT_ALLOWED, msg)
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
    97
    # enforce that you can only push using POST requests
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    98
    elif req.method != b'POST':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    99
        msg = b'push requires POST request'
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
   100
        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
   101
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
   102
    # 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
   103
    # and replayed
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   104
    if hgweb.configbool(b'web', b'push_ssl') and req.urlscheme != b'https':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   105
        raise ErrorResponse(HTTP_FORBIDDEN, b'ssl required')
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
   106
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   107
    deny = hgweb.configlist(b'web', b'deny_push')
19032
7d31f2e42a8a hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 18645
diff changeset
   108
    if deny and (not user or ismember(hgweb.repo.ui, user, deny)):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   109
        raise ErrorResponse(HTTP_UNAUTHORIZED, b'push not authorized')
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
   110
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   111
    allow = hgweb.configlist(b'web', b'allow-push')
19032
7d31f2e42a8a hgweb: refactor checks for granting and revoking user permissions
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 18645
diff changeset
   112
    if not (allow and ismember(hgweb.repo.ui, user, allow)):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   113
        raise ErrorResponse(HTTP_UNAUTHORIZED, b'push not authorized')
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
   114
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   115
14058
3233b39d756f hgweb: initialize permhooks at definition time
Martin Geisler <mg@lazybytes.net>
parents: 13959
diff changeset
   116
# 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
   117
# Each hook is invoked like this: hook(hgweb, request, operation),
37150
a2566597acb5 lfs: add basic routing for the server side wire protocol processing
Matt Harbison <matt_harbison@yahoo.com>
parents: 36883
diff changeset
   118
# where operation is either read, pull, push or upload. Hooks should either
14058
3233b39d756f hgweb: initialize permhooks at definition time
Martin Geisler <mg@lazybytes.net>
parents: 13959
diff changeset
   119
# raise an ErrorResponse exception, or just return.
3233b39d756f hgweb: initialize permhooks at definition time
Martin Geisler <mg@lazybytes.net>
parents: 13959
diff changeset
   120
#
3233b39d756f hgweb: initialize permhooks at definition time
Martin Geisler <mg@lazybytes.net>
parents: 13959
diff changeset
   121
# 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
   122
# this.
3233b39d756f hgweb: initialize permhooks at definition time
Martin Geisler <mg@lazybytes.net>
parents: 13959
diff changeset
   123
permhooks = [checkauthz]
9910
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
   124
6f92997dbdca hgweb: add support for extension-provided permission hooks
Sune Foldager <cryo@cyanite.org>
parents: 9694
diff changeset
   125
5561
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
   126
class ErrorResponse(Exception):
31399
7dafa8d0e006 hgweb: don't use mutable default argument value
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30766
diff changeset
   127
    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
   128
        if message is None:
75f5f312df5f hgweb: give ErrorResponse a descriptive string/Exception representation
Mads Kiilerich <mads@kiilerich.com>
parents: 13400
diff changeset
   129
            message = _statusmessage(code)
36459
f8ea6988a5fb hgweb: pass exception message to builtin Exception ctor as sysstr
Augie Fackler <augie@google.com>
parents: 36427
diff changeset
   130
        Exception.__init__(self, pycompat.sysstr(message))
5561
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
   131
        self.code = code
31444
2daeab02b4b1 hgweb: explicitly tests for None
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31399
diff changeset
   132
        if headers is None:
2daeab02b4b1 hgweb: explicitly tests for None
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31399
diff changeset
   133
            headers = []
2daeab02b4b1 hgweb: explicitly tests for None
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31399
diff changeset
   134
        self.headers = headers
42926
8d9322b6e687 hgweb: add a `message` attribute to `hgweb.common.ErrorResponse`
Connor Sheehan <sheehan@mozilla.com>
parents: 40211
diff changeset
   135
        self.message = message
5563
d61fea133f2d hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents: 5561
diff changeset
   136
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   137
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
   138
class continuereader:
36859
7066617187c1 hgweb: document continuereader
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36789
diff changeset
   139
    """File object wrapper to handle HTTP 100-continue.
7066617187c1 hgweb: document continuereader
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36789
diff changeset
   140
7066617187c1 hgweb: document continuereader
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36789
diff changeset
   141
    This is used by servers so they automatically handle Expect: 100-continue
7066617187c1 hgweb: document continuereader
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36789
diff changeset
   142
    request headers. On first read of the request body, the 100 Continue
7066617187c1 hgweb: document continuereader
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36789
diff changeset
   143
    response is sent. This should trigger the client into actually sending
7066617187c1 hgweb: document continuereader
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36789
diff changeset
   144
    the request body.
7066617187c1 hgweb: document continuereader
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36789
diff changeset
   145
    """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   146
13570
617a87cb7eb2 hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents: 13444
diff changeset
   147
    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
   148
        self.f = f
617a87cb7eb2 hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents: 13444
diff changeset
   149
        self._write = write
617a87cb7eb2 hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents: 13444
diff changeset
   150
        self.continued = False
617a87cb7eb2 hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents: 13444
diff changeset
   151
617a87cb7eb2 hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents: 13444
diff changeset
   152
    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
   153
        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
   154
            self.continued = True
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   155
            self._write(b'HTTP/1.1 100 Continue\r\n\r\n')
13570
617a87cb7eb2 hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents: 13444
diff changeset
   156
        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
   157
617a87cb7eb2 hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents: 13444
diff changeset
   158
    def __getattr__(self, attr):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   159
        if attr in (b'close', b'readline', b'readlines', b'__iter__'):
13570
617a87cb7eb2 hgweb: add support for 100-continue as recommended by PEP 333.
Augie Fackler <durin42@gmail.com>
parents: 13444
diff changeset
   160
            return getattr(self.f, attr)
16687
e34106fa0dc3 cleanup: "raise SomeException()" -> "raise SomeException"
Brodie Rao <brodie@sf.io>
parents: 14058
diff changeset
   161
        raise AttributeError
5563
d61fea133f2d hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents: 5561
diff changeset
   162
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   163
5563
d61fea133f2d hgweb: fix breaking tests on Python < 2.5
Bryan O'Sullivan <bos@serpentine.com>
parents: 5561
diff changeset
   164
def _statusmessage(code):
29566
075146e85bb6 py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29491
diff changeset
   165
    responses = httpserver.basehttprequesthandler.responses
43554
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43089
diff changeset
   166
    return pycompat.bytesurl(responses.get(code, ('Error', 'Unknown error'))[0])
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   167
5760
0145f9afb0e7 Removed tabs and trailing whitespace in python files
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5563
diff changeset
   168
9694
8269fe2d48f6 hgweb: send proper error messages to the client
Sune Foldager <cryo@cyanite.org>
parents: 9031
diff changeset
   169
def statusmessage(code, message=None):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   170
    return b'%d %s' % (code, message or _statusmessage(code))
131
c9d51742471c moving hgweb to mercurial subdir
jake@edge2.net
parents:
diff changeset
   171
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   172
25717
46e2c57026bc hgweb: drop the default argument for get_stat
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25660
diff changeset
   173
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
   174
    """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
   175
    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
   176
    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
   177
        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
   178
    else:
13958
71f51cc71652 hgweb: detect change based on changelog size too
Martin Geisler <mg@lazybytes.net>
parents: 13444
diff changeset
   179
        return os.stat(spath)
71f51cc71652 hgweb: detect change based on changelog size too
Martin Geisler <mg@lazybytes.net>
parents: 13444
diff changeset
   180
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   181
13958
71f51cc71652 hgweb: detect change based on changelog size too
Martin Geisler <mg@lazybytes.net>
parents: 13444
diff changeset
   182
def get_mtime(spath):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   183
    return get_stat(spath, b"00changelog.i")[stat.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
   184
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   185
31793
62f9679df1f2 hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31792
diff changeset
   186
def ispathsafe(path):
62f9679df1f2 hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31792
diff changeset
   187
    """Determine if a path is safe to use for filesystem access."""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   188
    parts = path.split(b'/')
31793
62f9679df1f2 hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31792
diff changeset
   189
    for part in parts:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   190
        if (
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   191
            part in (b'', pycompat.oscurdir, pycompat.ospardir)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   192
            or pycompat.ossep in part
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   193
            or pycompat.osaltsep is not None
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   194
            and pycompat.osaltsep in part
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   195
        ):
31793
62f9679df1f2 hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31792
diff changeset
   196
            return False
62f9679df1f2 hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31792
diff changeset
   197
62f9679df1f2 hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31792
diff changeset
   198
    return True
62f9679df1f2 hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31792
diff changeset
   199
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   200
45398
dc9fe90bdbd5 hgweb: let staticfile() look up path from default location unless provided
Martin von Zweigbergk <martinvonz@google.com>
parents: 45327
diff changeset
   201
def staticfile(templatepath, directory, fname, res):
5930
c301f15c965a send conservatively capitalized HTTP headers
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5779
diff changeset
   202
    """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
   203
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
   204
    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
   205
    contain unusual path components.
5930
c301f15c965a send conservatively capitalized HTTP headers
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5779
diff changeset
   206
    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
   207
    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
   208
1825
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
   209
    """
31793
62f9679df1f2 hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31792
diff changeset
   210
    if not ispathsafe(fname):
62f9679df1f2 hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31792
diff changeset
   211
        return
62f9679df1f2 hgweb: extract path traversal checking into standalone function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31792
diff changeset
   212
45398
dc9fe90bdbd5 hgweb: let staticfile() look up path from default location unless provided
Martin von Zweigbergk <martinvonz@google.com>
parents: 45327
diff changeset
   213
    if not directory:
dc9fe90bdbd5 hgweb: let staticfile() look up path from default location unless provided
Martin von Zweigbergk <martinvonz@google.com>
parents: 45327
diff changeset
   214
        tp = templatepath or templater.templatedir()
dc9fe90bdbd5 hgweb: let staticfile() look up path from default location unless provided
Martin von Zweigbergk <martinvonz@google.com>
parents: 45327
diff changeset
   215
        if tp is not None:
dc9fe90bdbd5 hgweb: let staticfile() look up path from default location unless provided
Martin von Zweigbergk <martinvonz@google.com>
parents: 45327
diff changeset
   216
            directory = os.path.join(tp, b'static')
dc9fe90bdbd5 hgweb: let staticfile() look up path from default location unless provided
Martin von Zweigbergk <martinvonz@google.com>
parents: 45327
diff changeset
   217
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   218
    fpath = os.path.join(*fname.split(b'/'))
45400
f0735f2ce542 hgweb: minimize scope of a try-block in staticfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45399
diff changeset
   219
    ct = pycompat.sysbytes(
f0735f2ce542 hgweb: minimize scope of a try-block in staticfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45399
diff changeset
   220
        mimetypes.guess_type(pycompat.fsdecode(fpath))[0] or r"text/plain"
f0735f2ce542 hgweb: minimize scope of a try-block in staticfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45399
diff changeset
   221
    )
45327
9a5c4875a88c hgweb: simplify staticfile() now that we always pass it a single directory
Martin von Zweigbergk <martinvonz@google.com>
parents: 43811
diff changeset
   222
    path = os.path.join(directory, fpath)
1793
83c6d8355909 Allow serving static files from hgwebdir to fix CSS and favicon.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1792
diff changeset
   223
    try:
1825
a9343f9d7365 Make hgweb.staticfile() more secure and portable.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1796
diff changeset
   224
        os.stat(path)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   225
        with open(path, b'rb') as fh:
31792
161a87ed456e hgweb: use context manager for file I/O
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31444
diff changeset
   226
            data = fh.read()
5561
22713dce19f6 hgweb: return meaningful HTTP status codes instead of nonsense
Bryan O'Sullivan <bos@serpentine.com>
parents: 4462
diff changeset
   227
    except TypeError:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   228
        raise ErrorResponse(HTTP_SERVER_ERROR, b'illegal filename')
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 22577
diff changeset
   229
    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
   230
        if err.errno == errno.ENOENT:
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5930
diff changeset
   231
            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
   232
        else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   233
            raise ErrorResponse(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   234
                HTTP_SERVER_ERROR, encoding.strtolocal(err.strerror)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   235
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   236
45400
f0735f2ce542 hgweb: minimize scope of a try-block in staticfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45399
diff changeset
   237
    res.headers[b'Content-Type'] = ct
f0735f2ce542 hgweb: minimize scope of a try-block in staticfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45399
diff changeset
   238
    res.setbodybytes(data)
f0735f2ce542 hgweb: minimize scope of a try-block in staticfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45399
diff changeset
   239
    return res
f0735f2ce542 hgweb: minimize scope of a try-block in staticfile()
Martin von Zweigbergk <martinvonz@google.com>
parents: 45399
diff changeset
   240
3276
db9d2a624521 hgweb: Search templates in templatepath/style/map, too, using a common function.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3244
diff changeset
   241
4462
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   242
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
   243
    """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
   244
    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
   245
        # 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
   246
        count = (stripecount + offset) % stripecount
36427
7a3590e67868 py3: use '//' for integer division in hgweb/common.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36329
diff changeset
   247
        parity = (stripecount + offset) // stripecount & 1
4462
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   248
    else:
12e4d9524951 hgweb: use generator to count parity of horizontal stripes for easier reading.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4038
diff changeset
   249
        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
   250
        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
   251
    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
   252
        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
   253
        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
   254
        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
   255
            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
   256
            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
   257
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   258
5779
e9f68860d5ed Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5760
diff changeset
   259
def get_contact(config):
e9f68860d5ed Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5760
diff changeset
   260
    """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
   261
e9f68860d5ed Don't let ui.username override web.contact (issue900)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5760
diff changeset
   262
    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
   263
    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
   264
    """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   265
    return (
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   266
        config(b"web", b"contact")
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   267
        or config(b"ui", b"username")
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   268
        or encoding.environ.get(b"EMAIL")
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   269
        or b""
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   270
    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42926
diff changeset
   271
12183
f64b416b0ac8 hgweb: support very simple caching model (issue1845)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 10264
diff changeset
   272
30766
d7bf7d2bd5ab hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30641
diff changeset
   273
def cspvalues(ui):
d7bf7d2bd5ab hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30641
diff changeset
   274
    """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
   275
d7bf7d2bd5ab hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30641
diff changeset
   276
    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
   277
d7bf7d2bd5ab hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30641
diff changeset
   278
    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
   279
    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
   280
    """
34643
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   281
    # Without demandimport, "import uuid" could have an immediate side-effect
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   282
    # running "ldconfig" on Linux trying to find libuuid.
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   283
    # With Python <= 2.7.12, that "ldconfig" is run via a shell and the shell
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   284
    # may pollute the terminal with:
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   285
    #
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   286
    #   shell-init: error retrieving current directory: getcwd: cannot access
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   287
    #   parent directories: No such file or directory
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   288
    #
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   289
    # Python >= 2.7.13 has fixed it by running "ldconfig" directly without a
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   290
    # shell (hg changeset a09ae70f3489).
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   291
    #
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   292
    # Moved "import uuid" from here so it's executed after we know we have
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   293
    # a sane cwd (i.e. after dispatch.py cwd check).
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   294
    #
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   295
    # We can move it back once we no longer need Python <= 2.7.12 support.
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   296
    import uuid
f42dec9c976e hgweb: do not import uuid immediately to avoid its side effect
Jun Wu <quark@fb.com>
parents: 34585
diff changeset
   297
30766
d7bf7d2bd5ab hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30641
diff changeset
   298
    # 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
   299
    # from a trusted/global source.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   300
    csp = ui.config(b'web', b'csp', untrusted=False)
30766
d7bf7d2bd5ab hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30641
diff changeset
   301
    nonce = None
d7bf7d2bd5ab hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30641
diff changeset
   302
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   303
    if csp and b'%nonce%' in csp:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   304
        nonce = base64.urlsafe_b64encode(uuid.uuid4().bytes).rstrip(b'=')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   305
        csp = csp.replace(b'%nonce%', nonce)
30766
d7bf7d2bd5ab hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30641
diff changeset
   306
d7bf7d2bd5ab hgweb: support Content Security Policy
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30641
diff changeset
   307
    return csp, nonce