On the 'kwallet' branch:
Merge r31194:31237 from trunk.
git-svn-id: https://svn.apache.org/repos/asf/subversion/branches/kwallet@871312 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/Makefile.in b/Makefile.in
index 3b1e922..ccc57d4 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -41,6 +41,7 @@
 SVN_APR_LIBS = @SVN_APR_LIBS@
 SVN_APRUTIL_LIBS = @SVN_APRUTIL_LIBS@
 SVN_DB_LIBS =
+SVN_KWALLET_LIBS = @SVN_KWALLET_LIBS@
 SVN_SERF_LIBS = @SVN_SERF_LIBS@
 SVN_SASL_LIBS = @SVN_SASL_LIBS@
 SVN_ZLIB_LIBS = @SVN_ZLIB_LIBS@
@@ -52,8 +53,9 @@
 libdir = @libdir@
 fsmod_libdir = @libdir@
 ramod_libdir = @libdir@
-neon_libdir = @libdir@
 bdb_libdir = @libdir@
+kwallet_libdir = @libdir@
+neon_libdir = @libdir@
 serf_libdir = @libdir@
 bindir = @bindir@
 includedir = @includedir@
@@ -102,9 +104,9 @@
 LT_CXX_LIBADD = @LT_CXX_LIBADD@
 
 INCLUDES = -I$(top_srcdir)/subversion/include -I$(top_builddir)/subversion \
-           @SVN_NEON_INCLUDES@ \
-           @SVN_APR_INCLUDES@ @SVN_APRUTIL_INCLUDES@ @SVN_SERF_INCLUDES@ \
-           @SVN_SASL_INCLUDES@ @SVN_ZLIB_INCLUDES@
+           @SVN_APR_INCLUDES@ @SVN_APRUTIL_INCLUDES@ \
+           @SVN_KWALLET_INCLUDES@ @SVN_NEON_INCLUDES@ @SVN_SASL_INCLUDES@ \
+           @SVN_SERF_INCLUDES@ @SVN_ZLIB_INCLUDES@
 
 APACHE_INCLUDES = @APACHE_INCLUDES@
 APACHE_LIBEXECDIR = $(DESTDIR)@APACHE_LIBEXECDIR@
@@ -152,6 +154,7 @@
 COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDES)
 COMPILE_CXX = $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES)
 LT_COMPILE = $(LIBTOOL) $(LTFLAGS) --mode=compile $(COMPILE)
+LT_COMPILE_CXX = $(LIBTOOL) $(LTCXXFLAGS) --mode=compile $(COMPILE_CXX)
 
 # special compilation for files destined for mod_dav_svn
 COMPILE_APACHE_MOD = $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS) $(APACHE_INCLUDES) $(INCLUDES) -o $@ -c
@@ -167,6 +170,7 @@
 COMPILE_JAVAHL_JAVAH = $(JAVAH)
 
 LINK = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS) $(LDFLAGS) -rpath $(libdir)
+LINK_CXX = $(LIBTOOL) $(LTCXXFLAGS) --mode=link $(CXX) $(LT_LDFLAGS) $(CXXFLAGS) $(LDFLAGS) -rpath $(libdir)
 
 # special link rule for mod_dav_svn
 LINK_APACHE_MOD = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS) $(LDFLAGS) -rpath $(APACHE_LIBEXECDIR) -avoid-version -module $(APACHE_LDFLAGS)
@@ -186,6 +190,7 @@
 INSTALL_FSMOD_LIB = $(INSTALL_LIB)
 INSTALL_RAMOD_LIB = $(INSTALL_LIB)
 INSTALL_BDB_LIB = $(INSTALL_LIB)
+INSTALL_KWALLET_LIB = $(INSTALL_LIB)
 INSTALL_NEON_LIB = $(INSTALL_LIB)
 INSTALL_SERF_LIB = $(INSTALL_LIB)
 INSTALL_BIN = $(LIBTOOL) --mode=install $(INSTALL)
@@ -560,15 +565,21 @@
 # Implicit rules for creating outputs from input files
 #
 .SUFFIXES:
-.SUFFIXES: .c .lo .o .la-a .la \
+.SUFFIXES: .c .cpp .lo .o .la-a .la \
            .po .spo .mo .rnc .rng .dtd .xsd
 
 .c.o:
 	$(COMPILE) -o $@ -c $<
 
+.cpp.o:
+	$(COMPILE_CXX) -o $@ -c $<
+
 .c.lo:
 	$(LT_COMPILE) -o $@ -c $<
 
+.cpp.lo:
+	$(LT_COMPILE_CXX) -o $@ -c $<
+
 .la.la-a:
 	sed "/library_names/s/'.*'/''/" $< > $@
 
diff --git a/build.conf b/build.conf
index 9f2f531..f5cac0c 100644
--- a/build.conf
+++ b/build.conf
@@ -318,6 +318,15 @@
 msvc-libs = advapi32.lib shfolder.lib ole32.lib
 msvc-export = svn_auth.h svn_base64.h svn_cmdline.h svn_compat.h svn_config.h svn_ctype.h svn_dso.h svn_error.h svn_hash.h svn_io.h svn_md5.h svn_nls.h svn_opt.h svn_mergeinfo.h svn_path.h svn_pools.h svn_props.h svn_quoprint.h svn_sorts.h svn_string.h svn_subst.h svn_time.h svn_types.h svn_user.h svn_utf.h svn_version.h svn_xml.h private\svn_atomic.h private\svn_log.h private\svn_mergeinfo_private.h svn_iter.h private\svn_opt_private.h
 
