mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-27 13:19:24 +01:00
Updated for XXXs down to unfinished reference code
-- Azaroth
This commit is contained in:
parent
32ba3b10b1
commit
afbeb4d582
315
src/dcc.py
315
src/dcc.py
@ -1,8 +1,13 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# You need a copyright notice here, azaroth.
|
|
||||||
|
|
||||||
# You might do well to put links to the documentation you're basing this on
|
# Copyright (c) Robert Sanderson All rights reserved.
|
||||||
# here. Then other people can help maintain it more easily.
|
# See LICENCE file in this distribution for details.
|
||||||
|
|
||||||
|
# Documentation on DCC specification
|
||||||
|
# http://www.mirc.co.uk/help/dccresum.txt
|
||||||
|
# www.irchelp.org/irchelp/rfc/dccspec.html
|
||||||
|
# Also several other lesser known/implemented/used commands are floating around
|
||||||
|
# but not implemented in major clients.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
@ -18,47 +23,48 @@ import ircutils
|
|||||||
import threading
|
import threading
|
||||||
|
|
||||||
def isDCC(msg):
|
def isDCC(msg):
|
||||||
# This needs to be more specific, it would catch too many messages
|
return msg.command == 'PRIVMSG' and msg.args[1][:5] == '\x01DCC '
|
||||||
# discussing DCC stuff. I added a test for this.
|
|
||||||
return msg.command == 'PRIVMSG' and msg.args[1][1:4] == 'DCC'
|
|
||||||
|
conf.registerGlobalValue(conf.supybot.protocols.dcc, 'timeout',
|
||||||
|
registry.Integer(120, "Timeout on DCC sockets"))
|
||||||
|
|
||||||
# ---- Out Handlers ----
|
# ---- Out Handlers ----
|
||||||
|
|
||||||
class DCCHandler:
|
class DCCHandler:
|
||||||
# You should reconsider whether all these arguments are necessary in the
|
|
||||||
# constructor. Long argument lists generally mean bad factoring.
|
|
||||||
def __init__(self, irc, nick, hostmask, logger=None):
|
def __init__(self, irc, nick, hostmask, logger=None):
|
||||||
self.irc = irc
|
self.irc = irc
|
||||||
self.nick = nick
|
self.nick = nick
|
||||||
self.hostmask = hostmask
|
self.hostmask = hostmask
|
||||||
self.sock = None
|
self.sock = None
|
||||||
# XXX () in if/while.
|
if logger:
|
||||||
if (logger):
|
|
||||||
# XXX Log something specific
|
|
||||||
self.log = logger
|
self.log = logger
|
||||||
else:
|
else:
|
||||||
self.log = log
|
self.log = log
|
||||||
# XXX Why 120? Shouldn't that be configurable?
|
|
||||||
self.timeout = 120
|
self.timeout = conf.supybot.protocols.dcc.timeout()
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
# What's this self.open? I don't see an open method.
|
|
||||||
t = threading.Thread(target=self.open)
|
t = threading.Thread(target=self.open)
|
||||||
world.threadsSpawned += 1
|
world.threadsSpawned += 1
|
||||||
t.setDaemon(True)
|
t.setDaemon(True)
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
|
def open(self):
|
||||||
|
# Override in subclasses to do something
|
||||||
|
pass
|
||||||
|
|
||||||
def clientConnected(self):
|
def clientConnected(self):
|
||||||
|
# Override in subclasses to do something when a client connects
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def clientClosed(self):
|
def clientClosed(self):
|
||||||
|
# Override to do something when a client closes connection
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class SendHandler(DCCHandler):
|
class SendHandler(DCCHandler):
|
||||||
""" Handle sending a file """
|
""" Handle sending a file """
|
||||||
# What I said about long argument lists in DCCHandler applies doubly here.
|
|
||||||
def __init__(self, irc, nick, hostmask, filename, logger=None, start=0):
|
def __init__(self, irc, nick, hostmask, filename, logger=None, start=0):
|
||||||
DCCHandler.__init__(self, irc, nick, hostmask, logger)
|
DCCHandler.__init__(self, irc, nick, hostmask, logger)
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
@ -76,167 +82,122 @@ class SendHandler(DCCHandler):
|
|||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
ip = conf.supybot.externalIP()
|
ip = conf.supybot.externalIP()
|
||||||
host = ircutils.hostFromHostmask(self.irc.prefix)
|
|
||||||
if not ip:
|
|
||||||
try:
|
|
||||||
ip = socket.gethostbyname(host)
|
|
||||||
except: # XXX Don't use blank excepts.
|
|
||||||
# XXX Be sure you mention who you are and why you couldn't do
|
|
||||||
# what you should.
|
|
||||||
self.log.warning('Could not determine IP address')
|
|
||||||
return
|
|
||||||
try:
|
try:
|
||||||
self.filesize = os.path.getsize(self.filename)
|
self.filesize = os.path.getsize(self.filename)
|
||||||
except OSError, e:
|
except OSError, e:
|
||||||
# XXX: There should be a log.warning or log.error here.
|
self.log.warning('Requested file does not exist: %r',
|
||||||
# Doesn't exist
|
self.filename)
|
||||||
# ^^^^^^^^^^^^^ What doesn't exist?
|
|
||||||
return
|
return
|
||||||
|
|
||||||
sock = utils.getSocket(ip)
|
sock = utils.getSocket(ip)
|
||||||
try:
|
try:
|
||||||
sock.bind((ip, 0))
|
sock.bind((ip, 0))
|
||||||
except socket.error, e:
|
except socket.error, e:
|
||||||
# XXX: There should be a log.warning or log.error here.
|
self.log.warning('Could not bind a socket to send.')
|
||||||
return
|
return
|
||||||
port = sock.getsockname()[1]
|
port = sock.getsockname()[1]
|
||||||
self.port = port
|
self.port = port
|
||||||
|
|
||||||
self.registerPort()
|
self.registerPort()
|
||||||
|
|
||||||
i = ircutils.dccIP(ip)
|
i = ircutils.dccIP(ip)
|
||||||
sock.listen(1)
|
sock.listen(1)
|
||||||
## self.irc.queueMsg(ircmsgs.privmsg(self.nick,
|
|
||||||
## '\x01DCC SEND %s %s %d %d\x01' % (self.filename, i, port,
|
|
||||||
## self.filesize)))
|
|
||||||
## That formatting is bad. Try this instead:
|
|
||||||
## msg = ircmsgs.privmsg(self.nick,
|
|
||||||
## '\x01DCC SEND %s %s %s %s\x01' % \
|
|
||||||
## (self.filename, i, port, self.filesize))
|
|
||||||
## self.irc.queueMsg(msg)
|
|
||||||
## Even better, I'll define a function ircmsgs.py.
|
|
||||||
msg = ircmsgs.dcc(self.nick, 'SEND', self.filename, i, port, self.filesize)
|
msg = ircmsgs.dcc(self.nick, 'SEND', self.filename, i, port, self.filesize)
|
||||||
self.irc.queueMsg(msg)
|
self.irc.queueMsg(msg)
|
||||||
# Wait for possible RESUME
|
|
||||||
# That comment isn't enough, why are we really sleeping? Why only one
|
# Wait for possible RESUME request to be handled which may change
|
||||||
# second? A link to some documentation might help.
|
# self.startPosition
|
||||||
|
# See Resume doc (URL in header)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
(realSock, addr) = sock.accept()
|
(realSock, addr) = sock.accept()
|
||||||
except socket.error, e:
|
except socket.error, e:
|
||||||
sock.close()
|
sock.close()
|
||||||
# Remember, we dont' use % in log strings -- we just put the
|
|
||||||
# arguments there after the string. utils.exnToString(e) gives a
|
|
||||||
# prettier string form than just e; the latter doesn't show what the
|
|
||||||
# class of the exception is.
|
|
||||||
# XXX % in log.
|
|
||||||
self.log.info('%r: Send init errored with %s',
|
self.log.info('%r: Send init errored with %s',
|
||||||
self.filename, utils.exnToString(e))
|
self.filename, utils.exnToString(e))
|
||||||
return
|
return
|
||||||
# XXX % in log.
|
self.log.info('%r: Sending to %s', self.filename, self.nick)
|
||||||
self.log.info('%r: Sending to %s' % (self.filename, self.nick))
|
|
||||||
# There shouldn't be blank space like this in a single function. But
|
|
||||||
# then again, a single function shouldn't be this long. Perhaps you
|
|
||||||
# can break this into multiple functions?
|
|
||||||
|
|
||||||
|
|
||||||
self.sock = realSock
|
self.sock = realSock
|
||||||
fh = file(self.filename)
|
fh = file(self.filename)
|
||||||
# Why no arguments to this clientConnected method?
|
|
||||||
self.clientConnected()
|
|
||||||
self.startTime = time.time()
|
|
||||||
try:
|
try:
|
||||||
slow = 0
|
self.clientConnected()
|
||||||
fh.seek(self.startPosition)
|
self.startTime = time.time()
|
||||||
self.currentPosition = fh.tell()
|
packetSize = conf.supybot.protocols.dcc.packetSize()
|
||||||
# Again, please no parentheses around the conditions of while loops
|
try:
|
||||||
# and if statements.
|
slow = 0
|
||||||
# XXX () in while/if
|
fh.seek(self.startPosition)
|
||||||
while (self.currentPosition < self.filesize):
|
|
||||||
data = fh.read(min(1024, self.filesize-self.currentPosition))
|
|
||||||
self.sock.send(data)
|
|
||||||
self.currentPosition = fh.tell()
|
self.currentPosition = fh.tell()
|
||||||
self.bytesSent += 1024
|
while self.currentPosition < self.filesize:
|
||||||
self.packetSent()
|
data = fh.read(min(packetSize, self.filesize - \
|
||||||
|
self.currentPosition))
|
||||||
except socket.error, e:
|
self.sock.send(data)
|
||||||
# Aborted/timedout chat
|
self.currentPosition = fh.tell()
|
||||||
# XXX % in log.
|
self.bytesSent += 1024
|
||||||
self.log.info('%r: Send errored with %s' %
|
self.packetSent()
|
||||||
(self.filename, e))
|
except socket.error, e:
|
||||||
except SendException, e:
|
exn = utils.exnToString(e)
|
||||||
# XXX % in log.
|
self.log.info('%r: Send errored with %s', self.filename, exn)
|
||||||
self.log.info('%r: Send aborted with %s' %
|
except SendException, e:
|
||||||
(self.filename, e))
|
exn = utils.exnToString(e)
|
||||||
# Wait for send to complete
|
self.log.info('%r: Send aborted with %s', self.filename, exn)
|
||||||
self.endTime = time.time()
|
|
||||||
duration = self.endTime - self.startTime
|
self.endTime = time.time()
|
||||||
# XXX. % in log. Also use %r here instead of %s.
|
duration = self.endTime - self.startTime
|
||||||
self.log.info('\'%s\': Sent %s/%s' %
|
self.log.info('%r: Sent %s/%s', self.filename, fh.tell(),
|
||||||
(self.filename, fh.tell(), self.filesize))
|
self.filesize)
|
||||||
# Why sleep here?
|
# Sleep to allow client to finish reading data.
|
||||||
time.sleep(1.0)
|
# This is needed as we'll be here immediately after the final
|
||||||
# XXX These closes should go in a finally: block.
|
# packet
|
||||||
fh.close()
|
time.sleep(1.0)
|
||||||
self.sock.close()
|
self.clientClosed()
|
||||||
self.clientClosed()
|
finally:
|
||||||
|
# Ensure that we're not leaking handles
|
||||||
|
fh.close()
|
||||||
|
self.sock.close()
|
||||||
|
|
||||||
|
|
||||||
class ChatHandler(DCCHandler):
|
class ChatHandler(DCCHandler):
|
||||||
""" Handle a DCC chat (initiate) """
|
""" Handle a DCC chat (initiate) """
|
||||||
def handleLine(self, line):
|
def lineReceived(self, line):
|
||||||
# What's this for? Documentation!
|
# Override in subclasses to process a line of text
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
ip = conf.supybot.externalIP()
|
ip = conf.supybot.externalIP()
|
||||||
# XXX () in while/if
|
|
||||||
if (not ip):
|
|
||||||
# Try and find it with utils
|
|
||||||
# No, I'll fix externalIP to return something sane for you.
|
|
||||||
pass
|
|
||||||
|
|
||||||
sock = utils.getSocket(ip)
|
sock = utils.getSocket(ip)
|
||||||
|
lineLength = conf.supybot.protocols.dcc.chatLineLength()
|
||||||
try:
|
try:
|
||||||
sock.bind((ip, 0))
|
sock.bind((ip, 0))
|
||||||
except socket.error, e:
|
except socket.error, e:
|
||||||
# XXX Who are you, and why can't you?
|
self.log.error('Could not bind chat socket.')
|
||||||
self.irc.error('Unable to initiate DCC CHAT.')
|
|
||||||
return
|
return
|
||||||
port = sock.getsockname()[1]
|
port = sock.getsockname()[1]
|
||||||
i = ircutils.dccIP(ip)
|
i = ircutils.dccIP(ip)
|
||||||
sock.listen(1)
|
sock.listen(1)
|
||||||
# XXX Use ircmsgs.dcc
|
msg = ircmsgs.dcc(self.nick, 'CHAT', 'chat', i, port)
|
||||||
self.irc.queueMsg(ircmsgs.privmsg(self.nick,
|
self.irc.queueMsg(msg)
|
||||||
'\x01DCC CHAT chat %s %s\x01' % (i, port)))
|
|
||||||
try:
|
try:
|
||||||
(realSock, addr) = sock.accept()
|
(realSock, addr) = sock.accept()
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
# XXX % in log
|
sock.close()
|
||||||
self.log.info('CHAT to %s timed out' % self.nick)
|
self.log.info('CHAT to %s timed out', self.nick)
|
||||||
return
|
return
|
||||||
# XXX % in log.
|
self.log.info('CHAT accepted from %s', self.nick)
|
||||||
self.log.info('CHAT accepted from %s' % self.nick)
|
|
||||||
realSock.settimeout(self.timeout)
|
realSock.settimeout(self.timeout)
|
||||||
self.startTime = time.time()
|
self.startTime = time.time()
|
||||||
self.sock = realSock
|
self.sock = realSock
|
||||||
try:
|
try:
|
||||||
self.clientConnected()
|
self.clientConnected()
|
||||||
# XXX () in while/if
|
while 1:
|
||||||
while (1):
|
line = realSock.recv(lineLength)
|
||||||
# XXX Why 66000?
|
if line != "\n":
|
||||||
line = realSock.recv(66000)
|
self.lineReceived(line)
|
||||||
# XXX Don't use <>; use !=.
|
|
||||||
if (line <> "\n"):
|
|
||||||
self.handleLine(line)
|
|
||||||
except socket.error, e:
|
except socket.error, e:
|
||||||
# Aborted/timedout chat. Only way to end.
|
self.log.info('CHAT ended with %s', self.nick)
|
||||||
# Are you sure you don't still need to close the socket here?
|
finally:
|
||||||
# XXX % in log. Also, don't use parens around a single value.
|
self.sock.close()
|
||||||
self.log.info('CHAT ended with %s' % (self.nick))
|
self.endTime = time.time()
|
||||||
self.endTime = time.time()
|
self.clientClosed()
|
||||||
self.clientClosed()
|
|
||||||
|
|
||||||
|
|
||||||
# ---- In Handlers ----
|
# ---- In Handlers ----
|
||||||
@ -247,8 +208,7 @@ class DCCReqHandler:
|
|||||||
self.irc = irc
|
self.irc = irc
|
||||||
self.msg = msg
|
self.msg = msg
|
||||||
self.args = args
|
self.args = args
|
||||||
# XXX: () in while/if
|
if logger:
|
||||||
if (logger):
|
|
||||||
self.log = logger
|
self.log = logger
|
||||||
else:
|
else:
|
||||||
self.log = log
|
self.log = log
|
||||||
@ -259,112 +219,89 @@ class DCCReqHandler:
|
|||||||
t.setDaemon(True)
|
t.setDaemon(True)
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
# Always put a blank line between methods, even if they just pass.
|
|
||||||
def clientConnected(self):
|
def clientConnected(self):
|
||||||
pass
|
pass
|
||||||
# XXX No blank line between methods.
|
|
||||||
def clientClosed(self):
|
def clientClosed(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class SendReqHandler(DCCReqHandler):
|
class SendReqHandler(DCCReqHandler):
|
||||||
""" We're being sent a file """
|
""" We're being sent a file """
|
||||||
# These should be setup in __init__ unless they have a real reason for
|
|
||||||
# being class variables.
|
|
||||||
ip = ""
|
|
||||||
filename = ""
|
|
||||||
port = 0
|
|
||||||
filesize = 0
|
|
||||||
|
|
||||||
def __init__(self, *args, **kw):
|
def __init__(self, *args, **kw):
|
||||||
DCCReqHandler.__init__(self, *args, **kw)
|
DCCReqHandler.__init__(self, *args, **kw)
|
||||||
# This should be added to by subclasses
|
# This should be added to by subclasses
|
||||||
self.incomingDir = conf.supybot.directories.data()
|
self.incomingDir = conf.supybot.directories.data()
|
||||||
|
|
||||||
def receivedPacket(self):
|
|
||||||
# What's this method for? Document.
|
|
||||||
pass
|
|
||||||
|
|
||||||
def open(self):
|
|
||||||
# XXX: Should this be factored into a separate function?
|
|
||||||
self.filename = self.args[0]
|
self.filename = self.args[0]
|
||||||
self.ip = ircutils.unDccIP(int(self.args[1]))
|
self.ip = ircutils.unDccIP(int(self.args[1]))
|
||||||
self.port = int(self.args[2])
|
self.port = int(self.args[2])
|
||||||
self.filesize = int(self.args[3])
|
self.filesize = int(self.args[3])
|
||||||
|
|
||||||
# XXX () in while/if
|
|
||||||
|
def receivedPacket(self):
|
||||||
|
# Override in subclass to do something with each packet received
|
||||||
|
pass
|
||||||
|
|
||||||
|
def open(self):
|
||||||
if (os.path.exists(self.filename)):
|
if (os.path.exists(self.filename)):
|
||||||
currsize = os.path.getsize(self.filename)
|
currsize = os.path.getsize(self.filename)
|
||||||
if (self.filesize > currsize):
|
if (self.filesize > currsize):
|
||||||
# Send RESUME DCC message and wait for ACCEPT
|
# Send RESUME DCC message and wait for ACCEPT
|
||||||
# XXX Line too long.
|
msg = ircutils.dcc(self.nick, 'RESUME', self.filename,
|
||||||
self.irc.queueMsg(ircmsgs.privmsg(self.msg.nick,
|
self.port, currsize)
|
||||||
'\x01DCC RESUME %s %d %d\x01' % (self.filename, self.port, currsize)))
|
self.irc.queueMsg(msg)
|
||||||
# URHG?
|
|
||||||
# What does "URGH?" mean? Details!
|
|
||||||
return
|
return
|
||||||
|
|
||||||
sock = utils.getSocket(self.ip)
|
sock = utils.getSocket(self.ip)
|
||||||
try:
|
try:
|
||||||
sock.connect((self.ip, self.port))
|
sock.connect((self.ip, self.port))
|
||||||
except:
|
except socket.error, e:
|
||||||
# XXX blank except, no log.
|
self.log.info('File receive could not connect')
|
||||||
return
|
return
|
||||||
|
|
||||||
self.clientConnected()
|
self.clientConnected()
|
||||||
|
rootedName = os.path.abspath(os.path.join(self.incomingDir,
|
||||||
# XXX long line; also, what does "rootedName" really mean?
|
self.filename))
|
||||||
rootedName = os.path.abspath(os.path.join(self.incomingDir, self.filename))
|
if not rootedName.startswith(self.incomingDir):
|
||||||
# XXX Use the startswith() method on strings.
|
self.log.warning('%s tried to send relative file', self.msg.nick)
|
||||||
if (rootedName[:len(self.incomingDir)] != self.incomingDir):
|
|
||||||
# XXX % in log.
|
|
||||||
self.log.warning('%s tried to send relative file' % self.msg.nick)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# XXX f is generally used for functions; use fh, or fd, or a name
|
fh = file(rootedName, 'w')
|
||||||
# representative what file is being used.
|
|
||||||
f = file(rootedName, 'w')
|
|
||||||
self.bytesReceived = 0
|
self.bytesReceived = 0
|
||||||
self.startTime = time.time()
|
self.startTime = time.time()
|
||||||
# XXX This is a src/ plugin. It shouldn't depend on any plugin. You
|
pktSize = conf.supybot.protocols.dcc.packetSize()
|
||||||
# definitely can't use any plugin's registry variables. This is the
|
self.log.info('%r: Send starting from %s', self.filename,
|
||||||
# number 1 biggest problem in this file.
|
self.msg.nick))
|
||||||
pktSize = conf.supybot.plugins.FServe.packetSize()
|
|
||||||
# XXX % in log, use %r
|
|
||||||
self.log.info('\'%s\': Send starting from %s' %
|
|
||||||
(self.filename, self.msg.nick))
|
|
||||||
try:
|
try:
|
||||||
# XXX () in while/if
|
while self.bytesReceived < self.filesize:
|
||||||
while (self.bytesReceived < self.filesize):
|
|
||||||
amnt = min(self.filesize - self.bytesReceived, pktSize)
|
amnt = min(self.filesize - self.bytesReceived, pktSize)
|
||||||
d = sock.recv(amnt)
|
d = sock.recv(amnt)
|
||||||
self.bytesReceived += len(d)
|
self.bytesReceived += len(d)
|
||||||
# XXX What's this do? Document please :)
|
# Required to send back packed integer to acknowledge receive
|
||||||
sock.send(struct.pack("!I", self.bytesReceived))
|
sock.send(struct.pack("!I", self.bytesReceived))
|
||||||
f.write(d)
|
f.write(d)
|
||||||
self.receivedPacket()
|
self.receivedPacket()
|
||||||
except socket.error, e:
|
except socket.error, e:
|
||||||
# % in log, use %r.
|
exn = utils.exnToString(e)
|
||||||
self.log.info('\'%s\': Send died with %s' % (filename, e))
|
self.log.info('%r: Send died with %s', filename, exn)
|
||||||
# XXX If you intend to fall through, i.e., not to return here, you
|
finally:
|
||||||
# should have a comment to that effect.
|
self.endTime = time.time()
|
||||||
self.endTime = time.time()
|
sock.close()
|
||||||
# XXX Perhaps these closes should go in a finally: block?
|
f.close()
|
||||||
sock.close()
|
self.log.info('%r: Received %s/%s in %d seconds',
|
||||||
f.close()
|
self.filename, self.bytesReceived, self.filesize,
|
||||||
# XXX % in log, use %r.
|
self.endTime - self.startTime)
|
||||||
self.log.info('\'%s\': Received %s/%s in %d seconds' %
|
self.clientClosed()
|
||||||
(self.filename, self.bytesReceived, self.filesize,
|
|
||||||
self.endTime - self.startTime))
|
|
||||||
self.clientClosed()
|
|
||||||
|
|
||||||
|
|
||||||
class ResumeReqHandler(DCCReqHandler):
|
class ResumeReqHandler(DCCReqHandler):
|
||||||
|
|
||||||
def _getSendHandler(self):
|
def _getSendHandler(self):
|
||||||
# XXX Explain this comment more.
|
# This will work in theory, BUT note well, if you instantiate
|
||||||
# This is bad. It will just start a new send.
|
# and do not override this to return the REAL SendHandler
|
||||||
# It needs to look up original
|
# the client may still get the original startPosition of 0
|
||||||
|
# See RESUME documentation URL in header
|
||||||
hostmask = self.irc.state.nickToHostmask(self.msg.nick)
|
hostmask = self.irc.state.nickToHostmask(self.msg.nick)
|
||||||
h = SendHandler(self.irc, self.msg.nick, hostmask, self.filename,
|
h = SendHandler(self.irc, self.msg.nick, hostmask, self.filename,
|
||||||
start=self.startPosition)
|
start=self.startPosition)
|
||||||
@ -372,22 +309,20 @@ class ResumeReqHandler(DCCReqHandler):
|
|||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
# filename is (apparently) ignored by mIRC
|
# filename is (apparently) ignored by mIRC
|
||||||
|
# so don't depend on it.
|
||||||
self.filename = self.args[0]
|
self.filename = self.args[0]
|
||||||
self.port = int(self.args[1])
|
self.port = int(self.args[1])
|
||||||
self.startPosition = int(self.args[2])
|
self.startPosition = int(self.args[2])
|
||||||
# XXX Use ircmsgs.dcc.
|
|
||||||
self.irc.queueMsg(ircmsgs.privmsg(self.msg.nick,
|
|
||||||
'\x01DCC ACCEPT %s %s %s\x01' % (self.filename, self.port,
|
|
||||||
self.startPosition)))
|
|
||||||
|
|
||||||
|
msg = ircutils.dcc(self.msg.nick, "ACCEPT", self.filename, self.port,
|
||||||
|
self.startPosition)
|
||||||
|
self.irc.queueMsg(msg)
|
||||||
cxn = self._getSendHandler()
|
cxn = self._getSendHandler()
|
||||||
cxn.startPosition = self.startPosition
|
cxn.startPosition = self.startPosition
|
||||||
# XXX % in log.
|
self.log.info('%r: RESUME received for %s', self.filename,
|
||||||
self.log.info('%r: RESUME received for %s' %
|
self.startPosition)
|
||||||
(self.filename, self.startPosition))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# --- IGNORE FROM HERE DOWN ---
|
||||||
|
|
||||||
def handleACCEPT(self):
|
def handleACCEPT(self):
|
||||||
port = int(self.args[1])
|
port = int(self.args[1])
|
||||||
|
Loading…
Reference in New Issue
Block a user