Start of work pulling code out of imaplib.py
This commit is contained in:
		
							
								
								
									
										198
									
								
								offlineimap/imaplibutil.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								offlineimap/imaplibutil.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,198 @@ | |||||||
|  | # imaplib | ||||||
|  | # Copyright (C) 2002-2007 John Goerzen | ||||||
|  | # <jgoerzen@complete.org> | ||||||
|  | # | ||||||
|  | #    This program is free software; you can redistribute it and/or modify | ||||||
|  | #    it under the terms of the GNU General Public License as published by | ||||||
|  | #    the Free Software Foundation; either version 2 of the License, or | ||||||
|  | #    (at your option) any later version. | ||||||
|  | # | ||||||
|  | #    This program is distributed in the hope that it will be useful, | ||||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | #    GNU General Public License for more details. | ||||||
|  | # | ||||||
|  | #    You should have received a copy of the GNU General Public License | ||||||
|  | #    along with this program; if not, write to the Free Software | ||||||
|  | #    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA | ||||||
|  |  | ||||||
|  | import re, string, types, binascii, socket, time, random, subprocess, sys, os | ||||||
|  | from offlineimap.ui import UIBase | ||||||
|  |  | ||||||
|  | class IMAP4_Tunnel(imaplib.IMAP4): | ||||||
|  |     """IMAP4 client class over a tunnel | ||||||
|  |  | ||||||
|  |     Instantiate with: IMAP4_Tunnel(tunnelcmd) | ||||||
|  |  | ||||||
|  |     tunnelcmd -- shell command to generate the tunnel. | ||||||
|  |     The result will be in PREAUTH stage.""" | ||||||
|  |  | ||||||
|  |     def __init__(self, tunnelcmd): | ||||||
|  |         imaplib.IMAP4.__init__(self, tunnelcmd) | ||||||
|  |  | ||||||
|  |     def open(self, host, port): | ||||||
|  |         """The tunnelcmd comes in on host!""" | ||||||
|  |         self.process = subprocess.Popen(host, shell=True, close_fds=True, | ||||||
|  |                         stdin=subprocess.PIPE, stdout=subprocess.PIPE) | ||||||
|  |         (self.outfd, self.infd) = (self.process.stdin, self.process.stdout) | ||||||
|  |  | ||||||
|  |     def read(self, size): | ||||||
|  |         retval = '' | ||||||
|  |         while len(retval) < size: | ||||||
|  |             retval += self.infd.read(size - len(retval)) | ||||||
|  |         return retval | ||||||
|  |  | ||||||
|  |     def readline(self): | ||||||
|  |         return self.infd.readline() | ||||||
|  |  | ||||||
|  |     def send(self, data): | ||||||
|  |         self.outfd.write(data) | ||||||
|  |  | ||||||
|  |     def shutdown(self): | ||||||
|  |         self.infd.close() | ||||||
|  |         self.outfd.close() | ||||||
|  |         self.process.wait() | ||||||
|  |          | ||||||
|  | # FIXME: need to use this in SSL instances | ||||||
|  | class sslwrapper: | ||||||
|  |     def __init__(self, sslsock): | ||||||
|  |         self.sslsock = sslsock | ||||||
|  |         self.readbuf = '' | ||||||
|  |  | ||||||
|  |     def write(self, s): | ||||||
|  |         return self.sslsock.write(s) | ||||||
|  |  | ||||||
|  |     def _read(self, n): | ||||||
|  |         return self.sslsock.read(n) | ||||||
|  |  | ||||||
|  |     def read(self, n): | ||||||
|  |         if len(self.readbuf): | ||||||
|  |             # Return the stuff in readbuf, even if less than n. | ||||||
|  |             # It might contain the rest of the line, and if we try to | ||||||
|  |             # read more, might block waiting for data that is not | ||||||
|  |             # coming to arrive. | ||||||
|  |             bytesfrombuf = min(n, len(self.readbuf)) | ||||||
|  |             retval = self.readbuf[:bytesfrombuf] | ||||||
|  |             self.readbuf = self.readbuf[bytesfrombuf:] | ||||||
|  |             return retval | ||||||
|  |         retval = self._read(n) | ||||||
|  |         if len(retval) > n: | ||||||
|  |             self.readbuf = retval[n:] | ||||||
|  |             return retval[:n] | ||||||
|  |         return retval | ||||||
|  |  | ||||||
|  |     def readline(self): | ||||||
|  |         retval = '' | ||||||
|  |         while 1: | ||||||
|  |             linebuf = self.read(1024) | ||||||
|  |             nlindex = linebuf.find("\n") | ||||||
|  |             if nlindex != -1: | ||||||
|  |                 retval += linebuf[:nlindex + 1] | ||||||
|  |                 self.readbuf = linebuf[nlindex + 1:] + self.readbuf | ||||||
|  |                 return retval | ||||||
|  |             else: | ||||||
|  |                 retval += linebuf | ||||||
|  |  | ||||||
|  | # FIXME: need to override this in IMAP instances | ||||||
|  |  | ||||||
|  | def new_mesg(self, s, secs=None): | ||||||
|  |             if secs is None: | ||||||
|  |                 secs = time.time() | ||||||
|  |             tm = time.strftime('%M:%S', time.localtime(secs)) | ||||||
|  |             UIBase.getglobalui().debug('imap', '  %s.%02d %s' % (tm, (secs*100)%100, s)) | ||||||
|  |  | ||||||
|  | # FIXME: use this | ||||||
|  | def new_open(self, host = '', port = imaplib.IMAP4_PORT): | ||||||
|  |         """Setup connection to remote server on "host:port" | ||||||
|  |             (default: localhost:standard IMAP4 port). | ||||||
|  |         This connection will be used by the routines: | ||||||
|  |             read, readline, send, shutdown. | ||||||
|  |         """ | ||||||
|  |         self.host = host | ||||||
|  |         self.port = port | ||||||
|  |         res = socket.getaddrinfo(host, port, socket.AF_UNSPEC, | ||||||
|  |                                  socket.SOCK_STREAM) | ||||||
|  |         self.sock = socket.socket(af, socktype, proto) | ||||||
|  |  | ||||||
|  |         # Try each address returned by getaddrinfo in turn until we | ||||||
|  |         # manage to connect to one. | ||||||
|  |         # Try all the addresses in turn until we connect() | ||||||
|  |         last_error = 0 | ||||||
|  |         for remote in res: | ||||||
|  |             af, socktype, proto, canonname, sa = remote | ||||||
|  |             self.sock = socket.socket(af, socktype, proto) | ||||||
|  |             last_error = self.sock.connect_ex(sa) | ||||||
|  |             if last_error == 0: | ||||||
|  |                 break | ||||||
|  |             else: | ||||||
|  |                 self.sock.close() | ||||||
|  |         if last_error != 0: | ||||||
|  |             # FIXME | ||||||
|  |             raise socket.error(last_error) | ||||||
|  |         self.file = self.sock.makefile('rb') | ||||||
|  |  | ||||||
|  | def new_open_ssl(self, host = '', port = IMAP4_SSL_PORT): | ||||||
|  |         """Setup connection to remote server on "host:port". | ||||||
|  |             (default: localhost:standard IMAP4 SSL port). | ||||||
|  |         This connection will be used by the routines: | ||||||
|  |             read, readline, send, shutdown. | ||||||
|  |         """ | ||||||
|  |         self.host = host | ||||||
|  |         self.port = port | ||||||
|  |         #This connects to the first ip found ipv4/ipv6 | ||||||
|  |         #Added by Adriaan Peeters <apeeters@lashout.net> based on a socket | ||||||
|  |         #example from the python documentation: | ||||||
|  |         #http://www.python.org/doc/lib/socket-example.html | ||||||
|  |         res = socket.getaddrinfo(host, port, socket.AF_UNSPEC, | ||||||
|  |                                  socket.SOCK_STREAM) | ||||||
|  |         # Try all the addresses in turn until we connect() | ||||||
|  |         last_error = 0 | ||||||
|  |         for remote in res: | ||||||
|  |             af, socktype, proto, canonname, sa = remote | ||||||
|  |             self.sock = socket.socket(af, socktype, proto) | ||||||
|  |             last_error = self.sock.connect_ex(sa) | ||||||
|  |             if last_error == 0: | ||||||
|  |                 break | ||||||
|  |             else: | ||||||
|  |                 self.sock.close() | ||||||
|  |         if last_error != 0: | ||||||
|  |             # FIXME | ||||||
|  |             raise socket.error(last_error) | ||||||
|  |         if sys.version_info[0] <= 2 and sys.version_info[1] <= 2: | ||||||
|  |             self.sslobj = socket.ssl(self.sock, self.keyfile, self.certfile) | ||||||
|  |         else: | ||||||
|  |             self.sslobj = socket.ssl(self.sock._sock, self.keyfile, self.certfile) | ||||||
|  |         self.sslobj = sslwrapper(self.sslobj) | ||||||
|  |  | ||||||
|  | mustquote = re.compile(r"[^\w!#$%&'+,.:;<=>?^`|~-]") | ||||||
|  |  | ||||||
|  | def Internaldate2epoch(resp): | ||||||
|  |     """Convert IMAP4 INTERNALDATE to UT. | ||||||
|  |  | ||||||
|  |     Returns seconds since the epoch. | ||||||
|  |     """ | ||||||
|  |  | ||||||
|  |     mo = InternalDate.match(resp) | ||||||
|  |     if not mo: | ||||||
|  |         return None | ||||||
|  |  | ||||||
|  |     mon = Mon2num[mo.group('mon')] | ||||||
|  |     zonen = mo.group('zonen') | ||||||
|  |  | ||||||
|  |     day = int(mo.group('day')) | ||||||
|  |     year = int(mo.group('year')) | ||||||
|  |     hour = int(mo.group('hour')) | ||||||
|  |     min = int(mo.group('min')) | ||||||
|  |     sec = int(mo.group('sec')) | ||||||
|  |     zoneh = int(mo.group('zoneh')) | ||||||
|  |     zonem = int(mo.group('zonem')) | ||||||
|  |  | ||||||
|  |     # INTERNALDATE timezone must be subtracted to get UT | ||||||
|  |  | ||||||
|  |     zone = (zoneh*60 + zonem)*60 | ||||||
|  |     if zonen == '-': | ||||||
|  |         zone = -zone | ||||||
|  |  | ||||||
|  |     tt = (year, mon, day, hour, min, sec, -1, -1, -1) | ||||||
|  |  | ||||||
|  |     return time.mktime(tt) | ||||||
		Reference in New Issue
	
	Block a user
	 John Goerzen
					John Goerzen