[GME-commit] GMESRC/GME/XmlBackEnd/SVNCode Client.cpp, NONE, 1.1 Client.h, NONE, 1.1 ClientUtil.h, NONE, 1.1 CmdClient.cpp, NONE, 1.1 CmdClient.h, NONE, 1.1 HiClient.cpp, NONE, 1.1 HiClient.h, NONE, 1.1 Path.cpp, NONE, 1.1 Path.h, NONE, 1.1 Pool.cpp, NONE, 1.1 Pool.h, NONE, 1.1 Prompter.cpp, NONE, 1.1 Prompter.h, NONE, 1.1 Revision.cpp, NONE, 1.1 Revision.h, NONE, 1.1 Targets.cpp, NONE, 1.1 Targets.h, NONE, 1.1 ThreadData.cpp, NONE, 1.1 ThreadData.h, NONE, 1.1 Util.cpp, NONE, 1.1 Util.h, NONE, 1.1

Log messages of CVS commits gme-commit at list.isis.vanderbilt.edu
Thu Feb 7 14:01:41 CST 2008


Update of /project/gme-repository/GMESRC/GME/XmlBackEnd/SVNCode
In directory escher:/tmp/cvs-serv27120

Added Files:
	Client.cpp Client.h ClientUtil.h CmdClient.cpp CmdClient.h 
	HiClient.cpp HiClient.h Path.cpp Path.h Pool.cpp Pool.h 
	Prompter.cpp Prompter.h Revision.cpp Revision.h Targets.cpp 
	Targets.h ThreadData.cpp ThreadData.h Util.cpp Util.h 
Log Message:
CmdLineClient and ApiClient files checked in.


CVS User: Zoltan Molnar, ISIS (zolmol)

--- NEW FILE: Path.cpp ---
/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003-2006 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 Path.cpp
 * @brief Implementation of the class Path
 */

#include "StdAfx.h"

#if(USESVN)

#include "Path.h"
#include "svn_path.h"
#include "Util.h"
#include "Pool.h"

/**
* Constructor
*
* @see Path::Path (const std::string &)
* @param path Path string
*/
Path::Path (const char * pi_path)
{
	init (pi_path);
}

/**
* Constructor that takes a string as parameter.
* The string is converted to subversion internal
* representation. The string is copied.
*
* @param path Path string
*/
Path::Path (const std::string & pi_path)
{
	init (pi_path.c_str ());
}

/**
* Copy constructor
*
* @param path Path to be copied
*/
Path::Path (const Path & pi_path)
{
	init (pi_path.c_str ());
}

/**
* initialize the class
*
* @param path Path string
*/
void
Path::init (const char * pi_path)
{
	if(*pi_path == 0)
	{
		m_error_occured = NULL;
		m_path = "";
	}
	else
	{
		m_error_occured = Util::preprocessPath(pi_path, 
			Util::getRequestPool()->pool() );

		m_path = pi_path;
	}
}

/**
* @return Path string
*/
const std::string &
Path::path () const
{
	return m_path;
}

/**
* @return Path string as c string
*/
const char *
Path::c_str() const
{
	return m_path.c_str ();
}

/**
* Assignment operator
*/
Path&
Path::operator=(const Path & pi_path)
{
	init (pi_path.c_str ());
	return *this;
}

svn_error_t *Path::error_occured() const
{
	return m_error_occured;
}

bool Path::isValid(const char *p)
{
	if (p == NULL)
	{
		return false;
	}

	Pool requestPool;
	svn_error_t *err = svn_path_check_valid(p, requestPool.pool());
	if (err == SVN_NO_ERROR)
	{
		return true;
	}
	else
	{
		svn_error_clear(err);
		return false;
	}
}

#endif
--- NEW FILE: Targets.h ---
/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003-2004 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 Targets.h
 * @brief Interface of the class Targets
 */

#pragma once

struct apr_array_header_t;
struct svn_error_t;
class Pool;
#include "Path.h"
#include <vector>

class Targets
{
private:
	std::vector<Path>     m_targets;
	svn_error_t *         m_error_occured;
	bool                  m_doesNotContainsPath;

public:
	Targets(const char *path);
	void add(const char *path);
	~Targets();

	const apr_array_header_t *         array(const Pool & pool);
	svn_error_t *                      error_occured();
	void                               setDoesNotContainsPath();
};

--- NEW FILE: Prompter.cpp ---
/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003 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 Prompter.cpp
 * @brief Implementation of the class Prompter
 */

#include "StdAfx.h"

#if(USESVN)

#include "Prompter.h"
#include "Pool.h"
#include "svn_client.h"
#include "conio.h"
#include "Util.h"
#include "..\\CredentialDlg.h"
#include "..\\CertificateDlg.h"
#include <iostream> // remove this later

extern std::string g_userName;
extern std::string g_passWord;

//static
void PromptImpl::scanfBlind( std::string& ret)
{
	ASSERT(0);
	int k = 0;
	ret.clear();

	// blind scanf like:
	while( 13 != ( k = getch()) && 10 != k)
	{
		if( k != 8)
		{
			std::cout << "*";
			ret += (char) k;
		}
		else
		{
			ret = ret.substr( 0, ret.length() - 1); // remove last one
			std::cout << "Backspace, please continue typing " << std::endl << std::string( ret.length(), '*');
		}
	}
	if( k == 13 || k == 10)
		std::cout << std::endl;
}

GPromptImpl::GPromptImpl()
: m_pWord( "-")
, m_uName( "-")
, m_credsFilled( false)
{
}

GPromptImpl::~GPromptImpl()
{
}

std::string GPromptImpl::username()
{
	// assumes that prompt() was called before, 
	// and the m_uName field was filled already 

	if( m_credsFilled && m_uName.size() > 0 && m_uName != "-")  // the default value
		return m_uName;

	ASSERT(0);
	CCredentialDlg dlg( true, m_uName);
	if( dlg.DoModal() == IDOK)
	{
		m_uName = dlg.name();
		m_pWord = dlg.word();
		m_credsFilled = true;
	}

	return m_uName;
}

std::string GPromptImpl::password()
{
	if( m_credsFilled && m_pWord.size() > 0 && m_pWord != "-")// && m_maySave) // if not the default value ("-") and only if allowed to be saved
		return m_pWord;

	ASSERT(0);
	CCredentialDlg dlg( true, m_uName);
	if( dlg.DoModal() == IDOK)
	{
		m_uName = dlg.name();
		m_pWord = dlg.word();
		m_credsFilled = true;
	}
	return m_pWord;
}

bool GPromptImpl::askYesNo(const char *realm, const char *question, 
                        bool yesIsDefault)
{
	std::string msg = "Realm: " + std::string( realm ? realm:"<norealm>") + "\nQuestion: " + std::string( question ? question :"<noquestion>");
	int res = AfxMessageBox( msg.c_str(), MB_YESNO);
	if( IDYES == res)
		return true;
	else if( IDNO == res)
		return false;
	else
		return yesIsDefault;
}

std::string GPromptImpl::askQuestion(const char *realm, const char *question, 
                                  bool showAnswer, bool maySave)
{
	std::string msg = "Realm: " + std::string( realm ? realm:"<norealm>") + "\nQuestion: " + std::string( question ? question :"<noquestion>");
	if( IDYES == AfxMessageBox( msg.c_str(), MB_YESNO))
		m_answer = "y";
	else
		m_answer = "n";

	m_maySave = false;
	msg = "May save the answer?";
	if( IDYES == AfxMessageBox( msg.c_str(), MB_YESNO))
		m_maySave = true;

	return m_answer;
}

int GPromptImpl::askTrust(const char *question, bool maySave)
{
	std::string q = question; 
	int offs = 0; // make it Windows multiline: \r\n instead of \n
	while( (offs = q.find( '\n', offs + 1)) != -1)
	{
		q.insert( offs, "\r"); offs += 2;
	}
	//if(maySave)
	//{
	//	q += "(R)eject, accept (t)emporarily or accept (p)ermanently?";
	//}
	//else
	//{
	//	q += "(R)eject or accept (t)emporarily?";
	//}

	CCertificateDlg dlg( q, maySave, 0);
	if( dlg.DoModal() == IDOK)
	{
		CCertificateDlg::Response rp = dlg.getResp();
		if( rp == CCertificateDlg::Response::PermanentAccept)
			return Prompter::PrompUserPass::AcceptPermanently;
		else if( rp == CCertificateDlg::Response::TemoraryAccept)
			return Prompter::PrompUserPass::AcceptTemporary;
		else
			return Prompter::PrompUserPass::Reject;
	}
	return Prompter::PrompUserPass::Reject;
}

bool GPromptImpl::prompt(const char *p_realm, const char *p_username, bool p_maySave)
{
	std::string u_name( p_username?p_username: "<<nousername>>");
	std::string msg = "Realm: " + std::string( p_realm?p_realm:"<<norealm>>") + "\n -Username-: '" + u_name + "'\nChange user credentials?";
	if( IDYES == AfxMessageBox( msg.c_str(), MB_YESNO))
	{
		CCredentialDlg dlg( p_maySave, u_name);
		if( dlg.DoModal() == IDOK)
		{
			m_uName = dlg.name();
			m_pWord = dlg.word();
			m_credsFilled = true;
			if( p_maySave)
			{
				m_maySave = dlg.maySave();
				if( m_maySave)
				{
					g_userName = m_uName;
					g_passWord = m_pWord;
					// todo: then save it by using the special set_password
					//
				}
			}
			else
				m_maySave = false;
		}
	}
	else
	{
		//m_uName = p_username;
		//m_pWord = "-";
	}

	return true;
}


//#include "svn_private_config.h"
TextPromptImpl::TextPromptImpl()
: m_pWord( "-")
, m_uName( "-")
{
}

std::string TextPromptImpl::readcnf( const EntryType& p_type)
{
	if( p_type == EntryType::UserName)
	{
		return "username";
	}
	else if( p_type == EntryType::Password)
	{
		return m_pWord.size() > 0 ? m_pWord : "<<no pw?>>";
	}
	return "";
}

TextPromptImpl::~TextPromptImpl()
{
}

std::string TextPromptImpl::username()
{
	// assumes that prompt() was called before, 
	// and the m_uName field was filled already 

	if( m_uName.size() > 0 && m_uName != "-")  // the default value
		return m_uName;

	return readcnf( EntryType::UserName);
}

std::string TextPromptImpl::password()
{
	if( m_pWord.size() > 0 && m_pWord != "-" && m_maySave) // if not the default value ("-") and only if allowed to be saved
		return m_pWord;

	// require it
	std::cout << "Password please : ";
	std::string ret;
	scanfBlind( ret);
	//if( 1 == scanf( "%s", &buff)) // cin eliminates whitespaces
		//ret = buff;
	//ret = readcnf( EntryType::Password);

	if( m_maySave)
	{
		m_pWord = ret;
	}
	return ret;
}

bool TextPromptImpl::askYesNo(const char *realm, const char *question, 
                        bool yesIsDefault)
{
	std::cout << "\nRealm: " << (realm?realm:"<<norealm>>") << "\nQuestion: " << question;
	
	//int k = getch();
	std::string res;
	std::cin >> res;
	int k = res.size() > 0 ? res[0]: ' ';
	if( (char) k == 'n' || (char) k == 'N')
		return false;
	else if( (char) k == 'y' || (char) k == 'Y')
		return true;
	else // if yesIsDefault return true = Yes, if !yesisDefault return false = No
		return yesIsDefault;
}

std::string TextPromptImpl::askQuestion(const char *realm, const char *question, 
                                  bool showAnswer, bool maySave)
{
	std::cout << "\nRealm: " << (realm?realm:"<norealm>") << "\nQuestion: " << (question?question:"<noquestion>");
	std::string ret;
	std::cin >> ret;
	m_answer = ret;
    if(maySave)
        m_maySave = askYesNo(realm, "May save the answer ?", true);
    else
        m_maySave = false;

	return m_answer;
}

int TextPromptImpl::askTrust(const char *question, bool maySave)
{
	std::string q = question;
	if(maySave)
	{
		q += "(R)eject, accept (t)emporarily or accept (p)ermanently?";
	}
	else
	{
		q += "(R)eject or accept (t)emporarily?";
	}
	std::string s_answer = askQuestion( NULL, q.c_str(), true, false);
	char answer = (s_answer.size() > 0)? s_answer[0]: ' ';
	if( answer == 't' || answer == 'T')
	{
		return 
			Prompter::PrompUserPass::AcceptTemporary;
	}
	else if(maySave && (answer == 'p' || answer == 'P'))
	{
		return 
			Prompter::PrompUserPass::AcceptPermanently;
	}
	else
		return Prompter::PrompUserPass::Reject;
}

