diff -urN dovecot/configure.in dovecot-jh2/configure.in
--- dovecot/configure.in	2006-01-16 21:15:01.000000000 +0100
+++ dovecot-jh2/configure.in	2006-01-19 11:59:34.000000000 +0100
@@ -181,6 +181,15 @@
 	fi,
 	want_mysql=no)
 
+AC_ARG_WITH(sqlite,
+[  --with-sqlite            Build with SQLite3 support],
+	if test x$withval = xno; then
+		want_sqlite=no
+	else
+	want_sqlite=yes
+	fi,
+	want_sqlite=no)
+
 AC_ARG_WITH(ssl,
 [  --with-ssl=[gnutls|openssl] Build with GNUTLS or OpenSSL (default)],
 	if test x$withval = xno; then
@@ -1435,6 +1444,57 @@
 	LIBS=$old_LIBS
 fi
 
+if test $want_sqlite = yes; then
+	# stolen from the mysql code above 
+	for i in /usr /usr/local /usr/local; do
+		for j in include  ""; do
+			if test -r "$i/$j/sqlite3.h"; then
+				MYSQL_INCLUDE=$i/$j
+			fi
+		done
+		for j in lib lib/sqlite3 ""; do
+			if test -f "$i/$j/libsqlite3.so" || test -f "$i/$j/libsqlite3.a"; then
+				MYSQL_LIBDIR=$i/$j
+			fi
+		done
+	done
+
+	old_LIBS=$LIBS
+	if test "$SQLITE_LIBDIR" != ""; then
+		LIBS="$LIBS -L$SQLITE_LIBDIR"
+	fi
+
+	sqlite_lib=""
+	LIBS="$LIBS -lz"
+	AC_CHECK_LIB(sqlite3, sqlite3_open, [
+		sqlite_lib="-lsqlite3 -lz"
+	])
+
+	if test "$sqlite_lib" != ""; then
+		old_CPPFLAGS=$CPPFLAGS
+		if test "$SQLITE_INCLUDE" != ""; then
+			CPPFLAGS="$CPPFLAGS -I $SQLITE_INCLUDE"
+		fi
+		AC_CHECK_HEADER(sqlite3.h, [
+			if test "$SQLITE_INCLUDE" != ""; then
+				SQL_CFLAGS="$SQL_CFLAGS -I$SQLITE_INCLUDE"
+			fi
+			if test "$SQLITE_LIBDIR" != ""; then
+				SQL_LIBS="$SQL_LIBS -L$SQLITE_LIBDIR"
+			fi
+			SQL_LIBS="$SQL_LIBS $sqlite_lib"
+
+			AC_DEFINE(HAVE_SQLITE,, Build with SQLite3 support)
+			have_sql=yes
+			userdb="$userdb sqlite"
+			passdb="$passdb sqlite"
+		])
+		CPPFLAGS=$old_CPPFLAGS
+	fi
+
+	LIBS=$old_LIBS
+fi
+
 if test "$have_sql" = yes; then
 	AC_DEFINE(PASSDB_SQL,, Build with SQL support)
 	AC_DEFINE(USERDB_SQL,, Build with SQL support)
diff -urN dovecot/doc/dovecot-sql.conf dovecot-jh2/doc/dovecot-sql.conf
--- dovecot/doc/dovecot-sql.conf	2005-12-10 21:36:18.000000000 +0100
+++ dovecot-jh2/doc/dovecot-sql.conf	2006-01-19 11:59:52.000000000 +0100
@@ -20,7 +20,7 @@
 #     active CHAR(1) DEFAULT 'Y' NOT NULL
 # );
 
-# Database driver: mysql, pgsql
+# Database driver: mysql, pgsql, sqlite
 #driver = 
 
 # Database connection string. This is driver-specific setting.
@@ -42,9 +42,13 @@
 #   You can connect to UNIX sockets by using host: host=/var/run/mysql.sock
 #   Note that currently you can't use spaces in parameters.
 #
+# sqlite:
+#   The path to the database file.
+#
 # Examples:
 #   connect = host=192.168.1.1 dbname=users
 #   connect = host=sql.example.com dbname=virtual user=virtual password=blarg
+#   connect = /etc/dovecot/authdb.sqlite
 #
 #connect = dbname=virtual user=virtual
 
diff -urN dovecot/src/lib-sql/driver-sqlite.c dovecot-jh2/src/lib-sql/driver-sqlite.c
--- dovecot/src/lib-sql/driver-sqlite.c	1970-01-01 01:00:00.000000000 +0100
+++ dovecot-jh2/src/lib-sql/driver-sqlite.c	2006-01-19 11:59:34.000000000 +0100
@@ -0,0 +1,373 @@
+/* Copyright (C) 2003-2004 Timo Sirainen, Alex Howansky */
+
+#include "lib.h"
+#include "str.h"
+#include "sql-api-private.h"
+
+#ifdef HAVE_SQLITE
+#include <stdlib.h>
+#include <time.h>
+#include <sqlite3.h>
+
+/* retry time if db is busy (in ms) */
+const int sqlite_busy_timeout = 1000;
+
+struct sqlite_db {
+	struct sql_db api;
+
+	pool_t pool;
+	const char *dbfile;
+	sqlite3 *sqlite;
+	unsigned int connected:1;
+	int rc;
+};
+
+struct sqlite_result {
+	struct sql_result api;
+  sqlite3_stmt *stmt;
+  unsigned int cols;
+  const char **row;
+};
+
+struct sqlite_transaction_context {
+	struct sql_transaction_context ctx;
+	unsigned int failed:1;
+};
+
+extern struct sql_result driver_sqlite_result;
+extern struct sql_result driver_sqlite_error_result;
+
+static int driver_sqlite_connect(struct sql_db *_db)
+{
+ 	struct sqlite_db *db = (struct sqlite_db *)_db;
+  
+	if (db->connected)
+		return 1;
+
+  db->rc = sqlite3_open(db->dbfile, &db->sqlite);
+	
+	if (db->rc == SQLITE_OK) {
+		db->connected = TRUE;
+		sqlite3_busy_timeout(db->sqlite, sqlite_busy_timeout);
+		return 1;
+	} else {
+		i_error("sqlite open %s: %s", db->dbfile, sqlite3_errmsg(db->sqlite));
+    sqlite3_close(db->sqlite);
+		return -1;
+	}
+}
+
+static struct sql_db *driver_sqlite_init(const char *connect_string)
+{
+	struct sqlite_db *db;
+	pool_t pool;
+
+	i_assert(connect_string != NULL);
+
+	pool = pool_alloconly_create("sqlite driver", 512);
+	db = p_new(pool, struct sqlite_db, 1);
+	db->pool = pool;
+	db->api = driver_sqlite_db;
+	db->dbfile = p_strdup(db->pool, connect_string);
+	db->connected = FALSE;
+
+	return &db->api;
+}
+
+static void driver_sqlite_deinit(struct sql_db *_db)
+{
+	struct sqlite_db *db = (struct sqlite_db *)_db;
+
+  sqlite3_close(db->sqlite);
+	pool_unref(db->pool);
+}
+
+static enum sql_db_flags
+driver_sqlite_get_flags(struct sql_db *db __attr_unused__)
+{
+  return SQL_DB_FLAG_BLOCKING;
+}
+
+static void driver_sqlite_exec(struct sql_db *_db, const char *query)
+{
+	struct sqlite_db *db = (struct sqlite_db *)_db;
+
+  db->rc = sqlite3_exec(db->sqlite, query, NULL, 0, NULL);
+  if (db->rc != SQLITE_OK)
+  	i_warning("sqlite_exec(%s) = %d (%s)",
+      query, db->rc, sqlite3_errmsg(db->sqlite));
+}
+
+static void driver_sqlite_query(struct sql_db *db, const char *query,
+			       sql_query_callback_t *callback, void *context)
+{
+	struct sql_result *result;
+
+	result = sql_query_s(db, query);
+	result->callback = TRUE;
+	callback(result, context);
+	sql_result_free(result);
+}
+
+static struct sql_result *
+driver_sqlite_query_s(struct sql_db *_db, const char *query)
+{
+	struct sqlite_db *db = (struct sqlite_db *)_db;
+	struct sqlite_result *result;
+	int rc;
+	const char *pzTail;
+
+	result = i_new(struct sqlite_result, 1);
+
+  rc = sqlite3_prepare(db->sqlite, query, -1, &result->stmt, &pzTail);
+
+  if (rc == SQLITE_OK) {
+  	result->api = driver_sqlite_result;
+    result->cols = sqlite3_column_count(result->stmt);
+    result->row = i_new(const char *, result->cols);
+	} else {
+		result->api = driver_sqlite_error_result;
+		result->stmt = NULL;
+		result->cols = 0;
+  }
+	result->api.db = _db;
+
+	return &result->api;
+}
+
+static void driver_sqlite_result_free(struct sql_result *_result)
+{
+	struct sqlite_result *result = (struct sqlite_result *)_result;
+  struct sqlite_db *db = (struct sqlite_db *)	result->api.db;
+  int rc;
+
+	if (result->stmt != NULL)
+	{
+    if ((rc = sqlite3_finalize(result->stmt)) != SQLITE_OK)
+      i_warning("sqlite3_finalize: %d (%s)", rc, sqlite3_errmsg(db->sqlite));
+    i_free(result->row);
+  }
+	i_free(result);
+}
+
+static int driver_sqlite_result_next_row(struct sql_result *_result)
+{
+	struct sqlite_result *result = (struct sqlite_result *)_result;
+
+  switch (sqlite3_step(result->stmt)) {
+  case SQLITE_ROW:
+    return 1;
+  case SQLITE_DONE:
+    return 0;
+  default:
+    return -1;
+  }
+}
+
+static unsigned int
+driver_sqlite_result_get_fields_count(struct sql_result *_result)
+{
+	struct sqlite_result *result = (struct sqlite_result *)_result;
+  return result->cols;
+}
+
+static const char *
+driver_sqlite_result_get_field_name(struct sql_result *_result, unsigned int idx)
+{
+	struct sqlite_result *result = (struct sqlite_result *)_result;
+
+	return sqlite3_column_name(result->stmt, idx);
+}
+
+static int driver_sqlite_result_find_field(struct sql_result *_result,
+					  const char *field_name)
+{
+	struct sqlite_result *result = (struct sqlite_result *)_result;
+	unsigned int i;
+
+	for (i = 0; i < result->cols; ++i) {
+		if (strcmp(sqlite3_column_name(result->stmt, i), field_name) == 0)
+			return i;
+	}
+	
+	return -1;
+}
+
+static const char *
+driver_sqlite_result_get_field_value(struct sql_result *_result,
+				    unsigned int idx)
+{
+	struct sqlite_result *result = (struct sqlite_result *)_result;
+
+  return sqlite3_column_text(result->stmt, idx);
+}
+
+static const char *
+driver_sqlite_result_find_field_value(struct sql_result *result,
+				     const char *field_name)
+{
+	int idx;
+
+	idx = driver_sqlite_result_find_field(result, field_name);
+	if (idx < 0)
+		return NULL;
+	return driver_sqlite_result_get_field_value(result, idx);
+}
+
+static const char *const *
+driver_sqlite_result_get_values(struct sql_result *_result)
+{
+	struct sqlite_result *result = (struct sqlite_result *)_result;
+	unsigned int i;
+
+  for (i = 0; i < result->cols; ++i)
+    result->row[i] = driver_sqlite_result_get_field_value(_result, i);
+  
+	return (const char *const *)result->row;
+}
+
+static const char *driver_sqlite_result_get_error(struct sql_result *_result)
+{
+	struct sqlite_result *result = (struct sqlite_result *)_result;
+  struct sqlite_db *db = (struct sqlite_db *)	result->api.db;
+
+  return sqlite3_errmsg(db->sqlite);
+}
+
+static struct sql_transaction_context *
+driver_sqlite_transaction_begin(struct sql_db *_db)
+{
+	struct sqlite_transaction_context *ctx;
+	struct sqlite_db *db = (struct sqlite_db *)_db;
+
+	ctx = i_new(struct sqlite_transaction_context, 1);
+	ctx->ctx.db = _db;
+	
+	sql_exec(_db, "BEGIN TRANSACTION");
+  if (db->rc != SQLITE_OK)
+    ctx->failed = TRUE;
+
+	return &ctx->ctx;
+}
+
+static void
+driver_sqlite_transaction_rollback(struct sql_transaction_context *_ctx)
+{
+	struct sqlite_transaction_context *ctx =
+		(struct sqlite_transaction_context *)_ctx;
+
+	sql_exec(_ctx->db, "ROLLBACK");
+	i_free(ctx);
+}
+
+static void
+driver_sqlite_transaction_commit(struct sql_transaction_context *_ctx,
+				sql_commit_callback_t *callback, void *context)
+{
+	struct sqlite_transaction_context *ctx =
+		(struct sqlite_transaction_context *)_ctx;
+  struct sqlite_db *db = (struct sqlite_db *) ctx->ctx.db;
+  const char * errmsg;
+
+  if (! ctx->failed) {
+  	sql_exec(_ctx->db, "COMMIT");
+    if (db->rc != SQLITE_OK)
+      ctx->failed = TRUE;
+  }
+
+ 	if (ctx->failed) {
+    errmsg = sqlite3_errmsg(db->sqlite);
+		callback(errmsg, context);
+    driver_sqlite_transaction_rollback(_ctx); /* also does i_free(ctx) */
+	} else {
+		callback(NULL, context);
+    i_free(ctx);
+  }
+}
+
+static int
+driver_sqlite_transaction_commit_s(struct sql_transaction_context *_ctx,
+				  const char **error_r)
+{
+	struct sqlite_transaction_context *ctx =
+		(struct sqlite_transaction_context *)_ctx;
+  struct sqlite_db *db = (struct sqlite_db *) ctx->ctx.db;
+
+	if (ctx->failed) {
+    driver_sqlite_transaction_rollback(_ctx); /* also does i_free(ctx) */
+    return -1;
+	}
+
+	sql_exec(_ctx->db, "COMMIT");
+  *error_r = sqlite3_errmsg(db->sqlite);
+	i_free(ctx);
+	return 0;
+}
+
+static void
+driver_sqlite_update(struct sql_transaction_context *_ctx, const char *query)
+{
+	struct sqlite_transaction_context *ctx =
+		(struct sqlite_transaction_context *)_ctx;
+   struct sqlite_db *db = (struct sqlite_db *) ctx->ctx.db;
+
+	if (ctx->failed)
+		return;
+
+	sql_exec(_ctx->db, query);
+	if (db->rc != SQLITE_OK)
+    ctx->failed = TRUE;
+}
+
+struct sql_db driver_sqlite_db = {
+	"sqlite",
+
+	driver_sqlite_init,
+	driver_sqlite_deinit,
+	driver_sqlite_get_flags,
+	driver_sqlite_connect,
+	driver_sqlite_exec,
+	driver_sqlite_query,
+	driver_sqlite_query_s,
+
+	driver_sqlite_transaction_begin,
+	driver_sqlite_transaction_commit,
+	driver_sqlite_transaction_commit_s,
+	driver_sqlite_transaction_rollback,
+	driver_sqlite_update
+};
+
+struct sql_result driver_sqlite_result = {
+	NULL,
+
+	driver_sqlite_result_free,
+	driver_sqlite_result_next_row,
+	driver_sqlite_result_get_fields_count,
+	driver_sqlite_result_get_field_name,
+	driver_sqlite_result_find_field,
+	driver_sqlite_result_get_field_value,
+	driver_sqlite_result_find_field_value,
+	driver_sqlite_result_get_values,
+	driver_sqlite_result_get_error,
+
+	FALSE
+};
+
+static int
+driver_sqlite_result_error_next_row(struct sql_result *result __attr_unused__)
+{
+  return -1;
+}
+
+struct sql_result driver_sqlite_error_result = {
+  NULL,
+
+  driver_sqlite_result_free,
+  driver_sqlite_result_error_next_row,
+  NULL, NULL, NULL, NULL, NULL, NULL,
+	driver_sqlite_result_get_error,
+
+  FALSE
+};
+
+#endif
diff -urN dovecot/src/lib-sql/Makefile.am dovecot-jh2/src/lib-sql/Makefile.am
--- dovecot/src/lib-sql/Makefile.am	2004-10-21 01:05:57.000000000 +0200
+++ dovecot-jh2/src/lib-sql/Makefile.am	2006-01-19 11:59:34.000000000 +0100
@@ -7,6 +7,7 @@
 libsql_a_SOURCES = \
 	driver-mysql.c \
 	driver-pgsql.c \
+	driver-sqlite.c \
 	sql-api.c
 
 noinst_HEADERS = \
diff -urN dovecot/src/lib-sql/sql-api.c dovecot-jh2/src/lib-sql/sql-api.c
--- dovecot/src/lib-sql/sql-api.c	2006-01-14 19:47:40.000000000 +0100
+++ dovecot-jh2/src/lib-sql/sql-api.c	2006-01-19 11:59:34.000000000 +0100
@@ -10,6 +10,9 @@
 #ifdef HAVE_MYSQL
 	&driver_mysql_db,
 #endif
+#ifdef HAVE_SQLITE
+	&driver_sqlite_db,
+#endif
 	NULL
 };
 
diff -urN dovecot/src/lib-sql/sql-api-private.h dovecot-jh2/src/lib-sql/sql-api-private.h
--- dovecot/src/lib-sql/sql-api-private.h	2005-12-10 19:57:11.000000000 +0100
+++ dovecot-jh2/src/lib-sql/sql-api-private.h	2006-01-19 11:59:34.000000000 +0100
@@ -56,6 +56,7 @@
 
 extern struct sql_db driver_mysql_db;
 extern struct sql_db driver_pgsql_db;
+extern struct sql_db driver_sqlite_db;
 
 extern struct sql_result sql_not_connected_result;
 
diff -urN dovecot/src/master/main.c dovecot-jh2/src/master/main.c
--- dovecot/src/master/main.c	2006-01-15 22:52:44.000000000 +0100
+++ dovecot-jh2/src/master/main.c	2006-01-19 11:59:34.000000000 +0100
@@ -639,6 +639,9 @@
 #ifdef HAVE_PGSQL
 		" postgresql"
 #endif
+#ifdef HAVE_SQLITE
+		" sqlite"
+#endif
 	"\nPassdb: "
 #ifdef PASSDB_BSDAUTH
 		"bsdauth "
