/offlineimap/head: changeset 297
Changed to a more account-centric behavior. The refresh time is now a per-account variable. Implemented new account classes. User interfaces must now be updated to take advantage of this.
This commit is contained in:
parent
1691cdbf0f
commit
854eaf3055
443
offlineimap/head/debian/changelog
Normal file
443
offlineimap/head/debian/changelog
Normal file
@ -0,0 +1,443 @@
|
||||
offlineimap (3.99.6) unstable; urgency=low
|
||||
|
||||
* Beginnings of work to make it work with a threaded Tcl/Tk Tkinter.
|
||||
* Now properly handles folder names that contain parenthesis. Used
|
||||
patch from Kyler Laird in
|
||||
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=173895.
|
||||
Closes: #173895.
|
||||
* Changed to a more account-centric behavior. The refresh time is now
|
||||
a per-account variable. Implemented new account classes. User
|
||||
interfaces must now be updated to take advantage of this.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Thu, 2 Jan 2003 13:59:44 -0600
|
||||
|
||||
offlineimap (3.99.5) unstable; urgency=low
|
||||
|
||||
* Added ability to disable expunging on the server.
|
||||
* Fixed infinite loop with preauth. Closes: #169514, #171485.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Tue, 03 Dec 2002 06:22:37 -0600
|
||||
|
||||
offlineimap (3.99.4) unstable; urgency=low
|
||||
|
||||
* Fixed setup.py installation instructions.
|
||||
* Added more debugging to the CRAM-MD5 authentication module.
|
||||
* CRAM-MD5 *really* fixed this time. Thanks to MJ for the patch.
|
||||
* Adding missing import os to imapserver.py. Thanks to John Wiegley
|
||||
for catching that.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Tue, 5 Nov 2002 08:06:45 -0600
|
||||
|
||||
offlineimap (3.99.3) unstable; urgency=low
|
||||
|
||||
* Moved password promting into imapserver.py. Passwords are now asked
|
||||
for on-demand and typos will no longer crash the program (the user
|
||||
will be re-prompted). Closes: #162672.
|
||||
* Falls back to plain-text auth if CRAM-MD5 fails. Fixes [complete.org #42]
|
||||
* Fixed CRAM-MD5 auth so it actually works now.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Mon, 4 Nov 2002 06:16:11 -0600
|
||||
|
||||
offlineimap (3.99.2) unstable; urgency=low
|
||||
|
||||
* Further attempts to fix imapsplit problems.
|
||||
* When an exception occurs, OfflineIMAP will attempt to print the last
|
||||
50 debug messages, whether or not debugging was enabled for this
|
||||
session. This way, even unexpected and non-repeatable errors stand
|
||||
a chance of getting a more detailed log.
|
||||
* Handle uidvalidity file in an atomic fashion. CLoses: #165600.
|
||||
* Supports CRAM-MD5 authentication. Fixes [complete.org #38], and for
|
||||
Debian, Closes: #154165.
|
||||
* Noted CRAM-MD5 support in the "CONFORMING TO" section of the manual.
|
||||
* Certain servers may not always return the UID flag for new messages.
|
||||
This causes an OfflineIMAP exception, though rerunning will fix it.
|
||||
Now, OfflineIMAP will detect the condition and ignore the offending
|
||||
messages (without an exception) until the next sync.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Sat, 02 Nov 2002 10:23:10 -0600
|
||||
|
||||
offlineimap (3.99.1) unstable; urgency=low
|
||||
|
||||
* Fixed some syntax errors in imaputil.py
|
||||
* Fixed a syntax error with mbnames
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Wed, 9 Oct 2002 19:34:37 -0500
|
||||
|
||||
offlineimap (3.99.0) unstable; urgency=low
|
||||
|
||||
* The next few releases are adding features and reorganizing
|
||||
code in preparation for 4.0.0.
|
||||
* imaputil.py now logs information with IMAP debugging is enabled.
|
||||
* Added folderfilter capability to mbnames recorder. You can now omit
|
||||
specified folders from the mbnames output.
|
||||
* Added a workaround to imaputil.py to deal with a bug in imaplib.py's
|
||||
tuple when a response contains a literal in certain cases.
|
||||
* Split out the code in bin/offlineimap into offlineimap/init.py.
|
||||
Retaining bin/offlineimap as a skeletal piece only. Contains
|
||||
about three lines of code now. This will make many things
|
||||
easier, including debugging.
|
||||
* Added library version check to bin/offlineimap and
|
||||
offlineimap/init.py.
|
||||
* Moved __main__.ui to functions in UIBase: getglobalui() and
|
||||
setglobalui().
|
||||
* Added license comments to some source files that were missing them.
|
||||
* Moved some code from offlineimap/init.py to new file
|
||||
offlineimap/syncmaster.py to help dileneate between code that
|
||||
performs different functions.
|
||||
* Moved threadexited from offlineimap/init.py to
|
||||
offlineimap/threadutil.py.
|
||||
* offlineimap.py is back to ease the use of OfflineIMAP in single-user
|
||||
installations.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Mon, 07 Oct 2002 05:08:08 -0500
|
||||
|
||||
offlineimap (3.2.8) unstable; urgency=low
|
||||
|
||||
* Added a work-around for some IMAP servers that respond poorly
|
||||
to LIST "" "". It will now do LIST "" "*", for them only.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Mon, 30 Sep 2002 10:48:01 -0500
|
||||
|
||||
offlineimap (3.2.7) unstable; urgency=low
|
||||
|
||||
* Moved executable to bin/offlineimap. This will allow setup.py to
|
||||
properly install it as offlineimap instead of offlineimap.py.
|
||||
* Made sure executables use /usr/bin/env in bangpath.
|
||||
* Font size for Blinkenlights interface is now configurable.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Thu, 19 Sep 2002 06:46:56 -0500
|
||||
|
||||
offlineimap (3.2.6) unstable; urgency=low
|
||||
|
||||
* Changed indentation in debian/control. Closes: #156327.
|
||||
* Removed calls to folder object deletions. None have been implemented
|
||||
anyway.
|
||||
* folder/Maildir.py: unlink throws OSError, not IOError; fixed.
|
||||
Now handles message deleting race condition properly.
|
||||
Closes: #154497.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Fri, 16 Aug 2002 17:43:19 -0500
|
||||
|
||||
offlineimap (3.2.5) unstable; urgency=low
|
||||
|
||||
* Now handles uploading messages without Message-Id headers.
|
||||
Closes: #156022.
|
||||
* Applied patch from Tommi Virtanen that adds two new config file
|
||||
options: pythonfile and foldersort. Fixes [complete.org #29], and
|
||||
for Debian, Closes: #155637.
|
||||
* Added documentation for the above features.
|
||||
* Even more resiliant in the face of invalid Date headers. Closes: #155994.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Fri, 9 Aug 2002 17:54:01 -0500
|
||||
|
||||
offlineimap (3.2.4) unstable; urgency=low
|
||||
|
||||
* When using nested folders, the Maildir repository handler now properly
|
||||
deals with folders that are nested inside "noselect" folders -- ones
|
||||
that do not actually contain messages and are not provided in the
|
||||
server's LIST response. Fixes [complete.org #32] and, for Debian,
|
||||
Closes: #155866.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Thu, 8 Aug 2002 17:54:44 -0500
|
||||
|
||||
offlineimap (3.2.3) unstable; urgency=low
|
||||
|
||||
* -d now takes a parameter: imap or maildir (or both) to specify
|
||||
what type of debugging to do.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Thu, 8 Aug 2002 10:02:36 -0500
|
||||
|
||||
offlineimap (3.2.2) unstable; urgency=low
|
||||
|
||||
* Updated manual to show new Gray color.
|
||||
* Scrolling behavior is better now; sometimes, with fast-scrolling text,
|
||||
the log would stop scrolling.
|
||||
* Better handling of read-only folders. We will now warn if there is
|
||||
a change, but not propogate it. New config variable ignore-readonly
|
||||
can suppress the warnings. This fixes [complete.org #10] and,
|
||||
for Debian, Closes: #154769.
|
||||
* If a given Maildir folder is new, remove the associated local status
|
||||
cache file, if any. That way, there will not be any chance of
|
||||
propogating hordes of deletes and adds based on old status data.
|
||||
* Added support for /-separated Maildirs -- that is, hierarchical
|
||||
Maildir trees. Fixes [complete.org #28] and, for Debian,
|
||||
Closes: #155460.
|
||||
* Preventitive security: Folder names may not contain ./ or start with /.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Wed, 07 Aug 2002 20:22:25 -0500
|
||||
|
||||
offlineimap (3.2.1) unstable; urgency=low
|
||||
|
||||
* There is a new "connecting" event that will appear in all but the
|
||||
Quiet UIs. It has a gray color in Blinkenlights. This event indicates
|
||||
the the program is connecting to a remote server.
|
||||
* Blinkenlights UI log window is now scrolled and has a new
|
||||
config file option "bufferlines" to specify the size of the scroll
|
||||
buffer.
|
||||
* The Blinkenlights window is now non-resizable when the log is disabled.
|
||||
When the log is enabled, the window is resizable, and the changes in
|
||||
size are reflected in the log widget. Therefore, the Bigger Log
|
||||
and Smaller Log items can disappear, and the Log menu now becomes
|
||||
a Show Log or a Hide Log menu option. No sub-menus necessary anymore.
|
||||
This presents a much cleaner feel, more intuitive operation, and
|
||||
faster navigation.
|
||||
* Fix for account name interpolation in dot warning from 3.2.0 from
|
||||
Martijn Pieters.
|
||||
* Backed out check for . in account names for now. Will put it back in
|
||||
when we have a consensus on what exactly to do. Doubt that anyone
|
||||
has a foldername that would conflict with Blinkenlights anyway.
|
||||
* Fix reading the ui.Tk.Blinkenlights bufferlines option.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Wed, 24 Jul 2002 17:04:04 -0500
|
||||
|
||||
offlineimap (3.2.0) unstable; urgency=low
|
||||
|
||||
* New BLINKENLIGHTS interface! Mesmerising, isn't it?
|
||||
* New ui.Tk.Blinkenlights section in offlineimap.conf.
|
||||
* New USER INTERFACES section in the manual.
|
||||
* TTYUI isusable() now checks to see if stdout and stdin are TTYs.
|
||||
* Added build-dependency on python2.2-dev. Closes: #154167.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Wed, 24 Jul 2002 17:53:20 -0500
|
||||
|
||||
offlineimap (3.1.1) unstable; urgency=low
|
||||
|
||||
* Modified imaputil.py and folder/Maildir.py to run faster. Eliminated
|
||||
many regular expressions; pre-compiled many others.
|
||||
* Fixed threadutil's exitnotifyloop to always handle threads in the order
|
||||
they exited, rather than sometimes in the inverse order. This way,
|
||||
make sure to handle thread's exception messages before a thread exited.
|
||||
* Replaced imaplib.py's braindead readline() with a more efficient one.
|
||||
* More optimizations to imaputil and folders for faster operation.
|
||||
* These optimizations, all together, have resulted in OfflineIMAP
|
||||
using approximately half the CPU time of previous versions, fixing
|
||||
[complete.org #6], and... Closes: #153503.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Wed, 24 Jul 2002 06:53:16 -0500
|
||||
|
||||
offlineimap (3.1.0) unstable; urgency=low
|
||||
|
||||
* When uploading messages from a Maildir, now convert \r\n to \n in case
|
||||
the message is stored weirdly. That way, everything is uniform.
|
||||
Fixes [complete.org #11].
|
||||
* Manual: added UW IMAPD example with references from docwhat@gerf.org.
|
||||
* New UI modules: Noninteractive.Basic and Noninteractive.Quiet.
|
||||
Fixes [complete.org #14].
|
||||
* Added per-thread profiling support to aid in debugging.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Sun, 21 Jul 2002 16:09:42 -0500
|
||||
|
||||
offlineimap (3.0.3) unstable; urgency=low
|
||||
|
||||
* No longer throws an exception when updating messages with strange
|
||||
Date headers; will just set IMAP Internaldate to the current date.
|
||||
Closes: #153425.
|
||||
* No longer doubles-up reference names for mailboxes. Closes: #153515.
|
||||
* Noted new bug-tracking system in manual and rebuilt manual files.
|
||||
* Now stores incoming messages in 'cur' instead of 'new' if they have
|
||||
the S flag. Closes: #152482.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Sun, 21 Jul 2002 13:46:13 -0500
|
||||
|
||||
offlineimap (3.0.2) unstable; urgency=low
|
||||
|
||||
* Fixed mailbox name recorder to use localfolder.getvisiblename() rather
|
||||
than remotefolder.getvisiblename()
|
||||
* Fixed remotepassfile option. Closes: #153119. Used 1-line patch from
|
||||
Tommi Virtanen.
|
||||
* Now handles cases of not being able to get UID for an uploaded message
|
||||
more gracefully. This could occur if the server doesn't support
|
||||
SEARCH, can't find the message ID, or finds multiple message IDs.
|
||||
Closes: #153241.
|
||||
* Now source is in Subversion. Make version.py log the Subversion
|
||||
revision number.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Wed, 15 Jul 2002 06:43:36 -0500
|
||||
|
||||
offlineimap (3.0.1) unstable; urgency=low
|
||||
|
||||
* Detabified the source.
|
||||
* Added UI list to the manpage.
|
||||
* Added -o (run only once) option with patch sent in by Martijn Pieters.
|
||||
* Optimized folder/IMAP.py addmessagesflags() with new listjoin() in
|
||||
imaputil. Now, send the server 1:5,7 instead of 1,2,3,4,5,7.
|
||||
* Made folder/Maildir.py/deletemessage() more tolerant if a message
|
||||
asked to be deleted already has been.
|
||||
* In Base.py/copymessageto(), no longer bother calling getmessage()
|
||||
unless a folder's storemessages() returns true. This will also help
|
||||
with syncing to LocalStatus if the user deleted messages in the
|
||||
Maildir since the cachemessagelist() was called.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Fri, 12 Jul 2002 07:28:24 -0500
|
||||
|
||||
offlineimap (3.0.0) unstable; urgency=low
|
||||
|
||||
* Introduced a new graphical user interface written with Tkinter.
|
||||
It features a nice view of multi-threaded displays.
|
||||
* The TTY user interface now also displays thread names.
|
||||
* Program-wide, new threads are given descriptive names to aid in
|
||||
debugging and status messages.
|
||||
* Added new module offlineimap/ui/detect.py that is used to detect
|
||||
which user interface to select for a given session. Its operation
|
||||
is governed by the ui config option and the -u command-line option.
|
||||
* Made IMAP folder addmessagesflags() resiliant to a server refusing
|
||||
to return a full set of new message flags. Closes: #152587.
|
||||
* Completely rewrote documentation. OfflineIMAP now has an
|
||||
exhaustive manpage, which is really a manual. It is also shipped
|
||||
in plain text, HTML, PDF, and PostScript formats.
|
||||
* New command-line options:
|
||||
-1 to force no multi-threaded operation
|
||||
-u to force a particular UI
|
||||
-a to specify which accounts to sync
|
||||
-h to print help
|
||||
-c to specify an alternate config file
|
||||
* Added a workaround for UW IMAP problem wherein the server loses
|
||||
uidvalidity whenever a folder is emptied. Now, the program
|
||||
will not consider it a problem if uidvalidity is lost when a folder
|
||||
and the local status cache are both completely empty, since we do
|
||||
not really need to preserve uidvalidity in that case anyway.
|
||||
Closes: #152079.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Thu, 11 Jul 2002 22:35:42 -0500
|
||||
|
||||
offlineimap (2.0.8) unstable; urgency=low
|
||||
|
||||
* Modified the IMAP folder to use SELECT rather than STATUS more often.
|
||||
Makes the code more robust; handles better with read-only folders;
|
||||
and runs faster, especially for non-threaded useres, where it
|
||||
may eliminate up to 2-3 commands per folder.
|
||||
* Made sure IMAP folder savemessage() does a select. This was a possible
|
||||
bug.
|
||||
* Modified Maildir folder to unlink messages with T flag in
|
||||
cachemessagelist()
|
||||
* My own box now syncs in 3 seconds.
|
||||
* Optimized acquireconnection() to try to give a thread back the
|
||||
connection that it last used, if possible.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Tue, 9 Jul 2002 23:29:30 -0500
|
||||
|
||||
offlineimap (2.0.7) unstable; urgency=low
|
||||
|
||||
* Fixed imaplib.py to work better with read-only folders.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Tue, 9 Jul 2002 20:24:21 -0500
|
||||
|
||||
offlineimap (2.0.6) unstable; urgency=low
|
||||
|
||||
* Added support for holdconnectionopen and keepalive. This feature
|
||||
allows for an IMAP server connection(s) to be held open until
|
||||
the next sync process, permitting faster restart times.
|
||||
* Another try at read-only folder support. This is nasty because I
|
||||
have no way to test it and imaplib's read-only support is weird.
|
||||
* Closing out old bug; fixed in 1.0.2. Closes: #150803.
|
||||
* Optimized algorithm so that a SELECT is never issued for folders
|
||||
that contain no messages.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Tue, 9 Jul 2002 20:05:24 -0500
|
||||
|
||||
offlineimap (2.0.5) unstable; urgency=low
|
||||
|
||||
* Fixed a folderfilter example. Partially fixes #152079.
|
||||
* Added folderincludes capability. Partially fixes #152079.
|
||||
* More fixes for read-only folders.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Fri, 5 Jul 2002 09:21:52 -0500
|
||||
|
||||
offlineimap (2.0.4) unstable; urgency=low
|
||||
|
||||
* Made OfflineIMAP at least rudimentarily compatible with read-only
|
||||
folders. It will still fail if they get modified locally, though.
|
||||
* Flags are handled case-insensitively. Closes: #151993.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Fri, 5 Jul 2002 09:10:29 -0500
|
||||
|
||||
offlineimap (2.0.3) unstable; urgency=low
|
||||
|
||||
* Added support for specifying references. Closes: #151960.
|
||||
* Added -d command-line option to enable imaplib debugging.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Thu, 4 Jul 2002 20:39:29 -0500
|
||||
|
||||
offlineimap (2.0.2) unstable; urgency=low
|
||||
|
||||
* Added support for remotepassfile. Closes: #151943.
|
||||
* Added support for preauth tunnels.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Thu, 4 Jul 2002 14:46:23 -0500
|
||||
|
||||
offlineimap (2.0.1) unstable; urgency=low
|
||||
|
||||
* Fixed a bug with not properly propogating foldersep changes.
|
||||
Now, local folders and status folders properly use the foldersep
|
||||
mechanism. This corrects a problem with Exchange servers.
|
||||
* Wrote a major new thread montiring subsystem, defined a new
|
||||
ExitNotifyThread. Handling of Ctrl-C now occurs within 1 second
|
||||
rather than after the whole program terminates. Exceptions that
|
||||
occur in a thread are now caught by the main thread and marshalled
|
||||
over into the UI side of things for dispatch. The entire program will
|
||||
now abort when one thread dies with an exception.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Thu, 4 Jul 2002 09:07:06 -0500
|
||||
|
||||
offlineimap (2.0.0) unstable; urgency=low
|
||||
|
||||
* This code is now multithreaded. New config file options control the
|
||||
behavior. This can make synchronizing several times faster.
|
||||
* Fixed the STATUS call to be compatible with Exchange.
|
||||
* Added the ability to exclude folders.
|
||||
* If upgrading from 1.0.x, you will need to add maxsyncaccounts to the
|
||||
general section and maxconnections to each account sections.
|
||||
There is also a new folderfilter option.
|
||||
You can find examples of all of these in the new offlineimap.conf
|
||||
example file packaged with the distribution.
|
||||
* The Debian package now properly installs the example offlineimap.conf
|
||||
file.
|
||||
* There is a new mailing list available. To join, send SUBSCRIBE
|
||||
to offlineimap-request@complete.org. The posting address is
|
||||
offlineimap@complete.org.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Wed, 3 Jul 2002 19:21:32 -0500
|
||||
|
||||
offlineimap (1.0.4) unstable; urgency=low
|
||||
|
||||
* Deletion of more than one message has been optimized. This could make
|
||||
deleting large numbers of messages far faster -- several orders of
|
||||
magnitude.
|
||||
* Moved more sleep code into ui layer. Fancier sleep actions are now
|
||||
possible. Better handling of Ctrl-C in TTY handler.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Tue, 2 Jul 2002 19:16:04 -0500
|
||||
|
||||
offlineimap (1.0.3) unstable; urgency=low
|
||||
|
||||
* Fixed a bug when a message was deleted on the IMAP side and modified
|
||||
on the local side.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Mon, 24 Jun 2002 19:08:21 -0500
|
||||
|
||||
offlineimap (1.0.2) unstable; urgency=low
|
||||
|
||||
* Made sure that LocalStatus does writing atomically. If the program
|
||||
is interrupted during save(), there will always be a complete copy of
|
||||
either the old or the new data.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Mon, 24 Jun 2002 06:57:28 -0500
|
||||
|
||||
offlineimap (1.0.1) unstable; urgency=low
|
||||
|
||||
* Fixed a bug with writing messages to some IMAP servers. Turns
|
||||
out we need to issue CHECK between APPEND and SEARCH for some.
|
||||
Thanks to Donovan Lange for reporting this bug and helping track it
|
||||
down.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Fri, 21 Jun 2002 22:03:12 -0500
|
||||
|
||||
offlineimap (1.0.0) unstable; urgency=low
|
||||
|
||||
* Initial Release. Closes: #150571.
|
||||
|
||||
-- John Goerzen <jgoerzen@complete.org> Fri, 21 Jun 2002 18:54:56 -0500
|
||||
|
||||
Local variables:
|
||||
mode: debian-changelog
|
||||
End:
|
46
offlineimap/head/offlineimap/CustomConfig.py
Normal file
46
offlineimap/head/offlineimap/CustomConfig.py
Normal file
@ -0,0 +1,46 @@
|
||||
# Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
from ConfigParser import ConfigParser
|
||||
from offlineimap.localeval import LocalEval
|
||||
import os
|
||||
|
||||
class CustomConfigParser(ConfigParser):
|
||||
def getdefault(self, section, option, default, *args, **kwargs):
|
||||
"""Same as config.get, but returns the "default" option if there
|
||||
is no such option specified."""
|
||||
if self.has_option(section, option):
|
||||
return apply(self.get, [section, option] + list(args), kwargs)
|
||||
else:
|
||||
return default
|
||||
|
||||
def getmetadatadir(self):
|
||||
metadatadir = os.path.expanduser(self.getdefault("general", "metadata", "~/.offlineimap"))
|
||||
if not os.path.exists(metadatadir):
|
||||
os.mkdir(metadatadir, 0700)
|
||||
return metadatadir
|
||||
|
||||
def getlocaleval(self):
|
||||
if self.has_option("general", "pythonfile"):
|
||||
path = os.path.expanduser(self.get("general", "pythonfile"))
|
||||
else:
|
||||
path = None
|
||||
return LocalEval(path)
|
||||
|
||||
def getaccountlist(self):
|
||||
return [x for x in self.sections() if x != 'general']
|
||||
|
211
offlineimap/head/offlineimap/accounts.py
Normal file
211
offlineimap/head/offlineimap/accounts.py
Normal file
@ -0,0 +1,211 @@
|
||||
# Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
from offlineimap import imapserver, repository, threadutil
|
||||
from offlineimap.ui import UIBase
|
||||
from offlineimap.threadutil import InstanceLimitedThread, ExitNotifyThread
|
||||
from threading import Event
|
||||
import os
|
||||
|
||||
mailboxes = []
|
||||
|
||||
class Account:
|
||||
def __init__(self, config, name):
|
||||
self.config = config
|
||||
self.name = name
|
||||
self.metadatadir = config.getmetadatadir()
|
||||
self.localeval = config.getlocaleval()
|
||||
self.server = imapserver.ConfigedIMAPServer(config, self.name)
|
||||
self.ui = UIBase.getglobalui()
|
||||
if self.config.has_option(self.name, 'autorefresh'):
|
||||
self.refreshperiod = self.config.getint(self.name, 'autorefresh')
|
||||
else:
|
||||
self.refreshperiod = None
|
||||
self.hold = self.config.has_option(self.name, 'holdconnectionopen') \
|
||||
and self.config.getboolean(self.name, 'holdconnectionopen')
|
||||
if self.config.has_option(self.name, 'keepalive'):
|
||||
self.keepalive = self.config.getint(self.name, 'keepalive')
|
||||
else:
|
||||
self.keepalive = None
|
||||
|
||||
def getconf(self, option, default = None):
|
||||
if default != None:
|
||||
return self.config.get(self.name, option)
|
||||
else:
|
||||
return self.config.getdefault(self.name, option,
|
||||
default)
|
||||
|
||||
def sleeper(self):
|
||||
"""Sleep handler. Returns same value as UIBase.sleep:
|
||||
0 if timeout expired, 1 if there was a request to cancel the timer,
|
||||
and 2 if there is a request to abort the program.
|
||||
|
||||
Also, returns 100 if configured to not sleep at all."""
|
||||
|
||||
if not self.refreshperiod:
|
||||
return 100
|
||||
refreshperiod = self.refreshperiod * 60
|
||||
if self.keepalive:
|
||||
kaevent = Event()
|
||||
kathread = ExitNotifyThread(target = self.server.keepalive,
|
||||
name = "Keep alive " + self.name,
|
||||
args = (self.keepalive, kaevent))
|
||||
kathread.setDaemon(1)
|
||||
kathread.start()
|
||||
sleepresult = self.ui.sleep(refreshperiod)
|
||||
if sleepresult == 2:
|
||||
# Cancel keep-alive, but don't bother terminating threads
|
||||
if self.keepalive:
|
||||
kaevent.set()
|
||||
return sleepresult
|
||||
else:
|
||||
# Cancel keep-alive and wait for thread to terminate.
|
||||
if self.keepalive:
|
||||
kaevent.set()
|
||||
kathread.join()
|
||||
return sleepresult
|
||||
|
||||
class AccountSynchronizationMixin:
|
||||
def syncrunner(self):
|
||||
self.ui.acct(self.name)
|
||||
if not self.refreshperiod:
|
||||
self.sync()
|
||||
self.ui.acctdone(self.name)
|
||||
return
|
||||
looping = 1
|
||||
while looping:
|
||||
self.sync()
|
||||
looping = self.sleeper() != 2
|
||||
self.ui.acctdone(self.name)
|
||||
|
||||
def sync(self):
|
||||
# We don't need an account lock because syncitall() goes through
|
||||
# each account once, then waits for all to finish.
|
||||
try:
|
||||
accountmetadata = os.path.join(self.metadatadir, self.name)
|
||||
if not os.path.exists(accountmetadata):
|
||||
os.mkdir(accountmetadata, 0700)
|
||||
|
||||
remoterepos = repository.IMAP.IMAPRepository(self.config,
|
||||
self.localeval,
|
||||
self.name,
|
||||
self.server)
|
||||
|
||||
# Connect to the Maildirs.
|
||||
localrepos = repository.Maildir.MaildirRepository(os.path.expanduser(self.config.get(self.name, "localfolders")), self.name, self.config)
|
||||
|
||||
# Connect to the local cache.
|
||||
statusrepos = repository.LocalStatus.LocalStatusRepository(accountmetadata)
|
||||
|
||||
self.ui.syncfolders(remoterepos, localrepos)
|
||||
remoterepos.syncfoldersto(localrepos)
|
||||
|
||||
folderthreads = []
|
||||
for remotefolder in remoterepos.getfolders():
|
||||
thread = InstanceLimitedThread(\
|
||||
instancename = 'FOLDER_' + self.name,
|
||||
target = syncfolder,
|
||||
name = "Folder sync %s[%s]" % \
|
||||
(self.name, remotefolder.getvisiblename()),
|
||||
args = (self.name, remoterepos, remotefolder, localrepos,
|
||||
statusrepos))
|
||||
thread.setDaemon(1)
|
||||
thread.start()
|
||||
folderthreads.append(thread)
|
||||
threadutil.threadsreset(folderthreads)
|
||||
if not self.hold:
|
||||
server.close()
|
||||
finally:
|
||||
pass
|
||||
|
||||
class SyncableAccount(Account, AccountSynchronizationMixin):
|
||||
pass
|
||||
|
||||
def syncfolder(accountname, remoterepos, remotefolder, localrepos,
|
||||
statusrepos):
|
||||
global mailboxes
|
||||
ui = UIBase.getglobalui()
|
||||
# Load local folder.
|
||||
localfolder = localrepos.\
|
||||
getfolder(remotefolder.getvisiblename().\
|
||||
replace(remoterepos.getsep(), localrepos.getsep()))
|
||||
# Write the mailboxes
|
||||
mailboxes.append({'accountname': accountname,
|
||||
'foldername': localfolder.getvisiblename()})
|
||||
# Load local folder
|
||||
ui.syncingfolder(remoterepos, remotefolder, localrepos, localfolder)
|
||||
ui.loadmessagelist(localrepos, localfolder)
|
||||
localfolder.cachemessagelist()
|
||||
ui.messagelistloaded(localrepos, localfolder, len(localfolder.getmessagelist().keys()))
|
||||
|
||||
|
||||
# Load status folder.
|
||||
statusfolder = statusrepos.getfolder(remotefolder.getvisiblename().\
|
||||
replace(remoterepos.getsep(),
|
||||
statusrepos.getsep()))
|
||||
if localfolder.getuidvalidity() == None:
|
||||
# This is a new folder, so delete the status cache to be sure
|
||||
# we don't have a conflict.
|
||||
statusfolder.deletemessagelist()
|
||||
|
||||
statusfolder.cachemessagelist()
|
||||
|
||||
|
||||
# If either the local or the status folder has messages and
|
||||
# there is a UID validity problem, warn and abort.
|
||||
# If there are no messages, UW IMAPd loses UIDVALIDITY.
|
||||
# But we don't really need it if both local folders are empty.
|
||||
# So, in that case, save it off.
|
||||
if (len(localfolder.getmessagelist()) or \
|
||||
len(statusfolder.getmessagelist())) and \
|
||||
not localfolder.isuidvalidityok(remotefolder):
|
||||
ui.validityproblem(remotefolder)
|
||||
return
|
||||
else:
|
||||
localfolder.saveuidvalidity(remotefolder.getuidvalidity())
|
||||
|
||||
# Load remote folder.
|
||||
ui.loadmessagelist(remoterepos, remotefolder)
|
||||
remotefolder.cachemessagelist()
|
||||
ui.messagelistloaded(remoterepos, remotefolder,
|
||||
len(remotefolder.getmessagelist().keys()))
|
||||
|
||||
|
||||
#
|
||||
|
||||
if not statusfolder.isnewfolder():
|
||||
# Delete local copies of remote messages. This way,
|
||||
# if a message's flag is modified locally but it has been
|
||||
# deleted remotely, we'll delete it locally. Otherwise, we
|
||||
# try to modify a deleted message's flags! This step
|
||||
# need only be taken if a statusfolder is present; otherwise,
|
||||
# there is no action taken *to* the remote repository.
|
||||
|
||||
remotefolder.syncmessagesto_delete(localfolder, [localfolder,
|
||||
statusfolder])
|
||||
ui.syncingmessages(localrepos, localfolder, remoterepos, remotefolder)
|
||||
localfolder.syncmessagesto(statusfolder, [remotefolder, statusfolder])
|
||||
|
||||
# Synchronize remote changes.
|
||||
ui.syncingmessages(remoterepos, remotefolder, localrepos, localfolder)
|
||||
remotefolder.syncmessagesto(localfolder)
|
||||
|
||||
# Make sure the status folder is up-to-date.
|
||||
ui.syncingmessages(localrepos, localfolder, statusrepos, statusfolder)
|
||||
localfolder.syncmessagesto(statusfolder)
|
||||
statusfolder.save()
|
||||
|
@ -21,7 +21,7 @@ from offlineimap.localeval import LocalEval
|
||||
from offlineimap.threadutil import InstanceLimitedThread, ExitNotifyThread
|
||||
from offlineimap.ui import UIBase
|
||||
import re, os, os.path, offlineimap, sys
|
||||
from ConfigParser import ConfigParser
|
||||
from offlineimap.CustomConfig import CustomConfigParser
|
||||
from threading import *
|
||||
from getopt import getopt
|
||||
|
||||
@ -51,20 +51,14 @@ def startup(versionno):
|
||||
threadutil.setprofiledir(profiledir)
|
||||
sys.stderr.write("WARNING: profile mode engaged;\nPotentially large data will be created in " + profiledir + "\n")
|
||||
|
||||
config = ConfigParser()
|
||||
config = CustomConfigParser()
|
||||
if not os.path.exists(configfilename):
|
||||
sys.stderr.write(" *** Config file %s does not exist; aborting!\n" % configfilename)
|
||||
sys.exit(1)
|
||||
|
||||
config.read(configfilename)
|
||||
|
||||
if config.has_option("general", "pythonfile"):
|
||||
path=os.path.expanduser(config.get("general", "pythonfile"))
|
||||
else:
|
||||
path=None
|
||||
localeval = LocalEval(path)
|
||||
|
||||
ui = offlineimap.ui.detector.findUI(config, localeval, options.get('-u'))
|
||||
ui = offlineimap.ui.detector.findUI(config, options.get('-u'))
|
||||
ui.init_banner()
|
||||
UIBase.setglobalui(ui)
|
||||
|
||||
@ -74,12 +68,9 @@ def startup(versionno):
|
||||
if debugtype == 'imap':
|
||||
imaplib.Debug = 5
|
||||
|
||||
if '-o' in options and config.has_option("general", "autorefresh"):
|
||||
config.remove_option("general", "autorefresh")
|
||||
|
||||
metadatadir = os.path.expanduser(config.get("general", "metadata"))
|
||||
if not os.path.exists(metadatadir):
|
||||
os.mkdir(metadatadir, 0700)
|
||||
if '-o' in options:
|
||||
for section in config.getaccountlist():
|
||||
config.remove_option(section, "autorefresh")
|
||||
|
||||
accounts = config.get("general", "accounts")
|
||||
if '-a' in options:
|
||||
@ -105,17 +96,11 @@ def startup(versionno):
|
||||
threadutil.initInstanceLimit(instancename,
|
||||
config.getint(account, "maxconnections"))
|
||||
|
||||
mailboxes = []
|
||||
servers = {}
|
||||
|
||||
threadutil.initexitnotify()
|
||||
t = ExitNotifyThread(target=syncmaster.sync_with_timer,
|
||||
t = ExitNotifyThread(target=syncmaster.syncitall,
|
||||
name='Sync Runner',
|
||||
kwargs = {'accounts': accounts,
|
||||
'metadatadir': metadatadir,
|
||||
'servers': servers,
|
||||
'config': config,
|
||||
'localeval': localeval})
|
||||
'config': config})
|
||||
t.setDaemon(1)
|
||||
t.start()
|
||||
try:
|
||||
|
@ -19,9 +19,10 @@
|
||||
import os.path
|
||||
import re # for folderfilter
|
||||
|
||||
def genmbnames(config, localeval, boxlist):
|
||||
def genmbnames(config, boxlist):
|
||||
"""Takes a configparser object and a boxlist, which is a list of hashes
|
||||
containing 'accountname' and 'foldername' keys."""
|
||||
localeval = config.getlocaleval()
|
||||
if not config.getboolean("mbnames", "enabled"):
|
||||
return
|
||||
file = open(os.path.expanduser(config.get("mbnames", "filename")), "wt")
|
||||
|
@ -18,187 +18,29 @@
|
||||
|
||||
from offlineimap import imaplib, imapserver, repository, folder, mbnames, threadutil, version
|
||||
from offlineimap.threadutil import InstanceLimitedThread, ExitNotifyThread
|
||||
import offlineimap.accounts
|
||||
from offlineimap.accounts import SyncableAccount
|
||||
from offlineimap.ui import UIBase
|
||||
import re, os, os.path, offlineimap, sys
|
||||
from ConfigParser import ConfigParser
|
||||
from threading import *
|
||||
|
||||
def syncaccount(accountname, metadatadir, servers, config,
|
||||
localeval, *args):
|
||||
ui = UIBase.getglobalui()
|
||||
# We don't need an account lock because syncitall() goes through
|
||||
# each account once, then waits for all to finish.
|
||||
try:
|
||||
ui.acct(accountname)
|
||||
accountmetadata = os.path.join(metadatadir, accountname)
|
||||
if not os.path.exists(accountmetadata):
|
||||
os.mkdir(accountmetadata, 0700)
|
||||
def syncaccount(threads, config, accountname):
|
||||
account = SyncableAccount(config, accountname)
|
||||
thread = InstanceLimitedThread(instancename = 'ACCOUNTLIMIT',
|
||||
target = account.syncrunner,
|
||||
name = "Account sync %s" % accountname)
|
||||
thread.setDaemon(1)
|
||||
thread.start()
|
||||
threads.add(thread)
|
||||
|
||||
server = None
|
||||
if accountname in servers:
|
||||
server = servers[accountname]
|
||||
else:
|
||||
server = imapserver.ConfigedIMAPServer(config, accountname)
|
||||
servers[accountname] = server
|
||||
|
||||
remoterepos = repository.IMAP.IMAPRepository(config, localeval, accountname, server)
|
||||
|
||||
# Connect to the Maildirs.
|
||||
localrepos = repository.Maildir.MaildirRepository(os.path.expanduser(config.get(accountname, "localfolders")), accountname, config)
|
||||
|
||||
# Connect to the local cache.
|
||||
statusrepos = repository.LocalStatus.LocalStatusRepository(accountmetadata)
|
||||
|
||||
ui.syncfolders(remoterepos, localrepos)
|
||||
remoterepos.syncfoldersto(localrepos)
|
||||
ui.acct(accountname)
|
||||
|
||||
folderthreads = []
|
||||
for remotefolder in remoterepos.getfolders():
|
||||
thread = InstanceLimitedThread(\
|
||||
instancename = 'FOLDER_' + accountname,
|
||||
target = syncfolder,
|
||||
name = "Folder sync %s[%s]" % \
|
||||
(accountname, remotefolder.getvisiblename()),
|
||||
args = (accountname, remoterepos, remotefolder, localrepos,
|
||||
statusrepos))
|
||||
thread.setDaemon(1)
|
||||
thread.start()
|
||||
folderthreads.append(thread)
|
||||
threadutil.threadsreset(folderthreads)
|
||||
if not (config.has_option(accountname, 'holdconnectionopen') and \
|
||||
config.getboolean(accountname, 'holdconnectionopen')):
|
||||
server.close()
|
||||
finally:
|
||||
pass
|
||||
|
||||
def syncfolder(accountname, remoterepos, remotefolder, localrepos,
|
||||
statusrepos):
|
||||
ui = UIBase.getglobalui()
|
||||
# Load local folder.
|
||||
localfolder = localrepos.\
|
||||
getfolder(remotefolder.getvisiblename().\
|
||||
replace(remoterepos.getsep(), localrepos.getsep()))
|
||||
# Write the mailboxes
|
||||
mailboxes.append({'accountname': accountname,
|
||||
'foldername': localfolder.getvisiblename()})
|
||||
# Load local folder
|
||||
ui.syncingfolder(remoterepos, remotefolder, localrepos, localfolder)
|
||||
ui.loadmessagelist(localrepos, localfolder)
|
||||
localfolder.cachemessagelist()
|
||||
ui.messagelistloaded(localrepos, localfolder, len(localfolder.getmessagelist().keys()))
|
||||
|
||||
|
||||
# Load status folder.
|
||||
statusfolder = statusrepos.getfolder(remotefolder.getvisiblename().\
|
||||
replace(remoterepos.getsep(),
|
||||
statusrepos.getsep()))
|
||||
if localfolder.getuidvalidity() == None:
|
||||
# This is a new folder, so delete the status cache to be sure
|
||||
# we don't have a conflict.
|
||||
statusfolder.deletemessagelist()
|
||||
|
||||
statusfolder.cachemessagelist()
|
||||
|
||||
|
||||
# If either the local or the status folder has messages and
|
||||
# there is a UID validity problem, warn and abort.
|
||||
# If there are no messages, UW IMAPd loses UIDVALIDITY.
|
||||
# But we don't really need it if both local folders are empty.
|
||||
# So, in that case, save it off.
|
||||
if (len(localfolder.getmessagelist()) or \
|
||||
len(statusfolder.getmessagelist())) and \
|
||||
not localfolder.isuidvalidityok(remotefolder):
|
||||
ui.validityproblem(remotefolder)
|
||||
return
|
||||
else:
|
||||
localfolder.saveuidvalidity(remotefolder.getuidvalidity())
|
||||
|
||||
# Load remote folder.
|
||||
ui.loadmessagelist(remoterepos, remotefolder)
|
||||
remotefolder.cachemessagelist()
|
||||
ui.messagelistloaded(remoterepos, remotefolder,
|
||||
len(remotefolder.getmessagelist().keys()))
|
||||
|
||||
|
||||
#
|
||||
|
||||
if not statusfolder.isnewfolder():
|
||||
# Delete local copies of remote messages. This way,
|
||||
# if a message's flag is modified locally but it has been
|
||||
# deleted remotely, we'll delete it locally. Otherwise, we
|
||||
# try to modify a deleted message's flags! This step
|
||||
# need only be taken if a statusfolder is present; otherwise,
|
||||
# there is no action taken *to* the remote repository.
|
||||
|
||||
remotefolder.syncmessagesto_delete(localfolder, [localfolder,
|
||||
statusfolder])
|
||||
ui.syncingmessages(localrepos, localfolder, remoterepos, remotefolder)
|
||||
localfolder.syncmessagesto(statusfolder, [remotefolder, statusfolder])
|
||||
|
||||
# Synchronize remote changes.
|
||||
ui.syncingmessages(remoterepos, remotefolder, localrepos, localfolder)
|
||||
remotefolder.syncmessagesto(localfolder)
|
||||
|
||||
# Make sure the status folder is up-to-date.
|
||||
ui.syncingmessages(localrepos, localfolder, statusrepos, statusfolder)
|
||||
localfolder.syncmessagesto(statusfolder)
|
||||
statusfolder.save()
|
||||
|
||||
|
||||
|
||||
def syncitall(accounts, metadatadir, servers, config, localeval):
|
||||
ui = UIBase.getglobalui()
|
||||
global mailboxes
|
||||
mailboxes = [] # Reset.
|
||||
threads = []
|
||||
for accountname in accounts:
|
||||
thread = InstanceLimitedThread(instancename = 'ACCOUNTLIMIT',
|
||||
target = syncaccount,
|
||||
name = "Account sync %s" % accountname,
|
||||
args = (accountname, metadatadir,
|
||||
servers, config,
|
||||
localeval))
|
||||
thread.setDaemon(1)
|
||||
thread.start()
|
||||
threads.append(thread)
|
||||
# Wait for the threads to finish.
|
||||
threadutil.threadsreset(threads)
|
||||
mbnames.genmbnames(config, localeval, mailboxes)
|
||||
|
||||
def sync_with_timer(accounts, metadatadir, servers, config,
|
||||
localeval):
|
||||
ui = UIBase.getglobalui()
|
||||
def syncitall(accounts, config):
|
||||
currentThread().setExitMessage('SYNC_WITH_TIMER_TERMINATE')
|
||||
syncitall(accounts, metadatadir, servers, config, localeval)
|
||||
if config.has_option('general', 'autorefresh'):
|
||||
refreshperiod = config.getint('general', 'autorefresh') * 60
|
||||
while 1:
|
||||
# Set up keep-alives.
|
||||
kaevents = {}
|
||||
kathreads = {}
|
||||
for accountname in accounts:
|
||||
if config.has_option(accountname, 'holdconnectionopen') and \
|
||||
config.getboolean(accountname, 'holdconnectionopen') and \
|
||||
config.has_option(accountname, 'keepalive'):
|
||||
event = Event()
|
||||
kaevents[accountname] = event
|
||||
thread = ExitNotifyThread(target = servers[accountname].keepalive,
|
||||
name = "Keep alive " + accountname,
|
||||
args = (config.getint(accountname, 'keepalive'), event))
|
||||
thread.setDaemon(1)
|
||||
thread.start()
|
||||
kathreads[accountname] = thread
|
||||
if ui.sleep(refreshperiod) == 2:
|
||||
# Cancel keep-alives, but don't bother terminating threads
|
||||
for event in kaevents.values():
|
||||
event.set()
|
||||
break
|
||||
else:
|
||||
# Cancel keep-alives and wait for threads to terminate.
|
||||
for event in kaevents.values():
|
||||
event.set()
|
||||
for thread in kathreads.values():
|
||||
thread.join()
|
||||
syncitall(accounts, metadatadir, servers, config,
|
||||
localeval)
|
||||
ui = UIBase.getglobalui()
|
||||
threads = threadutil.threadlist()
|
||||
offlineimap.accounts.mailboxes = [] # Reset.
|
||||
for accountname in accounts:
|
||||
syncaccount(threads, config, accountname)
|
||||
# Wait for the threads to finish.
|
||||
threads.reset()
|
||||
mbnames.genmbnames(config, offlineimap.accounts.mailboxes)
|
||||
|
17
offlineimap/head/offlineimap/test.py
Normal file
17
offlineimap/head/offlineimap/test.py
Normal file
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/python2.2 -i
|
||||
import hmac
|
||||
def getpassword():
|
||||
return 'tanstaaftanstaaf'
|
||||
|
||||
def md5handler(response):
|
||||
challenge = response.strip()
|
||||
print "challenge is", challenge
|
||||
msg = getpassword()
|
||||
reply = hmac.new(challenge, msg)
|
||||
retval = 'tim' + ' ' + \
|
||||
reply.hexdigest()
|
||||
while len(retval) < 64:
|
||||
retval += "\0"
|
||||
|
||||
print "md5handler returning", retval
|
||||
return retval
|
@ -48,6 +48,42 @@ def threadsreset(threadlist):
|
||||
for thr in threadlist:
|
||||
thr.join()
|
||||
|
||||
class threadlist:
|
||||
def __init__(self):
|
||||
self.lock = Lock()
|
||||
self.list = []
|
||||
|
||||
def add(self, thread):
|
||||
self.lock.acquire()
|
||||
try:
|
||||
self.list.append(thread)
|
||||
finally:
|
||||
self.lock.release()
|
||||
|
||||
def remove(self, thread):
|
||||
self.lock.acquire()
|
||||
try:
|
||||
self.list.remove(thread)
|
||||
finally:
|
||||
self.lock.release()
|
||||
|
||||
def pop(self):
|
||||
self.lock.acquire()
|
||||
try:
|
||||
if not len(self.list):
|
||||
return None
|
||||
return self.list.pop()
|
||||
finally:
|
||||
self.lock.release()
|
||||
|
||||
def reset(self):
|
||||
while 1:
|
||||
thread = self.pop()
|
||||
if not thread:
|
||||
return
|
||||
thread.join()
|
||||
|
||||
|
||||
######################################################################
|
||||
# Exit-notify threads
|
||||
######################################################################
|
||||
|
@ -20,7 +20,7 @@ import sys, time
|
||||
from UIBase import UIBase
|
||||
|
||||
class Basic(UIBase):
|
||||
def getpass(s, accountname, config):
|
||||
def getpass(s, accountname, config, errmsg = None):
|
||||
raise NotImplementedError, "Prompting for a password is not supported in noninteractive mode."
|
||||
|
||||
def _msg(s, msg):
|
||||
|
@ -140,6 +140,10 @@ class UIBase:
|
||||
if s.verbose >= 0:
|
||||
s._msg("***** Processing account %s" % accountname)
|
||||
|
||||
def acctdone(s, accountname):
|
||||
if s.verbose >= 0:
|
||||
s._msg("***** Finished processing account " + accountname)
|
||||
|
||||
def syncfolders(s, srcrepos, destrepos):
|
||||
if s.verbose >= 0:
|
||||
s._msg("Copying folder structure from %s to %s" % \
|
||||
|
@ -19,7 +19,7 @@
|
||||
import offlineimap.ui
|
||||
import sys
|
||||
|
||||
def findUI(config, localeval, chosenUI=None):
|
||||
def findUI(config, chosenUI=None):
|
||||
uistrlist = ['Tk.Blinkenlights', 'Tk.VerboseUI', 'TTY.TTYUI',
|
||||
'Noninteractive.Basic', 'Noninteractive.Quiet']
|
||||
namespace={}
|
||||
@ -34,7 +34,7 @@ def findUI(config, localeval, chosenUI=None):
|
||||
uistrlist = config.get("general", "ui").replace(" ", "").split(",")
|
||||
|
||||
for uistr in uistrlist:
|
||||
uimod = getUImod(uistr, localeval, namespace)
|
||||
uimod = getUImod(uistr, config.getlocaleval(), namespace)
|
||||
if uimod:
|
||||
uiinstance = uimod(config)
|
||||
if uiinstance.isusable():
|
||||
|
Loading…
Reference in New Issue
Block a user