diff --git a/offlineimap/imaplib2.py b/offlineimap/imaplib2.py index 2f7919b..2426754 100644 --- a/offlineimap/imaplib2.py +++ b/offlineimap/imaplib2.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2.5 """Threaded IMAP4 client. @@ -17,9 +17,9 @@ Public functions: Internaldate2Time __all__ = ("IMAP4", "IMAP4_SSL", "IMAP4_stream", "Internaldate2Time", "ParseFlags", "Time2Internaldate") -__version__ = "2.11" +__version__ = "2.6" __release__ = "2" -__revision__ = "11" +__revision__ = "6" __credits__ = """ Authentication code contributed by Donn Cave June 1998. String method conversion by ESR, February 2001. @@ -29,11 +29,11 @@ GET/SETQUOTA contributed by Andreas Zeidler June 2002. PROXYAUTH contributed by Rick Holbert November 2002. IDLE via threads suggested by Philippe Normand January 2005. GET/SETANNOTATION contributed by Tomas Lindroos June 2005. -COMPRESS/DEFLATE contributed by Bron Gondwana May 2009.""" +New socket open code from http://www.python.org/doc/lib/socket-example.html.""" __author__ = "Piers Lauder " -__URL__ = "http://janeelix.com/piers/python/imaplib2" +# Source URL: http://www.cs.usyd.edu.au/~piers/python/imaplib2 -import binascii, os, Queue, random, re, select, socket, sys, time, threading, zlib +import binascii, os, Queue, random, re, select, socket, sys, time, threading select_module = select @@ -62,7 +62,6 @@ Commands = { 'CAPABILITY': ((NONAUTH, AUTH, SELECTED), True), 'CHECK': ((SELECTED,), True), 'CLOSE': ((SELECTED,), False), - 'COMPRESS': ((AUTH,), False), 'COPY': ((SELECTED,), True), 'CREATE': ((AUTH, SELECTED), True), 'DELETE': ((AUTH, SELECTED), True), @@ -265,9 +264,6 @@ class IMAP4(object): self._accumulated_data = [] # Message data accumulated so far self._literal_expected = None # Message data descriptor - self.compressor = None # COMPRESS/DEFLATE if not None - self.decompressor = None - # Create unique tag for this session, # and compile tagged response matcher. @@ -362,8 +358,7 @@ class IMAP4(object): def open_socket(self): - """open_socket() - Open socket choosing first address family available.""" + """Open socket choosing first address family available.""" msg = (-1, 'could not open socket') for res in socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM): @@ -384,38 +379,17 @@ class IMAP4(object): return s - def start_compressing(self): - """start_compressing() - Enable deflate compression on the socket (RFC 4978).""" - - # rfc 1951 - pure DEFLATE, so use -15 for both windows - self.decompressor = zlib.decompressobj(-15) - self.compressor = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -15) - - def read(self, size): """data = read(size) Read at most 'size' bytes from remote.""" - if self.decompressor is None: - return self.sock.recv(size) - - if self.decompressor.unconsumed_tail: - data = self.decompressor.unconsumed_tail - else: - data = self.sock.recv(8192) - - return self.decompressor.decompress(data, size) + return self.sock.recv(size) def send(self, data): """send(data) Send 'data' to remote.""" - if self.compressor is not None: - data = self.compressor.compress(data) - data += self.compressor.flush(zlib.Z_SYNC_FLUSH) - self.sock.sendall(data) @@ -437,22 +411,6 @@ class IMAP4(object): # Utility methods - def enable_compression(self): - """enable_compression() - Ask the server to start compressing the connection. - Should be called from user of this class after instantiation, as in: - if 'COMPRESS=DEFLATE' in imapobj.capabilities: - imapobj.enable_compression()""" - - try: - typ, dat = self._simple_command('COMPRESS', 'DEFLATE') - if typ == 'OK': - self.start_compressing() - if __debug__: self._log(1, 'Enabled COMPRESS=DEFLATE') - finally: - self.state_change_pending.release() - - def recent(self, **kw): """(typ, [data]) = recent() Return most recent 'RECENT' responses if any exist, @@ -475,7 +433,7 @@ class IMAP4(object): typ, dat = self._untagged_response(code, [None], code.upper()) return self._deliver_dat(typ, dat, kw) - + @@ -689,9 +647,9 @@ class IMAP4(object): List mailbox names in directory matching pattern. 'data' is list of LIST responses. - NB: for 'pattern': - % matches all except separator ( so LIST "" "%" returns names at root) - * matches all (so LIST "" "*" returns whole directory tree from root)""" + NB: for 'pattern': + % matches all except separator ( so LIST "" "%" returns names at root) + * matches all (so LIST "" "*" returns whole directory tree from root)""" name = 'LIST' kw['untagged_response'] = name @@ -855,7 +813,7 @@ class IMAP4(object): self.state = AUTH if __debug__: self._log(1, 'state => AUTH') if typ == 'BAD': - self._deliver_exc(self.error, '%s command error: %s %s. Data: %.100s' % (name, typ, dat, mailbox), kw) + self._deliver_exc(self.error, '%s command error: %s %s' % (name, typ, dat), kw) return self._deliver_dat(typ, dat, kw) self.state = SELECTED if __debug__: self._log(1, 'state => SELECTED') @@ -1085,25 +1043,20 @@ class IMAP4(object): literal = self.literal if literal is not None: self.literal = None - if isinstance(literal, basestring): + if isinstance(literal, str): literator = None data = '%s {%s}' % (data, len(literal)) else: literator = literal - if __debug__: self._log(4, 'data=%s' % data) - rqb.data = '%s%s' % (data, CRLF) + self.ouq.put(rqb) if literal is None: - self.ouq.put(rqb) return rqb - # Must setup continuation expectancy *before* ouq.put crqb = self._request_push(tag='continuation') - self.ouq.put(rqb) - while True: # Wait for continuation response @@ -1123,10 +1076,6 @@ class IMAP4(object): if literal is None: break - if literator is not None: - # Need new request for next continuation response - crqb = self._request_push(tag='continuation') - if __debug__: self._log(4, 'write literal size %s' % len(literal)) crqb.data = '%s%s' % (literal, CRLF) self.ouq.put(crqb) @@ -1134,6 +1083,10 @@ class IMAP4(object): if literator is None: break + self.commands_lock.acquire() + self.tagged_commands['continuation'] = crqb + self.commands_lock.release() + return rqb @@ -1145,7 +1098,7 @@ class IMAP4(object): self._check_bye() if typ == 'BAD': if __debug__: self._print_log() - raise self.error('%s command error: %s %s. Data: %.100s' % (rqb.name, typ, dat, rqb.data)) + raise self.error('%s command error: %s %s' % (rqb.name, typ, dat)) if 'untagged_response' in kw: return self._untagged_response(typ, dat, kw['untagged_response']) return typ, dat @@ -1169,11 +1122,12 @@ class IMAP4(object): typ, dat = response if typ == 'BAD': if __debug__: self._print_log() - rqb.abort(self.error, '%s command error: %s %s. Data: %.100s' % (rqb.name, typ, dat, rqb.data)) + rqb.abort(self.error, '%s command error: %s %s' % (rqb.name, typ, dat)) return if 'untagged_response' in kw: - response = self._untagged_response(typ, dat, kw['untagged_response']) - rqb.deliver(response) + rqb.deliver(self._untagged_response(typ, dat, kw['untagged_response'])) + else: + rqb.deliver(response) def _deliver_dat(self, typ, dat, kw): @@ -1193,13 +1147,12 @@ class IMAP4(object): def _end_idle(self): irqb = self.idle_rqb - if irqb is None: - return - self.idle_rqb = None - self.idle_timeout = None - irqb.data = 'DONE%s' % CRLF - self.ouq.put(irqb) - if __debug__: self._log(2, 'server IDLE finished') + if irqb is not None: + self.idle_rqb = None + self.idle_timeout = None + irqb.data = 'DONE%s' % CRLF + self.ouq.put(irqb) + if __debug__: self._log(2, 'server IDLE finished') def _match(self, cre, s): @@ -1384,7 +1337,7 @@ class IMAP4(object): threading.currentThread().setName('hdlr') - time.sleep(0.1) # Don't start handling before main thread ready + time.sleep(0.1) # Don't start handling before main thread ready if __debug__: self._log(1, 'starting') @@ -1413,7 +1366,7 @@ class IMAP4(object): if line is None: break - if not isinstance(line, basestring): + if not isinstance(line, str): typ, val = line break @@ -1711,12 +1664,7 @@ class IMAP4_SSL(IMAP4): self.host = host is not None and host or '' self.port = port is not None and port or IMAP4_SSL_PORT self.sock = self.open_socket() - - try: - import ssl - self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, self.certfile) - except ImportError: - self.sslobj = socket.ssl(self.sock, self.keyfile, self.certfile) + self.sslobj = socket.ssl(self.sock, self.keyfile, self.certfile) self.read_fd = self.sock.fileno() @@ -1725,25 +1673,13 @@ class IMAP4_SSL(IMAP4): """data = read(size) Read at most 'size' bytes from remote.""" - if self.decompressor is None: - return self.sslobj.read(size) - - if self.decompressor.unconsumed_tail: - data = self.decompressor.unconsumed_tail - else: - data = self.sslobj.read(8192) - - return self.decompressor.decompress(data, size) + return self.sslobj.read(size) def send(self, data): """send(data) Send 'data' to remote.""" - if self.compressor is not None: - data = self.compressor.compress(data) - data += self.compressor.flush(zlib.Z_SYNC_FLUSH) - # NB: socket.ssl needs a "sendall" method to match socket objects. bytes = len(data) while bytes > 0: @@ -1800,24 +1736,12 @@ class IMAP4_stream(IMAP4): def read(self, size): """Read '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) + return os.read(self.read_fd, size) def send(self, data): """Send data to remote.""" - if self.compressor is not None: - data = self.compressor.compress(data) - data += self.compressor.flush(zlib.Z_SYNC_FLUSH) - self.writefile.write(data) self.writefile.flush() @@ -1996,7 +1920,7 @@ if __name__ == '__main__': import getopt, getpass try: - optlist, args = getopt.getopt(sys.argv[1:], 'd:l:s:p:v') + optlist, args = getopt.getopt(sys.argv[1:], 'd:l:s:p:') except getopt.error, val: optlist, args = (), () @@ -2014,9 +1938,6 @@ if __name__ == '__main__': elif opt == '-s': stream_command = val if not args: args = (stream_command,) - elif opt == '-v': - print __version__ - sys.exit(0) if not args: args = ('',) if not port: port = (keyfile is not None) and IMAP4_SSL_PORT or IMAP4_PORT @@ -2026,7 +1947,7 @@ if __name__ == '__main__': USER = getpass.getuser() test_mesg = 'From: %(user)s@localhost%(lf)sSubject: IMAP4 test%(lf)s%(lf)s%(data)s' \ - % {'user':USER, 'lf':'\n', 'data':open(__file__).read()} + % {'user':USER, 'lf':'\n', 'data':open(__file__).read()} test_seq1 = [ ('list', ('""', '%')), ('create', ('/tmp/imaplib2_test.0',)), @@ -2107,8 +2028,6 @@ if __name__ == '__main__': test_seq1.insert(0, ('login', (USER, PASSWD))) M._mesg('PROTOCOL_VERSION = %s' % M.PROTOCOL_VERSION) M._mesg('CAPABILITIES = %r' % (M.capabilities,)) - if 'COMPRESS=DEFLATE' in M.capabilities: - M.enable_compression() for cmd,args in test_seq1: run(cmd, args, cb=1)