mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-01 09:19:23 +01:00
unreal: fix #137
a.k.a. fix the mess I made encoding IPs by not knowing about socket.inet_pton / socket.inet_ntop.
This commit is contained in:
parent
197532c1be
commit
0c068c6543
@ -3,6 +3,7 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import codecs
|
import codecs
|
||||||
|
import socket
|
||||||
import re
|
import re
|
||||||
|
|
||||||
curdir = os.path.dirname(__file__)
|
curdir = os.path.dirname(__file__)
|
||||||
@ -64,12 +65,31 @@ class UnrealProtocol(TS6BaseProtocol):
|
|||||||
realhost=realhost, ip=ip, manipulatable=manipulatable)
|
realhost=realhost, ip=ip, manipulatable=manipulatable)
|
||||||
utils.applyModes(self.irc, uid, modes)
|
utils.applyModes(self.irc, uid, modes)
|
||||||
self.irc.servers[server].users.add(uid)
|
self.irc.servers[server].users.add(uid)
|
||||||
|
|
||||||
|
# UnrealIRCd requires encoding the IP by first packing it into a binary format,
|
||||||
|
# and then encoding the binary with Base64.
|
||||||
|
if ip == '0.0.0.0': # Dummy IP (for services, etc.) use a single *.
|
||||||
|
encoded_ip = '*'
|
||||||
|
else:
|
||||||
|
try: # Try encoding as IPv4 first.
|
||||||
|
binary_ip = socket.inet_pton(socket.AF_INET, ip)
|
||||||
|
except OSError:
|
||||||
|
try: # That failed, try IPv6 next.
|
||||||
|
binary_ip = socket.inet_pton(socket.AF_INET6, ip)
|
||||||
|
except OSError:
|
||||||
|
raise ValueError("Invalid IPv4 or IPv6 address %r." % ip)
|
||||||
|
|
||||||
|
# Encode in Base64.
|
||||||
|
encoded_ip = codecs.encode(binary_ip, "base64")
|
||||||
|
# Now, strip the trailing \n and decode into a string again.
|
||||||
|
encoded_ip = encoded_ip.strip().decode()
|
||||||
|
|
||||||
# <- :001 UID GL 0 1441306929 gl localhost 0018S7901 0 +iowx * midnight-1C620195 fwAAAQ== :realname
|
# <- :001 UID GL 0 1441306929 gl localhost 0018S7901 0 +iowx * midnight-1C620195 fwAAAQ== :realname
|
||||||
self._send(server, "UID {nick} 0 {ts} {ident} {realhost} {uid} 0 {modes} "
|
self._send(server, "UID {nick} 0 {ts} {ident} {realhost} {uid} 0 {modes} "
|
||||||
"{host} * * :{realname}".format(ts=ts, host=host,
|
"{host} * {ip} :{realname}".format(ts=ts, host=host,
|
||||||
nick=nick, ident=ident, uid=uid,
|
nick=nick, ident=ident, uid=uid,
|
||||||
modes=raw_modes, realname=realname,
|
modes=raw_modes, realname=realname,
|
||||||
realhost=realhost))
|
realhost=realhost, ip=encoded_ip))
|
||||||
return u
|
return u
|
||||||
|
|
||||||
def joinClient(self, client, channel):
|
def joinClient(self, client, channel):
|
||||||
@ -292,14 +312,18 @@ class UnrealProtocol(TS6BaseProtocol):
|
|||||||
if raw_ip == b'*': # Dummy IP (for services, etc.)
|
if raw_ip == b'*': # Dummy IP (for services, etc.)
|
||||||
ip = '0.0.0.0'
|
ip = '0.0.0.0'
|
||||||
else:
|
else:
|
||||||
# Each base64-encoded character represents a bit in the IP.
|
# First, decode the Base64 string into a packed binary IP address.
|
||||||
raw_ip = codecs.decode(raw_ip, "base64")
|
ip = codecs.decode(raw_ip, "base64")
|
||||||
ipbits = list(map(str, raw_ip)) # Decode every bit
|
|
||||||
|
|
||||||
if len(ipbits) == 4: # IPv4 address.
|
try: # IPv4 address.
|
||||||
ip = '.'.join(ipbits)
|
ip = socket.inet_ntop(socket.AF_INET, ip)
|
||||||
elif len(ipbits) == 16: # IPv6 address.
|
except ValueError: # IPv6 address.
|
||||||
ip = ':'.join(ipbits)
|
ip = socket.inet_ntop(socket.AF_INET6, ip)
|
||||||
|
# HACK: make sure a leading ":" in the IPv6 address (e.g. ::1)
|
||||||
|
# doesn't cause it to be misinterpreted as the last argument
|
||||||
|
# in a line, should it be mirrored to other networks.
|
||||||
|
if ip.startswith(':'):
|
||||||
|
ip = '0' + ip
|
||||||
else:
|
else:
|
||||||
raise ProtocolError("Invalid number of bits in IP address field (got %s, expected 4 or 16)." % len(ipbits))
|
raise ProtocolError("Invalid number of bits in IP address field (got %s, expected 4 or 16)." % len(ipbits))
|
||||||
realname = args[-1]
|
realname = args[-1]
|
||||||
|
Loading…
Reference in New Issue
Block a user