+# Support for KWallet
+[libsvn_auth_kwallet]
+description = Subversion KWallet Library
+type = lib
+install = kwallet-lib
+path = subversion/libsvn_auth_kwallet
+libs = apr kwallet libsvn_subr
+link-cmd = $(LINK_CXX)
+
 # Low-level grab bag of utilities
 [libsvn_fs_util]
 type = lib
@@ -827,6 +836,10 @@
 type = lib
 external-lib = $(SVN_DB_LIBS)
 
+[kwallet]
+type = lib
+external-lib = $(SVN_KWALLET_LIBS)
+
 [sasl]
 type = lib
 external-lib = $(SVN_SASL_LIBS)
diff --git a/build/generator/gen_base.py b/build/generator/gen_base.py
index 644d223..39bfabc 100644
--- a/build/generator/gen_base.py
+++ b/build/generator/gen_base.py
@@ -353,7 +353,7 @@
     Target.__init__(self, name, options, gen_obj)
     self.install = options.get('install')
     self.compile_cmd = options.get('compile-cmd')
-    self.sources = options.get('sources', '*.c')
+    self.sources = options.get('sources', '*.c *.cpp')
     self.link_cmd = options.get('link-cmd', '$(LINK)')
 
     self.external_lib = options.get('external-lib')
@@ -369,24 +369,26 @@
     # the specified install area depends upon this target
     self.gen_obj.graph.add(DT_INSTALL, self.install, self)
 
-    sources = _collect_paths(self.sources or '*.c', self.path)
+    sources = _collect_paths(self.sources or '*.c' or '*.cpp', self.path)
     sources.sort()
 
-    for src, reldir in sources:
-      if src[-2:] == '.c':
-        objname = src[:-2] + self.objext
-      elif src[-4:] == '.cpp':
-        objname = src[:-4] + self.objext
-      else:
-        raise GenError('ERROR: unknown file extension on ' + src)
+    for srcs, reldir in sources:
+      for src in srcs.split(" "):
+        if glob.glob(src):
+          if src[-2:] == '.c':
+            objname = src[:-2] + self.objext
+          elif src[-4:] == '.cpp':
+            objname = src[:-4] + self.objext
+          else:
+            raise GenError('ERROR: unknown file extension on ' + src)
 
-      ofile = ObjectFile(objname, self.compile_cmd)
+          ofile = ObjectFile(objname, self.compile_cmd)
 
-      # object depends upon source
-      self.gen_obj.graph.add(DT_OBJECT, ofile, SourceFile(src, reldir))
+          # object depends upon source
+          self.gen_obj.graph.add(DT_OBJECT, ofile, SourceFile(src, reldir))
 
-      # target (a linked item) depends upon object
-      self.gen_obj.graph.add(DT_LINK, self.name, ofile)
+          # target (a linked item) depends upon object
+          self.gen_obj.graph.add(DT_LINK, self.name, ofile)
 
     # collect all the paths where stuff might get built
     ### we should collect this from the dependency nodes rather than
diff --git a/configure.ac b/configure.ac
index 31c1dfc..976c7d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -25,6 +25,9 @@
 # Look for a C compiler (before anything can set CFLAGS)
 AC_PROG_CC
 
+# Look for a C++ compiler
+AC_PROG_CXX
+
 # Look for a C pre-processor
 AC_PROG_CPP
 
@@ -278,6 +281,11 @@
 fi
 
 
