The Big Rewrite. too many change to list them all.

as opposed to earlier threats, BerkDB was not entirely dropped; i
suppose the isync 0.7 -> 0.8 change had a reason, so i added an
alternative UID storage scheme.
note that BDB 4.0 is not sufficient, as the db->open function changed in
an incompatible way ...

i updated the debian packaging except for a changelog entry.
note that i removed the upgrade blurb, as upstream now has a smooth
upgrade path down to at least isync 0.4.
This commit is contained in:
Oswald Buddenhagen 2004-03-27 16:07:20 +00:00
parent 8d1b26aebe
commit 130664b622
48 changed files with 7946 additions and 4489 deletions

View File

@ -7,12 +7,16 @@ build-stamp
config.h
config.h.in
config.cache
config.guess
config.log
config.status
config.sub
configure
configure.lineno
configure-stamp
isync.spec
isync-*.tar.gz
patch-stamp
stamp-h
stamp-h.in
stamp-h1

View File

@ -1,6 +1,6 @@
SUBDIRS = src
man_MANS = isync.1
EXTRA_DIST = debian isyncrc.sample isync.spec $(man_MANS)
bin_SCRIPTS = get-cert
EXTRA_DIST = debian isync.spec $(bin_SCRIPTS)
log:
@perl -p -e "s/^(\\S+)\\s+(\\S.+\\S)\\s+(\\S+)\\s*\$$/\$$1:'\$$2 <\$$3>'\\n/" < ../CVSROOT/accounts > .usermap
@ -16,6 +16,9 @@ deb-clean:
distdir distclean: deb-clean
dist-hook:
find $(distdir)/debian \( -name CVS -o -name .cvsignore -o -name .#\*# -o -type l \) -print0 | xargs -0r rm -rf
rpm:
make dist
cp $(PACKAGE)-$(VERSION).tar.gz /usr/src/rpm/SOURCES

24
NEWS
View File

@ -1,3 +1,27 @@
[1.0.0]
Essentially a rewrite. Synchronization state storage concept, configuration
and command line changed entirely.
But you needn't to worry about the upgrade, as a fully automated migration
path is provided, even for users of isync 0.7 and below.
Still, you should re-read the manual to be able to take full advantage of the
new features:
The supported mailbox types can be freely paired.
A possible application of this is using a local IMAP server to access
mailboxes that are not natively supported yet.
Message deletions (expunges) are now propagated both ways, so there is no need
for using mutt with maildir_trash any more.
Additional trash options added.
`OneToOne' replaced by something more flexible.
Partial support for IMAP pipelining (streaming, parallelization) added.
Makes flag change propagation much faster - this affects every message that
becomes Seen/Read.
[0.9]
Added Tunnel directive to allow the user to specify a shell command to run

77
README
View File

@ -4,52 +4,69 @@
| \__ \ |_| | | | | (__
|_|___/\__, |_| |_|\___|
|___/
isync - IMAP4 to maildir mailbox synchronization program
isync/mbsync - free (GPL) mailbox synchronization program
http://isync.sf.net/
Author: Michael Elkins <me@mutt.org>
Current maintainer: Oswald Buddenhagen <ossi@users.sf.net>
See AUTHORS for contact information.
``isync'' is a command line application which synchronizes a local
maildir-style mailbox with a remote IMAP4 mailbox, suitable for use in
IMAP-disconnected mode. Multiple copies of the remote IMAP4 mailbox can be
maintained, and all flags are synchronized.
``mbsync'' is a command line application which synchronizes mailboxes;
currently Maildir and IMAP4 mailboxes are supported. New messages, message
deletions and flag changes can be propagated both ways.
``mbsync'' is suitable for use in IMAP-disconnected mode.
* Features:
Synchronization is based on unique message identifiers (UIDs), so no
identification conflicts can occur (as opposed to some other mail
synchronizers).
Synchronization state is kept in one local text file per mailbox pair;
multiple replicas of a mailbox can be maintained.
* Fast mode for fetching new mail only
* Supports imaps: (port 993) TLS/SSL connections
* Supports STARTTLS (RFC2595) for confidentiality
* Supports NAMESPACE (RFC2342)
* Supports CRAM-MD5 (RFC2095) for authentication
isync is the project name, while mbsync is the current executable name; this
change was necessary because of massive changes in the user interface. An
isync executable still exists; it is a compatibility wrapper around mbsync.
* Features
* Fine-grained selection of synchronization operations to perform
* Synchronizes single mailboxes or entire mailbox collections
* Partial mirrors possible: keep only the latest messages locally
* Trash functionality: backup messages before removing them
* IMAP features:
* Supports TLS/SSL via imaps: (port 993) and STARTTLS (RFC2595)
* Supports CRAM-MD5 (RFC2195) for authentication
* Supports NAMESPACE (RFC2342) for simplified configuration
* Pipelining for maximum speed (currently only partially implemented)
* Compatibility
``isync'' has been tested with the following IMAP servers:
isync should work fairly well with any IMAP4 compliant server;
particularily efficient with those that support the UIDPLUS and LITERAL+
extensions.
* Microsoft Exchange 2000 IMAP4rev1 server version 6.0.4417.0
* Courier-IMAP 1.2.3
* WU-IMAP 2000
* Domino IMAP4 Server Release 5.0.8
Courier 1.4.3 is known to be buggy, version 1.7.3 works fine.
c-client (UW-IMAP, Pine) is mostly fine, but tends to change UIDVALIDITY
pretty often when used with unix/mbox mailboxes, making isync refuse
synchronization.
The "cure" is to simply copy the new UIDVALIDITY from the affected
mailbox to mbsync's state file. This is a Bad Hack (TM), but it works -
use at your own risk (if the UIDVALIDITY change was genuine, this will
delete all messages in the affected mailbox - not that this ever
happened to me).
* Platforms
``isync'' has successfully been compiled on:
* Linux
* Solaris 2.7
* OpenBSD 2.8
* FreeBSD 4.3
At some point, ``isync'' has successfully run on:
Linux, Solaris 2.7, OpenBSD 2.8, FreeBSD 4.3, Cygwin
* Requirements
OpenSSL for TLS/SSL support (optional)
OpenSSL for TLS/SSL support (optional)
* INSTALLING
* Installation
./configure
make install
./configure
make install
* HELP
* Help
Please see the man page for complete documentation.
Please see the man page for complete documentation.

62
TODO
View File

@ -1,39 +1,51 @@
change of UIDVALIDITY shouldn't be considered fatal for the imap connection.
maybe the error handling needs to be cleaned up in general.
make SSL certificate validation more automatic.
don't require maildir_trash. currently MaxMessages gets into the way of
simply removing it; that is fixable with some shuffling, though.
add asynchronous operation to remote mailbox drivers. this is actually
what prevents us from simply using c-client and thus becoming mailsync.
refactor mailbox support. create proper mailbox drivers; handle imap and
maildir (and anything else) symmetrically; decouple UID->message mapping
from sync database - should use the same UID storing schemes as c-client
(pine, uw-imap) does, at least optionally, i think.
handle custom flags (keywords).
add asynchrounous operation to remote mailbox drivers. this is actually
what prevents us from simply using c-client for the previous point and
thus simply becoming mailsync.
fix maildir_{open_store,list} to handle partial names (last char not slash).
store message flags in sync database, so _un_setting them will be properly
synced as well.
add a way to automatically create and sync subfolders.
handle custom imap flags. currently, isync just fails horribly if it
encounters some.
could store TUID even when UIDPLUS is supported. would avoid duplicated
messages after abort before new UID arrives.
add options for fine-grained control of syncing operations (--new, --delete &
--flags) and direction (--push & --pull).
decouple TUID search from append. that's a prerequisite for usable
MULTIAPPEND, and is generally good for async. should be way faster, too,
as it saves repeated mailbox rescans with single-file formats.
add support for syncing with other: and shared: via NAMESPACE
use MULTIAPPEND and FETCH with multiple messages.
isync ignores asynchronous notifications (untagged responses), so mail
arriving during a fetch will not be fetched in the current run any more.
create dummies describing MIME structure of messages bigger than MaxSize.
flagging the dummy would fetch the real message. possibly remove --renew.
add a way to automatically create and sync IMAP subfolders.
don't SELECT boxes unless really needed; in particular not for appending,
and in write-only mode not before changes are made.
make the command line take precedence over the config file.
possibly request message attributes on a per-message basis from the drivers.
considerations:
- record non-existing UID ranges in the sync database, so IMAP FETCHes needn't
to exclude anyway non-existing messages explicitly.
- when detect unborn pairs and orphaned messages being gone? implied by expunge:
with trashing, by local driver, or of messages we deleted in this run. the
remaining cases could be handled by automatic periodical cleanup passes, an
explicit --cleanup action, or be implied by one of the other actions.
- the benefit of this is questionable, as fine-grained requests will result
in sending huge amounts of data, and upstream is often way slower than
downstream.
possibly timestamp mails with remote arrival date.
maildir: possibly timestamp mails with remote arrival date.
possibly recover from UIDVALIDITY change by resyncing according to message
IDs - this is a pretty common condition with uw-imap.
maybe throw out the ctx->recent stuff - it's used only for one info message.
possibly use ^[[1m to highlight error messages.
consider alternative trash implementation: trash only messages we delete,
and trash before marking them deleted in the mailbox. downside: all other
programs have to do the same. and what if the deleted flag is unset?
items out of scope of purely UID based approach:
- detect message moves between folders
- recovering from UIDVALIDITY change (uw-imap does this a lot)

View File

@ -1,31 +1,32 @@
AC_INIT(src/isync.h)
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(isync, 0.9.2)
AM_INIT_AUTOMAKE(isync, 1.0.0alpha)
AM_MAINTAINER_MODE
AM_PROG_CC_STDC
if test "$GCC" = yes; then
CFLAGS="$CFLAGS -pipe -W -Wall -Wshadow -Wmissing-prototypes"
CFLAGS="$CFLAGS -pipe -W -Wall -Wshadow -Wstrict-prototypes"
fi
AC_CHECK_FUNCS(getopt_long)
AC_CHECK_FUNCS(vasprintf)
AC_CHECK_LIB(socket, socket)
AC_CHECK_LIB(nsl, inet_ntoa)
AC_CHECK_LIB(socket, socket, [SOCK_LIBS="-lsocket"])
AC_CHECK_LIB(nsl, inet_ntoa, [SOCK_LIBS="$SOCK_LIBS -lnsl"])
AC_SUBST(SOCK_LIBS)
ssl=false
AC_ARG_WITH(ssl,
[ --with-ssl=DIR yes/no/OpenSSL installation root [detect]],
AS_HELP_STRING([--with-ssl=DIR], [yes/no/OpenSSL installation root [detect]]),
[ob_cv_with_ssl=$withval])
if test "x$ob_cv_with_ssl" != xno; then
if test -d "$ob_cv_with_ssl/lib"; then
CPFLAGS="$CPPFLAGS -I$ob_cv_with_ssl/include"
LDFLAGS="$LDFLAGS -L$ob_cv_with_ssl/lib"
CPFLAGS="$CPPFLAGS -I$ob_cv_with_ssl/include"
LDFLAGS="$LDFLAGS -L$ob_cv_with_ssl/lib"
fi
AC_CHECK_LIB(crypto, ERR_error_string, [cryptolib=" -lcrypto"])
AC_CHECK_LIB(ssl, SSL_library_init, [
LIBS="-lssl$cryptolib $LIBS"
SSL_LIBS="-lssl$cryptolib"
AC_DEFINE(HAVE_LIBSSL, 1, [Define if you want SSL support])
ssl=true
],[
@ -34,19 +35,29 @@ if test "x$ob_cv_with_ssl" != xno; then
fi
])
fi
AC_SUBST(SSL_LIBS)
AC_CACHE_CHECK(for db_create in -ldb, ac_cv_db_db_create,
[ac_cv_db_dbcreate=no
AC_TRY_LINK([#include <db.h>],
[db_create();],[ac_cv_db_db_create=yes])])
if test $ac_cv_db_db_create=yes; then
LIBS="$LIBS -ldb"
else
AC_MSG_ERROR([Berkley DB not found.
You must install libdb including the respective development files/headers.])
AC_CACHE_CHECK([for Berkley DB 4.2], ac_cv_berkdb4,
[ac_cv_berkdb4=no
AC_TRY_LINK([#include <db.h>],
[DB *db;
db->truncate(db, 0, 0, 0);
db->open(db, 0, "foo", "foo", DB_HASH, DB_CREATE, 0)],
[ac_cv_berkdb4=yes])])
if test "x$ac_cv_berkdb4" = xno; then
AC_MSG_ERROR([Berkley DB 4.2 not found.
You must install libdb4.2 including the respective development files/headers.])
fi
AC_OUTPUT(Makefile src/Makefile isync.spec)
AC_ARG_ENABLE(compat,
AS_HELP_STRING([--disable-compat], [don't include isync compatibility wrapper [no]]),
[ob_cv_enable_compat=$enableval])
if test "x$ob_cv_enable_compat" != xno; then
AC_CHECK_FUNCS(getopt_long)
fi
AM_CONDITIONAL(with_compat, test "x$ob_cv_enable_compat" != xno)
AC_OUTPUT(Makefile src/Makefile src/compat/Makefile isync.spec)
if $ssl; then
AC_MSG_RESULT([

16
debian/NEWS vendored
View File

@ -1,16 +0,0 @@
isync (0.8-1) unstable; urgency=low
IMPORTANT upgrade note:
This version includes a change to the way the UID for each message is
stored in the local mailbox. You need to remove all the messages in your
local folder if you were previously using another version of isync or else
you will end up with duplicate messages on your IMAP server.
A suggested upgrade procedure is to use isync version 0.7 to synchronize
any local changes in isync-managed mailboxes with your IMAP server, and
then remove the contents of the local mailboxes, before upgrading to this
version. Then run isync again to pull down the mail again. You must do
this manually, the Debian package will not do this for you.
-- Joey Hess <joeyh@debian.org> Tue, 29 Oct 2002 13:50:40 -0500

22
debian/README.Debian vendored
View File

@ -1,22 +0,0 @@
A note from isync's web site:
To use this command effectively, you need a mail client that sets the T
(trashed) flag when it deletes a message from a maildir mailbox, instead of
just removing it altogether. Currently, only Mutt 1.3.27 supports this. Without
such a client, isync will refetch the locally deleted messages from the server
since they will never get expunged. Be sure to put
set maildir_trash
in your ~/.muttrc when using Mutt.
isync can be integrated into Mutt fairly easily with a few hooks:
folder-hook ~A bind index $ <sync-mailbox>
folder-hook +maildir 'macro index $ "<sync-mailbox>!isync -e maildir\n"'
where maildir is the name of the local mailbox (or its alias). This works well
so long as you are not modifying the IMAP mailbox outside of Mutt. However, if
you are using another mail program simultaneously Mutt will have the wrong idea
of the local mailbox flags and messages will start disappearing from its index
display (don't worry, they are still on disk).

8
debian/config vendored
View File

@ -1,8 +0,0 @@
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
if [ "$1" = "configure" -a ! -z "$2" ] && \
dpkg --compare-versions "$2" lt 0.8; then
db_input critical isync/upgrade_0.8 || true
db_go || true
fi

27
debian/control vendored
View File

@ -4,21 +4,26 @@ Priority: optional
Maintainer: Nicolas Boullis <nboullis@debian.org>
Uploaders: Nicolas Boullis <nboullis@debian.org>, Theodore Y. Ts'o <tytso@mit.edu>
Standards-Version: 3.6.1
Build-Depends: libssl-dev, debhelper (>= 4.1.16), dpkg-dev (>= 1.9.0), libdb4.0-dev, dpatch
Build-Depends: libssl-dev, debhelper (>= 4.1.16), dpkg-dev (>= 1.9.0), libdb4.2-dev, dpatch
Package: isync
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Suggests: mutt
Description: Synchronize a local maildir with a remote IMAP4 mailbox
A command line application which synchronizes a local maildir-style
mailbox with a remote IMAP4 mailbox, suitable for use in disconnected
mode. Multiple copies of the remote IMAP4 mailbox can be maintained,
and all flags and messages are synchronized.
Description: Synchronize Maildir and IMAP4 mailboxes
A command line application which synchronizes mailboxes; currently
Maildir and IMAP4 mailboxes are supported.
New messages, message deletions and flag changes can be propagated both ways.
It is useful for working in disconnected mode, such as on a laptop or with a
non-permanent internet collection (dIMAP).
.
Features:
* Fast mode for fetching new mail only
* Supports imaps: (port 993) TLS/SSL connections
* Supports STARTTLS (RFC2595) for confidentiality
* Supports NAMESPACE (RFC2342)
* Supports CRAM-MD5 (RFC2095) for authentication
* Fine-grained selection of synchronization operations to perform
* Synchronizes single mailboxes or entire mailbox collections
* Partial mirrors possible: keep only the latest messages locally
* Trash functionality: backup messages before removing them
* IMAP features:
* Supports TLS/SSL via imaps: (port 993) and STARTTLS (RFC2595)
* Supports CRAM-MD5 (RFC2195) for authentication
* Supports NAMESPACE (RFC2342) for simplified configuration
* Pipelining for maximum speed (currently only partially implemented)

View File

@ -1 +0,0 @@
20-cleanup

View File

@ -1,146 +0,0 @@
#! /bin/sh -e
## 20-cleanup.dpatch by Theodore Ts'o <tytso@mit.edu>
##
## DP: Make sure the database store and the imap database is closed
## DP: if isync is aborted.
[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
patch_opts="${patch_opts:--f --no-backup-if-mismatch}"
if [ $# -ne 1 ]; then
echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
exit 1
fi
case "$1" in
-patch) patch $patch_opts -p1 < $0;;
-unpatch) patch $patch_opts -p1 -R < $0;;
*)
echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
exit 1;;
esac
exit 0
@DPATCH@
Problem description:
>> If isync dies in the middle of synchronization, or the network
>> connection breaks while it is synchronizing a mailbox, new messages
>> which are downloaded from the IMAP server do not have their UID saved
>> to the maildir directory. This is REALLY, REALLY BAD, because it
>> means that on the next isync, the downloaded messages are re-uploaded
>> to the imap server, resulting in duplicate messages in the IMAP store.
>>
>> This takes means the network download takes longer, and if the network
>> connection is unrealible, it means it's more likely the the IMAP
>> connection will break, resulting in more duplicate messages being
>> uploaded to the servers. (The first time, 14 messages were uploaded
>> to the server. The second time I re-isynced, 65 messages were
>> uploaded to the server, resulting in some 79 duplicate messages that I
>> had to manually weed out. Grr, grr, grr, grr.)
Problem solution:
Actually, I managed to figure out the solution a while ago, and got
hung up trying to figure out the right way to submit the patches back
to upstream (there's no mailing list that I can find; so do you just
communicate directly with the developers). Anyway, I got busy and I
never had a chance to send the patches a while ago.
This patch is not the best, but it does seem to work. Perhaps a
better approach would be to use the more advanced API's available with
berkdb, so you can actually force a sync to the db/dbm files after
the mail message has been downloaded. Fundamentally, that's the
problem. The id has been added to the db file, but the changes don't
get forced out to disk, so in the case of an abnormal termination of
the program, the id's never get written to disk.
The patch enclosed below solves the problem by establishing a signal
handler, which cleans up in the case of the user typing ^C (after the
network connection has gone away, say because your GSM phone's GPRS
connection has gotten flakey, for example). However, it doesn't solve
the problem in case of an abrupt system crash. In order to address
that problem, the overall program interfaces would have to be changed
to use the newer berkdb interfaces directly, but that would mean
dropping compatibility with the ancient dbm interface. Personally, I
don't think that to be any great loss, but the changes would be much
more invasive, and would require agreement with the upstream
maintainer that this is the right way to go.
Also, for bonus points, perhaps there should be an inactivity timer so
that isync can automatically figure out when the network connection
has gone away, and can do a clean shutdown and exit automatically,
instead of requiring the user to type ^C.
- Ted
Patched files: src/main.c
===================================================================
RCS file: isync-0.9.2/src/RCS/main.c,v
retrieving revision 1.3
diff -u -r1.3 isync-0.9.2/src/main.c
--- isync-0.9.2/src/main.c 2004/01/10 01:13:38 1.3
+++ isync-0.9.2/src/main.c 2004/01/10 01:14:34
@@ -35,6 +35,7 @@
#include <string.h>
#include <ctype.h>
#include <dirent.h>
+#include <signal.h>
int Quiet;
@@ -92,6 +93,22 @@
unsigned int Tag = 0;
char Hostname[256];
int Verbose = 0;
+mailbox_t *CleanupMail = 0;
+imap_t *CleanupImap = 0;
+int CleanupValid = 0;
+
+static void signal_exit(int sig)
+{
+ info("Abort received\n");
+ if (CleanupValid) {
+ info("Aborting, cleaning up\n");
+ if (CleanupMail)
+ maildir_close (CleanupMail);
+ if (CleanupImap)
+ imap_close (CleanupImap);
+ }
+ exit (1);
+}
static void
version (void)
@@ -319,6 +336,10 @@
usage (1);
}
+ signal(SIGTERM, signal_exit);
+ signal(SIGHUP, signal_exit);
+ signal(SIGINT, signal_exit);
+
gethostname (Hostname, sizeof (Hostname));
load_config (config, &o2o);
@@ -410,6 +431,9 @@
ret = 1;
break;
}
+ CleanupValid = 1;
+ CleanupMail = mail;
+ CleanupImap = imap;
info ("Synchronizing\n");
i = (delete || box->delete) ? SYNC_DELETE : 0;
@@ -460,6 +484,8 @@
} while (0);
+ CleanupValid = 0;
+
/* we never sync the same mailbox twice, so close it now */
if (mail)
maildir_close (mail);

View File

@ -1,458 +0,0 @@
#!/bin/sh -e
## 30-aysnc-imap.dpatch by Theodore Y. Ts'o <tytso@mit.edu>
##
## DP: Add the beginnings of asynchronous IMAP support. So far, we only
## DP: support asynchronous flag setting, since that's the easist.
## DP: Eventually we need to support asynchronous message fetches and
## DP: uploads.
if [ $# -ne 1 ]; then
echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
exit 1
fi
[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
patch_opts="${patch_opts:--f --no-backup-if-mismatch}"
case "$1" in
-patch) patch $patch_opts -p1 < $0;;
-unpatch) patch $patch_opts -p1 -R < $0;;
*)
echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
exit 1;;
esac
exit 0
@DPATCH@
diff -urNad /usr/projects/isync/SF-cvs/isync/src/imap.c isync/src/imap.c
--- /usr/projects/isync/SF-cvs/isync/src/imap.c 2004-01-15 14:24:40.000000000 -0500
+++ isync/src/imap.c 2004-01-15 20:36:15.000000000 -0500
@@ -3,6 +3,7 @@
* isync - IMAP4 to maildir mailbox synchronizer
* Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org>
* Copyright (C) 2002-2003 Oswald Buddenhagen <ossi@users.sf.net>
+ * Copyright (C) 2004 Theodore Ts'o <tytso@alum.mit.edu>
*
* 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
@@ -35,13 +36,33 @@
#include <string.h>
#include <ctype.h>
#include <sys/socket.h>
+#include <sys/ioctl.h>
#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#if HAVE_LIBSSL
# include <openssl/err.h>
#endif
+struct imap_cmd {
+ unsigned int tag;
+ char *cmd;
+ int flags;
+ int response;
+ struct imap_cmd *next;
+ int (*complete_fn) (imap_t *imap, struct imap_cmd * cmd);
+};
+
+#define IMAP_FLAG_DONE 0x0001
+
+static struct imap_cmd *in_progress = NULL;
+static int num_in_progress = 0;
+int max_in_progress_high = 50;
+int max_in_progress_low = 10;
+
+static struct imap_cmd *get_cmd_result(imap_t *imap);
+
const char *Flags[] = {
"\\Seen",
"\\Answered",
@@ -199,6 +220,22 @@
return write (sock->fd, buf, len);
}
+static int
+socket_pending(Socket_t *sock)
+{
+ int num = -1;
+
+ if (ioctl(sock->fd, FIONREAD, &num) < 0)
+ return -1;
+ if (num > 0)
+ return num;
+#if HAVE_LIBSSL
+ if (sock->use_ssl)
+ return SSL_pending (sock->ssl);
+#endif
+ return 0;
+}
+
static void
socket_perror (const char *func, Socket_t *sock, int ret)
{
@@ -301,16 +338,20 @@
}
static int
-parse_fetch (imap_t * imap, list_t * list)
+parse_fetch (imap_t * imap, char *cmd)
{
- list_t *tmp;
+ list_t *tmp, *list;
unsigned int uid = 0;
unsigned int mask = 0;
unsigned int size = 0;
message_t *cur;
- if (!is_list (list))
+ list = parse_list (cmd, 0);
+
+ if (!is_list (list)) {
+ free_list(list);
return -1;
+ }
for (tmp = list->child; tmp; tmp = tmp->next)
{
@@ -325,6 +366,7 @@
if (uid < imap->minuid)
{
/* already saw this message */
+ free_list(list);
return 0;
}
else if (uid > imap->maxuid)
@@ -387,6 +429,7 @@
cur->flags = mask;
cur->size = size;
+ free_list(list);
return 0;
}
@@ -415,39 +458,121 @@
}
}
-static int
-imap_exec (imap_t * imap, const char *fmt, ...)
+static void print_imap_command(const char *cmd, FILE *f)
+{
+ if (strncmp(cmd, "LOGIN", 5))
+ fputs(cmd, f);
+ else
+ fputs("LOGIN USERNAME PASSWORD", f);
+}
+
+static struct imap_cmd *issue_imap_cmd(imap_t *imap,
+ const char *fmt, ...)
{
va_list ap;
- char tmp[256];
- char buf[256];
- char *cmd;
- char *arg;
- char *arg1;
- config_t *box;
+ char tmp[1024];
+ char buf[1024];
+ struct imap_cmd *cmd;
int n;
+ cmd = malloc(sizeof(struct imap_cmd));
+ if (!cmd)
+ return NULL;
+
+ cmd->tag = ++Tag;
+ cmd->flags = 0;
+ cmd->response = 0;
+ cmd->complete_fn = 0;
+
va_start (ap, fmt);
vsnprintf (tmp, sizeof (tmp), fmt, ap);
va_end (ap);
- snprintf (buf, sizeof (buf), "%d %s\r\n", ++Tag, tmp);
+ cmd->cmd = malloc(strlen(tmp)+1);
+ if (cmd->cmd)
+ strcpy(cmd->cmd, tmp);
+
+ snprintf (buf, sizeof (buf), "%d %s\r\n", cmd->tag, tmp);
if (Verbose) {
- printf (">>> %s", buf);
+ if (num_in_progress)
+ printf("(%d in progress) ", num_in_progress);
+ printf(">>> %d ", cmd->tag);
+ print_imap_command(tmp, stdout);
+ fputc('\n', stdout);
fflush (stdout);
}
n = socket_write (imap->sock, buf, strlen (buf));
if (n <= 0)
{
socket_perror ("write", imap->sock, n);
- return -1;
+ free(cmd);
+ return NULL;
}
+ cmd->next = in_progress;
+ in_progress = cmd;
+ num_in_progress++;
+ if ((num_in_progress > max_in_progress_high) ||
+ socket_pending(imap->sock)) {
+ while ((num_in_progress > max_in_progress_low) ||
+ socket_pending(imap->sock)) {
+ if (Verbose && socket_pending(imap->sock))
+ printf("(Socket input pending)\n");
+ get_cmd_result(imap);
+ }
+ }
+ return cmd;
+}
+
+static struct imap_cmd *find_imap_cmd(unsigned int tag)
+{
+ struct imap_cmd *cmd, *prev;
+
+ for (prev=NULL, cmd=in_progress; cmd; cmd = cmd->next) {
+ if (tag == cmd->tag) {
+ return cmd;
+ }
+ prev = cmd;
+ }
+ return NULL;
+}
+
+static void dequeue_imap_cmd(unsigned int tag)
+{
+ struct imap_cmd *cmd, *prev;
+
+ for (prev=NULL, cmd=in_progress; cmd; cmd = cmd->next) {
+ if (tag != cmd->tag) {
+ prev = cmd;
+ continue;
+ }
+ if (prev)
+ prev->next = cmd->next;
+ else
+ in_progress = cmd->next;
+ cmd->next = 0;
+ if (cmd->cmd)
+ free(cmd->cmd);
+ cmd->cmd = 0;
+ free(cmd);
+ break;
+ }
+}
+
+static struct imap_cmd *get_cmd_result(imap_t *imap)
+{
+ char *cmd;
+ char *arg;
+ char *arg1;
+ config_t *box;
+ int n;
+ unsigned int tag;
+ struct imap_cmd *cmdp;
for (;;)
{
next:
if (buffer_gets (imap->buf, &cmd))
- return -1;
+ return NULL;
arg = next_arg (&cmd);
if (*arg == '*')
@@ -456,7 +581,7 @@
if (!arg)
{
fprintf (stderr, "IMAP error: unable to parse untagged response\n");
- return -1;
+ return NULL;
}
if (!strcmp ("NAMESPACE", arg))
@@ -528,23 +653,14 @@
imap->recent = atoi (arg);
else if (!strcmp ("FETCH", arg1))
{
- list_t *list;
-
- list = parse_list (cmd, 0);
-
- if (parse_fetch (imap, list))
- {
- free_list (list);
- return -1;
- }
-
- free_list (list);
+ if (parse_fetch (imap, cmd))
+ return NULL;
}
}
else
{
fprintf (stderr, "IMAP error: unable to parse untagged response\n");
- return -1;
+ return NULL;
}
}
#if HAVE_LIBSSL
@@ -555,7 +671,7 @@
if (!imap->cram)
{
fprintf (stderr, "IMAP error, not doing CRAM-MD5 authentication\n");
- return -1;
+ return NULL;
}
resp = cram (cmd, imap->box->user, imap->box->pass);
@@ -568,34 +684,94 @@
if (n <= 0)
{
socket_perror ("write", imap->sock, n);
- return -1;
+ return NULL;
}
n = socket_write (imap->sock, "\r\n", 2);
if (n <= 0)
{
socket_perror ("write", imap->sock, n);
- return -1;
+ return NULL;
}
imap->cram = 0;
}
#endif
- else if ((size_t) atol (arg) != Tag)
- {
- fprintf (stderr, "IMAP error: wrong tag\n");
- return -1;
- }
- else
- {
- arg = next_arg (&cmd);
- parse_response_code (imap, cmd);
- if (!strcmp ("OK", arg))
- return 0;
- return -1;
+ else {
+ tag = (unsigned int) atol (arg);
+ cmdp = find_imap_cmd(tag);
+ if (!cmdp) {
+ fprintf(stderr, "IMAP error: sent unknown tag: %u\n",
+ tag);
+ return NULL;
+ }
+ arg = next_arg (&cmd);
+ if (strncmp("OK", arg, 2)) {
+ if (cmdp->cmd) {
+ fputc('\'', stderr);
+ print_imap_command(cmdp->cmd, stderr);
+ fputc('\'', stderr);
+ } else
+ fprintf(stderr, "tag %u", tag);
+ fprintf(stderr, " returned an error (%s): %s\n",
+ arg, cmd ? cmd : "");
+ cmdp->response = -1;
+ }
+ parse_response_code (imap, cmd);
+ num_in_progress--;
+ cmdp->flags |= IMAP_FLAG_DONE;
+ if (Verbose)
+ printf("Tag %u completed with response %d\n",
+ cmdp->tag, cmdp->response);
+ return cmdp;
}
}
/* not reached */
}
+static void flush_imap_cmds(imap_t *imap)
+{
+ struct imap_cmd *cmdp;
+
+ while (num_in_progress) {
+ if (in_progress && in_progress->flags & IMAP_FLAG_DONE) {
+ dequeue_imap_cmd(in_progress->tag);
+ continue;
+ }
+ cmdp = get_cmd_result(imap);
+ if (!cmdp)
+ printf("Error trying to flush pending imap cmds\n");
+ }
+}
+
+static int
+imap_exec (imap_t * imap, const char *fmt, ...)
+{
+ va_list ap;
+ char tmp[1024];
+ struct imap_cmd *cmdp, *waitp;
+ int result;
+
+ va_start (ap, fmt);
+ vsnprintf (tmp, sizeof (tmp), fmt, ap);
+ va_end (ap);
+
+ cmdp = issue_imap_cmd(imap, "%s", tmp);
+ if (!cmdp)
+ return -1;
+
+ if (cmdp->flags & IMAP_FLAG_DONE)
+ return cmdp->response;
+
+ do {
+ waitp = get_cmd_result(imap);
+ } while (waitp->tag != cmdp->tag);
+
+ result = cmdp->response;
+ dequeue_imap_cmd(cmdp->tag);
+
+ return cmdp->response;
+
+}
+
#ifdef HAVE_LIBSSL
static int
start_tls (imap_t *imap, config_t * cfg)
@@ -1039,6 +1215,7 @@
size_t n;
char buf[1024];
+ flush_imap_cmds(imap);
send_server (imap->sock, "UID FETCH %d BODY.PEEK[]", uid);
for (;;)
@@ -1160,7 +1337,9 @@
(buf[0] != 0) ? " " : "", Flags[i]);
}
- return imap_exec (imap, "UID STORE %d +FLAGS.SILENT (%s)", uid, buf);
+ if (issue_imap_cmd(imap, "UID STORE %d +FLAGS.SILENT (%s)", uid, buf))
+ return 0;
+ return -1;
}
int
@@ -1249,6 +1428,7 @@
strcat (flagstr,") ");
}
+ flush_imap_cmds(imap);
send_server (imap->sock, "APPEND %s%s %s{%d}",
imap->prefix, imap->box->box, flagstr, len + extra);
@@ -1341,6 +1521,7 @@
}
/* didn't receive an APPENDUID */
+ flush_imap_cmds(imap);
send_server (imap->sock,
"UID SEARCH HEADER X-TUID %08lx%05lx%04x",
tv.tv_sec, tv.tv_usec, pid);

View File

@ -1 +0,0 @@
[type: gettext/rfc822deb] templates

74
debian/po/fr.po vendored
View File

@ -1,74 +0,0 @@
#
# Translators, if you are not familiar with the PO format, gettext
# documentation is worth reading, especially sections dedicated to
# this format, e.g. by running:
# info -n '(gettext)PO Files'
# info -n '(gettext)Header Entry'
#
# Some information specific to po-debconf are available at
# /usr/share/doc/po-debconf/README-trans
# or http://www.debian.org/intl/l10n/po-debconf/README-trans
#
# Developers do not need to manually edit POT or PO files.
#
msgid ""
msgstr ""
"Project-Id-Version: isync 0.9.1-1\n"
"POT-Creation-Date: 2003-10-14 21:55+0200\n"
"PO-Revision-Date: 2003-10-27 11:52+0100\n"
"Last-Translator: Christian Perrier <bubulle@debian.org>\n"
"Language-Team: French <debian-l10n-french@lists.debian.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-15\n"
"Content-Transfer-Encoding: 8bit\n"
#. Description
#: ../templates:4
msgid "Abort isync upgrade"
msgstr "Interrompre la mise à jour d'isync"
#. Description
#: ../templates:4
msgid ""
"You are upgrading from an older version of isync that stored the UID of each "
"message in a way that is not compatable with the new version. You need to "
"remove all the messages in local folders downloaded with the old version of "
"isync. Otherwise isync will get confused and upload duplicate messages to "
"the IMAP server."
msgstr ""
"Vous mettez isync à jour à partir d'une version qui utilise une méthode de "
"stockage des identifiants des messages incompatible avec la nouvelle "
"version. Il faut supprimer des répertoires locaux tous les messages "
"téléchargés avec l'ancienne version ; sinon, isync fonctionnera "
"incorrectement et enverra au serveur IMAP des doublons des messages."
#. Description
#: ../templates:4
msgid ""
"A suggested upgrade procedure is to use the isync version 0.7 to synchronize "
"any local changes in isync-managed mailboxes with your IMAP server (if there "
"are any local changes to synchronise), and then remove the contents of the "
"local mailboxes, before upgrading to version 0.8 or above. Then run isync "
"again to pull down the mail again. You must do this manually; the Debian "
"package will not do this for you."
msgstr ""
"La méthode suggérée pour la mise à jour est la suivante : en utilisant "
"la version 0.7 d'isync, synchronisez avec le serveur IMAP les éventuelles modifications locales "
"des boîtes aux lettres gérées par isync ; puis "
"supprimez le contenu des boîtes aux lettres locales. Ensuite, effectuez la "
"mise à jour vers une version supérieure ou égale à 0.8. Enfin, utilisez à "
"nouveau isync pour récupérer les courriels. Vous devez effectuer cette "
"opération vous-même : le paquet Debian ne la fera pas automatiquement."
#. Description
#: ../templates:4
msgid ""
"If you want, the upgrade of isync can be aborted to let you deal with this "
"issue. Or you can just suspend the upgrade or switch to a different virtual "
"console to take care of it. Do not continue past this point before manually "
"resolving this issue!"
msgstr ""
"Si vous le souhaitez, la mise à jour d'isync peut être interrompue pour vous "
"permettre d'effectuer cette opération. Vous pouvez également basculer vers "
"une autre console virtuelle pour vous en occuper, puis reprendre la mise à jour. Ne continuez pas "
"sans faire cette correction."

View File

@ -1,60 +0,0 @@
#
# Translators, if you are not familiar with the PO format, gettext
# documentation is worth reading, especially sections dedicated to
# this format, e.g. by running:
# info -n '(gettext)PO Files'
# info -n '(gettext)Header Entry'
#
# Some information specific to po-debconf are available at
# /usr/share/doc/po-debconf/README-trans
# or http://www.debian.org/intl/l10n/po-debconf/README-trans
#
# Developers do not need to manually edit POT or PO files.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2003-10-14 21:55+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#. Description
#: ../templates:4
msgid "Abort isync upgrade"
msgstr ""
#. Description
#: ../templates:4
msgid ""
"You are upgrading from an older version of isync that stored the UID of each "
"message in a way that is not compatable with the new version. You need to "
"remove all the messages in local folders downloaded with the old version of "
"isync. Otherwise isync will get confused and upload duplicate messages to "
"the IMAP server."
msgstr ""
#. Description
#: ../templates:4
msgid ""
"A suggested upgrade procedure is to use the isync version 0.7 to synchronize "
"any local changes in isync-managed mailboxes with your IMAP server (if there "
"are any local changes to synchronise), and then remove the contents of the "
"local mailboxes, before upgrading to version 0.8 or above. Then run isync "
"again to pull down the mail again. You must do this manually; the Debian "
"package will not do this for you."
msgstr ""
#. Description
#: ../templates:4
msgid ""
"If you want, the upgrade of isync can be aborted to let you deal with this "
"issue. Or you can just suspend the upgrade or switch to a different virtual "
"console to take care of it. Do not continue past this point before manually "
"resolving this issue!"
msgstr ""

19
debian/preinst vendored
View File

@ -1,19 +0,0 @@
#!/bin/sh
set -e
if [ "$1" = "upgrade" ] && dpkg --compare-versions "$2" lt "0.8"; then
# Do not do debconf stuff if debconf is not there.
# I don't want to have to pre-depend on debconf.
if [ -e /usr/share/debconf/confmodule ]; then
. /usr/share/debconf/confmodule
db_get isync/upgrade_0.8
if [ "$RET" = true ]; then
echo "Aborting isync upgrade at your request so you can manually resolve upgrade issue." >&2
exit 1
fi
else
echo "WARNING: Read NEWS.Debian file about manual upgrade issues from isync 0.7." >&2
fi
fi
#DEBHELPER#

3
debian/rules vendored
View File

@ -41,9 +41,8 @@ binary-arch: build install
dh_testroot
dh_installchangelogs ChangeLog
dh_installdocs AUTHORS NEWS README TODO
dh_installexamples isyncrc.sample
dh_installexamples src/mbsyncrc.sample src/compat/isyncrc.sample
dh_installman
dh_installdebconf
dh_strip
dh_compress
dh_fixperms

21
debian/templates vendored
View File

@ -1,21 +0,0 @@
Template: isync/upgrade_0.8
Type: boolean
Default: false
_Description: Abort isync upgrade
You are upgrading from an older version of isync that stored the UID of
each message in a way that is not compatable with the new version. You
need to remove all the messages in local folders downloaded with the old
version of isync. Otherwise isync will get confused and upload duplicate
messages to the IMAP server.
.
A suggested upgrade procedure is to use the isync version 0.7 to
synchronize any local changes in isync-managed mailboxes with your IMAP
server (if there are any local changes to synchronise), and then remove
the contents of the local mailboxes, before upgrading to version 0.8 or
above. Then run isync again to pull down the mail again. You must do this
manually; the Debian package will not do this for you.
.
If you want, the upgrade of isync can be aborted to let you deal with this
issue. Or you can just suspend the upgrade or switch to a different
virtual console to take care of it. Do not continue past this point before
manually resolving this issue!

View File

@ -10,16 +10,16 @@ Packager: Oswald Buddenhagen <ossi@users.sf.net>
BuildRoot: /var/tmp/%{name}-buildroot
%description
isync is a command line utility for synchronizing a remote IMAP mailbox with a
local maildir-style mailbox. This is useful for working in disconnected mode,
such as on a laptop. Modifications made locally and remotely are synchronized
so that no message status flags are lost.
isync is a command line utility which synchronizes mailboxes; currently
Maildir and IMAP4 mailboxes are supported.
New messages, message deletions and flag changes can be propagated both ways.
It is useful for working in disconnected mode, such as on a laptop or with a
non-permanent internet collection (dIMAP).
%prep
%setup
%build
./configure --prefix=/usr
make RPM_OPT_FLAGS="$RPM_OPT_FLAGS"
%install
make DESTDIR=$RPM_BUILD_ROOT install
@ -28,6 +28,11 @@ make DESTDIR=$RPM_BUILD_ROOT install
rm -rf $RPM_BUILD_ROOT
%files
%doc AUTHORS COPYING README TODO ChangeLog isyncrc.sample
%doc AUTHORS COPYING NEWS README TODO ChangeLog src/mbsyncrc.sample src/compat/isyncrc.sample
/usr/bin/isync
/usr/bin/mbsync
/usr/bin/mdconvert
/usr/bin/get-cert
/usr/man/man1/isync.1.gz
/usr/man/man1/mbsync.1.gz
/usr/man/man1/mdconvert.1.gz

View File

@ -1,4 +1,5 @@
.deps
Makefile
Makefile.in
isync
mbsync
mdconvert

View File

@ -1,5 +1,16 @@
bin_PROGRAMS = isync
isync_SOURCES = main.c imap.c sync.c maildir.c list.c cram.c config.c dotlock.c
noinst_HEADERS = isync.h dotlock.h
INCLUDES=$(RPM_OPT_FLAGS)
DISTCLEANFILES = *~
if with_compat
compat_dir = compat
endif
SUBDIRS = $(compat_dir)
bin_PROGRAMS = mbsync mdconvert
mbsync_SOURCES = main.c sync.c config.c util.c drv_imap.c drv_maildir.c
mbsync_LDADD = -ldb $(SSL_LIBS) $(SOCK_LIBS)
noinst_HEADERS = isync.h
mdconvert_SOURCES = mdconvert.c
mdconvert_LDADD = -ldb
man_MANS = mbsync.1 mdconvert.1
EXTRA_DIST = mbsyncrc.sample $(man_MANS)

4
src/compat/.cvsignore Normal file
View File

@ -0,0 +1,4 @@
.deps
Makefile
Makefile.in
isync

8
src/compat/Makefile.am Normal file
View File

@ -0,0 +1,8 @@
bin_PROGRAMS = isync
isync_SOURCES = main.c config.c convert.c util.c
isync_LDADD = -ldb
noinst_HEADERS = isync.h
man_MANS = isync.1
EXTRA_DIST = isyncrc.sample $(man_MANS)

443
src/compat/config.c Normal file
View File

@ -0,0 +1,443 @@
/*
* isync - mbsync wrapper: IMAP4 to maildir mailbox synchronizer
* Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org>
* Copyright (C) 2002-2004 Oswald Buddenhagen <ossi@users.sf.net>
*
* 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
*/
#include "isync.h"
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <pwd.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
static char *
my_strndup( const char *s, size_t nchars )
{
char *r = nfmalloc( sizeof(char) * (nchars + 1) );
memcpy( r, s, nchars );
r[nchars] = 0;
return r;
}
char *
expand_strdup( const char *s )
{
struct passwd *pw;
const char *p, *q;
char *r;
if (*s == '~') {
s++;
if (!*s) {
p = 0;
q = Home;
} else if (*s == '/') {
p = s + 1;
q = Home;
} else {
if ((p = strchr( s, '/' ))) {
r = my_strndup( s, (int)(p - s) );
pw = getpwnam( r );
free( r );
p++;
} else
pw = getpwnam( s );
if (!pw)
return 0;
q = pw->pw_dir;
}
nfasprintf( &r, "%s/%s", q, p ? p : "" );
return r;
} else if (*s != '/' && xmaildir) {
nfasprintf( &r, "%s/%s", xmaildir, s );
return r;
} else
return nfstrdup( s );
}
static int
is_true( const char *val )
{
return
!strcasecmp( val, "yes" ) ||
!strcasecmp( val, "true" ) ||
!strcasecmp( val, "on" ) ||
!strcmp( val, "1" );
}
void
load_config( const char *path, config_t ***stor )
{
config_t **sstor, *cfg;
FILE *fp;
char *p, *cmd, *val;
int line = 0;
char buf[1024];
if (!(fp = fopen( path, "r" ))) {
if (errno != ENOENT)
perror( "fopen" );
return;
}
if (!Quiet && !Debug && !Verbose)
printf( "Reading configuration file %s\n", path );
buf[sizeof(buf) - 1] = 0;
cfg = &global;
while (fgets( buf, sizeof(buf) - 1, fp )) {
p = buf;
cmd = next_arg( &p );
val = next_arg( &p );
line++;
if (!cmd || *cmd == '#')
continue;
if (!val) {
fprintf( stderr, "%s:%d: parameter missing\n", path, line );
continue;
}
if (!strcasecmp( "Mailbox", cmd )) {
if (o2o)
break;
cfg = **stor = nfmalloc( sizeof(config_t) );
*stor = &cfg->next;
memcpy( cfg, &global, sizeof(config_t) );
/* not expanded at this point */
cfg->path = nfstrdup( val );
} else if (!strcasecmp( "OneToOne", cmd )) {
if (boxes) {
forbid:
fprintf( stderr,
"%s:%d: keyword '%s' allowed only in global section\n",
path, line, cmd );
continue;
}
o2o = is_true( val );
} else if (!strcasecmp( "Maildir", cmd )) {
if (boxes)
goto forbid;
maildir = nfstrdup( val );
xmaildir = expand_strdup( val );
} else if (!strcasecmp( "Folder", cmd )) {
if (boxes)
goto forbid;
folder = nfstrdup( val );
} else if (!strcasecmp( "Inbox", cmd )) {
if (boxes)
goto forbid;
inbox = nfstrdup( val );
} else if (!strcasecmp( "Host", cmd )) {
if (!memcmp( "imaps:", val, 6 )) {
val += 6;
cfg->use_imaps = 1;
cfg->port = 993;
cfg->use_sslv2 = 1;
cfg->use_sslv3 = 1;
}
cfg->host = nfstrdup( val );
} else if (!strcasecmp( "User", cmd ))
cfg->user = nfstrdup( val );
else if (!strcasecmp( "Pass", cmd ))
cfg->pass = nfstrdup( val );
else if (!strcasecmp ( "Port", cmd ))
cfg->port = atoi( val );
else if (!strcasecmp ( "Box", cmd ))
cfg->box = nfstrdup( val );
else if (!strcasecmp ( "Alias", cmd )) {
if (!boxes) {
fprintf( stderr,
"%s:%d: keyword 'Alias' allowed only in mailbox specification\n",
path, line );
continue;
}
cfg->alias = nfstrdup( val );
} else if (!strcasecmp( "MaxSize", cmd ))
cfg->max_size = atol( val );
else if (!strcasecmp ( "MaxMessages", cmd ))
cfg->max_messages = atol( val );
else if (!strcasecmp ( "UseNamespace", cmd ))
cfg->use_namespace = is_true( val );
else if (!strcasecmp ( "CopyDeletedTo", cmd ))
cfg->copy_deleted_to = nfstrdup( val );
else if (!strcasecmp ( "Tunnel", cmd ))
cfg->tunnel = nfstrdup( val );
else if (!strcasecmp ( "Expunge", cmd ))
cfg->expunge = is_true( val );
else if (!strcasecmp( "Delete", cmd ))
cfg->delete = is_true( val );
else if (!strcasecmp( "CertificateFile", cmd ))
cfg->cert_file = expand_strdup( val );
else if (!strcasecmp( "RequireSSL", cmd ))
cfg->require_ssl = is_true( val );
else if (!strcasecmp( "UseSSLv2", cmd ))
cfg->use_sslv2 = is_true( val );
else if (!strcasecmp( "UseSSLv3", cmd ))
cfg->use_sslv3 = is_true( val );
else if (!strcasecmp( "UseTLSv1", cmd ))
cfg->use_tlsv1 = is_true( val );
else if (!strcasecmp( "RequireCRAM", cmd ))
cfg->require_cram = is_true( val );
else if (buf[0])
fprintf( stderr, "%s:%d: unknown keyword '%s'\n", path, line, cmd );
}
fclose( fp );
if (o2o) {
if (!global.host && !global.tunnel) {
fprintf( stderr, "Neither Host nor Tunnel given to OneToOne. Aborting.\n" );
exit( 1 );
}
} else
for (sstor = &boxes; (cfg = *sstor); ) {
if (!cfg->host && !cfg->tunnel) {
fprintf( stderr, "Mailbox '%s' has neither Host nor Tunnel. Skipping.\n",
cfg->alias ? cfg->alias : cfg->path );
if (&cfg->next == *stor)
*stor = sstor;
*sstor = cfg->next;
continue;
}
sstor = &cfg->next;
}
}
static const char *
tb( int on )
{
return on ? "yes" : "no";
}
static void
write_imap_server( FILE *fp, config_t *cfg )
{
config_t *pbox;
char *p, *p2;
int hl, a1, a2, a3, a4;
char buf[128];
static int tunnels;
if (cfg->tunnel) {
nfasprintf( (char **)&cfg->server_name, "tunnel%d", ++tunnels );
fprintf( fp, "IMAPAccount %s\nTunnel \"%s\"\n",
cfg->server_name, cfg->tunnel );
} else {
if (sscanf( cfg->host, "%d.%d.%d.%d", &a1, &a2, &a3, &a4 ) == 4)
cfg->server_name = nfstrdup( cfg->host );
else {
p = strrchr( cfg->host, '.' );
if (!p)
hl = nfsnprintf( buf, sizeof(buf), "%s", cfg->host );
else {
hl = nfsnprintf( buf, sizeof(buf), "%.*s", p - cfg->host, cfg->host );
p2 = strrchr( buf, '.' );
if (p2)
hl = sprintf( buf, "%s", p2 + 1 );
}
if (boxes) /* !o2o */
for (pbox = boxes; pbox != cfg; pbox = pbox->next)
if (!memcmp( pbox->server_name, buf, hl + 1 )) {
nfasprintf( (char **)&cfg->server_name, "%s-%d", buf, ++pbox->servers );
goto gotsrv;
}
cfg->server_name = nfstrdup( buf );
cfg->servers = 1;
gotsrv: ;
}
fprintf( fp, "IMAPAccount %s\n", cfg->server_name );
if (cfg->use_imaps)
fprintf( fp, "Host imaps:%s\n", cfg->host );
else
fprintf( fp, "Host %s\n", cfg->host );
fprintf( fp, "Port %d\n", cfg->port );
}
if (cfg->user)
fprintf( fp, "User %s\n", cfg->user );
if (cfg->pass)
fprintf( fp, "Pass \"%s\"\n", cfg->pass );
fprintf( fp, "RequireCRAM %s\nRequireSSL %s\n"
"UseSSLv2 %s\nUseSSLv3 %s\nUseTLSv1 %s\n",
tb(cfg->require_cram), tb(cfg->require_ssl),
tb(cfg->use_sslv2), tb(cfg->use_sslv3), tb(cfg->use_tlsv1) );