Fix IMAP4_Tunnel to work with imaplib2
* IMAP4_Tunnel constructor should support base-class arguments, in order to support the timeout argument. * IMAP4_Tunnel needs to store the member IMAP4.host, which is normally done in IMAP4.open(). * Update IMAP4_Tunnel.read() and IMAP4_Tunnel.send(). We turn on nonblocking mode for these sockets, so we can return immediately with whatever data is available. Signed-off-by: Ethan Glasser-Camp <ethan@betacantrips.com> Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
parent
fdf22400b1
commit
9e734006f6
@ -22,6 +22,8 @@ Changes
|
|||||||
Bug Fixes
|
Bug Fixes
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
* Fix IMAP4 tunnel with imaplib2.
|
||||||
|
|
||||||
|
|
||||||
Pending for the next major release
|
Pending for the next major release
|
||||||
==================================
|
==================================
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
import os
|
||||||
|
import fcntl
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
@ -67,32 +69,50 @@ class IMAP4_Tunnel(UsefulIMAPMixIn, IMAP4):
|
|||||||
tunnelcmd -- shell command to generate the tunnel.
|
tunnelcmd -- shell command to generate the tunnel.
|
||||||
The result will be in PREAUTH stage."""
|
The result will be in PREAUTH stage."""
|
||||||
|
|
||||||
def __init__(self, tunnelcmd):
|
def __init__(self, tunnelcmd, **kwargs):
|
||||||
IMAP4.__init__(self, tunnelcmd)
|
IMAP4.__init__(self, tunnelcmd, **kwargs)
|
||||||
|
|
||||||
def open(self, host, port):
|
def open(self, host, port):
|
||||||
"""The tunnelcmd comes in on host!"""
|
"""The tunnelcmd comes in on host!"""
|
||||||
|
self.host = host
|
||||||
self.process = subprocess.Popen(host, shell=True, close_fds=True,
|
self.process = subprocess.Popen(host, shell=True, close_fds=True,
|
||||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
(self.outfd, self.infd) = (self.process.stdin, self.process.stdout)
|
(self.outfd, self.infd) = (self.process.stdin, self.process.stdout)
|
||||||
# imaplib2 polls on this fd
|
# imaplib2 polls on this fd
|
||||||
self.read_fd = self.infd.fileno()
|
self.read_fd = self.infd.fileno()
|
||||||
|
|
||||||
def read(self, size):
|
self.set_nonblocking(self.read_fd)
|
||||||
retval = ''
|
|
||||||
while len(retval) < size:
|
|
||||||
buf = self.infd.read(size - len(retval))
|
|
||||||
if not buf:
|
|
||||||
break
|
|
||||||
retval += buf
|
|
||||||
return retval
|
|
||||||
|
|
||||||
def readline(self):
|
def set_nonblocking(self, fd):
|
||||||
return self.infd.readline()
|
"Mark fd as nonblocking"
|
||||||
|
# get the file's current flag settings
|
||||||
|
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
|
||||||
|
# clear non-blocking mode from flags
|
||||||
|
fl = fl & ~os.O_NONBLOCK
|
||||||
|
fcntl.fcntl(fd, fcntl.F_SETFL, fl)
|
||||||
|
|
||||||
|
def read(self, size):
|
||||||
|
"""data = read(size)
|
||||||
|
Read at most 'size' bytes from remote."""
|
||||||
|
|
||||||
|
if self.decompressor is None:
|
||||||
|
return os.read(self.read_fd, size)
|
||||||
|
|
||||||
|
if self.decompressor.unconsumed_tail:
|
||||||
|
data = self.decompressor.unconsumed_tail
|
||||||
|
else:
|
||||||
|
data = os.read(self.read_fd, 8192)
|
||||||
|
|
||||||
|
return self.decompressor.decompress(data, size)
|
||||||
|
|
||||||
def send(self, data):
|
def send(self, data):
|
||||||
|
if self.compressor is not None:
|
||||||
|
data = self.compressor.compress(data)
|
||||||
|
data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
|
||||||
|
|
||||||
self.outfd.write(data)
|
self.outfd.write(data)
|
||||||
|
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
self.infd.close()
|
self.infd.close()
|
||||||
self.outfd.close()
|
self.outfd.close()
|
||||||
|
Loading…
Reference in New Issue
Block a user