+dnl pkg-config (required for support for KWallet and GNOME Keyring) -------------------
+
+AC_CHECK_PROG(HAVE_PKG_CONFIG, pkg-config, yes)
+
+
 dnl I18n -------------------
 
 AC_ARG_ENABLE(nls,
@@ -342,6 +350,102 @@
 fi
 AC_SUBST(MSGFMTFLAGS)
 
+
+dnl KWallet -------------------
+
+AC_ARG_WITH(kwallet,
+  [AS_HELP_STRING([[--with-kwallet[=PATH]]],
+                  [Enable use of KWallet (KDE 4) for auth credentials])],
+                  [with_kwallet="$withval"],
+                  [with_kwallet=no])
+
+AC_MSG_CHECKING([whether to look for KWallet])
+if test "$with_kwallet" != "no"; then
+  AC_MSG_RESULT([yes])
+  if test "$enable_shared" = "yes"; then
+    if test "$USE_NLS" = "yes"; then
+      if test "$HAVE_PKG_CONFIG" = "yes"; then
+        AC_MSG_CHECKING([for QtCore, QtDBus, QtGui])
+        if pkg-config --exists QtCore QtDBus QtGui; then
+          AC_MSG_RESULT([yes])
+          if test "$with_kwallet" != "yes"; then
+            AC_MSG_CHECKING([for kde4-config])
+            kde4_config="$with_kwallet/bin/kde4-config"
+            if test -f "$kde4_config" && test -x "$kde4_config"; then
+              HAVE_KDE4_CONFIG="yes"
+              AC_MSG_RESULT([yes])
+            else
+              AC_MSG_RESULT([no])
+            fi
+          else
+            AC_CHECK_PROG(HAVE_KDE4_CONFIG, kde4-config, yes)
+            kde4_config="kde4-config"
+          fi
+          if test "$HAVE_KDE4_CONFIG" = "yes"; then
+            AC_MSG_CHECKING([for KWallet])
+            old_CXXFLAGS="$CXXFLAGS"
+            old_LDFLAGS="$LDFLAGS"
+            old_LIBS="$LIBS"
+            for d in [`pkg-config --cflags QtCore QtDBus QtGui | $GREP -o -- -D[^[:space:]]*`]; do
+              CPPFLAGS="$CPPFLAGS $d"
+            done
+            qt_include_dirs=""
+            for i in [`pkg-config --cflags QtCore QtDBus QtGui | $GREP -o -- -I[^[:space:]]*`]; do
+              qt_include_dirs="$qt_include_dirs $i"
+            done
+            qt_include_dirs="${qt_include_dirs## }"
+            kde_dir="`$kde4_config --prefix`"
+            SVN_KWALLET_INCLUDES="$qt_include_dirs -I$kde_dir/include"
+            SVN_KWALLET_LIBS="-lQtCore -lQtDBus -lQtGui -lkdecore -lkdeui"
+            CXXFLAGS="$CXXFLAGS $SVN_KWALLET_INCLUDES"
+            LIBS="$LIBS $SVN_KWALLET_LIBS"
+            qt_lib_dirs=""
+            for l in [`pkg-config --libs QtCore QtDBus QtGui | $GREP -o -- -L[^[:space:]]*`]; do
+              qt_lib_dirs="$qt_lib_dirs $l"
+            done
+            qt_lib_dirs="${qt_lib_dirs## }"
+            LDFLAGS="$old_LDFLAGS $qt_lib_dirs -L$kde_dir/lib`$kde4_config --libsuffix`"
+            AC_LANG(C++)
+            AC_LINK_IFELSE([
+#include <kwallet.h>
+int main()
+{KWallet::Wallet::walletList();}], with_kwallet=yes, with_kwallet=no)
+            AC_LANG(C)
+            if test "$with_kwallet" = "yes"; then
+              AC_DEFINE([SVN_HAVE_KWALLET], [1],
+                        [Is KWallet support enabled?])
+              AC_MSG_RESULT([yes])
+              CXXFLAGS="$old_CXXFLAGS"
+              LIBS="$old_LIBS"
+            else
+              AC_MSG_RESULT([no])
+              AC_MSG_ERROR([cannot find KWallet])
+            fi
+          else
+            AC_MSG_ERROR([cannot find kde4-config])
+          fi
+        else
+          AC_MSG_RESULT([no])
+          AC_MSG_ERROR([cannot find QtCore, QtDBus, QtGui])
+        fi
+      else
+        AC_MSG_ERROR([cannot find pkg-config])
+      fi
+    else
+      AC_MSG_ERROR([missing support for internationalization])
+    fi
+  else
+    AC_MSG_ERROR([--with-kwallet conflicts with --disable-shared])
+  fi
+else
+  AC_MSG_RESULT([no])
+fi
+AC_SUBST(SVN_KWALLET_INCLUDES)
+AC_SUBST(SVN_KWALLET_LIBS)
+
+
+dnl Build and install rules -------------------
+
 INSTALL_STATIC_RULES="install-bin install-docs"
 INSTALL_RULES="install-fsmod-lib install-ramod-lib install-lib install-include install-static"
 INSTALL_RULES="$INSTALL_RULES $INSTALL_APACHE_RULE"
@@ -367,6 +471,12 @@
   INSTALL_STATIC_RULES="$INSTALL_STATIC_RULES install-serf-lib"
 fi
 
+if test "$with_kwallet" = "yes"; then
+  BUILD_RULES="$BUILD_RULES kwallet-lib"
+  INSTALL_RULES="`echo $INSTALL_RULES | sed 's/install-lib/install-lib install-kwallet-lib/'`"
+  INSTALL_STATIC_RULES="$INSTALL_STATIC_RULES install-kwallet-lib"
+fi
+
 if test "$USE_NLS" = "yes"; then
   BUILD_RULES="$BUILD_RULES locale"
   INSTALL_RULES="$INSTALL_RULES install-locale"
@@ -676,8 +786,6 @@
                   Please specify a suitable JDK using the --with-jdk option.])
   fi
   
-  AC_PROG_CXX
-  
   dnl The temporary directory where libtool compiles libsvnjavahl.
   dnl N.B. objdir is "the name of the directory that contains temporary
   dnl libtool files" and it is set by libtool.m4