bool TextPromptImpl::prompt(const char *p_realm, const char *p_username, bool p_maySave)
{
	// aren't we too ambitious here
	std::cout << "\nRealm: " << (p_realm?p_realm:"<<norealm>>") << std::endl << "-Username-: '" << (p_username?p_username: "<<zerousernameptr>>") << "'";
	if( askYesNo( p_realm, "Change user name?", false))
	{
		std::cout << "Username please : ";
		std::cin >> m_uName; // what about storing retv somewhere?

		std::cout << "Password for '" << m_uName << "' please : ";
		scanfBlind( m_pWord);

		if( p_maySave)
		{
			m_maySave = askYesNo( p_realm, "May save the answer ?", true);
			if( m_maySave)
			{
				g_userName = m_uName;
				g_passWord = m_pWord;
				// todo: then save it by using the special set_password
				//
			}
		}
		else
			m_maySave = false;

		return true;
	}
	else
		m_uName = p_username;

	return true;
}

//**************************************
//*************************************

Prompter::Prompter( PromptImpl* p_prompter)
{
    m_impl = p_prompter;
}

Prompter::~Prompter()
{
    if( m_impl)
	{
		delete m_impl;
	}
}

Prompter* Prompter::makePrompter( PromptImpl* p_promptImpl)
{
    return new Prompter( p_promptImpl);
}

svn_auth_provider_object_t*   Prompter::getProviderSimple()
{
    apr_pool_t *pool = Util::getRequestPool()->pool();
    svn_auth_provider_object_t *provider;
    svn_client_get_simple_prompt_provider (&provider,
                                           CallbackHelpers::simple_prompt, /* prompt function */
                                           m_impl,                         /* prompt baton    */
                                           2, /* retry limit */
                                           pool);

    return provider;
}

svn_auth_provider_object_t*   Prompter::getProviderUsername()
{
    apr_pool_t *pool = Util::getRequestPool()->pool();
    svn_auth_provider_object_t *provider;
    svn_client_get_username_prompt_provider (&provider,
                                             CallbackHelpers::username_prompt, /* prompt function */
                                             m_impl,                           /* prompt baton    */
                                             2, /* retry limit */
                                             pool);

    return provider;
}

svn_auth_provider_object_t*   Prompter::getProviderServerSSLTrust()
{
    apr_pool_t *pool = Util::getRequestPool()->pool();
    svn_auth_provider_object_t *provider;
    svn_client_get_ssl_server_trust_prompt_provider
		(&provider, CallbackHelpers::ssl_server_trust_prompt, m_impl, pool);

    return provider;
}

svn_auth_provider_object_t*   Prompter::getProviderClientSSL()
{
    apr_pool_t *pool = Util::getRequestPool()->pool();
    svn_auth_provider_object_t *provider;
    svn_client_get_ssl_client_cert_prompt_provider
          (&provider, CallbackHelpers::ssl_client_cert_prompt, m_impl, 2, /* retry limit */pool);

    return provider;
}

svn_auth_provider_object_t*   Prompter::getProviderClientSSLPassword()
{
    apr_pool_t *pool = Util::getRequestPool()->pool();
    svn_auth_provider_object_t *provider;
    svn_client_get_ssl_client_cert_pw_prompt_provider
          (&provider, CallbackHelpers::ssl_client_cert_pw_prompt, m_impl, 2 /* retry limit */,
                                                         pool);

    return provider;
}

// *********************************************************************************************
// *********************** C A L L B A C K   H E L P E R   M E T H O D S ***********************
// *********************************************************************************************

// static, callback
svn_error_t *Prompter::CallbackHelpers::simple_prompt(svn_auth_cred_simple_t **cred_p, 
                                     void *baton,
                                     const char *realm, const char *username, 
                                     svn_boolean_t may_save,
                                     apr_pool_t *pool)
{
	// SVN_AUTH_CRED_SIMPLE [svn.simple] credentials ( svn_auth_cred_simple_t ) comprise of
	// const char *username;
	// const char *password;
	// svn_boolean_t may_save;
	// This latter indicates if the credentials may be saved (to disk). 
	// For example, a GUI prompt implementation with a remember password
	// checkbox shall set may_save to TRUE if the checkbox is checked.

	PromptImpl *that = (PromptImpl*)baton;
	svn_auth_cred_simple_t *ret = (svn_auth_cred_simple_t*)apr_pcalloc(pool, sizeof(*ret));

	// show dlg
	if(!that->prompt( realm, username, may_save ? true : false))
		return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog");

	// retrieve uname
	std::string user = that->username();
	if(user == "")
		return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog");

	// duplicate uname into return variable
	ret->username = apr_pstrdup( pool, user.c_str());

	// retrieve passwrd
	std::string pass = that->password();
	if(pass == "")
		return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog");

	// duplicate password into return variable
	ret->password  = apr_pstrdup( pool, pass.c_str());

	// retrieve may_save option
	ret->may_save = that->m_maySave;

	*cred_p = ret;
	return SVN_NO_ERROR;
}

// static, callback
svn_error_t*   Prompter::CallbackHelpers::username_prompt(svn_auth_cred_username_t **cred_p, 
                                       void *baton,
                                       const char *realm, 
                                       svn_boolean_t may_save, 
                                       apr_pool_t *pool)
{
	// SVN_AUTH_CRED_USERNAME [svn.username] credentials ( svn_auth_cred_username_t ) comprise of
	// const char *username;
	// svn_boolean_t may_save;
	// This latter indicates if the credentials may be saved (to disk). 
	// For example, a GUI prompt implementation with a remember username
	// checkbox shall set may_save to TRUE if the checkbox is checked.

	PromptImpl *that = (PromptImpl*)baton;
	svn_auth_cred_username_t *ret = (svn_auth_cred_username_t*)apr_pcalloc(pool, sizeof(*ret));

	// show question
	std::string user = that->askQuestion( realm, "[svn.username] Username: ", true, may_save ? true : false);
	if(user == "")
		return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog");

	// duplicate uname into return variable
	ret->username = apr_pstrdup(pool,user.c_str());

	// retrieve may_save option
	ret->may_save = that->m_maySave;

	*cred_p = ret;
	return SVN_NO_ERROR;
}

// static, callback
svn_error_t*   Prompter::CallbackHelpers::ssl_server_trust_prompt(
                              svn_auth_cred_ssl_server_trust_t **cred_p,
                              void *baton,
                              const char *realm,
                              apr_uint32_t failures,
                              const svn_auth_ssl_server_cert_info_t *cert_info,
                              svn_boolean_t may_save,
                               apr_pool_t *pool)
{
	PromptImpl *that = (PromptImpl*)baton;
	svn_auth_cred_ssl_server_trust_t *ret = (svn_auth_cred_ssl_server_trust_t*)apr_pcalloc(pool, sizeof(*ret));

	std::string question = "Error validating server certificate for ";
	question += realm;
	question += ":\n";

	if(failures & SVN_AUTH_SSL_UNKNOWNCA)
	{
		question += " - Unknown certificate issuer\n";
		question += "   Fingerprint: ";
		question += cert_info->fingerprint;
		question += "\n";
		question += "   Distinguished name: ";
		question += cert_info->issuer_dname;
		question += "\n";
	}

	if(failures & SVN_AUTH_SSL_CNMISMATCH)
	{
		question += " - Hostname mismatch (";
		question += cert_info->hostname;
		question += ")\n";
	}

	if(failures & SVN_AUTH_SSL_NOTYETVALID)
	{
		question += " - Certificate is not yet valid\n";
		question += "   Valid from ";
		question += cert_info->valid_from;
		question += "\n";
	}

	if(failures & SVN_AUTH_SSL_EXPIRED)
	{
		question += " - Certificate is expired\n";
		question += "   Valid until ";
		question += cert_info->valid_until;
		question += "\n";
	}

	switch( that->askTrust( question.c_str(), may_save ? true : false))
	{
	case PrompUserPass::AcceptTemporary:
		*cred_p = ret;
		ret->may_save = FALSE;
		break;
	case PrompUserPass::AcceptPermanently:
		*cred_p = ret;
		ret->may_save = TRUE;
		ret->accepted_failures = failures;
		break;
	default:
		*cred_p = NULL;
	}
	return SVN_NO_ERROR;
}

// static, callback
svn_error_t*   Prompter::CallbackHelpers::ssl_client_cert_prompt(
                                     svn_auth_cred_ssl_client_cert_t **cred_p,
                                     void *baton, 
                                     const char *realm, 
                                     svn_boolean_t may_save,
                                     apr_pool_t *pool)
{
	PromptImpl *that = (PromptImpl*)baton;
	svn_auth_cred_ssl_client_cert_t *ret = (svn_auth_cred_ssl_client_cert_t*)apr_pcalloc(pool, sizeof(*ret));

	std::string cert_file = that->askQuestion( realm, "client certificate filename: ", true, may_save ? true : false);
	if(cert_file == "")
		return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog");

	ret->cert_file = apr_pstrdup(pool, cert_file.c_str());
	ret->may_save = that->m_maySave;
	*cred_p = ret;

	return SVN_NO_ERROR;
}

// static, callback
svn_error_t*   Prompter::CallbackHelpers::ssl_client_cert_pw_prompt(
                                  svn_auth_cred_ssl_client_cert_pw_t **cred_p,
                                  void *baton, 
                                  const char *realm, 
                                  svn_boolean_t may_save,
                                  apr_pool_t *pool)
{
	PromptImpl *that = (PromptImpl*)baton;
	svn_auth_cred_ssl_client_cert_pw_t *ret = (svn_auth_cred_ssl_client_cert_pw_t*)apr_pcalloc(pool, sizeof(*ret));

	std::string info = that->askQuestion( realm, "client certificate passphrase: ", false, may_save ? true : false);
	if(info == "")
		return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog");

	ret->password = apr_pstrdup( pool, info.c_str());
	ret->may_save = that->m_maySave;
	*cred_p = ret;

	return SVN_NO_ERROR;
}

// *********************************************************************************************
//  E O F
// *********************************************************************************************

#endif
--- NEW FILE: Revision.h ---
/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003-2004 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 Revision.h
 * @brief Interface of the class Revision
 */


#pragma once

#include "svn_opt.h"

class Revision
{
private:
	svn_opt_revision_t m_revision;

public:
	static const svn_opt_revision_kind START;
	static const svn_opt_revision_kind HEAD;

	Revision();
	Revision( bool p_head /*= false*/, bool p_one /*= false*/);
	Revision( const svn_opt_revision_kind p_kind);
	~Revision();

	const svn_opt_revision_t *revision() const;

};

--- NEW FILE: Path.h ---
/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003-2006 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 Path.h
 * @brief Interface of the C++ class Path.
 */

#pragma once

#include <string>
struct svn_error_t;

/**
* Encapsulation for Subversion Path handling
*/
class Path  
{
private:
	// the path to be stored
	std::string m_path;

	svn_error_t *m_error_occured;

	/**
	* initialize the class
	*
	* @param pi_path Path string
	*/
	void init(const char * pi_path);

public:
	/**
	* Constructor that takes a string as parameter.
	* The string is converted to subversion internal
	* representation. The string is copied.
	*
	* @param pi_path Path string
	*/
	Path(const std::string & pi_path = "");

	/**
	* Constructor
	*
	* @see Path::Path (const std::string &)
	* @param pi_path Path string
	*/
	Path(const char * pi_path);

	/**
	* Copy constructor
	*
	* @param pi_path Path to be copied
	*/
	Path(const Path & pi_path);

	/**
	* Assignment operator
	*/
	Path& operator=(const Path&);

	/**
	* @return Path string
	*/
	const std::string &
		path() const;

	/**
	* @return Path string as c string
	*/
	const char * 
		c_str() const;

	svn_error_t * 
		error_occured() const;

	/**
	* Returns whether @a path is non-NULL and passes the @c
	* svn_path_check_valid() test.
	*
	* @since 1.4.0
	*/
	static bool isValid(const char *path);
};

--- NEW FILE: Client.h ---
#pragma once

