def __handle_privmsg(self, source, target, message): nick = get_irc_nick(source) if target == self.nick: if message[0] == '\x01': endindex = message[1:].find('\x01') if endindex == -1: return ctcp = message[1:endindex + 1] if ctcp.upper() == 'VERSION': self.send_raw('PRIVMSG ' + nick + ' :\x01VERSION xchat 2.8.8 Ubuntu\x01') return if nick not in self.built_privmsg: if message[0] != COMMAND_PREFIX: log.debug('message not a cmd') return # new message starting cmd_string = message[1:].split(' ')[0] if cmd_string not in plaintext_commands + encrypted_commands: log.debug('cmd not in cmd_list, line="' + message + '"') return self.built_privmsg[nick] = [cmd_string, message[:-2]] else: self.built_privmsg[nick][1] += message[:-2] box, encrypt = self.__get_encryption_box( self.built_privmsg[nick][0], nick) if message[-1] == ';': self.waiting[nick] = True elif message[-1] == '~': self.waiting[nick] = False if encrypt: if not box: log.debug('error, dont have encryption box object for ' + nick + ', dropping message') return # need to decrypt everything after the command string to_decrypt = ''.join(self.built_privmsg[nick][1].split(' ')[ 1]) try: decrypted = decode_decrypt(to_decrypt, box) except ValueError as e: log.debug('valueerror when decrypting, skipping: ' + repr(e)) return parsed = self.built_privmsg[nick][1].split(' ')[ 0] + ' ' + decrypted else: parsed = self.built_privmsg[nick][1] # wipe the message buffer waiting for the next one del self.built_privmsg[nick] log.debug("<<privmsg nick=%s message=%s" % (nick, parsed)) self.__on_privmsg(nick, parsed) else: # drop the bad nick del self.built_privmsg[nick] elif target == self.channel: log.debug("<<pubmsg nick=%s message=%s" % (nick, message)) self.__on_pubmsg(nick, message) else: log.debug('what is this? privmsg src=%s target=%s message=%s;' % (source, target, message))
def on_privmsg(self, nick, message): """handles the case when a private message is received""" #Aberrant short messages should be handled by subclasses #in _privmsg, but this constitutes a sanity check. Note that #messages which use an encrypted_command but present no #ciphertext will be rejected with the ValueError on decryption. #Other ill formatted messages will be caught in the try block. if len(message) < 2: return if message[0] != COMMAND_PREFIX: log.debug('message not a cmd') return cmd_string = message[1:].split(' ')[0] if cmd_string not in plaintext_commands + encrypted_commands: log.debug('cmd not in cmd_list, line="' + message + '"') return #Verify nick ownership sig = message[1:].split(' ')[-2:] #reconstruct original message without cmd rawmessage = ' '.join(message[1:].split(' ')[1:-2]) #sanity check that the sig was appended properly if len(sig) != 2 or len(rawmessage) == 0: log.debug("Sig not properly appended to privmsg, ignoring") return if not self.verify_nick(nick, sig, rawmessage): #This is an impostor; just ignore log.debug("Message received from unverified counterparty; ignoring") return #Marks the nick as active on this channel; note *only* if verified. #Otherwise squatter/attacker can persuade us to send privmsgs to him. if self.on_privmsg_trigger: self.on_privmsg_trigger(nick, self) #strip sig from message for processing, having verified message = " ".join(message[1:].split(" ")[:-2]) for command in message.split(COMMAND_PREFIX): _chunks = command.split(" ") #Decrypt if necessary if _chunks[0] in encrypted_commands: box, encrypt = self.get_encryption_box(_chunks[0], nick) if encrypt: if not box: log.debug('error, dont have encryption box object for ' + nick + ', dropping message') return # need to decrypt everything after the command string to_decrypt = ''.join(_chunks[1:]) try: decrypted = decode_decrypt(to_decrypt, box) except ValueError as e: log.debug('valueerror when decrypting, skipping: ' + repr(e)) return #rebuild the chunks array as if it had been plaintext _chunks = [_chunks[0]] + decrypted.split(" ") # looks like a very similar pattern for all of these # check for a command name, parse arguments, call a function # maybe we need some eval() trickery to do it better try: # orderbook watch commands if self.check_for_orders(nick, _chunks): pass # taker commands elif _chunks[0] == 'pubkey': maker_pk = _chunks[1] if self.on_pubkey: self.on_pubkey(nick, maker_pk) elif _chunks[0] == 'ioauth': utxo_list = _chunks[1].split(',') auth_pub = _chunks[2] cj_addr = _chunks[3] change_addr = _chunks[4] btc_sig = _chunks[5] if self.on_ioauth: self.on_ioauth(nick, utxo_list, auth_pub, cj_addr, change_addr, btc_sig) elif _chunks[0] == 'sig': sig = _chunks[1] if self.on_sig: self.on_sig(nick, sig) # maker commands if self.check_for_commitments(nick, _chunks, private=True): pass if _chunks[0] == 'fill': try: oid = int(_chunks[1]) amount = int(_chunks[2]) taker_pk = _chunks[3] if len(_chunks) > 4: commit = _chunks[4] else: commit = None except (ValueError, IndexError) as e: self.send_error(nick, str(e)) if self.on_order_fill: self.on_order_fill(nick, oid, amount, taker_pk, commit) elif _chunks[0] == 'auth': try: cr = _chunks[1] except (ValueError, IndexError) as e: self.send_error(nick, str(e)) if self.on_seen_auth: self.on_seen_auth(nick, cr) elif _chunks[0] == 'tx': b64tx = _chunks[1] try: txhex = base64.b64decode(b64tx).encode('hex') except TypeError as e: self.send_error(nick, 'bad base64 tx. ' + repr(e)) if self.on_seen_tx: self.on_seen_tx(nick, txhex) elif _chunks[0] == 'push': b64tx = _chunks[1] try: txhex = base64.b64decode(b64tx).encode('hex') except TypeError as e: self.send_error(nick, 'bad base64 tx. ' + repr(e)) if self.on_push_tx: self.on_push_tx(nick, txhex) except CJPeerError: # TODO proper error handling log.debug('cj peer error TODO handle') continue
def __handle_privmsg(self, source, target, message): nick = get_irc_nick(source) if target == self.nick: if message[0] == '\x01': endindex = message[1:].find('\x01') if endindex == -1: return ctcp = message[1:endindex + 1] if ctcp.upper() == 'VERSION': self.send_raw('PRIVMSG ' + nick + ' :\x01VERSION xchat 2.8.8 Ubuntu\x01') return if nick not in self.built_privmsg: if message[0] != COMMAND_PREFIX: log.debug('message not a cmd') return # new message starting cmd_string = message[1:].split(' ')[0] if cmd_string not in plaintext_commands + encrypted_commands: log.debug('cmd not in cmd_list, line="' + message + '"') return self.built_privmsg[nick] = [cmd_string, message[:-2]] else: self.built_privmsg[nick][1] += message[:-2] box, encrypt = self.__get_encryption_box( self.built_privmsg[nick][0], nick) if message[-1] == ';': self.waiting[nick] = True elif message[-1] == '~': self.waiting[nick] = False if encrypt: if not box: log.debug( 'error, dont have encryption box object for ' + nick + ', dropping message') return # need to decrypt everything after the command string to_decrypt = ''.join( self.built_privmsg[nick][1].split(' ')[1]) try: decrypted = decode_decrypt(to_decrypt, box) except ValueError as e: log.debug('valueerror when decrypting, skipping: ' + repr(e)) return parsed = self.built_privmsg[nick][1].split( ' ')[0] + ' ' + decrypted else: parsed = self.built_privmsg[nick][1] # wipe the message buffer waiting for the next one del self.built_privmsg[nick] log.debug("<<privmsg nick=%s message=%s" % (nick, parsed)) self.__on_privmsg(nick, parsed) else: # drop the bad nick del self.built_privmsg[nick] elif target == self.channel: log.debug("<<pubmsg nick=%s message=%s" % (nick, message)) self.__on_pubmsg(nick, message) else: log.debug('what is this? privmsg src=%s target=%s message=%s;' % (source, target, message))
def on_privmsg(self, nick, message): """handles the case when a private message is received""" if message[0] != COMMAND_PREFIX: log.debug('message not a cmd') return cmd_string = message[1:].split(' ')[0] if cmd_string not in plaintext_commands + encrypted_commands: log.debug('cmd not in cmd_list, line="' + message + '"') return for command in message[1:].split(COMMAND_PREFIX): _chunks = command.split(" ") #Decrypt if necessary if _chunks[0] in encrypted_commands: box, encrypt = self.get_encryption_box(_chunks[0], nick) if encrypt: if not box: log.debug('error, dont have encryption box object for ' + nick + ', dropping message') return # need to decrypt everything after the command string to_decrypt = ''.join(_chunks[1:]) try: decrypted = decode_decrypt(to_decrypt, box) except ValueError as e: log.debug('valueerror when decrypting, skipping: ' + repr(e)) return #rebuild the chunks array as if it had been plaintext _chunks = [_chunks[0]] + decrypted.split(" ") # looks like a very similar pattern for all of these # check for a command name, parse arguments, call a function # maybe we need some eval() trickery to do it better try: # orderbook watch commands if self.check_for_orders(nick, _chunks): pass # taker commands elif _chunks[0] == 'pubkey': maker_pk = _chunks[1] if self.on_pubkey: self.on_pubkey(nick, maker_pk) elif _chunks[0] == 'ioauth': utxo_list = _chunks[1].split(',') cj_pub = _chunks[2] change_addr = _chunks[3] btc_sig = _chunks[4] if self.on_ioauth: self.on_ioauth(nick, utxo_list, cj_pub, change_addr, btc_sig) elif _chunks[0] == 'sig': sig = _chunks[1] if self.on_sig: self.on_sig(nick, sig) # maker commands if _chunks[0] == 'fill': try: oid = int(_chunks[1]) amount = int(_chunks[2]) taker_pk = _chunks[3] except (ValueError, IndexError) as e: self.send_error(nick, str(e)) if self.on_order_fill: self.on_order_fill(nick, oid, amount, taker_pk) elif _chunks[0] == 'auth': try: i_utxo_pubkey = _chunks[1] btc_sig = _chunks[2] except (ValueError, IndexError) as e: self.send_error(nick, str(e)) if self.on_seen_auth: self.on_seen_auth(nick, i_utxo_pubkey, btc_sig) elif _chunks[0] == 'tx': b64tx = _chunks[1] try: txhex = base64.b64decode(b64tx).encode('hex') except TypeError as e: self.send_error(nick, 'bad base64 tx. ' + repr(e)) if self.on_seen_tx: self.on_seen_tx(nick, txhex) elif _chunks[0] == 'push': b64tx = _chunks[1] try: txhex = base64.b64decode(b64tx).encode('hex') except TypeError as e: self.send_error(nick, 'bad base64 tx. ' + repr(e)) if self.on_push_tx: self.on_push_tx(nick, txhex) except CJPeerError: # TODO proper error handling log.debug('cj peer error TODO handle') continue