diff --git a/subversion/include/private/svn_auth_private.h b/subversion/include/private/svn_auth_private.h
new file mode 100644
index 0000000..528b1a8
--- /dev/null
+++ b/subversion/include/private/svn_auth_private.h
@@ -0,0 +1,99 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Copyright (c) 2008 CollabNet.  All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file svn_auth_private.h
+ * @brief Subversion's authentication system - Internal routines
+ */
+
+#ifndef SVN_AUTH_PRIVATE_H
+#define SVN_AUTH_PRIVATE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* If you add a password type for a provider which stores
+ * passwords on disk in encrypted form, remember to update
+ * svn_auth__simple_save_creds_helper. Otherwise it will be
+ * assumed that your provider stores passwords in plaintext. */
+#define SVN_AUTH__SIMPLE_PASSWORD_TYPE             "simple"
+#define SVN_AUTH__WINCRYPT_PASSWORD_TYPE           "wincrypt"
+#define SVN_AUTH__KEYCHAIN_PASSWORD_TYPE           "keychain"
+#define SVN_AUTH__KWALLET_PASSWORD_TYPE            "kwallet"
+
+/* A function that stores in *PASSWORD (potentially after decrypting it)
+   the user's password.  It might be obtained directly from CREDS, or
+   from an external store, using REALMSTRING and USERNAME as keys.
+   If NON_INTERACTIVE is set, the user must not be involved in the
+   retrieval process.  POOL is used for any necessary allocation. */
+typedef svn_boolean_t (*svn_auth__password_get_t)
+  (const char **password,
+   apr_hash_t *creds,
+   const char *realmstring,
+   const char *username,
+   svn_boolean_t non_interactive,
+   apr_pool_t *pool);
+
+/* A function that stores PASSWORD (or some encrypted version thereof)
+   either directly in CREDS, or externally using REALMSTRING and USERNAME
+   as keys into the external store.  If NON_INTERACTIVE is set, the user
+   must not be involved in the storage process.  POOL is used for any
+   necessary allocation. */
+typedef svn_boolean_t (*svn_auth__password_set_t)
+  (apr_hash_t *creds,
+   const char *realmstring,
+   const char *username,
+   const char *password,
+   svn_boolean_t non_interactive,
+   apr_pool_t *pool);
+
+/* Common implementation for simple_first_creds and
+   windows_simple_first_creds. Uses PARAMETERS, REALMSTRING and the
+   simple auth provider's username and password cache to fill a set of
+   CREDENTIALS. PASSWORD_GET is used to obtain the password value.
+   PASSTYPE identifies the type of the cached password. CREDENTIALS are
+   allocated from POOL. */
+svn_error_t *
+svn_auth__simple_first_creds_helper(void **credentials,
+                                    void **iter_baton,
+                                    void *provider_baton,
+                                    apr_hash_t *parameters,
+                                    const char *realmstring,
+                                    svn_auth__password_get_t password_get,
+                                    const char *passtype,
+                                    apr_pool_t *pool);
+
+/* Common implementation for simple_save_creds and
+   windows_simple_save_creds. Uses PARAMETERS and REALMSTRING to save
+   a set of CREDENTIALS to the simple auth provider's username and
+   password cache. PASSWORD_SET is used to store the password.
+   PASSTYPE identifies the type of the cached password. Allocates from POOL. */
+svn_error_t *
+svn_auth__simple_save_creds_helper(svn_boolean_t *saved,
+                                   void *credentials,
+                                   void *provider_baton,
+                                   apr_hash_t *parameters,
+                                   const char *realmstring,
+                                   svn_auth__password_set_t password_set,
+                                   const char *passtype,
+                                   apr_pool_t *pool);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SVN_AUTH_PRIVATE_H */
diff --git a/subversion/include/svn_auth.h b/subversion/include/svn_auth.h
index cf7d234..4f13348 100644
--- a/subversion/include/svn_auth.h
+++ b/subversion/include/svn_auth.h
@@ -1,7 +1,7 @@
 /**
  * @copyright
  * ====================================================================
- * Copyright (c) 2000-2004 CollabNet.  All rights reserved.
+ * Copyright (c) 2002-2008 CollabNet.  All rights reserved.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution.  The terms
@@ -157,6 +157,10 @@
 
 } svn_auth_provider_object_t;
 
+/** The type of function returning authentication provider. */
+typedef void (*svn_auth_simple_provider_func_t)
+  (svn_auth_provider_object_t **provider,
+   apr_pool_t *pool);
 
 
 /** Specific types of credentials **/
@@ -747,7 +751,6 @@
 #endif /* WIN32 || DOXYGEN */
 
 #if defined(DARWIN) || defined(DOXYGEN)
-
 /**
  * Create and return @a *provider, an authentication provider of type @c
  * svn_auth_cred_simple_t that gets/sets information from the user's
@@ -763,9 +766,9 @@
 void
 svn_auth_get_keychain_simple_provider(svn_auth_provider_object_t **provider,
                                       apr_pool_t *pool);
-
 #endif /* DARWIN || DOXYGEN */
 