#include "Revision.h"
#include "Targets.h"
#include "svn_client.h"
#include "Prompter.h"
#include "ClientUtil.h"

// class mimicing subversion/bindings/java/javahl/native/svnclient.cpp
class CommitMessage;

class Client
{
public:
	//Client(void);
	Client( const std::string& p_userName, const std::string& p_passWord);
	virtual ~Client(void);

protected:
	// not so public: signaled by the sub_ prefix
	long sub_checkout(const char *moduleName, const char *destPath, 
		Revision &revision, Revision &pegRevision, 
		bool recurse, bool ignoreExternals);

	typedef std::vector< long> UPDATE_RES;

	bool sub_update(Targets &targets, Revision &revision, bool recurse,
		bool ignoreExternals, UPDATE_RES& res);

	long sub_commit(Targets &targets, const char *message, bool recurse,
		bool noUnlock);
	long sub_commit3(Targets &targets, const char *message, bool recurse,
		bool noUnlock);

	bool sub_cleanup( const char *path);
	bool sub_resolved(const char *path, bool recurse);

	bool sub_propertySet(const char *path, const char *name, 
		const char *value, bool recurse, bool force);

	bool sub_lock(Targets &targets, const char *comment, 
		bool force);

	bool sub_unlock(Targets &targets);

	bool sub_info2( const char * p_path, Revision &revision, Revision &pegRevision, bool p_recurse, ClientUtil::InfoHelp::InfoVec& p_infoVect, bool p_suppressIllegalUrlErrorMsg);
	bool info2Qck ( const char * p_path, bool p_recursive, ClientUtil::InfoHelp::InfoVec& p_infoVect, bool p_suppressErrorMsg = false);

	int sub_add( const char *p_pathOrUrl, bool rec);
	

	long sub_mkdir( Targets& targets, const char * p_msg);
	long sub_mkdir2( Targets& targets, const char * p_msg);

	svn_client_ctx_t * getContext(const char *p_message);

	//void * getCommitMessageBaton(const char *message);


	ClientUtil::NotifyHelp *m_notify2;
	void notification2( ClientUtil::NotifyHelp *notify2);

    Prompter *m_prompter;
	void setPrompt(Prompter *prompter);

	ClientUtil::CommitHelp::MsgBuilder * m_commitMessageBuilder;
	void setCommitMessageHandler( ClientUtil::CommitHelp::MsgBuilder * p_commitMessageBuilder);

	std::string m_userName;
	std::string m_passWord;
	std::string m_configDir;

	void cancelOperation();


	ClientUtil::StatusInfo sub_single_status(const char *path, bool onServer);
	ClientUtil::StatusExtInfoVec sub_extended_status( const char * p_path, bool p_onServer);

public:
	bool m_cancelOperation; // client can signal her patience is not endless
	                        // accessed from batons as well
};


--- NEW FILE: HiClient.h ---
#pragma once
//#include "SvnConfig.h"

#if(USESVN)
#include "Client.h"
#endif

#if(USESVN)
class HiClient : protected Client // implementation inherited from Client
#else
class HiClient
#endif
{
	bool m_logEnabled;
	void log( const std::string& p_command, const std::string& p_parameter);
public:
	HiClient( const std::string& p_userName, const std::string& p_passWord);
	~HiClient(void);

	void setLog( bool p_val);

	// public :
	bool isItUs              ( const std::string& p_userName);
	bool isLocked            ( const std::string& p_path);
	bool isLockedByUs        ( const std::string& p_path);
	bool isLockedByOthers    ( const std::string& p_path);
	bool isLockedByWhom      ( const std::string& p_path, bool * p_us, bool * p_else);
	//bool isLockedBy          ( const char * p_path, char * p_res, int p_len);
	bool isLockedByUser      ( const std::string& p_path, std::string& p_holder);
	bool isVersioned         ( const std::string& p_path, bool p_isADir = false, bool p_suppressErrorMsg = false);
	bool info                ( const std::string& p_url,  bool p_recursive, bool p_assembleInfoMsg, std::string& p_infoMsg, std::string& p_author, std::string& p_lockOwner);
	bool status              ( const std::string& p_path, bool p_assembleStatusMsg, std::string& p_statMsg);
	bool cleanup             ( const std::string& p_path);
	bool resolve             ( const std::string& p_path, bool p_recursive);

	bool tryLock             ( const std::string& p_path);
	bool unLock              ( const std::string& p_path);
	bool lockableProp        ( const std::string& p_path);
	bool getLatest           ( const std::string& p_path);
	bool lightCheckOut       ( const std::string& p_path, const std::string& p_localDir); // this is used as svn checkout (in contrast with lock+checkout as in other versioning systems)
	bool commitAll           ( const std::string& p_path, bool p_keepCheckedOut);
	bool add                 ( const std::string& p_path, bool p_recursive);
	bool mkDirOnServer       ( const std::string& p_path);
};

--- NEW FILE: Pool.h ---
/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003-2004 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 Pool.h
 * @brief Interface of the class Pool
 */

#pragma once
#include "apr.h"

struct apr_pool_t;

/**
 * this class manages one apr pool. Objects of this class are allocated on
 * the stack of the SVNClient & SVNAdmin methods as the request pool. 
 * Leaving the methods will destroy the pool.
 */
class Pool
{
public:
	Pool();
	~Pool();
	apr_pool_t * pool() const;

private:
    /**
     * the apr pool request pool
     */
	apr_pool_t * m_pool;

};

--- NEW FILE: Targets.cpp ---
/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003 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 Targets.cpp
 * @brief Implementation of the class Targets
 */

#include "StdAfx.h"

#if(USESVN)

#include "Targets.h"
#include "Pool.h"
#include "Util.h"
#include <apr_tables.h>
#include <apr_strings.h>
#include <svn_path.h>
#include <iostream> // remove this later
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Targets::~Targets()
{
	m_targets.clear();
}

Targets::Targets(const char *path)
{
	m_targets.push_back (path);
	m_error_occured = NULL;
	m_doesNotContainsPath = false;
}

void Targets::add(const char *path)
{
	m_targets.push_back (path);
}

const apr_array_header_t *Targets::array (const Pool & pool)
{
	std::vector<Path>::const_iterator it;

	apr_pool_t *apr_pool = pool.pool ();
	apr_array_header_t *apr_targets =
		apr_array_make (apr_pool,
		m_targets.size(),
		sizeof (const char *));

	for (it = m_targets.begin (); it != m_targets.end (); it++)
	{
		const Path &path = *it;
		const char * target =
			apr_pstrdup (apr_pool, path.c_str());
		(*((const char **) apr_array_push (apr_targets))) = target;
	}

	return apr_targets;
}

svn_error_t *Targets::error_occured()
{
	return m_error_occured;
}

void Targets::setDoesNotContainsPath()
{
	m_doesNotContainsPath = true;
}

#endif

--- NEW FILE: CmdClient.h ---
#pragma once

#include <string>

class CmdClient
{
	bool m_logEnabled;
	void log( const std::string& p_command, const std::string& p_parameter);

	const char   * m_stdo; // "stdo.tmp"
	const char   * m_stde; // "stde.tmp"
	bool         m_showCmdWindows;
	bool         m_redirectOutput;

	static const char * m_cs_checkout;
	static const char * m_cs_update;
	static const char * m_cs_lock;
	static const char * m_cs_unlock;
	static const char * m_cs_mkdir;
	static const char * m_cs_propset_needs_lock;
	static const char * m_cs_add;
	static const char * m_cs_commit;
	static const char * m_cs_info;
	static const char * m_cs_status;
	static const char * m_cs_cleanup;
	static const char * m_cs_resolved;

	std::string  m_svnPath;
public:

	CmdClient( bool p_showCmdWindows, bool p_redirectOutput);

	void         setLog                 ( bool p_val);
	void         setSvnPath             ( const std::string& p_svnPath);

	//tobe void         getCheckOutUserSVN     ( XmlObject * obj, std::string& user, bool& newfile);
	bool         getLatest              ( const std::string& p_dir);
	bool         isCheckedOutByElse     ( const std::string& p_file);
	bool         isLockedByUser         ( const std::string& p_path, std::string& p_holderUserName);
	bool         lightCheckOut          ( const std::string& p_url, const std::string& p_localDestPath); // this is used as svn checkout (in contrast with lock+checkout as in other versioning systems)
	bool         isVersioned            ( const std::string& p_file, bool p_isADir = false, bool p_suppressErrorMsg = false);
	bool         info                   ( const std::string& p_url, bool p_recursive, bool p_assembleInfoMsg, std::string& p_resultMsg, std::string& p_author, std::string& p_holder);
	bool         status                 ( const std::string& p_path, bool p_assembleStatMsg, std::string& p_resultMsg);
	bool         cleanup                ( const std::string& p_path, bool p_assembleStatMsg, std::string& p_resultMsg);
	bool         resolve                ( const std::string& p_path, bool p_recursive);

	bool         lockableProp           ( const std::string& p_file);
	bool         applyLock              ( const std::string& p_file); // obsolete
	bool         removeLock             ( const std::string& p_file); // obsolete
	bool         tryLock                ( const std::string& p_file);
	bool         unLock                 ( const std::string& p_file);
	//bool         mkdirWithUpdate        ( const std::string& p_url, const std::string& p_path, const std::string& p_dir); // obsolete
	bool         mkdirOnServer          ( const std::string& p_path);
	bool         add                    ( const std::string& p_file, bool p_recursive = false);
	bool         commit                 ( const std::string& p_dirOrFile, bool p_initialCommit = false, bool p_noUnlock = false);
	bool         update                 ( const std::string& p_dirOrFile);

protected:

	int          execute                ( const char * p);
	bool         check                  ( long p_code, bool p_suppressNonversionedErrorMsg = false);
	void         redirect               ( std::string& p_cmd);
	void         loadContents           ( const char * p_fname, std::string& p_fileContent);
	void         dumpContents           ( const char * p_fname, long p_type);

	DWORD        runSilent              ( const char* p_strFunct, const char* p_strstrParams, bool p_silent = true);
	std::string  command                ( const char * p_command, const char * p_par = 0);

	std::string  findLastChangeAuthor   ( const std::string& p_out);
	std::string  findLockOwner          ( const std::string& p_out);
};
--- NEW FILE: Pool.cpp ---
/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003 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 Pool.cpp
 * @brief Implementation of the class Pool
 */

#include "StdAfx.h"

#if(USESVN)

#include "Pool.h"
#include "Util.h"
//#include "JNIMutex.h"
//#include "JNICriticalSection.h"
#include "svn_pools.h"

/**
 * Constructor to create one apr pool as the subpool of the global pool
 * store this pool as the request pool.
 */ 
Pool::Pool()
{
	//JNICriticalSection criticalSection(*JNIUtil::getGlobalPoolMutex());
	m_pool = svn_pool_create(Util::getPool());
	// we need to store in the static
	Util::setRequestPool( this);
	//Util::setRequestPool(this);
}

/**
 * Destructor to destroy the apr pool and to clear the request pool pointer
 */
Pool::~Pool()
{
	//JNICriticalSection criticalSection(*JNIUtil::getGlobalPoolMutex());
	Util::setRequestPool(NULL); // will nullify the ptr's value

	if(m_pool)
	{
		svn_pool_destroy (m_pool);
	}

}

/**
 * Returns the apr pool.
 * @return the apr pool
 */
apr_pool_t * Pool::pool () const
{
	return m_pool;
}

#endif
--- NEW FILE: CmdClient.cpp ---
#include "StdAfx.h"
#include "CmdClient.h"
#include "CoreXmlFile.h"
#include "FileHelp.h"
#include "MsgConsole.h"
//#include <stdlib.h>
#include <direct.h>

#if(USESVN)
// statics
const char * CmdClient::m_cs_checkout            = "co"; // a light checkout, with no consequences on locks!
const char * CmdClient::m_cs_update              = "update";
const char * CmdClient::m_cs_lock                = "lock";
const char * CmdClient::m_cs_unlock              = "unlock";
const char * CmdClient::m_cs_mkdir               = "mkdir";
const char * CmdClient::m_cs_propset_needs_lock  = "propset svn:needs-lock 'na'";
const char * CmdClient::m_cs_add                 = "add";
const char * CmdClient::m_cs_commit              = "commit";
const char * CmdClient::m_cs_info                = "info";
const char * CmdClient::m_cs_status              = "status";
const char * CmdClient::m_cs_cleanup             = "cleanup";
const char * CmdClient::m_cs_resolved            = "resolved";

