Gee whiz, all I had to do was rewrite libsvn_ra_dav/session.c, and
suddenly I can do a dav checkout and it NO LONGER pre-emptively asks
me for a username/password. What a Great Thing!
Greg and Joe, this new session.c is working for me. I thought maybe
you could give it a quick look-over. I'm only 90% certain of what I'm
doing. :-)
In the meantime, I now have the tricky task of making ra_dav decide
exactly when to store auth info. I'm not sure where to poke around,
but here's what I want:
* for checkouts, svn_ra_dav__close(session) should call the auth
storage callback. This ensure that the working copy exists
first.
* for updates, the storage should happen *after* ra_dav calls
update_editor->close_edit(). This ensures that any newly-added
directories will get the info during the recursive store.
* for commits, the storage can happen anytime after authentication
succeeds, doesn't really matter.
* for imports, the storage should *never* happen.
I'm a bit worried, because the RA interface doesn't distinguish
between commits and imports; they both use RA->get_commit_editor().
The answer here is that the client can simply set the storage callback
to NULL during an import, which means "don't call me". (I've already
documented that semantic.)
===================================================================
/*
* session.c : routines for maintaining sessions state (to the DAV server)
*
* ====================================================================
* Copyright (c) 2000-2001 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/.
* ====================================================================
*/
#include <apr_pools.h>
#define APR_WANT_STRFUNC
#include <apr_want.h>
#include <apr_general.h>
#include <ne_socket.h>
#include <ne_request.h>
#include <ne_uri.h>
#include <ne_auth.h>
#include "svn_error.h"
#include "svn_ra.h"
#include "svn_version.h"
#include "ra_dav.h"
/* a cleanup routine attached to the pool that contains the RA session
baton. */
static apr_status_t cleanup_session(void *sess)
{
ne_session_destroy(sess);
return APR_SUCCESS;
}
/* A routine that neon calls to 'pull' authentication data from the
neon session. In turn, this routine should 'pull' the data from
the client callbacks as needed. */
static int request_auth(void *userdata, const char *realm,
char **username, char **password)
{
apr_size_t l;
void *a, *auth_baton;
char *uname, *pword;
svn_ra_simple_password_authenticator_t *authenticator = NULL;
svn_ra_session_t *ras = userdata;
/* ### my only worry is that we're not catching any svn_errors from
get_authenticator, get_username, get_password... */
if (! ras->username)
{
/* pull the username from the client */
ras->callbacks->get_authenticator (&a, &auth_baton,
SVN_RA_AUTH_SIMPLE_PASSWORD,
ras->callback_baton, ras->pool);
authenticator = (svn_ra_simple_password_authenticator_t *) a;
authenticator->get_username (&uname, auth_baton, ras->pool);
ras->username = uname;
}
if (! ras->password)
{
if (! authenticator)
{
ras->callbacks->get_authenticator (&a, &auth_baton,
SVN_RA_AUTH_SIMPLE_PASSWORD,
ras->callback_baton, ras->pool);
authenticator = (svn_ra_simple_password_authenticator_t *) a;
}
authenticator->get_password (&pword, auth_baton, ras->pool);
ras->password = pword;
}
/* send a malloc'd copy of the username to neon */
l = strlen(ras->username) + 1;
*username = malloc(l);
memcpy(*username, ras->username, l);
/* send a malloc'd copy of the password to neon */
l = strlen(ras->password) + 1;
*password = malloc(l);
memcpy(*password, ras->password, l);
return 0;
}
/* ### need an ne_session_dup to avoid the second gethostbyname
* call and make this halfway sane. */
static svn_error_t *
svn_ra_dav__open (void **session_baton,
svn_stringbuf_t *repos_URL,
svn_ra_callbacks_t *callbacks,
void *callback_baton,
apr_pool_t *pool)
{
const char *repository = repos_URL->data;
apr_size_t len;
ne_session *sess, *sess2;
struct uri uri = { 0 };
svn_ra_session_t *ras;
/* Sanity check the URI */
if (uri_parse(repository, &uri, NULL)
|| uri.host == NULL || uri.path == NULL)
{
return svn_error_create(SVN_ERR_RA_ILLEGAL_URL, 0, NULL, pool,
"illegal URL for repository");
}
/* Can we initialize network? */
if (sock_init() != 0) {
return svn_error_create(SVN_ERR_RA_SOCK_INIT, 0, NULL, pool,
"network socket initialization failed");
}
/* Create two neon session objects, and set their properties... */
sess = ne_session_create();
sess2 = ne_session_create();
#if 0
/* #### enable this block for debugging output on stderr. */
ne_debug_init(stderr, NE_DBG_HTTP|NE_DBG_HTTPBODY);
#endif
/* ### persistent connection problems in Apache 2.0? seeing some
* "Could not read status line" errors, and connections being closed
* prematurely, etc. Turn them off for now. */
ne_set_persist(sess, 0);
/* make sure we will eventually destroy the session */
apr_pool_cleanup_register(pool, sess, cleanup_session, apr_pool_cleanup_null);
apr_pool_cleanup_register(pool, sess2, cleanup_session, apr_pool_cleanup_null);
ne_set_useragent(sess, "SVN/" SVN_VERSION);
ne_set_useragent(sess2, "SVN/" SVN_VERSION);
/* we want to know if the repository is actually somewhere else */
/* ### not yet: http_redirect_register(sess, ... ); */
if (strcasecmp(uri.scheme, "https") == 0)
{
if (uri.port == -1)
{
uri.port = 443;
}
if (ne_set_secure(sess, 1))
{
return svn_error_create(SVN_ERR_RA_SOCK_INIT, 0, NULL, pool,
"SSL is not supported");
}
ne_set_secure(sess2, 1);
}
#if 0
else
{
/* accept server-requested TLS upgrades... useless feature
* currently since there is no server support yet. */
(void) ne_set_accept_secure_upgrade(sess, 1);
}
#endif
if (uri.port == -1)
{
uri.port = 80;
}
if (ne_session_server(sess, uri.host, uri.port))
{
return svn_error_createf(SVN_ERR_RA_HOSTNAME_LOOKUP, 0, NULL, pool,
"Hostname not found: %s", uri.host);
}
ne_session_server(sess2, uri.host, uri.port);
/* clean up trailing slashes from the URL */
len = strlen(uri.path);
if (len > 1 && uri.path[len - 1] == '/')
uri.path[len - 1] = '\0';
/* Register an authentication 'pull' callback with the neon sessions */
ne_set_server_auth(sess, request_auth, ras);
ne_set_server_auth(sess2, request_auth, ras);
/* Create and fill a session_baton. */
ras = apr_pcalloc(pool, sizeof(*ras));
ras->pool = pool;
ras->root = uri;
ras->sess = sess;
ras->sess2 = sess2;
ras->callbacks = callbacks;
ras->callback_baton = callback_baton;
/* note that ras->username and ras->password are still NULL at this
point. */
*session_baton = ras;
return SVN_NO_ERROR;
}
static svn_error_t *svn_ra_dav__close (void *session_baton)
{
svn_ra_session_t *ras = session_baton;
(void) apr_pool_cleanup_run(ras->pool, ras->sess, cleanup_session);
(void) apr_pool_cleanup_run(ras->pool, ras->sess2, cleanup_session);
return NULL;
}
static const svn_ra_plugin_t dav_plugin = {
"ra_dav",
"Module for accessing a repository via WebDAV (DeltaV) protocol.",
svn_ra_dav__open,
svn_ra_dav__close,
svn_ra_dav__get_latest_revnum,
svn_ra_dav__get_dated_revision,
svn_ra_dav__get_commit_editor,
svn_ra_dav__do_checkout,
svn_ra_dav__do_update
};
svn_error_t *svn_ra_dav_init(int abi_version,
apr_pool_t *pconf,
apr_hash_t *hash)
{
/* ### need a version number to check here... */
if (abi_version != 0)
;
apr_hash_set (hash, "http", APR_HASH_KEY_STRING, &dav_plugin);
#ifdef NEON_SSL
/* Only add this if neon is compiled with SSL support. */
apr_hash_set (hash, "https", APR_HASH_KEY_STRING, &dav_plugin);
#endif
return NULL;
}
/*
* local variables:
* eval: (load-file "../svn-dev.el")
* end:
*/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sat Oct 21 14:36:41 2006