diff options
Diffstat (limited to 'libpathod')
-rw-r--r-- | libpathod/language/base.py | 42 | ||||
-rw-r--r-- | libpathod/language/http.py | 16 | ||||
-rw-r--r-- | libpathod/language/websockets.py | 23 |
3 files changed, 70 insertions, 11 deletions
diff --git a/libpathod/language/base.py b/libpathod/language/base.py index 41855da3..725a0d42 100644 --- a/libpathod/language/base.py +++ b/libpathod/language/base.py @@ -291,14 +291,19 @@ class OptionsOrValue(_Component): Can be any of a specified set of options, or a value specifier. """ preamble = "" + options = [] def __init__(self, value): # If it's a string, we were passed one of the options, so we lower-case # it to be canonical. The user can specify a different case by using a # string value literal. self.option_used = False if isinstance(value, basestring): - value = TokValueLiteral(value.lower()) - self.option_used = True + for i in self.options: + # Find the exact option value in a case-insensitive way + if i.lower() == value.lower(): + self.option_used = True + value = TokValueLiteral(i) + break self.value = value @classmethod @@ -369,3 +374,36 @@ class Value(_Component): def freeze(self, settings): return self.__class__(self.value.freeze(settings)) + + +class IntField(_Component): + """ + An integer field, where values can optionally specified by name. + """ + names = {} + max = 16 + preamble = "" + + def __init__(self, value): + self.origvalue = value + self.value = self.names.get(value, value) + if self.value > self.max: + raise exceptions.ParseException( + "Value can't exceed %s"%self.max, 0, 0 + ) + + @classmethod + def expr(klass): + parts = [pp.CaselessLiteral(i) for i in klass.names.keys()] + m = pp.MatchFirst(parts) + spec = m | v_integer.copy() + spec = spec.setParseAction(lambda x: klass(*x)) + if klass.preamble: + spec = pp.Literal(klass.preamble).suppress() + spec + return spec + + def values(self, settings): + return [str(self.value)] + + def spec(self): + return "%s%s"%(self.preamble, self.origvalue) diff --git a/libpathod/language/http.py b/libpathod/language/http.py index ba43a367..94de7237 100644 --- a/libpathod/language/http.py +++ b/libpathod/language/http.py @@ -34,14 +34,14 @@ class Body(base.Value): class Method(base.OptionsOrValue): options = [ - "get", - "head", - "post", - "put", - "delete", - "options", - "trace", - "connect", + "GET", + "HEAD", + "POST", + "PUT", + "DELETE", + "OPTIONS", + "TRACE", + "CONNECT", ] diff --git a/libpathod/language/websockets.py b/libpathod/language/websockets.py index ae755f30..ddffdab9 100644 --- a/libpathod/language/websockets.py +++ b/libpathod/language/websockets.py @@ -17,6 +17,19 @@ class WF(base.CaselessLiteral): TOK = "wf" +class Code(base.IntField): + names = { + "continue": netlib.websockets.OPCODE.CONTINUE, + "text": netlib.websockets.OPCODE.TEXT, + "binary": netlib.websockets.OPCODE.BINARY, + "close": netlib.websockets.OPCODE.CLOSE, + "ping": netlib.websockets.OPCODE.PING, + "pong": netlib.websockets.OPCODE.PONG, + } + max = 15 + preamble = "c" + + class Body(base.Value): preamble = "b" @@ -24,6 +37,7 @@ class Body(base.Value): class WebsocketFrame(message.Message): comps = ( Body, + Code, actions.PauseAt, actions.DisconnectAt, actions.InjectAt @@ -37,6 +51,10 @@ class WebsocketFrame(message.Message): def body(self): return self.tok(Body) + @property + def code(self): + return self.tok(Code) + @classmethod def expr(klass): parts = [i.expr() for i in klass.comps] @@ -59,10 +77,13 @@ class WebsocketFrame(message.Message): else: bodygen = None length = 0 - frame = netlib.websockets.FrameHeader( + frameparts = dict( mask = True, payload_length = length ) + if self.code: + frameparts["opcode"] = self.code.value + frame = netlib.websockets.FrameHeader(**frameparts) vals = [frame.to_bytes()] if self.body: masker = netlib.websockets.Masker(frame.masking_key) |