diff --git a/maven-scm-providers/maven-scm-providers-svn/maven-scm-provider-svnexe/src/main/java/org/apache/maven/scm/provider/svn/svnexe/command/SvnCommandLineUtils.java b/maven-scm-providers/maven-scm-providers-svn/maven-scm-provider-svnexe/src/main/java/org/apache/maven/scm/provider/svn/svnexe/command/SvnCommandLineUtils.java index cf98f4a9e..a4c9c4a33 100644 --- a/maven-scm-providers/maven-scm-providers-svn/maven-scm-provider-svnexe/src/main/java/org/apache/maven/scm/provider/svn/svnexe/command/SvnCommandLineUtils.java +++ b/maven-scm-providers/maven-scm-providers-svn/maven-scm-provider-svnexe/src/main/java/org/apache/maven/scm/provider/svn/svnexe/command/SvnCommandLineUtils.java @@ -107,25 +107,25 @@ else if ( !StringUtils.isEmpty( SvnUtil.getSettings().getConfigDirectory() ) ) cl.createArg().setValue( SvnUtil.getSettings().getConfigDirectory() ); } - boolean hasAuthInfo = false; + boolean hasAuthInfo = false; if ( repository != null && !StringUtils.isEmpty( repository.getUser() ) ) { - hasAuthInfo = true; + hasAuthInfo = true; cl.createArg().setValue( "--username" ); cl.createArg().setValue( repository.getUser() ); } if ( repository != null && !StringUtils.isEmpty( repository.getPassword() ) ) { - hasAuthInfo = true; + hasAuthInfo = true; cl.createArg().setValue( "--password" ); cl.createArg().setValue( repository.getPassword() ); } - // [by Lenik] don't overwrite existing auth cache by default. - if ( hasAuthInfo && !SvnUtil.getSettings().isUseAuthCache() ) + // [by Lenik] don't overwrite existing auth cache by default. + if ( hasAuthInfo && !SvnUtil.getSettings().isUseAuthCache() ) { - cl.createArg().setValue( "--no-auth-cache" ); + cl.createArg().setValue( "--no-auth-cache" ); } if ( SvnUtil.getSettings().isUseNonInteractive() ) @@ -222,21 +222,48 @@ public static String cryptPassword( Commandline cl ) { String clString = cl.toString(); - int pos = clString.indexOf( "--password" ); + final String passwordArg = "--password "; + String quoteChar; + String escapedQuoteChar; + String cryptedPassword; + + int pos = clString.indexOf( passwordArg ); if ( pos > 0 ) { - String beforePassword = clString.substring( 0, pos + "--password ".length() ); - String afterPassword = clString.substring( pos + "--password ".length() ); - afterPassword = afterPassword.substring( afterPassword.indexOf( ' ' ) ); + String beforePassword = clString.substring( 0, pos + passwordArg.length() ); + String afterPassword = clString.substring( pos + passwordArg.length() ); + if ( Os.isFamily( Os.FAMILY_WINDOWS ) ) { - clString = beforePassword + "*****" + afterPassword; + quoteChar = "\""; + escapedQuoteChar = "\"\""; + cryptedPassword = "*****"; + } + else + { + quoteChar = "'"; + escapedQuoteChar = "'\\''"; + cryptedPassword = "'*****'"; + } + + if ( afterPassword.startsWith( quoteChar ) ) + { + pos = 1; + while ( afterPassword.indexOf( escapedQuoteChar, pos ) != -1 ) + { + pos = afterPassword.indexOf( escapedQuoteChar, pos ) + escapedQuoteChar.length(); + } + afterPassword = afterPassword.substring ( afterPassword.indexOf( quoteChar, pos ) + + quoteChar.length() ); } else { - clString = beforePassword + "'*****'" + afterPassword; + afterPassword = afterPassword.substring( afterPassword.indexOf( ' ' ) ); } + + clString = beforePassword + cryptedPassword + afterPassword; + } return clString; diff --git a/maven-scm-providers/maven-scm-providers-svn/maven-scm-provider-svnexe/src/test/java/org/apache/maven/scm/provider/svn/svnexe/command/SvnCommandLineUtilsTest.java b/maven-scm-providers/maven-scm-providers-svn/maven-scm-provider-svnexe/src/test/java/org/apache/maven/scm/provider/svn/svnexe/command/SvnCommandLineUtilsTest.java index f3a7f8a5c..37f4f834b 100644 --- a/maven-scm-providers/maven-scm-providers-svn/maven-scm-provider-svnexe/src/test/java/org/apache/maven/scm/provider/svn/svnexe/command/SvnCommandLineUtilsTest.java +++ b/maven-scm-providers/maven-scm-providers-svn/maven-scm-provider-svnexe/src/test/java/org/apache/maven/scm/provider/svn/svnexe/command/SvnCommandLineUtilsTest.java @@ -21,8 +21,11 @@ import org.apache.maven.scm.ScmTestCase; import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository; +import org.codehaus.plexus.util.Os; import org.codehaus.plexus.util.cli.Commandline; +import static org.junit.Assert.assertNotEquals; + import java.io.File; /** @@ -35,6 +38,9 @@ public class SvnCommandLineUtilsTest public void testCryptPassword() throws Exception { + /* FIXME Plexus does not quote the crypted password on Windows which is actually incorrect at the moment + * it would cause wildcard expansion with cmd: https://github.com/codehaus-plexus/plexus-utils/issues/37. + */ SvnScmProviderRepository repo = new SvnScmProviderRepository( "https://svn.apache.org/repos/asf/maven/scm/trunk", "username", "password" ); String clString = @@ -48,5 +54,72 @@ public void testCryptPassword() SvnCommandLineUtils.cryptPassword( SvnCommandLineUtils.getBaseSvnCommandLine( new File( "." ), repo ) ); assertCommandLine( "svn --username username --no-auth-cache --non-interactive", new File( "." ), SvnCommandLineUtils.getBaseSvnCommandLine( new File( "." ), repo ) ); + + repo = new SvnScmProviderRepository( "https://svn.apache.org/repos/asf/maven/scm/trunk", "username", "password with spaces" ); + clString = + SvnCommandLineUtils.cryptPassword( SvnCommandLineUtils.getBaseSvnCommandLine( new File( "." ), repo ) ); + expectedCmd = new Commandline( "svn --username username --password ***** --no-auth-cache --non-interactive" ); + expectedCmd.setWorkingDirectory( new File( "." ).getAbsolutePath() ); + assertEquals( expectedCmd.toString(), clString ); + + repo = new SvnScmProviderRepository( "https://svn.apache.org/repos/asf/maven/scm/trunk", "username", "password'with'single'quotes" ); + clString = + SvnCommandLineUtils.cryptPassword( SvnCommandLineUtils.getBaseSvnCommandLine( new File( "." ), repo ) ); + expectedCmd = new Commandline( "svn --username username --password ***** --no-auth-cache --non-interactive" ); + expectedCmd.setWorkingDirectory( new File( "." ).getAbsolutePath() ); + assertEquals( expectedCmd.toString(), clString ); + + repo = new SvnScmProviderRepository( "https://svn.apache.org/repos/asf/maven/scm/trunk", "username", "password'with'single'quotes and spaces" ); + clString = + SvnCommandLineUtils.cryptPassword( SvnCommandLineUtils.getBaseSvnCommandLine( new File( "." ), repo ) ); + expectedCmd = new Commandline( "svn --username username --password ***** --no-auth-cache --non-interactive" ); + expectedCmd.setWorkingDirectory( new File( "." ).getAbsolutePath() ); + assertEquals( expectedCmd.toString(), clString ); + + repo = new SvnScmProviderRepository( "https://svn.apache.org/repos/asf/maven/scm/trunk", "username", "password\"with\"double\"quotes" ); + clString = + SvnCommandLineUtils.cryptPassword( SvnCommandLineUtils.getBaseSvnCommandLine( new File( "." ), repo ) ); + expectedCmd = new Commandline( "svn --username username --password ***** --no-auth-cache --non-interactive" ); + expectedCmd.setWorkingDirectory( new File( "." ).getAbsolutePath() ); + assertEquals( expectedCmd.toString(), clString ); + + repo = new SvnScmProviderRepository( "https://svn.apache.org/repos/asf/maven/scm/trunk", "username", "password\"with\"double\"quotes and spaces" ); + clString = + SvnCommandLineUtils.cryptPassword( SvnCommandLineUtils.getBaseSvnCommandLine( new File( "." ), repo ) ); + expectedCmd = new Commandline( "svn --username username --password ***** --no-auth-cache --non-interactive" ); + expectedCmd.setWorkingDirectory( new File( "." ).getAbsolutePath() ); + // FIXME https://github.com/codehaus-plexus/plexus-utils/issues/36 + if ( Os.isFamily( Os.FAMILY_WINDOWS ) ) + { + assertNotEquals( expectedCmd.toString(), clString ); + } + else { + assertEquals( expectedCmd.toString(), clString ); + } + + repo = new SvnScmProviderRepository( "https://svn.apache.org/repos/asf/maven/scm/trunk", "username", "password\"with\"double\"quotes'and'single'quotes" ); + clString = + SvnCommandLineUtils.cryptPassword( SvnCommandLineUtils.getBaseSvnCommandLine( new File( "." ), repo ) ); + expectedCmd = new Commandline( "svn --username username --password ***** --no-auth-cache --non-interactive" ); + expectedCmd.setWorkingDirectory( new File( "." ).getAbsolutePath() ); + assertEquals( expectedCmd.toString(), clString ); + + repo = new SvnScmProviderRepository( "https://svn.apache.org/repos/asf/maven/scm/trunk", "username", "password\"with\"double\"quotes'and'single'quotes and spaces" ); + clString = + SvnCommandLineUtils.cryptPassword( SvnCommandLineUtils.getBaseSvnCommandLine( new File( "." ), repo ) ); + expectedCmd = new Commandline( "svn --username username --password ***** --no-auth-cache --non-interactive" ); + expectedCmd.setWorkingDirectory( new File( "." ).getAbsolutePath() ); + // FIXME https://github.com/codehaus-plexus/plexus-utils/issues/36 + if ( Os.isFamily( Os.FAMILY_WINDOWS ) ) + { + assertNotEquals( expectedCmd.toString(), clString ); + } + else { + assertEquals( expectedCmd.toString(), clString ); + } + + repo = new SvnScmProviderRepository( "https://svn.apache.org/repos/asf/maven/scm/trunk", "username", null ); + assertCommandLine( "svn --username username --no-auth-cache --non-interactive", new File( "." ), + SvnCommandLineUtils.getBaseSvnCommandLine( new File( "." ), repo ) ); } }