summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/distrib/linux/authority.sh2
-rwxr-xr-xsrc/main/distrib/linux/install-service-fedora.sh10
-rw-r--r--src/main/distrib/linux/migrate-tickets.sh4
-rw-r--r--src/main/distrib/linux/reindex-tickets.sh4
-rw-r--r--src/main/distrib/linux/service-centos.sh6
-rw-r--r--src/main/distrib/linux/service-ubuntu.sh2
-rw-r--r--src/main/java/com/gitblit/manager/AuthenticationManager.java85
-rw-r--r--src/main/java/com/gitblit/utils/StringUtils.java15
-rw-r--r--src/site/federation.mkd2
-rw-r--r--src/site/rpc.mkd2
-rw-r--r--src/site/setup_go.mkd2
-rw-r--r--src/site/upgrade_go.mkd22
-rw-r--r--src/test/java/com/gitblit/tests/AuthenticationManagerTest.java100
-rw-r--r--src/test/java/com/gitblit/tests/StringUtilsTest.java15
14 files changed, 202 insertions, 69 deletions
diff --git a/src/main/distrib/linux/authority.sh b/src/main/distrib/linux/authority.sh
index 740f51a8..c5c6c687 100644
--- a/src/main/distrib/linux/authority.sh
+++ b/src/main/distrib/linux/authority.sh
@@ -1,2 +1,2 @@
#!/bin/bash
-java -cp gitblit.jar:ext/* com.gitblit.authority.GitblitAuthority --baseFolder data
+java -cp "gitblit.jar:ext/*" com.gitblit.authority.GitblitAuthority --baseFolder data
diff --git a/src/main/distrib/linux/install-service-fedora.sh b/src/main/distrib/linux/install-service-fedora.sh
index 4fb43c61..df17590f 100755
--- a/src/main/distrib/linux/install-service-fedora.sh
+++ b/src/main/distrib/linux/install-service-fedora.sh
@@ -18,16 +18,16 @@ After=network.target
[Service]
User=gitblit
Group=gitblit
-Environment="ARGS=-server -Xmx1024M -Djava.awt.headless=true -jar"
+Environment="ARGS=-server -Xmx1024M -Djava.awt.headless=true -cp"
EnvironmentFile=-/etc/sysconfig/gitblit
WorkingDirectory=/opt/gitblit
-ExecStart=/usr/bin/java \$ARGS gitblit.jar --httpsPort \$GITBLIT_HTTPS_PORT --httpPort \$GITBLIT_HTTP_PORT --baseFolder \$GITBLIT_BASE_FOLDER --dailyLogFile
-ExecStop=/usr/bin/java \$ARGS gitblit.jar --baseFolder \$GITBLIT_BASE_FOLDER --stop
+ExecStart=/usr/bin/java \$ARGS gitblit.jar:ext/* com.gitblit.GitBlitServer --httpsPort \$GITBLIT_HTTPS_PORT --httpPort \$GITBLIT_HTTP_PORT --baseFolder \$GITBLIT_BASE_FOLDER --dailyLogFile
+ExecStop=/usr/bin/java \$ARGS gitblit.jar:ext/* com.gitblit.GitBlitServer --baseFolder \$GITBLIT_BASE_FOLDER --stop
[Install]
WantedBy=multi-user.target
EOF
# Finally copy the files to the destination and register the systemd unit.
-sudo su -c "cp /tmp/gitblit.defaults /etc/sysconfig/gitblit && cp /tmp/gitblit.service /etc/systemd/system/"
-sudo su -c "systemctl daemon-reload && systemctl enable gitblit.service && systemctl start gitblit.service"
+sudo sh -c "cp /tmp/gitblit.defaults /etc/sysconfig/gitblit && cp /tmp/gitblit.service /etc/systemd/system/"
+sudo sh -c "systemctl daemon-reload && systemctl enable gitblit.service && systemctl start gitblit.service"
diff --git a/src/main/distrib/linux/migrate-tickets.sh b/src/main/distrib/linux/migrate-tickets.sh
index f521528e..4f360918 100644
--- a/src/main/distrib/linux/migrate-tickets.sh
+++ b/src/main/distrib/linux/migrate-tickets.sh
@@ -8,7 +8,7 @@
#
# --------------------------------------------------------------------------
-if [[ -z $1 || -z $2 ]]; then
+if [ -z $1 ] || [ -z $2 ]; then
echo "Please specify the output ticket service and your baseFolder!";
echo "";
echo "usage:";
@@ -17,5 +17,5 @@ if [[ -z $1 || -z $2 ]]; then
exit 1;
fi
-java -cp gitblit.jar:./ext/* com.gitblit.MigrateTickets $1 --baseFolder $2
+java -cp "gitblit.jar:ext/*" com.gitblit.MigrateTickets $1 --baseFolder $2
diff --git a/src/main/distrib/linux/reindex-tickets.sh b/src/main/distrib/linux/reindex-tickets.sh
index 8261b819..42239ea1 100644
--- a/src/main/distrib/linux/reindex-tickets.sh
+++ b/src/main/distrib/linux/reindex-tickets.sh
@@ -11,7 +11,7 @@
#
# --------------------------------------------------------------------------
-if [[ -z $1 ]]; then
+if [ -z $1 ] ; then
echo "Please specify your baseFolder!";
echo "";
echo "usage:";
@@ -20,5 +20,5 @@ if [[ -z $1 ]]; then
exit 1;
fi
-java -cp gitblit.jar:./ext/* com.gitblit.ReindexTickets --baseFolder $1
+java -cp "gitblit.jar:ext/*" com.gitblit.ReindexTickets --baseFolder $1
diff --git a/src/main/distrib/linux/service-centos.sh b/src/main/distrib/linux/service-centos.sh
index 843f015a..a2645e7e 100644
--- a/src/main/distrib/linux/service-centos.sh
+++ b/src/main/distrib/linux/service-centos.sh
@@ -11,7 +11,7 @@ GITBLIT_HTTP_PORT=0
GITBLIT_HTTPS_PORT=8443
GITBLIT_LOG=/var/log/gitblit.log
source ${GITBLIT_PATH}/java-proxy-config.sh
-JAVA="java -server -Xmx1024M ${JAVA_PROXY_CONFIG} -Djava.awt.headless=true -jar"
+JAVA="java -server -Xmx1024M ${JAVA_PROXY_CONFIG} -Djava.awt.headless=true -cp"
RETVAL=0
@@ -21,7 +21,7 @@ case "$1" in
then
echo $"Starting gitblit server"
cd $GITBLIT_PATH
- $JAVA $GITBLIT_PATH/gitblit.jar --httpsPort $GITBLIT_HTTPS_PORT --httpPort $GITBLIT_HTTP_PORT --baseFolder $GITBLIT_BASE_FOLDER --dailyLogFile &
+ $JAVA "$GITBLIT_PATH/gitblit.jar:$GITBLIT_PATH/ext/*" com.gitblit.GitBlitServer --httpsPort $GITBLIT_HTTPS_PORT --httpPort $GITBLIT_HTTP_PORT --baseFolder $GITBLIT_BASE_FOLDER --dailyLogFile &
echo "."
exit $RETVAL
fi
@@ -32,7 +32,7 @@ case "$1" in
then
echo $"Stopping gitblit server"
cd $GITBLIT_PATH
- $JAVA $GITBLIT_PATH/gitblit.jar --baseFolder $GITBLIT_BASE_FOLDER --stop > /dev/null &
+ $JAVA "$GITBLIT_PATH/gitblit.jar:$GITBLIT_PATH/ext/*" com.gitblit.GitBlitServer --baseFolder $GITBLIT_BASE_FOLDER --stop > /dev/null &
echo "."
exit $RETVAL
fi
diff --git a/src/main/distrib/linux/service-ubuntu.sh b/src/main/distrib/linux/service-ubuntu.sh
index 769e3072..461a678c 100644
--- a/src/main/distrib/linux/service-ubuntu.sh
+++ b/src/main/distrib/linux/service-ubuntu.sh
@@ -19,7 +19,7 @@ GITBLIT_PATH=/opt/gitblit
GITBLIT_BASE_FOLDER=/opt/gitblit/data
GITBLIT_USER="gitblit"
source ${GITBLIT_PATH}/java-proxy-config.sh
-ARGS="-server -Xmx1024M ${JAVA_PROXY_CONFIG} -Djava.awt.headless=true -jar gitblit.jar --baseFolder $GITBLIT_BASE_FOLDER --dailyLogFile"
+ARGS="-server -Xmx1024M ${JAVA_PROXY_CONFIG} -Djava.awt.headless=true -cp gitblit.jar:ext/* com.gitblit.GitBlitServer --baseFolder $GITBLIT_BASE_FOLDER --dailyLogFile"
RETVAL=0
diff --git a/src/main/java/com/gitblit/manager/AuthenticationManager.java b/src/main/java/com/gitblit/manager/AuthenticationManager.java
index 83ca4b70..68c83dae 100644
--- a/src/main/java/com/gitblit/manager/AuthenticationManager.java
+++ b/src/main/java/com/gitblit/manager/AuthenticationManager.java
@@ -18,10 +18,7 @@ package com.gitblit.manager;
import java.nio.charset.Charset;
import java.security.Principal;
import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.Cookie;
@@ -455,7 +452,6 @@ public class AuthenticationManager implements IAuthenticationManager {
/**
* Authenticate a user based on a username and password.
*
- * @see IUserService.authenticate(String, char[])
* @param username
* @param password
* @return a user object or null
@@ -474,34 +470,39 @@ public class AuthenticationManager implements IAuthenticationManager {
}
String usernameDecoded = StringUtils.decodeUsername(username);
- String pw = new String(password);
- if (StringUtils.isEmpty(pw)) {
+ if (StringUtils.isEmpty(password)) {
// can not authenticate empty password
return null;
}
UserModel user = userManager.getUserModel(usernameDecoded);
- // try local authentication
- if (user != null && user.isLocalAccount()) {
- UserModel returnedUser = authenticateLocal(user, password);
- if (returnedUser != null) {
- // user authenticated
- return returnedUser;
- }
- } else {
- // try registered external authentication providers
- for (AuthenticationProvider provider : authenticationProviders) {
- if (provider instanceof UsernamePasswordAuthenticationProvider) {
- UserModel returnedUser = provider.authenticate(usernameDecoded, password);
- if (returnedUser != null) {
- // user authenticated
- returnedUser.accountType = provider.getAccountType();
- return validateAuthentication(returnedUser, AuthenticationType.CREDENTIALS);
+ try {
+ // try local authentication
+ if (user != null && user.isLocalAccount()) {
+ UserModel returnedUser = authenticateLocal(user, password);
+ if (returnedUser != null) {
+ // user authenticated
+ return returnedUser;
+ }
+ } else {
+ // try registered external authentication providers
+ for (AuthenticationProvider provider : authenticationProviders) {
+ if (provider instanceof UsernamePasswordAuthenticationProvider) {
+ UserModel returnedUser = provider.authenticate(usernameDecoded, password);
+ if (returnedUser != null) {
+ // user authenticated
+ returnedUser.accountType = provider.getAccountType();
+ return validateAuthentication(returnedUser, AuthenticationType.CREDENTIALS);
+ }
}
}
}
}
+ finally {
+ // Zero out password array to delete password from memory
+ Arrays.fill(password, Character.MIN_VALUE);
+ }
// could not authenticate locally or with a provider
logger.warn(MessageFormat.format("Failed login attempt for {0}, invalid credentials from {1}", username,
@@ -520,21 +521,33 @@ public class AuthenticationManager implements IAuthenticationManager {
protected UserModel authenticateLocal(UserModel user, char [] password) {
UserModel returnedUser = null;
- PasswordHash pwdHash = PasswordHash.instanceFor(user.password);
- if (pwdHash != null) {
- if (pwdHash.matches(user.password, password, user.username)) {
+ // Create a copy of the password that we can use to rehash to upgrade to a more secure hashing method.
+ // This is done to be independent from the implementation of the PasswordHash, which might already clear out
+ // the password it gets passed in. This looks a bit stupid, as we could simply clean up the mess, but this
+ // falls under "better safe than sorry".
+ char[] pwdToUpgrade = Arrays.copyOf(password, password.length);
+ try {
+ PasswordHash pwdHash = PasswordHash.instanceFor(user.password);
+ if (pwdHash != null) {
+ if (pwdHash.matches(user.password, password, user.username)) {
+ returnedUser = user;
+ }
+ } else if (user.password.equals(new String(password))) {
+ // plain-text password
returnedUser = user;
}
- } else if (user.password.equals(new String(password))) {
- // plain-text password
- returnedUser = user;
- }
-
- // validate user
- returnedUser = validateAuthentication(returnedUser, AuthenticationType.CREDENTIALS);
-
- // try to upgrade the stored password hash to a stronger hash, if necessary
- upgradeStoredPassword(returnedUser, password, pwdHash);
+
+ // validate user
+ returnedUser = validateAuthentication(returnedUser, AuthenticationType.CREDENTIALS);
+
+ // try to upgrade the stored password hash to a stronger hash, if necessary
+ upgradeStoredPassword(returnedUser, pwdToUpgrade, pwdHash);
+ }
+ finally {
+ // Now we make sure that the password is zeroed out in any case.
+ Arrays.fill(password, Character.MIN_VALUE);
+ Arrays.fill(pwdToUpgrade, Character.MIN_VALUE);
+ }
return returnedUser;
}
diff --git a/src/main/java/com/gitblit/utils/StringUtils.java b/src/main/java/com/gitblit/utils/StringUtils.java
index b192c80b..442acbbf 100644
--- a/src/main/java/com/gitblit/utils/StringUtils.java
+++ b/src/main/java/com/gitblit/utils/StringUtils.java
@@ -57,6 +57,21 @@ public class StringUtils {
}
/**
+ * Returns true if the character array represents an empty String.
+ * An empty character sequence is defined as a sequence that
+ * either has no characters at all, or no characters above
+ * '\u0020' (space).
+ *
+ * @param value
+ * @return true if value is null or represents an empty String
+ */
+ public static boolean isEmpty(char[] value) {
+ if (value == null || value.length == 0) return true;
+ for ( char c : value) if (c > '\u0020') return false;
+ return true;
+ }
+
+ /**
* Replaces carriage returns and line feeds with html line breaks.
*
* @param string
diff --git a/src/site/federation.mkd b/src/site/federation.mkd
index 231a9f35..b802a087 100644
--- a/src/site/federation.mkd
+++ b/src/site/federation.mkd
@@ -335,6 +335,6 @@ Instead of using `federation.properties` you may directly specify a Gitblit inst
java -cp fedclient.jar;"%CD%/ext/*" com.gitblit.FederationClient --url https://go.gitblit.com --mirror --bare --token 123456789
--repositoriesFolder c:/mymirror
- java -cp fedclient.jar:ext/* com.gitblit.FederationClient --url https://go.gitblit.com --mirror --bare --token 123456789
+ java -cp "fedclient.jar:ext/*" com.gitblit.FederationClient --url https://go.gitblit.com --mirror --bare --token 123456789
--repositoriesFolder /srv/mymirror --daemon --frequency "24 hours"
diff --git a/src/site/rpc.mkd b/src/site/rpc.mkd
index e51fbaae..ac963a87 100644
--- a/src/site/rpc.mkd
+++ b/src/site/rpc.mkd
@@ -8,7 +8,7 @@ Gitblit optionally allows a remote client to administer the Gitblit server. Thi
web.enableRpcManagement=false
web.enableRpcAdministration=false
-**https** is strongly recommended because passwords are insecurely transmitted form your browser/rpc client using Basic authentication!
+**https** is strongly recommended because passwords are insecurely transmitted from your browser/rpc client using Basic authentication!
The Gitblit JSON RPC mechanism, like the Gitblit JGit servlet, syndication/feed servlet, etc, supports request-based authentication. Making an *admin* request will trigger Gitblit's basic authentication mechanism. Listing of repositories, generally, will not trigger this authentication mechanism unless *web.authenticateViewPages=true*. That means its possible to allow anonymous enumeration of repositories that are not *view restricted* or *clone restricted*. Of course, if credentials are provided then all private repositories that are available to the user account will be enumerated in the JSON response.
diff --git a/src/site/setup_go.mkd b/src/site/setup_go.mkd
index 20b4ba48..e0470f31 100644
--- a/src/site/setup_go.mkd
+++ b/src/site/setup_go.mkd
@@ -17,7 +17,7 @@ Open `data/gitblit.properties` in your favorite text editor and make sure to rev
**NOTE:** You can only have **one** SSL certificate specified for a port.
4. exit the authority app
4. Windows: Execute `gitblit.cmd` or `java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --baseFolder data` from a command-line
- Linux/OSX: Execute `gitblit.sh` or `java -cp gitblit.jar;ext/* com.gitblit.GitBlitServer --baseFolder data` from a command-line
+ Linux/OSX: Execute `gitblit.sh` or `java -cp "gitblit.jar:ext/*"" com.gitblit.GitBlitServer --baseFolder data` from a command-line
5. Open your browser to <http://localhost:8080> or <https://localhost:8443> depending on your chosen configuration.
6. Enter the default administrator credentials: **admin / admin** and click the *Login* button
**NOTE:** Make sure to change the administrator username and/or password!!
diff --git a/src/site/upgrade_go.mkd b/src/site/upgrade_go.mkd
index a0092588..4bc2272f 100644
--- a/src/site/upgrade_go.mkd
+++ b/src/site/upgrade_go.mkd
@@ -1,3 +1,25 @@
+## Upgrading Gitblit GO (1.9.1+)
+
+The command line to start Gitblit has changed from
+
+```
+java -jar gitblit.jar --baseFolder data
+```
+
+to
+
+```
+java -cp "gitblit.jar:ext/*" com.gitblit.GitBlitServer --baseFolder data
+```
+
+or on Windows to
+
+```
+java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --baseFolder data
+```
+
+The class path and main class need to be specified now. If you have installed Gitblit as a service you will need to adjust the service scripts or definitions accordingly.
+
## Upgrading Gitblit GO (1.7.0+)
The default `gitblit.properties` file has been split into two files: `gitblit.properties`, which is the recommended file for setting your configuration, and `defaults.properties` which are Gitblit's default settings.
diff --git a/src/test/java/com/gitblit/tests/AuthenticationManagerTest.java b/src/test/java/com/gitblit/tests/AuthenticationManagerTest.java
index 45009856..81d68895 100644
--- a/src/test/java/com/gitblit/tests/AuthenticationManagerTest.java
+++ b/src/test/java/com/gitblit/tests/AuthenticationManagerTest.java
@@ -19,13 +19,7 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
+import java.util.*;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
@@ -654,16 +648,84 @@ public class AuthenticationManagerTest extends GitblitUnitTest {
public void testAuthenticate() throws Exception {
IAuthenticationManager auth = newAuthenticationManager();
+
+ String password = "pass word";
UserModel user = new UserModel("sunnyjim");
- user.password = "password";
+ user.password = password;
users.updateUserModel(user);
- assertNotNull(auth.authenticate(user.username, user.password.toCharArray(), null));
+ char[] pwd = password.toCharArray();
+ assertNotNull(auth.authenticate(user.username, pwd, null));
+
+ // validate that the passed in password has been zeroed out in memory
+ char[] zeroes = new char[pwd.length];
+ Arrays.fill(zeroes, Character.MIN_VALUE);
+ assertArrayEquals(zeroes, pwd);
+ }
+
+
+ @Test
+ public void testAuthenticateDisabledUser() throws Exception {
+ IAuthenticationManager auth = newAuthenticationManager();
+
+
+ String password = "password";
+ UserModel user = new UserModel("sunnyjim");
+ user.password = password;
user.disabled = true;
+ users.updateUserModel(user);
+
+ assertNull(auth.authenticate(user.username, password.toCharArray(), null));
+
+ user.disabled = false;
+ users.updateUserModel(user);
+ assertNotNull(auth.authenticate(user.username, password.toCharArray(), null));
+ }
+
+
+ @Test
+ public void testAuthenticateEmptyPassword() throws Exception {
+ IAuthenticationManager auth = newAuthenticationManager();
+
+
+ String password = "password";
+ UserModel user = new UserModel("sunnyjim");
+ user.password = password;
+ users.updateUserModel(user);
+ assertNull(auth.authenticate(user.username, "".toCharArray(), null));
+ assertNull(auth.authenticate(user.username, " ".toCharArray(), null));
+ assertNull(auth.authenticate(user.username, new char[]{' ', '\u0010', '\u0015'}, null));
+ }
+
+
+
+
+ @Test
+ public void testAuthenticateWrongPassword() throws Exception {
+ IAuthenticationManager auth = newAuthenticationManager();
+
+
+ String password = "password";
+ UserModel user = new UserModel("sunnyjim");
+ user.password = password;
users.updateUserModel(user);
- assertNull(auth.authenticate(user.username, user.password.toCharArray(), null));
- users.deleteUserModel(user);
+
+ assertNull(auth.authenticate(user.username, "helloworld".toCharArray(), null));
+ }
+
+
+ @Test
+ public void testAuthenticateNoSuchUser() throws Exception {
+ IAuthenticationManager auth = newAuthenticationManager();
+
+
+ String password = "password";
+ UserModel user = new UserModel("sunnyjim");
+ user.password = password;
+ users.updateUserModel(user);
+
+ assertNull(auth.authenticate("rainyjoe", password.toCharArray(), null));
}
@@ -671,14 +733,18 @@ public class AuthenticationManagerTest extends GitblitUnitTest {
public void testAuthenticateUpgradePlaintext() throws Exception {
IAuthenticationManager auth = newAuthenticationManager();
+ String password = "topsecret";
UserModel user = new UserModel("sunnyjim");
- user.password = "password";
+ user.password = password;
users.updateUserModel(user);
- assertNotNull(auth.authenticate(user.username, user.password.toCharArray(), null));
+ assertNotNull(auth.authenticate(user.username, password.toCharArray(), null));
// validate that plaintext password was automatically updated to hashed one
assertTrue(user.password.startsWith(PasswordHash.getDefaultType().name() + ":"));
+
+ // validate that the password is still valid and the user can log in
+ assertNotNull(auth.authenticate(user.username, password.toCharArray(), null));
}
@@ -686,14 +752,18 @@ public class AuthenticationManagerTest extends GitblitUnitTest {
public void testAuthenticateUpgradeMD5() throws Exception {
IAuthenticationManager auth = newAuthenticationManager();
+ String password = "secretAndHashed";
UserModel user = new UserModel("sunnyjim");
- user.password = "MD5:5F4DCC3B5AA765D61D8327DEB882CF99";
+ user.password = "MD5:BD95A1CFD00868B59B3564112D1E5847";
users.updateUserModel(user);
- assertNotNull(auth.authenticate(user.username, "password".toCharArray(), null));
+ assertNotNull(auth.authenticate(user.username, password.toCharArray(), null));
// validate that MD5 password was automatically updated to hashed one
assertTrue(user.password.startsWith(PasswordHash.getDefaultType().name() + ":"));
+
+ // validate that the password is still valid and the user can log in
+ assertNotNull(auth.authenticate(user.username, password.toCharArray(), null));
}
diff --git a/src/test/java/com/gitblit/tests/StringUtilsTest.java b/src/test/java/com/gitblit/tests/StringUtilsTest.java
index 7176b88c..3dae66f4 100644
--- a/src/test/java/com/gitblit/tests/StringUtilsTest.java
+++ b/src/test/java/com/gitblit/tests/StringUtilsTest.java
@@ -26,13 +26,26 @@ public class StringUtilsTest extends GitblitUnitTest {
@Test
public void testIsEmpty() throws Exception {
- assertTrue(StringUtils.isEmpty(null));
+ assertTrue(StringUtils.isEmpty((String)null));
assertTrue(StringUtils.isEmpty(""));
assertTrue(StringUtils.isEmpty(" "));
assertFalse(StringUtils.isEmpty("A"));
}
@Test
+ public void testIsEmptyCharArray() throws Exception {
+ assertTrue(StringUtils.isEmpty((char[])null));
+ assertTrue(StringUtils.isEmpty(new char[0]));
+ assertTrue(StringUtils.isEmpty(new char[]{ ' ' }));
+ assertTrue(StringUtils.isEmpty(new char[]{ ' '}));
+ assertTrue(StringUtils.isEmpty(new char[]{ ' ', ' ' }));
+ assertTrue(StringUtils.isEmpty(new char[]{ ' ', ' ', ' ' }));
+ assertFalse(StringUtils.isEmpty(new char[]{ '\u0020', 'f' }));
+ assertFalse(StringUtils.isEmpty(new char[]{ '\u0148', '\u0020' }));
+ assertFalse(StringUtils.isEmpty(new char[]{ 'A' }));
+ }
+
+ @Test
public void testBreakLinesForHtml() throws Exception {
String input = "this\nis\r\na\rtest\r\n\r\nof\n\nline\r\rbreaking";
String output = "this<br/>is<br/>a<br/>test<br/><br/>of<br/><br/>line<br/><br/>breaking";