+
 /** Create and return @a *provider, an authentication provider of type @c
  * svn_auth_cred_username_t that gets/sets information from a user's
  * ~/.subversion configuration directory.  Allocate @a *provider in
diff --git a/subversion/include/svn_auth_kwallet.h b/subversion/include/svn_auth_kwallet.h
new file mode 100644
index 0000000..a57e1cf
--- /dev/null
+++ b/subversion/include/svn_auth_kwallet.h
@@ -0,0 +1,54 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Copyright (c) 2008 CollabNet.  All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file svn_auth_kwallet.h
+ * @brief Subversion's authentication system - Support for KWallet
+ */
+
+#ifndef SVN_AUTH_KWALLET_H
+#define SVN_AUTH_KWALLET_H
+
+#include <apr_pools.h>
+
+#include "svn_auth.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Create and return @a *provider, an authentication provider of type @c
+ * svn_auth_cred_simple_t that gets/sets information from the user's
+ * ~/.subversion configuration directory.  Allocate @a *provider in
+ * @a pool.
+ *
+ * This is like svn_client_get_simple_provider(), except that the
+ * password is stored in KWallet.
+ *
+ * @since New in 1.6
+ * @note This function actually works only on systems with libsvn_auth_kwallet
+ * and KWallet installed.
+ */
+void
+svn_auth_get_kwallet_simple_provider(svn_auth_provider_object_t **provider,
+                                     apr_pool_t *pool);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SVN_AUTH_KWALLET_H */
diff --git a/subversion/libsvn_auth_kwallet/kwallet.cpp b/subversion/libsvn_auth_kwallet/kwallet.cpp
new file mode 100644
index 0000000..1303a23
--- /dev/null
+++ b/subversion/libsvn_auth_kwallet/kwallet.cpp
@@ -0,0 +1,231 @@
+/*
+ * kwallet.cpp: KWallet provider for SVN_AUTH_CRED_SIMPLE
+ *
+ * ====================================================================
+ * Copyright (c) 2008 CollabNet.  All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+/*** Includes. ***/
+
+#include <apr_pools.h>
+#include "svn_auth.h"
+#include "svn_auth_kwallet.h"
+#include "svn_error.h"
+#include "svn_version.h"
+
+#include "private/svn_auth_private.h"
+
+#include "svn_private_config.h"
+
+#include <QtCore/QString>
+#include <QtGui/QWidget>
+
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kwallet.h>
+
+
+/*-----------------------------------------------------------------------*/
+/* KWallet simple provider, puts passwords in KWallet                    */
+/*-----------------------------------------------------------------------*/
+
+/* Implementation of svn_auth__password_get_t that retrieves
+   the password from KWallet. */
+static svn_boolean_t
+kwallet_password_get(const char **password,
+                     apr_hash_t *creds,
+                     const char *realmstring,
+                     const char *username,
+                     svn_boolean_t non_interactive,
+                     apr_pool_t *pool)
+{
+  if (non_interactive)
+    {
+      return FALSE;
+    }
+
+  if (! KWallet::Wallet::isEnabled())
+    {
+      return FALSE;
+    }
+
+  KCmdLineArgs::init(1,
+                     (char *[1]) { "svn" },
+                     "Subversion",
+                     "subversion",
+                     ki18n("Subversion"),
+                     SVN_VER_NUMBER,
+                     ki18n("Version control system"),
+                     KCmdLineArgs::CmdLineArgKDE);
+  KApplication application;
+  QWidget widget;
+  WId wid = widget.winId();
+  svn_boolean_t ret = FALSE;
+  QString wallet_name = KWallet::Wallet::NetworkWallet();
+  QString folder = QString::fromUtf8("Subversion");
+  QString key =
+    QString::fromUtf8(username) + "@" + QString::fromUtf8(realmstring);
+  if (! KWallet::Wallet::keyDoesNotExist(wallet_name, folder, key))
+    {
+      KWallet::Wallet *wallet =
+        KWallet::Wallet::openWallet(wallet_name,
+                                    wid,
+                                    KWallet::Wallet::Synchronous);
+      if (wallet)
+        {
+          if (wallet->hasFolder(folder))
+            {
+              if (wallet->setFolder(folder))
+                {
+                  QString q_password;
+                  if (wallet->readPassword(key, q_password) == 0);
+                    {
+                      *password = apr_pstrmemdup(pool,
+                                                 q_password.toUtf8().data(),
+                                                 q_password.size());
+                      ret = TRUE;
+                    }
+                }
+            }
+        }
+    }
+  KWallet::Wallet::disconnectApplication(wallet_name,
+                                         QString::fromUtf8("Subversion"));
+  return ret;
+}
+
+/* Implementation of svn_auth__password_set_t that stores
+   the password in KWallet. */
+static svn_boolean_t
+kwallet_password_set(apr_hash_t *creds,
+                     const char *realmstring,
+                     const char *username,
+                     const char *password,
+                     svn_boolean_t non_interactive,
+                     apr_pool_t *pool)
+{
+  if (non_interactive)
+    {
+      return FALSE;
+    }
+
+  if (! KWallet::Wallet::isEnabled())
+    {
+      return FALSE;
+    }
+
+  KCmdLineArgs::init(1,
+                     (char *[1]) { "svn" },
+                     "Subversion",
+                     "subversion",
+                     ki18n("Subversion"),
+                     SVN_VER_NUMBER,
+                     ki18n("Version control system"),
+                     KCmdLineArgs::CmdLineArgKDE);
+  KApplication application;
+  QWidget widget;
+  WId wid = widget.winId();
+  svn_boolean_t ret = FALSE;
+  QString q_password = QString::fromUtf8(password);
+  QString wallet_name = KWallet::Wallet::NetworkWallet();
+  QString folder = QString::fromUtf8("Subversion");
+  KWallet::Wallet *wallet =
+    KWallet::Wallet::openWallet(wallet_name,
+                                wid,
+                                KWallet::Wallet::Synchronous);
+  if (wallet)
+    {
+      if (! wallet->hasFolder(folder))
+        {
+          wallet->createFolder(folder);
+        }
+      if (wallet->hasFolder(folder))
+        {
+          if (wallet->setFolder(folder))
+            {
+              QString key = QString::fromUtf8(username) + "@"
+                + QString::fromUtf8(realmstring);
+              if (wallet->writePassword(key, q_password) == 0)
+                {
+                  ret = TRUE;
+                }
+            }
+        }
+    }
+  KWallet::Wallet::disconnectApplication(wallet_name,
+                                         QString::fromUtf8("Subversion"));
+  return ret;
+}
+
+/* Get cached encrypted credentials from the simple provider's cache. */
+static svn_error_t *
+kwallet_simple_first_creds(void **credentials,
+                           void **iter_baton,
+                           void *provider_baton,
+                           apr_hash_t *parameters,
+                           const char *realmstring,
+                           apr_pool_t *pool)
+{
+  return svn_auth__simple_first_creds_helper(credentials,
+                                             iter_baton,
+                                             provider_baton,
+                                             parameters,
+                                             realmstring,
+                                             kwallet_password_get,
+                                             SVN_AUTH__KWALLET_PASSWORD_TYPE,
+                                             pool);
+}
+
+/* Save encrypted credentials to the simple provider's cache. */
+static svn_error_t *
+kwallet_simple_save_creds(svn_boolean_t *saved,
+                          void *credentials,
+                          void *provider_baton,
+                          apr_hash_t *parameters,
+                          const char *realmstring,
+                          apr_pool_t *pool)
+{
+  return svn_auth__simple_save_creds_helper(saved, credentials,
+                                            provider_baton,
+                                            parameters,
+                                            realmstring,
+                                            kwallet_password_set,
+                                            SVN_AUTH__KWALLET_PASSWORD_TYPE,
+                                            pool);
+}
+
+static const svn_auth_provider_t kwallet_simple_provider = {
+  SVN_AUTH_CRED_SIMPLE,
+  kwallet_simple_first_creds,
+  NULL,
+  kwallet_simple_save_creds
+};
+
+/* Public API */
+extern "C" {
+void
+svn_auth_get_kwallet_simple_provider(svn_auth_provider_object_t **provider,
+                                     apr_pool_t *pool)
+{
+  svn_auth_provider_object_t *po =
+    static_cast<svn_auth_provider_object_t *> (apr_pcalloc(pool, sizeof(*po)));
+
+  po->vtable = &kwallet_simple_provider;
+  *provider = po;
+}
+}
diff --git a/subversion/libsvn_subr/cmdline.c b/subversion/libsvn_subr/cmdline.c
index 82b42fa..5d3bb4f 100644
--- a/subversion/libsvn_subr/cmdline.c
+++ b/subversion/libsvn_subr/cmdline.c
@@ -2,7 +2,7 @@
  * cmdline.c :  Helpers for command-line programs.
  *
  * ====================================================================
