def process_reply(self, code): if code not in reply_names: raise ProtocolError('%s is not a known reply code' % code) if code not in self.allowed_replies: code_name = reply_names[code] raise ProtocolError('reply code %s is not allowed for %s' % (code_name, self.command)) return True
def encode(self, *params): """ Encode the event into a string. :return: a unicode string ending in CRLF :raises ProtocolError: if any parameter save the last one contains spaces """ buffer = '' if self.sender: buffer += ':' + self.sender + ' ' for i, param in enumerate(params): if not param: continue if ' ' in param: if i == len(params) - 1: param = ':' + param else: raise ProtocolError( 'only the last parameter can contain spaces') if i > 0: buffer += ' ' buffer += param return buffer + '\r\n'
def validate_hostmask(mask): """ Ensure that a host mask conforms to the restrictions of RFC 2818. :param bytes mask: the mask to validate :raises ..exceptions.ProtocolError: if the host mask is invalid """ if not hostmask_re.match(mask): raise ProtocolError(u'invalid host mask: %s' % mask.decode('ascii', errors='backslashreplace'))
def validate_nickname(name): """ Ensure that a nickname conforms to the restrictions of RFC 2818. :param bytes name: the nickname to validate :raises ..exceptions.ProtocolError: if the nickname is invalid """ if not nickname_re.match(name): raise ProtocolError(u'invalid nickname: %s' % name.decode('ascii', errors='backslashreplace'))
def _send_event(self, event): """ Send an event to the peer. :param ircproto.events.Event event: the event to send """ if self._closed: raise ProtocolError('the connection has been closed') encoded_event = event.encode() self._output_buffer.extend(self.output_codec(encoded_event)[0])
def decode_event(buffer, decoder=codecs.getdecoder('utf-8'), fallback_decoder=codecs.getdecoder('iso-8859-1')): end_index = buffer.find(b'\r\n') if end_index == -1: return None elif end_index > 510: # Section 2.3 raise ProtocolError('received oversized message (%d bytes)' % (end_index + 2)) try: message = decoder(buffer[:end_index])[0] except UnicodeDecodeError: message = fallback_decoder(buffer[:end_index], errors='replace')[0] del buffer[:end_index + 2] if message[0] == ':': prefix, _, rest = message[1:].partition(' ') command, _, rest = rest.partition(' ') else: prefix = None command, _, rest = message.partition(' ') if command.isdigit(): return Reply(prefix, command, rest) try: command_class = commands[command] except KeyError: raise UnknownCommand(command) params = [] if rest: parts = rest.split(' ') for i, param in enumerate(parts): if param.startswith(':'): param = param[1:] if parts[i + 1:]: param += ' ' + ' '.join(parts[i + 1:]) params.append(param) break elif param: params.append(param) return command_class.decode(prefix, *params)
def send_command(self, command, *params): """ Send a command to the peer. This method looks up the appropriate command event class and instantiates it using ``params``. Then the event is encoded and added to the output buffer. :param str command: name of the command (``NICK``, ``PRIVMSG`` etc.) :param str params: arguments for the constructor of the command class """ if isinstance(command, bytes): command = command.decode('ascii') try: command_cls = commands[command] except KeyError: raise ProtocolError('no such command: %s' % command) event = command_cls(None, *params) self._send_event(event)
def decode(cls, sender, *params): try: return cls(sender, *params) except TypeError: raise ProtocolError('wrong number of arguments for %s' % cls.command)