Exemple #1
0
    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
Exemple #2
0
    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'
Exemple #3
0
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'))
Exemple #4
0
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'))
Exemple #5
0
    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])
Exemple #6
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)
Exemple #7
0
    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)
Exemple #8
0
 def decode(cls, sender, *params):
     try:
         return cls(sender, *params)
     except TypeError:
         raise ProtocolError('wrong number of arguments for %s' %
                             cls.command)