Merge branch 'next'
All current changes in next received some testing and no regressions were spotted. Make them to receive beating from people running "master".
This commit is contained in:
		
							
								
								
									
										14
									
								
								COPYING
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								COPYING
									
									
									
									
									
								
							| @@ -348,3 +348,17 @@ proprietary programs.  If your program is a subroutine library, you may | |||||||
| consider it more useful to permit linking proprietary applications with the | consider it more useful to permit linking proprietary applications with the | ||||||
| library.  If this is what you want to do, use the GNU Library General | library.  If this is what you want to do, use the GNU Library General | ||||||
| Public License instead of this License. | Public License instead of this License. | ||||||
|  |  | ||||||
|  | ---------------------------------------------------------------- | ||||||
|  | In addition, as a special exception, the copyright holders give | ||||||
|  | permission to link the code of portions of this program with the OpenSSL | ||||||
|  | library under certain conditions as described in each individual source | ||||||
|  | file, and distribute linked combinations including the two. | ||||||
|  |  | ||||||
|  | You must obey the GNU General Public License in all respects for all of | ||||||
|  | the code used other than OpenSSL. If you modify file(s) with this | ||||||
|  | exception, you may extend this exception to your version of the file(s), | ||||||
|  | but you are not obligated to do so. If you do not wish to do so, delete | ||||||
|  | this exception statement from your version. If you delete this exception | ||||||
|  | statement from all source files in the program, then also delete it | ||||||
|  | here. | ||||||
|   | |||||||
| @@ -8,6 +8,15 @@ ChangeLog | |||||||
| OfflineIMAP v6.5.6.1 (YYYY-MM-DD) | OfflineIMAP v6.5.6.1 (YYYY-MM-DD) | ||||||
| ================================= | ================================= | ||||||
|  |  | ||||||
|  | * Added OpenSSL exception clause to our main GPL to allow | ||||||
|  |   people to link with OpenSSL in run-time.  It is needed | ||||||
|  |   at least for Debian, see | ||||||
|  |     https://lists.debian.org/debian-legal/2002/10/msg00113.html | ||||||
|  |   for details. | ||||||
|  |  | ||||||
|  | * Fix warning-level message processing by MachineUI | ||||||
|  |   (GitHub pull #64, GitHub pull #118). | ||||||
|  |  | ||||||
| * Support default CA bundle locations for a couple of | * Support default CA bundle locations for a couple of | ||||||
|   known Unix systems (Michael Vogt, GutHub pull #19) |   known Unix systems (Michael Vogt, GutHub pull #19) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,9 +17,10 @@ documentation. | |||||||
| OfflineIMAP does not require additional python dependencies beyond python >=2.6 | OfflineIMAP does not require additional python dependencies beyond python >=2.6 | ||||||
| (although python-sqlite is strongly recommended). | (although python-sqlite is strongly recommended). | ||||||
|  |  | ||||||
| OfflineIMAP is a Free Software project licensed under the GNU General Public | OfflineIMAP is a Free Software project licensed under the GNU General | ||||||
| License version 2 (or later). You can download it for free, and you can modify | Public License version 2 (or later) with a special exception that allows | ||||||
| it. In fact, you are encouraged to contribute to OfflineIMAP. | the OpenSSL library to be used. You can download it for free, and you | ||||||
|  | can modify it. In fact, you are encouraged to contribute to OfflineIMAP. | ||||||
|  |  | ||||||
| Documentation | Documentation | ||||||
| ------------- | ------------- | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ __copyright__   = "Copyright 2002-2013 John Goerzen & contributors" | |||||||
| __author__      = "John Goerzen" | __author__      = "John Goerzen" | ||||||
| __author_email__= "john@complete.org" | __author_email__= "john@complete.org" | ||||||
| __description__ = "Disconnected Universal IMAP Mail Synchronization/Reader Support" | __description__ = "Disconnected Universal IMAP Mail Synchronization/Reader Support" | ||||||
| __license__  = "Licensed under the GNU GPL v2+ (v2 or any later version)" | __license__  = "Licensed under the GNU GPL v2 or any later version (with an OpenSSL exception)" | ||||||
| __bigcopyright__ = """%(__productname__)s %(__bigversion__)s | __bigcopyright__ = """%(__productname__)s %(__bigversion__)s | ||||||
|   %(__license__)s""" % locals() |   %(__license__)s""" % locals() | ||||||
| __homepage__ = "http://offlineimap.org" | __homepage__ = "http://offlineimap.org" | ||||||
|   | |||||||
| @@ -28,82 +28,107 @@ protocol = '7.0.0' | |||||||
|  |  | ||||||
| class MachineLogFormatter(logging.Formatter): | class MachineLogFormatter(logging.Formatter): | ||||||
|     """urlencodes any outputted line, to avoid multi-line output""" |     """urlencodes any outputted line, to avoid multi-line output""" | ||||||
|     def format(self, record): |     def format(s, record): | ||||||
|         # urlencode the "mesg" attribute and append to regular line... |         # Mapping of log levels to historic tag names | ||||||
|         line = super(MachineLogFormatter, self).format(record) |         severity_map = { | ||||||
|         return line + urlencode([('', record.mesg)])[1:] |          'info': 'msg', | ||||||
|  |          'warning': 'warn', | ||||||
|  |         } | ||||||
|  |         line = super(MachineLogFormatter, s).format(record) | ||||||
|  |         severity = record.levelname.lower() | ||||||
|  |         if severity in severity_map: | ||||||
|  |             severity = severity_map[severity] | ||||||
|  |         if hasattr(record, "machineui"): | ||||||
|  |             command = record.machineui["command"] | ||||||
|  |             whoami = record.machineui["id"] | ||||||
|  |         else: | ||||||
|  |             command = "" | ||||||
|  |             whoami = currentThread().getName() | ||||||
|  |  | ||||||
|  |         prefix = "%s:%s" % (command, urlencode([('', whoami)])[1:]) | ||||||
|  |         return "%s:%s:%s" % (severity, prefix, urlencode([('', line)])[1:]) | ||||||
|  |  | ||||||
|  |  | ||||||
| class MachineUI(UIBase): | class MachineUI(UIBase): | ||||||
|     def __init__(self, config, loglevel = logging.INFO): |     def __init__(s, config, loglevel = logging.INFO): | ||||||
|         super(MachineUI, self).__init__(config, loglevel) |         super(MachineUI, s).__init__(config, loglevel) | ||||||
|         self._log_con_handler.createLock() |         s._log_con_handler.createLock() | ||||||
|         """lock needed to block on password input""" |         """lock needed to block on password input""" | ||||||
|         # Set up the formatter that urlencodes the strings... |         # Set up the formatter that urlencodes the strings... | ||||||
|         self._log_con_handler.setFormatter(MachineLogFormatter()) |         s._log_con_handler.setFormatter(MachineLogFormatter()) | ||||||
|  |  | ||||||
|     def _printData(self, command, msg): |     # Arguments: | ||||||
|         self.logger.info("%s:%s:%s" % ( |     # - handler: must be method from s.logger that reflects | ||||||
|                 'msg', command, currentThread().getName()), extra={'mesg': msg}) |     #   the severity of the passed message | ||||||
|  |     # - command: command that produced this message | ||||||
|  |     # - msg: the message itself | ||||||
|  |     def _printData(s, handler, command, msg): | ||||||
|  |         handler(msg, | ||||||
|  |                 extra = { | ||||||
|  |                   'machineui': { | ||||||
|  |                    'command': command, | ||||||
|  |                    'id': currentThread().getName(), | ||||||
|  |                   } | ||||||
|  |                 }) | ||||||
|  |  | ||||||
|     def _msg(s, msg): |     def _msg(s, msg): | ||||||
|         s._printData('_display', msg) |         s._printData(s.logger.info, '_display', msg) | ||||||
|  |  | ||||||
|     def warn(self, msg, minor = 0): |     def warn(s, msg, minor = 0): | ||||||
|         # TODO, remove and cleanup the unused minor stuff |         # TODO, remove and cleanup the unused minor stuff | ||||||
|         self.logger.warning("%s:%s:%s:%s" % ( |         s._printData(s.logger.warning, '', msg) | ||||||
|                 'warn', '', currentThread().getName(), msg)) |  | ||||||
|  |  | ||||||
|     def registerthread(self, account): |     def registerthread(s, account): | ||||||
|         super(MachineUI, self).registerthread(account) |         super(MachineUI, s).registerthread(account) | ||||||
|         self._printData('registerthread', account) |         s._printData(s.logger.info, 'registerthread', account) | ||||||
|  |  | ||||||
|     def unregisterthread(s, thread): |     def unregisterthread(s, thread): | ||||||
|         UIBase.unregisterthread(s, thread) |         UIBase.unregisterthread(s, thread) | ||||||
|         s._printData('unregisterthread', thread.getName()) |         s._printData(s.logger.info, 'unregisterthread', thread.getName()) | ||||||
|  |  | ||||||
|     def debugging(s, debugtype): |     def debugging(s, debugtype): | ||||||
|         s._printData('debugging', debugtype) |         s._printData(s.logger.debug, 'debugging', debugtype) | ||||||
|  |  | ||||||
|     def acct(s, accountname): |     def acct(s, accountname): | ||||||
|         s._printData('acct', accountname) |         s._printData(s.logger.info, 'acct', accountname) | ||||||
|  |  | ||||||
|     def acctdone(s, accountname): |     def acctdone(s, accountname): | ||||||
|         s._printData('acctdone', accountname) |         s._printData(s.logger.info, 'acctdone', accountname) | ||||||
|  |  | ||||||
|     def validityproblem(s, folder): |     def validityproblem(s, folder): | ||||||
|         s._printData('validityproblem', "%s\n%s\n%s\n%s" % \ |         s._printData(s.logger.warning, 'validityproblem', "%s\n%s\n%s\n%s" % \ | ||||||
|                 (folder.getname(), folder.getrepository().getname(), |                 (folder.getname(), folder.getrepository().getname(), | ||||||
|                  folder.get_saveduidvalidity(), folder.get_uidvalidity())) |                  folder.get_saveduidvalidity(), folder.get_uidvalidity())) | ||||||
|  |  | ||||||
|     def connecting(s, hostname, port): |     def connecting(s, hostname, port): | ||||||
|         s._printData('connecting', "%s\n%s" % (hostname, str(port))) |         s._printData(s.logger.info, 'connecting', "%s\n%s" % (hostname, str(port))) | ||||||
|  |  | ||||||
|     def syncfolders(s, srcrepos, destrepos): |     def syncfolders(s, srcrepos, destrepos): | ||||||
|         s._printData('syncfolders', "%s\n%s" % (s.getnicename(srcrepos), |         s._printData(s.logger.info, 'syncfolders', "%s\n%s" % (s.getnicename(srcrepos), | ||||||
|                                                 s.getnicename(destrepos))) |                                                 s.getnicename(destrepos))) | ||||||
|  |  | ||||||
|     def syncingfolder(s, srcrepos, srcfolder, destrepos, destfolder): |     def syncingfolder(s, srcrepos, srcfolder, destrepos, destfolder): | ||||||
|         s._printData('syncingfolder', "%s\n%s\n%s\n%s\n" % \ |         s._printData(s.logger.info, 'syncingfolder', "%s\n%s\n%s\n%s\n" % \ | ||||||
|                 (s.getnicename(srcrepos), srcfolder.getname(), |                 (s.getnicename(srcrepos), srcfolder.getname(), | ||||||
|                  s.getnicename(destrepos), destfolder.getname())) |                  s.getnicename(destrepos), destfolder.getname())) | ||||||
|  |  | ||||||
|     def loadmessagelist(s, repos, folder): |     def loadmessagelist(s, repos, folder): | ||||||
|         s._printData('loadmessagelist', "%s\n%s" % (s.getnicename(repos), |         s._printData(s.logger.info, 'loadmessagelist', "%s\n%s" % (s.getnicename(repos), | ||||||
|                                                     folder.getvisiblename())) |                                                     folder.getvisiblename())) | ||||||
|  |  | ||||||
|     def messagelistloaded(s, repos, folder, count): |     def messagelistloaded(s, repos, folder, count): | ||||||
|         s._printData('messagelistloaded', "%s\n%s\n%d" % \ |         s._printData(s.logger.info, 'messagelistloaded', "%s\n%s\n%d" % \ | ||||||
|                 (s.getnicename(repos), folder.getname(), count)) |                 (s.getnicename(repos), folder.getname(), count)) | ||||||
|  |  | ||||||
|     def syncingmessages(s, sr, sf, dr, df): |     def syncingmessages(s, sr, sf, dr, df): | ||||||
|         s._printData('syncingmessages', "%s\n%s\n%s\n%s\n" % \ |         s._printData(s.logger.info, 'syncingmessages', "%s\n%s\n%s\n%s\n" % \ | ||||||
|                 (s.getnicename(sr), sf.getname(), s.getnicename(dr), |                 (s.getnicename(sr), sf.getname(), s.getnicename(dr), | ||||||
|                  df.getname())) |                  df.getname())) | ||||||
|  |  | ||||||
|     def copyingmessage(self, uid, num, num_to_copy, srcfolder, destfolder): |     def copyingmessage(s, uid, num, num_to_copy, srcfolder, destfolder): | ||||||
|         self._printData('copyingmessage', "%d\n%s\n%s\n%s[%s]" % \ |         s._printData(s.logger.info, 'copyingmessage', "%d\n%s\n%s\n%s[%s]" % \ | ||||||
|                 (uid, self.getnicename(srcfolder), srcfolder.getname(), |                 (uid, s.getnicename(srcfolder), srcfolder.getname(), | ||||||
|                  self.getnicename(destfolder), destfolder)) |                  s.getnicename(destfolder), destfolder)) | ||||||
|  |  | ||||||
|     def folderlist(s, list): |     def folderlist(s, list): | ||||||
|         return ("\f".join(["%s\t%s" % (s.getnicename(x), x.getname()) for x in list])) |         return ("\f".join(["%s\t%s" % (s.getnicename(x), x.getname()) for x in list])) | ||||||
| @@ -113,57 +138,58 @@ class MachineUI(UIBase): | |||||||
|  |  | ||||||
|     def deletingmessages(s, uidlist, destlist): |     def deletingmessages(s, uidlist, destlist): | ||||||
|         ds = s.folderlist(destlist) |         ds = s.folderlist(destlist) | ||||||
|         s._printData('deletingmessages', "%s\n%s" % (s.uidlist(uidlist), ds)) |         s._printData(s.logger.info, 'deletingmessages', "%s\n%s" % (s.uidlist(uidlist), ds)) | ||||||
|  |  | ||||||
|     def addingflags(s, uidlist, flags, dest): |     def addingflags(s, uidlist, flags, dest): | ||||||
|         s._printData("addingflags", "%s\n%s\n%s" % (s.uidlist(uidlist), |         s._printData(s.logger.info, "addingflags", "%s\n%s\n%s" % (s.uidlist(uidlist), | ||||||
|                                                     "\f".join(flags), |                                                     "\f".join(flags), | ||||||
|                                                     dest)) |                                                     dest)) | ||||||
|  |  | ||||||
|     def deletingflags(s, uidlist, flags, dest): |     def deletingflags(s, uidlist, flags, dest): | ||||||
|         s._printData('deletingflags', "%s\n%s\n%s" % (s.uidlist(uidlist), |         s._printData(s.logger.info, 'deletingflags', "%s\n%s\n%s" % (s.uidlist(uidlist), | ||||||
|                                                       "\f".join(flags), |                                                       "\f".join(flags), | ||||||
|                                                       dest)) |                                                       dest)) | ||||||
|  |  | ||||||
|     def threadException(self, thread): |     def threadException(s, thread): | ||||||
|         self._printData('threadException', "%s\n%s" % \ |         s._printData(s.logger.warning, 'threadException', "%s\n%s" % \ | ||||||
|                      (thread.getName(), self.getThreadExceptionString(thread))) |                      (thread.getName(), s.getThreadExceptionString(thread))) | ||||||
|         self.delThreadDebugLog(thread) |         s.delThreadDebugLog(thread) | ||||||
|         self.terminate(100) |         s.terminate(100) | ||||||
|  |  | ||||||
|     def terminate(s, exitstatus = 0, errortitle = '', errormsg = ''): |     def terminate(s, exitstatus = 0, errortitle = '', errormsg = ''): | ||||||
|         s._printData('terminate', "%d\n%s\n%s" % (exitstatus, errortitle, errormsg)) |         s._printData(s.logger.info, 'terminate', "%d\n%s\n%s" % (exitstatus, errortitle, errormsg)) | ||||||
|         sys.exit(exitstatus) |         sys.exit(exitstatus) | ||||||
|  |  | ||||||
|     def mainException(s): |     def mainException(s): | ||||||
|         s._printData('mainException', s.getMainExceptionString()) |         s._printData(s.logger.warning, 'mainException', s.getMainExceptionString()) | ||||||
|  |  | ||||||
|     def threadExited(s, thread): |     def threadExited(s, thread): | ||||||
|         s._printData('threadExited', thread.getName()) |         s._printData(s.logger.info, 'threadExited', thread.getName()) | ||||||
|         UIBase.threadExited(s, thread) |         UIBase.threadExited(s, thread) | ||||||
|  |  | ||||||
|     def sleeping(s, sleepsecs, remainingsecs): |     def sleeping(s, sleepsecs, remainingsecs): | ||||||
|         s._printData('sleeping', "%d\n%d" % (sleepsecs, remainingsecs)) |         s._printData(s.logger.info, 'sleeping', "%d\n%d" % (sleepsecs, remainingsecs)) | ||||||
|         if sleepsecs > 0: |         if sleepsecs > 0: | ||||||
|             time.sleep(sleepsecs) |             time.sleep(sleepsecs) | ||||||
|         return 0 |         return 0 | ||||||
|  |  | ||||||
|  |  | ||||||
|     def getpass(self, accountname, config, errmsg = None): |     def getpass(s, accountname, config, errmsg = None): | ||||||
|         if errmsg: |         if errmsg: | ||||||
|             self._printData('getpasserror', "%s\n%s" % (accountname, errmsg), |             s._printData(s.logger.warning, | ||||||
|  |               'getpasserror', "%s\n%s" % (accountname, errmsg), | ||||||
|               False) |               False) | ||||||
|  |  | ||||||
|         self._log_con_handler.acquire() # lock the console output |         s._log_con_handler.acquire() # lock the console output | ||||||
|         try: |         try: | ||||||
|             self._printData('getpass', accountname, False) |             s._printData(s.logger.info, 'getpass', accountname, False) | ||||||
|             return (sys.stdin.readline()[:-1]) |             return (sys.stdin.readline()[:-1]) | ||||||
|         finally: |         finally: | ||||||
|             self._log_con_handler.release() |             s._log_con_handler.release() | ||||||
|  |  | ||||||
|     def init_banner(self): |     def init_banner(s): | ||||||
|         self._printData('protocol', protocol) |         s._printData(s.logger.info, 'protocol', protocol) | ||||||
|         self._printData('initbanner', offlineimap.banner) |         s._printData(s.logger.info, 'initbanner', offlineimap.banner) | ||||||
|  |  | ||||||
|     def callhook(self, msg): |     def callhook(s, msg): | ||||||
|         self._printData('callhook', msg) |         s._printData(s.logger.info, 'callhook', msg) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Eygene Ryabinkin
					Eygene Ryabinkin