CmdClient::CmdClient( bool p_showCmdWindows, bool p_redirectOutput)
	: m_stdo( "stdo.tmp")
	, m_stde( "stde.tmp")
	, m_showCmdWindows( p_showCmdWindows)
	, m_redirectOutput( p_redirectOutput)
	, m_svnPath( "svn")
{
}

std::string CmdClient::command( const char * p_command, const char * p_par /*= 0*/)
{
	return m_svnPath + " " + p_command + " " + (p_par? p_par : "") + " ";
}

void CmdClient::setSvnPath( const std::string& p_svnPath)
{
	m_svnPath = p_svnPath;
}

//void CmdClient::getCheckOutUserSVN(XmlObject * obj, string& user, bool& newfile)
//{
//	ASSERT( m_sourceControl == SC_SUBVERSION );
//	ASSERT( obj->isContainer() );
//	ASSERT( m_svnByAPI);
//
//	if( m_svnByAPI)
//	{
//		std::string fname;
//		getContainerFileName( obj, fname, true);
//		//char buff[100];
//		//bool ret = m_svn->isLockedBy( fname.c_str(), &buff[0], 100);
//		//if( ret)
//		//	user = buff;
//		bool ret = m_svn->isLockedByUser( fname, user);
//		newfile = false; // todo
//	}
//}

bool CmdClient::isCheckedOutByElse( const std::string& p_file)
{
	//ASSERT( isVersionedInSVN( p_file));
	if( !FileHelp::isFileReadOnly( p_file)) 
		return false; // file is svnlocked by us

	if( applyLock( p_file))
	{
		// success: was not checked out by somebody else
		if( removeLock( p_file))
			return false;
	}
	return true;
}

bool CmdClient::isLockedByUser( const std::string& p_path/*, std::string& p_lastAuthor*/, std::string& p_holderUserName)
{
	// ret val is always true
	// p_username !empty indicates whether is held or not
	return info( p_path, false /*recursive*/, false /*assemble inf msg*/, std::string() /*msg*/, std::string() /*p_lastAuthor*/, p_holderUserName);
}

bool CmdClient::lightCheckOut( const std::string& p_url, const std::string& p_localDestPath)
{
	std::string cmd = command( m_cs_checkout) + p_url + " " + p_localDestPath;
	redirect( cmd);

	int r;
	r = execute( cmd.c_str());

	return check( r);
}

bool CmdClient::getLatest( const std::string& p_dir)
{
	int r0;
	r0 = _chdir( p_dir.c_str());
	check( r0 );

	// what about a clean?, or what about the first time this is called: 'svn checkout' should be used
	std::string cmd = command( m_cs_update) + " . ";
	redirect( cmd);

	int r;
	r = execute( cmd.c_str());

	return check( r);
}

// obsolete
bool CmdClient::applyLock( const std::string& p_file)
{
	std::string cmd = command( m_cs_lock) + p_file;
	redirect( cmd);

	int r;
	r = execute( cmd.c_str());

	return check( r);
}

bool CmdClient::removeLock( const std::string& p_file)
{
	std::string cmd = command( m_cs_unlock) + p_file;
	redirect( cmd);

	int r;
	r = execute( cmd.c_str());

	return check( r);
}

