Patchwork D1999: wireproto: function for testing if wire protocol command is available

login
register
mail settings
Submitter phabricator
Date Feb. 6, 2018, 9:04 p.m.
Message ID <185b07812ab6ca9043f11e2bfbbe1964@localhost.localdomain>
Download mbox | patch
Permalink /patch/27385/
State Not Applicable
Headers show

Comments

phabricator - Feb. 6, 2018, 9:04 p.m.
indygreg updated this revision to Diff 5258.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D1999?vs=5138&id=5258

REVISION DETAIL
  https://phab.mercurial-scm.org/D1999

AFFECTED FILES
  mercurial/hgweb/hgweb_mod.py
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS




To: indygreg, #hg-reviewers
Cc: mercurial-devel

Patch

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -217,6 +217,13 @@ 
             yield chunk
 
     rsp = wireproto.dispatch(repo, proto, cmd)
+
+    if not wireproto.commands.commandavailable(cmd, proto):
+        req.respond(HTTP_OK, HGERRTYPE,
+                    body=_('requested wire protocol command is not available '
+                           'over HTTP'))
+        return []
+
     if isinstance(rsp, bytes):
         req.respond(HTTP_OK, HGTYPE, body=rsp)
         return []
@@ -345,7 +352,7 @@ 
 
     def serve_one(self):
         cmd = self._fin.readline()[:-1]
-        if cmd and cmd in wireproto.commands:
+        if cmd and wireproto.commands.commandavailable(cmd, self):
             rsp = wireproto.dispatch(self._repo, self, cmd)
             self._handlers[rsp.__class__](self, rsp)
         elif cmd:
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -691,6 +691,12 @@ 
 
         return super(commanddict, self).__setitem__(k, v)
 
+    def commandavailable(self, command, proto):
+        """Determine if a command is available for the requested protocol."""
+        # For now, commands are available for all protocols. So do a simple
+        # membership test.
+        return command in self
+
 commands = commanddict()
 
 def wireprotocommand(name, args=''):
diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -357,6 +357,14 @@ 
             query = req.env[r'QUERY_STRING'].partition(r'&')[0]
             query = query.partition(r';')[0]
 
+        # The ``cmd`` request parameter is used by both the wire protocol
+        # and hgweb. We route all known wire protocol commands to the
+        # wire protocol handler, even if the command isn't available for
+        # this transport. That's better for machine clients in the case
+        # of an errant request to an unavailable protocol command. And it
+        # prevents hgweb from accidentally using ``cmd`` values used by
+        # the wire protocol.
+
         # process this if it's a protocol request
         # protocol bits don't need to create any URLs
         # and the clients always use the old URL structure