- * Copyright (c) 2000-2007 CollabNet.  All rights reserved.
+ * Copyright (c) 2003-2008 CollabNet.  All rights reserved.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution.  The terms
@@ -41,6 +41,7 @@
 #include "svn_error.h"
 #include "svn_nls.h"
 #include "svn_auth.h"
+#include "svn_version.h"
 #include "utf_impl.h"
 #include "svn_config.h"
 
@@ -353,6 +354,38 @@
   return EXIT_FAILURE;
 }
 
+/* Dynamically load authentication simple provider. */
+static svn_boolean_t
+get_auth_simple_provider(svn_auth_provider_object_t **provider,
+                         const char *provider_name,
+                         apr_pool_t *pool)
+{
+  apr_dso_handle_t *dso;
+  apr_dso_handle_sym_t provider_symbol;
+  const char *libname;
+  const char *funcname;
+  svn_boolean_t ret = FALSE;
+  libname = apr_psprintf(pool,
+                         "libsvn_auth_%s-%d.so.0",
+                         provider_name,
+                         SVN_VER_MAJOR);
+  funcname = apr_psprintf(pool,
+                          "svn_auth_get_%s_simple_provider",
+                          provider_name);
+  svn_error_clear(svn_dso_load(&dso, libname));
+  if (dso)
+    {
+      if (! apr_dso_sym(&provider_symbol, dso, funcname))
+        {
+          svn_auth_simple_provider_func_t func;
+          func = (svn_auth_simple_provider_func_t) provider_symbol;
+          func(provider, pool);
+          ret = TRUE;
+        }
+    }
+  return ret;
+}
+
 svn_error_t *
 svn_cmdline_setup_auth_baton(svn_auth_baton_t **ab,
                              svn_boolean_t non_interactive,
@@ -395,6 +428,12 @@
   svn_auth_get_keychain_simple_provider(&provider, pool);
   APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
 #endif
+#ifdef SVN_HAVE_KWALLET
+  if (get_auth_simple_provider(&provider, "kwallet", pool))
+  {
+    APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+  }
+#endif
   if (non_interactive == FALSE)
     {
       /* This provider is odd in that it isn't a prompting provider in
diff --git a/subversion/libsvn_subr/simple_providers.c b/subversion/libsvn_subr/simple_providers.c
index 9622a1b..d4e0443 100644
--- a/subversion/libsvn_subr/simple_providers.c
+++ b/subversion/libsvn_subr/simple_providers.c
@@ -2,7 +2,7 @@
  * simple_providers.c: providers for SVN_AUTH_CRED_SIMPLE
  *
  * ====================================================================
- * Copyright (c) 2000-2004 CollabNet.  All rights reserved.
+ * Copyright (c) 2003-2006, 2008 CollabNet.  All rights reserved.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution.  The terms
@@ -29,6 +29,8 @@
 #include "svn_config.h"
 #include "svn_user.h"
 
+#include "private/svn_auth_private.h"
+
 #include "svn_private_config.h"
 
 /*-----------------------------------------------------------------------*/
@@ -40,14 +42,6 @@
 #define SVN_AUTH__AUTHFILE_PASSWORD_KEY            "password"
 #define SVN_AUTH__AUTHFILE_PASSTYPE_KEY            "passtype"
 
-/* If you add a password type for a provider which stores
- * passwords on disk in encrypted form, remember to update
- * simple_save_creds_helper. Otherwise it will be assumed
- * that your provider stores passwords in plaintext. */
-#define SVN_AUTH__SIMPLE_PASSWORD_TYPE             "simple"
-#define SVN_AUTH__WINCRYPT_PASSWORD_TYPE           "wincrypt"
-#define SVN_AUTH__KEYCHAIN_PASSWORD_TYPE           "keychain"
-
 /* Baton type for the simple provider. */
 typedef struct
 {
@@ -60,34 +54,8 @@
 } simple_provider_baton_t;
 
 
-/* A function that stores PASSWORD (or some encrypted version thereof)
-   either directly in CREDS, or externally using REALMSTRING and USERNAME
-   as keys into the external store.  If NON_INTERACTIVE is set, the user
-   must not be involved in the storage process.  POOL is used for any
-   necessary allocation. */
-typedef svn_boolean_t (*password_set_t)(apr_hash_t *creds,
-                                        const char *realmstring,
-                                        const char *username,
-                                        const char *password,
-                                        svn_boolean_t non_interactive,
-                                        apr_pool_t *pool);
-
-/* A function that stores in *PASSWORD (potentially after decrypting it)
-   the user's password.  It might be obtained directly from CREDS, or
-   from an external store, using REALMSTRING and USERNAME as keys.
-   If NON_INTERACTIVE is set, the user must not be involved in the
-   retrieval process.  POOL is used for any necessary allocation. */
-typedef svn_boolean_t (*password_get_t)(const char **password,
-                                        apr_hash_t *creds,
-                                        const char *realmstring,
-                                        const char *username,
-                                        svn_boolean_t non_interactive,
-                                        apr_pool_t *pool);
-
-
-
-/* Implementation of password_get_t that retrieves the plaintext password
-   from CREDS. */
+/* Implementation of svn_auth__password_get_t that retrieves
+   the plaintext password from CREDS. */
 static svn_boolean_t
 simple_password_get(const char **password,
                     apr_hash_t *creds,
@@ -107,8 +75,8 @@
   return FALSE;
 }
 
-/* Implementation of password_set_t that store the plaintext password
-   in CREDS. */
+/* Implementation of svn_auth__password_set_t that stores
+   the plaintext password in CREDS. */
 static svn_boolean_t
 simple_password_set(apr_hash_t *creds,
                     const char *realmstring,
@@ -128,15 +96,15 @@
    CREDENTIALS. PASSWORD_GET is used to obtain the password value.
    PASSTYPE identifies the type of the cached password. CREDENTIALS are
    allocated from POOL. */
-static svn_error_t *
-simple_first_creds_helper(void **credentials,
-                          void **iter_baton,
-                          void *provider_baton,
-                          apr_hash_t *parameters,
-                          const char *realmstring,
-                          password_get_t password_get,
-                          const char *passtype,
-                          apr_pool_t *pool)
+svn_error_t *
+svn_auth__simple_first_creds_helper(void **credentials,
+                                    void **iter_baton,
+                                    void *provider_baton,
+                                    apr_hash_t *parameters,
+                                    const char *realmstring,
+                                    svn_auth__password_get_t password_get,
+                                    const char *passtype,
+                                    apr_pool_t *pool)
 {
   const char *config_dir = apr_hash_get(parameters,
                                         SVN_AUTH_PARAM_CONFIG_DIR,
@@ -235,15 +203,15 @@
    a set of CREDENTIALS to the simple auth provider's username and
    password cache. PASSWORD_SET is used to store the password.
    PASSTYPE identifies the type of the cached password. Allocates from POOL. */
-static svn_error_t *
-simple_save_creds_helper(svn_boolean_t *saved,
-                         void *credentials,
-                         void *provider_baton,
-                         apr_hash_t *parameters,
-                         const char *realmstring,
-                         password_set_t password_set,
-                         const char *passtype,
-                         apr_pool_t *pool)
+svn_error_t *
+svn_auth__simple_save_creds_helper(svn_boolean_t *saved,
+                                   void *credentials,
+                                   void *provider_baton,
+                                   apr_hash_t *parameters,
+                                   const char *realmstring,
+                                   svn_auth__password_set_t password_set,
+                                   const char *passtype,
+                                   apr_pool_t *pool)
 {
   svn_auth_cred_simple_t *creds = credentials;
   apr_hash_t *creds_hash = NULL;
@@ -292,7 +260,8 @@
        * ahead and store it to disk. Else determine whether saving
        * in plaintext is OK. */
       if (strcmp(passtype, SVN_AUTH__WINCRYPT_PASSWORD_TYPE) == 0
-          || strcmp(passtype, SVN_AUTH__KEYCHAIN_PASSWORD_TYPE) == 0)
+          || strcmp(passtype, SVN_AUTH__KEYCHAIN_PASSWORD_TYPE) == 0
+          || strcmp(passtype, SVN_AUTH__KWALLET_PASSWORD_TYPE) == 0)
         {
           may_save_password = TRUE;
         }
@@ -416,12 +385,14 @@
                    const char *realmstring,
                    apr_pool_t *pool)
 {
-  return simple_first_creds_helper(credentials,
-                                   iter_baton, provider_baton,
-                                   parameters, realmstring,
-                                   simple_password_get,
-                                   SVN_AUTH__SIMPLE_PASSWORD_TYPE,
-                                   pool);
+  return svn_auth__simple_first_creds_helper(credentials,
+                                             iter_baton,
+                                             provider_baton,
+                                             parameters,
+                                             realmstring,
+                                             simple_password_get,
+                                             SVN_AUTH__SIMPLE_PASSWORD_TYPE,
+                                             pool);
 }
 
 /* Save (unencrypted) credentials to the simple provider's cache. */
@@ -433,11 +404,13 @@
                   const char *realmstring,
                   apr_pool_t *pool)
 {
-  return simple_save_creds_helper(saved, credentials, provider_baton,
-                                  parameters, realmstring,
-                                  simple_password_set,
-                                  SVN_AUTH__SIMPLE_PASSWORD_TYPE,
-                                  pool);
+  return svn_auth__simple_save_creds_helper(saved, credentials,
+                                            provider_baton,
+                                            parameters,
+                                            realmstring,
+                                            simple_password_set,
+                                            SVN_AUTH__SIMPLE_PASSWORD_TYPE,
+                                            pool);
 }
 
 static const svn_auth_provider_t simple_provider = {
@@ -703,8 +676,8 @@
   return FALSE;
 }
 
-/* Implementation of password_set_t that encrypts the incoming
-   password using the Windows CryptoAPI. */
+/* Implementation of svn_auth__password_set_t that encrypts
+   the incoming password using the Windows CryptoAPI. */
 static svn_boolean_t
 windows_password_encrypter(apr_hash_t *creds,
                            const char *realmstring,
@@ -750,8 +723,9 @@
   return crypted;
 }
 
-/* Implementation of password_get_t that decrypts the incoming
-   password using the Windows CryptoAPI and verifies its validity. */
+/* Implementation of svn_auth__password_get_t that decrypts
+   the incoming password using the Windows CryptoAPI and verifies its
+   validity. */
 static svn_boolean_t
 windows_password_decrypter(const char **out,
                            apr_hash_t *creds,
@@ -813,12 +787,14 @@
                            const char *realmstring,
                            apr_pool_t *pool)
 {
-  return simple_first_creds_helper(credentials,
-                                   iter_baton, provider_baton,
-                                   parameters, realmstring,
-                                   windows_password_decrypter,
-                                   SVN_AUTH__WINCRYPT_PASSWORD_TYPE,
-                                   pool);
+  return svn_auth__simple_first_creds_helper(credentials,
+                                             iter_baton,
+                                             provider_baton,
+                                             parameters,
+                                             realmstring,
+                                             windows_password_decrypter,
+                                             SVN_AUTH__WINCRYPT_PASSWORD_TYPE,
+                                             pool);
 }
 
 /* Save encrypted credentials to the simple provider's cache. */
@@ -830,11 +806,13 @@
                           const char *realmstring,
                           apr_pool_t *pool)
 {
-  return simple_save_creds_helper(saved, credentials, provider_baton,
-                                  parameters, realmstring,
-                                  windows_password_encrypter,
-                                  SVN_AUTH__WINCRYPT_PASSWORD_TYPE,
-                                  pool);
+  return svn_auth__simple_save_creds_helper(saved, credentials,
+                                            provider_baton,
+                                            parameters,
+                                            realmstring,
+                                            windows_password_encrypter,
+                                            SVN_AUTH__WINCRYPT_PASSWORD_TYPE,
+                                            pool);
 }
 
 static const svn_auth_provider_t windows_simple_provider = {
@@ -884,8 +862,8 @@
  * the same Subversion auth provider-based app run concurrently.
  */
 
-/* Implementation of password_set_t that stores the password
-   in the OS X KeyChain. */
+/* Implementation of svn_auth__password_set_t that stores
+   the password in the OS X KeyChain. */
 static svn_boolean_t
 keychain_password_set(apr_hash_t *creds,
                       const char *realmstring,
@@ -925,8 +903,8 @@
   return status == 0;
 }
 
-/* Implementation of password_get_t that retrieves the password
-   from the OS X KeyChain. */
+/* Implementation of svn_auth__password_get_t that retrieves
+   the password from the OS X KeyChain. */
 static svn_boolean_t
 keychain_password_get(const char **password,
                       apr_hash_t *creds,
@@ -966,12 +944,14 @@
                             const char *realmstring,
                             apr_pool_t *pool)
 {
-  return simple_first_creds_helper(credentials,
-                                   iter_baton, provider_baton,
-                                   parameters, realmstring,
-                                   keychain_password_get,
-                                   SVN_AUTH__KEYCHAIN_PASSWORD_TYPE,
-                                   pool);
+  return svn_auth__simple_first_creds_helper(credentials,
+                                             iter_baton,
+                                             provider_baton,
+                                             parameters,
+                                             realmstring,
+                                             keychain_password_get,
+                                             SVN_AUTH__KEYCHAIN_PASSWORD_TYPE,
+                                             pool);
 }
 
 /* Save encrypted credentials to the simple provider's cache. */
@@ -983,11 +963,13 @@
                            const char *realmstring,
                            apr_pool_t *pool)
 {
-  return simple_save_creds_helper(saved, credentials, provider_baton,
-                                  parameters, realmstring,
-                                  keychain_password_set,
-                                  SVN_AUTH__KEYCHAIN_PASSWORD_TYPE,
-                                  pool);
+  return svn_auth__simple_save_creds_helper(saved, credentials,
+                                            provider_baton,
+                                            parameters,
+                                            realmstring,
+                                            keychain_password_set,
+                                            SVN_AUTH__KEYCHAIN_PASSWORD_TYPE,
+                                            pool);
 }
 
 static const svn_auth_provider_t keychain_simple_provider = {