bool CmdClient::tryLock( const std::string& p_file)
{
	// is locked already? // optimization, but might mislead
	WIN32_FILE_ATTRIBUTE_DATA attr;
	BOOL res = GetFileAttributesEx( p_file.c_str(), GetFileExInfoStandard, &attr );
	if( (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY //non-dir
	 && (attr.dwFileAttributes & FILE_ATTRIBUTE_READONLY)  != FILE_ATTRIBUTE_READONLY) //non-read-only
		return true; // lock present

	// process with lock command
	std::string cmd = command( m_cs_lock) + p_file;
	redirect( cmd);

	int r;
	r = execute( cmd.c_str());

	return check( r);
}

bool CmdClient::unLock( const std::string& p_file)
{
	// is unlocked already? // optimization, but might mislead
	WIN32_FILE_ATTRIBUTE_DATA attr;
	BOOL res = GetFileAttributesEx( p_file.c_str(), GetFileExInfoStandard, &attr );
	if( (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY //non-dir
	 && (attr.dwFileAttributes & FILE_ATTRIBUTE_READONLY)  == FILE_ATTRIBUTE_READONLY) //read-only
		return true; // presumably unlocked, that's why is read-only

	// process with unlock command
	std::string cmd = command( m_cs_unlock) + p_file;
	redirect( cmd);

	int r;
	r = execute( cmd.c_str());

	return check( r);
}

bool CmdClient::mkdirOnServer( const std::string& p_path)
{
	// creates and commits the versioned directory on the server
	std::string cmd = command( m_cs_mkdir) + p_path + " -m \"initial checkin\"";
	redirect( cmd);

	int r;
	r = execute( cmd.c_str());

	return check( r );
}

// obsolete
//bool CmdClient::mkdirWithUpdate( const std::string& p_url, const std::string& p_path, const std::string& p_dir)
//{
//	// creates and commits the versioned directory on the server
//	std::string cmd = command( m_cs_mkdir);
//	cmd += p_url + "/" + p_dir + " -m \"initial checkin\"";
//	redirect( cmd);
//
//	int r = execute( cmd.c_str());
//	bool err = check( r );
//	
//	// check out a working copy to local directory
//	//r = _chdir( m_folderPath);
//	//check( r );
//
//	// svn checkout URL PATH form can be used also e.g.:
//	// svn checkout svn://localhost/svn_02 f:\t\at\an\svn_02
//	std::string cmd2 = command( m_cs_checkout);
//	cmd2 += p_url + '/' + p_dir + ' ' + p_path;
//	redirect( cmd2);
//
//	r = execute( cmd2.c_str());
//	bool err2 = check( r);
//
//	// change into the newly created directory
//	r = _chdir( p_path.c_str());
//
//	return err && err2 && check( r);
//}

bool CmdClient::lockableProp( const std::string& p_file)
{
	// svn propset svn:needs-lock 'anyvalue' <file>
	std::string cmd = command( m_cs_propset_needs_lock) + p_file;

	redirect( cmd);

	int r;
	r = execute( cmd.c_str());

	return check( r);
}

bool CmdClient::add( const std::string& p_entity, bool p_recursive /* = false*/)
{
	std::string cmd = command( m_cs_add) + (p_recursive?"": " -N ") + p_entity;
	//std::string cmt_line( "svn commit ");
	//cmt_line.append( p_entity);
	redirect( cmd);

	int r;
	r = execute( cmd.c_str());
	//r2 = execute( cmt_line.c_str());

	return check( r);
}


bool CmdClient::commit( const std::string& p_dirOrFile, bool p_initialCommit /* = false*/, bool p_noUnlock /* = false*/)
{
	if( !p_initialCommit && !p_noUnlock && FileHelp::isFile( p_dirOrFile) && !FileHelp::isFileReadOnly( p_dirOrFile))
		removeLock( p_dirOrFile); // commit does not always remove lock, [at least when diff is empty]

	std::string cmd = command( m_cs_commit) + " -m \"ok\" " + p_dirOrFile;

	if( p_noUnlock) 
		cmd.append( " --no-unlock ");

	redirect( cmd);

	int r;
	r = execute( cmd.c_str());

	return check( r);
}

bool CmdClient::update( const std::string& p_dirOrFile)
{
	std::string cmd = command( m_cs_update) + p_dirOrFile;
	redirect( cmd);

	int r;
	r = execute( cmd.c_str());

	return check( r);
}

bool CmdClient::isVersioned( const std::string& p_file, bool p_isADir /*= false*/, bool p_suppressErrorMsg /*=false*/)
{
	if( p_isADir)
	{
		if( FileHelp::isFile( p_file))
		{
			ASSERT( 0); // it should be a directory
			return false;
		}
	}
	else
	{
		// may be redundant sometimes, but needed when called from makeSureFileExistsInVerSys
		if( !FileHelp::fileExist( p_file)) // the file even not exists not even a file
			return false;
	}

	//std::string status_line = "svn status " + p_file;
	std::string cmd = command( m_cs_info) + p_file;
	redirect( cmd);
	// error given in case file not committed: <<filename>>.txt:  (Not a versioned resource)

	int r;
	r = execute( cmd.c_str());

	return check( r);
}

#if(0)
// this is like isVersioned, but expects an element not be versioned, thus
// won't dump any error message onto the console.
// In other words its default behaviour is a little different.
bool CmdClient::isNotVersioned( const std::string& p_fileUrl, bool p_isADir = false, bool p_suppressErrorMsg = false)
{
	if( p_isADir)
	{
		if( FileHelp::isFile( p_file))
		{
			ASSERT( 0); // it should be a directory
			return false;
		}
	}
	else
	{
		// file doesn't exist, means that is not versioned either
		if( !FileHelp::fileExist( p_file))
			return true;
	}

	std::string cmd = command( m_cs_info) + p_file;
	redirect( cmd);
	// error given in case file not committed: <<filename>>.txt:  (Not a versioned resource)

	int r;
	r = execute( cmd.c_str());

	if( r != 0) // error executing it
		return true;

	if( p_suppressErrorMsg)
	std::string error_msg;
	loadContents( m_stde, error_msg); // std out file
	if( !error_msg.empty())
		return true; // if errors => not versioned

	return false;
}
#endif

bool CmdClient::info( const std::string& p_url, bool p_recursive, bool p_assembleInfoMsg, std::string& p_resultMsg, std::string& p_author, std::string& p_holder)
{
	std::string cmd = command( m_cs_info) + p_url;
	redirect( cmd);

	int r;
	r = execute( cmd.c_str());
	
	std::string  fc;

	loadContents( m_stdo, fc); // std out file

	//p_author = m_vssUser;                           // fooling the author consistency check
	p_author.clear();                               // clear the in params
	p_holder.clear();

	p_author = findLastChangeAuthor( fc);
	p_holder = findLockOwner( fc);

	if( p_assembleInfoMsg)
	{
		p_resultMsg.append( "\nOutput:\n");
		p_resultMsg.append( fc);

		p_resultMsg.append( "\nError (if any):\n");
		loadContents( m_stde, fc); // std error file
		p_resultMsg.append( fc);
	}

	return true; // always true, since the stde is captured and shown
}

bool CmdClient::status( const std::string& p_path, bool p_assembleStatMsg, std::string& p_resultMsg)
{
	std::string cmd = command( m_cs_status) + p_path;
	redirect( cmd);

	int r;
	r = execute( cmd.c_str());
	
	std::string  fc;

	loadContents( m_stdo, fc); // std out file

	if( p_assembleStatMsg)
	{
		p_resultMsg.append( "\nOutput:\n");
		p_resultMsg.append( fc);

		p_resultMsg.append( "\nError (if any):\n");
		loadContents( m_stde, fc); // std error file
		p_resultMsg.append( fc);
	}

	return true; // always true, since the stde is captured and shown
}

bool CmdClient::cleanup( const std::string& p_path, bool p_assembleStatMsg, std::string& p_resultMsg)
{
	std::string cmd = command( m_cs_cleanup) + p_path;
	redirect( cmd);

	int r;
	r = execute( cmd.c_str());
	
	std::string  fc;

	loadContents( m_stdo, fc); // std out file

	if( p_assembleStatMsg)
	{
		p_resultMsg.append( "\nOutput:\n");
		p_resultMsg.append( fc);

		p_resultMsg.append( "\nError (if any):\n");
		loadContents( m_stde, fc); // std error file
		p_resultMsg.append( fc);
	}

	return true; // always true, since the stde is captured and shown
}

bool CmdClient::resolve( const std::string& p_path, bool p_recursive)
{
	std::string cmd = command( m_cs_resolved) + (p_recursive?" -R ":"") + p_path;
	redirect( cmd);

	int r;
	r = execute( cmd.c_str());
	
	return check( r);
}

// static
DWORD CmdClient::runSilent(const char* p_strFunct, const char* p_strstrParams, bool p_silent /*= true*/)
{
	STARTUPINFO          startup_info;
	PROCESS_INFORMATION  process_info;

	char *env_CMD        = NULL;
	char *default_CMD    = "CMD.EXE";
	char  args[4096];

	ULONG rc;

	//static HANDLE hi, ho, he;
	
	memset(&startup_info, 0, sizeof(startup_info)); // clear all members
	startup_info.cb = sizeof(STARTUPINFO);
	startup_info.dwFlags = STARTF_USESHOWWINDOW;
	if( p_silent)
	{
		startup_info.wShowWindow = SW_HIDE;
		//startup_info.dwFlags | = STARTF_USESTDHANDLES;
		//startup_info.hStdError = he;
		//startup_info.hStdInput = hi;
		//startup_info.hStdOutput = ho;
	}
	else 
	{
		startup_info.wShowWindow = SW_SHOW;
	}

	args[0] = 0;

	env_CMD = getenv("COMSPEC");

	if(env_CMD) strcpy(args, env_CMD);
	else        strcpy(args, default_CMD);

	// "/c" option - Do the command then terminate the command window
	//if( p_silent) strcat(args, " /c "); 
	strcat( args, " /c ");
	//the application you would like to run from the command window
	strcat(args, p_strFunct);  
	strcat(args, " "); 
	//the parameters passed to the application being run from the command window.
	strcat(args, p_strstrParams); 

	if (!CreateProcess( NULL, args, NULL, NULL, FALSE,
		CREATE_NEW_CONSOLE, NULL, NULL,
		&startup_info, &process_info))
	{
		return GetLastError();
	}

	//if( p_silent) 
	{
		WaitForSingleObject(process_info.hProcess, INFINITE);
		if(!GetExitCodeProcess(process_info.hProcess, &rc))
			rc = 0;

		CloseHandle(process_info.hThread);
		CloseHandle(process_info.hProcess);
	}
	//else
	{
		//GetStartupInfo()process_info.hProcess
	}

	return rc;	
}

int CmdClient::execute( const char * p)
{
	log( p, "");
	return runSilent( "", p, !m_showCmdWindows);
	// the alternative could be to use the system() call:
	//return system( p); // this can set errno
}


bool CmdClient::check( long p_ret, bool p_suppressNonversionedErrorMsg /*= false*/)
{
	bool no_error = true;
	
	// svn related std output and std error handling
	WIN32_FILE_ATTRIBUTE_DATA attre, attro;
	BOOL res = GetFileAttributesEx( m_stde, GetFileExInfoStandard, &attre );
	BOOL rep = GetFileAttributesEx( m_stdo, GetFileExInfoStandard, &attro );

	if( res && attre.nFileSizeHigh == 0 && attre.nFileSizeLow == 0) { } // no problem
	else if( res) {
		no_error = false; 
		if( !p_suppressNonversionedErrorMsg) 
			dumpContents( m_stde, MSG_ERROR);
	}

	if( rep && attro.nFileSizeHigh == 0 && attro.nFileSizeLow == 0) { } // no problem
	else if( rep) {
		dumpContents( m_stdo, MSG_INFO);
	}

	// execution related problems
	if( p_ret != 0)
	{
		no_error = false;
	}

	// if execute uses the system() 
	if( p_ret == -1)
	{
		no_error = false;
		// errno global variable handling:
		switch( errno)
		{
		case E2BIG:// The space required for the arguments and environment settings exceeds 32 K. 
			MsgConsole::ssendMsg( "Cmd.exe execution error: E2BIG", MSG_ERROR);
			break;
		case EACCES:// The specified file has a locking or sharing violation. 
			MsgConsole::ssendMsg( "Cmd.exe execution error: EACCES", MSG_ERROR);
			break;
		case EMFILE:// Too many files open (the specified file must be opened to determine whether it is executable). 
			MsgConsole::ssendMsg( "Cmd.exe execution error: EMFILE", MSG_ERROR);
			break;
		case ENOENT:// File or path not found. 
			MsgConsole::ssendMsg( "Cmd.exe execution error: ENOENT", MSG_ERROR);
			break;
		case ENOEXEC:// The specified file is not executable or has an invalid executable-file format. 
			MsgConsole::ssendMsg( "Cmd.exe execution error: ENOEXEC", MSG_ERROR);
			break;
		case ENOMEM: 
			MsgConsole::ssendMsg( "Cmd.exe execution error: ENOMEM", MSG_ERROR);
			break;
		default:
			MsgConsole::ssendMsg( "Cmd.exe execution error: <<unkown>>", MSG_ERROR);
		}
	}

	return no_error;
}

// static
void CmdClient::loadContents( const char * p_fname, std::string& p_fileContent)
{
	p_fileContent.clear();

	std::ifstream f;
	f.open( p_fname, std::ios_base::in);
	if( !f.is_open()) 
		return;

	char buffer[1024];
	while( f)
	{
		if( !p_fileContent.empty()) p_fileContent += '\n';
		f.getline( buffer, 1024);
		p_fileContent.append( buffer);
	}
	f.close();
}

void CmdClient::dumpContents( const char * p_fname, long p_msgType)
{
	//FILE * f = fopen( p_fname, "r");
	//if( !f) sendMsg( std::string( "Could not open file: ") + p_fname, p_msgType);
	//char buffer[1024];
	//while( !feof( f))
	//{
	//	fread( buffer, 1, 1024, f);
	//	sendMsg( buffer, p_msgType);
	//}
	//fclose( f);
	std::ifstream f;
	f.open( p_fname, std::ios_base::in);
	if( !f.is_open()) 
	{
		MsgConsole::ssendMsg( std::string( "Could not open file: ") + p_fname, p_msgType);
		return;
	}

	char buffer[1024];
	while( f)
	{
		f.getline( buffer, 1024);
		MsgConsole::ssendMsg( std::string( "SVN> ") + buffer, p_msgType);
	}
	f.close();
}

// static
void CmdClient::redirect( std::string& p_cmd)
{
	if( m_redirectOutput)
		p_cmd.append( std::string( " 1> ") + m_stdo + " 2>" + m_stde + " ");//p_cmd.append( " 1>stdo.tmp 2>stde.tmp ");
}

std::string CmdClient::findLastChangeAuthor( const std::string& p_out)
{
	const char * lca_str = "\nLast Changed Author: ";
	const int    lca_len = strlen( lca_str);

	int ps = p_out.find( lca_str);
	int ps_end = p_out.find( "\n", ps + 1);
	if( ps != std::string::npos && ps_end != std::string::npos)
	{
		return p_out.substr( ps + lca_len, ps_end - ps - lca_len);
	}

	return "";
}

std::string CmdClient::findLockOwner( const std::string& p_out)
{
	const char * lca_str = "\nLock Owner: ";
	const int    lca_len = strlen( lca_str);

	int ps = p_out.find( lca_str);
	int ps_end = p_out.find( "\n", ps + 1);
	if( ps != std::string::npos && ps_end != std::string::npos)
	{
		return p_out.substr( ps + lca_len, ps_end - ps - lca_len);
	}

	return "";
}

void CmdClient::log( const std::string& p_command, const std::string& p_par)
{
	if( !m_logEnabled) return;

	std::ofstream fs;
	fs.open( "c:\\svnlog.txt", std::ios_base::ate | std::ios_base::app); // append
	if( fs)
	{
		fs << p_command << " " << p_par << std::endl;
		fs.close();
	}
}

void CmdClient::setLog( bool p_val)
{
	m_logEnabled = p_val;
}
#endif
--- NEW FILE: Util.cpp ---
#include "StdAfx.h"

#if(USESVN)

#include ".\util.h"
#include <iostream> // remove this later
#include <fstream>
#include <string>
#include "svn_path.h"
#include "svn_pools.h"
#include "ThreadData.h"
#include <locale.h> // for LC_ALL

//#define _ 

/*static*/ //Pool *              Util::m_requestPool      = 0;
/*static*/ apr_pool_t*         Util::g_pool             = 0;
/*static*/ bool                Util::g_inInit           = false;
/*static*/ bool                Util::g_initException    = false;
/*static*/ ThreadData          Util::m_globalData;
/*static*/ char                Util::g_initFormatBuffer[formatBufferSize];

/*static*/ std::ofstream       Util::g_logStream;
/*static*/ int                 Util::g_logLevel         = Util::noLog;

/**
 * initialize the environment for all requests
 * @param env   the JNI environment for this request
 */
//void Util::globalInit()
//{
//	if (apr_initialize() != APR_SUCCESS)
//	{
//		printf("apr_initialize() failed.\n");
//		exit(1);
//	}
//
//	g_pool = svn_pool_create (NULL);
//}

/**
 * initialize the environment for all requests
 * @param env   the JNI environment for this request
 */
bool Util::globalInit()
{
	// this method has to be run only once during the run a 
    // programm
    static bool run = false;
    if(run) // already run
    {
		return true;
    }
    run = true;
    // do not run this part more than one time. 
    // this leaves a small time window when two threads create their first
    // SVNClient & SVNAdmin at the same time, but I do not see a better 
    // option without APR already initialized
    if(g_inInit)
    {
        return false;
    }
    g_inInit = true;
    //g_initEnv = env;

    apr_status_t status;

    /* C programs default to the "C" locale. But because svn is supposed
       to be i18n-aware, it should inherit the default locale of its
       environment.  */
    if (!setlocale(LC_ALL, ""))
    {
        if (stderr)
        {
            const char *env_vars[] = { "LC_ALL", "LC_CTYPE", "LANG", NULL };
            const char **env_var = &env_vars[0], *env_val = NULL;
            while (*env_var)
            {
                env_val = getenv(*env_var);
                if (env_val && env_val[0])
                    break;
                ++env_var;
            }

            if (!*env_var)
            {
                /* Unlikely. Can setlocale fail if no env vars are set? */
                --env_var;
                env_val = "not set";
            }

            fprintf(stderr,
                  "%s: error: cannot set LC_ALL locale\n"
                  "%s: error: environment variable %s is %s\n"
                  "%s: error: please check that your locale name is correct\n",
                  "svnjavahl", "svnjavahl", *env_var, env_val, "svnjavahl");
        }
        return FALSE;
    }

    /* Initialize the APR subsystem, and register an atexit() function
       to Uninitialize that subsystem at program exit. */
    status = apr_initialize();
    if (status)
    {
        if (stderr)
        {
            char buf[1024];
            apr_strerror(status, buf, sizeof(buf) - 1);
            fprintf(stderr,
                  "%s: error: cannot initialize APR: %s\n",
                  "svnjavahl", buf);
        }
        return FALSE;
    }

    if (0 > atexit(apr_terminate))
    {
        if (stderr)
            fprintf(stderr,
                "%s: error: atexit registration failed\n",
                "svnjavahl");
        return FALSE;
    }

#ifdef ENABLE_NLS
#ifdef WIN32
    {
        WCHAR ucs2_path[MAX_PATH];
        char* utf8_path;
        const char* internal_path;
        apr_pool_t* pool;
        apr_status_t apr_err;
        unsigned int inwords, outbytes, outlength;

        apr_pool_create (&pool, 0);
        /* get dll name - our locale info will be in '../share/locale' */
        inwords = sizeof (ucs2_path) / sizeof(ucs2_path[0]);
        HINSTANCE moduleHandle = GetModuleHandle("libsvnjavahl-1");
        GetModuleFileNameW (moduleHandle, ucs2_path, inwords);
        inwords = lstrlenW (ucs2_path);
        outbytes = outlength = 3 * (inwords + 1);
        utf8_path = (char *)apr_palloc (pool, outlength);
        apr_err = apr_conv_ucs2_to_utf8 ((const apr_wchar_t *) ucs2_path,
                                         &inwords, utf8_path, &outbytes);
        if (!apr_err && (inwords > 0 || outbytes == 0))
          apr_err = APR_INCOMPLETE;
        if (apr_err)
        {
          if (stderr)
            fprintf (stderr, "Can't convert module path to UTF-8");
          return FALSE;
        }
        utf8_path[outlength - outbytes] = '\0';
        internal_path = svn_path_internal_style (utf8_path, pool);
        /* get base path name */
        internal_path = svn_path_dirname (internal_path, pool);
        internal_path = svn_path_join (internal_path, SVN_LOCALE_RELATIVE_PATH,
                                       pool);
        bindtextdomain (PACKAGE_NAME, internal_path);
        apr_pool_destroy (pool);
    }
#else
    bindtextdomain(PACKAGE_NAME, SVN_LOCALE_DIR);
#endif
    textdomain(PACKAGE_NAME);
#endif

    /* Create our top-level pool. */
    g_pool = svn_pool_create (NULL);

#if defined(WIN32) || defined(__CYGWIN__)
    /* See http://svn.collab.net/repos/svn/trunk/notes/asp-dot-net-hack.txt */
    /* ### This code really only needs to be invoked by consumers of
       ### the libsvn_wc library, which basically means SVNClient. */
    if (getenv ("SVN_ASP_DOT_NET_HACK"))
    {
        svn_error_t *err = svn_wc_set_adm_dir("_svn", g_pool);
        if (err)
        {
            if (stderr)
            {
                fprintf(stderr,
                        "%s: error: SVN_ASP_DOT_NET_HACK failed: %s\n",
                        "svnjavahl", err->message);
            }
            svn_error_clear(err);
            return FALSE;
        }
    }
#endif

    //// build all mutexes
    //g_finalizedObjectsMutex = new JNIMutex(g_pool);
    //if(isExceptionThrown())
    //{
    //    return false;
    //}

    //g_logMutex = new JNIMutex(g_pool);
    //if(isExceptionThrown())
    //{
    //    return false;
    //}

    //g_globalPoolMutext = new JNIMutex(g_pool);
    //if(isExceptionThrown())
    //{
    //    return false;
    //}

    //// initialized the thread local storage
    //if(!JNIThreadData::initThreadData())
    //{
    //    return false;
    //}

    //setEnv(env);
    //if(isExceptionThrown())
    //{
    //    return false;
    //}

    //g_initEnv = NULL;
	m_globalData.init();
    g_inInit = false;
    return true;
}

void Util::handleAPRError(int error, const char *op)
{
	char *buffer = getFormatBuffer();
	if(buffer == NULL)
	{
		return;
	}
	apr_snprintf(buffer, formatBufferSize, 
		"an error occurred in function %s with return value %d",
		op, error);

	throwError(buffer);
} 

//static
bool Util::isOtherExceptionThrown()
{
	return false;
}

//static
bool Util::isExceptionThrown()
{
	if(g_inInit) // during init -> look in the global member
	{
		return g_initException;
	}

	// look in the thread local storage
	//JNIThreadData *data = JNIThreadData::getThreadData();
	//return data == NULL || data->m_exceptionThrown;
	return m_globalData.m_exceptionThrown;
}

//static 
void Util::setExceptionThrown()
{
	if (g_inInit)
	{
		// During global initialization, store any errors that occur
		// in in a global variable (since thread-local storage may not
		// yet be available).
		g_initException = true;
	}
	else
	{
		// When global initialization is complete, thread-local
		// storage should be available, so store the error there.
		//JNIThreadData *data = JNIThreadData::getThreadData();
		//data->m_exceptionThrown = true;
		m_globalData.m_exceptionThrown = true;
	}
}

/*static*/ void Util::throwNullPointerException( const char * p_msg)
{
	std::cout << "Exception " << p_msg << std::endl;
    //if (getLogLevel() >= errorLog)
    {
        logMessage("NullPointerException thrown");
    }

	setExceptionThrown();
}

//static
void Util::throwError(const char *message)
{
	//raiseThrowable(JAVA_PACKAGE"/JNIError", message);
	throw std::string( message);
}


/**
 * returns the global (not request specific) pool
 * @return global pool
 */
/*static*/ apr_pool_t * Util::getPool()
{
	return g_pool;
}

/**
 * build the error message from the svn error into buffer. This method calls 
 * itselft recursivly for all the chained errors
 *
 * @param err               the subversion error
 * @param depth             the depth of the call, used for formating
 * @param parent_apr_err    the apr of the previous level, used for formating
 * @param buffer            the buffer where the formated error message will
 *                          be stored
 */
void Util::assembleErrorMessage(svn_error_t *err, int depth, 
								apr_status_t parent_apr_err, 
								std::string &buffer)
{
	// buffer for a single error message
	char errbuf[256];

	/* Pretty-print the error */
	/* Note: we can also log errors here someday. */

	/* When we're recursing, don't repeat the top-level message if its
	   the same as before. */
	if (depth == 0 || err->apr_err != parent_apr_err)
	{
		/* Is this a Subversion-specific error code? */
		if ((err->apr_err > APR_OS_START_USEERR)
			&& (err->apr_err <= APR_OS_START_CANONERR))
			buffer.append(svn_strerror (err->apr_err, errbuf, sizeof (errbuf)));
		/* Otherwise, this must be an APR error code. */
		else
			buffer.append(apr_strerror (err->apr_err, errbuf, sizeof (errbuf)));
		buffer.append("\n");
	}
	if (err->message)
		buffer.append( "svn: ").append(err->message).append("\n");

	if (err->child)
		assembleErrorMessage(err->child, depth + 1, err->apr_err, buffer);

}

//static
std::string Util::makeSVNErrorMessage(svn_error_t *err)
{
    if(err == NULL)
        return "";
    std::string buffer;
    assembleErrorMessage(err, 0, APR_SUCCESS, buffer);
    return buffer;
}

/**
 * process a svn error by wraping in into a ClientExpection
 * and throwing that
 * @param err   the error to by handled
 */
/*static*/ void Util::handleSVNError( svn_error_t * p_err)
{
	if( !p_err) 
	{ 
		//std::cout << "handleSVNError: p_err is 0" << std::endl; 
		return; 
	}
	//std::cout << "Error " << ( p_err->message?p_err->message:"<<nomsg>>") << std::endl;

    if(isOtherExceptionThrown())
    {
        svn_error_clear( p_err);
		AfxMessageBox( "Other exception thrown, Util::handleSVNError");
        return;
    } 
	
	std::string buffer;
    assembleErrorMessage( p_err, 0, APR_SUCCESS, buffer);
	AfxMessageBox( (std::string( "SVN Error details follow:\n") + buffer).c_str());
	//std::cout << "Error " << buffer << std::endl;

	//if( p_err->apr_err == SVN_ERR_RA_ILLEGAL_URL)
	//	std::cout << "Error SVN_ERR_RA_ILLEGAL_URL, [URL does not exist]. " << std::endl;
	//if( p_err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)
	//	std::cout << "Error SVN_ERR_UNSUPPORTED_FEATURE, [URL refs to file instead of a directory]. " << std::endl;
	//if( p_err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE)
	//	std::cout << "Error SVN_ERR_UNVERSIONED_RESOURCE " << ( p_err->file? p_err->file: "<<nofile>>") << " msg = " << ( p_err->message?p_err->message:"<<nomsg>>") << std::endl;
	//if( p_err->apr_err == SVN_ERR_RA_ILLEGAL_URL)
	//	std::cout << "Error SVN_ERR_RA_ILLEGAL_URL " << ( p_err->file? p_err->file: "<<nofile>>") << " msg = " << ( p_err->message?p_err->message:"<<nomsg>>") << std::endl;
	//if( p_err->apr_err == SVN_ERR_RA_DAV_SOCK_INIT)
	//	std::cout << "Error SVN_ERR_RA_DAV_SOCK_INIT " << (p_err->file?p_err->file:"") << " msg = " << ( p_err->message?p_err->message:"<<nomsg>>") << std::endl;
	//if( p_err->child)
	//	handleSVNError( p_err->child);
}

/*static*/ svn_error_t * Util::preprocessPath(const char *&path, apr_pool_t * pool)
{
	/* URLs and wc-paths get treated differently. */
	if (svn_path_is_url (path))
	{
		/* No need to canonicalize a URL's case or path separators. */

		/* Convert to URI. */
		path = svn_path_uri_from_iri (path, pool);
		/* Auto-escape some ASCII characters. */
		path = svn_path_uri_autoescape (path, pool);

		/* The above doesn't guarantee a valid URI. */
		if (! svn_path_is_uri_safe (path))
			return svn_error_createf (SVN_ERR_BAD_URL, 0,
			"URL '%s' is not properly URI-encoded",
			path);

		/* Verify that no backpaths are present in the URL. */
		if (svn_path_is_backpath_present (path))
			return svn_error_createf (SVN_ERR_BAD_URL, 0,
			"URL '%s' contains a '..' element",
			path);

		/* strip any trailing '/' */
		path = svn_path_canonicalize (path, pool);
	}
	else  /* not a url, so treat as a path */
	{
		const char *apr_target;
		char *truenamed_target; /* APR-encoded */
		apr_status_t apr_err;

		/* canonicalize case, and change all separators to '/'. */
		SVN_ERR (svn_path_cstring_from_utf8 (&apr_target, path,
			pool));
		apr_err = apr_filepath_merge (&truenamed_target, "", apr_target,
			APR_FILEPATH_TRUENAME, pool);

		if (!apr_err)
			/* We have a canonicalized APR-encoded target now. */
			apr_target = truenamed_target;
		else if (APR_STATUS_IS_ENOENT (apr_err))
			/* It's okay for the file to not exist, that just means we
			have to accept the case given to the client. We'll use
			the original APR-encoded target. */
			;
		else
			return svn_error_createf (apr_err, NULL,
			"Error resolving case of '%s'",
			svn_path_local_style (path,
			pool));

		/* convert back to UTF-8. */
		SVN_ERR (svn_path_cstring_to_utf8 (&path, apr_target, pool));
		path = svn_path_canonicalize (path, pool);

	}
	return NULL;
}

/** 
 * Return the request pool. The request pool will be destroyed after each 
 * request (call) 
 * @return the pool to be used for this request
 */
/*static*/ Pool * Util::getRequestPool()
{
    //return JNIThreadData::getThreadData()->m_requestPool;
	return m_globalData.m_requestPool;
	//return m_requestPool;
}
/**
 * Set the request pool in thread local storage
 * @param pool  the request pool
 */
/*static*/ void Util::setRequestPool(Pool *pool)
{
    //JNIThreadData::getThreadData()->m_requestPool = pool;
    //m_requestPool = pool;
	m_globalData.m_requestPool = pool;
}

char * Util::getFormatBuffer()
{
	if(g_inInit) // during init -> use the global buffer
	{
		return g_initFormatBuffer;
	}
	// use the buffer in the thread local storage
	//JNIThreadData *data = JNIThreadData::getThreadData();
	//if(data == NULL) // if that does not exists -> use the global buffer
	//{
	//	return g_initFormatBuffer;
	//}
	//return data->m_formatBuffer;
	return m_globalData.m_formatBuffer;
}

/** 
 * initialite the log file
 * @param level the log level
 * @param the name of the log file
 */
void Util::initLogFile(int level, const std::string& path)
{
    // lock this operation
    //JNICriticalSection cs(*g_logMutex);
    if(g_logLevel > noLog) // if the log file has been opened
    {
        g_logStream.close();
    }
    // remember the log level
    g_logLevel = level;
    //JNIStringHolder myPath(path);
	const char * myPath = path.c_str();
    if(g_logLevel > noLog) // if a new log file is needed
    {
        // open it
        g_logStream.open(myPath, std::ios::app);
    }
}

/**
 * Returns the current log level
 * @return the log level
 */
int Util::getLogLevel()
{
    return g_logLevel;
}
/**
 * write a message to the log file if needed
 * @param the log message
 */
void Util::logMessage(const char *message)
{
    // lock the log file
    //JNICriticalSection cs(*g_logMutex);
    g_logStream << message << std::endl;
}

#endif
--- NEW FILE: ThreadData.h ---
#pragma once
#include "svn_client.h"
#include "Pool.h"
#include "Util.h"

class ThreadData
{
public:
	ThreadData(void);
	~ThreadData(void);

	void init();

	/**
	* flag that a java execption has been detected
	*/
	bool m_exceptionThrown;
	/**
	* a buffer used for formating messages
	*/
	char m_formatBuffer[Util::formatBufferSize];
	/**
	* the pool for the current request (call)
	*/
	Pool *m_requestPool; 

};

--- NEW FILE: ThreadData.cpp ---
#include "StdAfx.h"

#if(USESVN)

#include ".\threaddata.h"

ThreadData::ThreadData(void)
{
}

ThreadData::~ThreadData(void)
{
}

void ThreadData::init()
{
	m_exceptionThrown = false;
	m_requestPool = 0; 
}
#endif
--- NEW FILE: Util.h ---
/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003-2004 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 JNIUtil.h
 * @brief Interface of the class JNIUtil
 */

#pragma once
#include "svn_client.h"
#include "Pool.h"
#include <string>

class ThreadData;
/**
 * class to hold a number of JNI relate utility methods. No Objects of this 
 * class are ever created
 */

class Util
{
public:
	enum { formatBufferSize = 2048 };

	static char *         getFormatBuffer();

	static bool           globalInit();

	static svn_error_t *  preprocessPath(const char *&path, apr_pool_t * pool);

	static void           logMessage(const char *message);
	static int            getLogLevel();
	static void           initLogFile(int level, const std::string& path);

	static void           handleAPRError(int error, const char *op);
	static bool           isOtherExceptionThrown();
	static bool           isExceptionThrown();
	static void           setExceptionThrown();
	static void           throwNullPointerException( const char *);
	static void           throwError(const char *message);

	static Pool*          getRequestPool();
	static void           setRequestPool(Pool *pool);
	
	static void           assembleErrorMessage(svn_error_t *err, int depth,
	                           apr_status_t parent_apr_err,
	                           std::string& buffer);

	static std::string    makeSVNErrorMessage(svn_error_t *err); 
	static void           handleSVNError( svn_error_t *);

	static apr_pool_t *   getPool(); 

private:

	//static Pool *m_requestPool; // was in a Thread Local Storage

	/**
	* global master pool. All other pool are subpools of this pool
	*/
	static apr_pool_t* g_pool;

	/**
	* flag, that one thread is in the init code. Cannot use mutex here since 
	* apr is not initialized yes
	*/
	static bool g_inInit;
	/**
	* flag, that an exception occured during our initialization
	*/
	static bool g_initException;

	enum { noLog, errorLog, exceptionLog, entryLog } LogLevel;
	/** 
	* the log level of this module
	*/ 
	static int g_logLevel;
	/**
	* the stream to write log messages to
	*/
	static std::ofstream g_logStream;

	static char           g_initFormatBuffer[formatBufferSize];

	static ThreadData     m_globalData; 

};

--- NEW FILE: HiClient.cpp ---
#include "StdAfx.h"
#include "HiClient.h"
#include <fstream>

#if(USESVN)

//#include "Revision.h" // these should not be here at all
#include "Pool.h"
//#include "Util.h"
//#include "Prompter.h" // end

extern std::string g_userName;
extern std::string g_passWord;

HiClient::HiClient( const std::string& p_userName, const std::string& p_passWord)
	: Client( p_userName, p_passWord)
	, m_logEnabled( true)
{
}

HiClient::~HiClient(void)
{
}

bool HiClient::isItUs( const std::string& p_userName)
{
	log( "isItUs", p_userName);
	return m_userName == p_userName;//strcmp( m_userName.c_str(), ( p_userName?p_userName:"")) == 0; // equal means yes
}

bool HiClient::isLocked            ( const std::string& p_path)
{
	log( "isLocked", p_path);
	return isLockedByUser( p_path, std::string());
}

bool HiClient::isLockedByUs        ( const std::string& p_path)
{
	bool lkd, l_us, l_else;

	log( "isLockedByUs", p_path);
	lkd = isLockedByWhom( p_path, &l_us, &l_else);

	return lkd && l_us;
}

bool HiClient::isLockedByOthers    ( const std::string& p_path)
{
	bool lkd, l_us, l_else;

	log( "isLockedByOthers", p_path);
	lkd = isLockedByWhom( p_path, &l_us, &l_else);

	return lkd && l_else;
}

bool HiClient::isLockedByWhom      ( const std::string& p_path, bool * p_us, bool * p_else)
{
	ASSERT( p_us);
	ASSERT( p_else);

	std::string    uname;
	bool           lockd = false;

	log( "isLockedByWhom", p_path);
	lockd = isLockedByUser( p_path, uname);

	*p_us   = isItUs( uname);
	*p_else = !*p_us;

	return lockd;
}

bool HiClient::isLockedByUser      ( const std::string& p_path, std::string& p_username)
{
	Pool reqPool;

	bool res = false;
	ClientUtil::InfoHelp::InfoVec inf;

	log( "isLockedByUser", p_path + p_username);
	bool suc = info2Qck( p_path.c_str(), false, inf);
	ASSERT( suc);
	ASSERT( inf.size() == 1);

	for( ClientUtil::InfoHelp::InfoVecConIter it = inf.begin(), en = inf.end(); suc && it != en; ++it)
	{
		if( it->m_info && it->m_info->lock)
		{
			// locked
			res = true;
			
			// by whom
			ASSERT( it->m_info->lock->owner);
			if( it->m_info->lock->owner)
				p_username = it->m_info->lock->owner;
			else
				p_username = "";
		}
	}

	return res;
}

bool HiClient::isVersioned         ( const std::string& p_path, bool p_isADir /*= false*/, bool p_suppressErrorMsg /*= false*/)
{
	Pool reqPool;

	log( "isVersioned", p_path + (p_isADir?" dir ": " file "));
	ClientUtil::InfoHelp::InfoVec inf;
	bool res = info2Qck( p_path.c_str(), false, inf, p_suppressErrorMsg);
	return res;
}

bool HiClient::info                ( const std::string& p_path, bool p_recursive, bool p_assembleInfoMessage, std::string& p_resultMsg, std::string& p_lastChangingAuthor, std::string& p_lockOwner)
{
	Pool reqPool;

	bool rv = false;
	std::string msg;
	std::string aut;
	std::string own;

	log( "info", p_path);
	ClientUtil::InfoHelp::InfoVec inf;
	if( sub_info2( p_path.c_str(), Revision(), Revision(), p_recursive, inf, true)) // non-recursive info only
	{
		rv = true;

		if( p_assembleInfoMessage)
		{
			msg = "After issuing 'svn info "; msg += ClientUtil::charstar2str( p_path.c_str(), "Url"); msg += "'";
			for( ClientUtil::InfoHelp::InfoVecConIter it = inf.begin(), en = inf.end(); it != en; ++it)
			{
				msg.append( "\nI know about: '");
				msg.append( ClientUtil::charstar2str( it->m_path, "Path"));
				msg.append( "' the following:");
				if( it->m_info)
				{
					if( !aut.empty()) aut.append( ", "); // if multiple entries in inf, then separate authors by ,

					msg.append( "\n\tLast Changed Author: "); 
					aut.append( ClientUtil::charstar2str( it->m_info->last_changed_author, "Author"));
					msg.append( ClientUtil::charstar2str( it->m_info->last_changed_author, "Author"));

					msg.append( "\n\tVersioned as (URL): "); 
					msg.append( ClientUtil::charstar2str( it->m_info->URL, "Url"));
					
					if( it->m_info->lock)
					{
						msg.append( "\n\tLocked by "); 
						if( !own.empty()) own.append( ", "); // if multiple entries in inf, then separate owners by ,

						own.append( ClientUtil::charstar2str( it->m_info->lock->owner, "LockOwner"));
						msg.append( ClientUtil::charstar2str( it->m_info->lock->owner, "LockOwner"));
					}
					else
						msg.append( "\n\tNot Locked");
				}
				else 
					msg.append( "No detailed info present for item");
			}
		}
	} 
	else 
	{
		rv = false;

		if( p_assembleInfoMessage)
		{
			msg.append( "svn info command failed");
		}
	}

	if( p_assembleInfoMessage)
		p_resultMsg = msg;

	p_lastChangingAuthor = aut;
	p_lockOwner          = own;
	return rv;
}

bool HiClient::tryLock             ( const std::string& p_path)
{
	log( "tryLock", p_path);

	bool res = false;
	if( isLockedByOthers( p_path)) return res;

	Pool reqPool;

	res = sub_lock( Targets( p_path.c_str()), /*comment =*/ "nc" , /*force =*/ false );
	return res;
}

bool HiClient::unLock              ( const std::string& p_path)
{
	log( "unLock", p_path);

	Pool reqPool;

	return sub_unlock( Targets( p_path.c_str()));

}

bool HiClient::lockableProp        ( const std::string& p_path)
{
	log( "lockableProp", p_path);

	Pool reqPool;

	return sub_propertySet( p_path.c_str(), "svn:needs-lock", /*value =*/ "na", /*recurse =*/ false, /*force =*/ false );
}

bool HiClient::getLatest           ( const std::string& p_path)
{
	log( "getLatest", p_path);

	Pool reqPool;

	UPDATE_RES res;
	bool succ = sub_update( Targets( p_path.c_str()), Revision(), /*recurse =*/ true, /*ignoreExt =*/ false, res);
	return succ;
}

bool HiClient::lightCheckOut( const std::string& p_path, const std::string& p_localDir)
{
	log( "checkOut", p_path);

	Pool reqPool;

	return 0 < sub_checkout( p_path.c_str(), p_localDir.c_str(), Revision(), Revision(), /*recurse =*/ true, /*ignoreExt =*/ false);
}

bool HiClient::commitAll           ( const std::string& p_path, bool p_keepCheckedOut)
{
	log( "commitAll", p_path);

	Pool requestPool;

	Targets tgt( p_path.c_str()); // commit might return -1 if there were no things to commit (diff was 0)
	return 0 < sub_commit( tgt, "no message", /*recurse =*/ true, /*noUnlock =*/ p_keepCheckedOut);
}

bool HiClient::add                 ( const std::string& p_path, bool p_recursive)
{
	log( "add", p_path);

	Pool reqPool;

	return 0 < sub_add( p_path.c_str(), p_recursive);
}

bool HiClient::mkDirOnServer       ( const std::string& p_path)
{
	log( "mkDirOnServer", p_path);

	Pool reqPool;

	return 0 < sub_mkdir2( Targets( p_path.c_str()), "nm");
}

bool HiClient::cleanup( const std::string& p_path)
{
	log( "cleanup", p_path);

	Pool reqPool;
	
	return sub_cleanup( p_path.c_str());
}

bool HiClient::resolve( const std::string& p_path, bool p_recursive)
{
	log( "resolve", p_path);

	Pool reqPool;

	return sub_resolved( p_path.c_str(), p_recursive);
}

bool HiClient::status( const std::string& p_path, bool p_assembleStatusMsg, std::string& p_statMsg)
{
	log( "status", p_path);

	Pool reqPool;

	bool        rv = false;
	std::string msg;

	ClientUtil::StatusExtInfoVec vec;
	vec = sub_extended_status( p_path.c_str(), false /* on_server*/);
	if( !vec.empty())
	{
		rv = true;

		if( p_assembleStatusMsg)
		{
			msg = "Svn status " + p_path + " command resulted in:\n";
			for( ClientUtil::StatusExtInfoVec::iterator it = vec.begin(); it != vec.end(); ++it)
			{
				//const char *                   m_path;
				//svn_wc_status2_t *             m_status;

				if( !it->m_status)
					msg.append( "Null status");
				else
				{
					std::string st;
					switch( it->m_status->text_status) {
					//case items copied from enum svn_wc_status_kind, svn_wc.h
					case svn_wc_status_none:        st += "Not exists "; break; /** does not exist */
					case svn_wc_status_unversioned: st += "Unversioned"; break; /** is not a versioned thing in this wc */
					case svn_wc_status_normal:      st += "Normal     "; break; /** exists, but uninteresting */
					case svn_wc_status_added:       st += "Added      "; break; /** is scheduled for addition */
					case svn_wc_status_missing:     st += "Missing    "; break; /** under v.c., but is missing */
					case svn_wc_status_deleted:     st += "Deleted    "; break; /** scheduled for deletion */
					case svn_wc_status_replaced:    st += "Replaced   "; break; /** was deleted and then re-added */
					case svn_wc_status_modified:    st += "Modified   "; break; /** text or props have been modified */
					case svn_wc_status_merged:      st += "Merged     "; break; /** local mods received repos mods */
					case svn_wc_status_conflicted:  st += "Conflicted "; break; /** local mods received conflicting repos mods */
					case svn_wc_status_ignored:     st += "Ignored    "; break; /** is unversioned but configured to be ignored */
					case svn_wc_status_obstructed:  st += "Obstructed "; break; /** an unversioned resource is in the way of the versioned resource */
					case svn_wc_status_external:    st += "External   "; break; /** an unversioned path populated by an svn:externals property */
					case svn_wc_status_incomplete:  st += "Incomplete "; break; /** a directory doesn't contain a complete entries list */
					default:                        st += "Unknown    ";
					};

					msg.append( st);
				}
				msg.append( " ");
				msg.append( ClientUtil::charstar2str( it->m_path, "Path"));
				if( it->m_status && it->m_status->locked)
					msg.append( " locked");
				if( it->m_status && it->m_status->repos_lock)
					msg.append( std::string( " by ") + ClientUtil::charstar2str( it->m_status->repos_lock->owner, "Owner"));
				msg.append( "\n");
			}
			p_statMsg = msg;
		}
	}
	else // vec.empty()
	{
		if( p_assembleStatusMsg)
			p_statMsg = "svn status command failed";
	}
	return rv;
}

#if(0)
			msg = "After issuing 'svn info "; msg += ClientUtil::charstar2str( p_path.c_str(), "Url"); msg += "'";
			for( ClientUtil::InfoHelp::InfoVecConIter it = inf.begin(), en = inf.end(); it != en; ++it)
			{
				msg.append( "\nI know about: '");
				msg.append( ClientUtil::charstar2str( it->m_path, "Path"));
				msg.append( "' the following:");
				if( it->m_info)
				{
					if( !aut.empty()) aut.append( ", "); // if multiple entries in inf, then separate authors by ,

					msg.append( "\n\tLast Changed Author: "); 
					aut.append( ClientUtil::charstar2str( it->m_info->last_changed_author, "Author"));
					msg.append( ClientUtil::charstar2str( it->m_info->last_changed_author, "Author"));

					msg.append( "\n\tVersioned as (URL): "); 
					msg.append( ClientUtil::charstar2str( it->m_info->URL, "Url"));
					
					if( it->m_info->lock)
					{
						msg.append( "\n\tLocked by "); 
						if( !own.empty()) own.append( ", "); // if multiple entries in inf, then separate owners by ,

						own.append( ClientUtil::charstar2str( it->m_info->lock->owner, "LockOwner"));
						msg.append( ClientUtil::charstar2str( it->m_info->lock->owner, "LockOwner"));
					}
					else
						msg.append( "\n\tNot Locked");
				}
				else 
					msg.append( "No detailed info present for item");
			}
#endif

void HiClient::log( const std::string& p_command, const std::string& p_par)
{
	if( !m_logEnabled) return;

	std::ofstream fs;
	fs.open( "c:\\svnlog.txt", std::ios_base::ate | std::ios_base::app); // append
	if( fs)
	{
		fs << p_command << " " << p_par << std::endl;
		fs.close();
	}
}

void HiClient::setLog( bool p_val)
{
	m_logEnabled = p_val;
}

#endif
--- NEW FILE: Client.cpp ---
#include "StdAfx.h"

#if(USESVN)

#include ".\client.h"
#include <crtdbg.h> // for ASSERT
#include <iostream> // remove this later
#include "Pool.h"
#include "Util.h"
#include "svn_client.h"
#include "svn_config.h"

extern std::string g_userName;
extern std::string g_passWord;

//Client::Client(void)
//	: m_notify2( 0)
//	, m_prompter( 0)
//	, m_commitMessageBuilder( 0)
[...1099 lines suppressed...]
		return commit2_info->revision;

	return -1;
}

//
// std::string.append( const char * ) crashes if parameter ptr is 0, that's why this function is useful
//
// static 
std::string ClientUtil::charstar2str( const char* p_charStar, const std::string p_name)
{
	if( p_charStar)
	{
		return std::string( p_charStar);
	}

	return std::string( "<no" + p_name + ">");
}

#endif

--- NEW FILE: ClientUtil.h ---
#pragma once
#include "Revision.h"
#include "Targets.h"
#include "svn_client.h"
#include "Prompter.h"

// class mimicing subversion/bindings/java/javahl/native/svnclient.cpp

class ClientUtil
{
public:
	//
	//   ********  Info *********
	//
	struct InfoHelp
	{
		struct InfoEntry
		{
			const char *m_path;
			svn_info_t *m_info;
		};

		typedef std::vector<InfoEntry> InfoVec;
		typedef InfoVec::const_iterator InfoVecConIter;

		struct InfoBaton
		{
			InfoVec     m_infoVect;
			apr_pool_t *m_pool;
		};

		// callback, which will fill an InfoBaton struct (got in void *baton)
		static svn_error_t * infoReceiver(void *baton, 
										const char *path,
										const svn_info_t *info,
										apr_pool_t *pool);

	};
	
	//
	//   ********  Commit related helper *********
	//
	struct CommitHelp
	{
		class MsgBuilder // builds a proper commit message based on entries
		{
			void dealWithItem( std::string& res, svn_client_commit_item_t * item);
		public:
			std::string build( const apr_array_header_t *commit_items);
		};

		struct LogMsgBaton // log_msg_baton
		{
			const char *      m_message;
			MsgBuilder *      m_messageHandler;
		}; 

		// creates the baton class given to the callback
		static void* createLogMsgBaton( const char * p_strMessage, CommitHelp::MsgBuilder * p_msgComposer);


		// callback, which is called by commit-y operations
		static svn_error_t * logMsg(const char **log_msg,
									const char **tmp_file,
									const apr_array_header_t *commit_items,
									void *baton,
									apr_pool_t *pool);

	};


	//
	//   ********  Notify : a Commit and Checkout related helper *********
	//
	struct NotifyHelp
	{
		/**
		* Handler for Subversion notifications.
		*
		* @param notify all the information about the event
		* @param pool an apr pool to allocated memory
		*/
		void onNotify( const svn_wc_notify_t *notify, apr_pool_t *pool);

		/**
		* notification function passed as svn_wc_notify_func2_t
		* @param baton notification instance is passed using this parameter
		* @param notify all the information about the event
		* @param pool an apr pool to allocated memory
		*/

		// callback, which is called during notification
		static void notify2(void *baton,
						const svn_wc_notify_t *notify,
						apr_pool_t *pool);

	};

	// **************************************
	// other callbacks
	// **************************************
	struct OtherHelp
	{
		static svn_error_t * checkCancel(void *cancelBaton);
	};

	//
	//   ********  Status related helper *********
	//
	struct StatusHelp
	{
		struct StatusEntry
		{
			const char *                   m_path;
			svn_wc_status2_t *             m_status;
		};

		struct StatusBaton
		{
			std::vector<StatusEntry>       m_statusVect;
			apr_pool_t *                   m_pool;
		};

		static void statusReceiver(void *baton, const char *path, 
			svn_wc_status2_t *status);
	};

	typedef std::pair<std::string, long> StatusInfo;
	StatusInfo sub_single_status(const char *path, bool onServer);

	typedef StatusHelp::StatusEntry StatusExtInfo;
	typedef std::vector<StatusExtInfo>   StatusExtInfoVec;
	StatusExtInfoVec sub_extended_status( const char * p_path, bool p_onServer);

	// statics
	static std::string charstar2str( const char* p_charStar, const std::string p_name);

};

--- NEW FILE: Revision.cpp ---
/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003 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 Revision.cpp
 * @brief Implementation of the class Revision
 */


#include "StdAfx.h"

#if(USESVN)

#include "Revision.h"

const svn_opt_revision_kind Revision::START = svn_opt_revision_unspecified;
const svn_opt_revision_kind Revision::HEAD  = svn_opt_revision_head;

Revision::Revision()
{
	m_revision.value.number = 0;
	m_revision.kind = svn_opt_revision_head;
}

Revision::Revision( bool p_head /* = false */, bool p_one /* = false */)
{
	m_revision.kind = svn_opt_revision_unspecified;
	m_revision.value.number = 0;

	if( p_head)
		m_revision.kind = svn_opt_revision_head;
	else if( p_one)
	{
		m_revision.kind = svn_opt_revision_number;
		m_revision.value.number = 1;
	}
}

Revision::Revision (const svn_opt_revision_kind p_kind)
{
	m_revision.kind = p_kind;
	m_revision.value.number = 0;
}

Revision::~Revision()
{
}

const svn_opt_revision_t *Revision::revision () const
{
	return &m_revision;
}

#endif

--- NEW FILE: Prompter.h ---
/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2003-2004 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 Prompter.h
 * @brief Interface of the class Prompter
 */

#if !defined(AFX_PROMPTER_H__6833BB77_DDCC_4BF8_A995_5A5CBC48DF4C__INCLUDED_)
#define AFX_PROMPTER_H__6833BB77_DDCC_4BF8_A995_5A5CBC48DF4C__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "svn_auth.h"
#include <string>

/**
 * An interface to be implemented by subclasses.
 * Callback methods of Prompter::CallbackHelpers will call these methods if needed.
 */

class PromptImpl
{
public:
	PromptImpl() : m_maySave( false) { }
	virtual ~PromptImpl() { }
	
	virtual bool prompt
		(const char *realm, const char *pi_username, bool maySave) = 0;

	virtual bool askYesNo
		(const char *realm, const char *question, bool yesIsDefault) = 0;
    
    virtual int  askTrust
		(const char *question, bool maySave) = 0;

	virtual std::string askQuestion
		( const char *realm, const char *question, bool showAnswer, bool maySave) = 0;

	virtual std::string password() = 0;
	virtual std::string username() = 0;

    /**
     * flag is the user allowed, that the last answer is stored in 
     * the configuration
     */
    bool m_maySave;


	static void scanfBlind( std::string& ret);
};

class TextPromptImpl : public PromptImpl
{
protected:
	std::string m_uName;
	std::string m_pWord;

	enum EntryType
	{
		UserName
		, Password
	};
	std::string readcnf( const EntryType& p_type);

	std::string m_answer;

public:
	TextPromptImpl();
	virtual ~TextPromptImpl();

	virtual bool prompt(const char *realm, const char *pi_username, bool maySave);

	virtual bool askYesNo(const char *realm, const char *question, bool yesIsDefault);

	virtual int  askTrust(const char *question, bool maySave);

	virtual std::string askQuestion(const char *realm, const char *question, bool showAnswer, bool maySave);

	virtual std::string password();
	virtual std::string username();
};

class GPromptImpl : public PromptImpl
{
protected:
	std::string m_uName;
	std::string m_pWord;
	bool        m_credsFilled;

	std::string m_answer;

public:
	GPromptImpl();
	virtual ~GPromptImpl();

	virtual bool prompt(const char *realm, const char *pi_username, bool maySave);

	virtual bool askYesNo(const char *realm, const char *question, bool yesIsDefault);

	virtual int  askTrust(const char *question, bool maySave);

	virtual std::string askQuestion(const char *realm, const char *question, bool showAnswer, bool maySave);

	virtual std::string password();
	virtual std::string username();
};

/**
 * This class helps setting up the prompters and providers for authentication.
 */
class Prompter
{
	PromptImpl * m_impl;
	Prompter( PromptImpl* p_prompter);

public:
	static Prompter *makePrompter( PromptImpl* p_prompter);

	~Prompter();

	svn_auth_provider_object_t *getProviderUsername();
	svn_auth_provider_object_t *getProviderSimple();
	svn_auth_provider_object_t *getProviderServerSSLTrust();
	svn_auth_provider_object_t *getProviderClientSSL();
	svn_auth_provider_object_t *getProviderClientSSLPassword();

	enum PrompUserPass
	{
		AcceptPermanently
		, AcceptTemporary
		, Reject
	};

	class CallbackHelpers
	{
	public:
		static svn_error_t*    simple_prompt(
			svn_auth_cred_simple_t **cred_p,
			void *baton, const char *realm,
			const char *username,
			svn_boolean_t may_save,
			apr_pool_t *pool);

		static svn_error_t*    username_prompt(
			svn_auth_cred_username_t **cred_p,
			void *baton,
			const char *realm,
			svn_boolean_t may_save,
			apr_pool_t *pool);

		static svn_error_t*    ssl_server_trust_prompt(
			svn_auth_cred_ssl_server_trust_t **cred_p,
			void *baton,
			const char *realm,
			apr_uint32_t failures,
			const svn_auth_ssl_server_cert_info_t *cert_info,
			svn_boolean_t may_save,
			apr_pool_t *pool);

		static svn_error_t*    ssl_client_cert_prompt(
			svn_auth_cred_ssl_client_cert_t **cred_p,
			void *baton,
			const char *realm,
			svn_boolean_t may_save,
			apr_pool_t *pool);

		static svn_error_t*    ssl_client_cert_pw_prompt(
			svn_auth_cred_ssl_client_cert_pw_t **cred_p,
			void *baton,
			const char *realm,
			svn_boolean_t may_save,
			apr_pool_t *pool);
	};
};

#endif
// !defined(AFX_PROMPTER_H__6833BB77_DDCC_4BF8_A995_5A5CBC48DF4C__INCLUDED_)



More information about the GME-commit mailing list