James Moger
2011-04-15 87cc1ed60735a419a3ea23f20614fc0a3f9bab60
Settings overhaul. Fixes to authentication.  Bind interface feature.

Settings access has been abstracted and the way is becoming clear to
offer a WAR build in addition to the integrated server stack. Util
methods moved around.
2 files renamed
4 files added
31 files modified
810 ■■■■■ changed files
build.xml 1 ●●●● patch | view | raw | blame | history
gitblit.properties 47 ●●●●● patch | view | raw | blame | history
src/com/gitblit/Build.java 71 ●●●●● patch | view | raw | blame | history
src/com/gitblit/FileSettings.java 41 ●●●●● patch | view | raw | blame | history
src/com/gitblit/GitBlit.java 63 ●●●● patch | view | raw | blame | history
src/com/gitblit/GitBlitServer.java 50 ●●●●● patch | view | raw | blame | history
src/com/gitblit/IStoredSettings.java 23 ●●●●● patch | view | raw | blame | history
src/com/gitblit/WebXmlSettings.java 65 ●●●●● patch | view | raw | blame | history
src/com/gitblit/utils/ByteFormat.java 5 ●●●●● patch | view | raw | blame | history
src/com/gitblit/utils/HtmlDiffFormatter.java 2 ●●● patch | view | raw | blame | history
src/com/gitblit/utils/PatchFormatter.java 2 ●●● patch | view | raw | blame | history
src/com/gitblit/utils/StringUtils.java 110 ●●●●● patch | view | raw | blame | history
src/com/gitblit/utils/TimeUtils.java 49 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/AuthorizationStrategy.java 23 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/BasePage.html 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/BasePage.java 18 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/GitBlitWebApp.java 17 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/GitBlitWebApp.properties 6 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/LinkPanel.java 4 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/LoginPage.html 12 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/LoginPage.java 35 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/LogoutPage.java 12 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/RepositoryPage.java 23 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/User.java 10 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/WicketUtils.java 38 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/BlobPage.java 8 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/RawPage.java 5 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/RepositoriesPage.java 15 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/SummaryPage.java 11 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/TicGitPage.java 5 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/TicGitTicketPage.html 5 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/TicGitTicketPage.java 8 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/BasePanel.java 4 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/BranchesPanel.java 3 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/LogPanel.java 7 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/PageLinksPanel.java 7 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/TagsPanel.java 3 ●●●● patch | view | raw | blame | history
build.xml
@@ -17,6 +17,7 @@
        <javac srcdir="${basedir}/src" destdir="${project.build.dir}">
            <include name="com/gitblit/Build.java" />
            <include name="com/gitblit/Constants.java" />
            <include name="com/gitblit/utils/StringUtils.java" />
        </javac>
        <java classpath="${project.build.dir}" classname="com.gitblit.Build" />
gitblit.properties
@@ -33,25 +33,14 @@
server.realmFile = users.properties
#
# Server Settings
#
server.debugMode = true
server.tempFolder = temp
server.log4jPattern = %-5p %d{MM-dd HH:mm:ss.SSS}  %-20.20c{1}  %m%n
# Aggressive heap management will run the garbage collector on every generated
# page.  This slows down page generation but improves heap consumption.
server.aggressiveHeapManagement = true
#
# Git:Blit UI Settings
# Git:Blit Web Settings
#
web.siteName =
# If authenticateWebUI=true, users with "admin" role can create repositories,
# If web.authenticate=true, users with "admin" role can create repositories,
# create users, and edit repository metadata (owner, description, etc)
#
# If authenticateWebUI=false, any user can execute the aforementioned functions.
# If web.authenticate=false, any user can execute the aforementioned functions.
web.allowAdministration = true
# This is the message display above the repositories table.
@@ -92,18 +81,36 @@
# Registered extensions for binary blobs
web.binaryExtensions = jar pdf tar.gz zip
# Aggressive heap management will run the garbage collector on every generated
# page.  This slows down page generation but improves heap consumption.
web.aggressiveHeapManagement = true
# Run the webapp in debug mode
web.debugMode = true
# Enable/disable global regex substitutions (i.e. shared across repositories)
regex.global = true
# Example global regex substitutions
# Use !!! to separate the search pattern and the replace pattern
# searchpattern!!!replacepattern
regex.global.bug = \\b(Bug:)(\\s*[#]?|-){0,1}(\\d+)\\b!!!<a href="http://somehost/bug/$3">Bug-Id: $3</a>
regex.global.changeid = \\b(Change-Id:\\s*)([A-Za-z0-9]*)\\b!!!<a href="http://somehost/changeid/$2">Change-Id: $2</a>
# Example per-repository regex substitutions overrides global
#regex.myrepository.bug = \\b(Bug:)(\\s*[#]?|-){0,1}(\\d+)\\b!!!<a href="http://elsewhere/bug/$3">Bug-Id: $3</a>
# Enable ticgit viewer for all repositories (checks for ticgit branch)
# Enable ticgit pages for all repositories (if ticgit branch is present)
ticgit.global = false
# Enable ticgit viewer for specified repository (checks for ticgit branch)
# Enable ticgit pages for specified repository (if ticgit branch is present)
#ticgit.myrepository = true
#
# Server Settings
#
server.tempFolder = temp
server.log4jPattern = %-5p %d{MM-dd HH:mm:ss.SSS}  %-20.20c{1}  %m%n
#
# Jetty Settings
@@ -118,6 +125,14 @@
# Secure/SSL https port to serve. <= 0 disables this connector.
server.httpsPort = 443
# Specify the interface for Jetty to bind the standard connector.
# You may specify an ip or an empty value to bind to all interfaces.
server.httpBindInterface = localhost
# Specify the interface for Jetty to bind the secure connector.
# You may specify an ip or an empty value to bind to all interfaces.
server.httpsBindInterface = localhost
# Password for SSL keystore (keystore password and certificate password must match)
server.storePassword = dosomegit
src/com/gitblit/Build.java
@@ -8,13 +8,15 @@
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import com.gitblit.utils.StringUtils;
public class Build {
@@ -41,6 +43,7 @@
    }
    public static void buildSettingKeys() {
        // Load all keys
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream(Constants.PROPERTIES_FILE));
@@ -50,6 +53,23 @@
        List<String> keys = new ArrayList<String>(properties.stringPropertyNames());
        Collections.sort(keys);
        // Determine static key group classes
        Map<String, List<String>> staticClasses = new HashMap<String, List<String>>();
        staticClasses.put("", new ArrayList<String>());
        for (String key : keys) {
            String clazz = "";
            String field = key;
            if (key.indexOf('.') > -1) {
                clazz = key.substring(0, key.indexOf('.'));
                field = key.substring(key.indexOf('.') + 1);
            }
            if (!staticClasses.containsKey(clazz)) {
                staticClasses.put(clazz, new ArrayList<String>());
            }
            staticClasses.get(clazz).add(field);
        }
        // Assemble Keys source file
        StringBuilder sb = new StringBuilder();
        sb.append("package com.gitblit;\n");
        sb.append("\n");
@@ -59,10 +79,28 @@
        sb.append(" */\n");
        sb.append("public final class Keys {\n");
        sb.append("\n");
        for (String key : keys) {
            sb.append(MessageFormat.format("\tpublic static final String {0} = \"{1}\";\n\n", key.replace('.', '_'), key));
        List<String> classSet = new ArrayList<String>(staticClasses.keySet());
        Collections.sort(classSet);
        for (String clazz : classSet) {
            List<String> keySet = staticClasses.get(clazz);
            if (clazz.equals("")) {
                // root keys
                for (String key : keySet) {
                    sb.append(MessageFormat.format("\tpublic static final String {0} = \"{1}\";\n\n", key.replace('.', '_'), key));
                }
            } else {
                // class keys
                sb.append(MessageFormat.format("\tpublic static final class {0} '{'\n\n", clazz));
                sb.append(MessageFormat.format("\t\tpublic static final String _ROOT = \"{0}\";\n\n", clazz));
                for (String key : keySet) {
                    sb.append(MessageFormat.format("\t\tpublic static final String {0} = \"{1}\";\n\n", key.replace('.', '_'), clazz + "." + key));
                }
                sb.append("\t}\n\n");
            }
        }
        sb.append("}");
        // Save Keys class definition
        try {
            File file = new File("src/com/gitblit/Keys.java");
            file.delete();
@@ -119,7 +157,7 @@
            throw new RuntimeException("Error downloading " + mavenURL + " to " + targetFile, e);
        }
        byte[] data = buff.toByteArray();
        String got = getSHA1(data);
        String got = StringUtils.getSHA1(data);
        if (mo.sha1 != null && !got.equals(mo.sha1)) {
            throw new RuntimeException("SHA1 checksum mismatch; got: " + got);
        }
@@ -132,29 +170,6 @@
            throw new RuntimeException("Error writing to file " + targetFile, e);
        }
        return targetFile;
    }
    /**
     * Generate the SHA1 checksum of a byte array.
     *
     * @param data
     *            the byte array
     * @return the SHA1 checksum
     */
    public static String getSHA1(byte[] data) {
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("SHA-1");
            byte[] value = md.digest(data);
            StringBuilder buff = new StringBuilder(value.length * 2);
            for (byte c : value) {
                int x = c & 0xff;
                buff.append(Integer.toString(x >> 4, 16)).append(Integer.toString(x & 0xf, 16));
            }
            return buff.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
    private static class MavenObject {
src/com/gitblit/FileSettings.java
File was renamed from src/com/gitblit/StoredSettings.java
@@ -11,18 +11,19 @@
import org.slf4j.LoggerFactory;
/**
 * Reads settings file.
 * Reads GitBlit settings file.
 * 
 */
public class StoredSettings {
public class FileSettings implements IStoredSettings {
    private static Properties properties = new Properties();
    private Properties properties = new Properties();
    private static long lastread = 0;
    private long lastread = 0;
    private static final Logger logger = LoggerFactory.getLogger(StoredSettings.class);
    private final Logger logger = LoggerFactory.getLogger(FileSettings.class);
    public static List<String> getAllKeys(String startingWith) {
    @Override
    public List<String> getAllKeys(String startingWith) {
        startingWith = startingWith.toLowerCase();
        List<String> keys = new ArrayList<String>();
        Properties props = read();
@@ -35,7 +36,8 @@
        return keys;
    }
    public static boolean getBoolean(String name, boolean defaultValue) {
    @Override
    public boolean getBoolean(String name, boolean defaultValue) {
        Properties props = read();
        if (props.containsKey(name)) {
            try {
@@ -50,7 +52,8 @@
        return defaultValue;
    }
    public static int getInteger(String name, int defaultValue) {
    @Override
    public int getInteger(String name, int defaultValue) {
        Properties props = read();
        if (props.containsKey(name)) {
            try {
@@ -65,7 +68,8 @@
        return defaultValue;
    }
    public static String getString(String name, String defaultValue) {
    @Override
    public String getString(String name, String defaultValue) {
        Properties props = read();
        if (props.containsKey(name)) {
            try {
@@ -80,15 +84,18 @@
        return defaultValue;
    }
    public static List<String> getStrings(String name) {
    @Override
    public List<String> getStrings(String name) {
        return getStrings(name, " ");
    }
    public static List<String> getStringsFromValue(String value) {
    @Override
    public List<String> getStringsFromValue(String value) {
        return getStringsFromValue(value, " ");
    }
    public static List<String> getStrings(String name, String separator) {
    @Override
    public List<String> getStrings(String name, String separator) {
        List<String> strings = new ArrayList<String>();
        Properties props = read();
        if (props.containsKey(name)) {
@@ -98,7 +105,8 @@
        return strings;
    }
    public static List<String> getStringsFromValue(String value, String separator) {
    @Override
    public List<String> getStringsFromValue(String value, String separator) {
        List<String> strings = new ArrayList<String>();
        try {
            String[] chunks = value.split(separator);
@@ -113,7 +121,7 @@
        return strings;
    }
    private static synchronized Properties read() {
    private synchronized Properties read() {
        File file = new File(Constants.PROPERTIES_FILE);
        if (file.exists() && (file.lastModified() > lastread)) {
            try {
@@ -127,4 +135,9 @@
        }
        return properties;
    }
    @Override
    public String toString() {
        return getClass().getSimpleName() + ": " + new File(Constants.PROPERTIES_FILE).getAbsolutePath();
    }
}
src/com/gitblit/GitBlit.java
@@ -5,6 +5,8 @@
import java.util.Date;
import java.util.List;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
@@ -22,38 +24,43 @@
import com.gitblit.wicket.User;
import com.gitblit.wicket.models.RepositoryModel;
public class GitBlit {
public class GitBlit implements ServletContextListener {
    private static GitBlit gitblit;
    private final static GitBlit gitblit;
    private final Logger logger = LoggerFactory.getLogger(GitBlit.class);
    private final boolean debugMode;
    private FileResolver repositoryResolver;
    private final FileResolver repositoryResolver;
    private File repositories;
    private final File repositories;
    private final boolean exportAll;
    private boolean exportAll;
    private ILoginService loginService;
    private IStoredSettings storedSettings;
    static {
        gitblit = new GitBlit();
    }
    public static GitBlit self() {
        if (gitblit == null) {
            gitblit = new GitBlit();
        }
        return gitblit;
    }
    private GitBlit() {
        repositories = new File(StoredSettings.getString(Keys.git_repositoriesFolder, "repos"));
        exportAll = StoredSettings.getBoolean(Keys.git_exportAll, true);
        repositoryResolver = new FileResolver(repositories, exportAll);
        debugMode = StoredSettings.getBoolean(Keys.server_debugMode, false);
    }
    public IStoredSettings settings() {
        return storedSettings;
    }
    public boolean isDebugMode() {
        return debugMode;
        return storedSettings.getBoolean(Keys.web.debugMode, false);
    }
    public String getCloneUrl(String repositoryName) {
        return storedSettings.getString(Keys.git.cloneUrl, "https://localhost/git/") + repositoryName;
    }
    public void setLoginService(ILoginService loginService) {
@@ -90,7 +97,7 @@
    }
    public List<String> getRepositoryList() {
        return JGitUtils.getRepositoryList(repositories, exportAll, StoredSettings.getBoolean(Keys.git_nestedRepositories, true));
        return JGitUtils.getRepositoryList(repositories, exportAll, storedSettings.getBoolean(Keys.git.nestedRepositories, true));
    }
    public List<RepositoryModel> getRepositories(Request request) {
@@ -124,4 +131,28 @@
        }
        return r;
    }
    public void setupContext(IStoredSettings settings) {
        logger.info("Setting up GitBlit context from " + settings.toString());
        this.storedSettings = settings;
        repositories = new File(settings.getString(Keys.git.repositoriesFolder, "repos"));
        exportAll = settings.getBoolean(Keys.git.exportAll, true);
        repositoryResolver = new FileResolver(repositories, exportAll);
    }
    @Override
    public void contextInitialized(ServletContextEvent contextEvent) {
        logger.info("GitBlit context initialization by servlet container...");
        if (storedSettings == null) {
            WebXmlSettings webxmlSettings = new WebXmlSettings(contextEvent.getServletContext());
            setupContext(webxmlSettings);
        } else {
            logger.info("GitBlit context already setup by " + storedSettings.toString());
        }
    }
    @Override
    public void contextDestroyed(ServletContextEvent contextEvent) {
        logger.info("GitBlit context destroyed by servlet container.");
    }
}
src/com/gitblit/GitBlitServer.java
@@ -11,6 +11,7 @@
import java.net.URL;
import java.net.UnknownHostException;
import java.security.ProtectionDomain;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
@@ -44,12 +45,15 @@
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import com.beust.jcommander.Parameters;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebApp;
public class GitBlitServer {
    private final static Logger logger = Log.getLogger(GitBlitServer.class.getSimpleName());
    private final static String border_star = "***********************************************************";
    private final static FileSettings fileSettings = new FileSettings();
    public static void main(String[] args) {
        Params params = new Params();
@@ -106,10 +110,7 @@
     * Start Server.
     */
    private static void start(Params params) {
        // instantiate GitBlit
        GitBlit.self();
        PatternLayout layout = new PatternLayout(StoredSettings.getString(Keys.server_log4jPattern, "%-5p %d{MM-dd HH:mm:ss.SSS}  %-20.20c{1}  %m%n"));
        PatternLayout layout = new PatternLayout(fileSettings.getString(Keys.server.log4jPattern, "%-5p %d{MM-dd HH:mm:ss.SSS}  %-20.20c{1}  %m%n"));
        org.apache.log4j.Logger rootLogger = org.apache.log4j.Logger.getRootLogger();
        rootLogger.addAppender(new ConsoleAppender(layout));
@@ -121,20 +122,26 @@
        String osversion = System.getProperty("os.version");
        logger.info("Running on " + osname + " (" + osversion + ")");
        if (StoredSettings.getBoolean(Keys.server_debugMode, false)) {
            logger.warn("DEBUG Mode");
        }
        // Determine port connectors
        List<Connector> connectors = new ArrayList<Connector>();
        if (params.port > 0) {
            Connector httpConnector = createConnector(params.useNIO, params.port);
            String bindInterface = fileSettings.getString(Keys.server.httpBindInterface, null);
            if (!StringUtils.isEmpty(bindInterface)) {
                logger.warn(MessageFormat.format("Binding port {0} to {1}", params.port, bindInterface));
                httpConnector.setHost(bindInterface);
            }
            connectors.add(httpConnector);
        }
        if (params.securePort > 0) {
            if (new File("keystore").exists()) {
                Connector secureConnector = createSSLConnector(params.useNIO, params.securePort, params.storePassword);
                String bindInterface = fileSettings.getString(Keys.server.httpsBindInterface, null);
                if (!StringUtils.isEmpty(bindInterface)) {
                    logger.warn(MessageFormat.format("Binding port {0} to {1}", params.port, bindInterface));
                    secureConnector.setHost(bindInterface);
                }
                connectors.add(secureConnector);
            } else {
                logger.warn("Failed to find Keystore?  Did you run \"makekeystore\"?");
@@ -177,7 +184,7 @@
        // Git Servlet
        ServletHolder gitServlet = null;
        String gitServletPathSpec = "/git/*";
        if (StoredSettings.getBoolean(Keys.git_allowPushPull, true)) {
        if (fileSettings.getBoolean(Keys.git.allowPushPull, true)) {
            gitServlet = rootContext.addServlet(GitServlet.class, gitServletPathSpec);
            gitServlet.setInitParameter("base-path", params.repositoriesFolder);
            gitServlet.setInitParameter("export-all", params.exportAll ? "1" : "0");
@@ -234,6 +241,11 @@
        // Set the server's contexts
        server.setHandler(handler);
        // Setup the GitBlit context
        GitBlit gitblit = GitBlit.self();
        gitblit.setupContext(fileSettings);
        rootContext.addEventListener(gitblit);
        // Start the Server
        try {
@@ -356,43 +368,43 @@
        public Boolean stop = false;
        @Parameter(names = { "--temp" }, description = "Server temp folder")
        public String temp = StoredSettings.getString(Keys.server_tempFolder, "temp");
        public String temp = fileSettings.getString(Keys.server.tempFolder, "temp");
        /*
         * GIT Servlet Parameters
         */
        @Parameter(names = { "--repos" }, description = "Git Repositories Folder")
        public String repositoriesFolder = StoredSettings.getString(Keys.git_repositoriesFolder, "repos");
        public String repositoriesFolder = fileSettings.getString(Keys.git.repositoriesFolder, "repos");
        @Parameter(names = { "--exportAll" }, description = "Export All Found Repositories")
        public Boolean exportAll = StoredSettings.getBoolean(Keys.git_exportAll, true);
        public Boolean exportAll = fileSettings.getBoolean(Keys.git.exportAll, true);
        /*
         * Authentication Parameters
         */
        @Parameter(names = { "--authenticatePushPull" }, description = "Authenticate Git Push/Pull access")
        public Boolean authenticatePushPull = StoredSettings.getBoolean(Keys.git_authenticate, true);
        public Boolean authenticatePushPull = fileSettings.getBoolean(Keys.git.authenticate, true);
        @Parameter(names = { "--realm" }, description = "Users Realm Hash File")
        public String realmFile = StoredSettings.getString(Keys.server_realmFile, "users.properties");
        public String realmFile = fileSettings.getString(Keys.server.realmFile, "users.properties");
        /*
         * JETTY Parameters
         */
        @Parameter(names = { "--nio" }, description = "Use NIO Connector else use Socket Connector.")
        public Boolean useNIO = StoredSettings.getBoolean(Keys.server_useNio, true);
        public Boolean useNIO = fileSettings.getBoolean(Keys.server.useNio, true);
        @Parameter(names = "--port", description = "HTTP port for to serve. (port <= 0 will disable this connector)")
        public Integer port = StoredSettings.getInteger(Keys.server_httpPort, 80);
        public Integer port = fileSettings.getInteger(Keys.server.httpPort, 80);
        @Parameter(names = "--securePort", description = "HTTPS port to serve.  (port <= 0 will disable this connector)")
        public Integer securePort = StoredSettings.getInteger(Keys.server_httpsPort, 443);
        public Integer securePort = fileSettings.getInteger(Keys.server.httpsPort, 443);
        @Parameter(names = "--storePassword", description = "Password for SSL (https) keystore.")
        public String storePassword = StoredSettings.getString(Keys.server_storePassword, "");
        public String storePassword = fileSettings.getString(Keys.server.storePassword, "");
        @Parameter(names = "--shutdownPort", description = "Port for Shutdown Monitor to listen on. (port <= 0 will disable this monitor)")
        public Integer shutdownPort = StoredSettings.getInteger(Keys.server_shutdownPort, 8081);
        public Integer shutdownPort = fileSettings.getInteger(Keys.server.shutdownPort, 8081);
    }
}
src/com/gitblit/IStoredSettings.java
New file
@@ -0,0 +1,23 @@
package com.gitblit;
import java.util.List;
public interface IStoredSettings {
    public abstract List<String> getAllKeys(String startingWith);
    public abstract boolean getBoolean(String name, boolean defaultValue);
    public abstract int getInteger(String name, int defaultValue);
    public abstract String getString(String name, String defaultValue);
    public abstract List<String> getStrings(String name);
    public abstract List<String> getStringsFromValue(String value);
    public abstract List<String> getStrings(String name, String separator);
    public abstract List<String> getStringsFromValue(String value, String separator);
}
src/com/gitblit/WebXmlSettings.java
New file
@@ -0,0 +1,65 @@
package com.gitblit;
import java.util.List;
import javax.servlet.ServletContext;
public class WebXmlSettings implements IStoredSettings {
    public WebXmlSettings(ServletContext context) {
    }
    @Override
    public List<String> getAllKeys(String startingWith) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public boolean getBoolean(String name, boolean defaultValue) {
        // TODO Auto-generated method stub
        return false;
    }
    @Override
    public int getInteger(String name, int defaultValue) {
        // TODO Auto-generated method stub
        return 0;
    }
    @Override
    public String getString(String name, String defaultValue) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public List<String> getStrings(String name) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public List<String> getStringsFromValue(String value) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public List<String> getStrings(String name, String separator) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public List<String> getStringsFromValue(String value, String separator) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public String toString() {
        return getClass().getSimpleName() + ": web.xml";
    }
}
src/com/gitblit/utils/ByteFormat.java
@@ -1,8 +1,3 @@
/*
 * Copyright 2011 Squeal Group.  Licensed under the Eclipse Public License,
 * Version 1.0 (http://www.eclipse.org/legal/epl-v10.html).
 * Initial Developer: Squeal Group
 */
package com.gitblit.utils;
import java.text.DecimalFormat;
src/com/gitblit/utils/HtmlDiffFormatter.java
@@ -91,7 +91,7 @@
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        text.writeLine(bos, cur);
        String line = bos.toString();
        line = Utils.escapeForHtml(line, false);
        line = StringUtils.escapeForHtml(line, false);
        os.write(line.getBytes());
        switch (prefix) {
        case '+':
src/com/gitblit/utils/PatchFormatter.java
@@ -78,7 +78,7 @@
        }
        for (String path : changes.keySet()) {
            PatchTouple touple = changes.get(path);
            patch.append("\n " + Utils.rightPad(path, maxPathLen, ' ') + " | " + Utils.leftPad("" + touple.total(), 4, ' ') + " " + touple.relativeScale(unit));
            patch.append("\n " + StringUtils.rightPad(path, maxPathLen, ' ') + " | " + StringUtils.leftPad("" + touple.total(), 4, ' ') + " " + touple.relativeScale(unit));
        }
        patch.append(MessageFormat.format("\n {0} files changed, {1} insertions(+), {2} deletions(-)\n\n", files, insertions, deletions));
        patch.append(os.toString());
src/com/gitblit/utils/StringUtils.java
New file
@@ -0,0 +1,110 @@
package com.gitblit.utils;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
public class StringUtils {
    public static boolean isEmpty(String value) {
        return value == null || value.trim().length() == 0;
    }
    public static String breakLinesForHtml(String string) {
        return string.replace("\r\n", "<br/>").replace("\r", "<br/>").replace("\n", "<br/>");
    }
    public static String escapeForHtml(String inStr, boolean changeSpace) {
        StringBuffer retStr = new StringBuffer();
        int i = 0;
        while (i < inStr.length()) {
            if (inStr.charAt(i) == '&') {
                retStr.append("&amp;");
            } else if (inStr.charAt(i) == '<') {
                retStr.append("&lt;");
            } else if (inStr.charAt(i) == '>') {
                retStr.append("&gt;");
            } else if (inStr.charAt(i) == '\"') {
                retStr.append("&quot;");
            } else if (changeSpace && inStr.charAt(i) == ' ') {
                retStr.append("&nbsp;");
            } else if (changeSpace && inStr.charAt(i) == '\t') {
                retStr.append(" &nbsp; &nbsp;");
            } else
                retStr.append(inStr.charAt(i));
            i++;
        }
        return retStr.toString();
    }
    public static String flattenStrings(List<String> values) {
        StringBuilder sb = new StringBuilder();
        for (String value : values) {
            sb.append(value).append(" ");
        }
        return sb.toString().trim();
    }
    public static String trimString(String value, int max) {
        if (value.length() <= max) {
            return value;
        }
        return value.substring(0, max - 3) + "...";
    }
    public static String trimShortLog(String string) {
        return trimString(string, 60);
    }
    public static String leftPad(String input, int length, char pad) {
        if (input.length() < length) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0, len = length - input.length(); i < len; i++) {
                sb.append(pad);
            }
            sb.append(input);
            return sb.toString();
        }
        return input;
    }
    public static String rightPad(String input, int length, char pad) {
        if (input.length() < length) {
            StringBuilder sb = new StringBuilder();
            sb.append(input);
            for (int i = 0, len = length - input.length(); i < len; i++) {
                sb.append(pad);
            }
            return sb.toString();
        }
        return input;
    }
    public static String getSHA1(String text) {
        try {
            byte[] bytes = text.getBytes("iso-8859-1");
            return getSHA1(bytes);
        } catch (UnsupportedEncodingException u) {
            throw new RuntimeException(u);
        }
    }
    public static String getSHA1(byte[] bytes) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(bytes, 0, bytes.length);
            byte[] sha1hash = md.digest();
            StringBuilder sb = new StringBuilder(sha1hash.length * 2);
            for (int i = 0; i < sha1hash.length; i++) {
                if (((int) sha1hash[i] & 0xff) < 0x10)
                    sb.append("0");
                sb.append(Long.toString((int) sha1hash[i] & 0xff, 16));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException t) {
            throw new RuntimeException(t);
        }
    }
}
src/com/gitblit/utils/TimeUtils.java
File was renamed from src/com/gitblit/utils/Utils.java
@@ -2,7 +2,7 @@
import java.util.Date;
public class Utils {
public class TimeUtils {
    private final static long min = 1000 * 60l;
    private final static long halfhour = min * 30l;
@@ -115,52 +115,5 @@
            }
        }
        return ago;
    }
    public static String leftPad(String input, int length, char pad) {
        if (input.length() < length) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0, len = length - input.length(); i < len; i++) {
                sb.append(pad);
            }
            sb.append(input);
            return sb.toString();
        }
        return input;
    }
    public static String rightPad(String input, int length, char pad) {
        if (input.length() < length) {
            StringBuilder sb = new StringBuilder();
            sb.append(input);
            for (int i = 0, len = length - input.length(); i < len; i++) {
                sb.append(pad);
            }
            return sb.toString();
        }
        return input;
    }
    public static String escapeForHtml(String inStr, boolean changeSpace) {
        StringBuffer retStr = new StringBuffer();
        int i = 0;
        while (i < inStr.length()) {
            if (inStr.charAt(i) == '&') {
                retStr.append("&amp;");
            } else if (inStr.charAt(i) == '<') {
                retStr.append("&lt;");
            } else if (inStr.charAt(i) == '>') {
                retStr.append("&gt;");
            } else if (inStr.charAt(i) == '\"') {
                retStr.append("&quot;");
            } else if (changeSpace && inStr.charAt(i) == ' ') {
                retStr.append("&nbsp;");
            } else if (changeSpace && inStr.charAt(i) == '\t') {
                retStr.append(" &nbsp; &nbsp;");
            } else
                retStr.append(inStr.charAt(i));
            i++;
        }
        return retStr.toString();
    }
}
src/com/gitblit/wicket/AuthorizationStrategy.java
@@ -15,9 +15,15 @@
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    protected boolean isPageAuthorized(Class pageClass) {
        if (BasePage.class.isAssignableFrom(pageClass))
            return isAuthorized(pageClass);
        // Return contruction by default
        if (BasePage.class.isAssignableFrom(pageClass)) {
            GitBlitWebSession session = GitBlitWebSession.get();
            if (!session.isLoggedIn())
                return false;
            User user = session.getUser();
            if (pageClass.isAnnotationPresent(AdminPage.class)) {
                return user.canAdmin();
            }
        }
        return true;
    }
@@ -30,16 +36,5 @@
            else
                throw new RestartResponseAtInterceptPageException(RepositoriesPage.class);
        }
    }
    protected boolean isAuthorized(Class<? extends BasePage> pageClass) {
        GitBlitWebSession session = GitBlitWebSession.get();
        if (!session.isLoggedIn())
            return false;
        User user = session.getUser();
        if (pageClass.isAnnotationPresent(AdminPage.class)) {
        }
        return true;
    }
}
src/com/gitblit/wicket/BasePage.html
@@ -32,7 +32,7 @@
            <div style="float:right">
                <a href="http://gitblit.com"><span wicket:id="gbVersion"></span></a> 
            </div>
            <div wicket:id="userText">[user text]</div>
            <div wicket:id="userPanel">[user panel]</div>
        </div>
    </body>
</html>
src/com/gitblit/wicket/BasePage.java
@@ -12,20 +12,22 @@
import org.slf4j.LoggerFactory;
import com.gitblit.Constants;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.StoredSettings;
import com.gitblit.wicket.pages.SummaryPage;
public abstract class BasePage extends WebPage {
    Logger logger = LoggerFactory.getLogger(BasePage.class);
    private final Logger logger;
    public BasePage() {
        super();
        logger = LoggerFactory.getLogger(getClass());
    }
    public BasePage(PageParameters params) {
        super(params);
        logger = LoggerFactory.getLogger(getClass());
    }
    protected void setupPage(String repositoryName, String pageName) {
@@ -35,7 +37,7 @@
            add(new Label("title", getServerName()));
        }
        // header
        String siteName = StoredSettings.getString(Keys.web_siteName, Constants.NAME);
        String siteName = GitBlit.self().settings().getString(Keys.web.siteName, Constants.NAME);
        if (siteName == null || siteName.trim().length() == 0) {
            siteName = Constants.NAME;
        }
@@ -45,20 +47,20 @@
        // footer
        User user = null;
        if (StoredSettings.getBoolean(Keys.web_authenticate, true)) {
        if (GitBlit.self().settings().getBoolean(Keys.web.authenticate, true)) {
            user = GitBlitWebSession.get().getUser();
            add(new Label("userText", "Logout " + user.toString()));
            add(new LinkPanel("userPanel", null, getString("gb.logout") + " " + user.toString(), LogoutPage.class));
        } else {
            add(new Label("userText", ""));
            add(new Label("userPanel", ""));
        }
        add(new Label("gbVersion", "v" + Constants.VERSION));
        if (StoredSettings.getBoolean(Keys.server_aggressiveHeapManagement, false)) {
        if (GitBlit.self().settings().getBoolean(Keys.web.aggressiveHeapManagement, false)) {
            System.gc();
        }
    }
    protected TimeZone getTimeZone() {
        return StoredSettings.getBoolean(Keys.web_useClientTimezone, false) ? GitBlitWebSession.get().getTimezone() : TimeZone.getDefault();
        return GitBlit.self().settings().getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get().getTimezone() : TimeZone.getDefault();
    }
    protected String getServerName() {
src/com/gitblit/wicket/GitBlitWebApp.java
@@ -12,7 +12,6 @@
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.StoredSettings;
import com.gitblit.wicket.pages.BlobDiffPage;
import com.gitblit.wicket.pages.BlobPage;
import com.gitblit.wicket.pages.BranchesPage;
@@ -36,14 +35,14 @@
        super.init();
        // Setup page authorization mechanism
        if (StoredSettings.getBoolean(Keys.web_authenticate, false)) {
        if (GitBlit.self().settings().getBoolean(Keys.web.authenticate, false)) {
            AuthorizationStrategy authStrategy = new AuthorizationStrategy();
            getSecuritySettings().setAuthorizationStrategy(authStrategy);
            getSecuritySettings().setUnauthorizedComponentInstantiationListener(authStrategy);
        }
        // Grab Browser info (like timezone, etc)
        if (StoredSettings.getBoolean(Keys.web_useClientTimezone, false)) {
        if (GitBlit.self().settings().getBoolean(Keys.web.useClientTimezone, false)) {
            getRequestCycleSettings().setGatherExtendedBrowserInfo(true);
        }
@@ -61,11 +60,15 @@
        mount(new MixedParamUrlCodingStrategy("/commitdiff", CommitDiffPage.class, new String[] { "r", "h" }));
        mount(new MixedParamUrlCodingStrategy("/patch", PatchPage.class, new String[] { "r", "h", "f" }));
        // setup extended urls
        // setup ticgit urls
        mount(new MixedParamUrlCodingStrategy("/ticgit", TicGitPage.class, new String[] { "r" }));
        mount(new MixedParamUrlCodingStrategy("/ticgittkt", TicGitTicketPage.class, new String[] { "r", "h", "f" }));
        mount(new MixedParamUrlCodingStrategy("/login", LoginPage.class, new String[] {}));
        // setup login/logout urls, if we are using authentication
        if (GitBlit.self().settings().getBoolean(Keys.web.authenticate, true)) {
            mount(new MixedParamUrlCodingStrategy("/login", LoginPage.class, new String[] {}));
            mount(new MixedParamUrlCodingStrategy("/logout", LogoutPage.class, new String[] {}));
        }
    }
    @Override
@@ -88,10 +91,6 @@
        if (GitBlit.self().isDebugMode())
            return Application.DEVELOPMENT;
        return Application.DEPLOYMENT;
    }
    public String getCloneUrl(String repositoryName) {
        return StoredSettings.getString(Keys.git_cloneUrl, "https://localhost/git/") + repositoryName;
    }
    public static GitBlitWebApp get() {
src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -40,4 +40,8 @@
gb.pageNext = next
gb.parent = parent
gb.head = HEAD
gb.blame = blame
gb.blame = blame
gb.login = Login
gb.logout = Logout
gb.username = Username
gb.password = Password
src/com/gitblit/wicket/LinkPanel.java
@@ -16,6 +16,10 @@
    private final IModel<String> labelModel;
    public LinkPanel(String wicketId, String linkCssClass, String label, Class<? extends WebPage> clazz) {
        this(wicketId, linkCssClass, new Model<String>(label), clazz, null);
    }
    public LinkPanel(String wicketId, String linkCssClass, String label, Class<? extends WebPage> clazz, PageParameters parameters) {
        this(wicketId, linkCssClass, new Model<String>(label), clazz, parameters);
    }
src/com/gitblit/wicket/LoginPage.html
@@ -17,17 +17,21 @@
    <body onload="document.getElementById('username').focus();">
    <div>
        <center>
            <img wicket:id="logo" /><br/>
            <wicket:link>
                <img src="resources/gitblt2.png" alt="Git:Blit"/><br/>
            </wicket:link>
            <span style="font-weight:bold;" wicket:id="name">[name]</span><br/>
            <div>
                <form style="text-align:center;" wicket:id="loginForm">
                    <p/>
                    Username <input type="text" id="username" wicket:id="username" value=""/>
                    <wicket:message key="gb.username"></wicket:message>
                    <input type="text" id="username" wicket:id="username" value=""/>
                    <p/>
                    Password <input type="password"  wicket:id="password" value=""/>
                    <wicket:message key="gb.password"></wicket:message>
                    <input type="password"  wicket:id="password" value=""/>
                    <p/>
                    <input type="submit" value="Login" />
                    <input type="submit" value="Login" wicket:message="value:gb.login" />
                    <div style="background-color:#c7c7c7" wicket:id="feedback"></div>
                </form>
            </div>
src/com/gitblit/wicket/LoginPage.java
@@ -1,24 +1,23 @@
package com.gitblit.wicket;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.StatelessForm;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.image.ContextImage;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.protocol.http.WebRequest;
import org.apache.wicket.protocol.http.WebResponse;
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
import com.gitblit.Constants;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
public class LoginPage extends WebPage {
@@ -30,8 +29,7 @@
        tryAutomaticLogin();
        add(new Label("title", getServerName()));
        add(new ContextImage("logo", "gitblt2.png"));
        add(new Label("title", GitBlit.self().settings().getString(Keys.web.siteName, Constants.NAME)));
        add(new Label("name", Constants.NAME));
        Form<Void> loginForm = new LoginForm("loginForm");
@@ -41,17 +39,20 @@
        add(loginForm);
    }
    protected String getServerName() {
        ServletWebRequest servletWebRequest = (ServletWebRequest) getRequest();
        HttpServletRequest req = servletWebRequest.getHttpServletRequest();
        return req.getServerName();
    }
    class LoginForm extends Form<Void> {
    class LoginForm extends StatelessForm<Void> {
        private static final long serialVersionUID = 1L;
        public LoginForm(String id) {
            super(id);
            // If we are already logged in because user directly accessed
            // the login url, redirect to the home page
            if (GitBlitWebSession.get().isLoggedIn()) {
                setRedirect(true);
                setResponsePage(getApplication().getHomePage());
            }
            tryAutomaticLogin();
        }
        @Override
@@ -82,20 +83,16 @@
    private void loginUser(User user) {
        if (user != null) {
            GitBlitWebSession session = GitBlitWebSession.get();
            // Set the user into the session
            GitBlitWebSession.get().setUser(user);
            // Set Cookie
            WebResponse response = (WebResponse) getRequestCycle().getResponse();
            GitBlit.self().setCookie(response, user);
            // track user object so that we do not have to continue
            // re-authenticating on each request.
            session.setUser(user);
            // Redirect to original page OR to first available tab
            if (!continueToOriginalDestination()) {
                // Redirect to home page
                setResponsePage(session.getApplication().getHomePage());
                setResponsePage(getApplication().getHomePage());
            }
        }
    }
src/com/gitblit/wicket/LogoutPage.java
New file
@@ -0,0 +1,12 @@
package com.gitblit.wicket;
import org.apache.wicket.markup.html.WebPage;
public class LogoutPage extends WebPage {
    public LogoutPage() {
        getSession().invalidate();
        setRedirect(true);
        setResponsePage(getApplication().getHomePage());
    }
}
src/com/gitblit/wicket/RepositoryPage.java
@@ -11,10 +11,13 @@
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.GitBlit;
import com.gitblit.StoredSettings;
import com.gitblit.Keys;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.pages.RepositoriesPage;
import com.gitblit.wicket.panels.PageLinksPanel;
import com.gitblit.wicket.panels.RefsPanel;
@@ -27,6 +30,8 @@
    private transient Repository r = null;
    private final Logger logger = LoggerFactory.getLogger(RepositoryPage.class);
    public RepositoryPage(PageParameters params) {
        super(params);
        if (!params.containsKey("r")) {
@@ -69,20 +74,24 @@
    }
    protected void addFullText(String wicketId, String text, boolean substituteRegex) {
        String html = WicketUtils.breakLines(text);
        String html = StringUtils.breakLinesForHtml(text);
        if (substituteRegex) {
            Map<String, String> map = new HashMap<String, String>();
            // global regex keys
            for (String key : StoredSettings.getAllKeys("regex.global")) {
                String subKey = key.substring(key.lastIndexOf('.') + 1);
                map.put(subKey, StoredSettings.getString(key, ""));
            if (GitBlit.self().settings().getBoolean(Keys.regex.global, false)) {
                for (String key : GitBlit.self().settings().getAllKeys(Keys.regex.global)) {
                    if (!key.equals(Keys.regex.global)) {
                        String subKey = key.substring(key.lastIndexOf('.') + 1);
                        map.put(subKey, GitBlit.self().settings().getString(key, ""));
                    }
                }
            }
            // repository-specific regex keys
            List<String> keys = StoredSettings.getAllKeys("regex." + repositoryName.toLowerCase());
            List<String> keys = GitBlit.self().settings().getAllKeys(Keys.regex._ROOT + "." + repositoryName.toLowerCase());
            for (String key : keys) {
                String subKey = key.substring(key.lastIndexOf('.') + 1);
                map.put(subKey, StoredSettings.getString(key, ""));
                map.put(subKey, GitBlit.self().settings().getString(key, ""));
            }
            for (String key : map.keySet()) {
src/com/gitblit/wicket/User.java
@@ -1,10 +1,14 @@
package com.gitblit.wicket;
import com.gitblit.Build;
import java.io.Serializable;
import com.gitblit.Constants;
import com.gitblit.utils.StringUtils;
public class User {
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String username;
    private String cookie;
    private boolean canAdmin = false;
@@ -13,7 +17,7 @@
    public User(String username, char[] password) {
        this.username = username;
        this.cookie = Build.getSHA1((Constants.NAME + username + new String(password)).getBytes());
        this.cookie = StringUtils.getSHA1((Constants.NAME + username + new String(password)));
    }
    public void canAdmin(boolean value) {
src/com/gitblit/wicket/WicketUtils.java
@@ -3,7 +3,6 @@
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import org.apache.wicket.Component;
@@ -12,9 +11,9 @@
import org.apache.wicket.markup.html.basic.Label;
import org.eclipse.jgit.lib.Constants;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.StoredSettings;
import com.gitblit.utils.Utils;
import com.gitblit.utils.TimeUtils;
public class WicketUtils {
@@ -28,10 +27,6 @@
    public static void setHtmlTitle(Component container, String value) {
        container.add(new SimpleAttributeModifier("title", value));
    }
    public static String breakLines(String string) {
        return string.replace("\r", "<br/>").replace("\n", "<br/>");
    }
    public static void setTicketCssClass(Component container, String state) {
@@ -50,14 +45,6 @@
        }
    }
    public static String flattenStrings(List<String> values) {
        StringBuilder sb = new StringBuilder();
        for (String value : values) {
            sb.append(value).append(" ");
        }
        return sb.toString().trim();
    }
    public static void setAlternatingBackground(Component c, int i) {
        String clazz = i % 2 == 0 ? "dark" : "light";
        setCssClass(c, clazz);
@@ -67,17 +54,6 @@
        Label label = new Label(wicketId, author);
        WicketUtils.setHtmlTitle(label, author);
        return label;
    }
    public static String trimShortLog(String string) {
        return trimString(string, 60);
    }
    public static String trimString(String value, int max) {
        if (value.length() <= max) {
            return value;
        }
        return value.substring(0, max - 3) + "...";
    }
    public static PageParameters newRepositoryParameter(String repositoryName) {
@@ -122,30 +98,30 @@
    }
    public static Label createDateLabel(String wicketId, Date date, TimeZone timeZone) {
        DateFormat df = new SimpleDateFormat(StoredSettings.getString(Keys.web_datestampShortFormat, "MM/dd/yy"));
        DateFormat df = new SimpleDateFormat(GitBlit.self().settings().getString(Keys.web.datestampShortFormat, "MM/dd/yy"));
        if (timeZone != null) {
            df.setTimeZone(timeZone);
        }
        String dateString = df.format(date);
        String title = Utils.timeAgo(date);
        String title = TimeUtils.timeAgo(date);
        if ((System.currentTimeMillis() - date.getTime()) < 10 * 24 * 60 * 60 * 1000l) {
            String tmp = dateString;
            dateString = title;
            title = tmp;
        }
        Label label = new Label(wicketId, dateString);
        WicketUtils.setCssClass(label, Utils.timeAgoCss(date));
        WicketUtils.setCssClass(label, TimeUtils.timeAgoCss(date));
        WicketUtils.setHtmlTitle(label, title);
        return label;
    }
    public static Label createTimestampLabel(String wicketId, Date date, TimeZone timeZone) {
        DateFormat df = new SimpleDateFormat(StoredSettings.getString(Keys.web_datetimestampLongFormat, "EEEE, MMMM d, yyyy h:mm a z"));
        DateFormat df = new SimpleDateFormat(GitBlit.self().settings().getString(Keys.web.datetimestampLongFormat, "EEEE, MMMM d, yyyy h:mm a z"));
        if (timeZone != null) {
            df.setTimeZone(timeZone);
        }
        String dateString = df.format(date);
        String title = Utils.timeAgo(date);
        String title = TimeUtils.timeAgo(date);
        Label label = new Label(wicketId, dateString);
        WicketUtils.setHtmlTitle(label, title);
        return label;
src/com/gitblit/wicket/pages/BlobPage.java
@@ -11,8 +11,8 @@
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.StoredSettings;
import com.gitblit.utils.JGitUtils;
import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.RepositoryPage;
@@ -45,13 +45,13 @@
        // Map the extensions to types
        Map<String, Integer> map = new HashMap<String, Integer>();
        for (String ext : StoredSettings.getStrings(Keys.web_prettyPrintExtensions)) {
        for (String ext : GitBlit.self().settings().getStrings(Keys.web.prettyPrintExtensions)) {
            map.put(ext.toLowerCase(), 1);
        }
        for (String ext : StoredSettings.getStrings(Keys.web_imageExtensions)) {
        for (String ext : GitBlit.self().settings().getStrings(Keys.web.imageExtensions)) {
            map.put(ext.toLowerCase(), 2);
        }
        for (String ext : StoredSettings.getStrings(Keys.web_binaryExtensions)) {
        for (String ext : GitBlit.self().settings().getStrings(Keys.web.binaryExtensions)) {
            map.put(ext.toLowerCase(), 3);
        }
src/com/gitblit/wicket/pages/RawPage.java
@@ -15,7 +15,6 @@
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.StoredSettings;
import com.gitblit.utils.JGitUtils;
import com.gitblit.wicket.WicketUtils;
@@ -52,10 +51,10 @@
        // Map the extensions to types
        Map<String, Integer> map = new HashMap<String, Integer>();
        for (String ext : StoredSettings.getStrings(Keys.web_imageExtensions)) {
        for (String ext : GitBlit.self().settings().getStrings(Keys.web.imageExtensions)) {
            map.put(ext.toLowerCase(), 2);
        }
        for (String ext : StoredSettings.getStrings(Keys.web_binaryExtensions)) {
        for (String ext : GitBlit.self().settings().getStrings(Keys.web.binaryExtensions)) {
            map.put(ext.toLowerCase(), 3);
        }
src/com/gitblit/wicket/pages/RepositoriesPage.java
@@ -19,8 +19,7 @@
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.StoredSettings;
import com.gitblit.utils.Utils;
import com.gitblit.utils.TimeUtils;
import com.gitblit.wicket.BasePage;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.LinkPanel;
@@ -34,11 +33,11 @@
        setupPage("", "");
        boolean showAdmin = false;
        if (StoredSettings.getBoolean(Keys.web_authenticate, true)) {
            boolean allowAdmin = StoredSettings.getBoolean(Keys.web_allowAdministration, false);
        if (GitBlit.self().settings().getBoolean(Keys.web.authenticate, true)) {
            boolean allowAdmin = GitBlit.self().settings().getBoolean(Keys.web.allowAdministration, false);
            showAdmin = allowAdmin && GitBlitWebSession.get().canAdmin();
        } else {
            showAdmin = StoredSettings.getBoolean(Keys.web_allowAdministration, false);
            showAdmin = GitBlit.self().settings().getBoolean(Keys.web.allowAdministration, false);
        }
        Fragment adminLinks = new Fragment("adminPanel", "adminLinks", this);
@@ -46,7 +45,7 @@
        adminLinks.add(new BookmarkablePageLink<Void>("newUser", RepositoriesPage.class));
        add(adminLinks.setVisible(showAdmin));
        add(new Label("repositoriesMessage", StoredSettings.getString(Keys.web_repositoriesMessage, "")).setEscapeModelStrings(false));
        add(new Label("repositoriesMessage", GitBlit.self().settings().getString(Keys.web.repositoriesMessage, "")).setEscapeModelStrings(false));
        List<RepositoryModel> rows = GitBlit.self().getRepositories(getRequest());
        DataProvider dp = new DataProvider(rows);
@@ -61,10 +60,10 @@
                item.add(new LinkPanel("repositoryDescription", "list", entry.description, SummaryPage.class, pp));
                item.add(new Label("repositoryOwner", entry.owner));
                String lastChange = Utils.timeAgo(entry.lastChange);
                String lastChange = TimeUtils.timeAgo(entry.lastChange);
                Label lastChangeLabel = new Label("repositoryLastChange", lastChange);
                item.add(lastChangeLabel);
                WicketUtils.setCssClass(lastChangeLabel, Utils.timeAgoCss(entry.lastChange));
                WicketUtils.setCssClass(lastChangeLabel, TimeUtils.timeAgoCss(entry.lastChange));
                WicketUtils.setAlternatingBackground(item, counter);
                counter++;
src/com/gitblit/wicket/pages/SummaryPage.java
@@ -15,10 +15,9 @@
import com.codecommit.wicket.ChartProvider;
import com.codecommit.wicket.ChartType;
import com.codecommit.wicket.IChartData;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.StoredSettings;
import com.gitblit.utils.JGitUtils;
import com.gitblit.wicket.GitBlitWebApp;
import com.gitblit.wicket.RepositoryPage;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.models.Metric;
@@ -34,12 +33,12 @@
        int numCommitsDef = 20;
        int numRefsDef = 5;
        int numberCommits = StoredSettings.getInteger(Keys.web_summaryCommitCount, numCommitsDef);
        int numberCommits = GitBlit.self().settings().getInteger(Keys.web.summaryCommitCount, numCommitsDef);
        if (numberCommits <= 0) {
            numberCommits = numCommitsDef;
        }
        int numberRefs = StoredSettings.getInteger(Keys.web_summaryRefsCount, numRefsDef);
        int numberRefs = GitBlit.self().settings().getInteger(Keys.web.summaryRefsCount, numRefsDef);
        if (numberRefs <= 0) {
            numberRefs = numRefsDef;
        }
@@ -57,7 +56,7 @@
        add(new Label("repositoryOwner", JGitUtils.getRepositoryOwner(r)));
        add(WicketUtils.createTimestampLabel("repositoryLastChange", JGitUtils.getLastChange(r), getTimeZone()));
        add(new Label("repositoryCloneUrl", GitBlitWebApp.get().getCloneUrl(repositoryName)));
        add(new Label("repositoryCloneUrl", GitBlit.self().getCloneUrl(repositoryName)));
        add(new LogPanel("commitsPanel", repositoryName, null, r, numberCommits, 0));
        add(new TagsPanel("tagsPanel", repositoryName, r, numberRefs));
@@ -73,7 +72,7 @@
    }
    private void insertActivityGraph(List<Metric> metrics) {
        if (StoredSettings.getBoolean(Keys.web_generateActivityGraph, true)) {
        if (GitBlit.self().settings().getBoolean(Keys.web.generateActivityGraph, true)) {
            IChartData data = getChartData(metrics);
            ChartProvider provider = new ChartProvider(new Dimension(400, 80), ChartType.LINE, data);
src/com/gitblit/wicket/pages/TicGitPage.java
@@ -9,6 +9,7 @@
import org.apache.wicket.markup.repeater.data.ListDataProvider;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.RepositoryPage;
@@ -36,8 +37,8 @@
                WicketUtils.setTicketCssClass(stateLabel, entry.state);
                item.add(stateLabel);
                item.add(WicketUtils.createDateLabel("ticketDate", entry.date, GitBlitWebSession.get().getTimezone()));
                item.add(new Label("ticketHandler", WicketUtils.trimString(entry.handler.toLowerCase(), 30)));
                item.add(new LinkPanel("ticketTitle", "list subject", WicketUtils.trimString(entry.title, 80), TicGitTicketPage.class, newPathParameter(entry.name)));
                item.add(new Label("ticketHandler", StringUtils.trimString(entry.handler.toLowerCase(), 30)));
                item.add(new LinkPanel("ticketTitle", "list subject", StringUtils.trimString(entry.title, 80), TicGitTicketPage.class, newPathParameter(entry.name)));
                WicketUtils.setAlternatingBackground(item, counter);
                counter++;
src/com/gitblit/wicket/pages/TicGitTicketPage.html
@@ -29,8 +29,9 @@
    <table style="width:100%;" class="comments">
        <tbody>
            <tr valign="top" wicket:id="comment">
                 <td><span class="date" wicket:id="commentDate">[comment date]</span><br/>
                 <span class="author" wicket:id="commentAuthor">[comment author]</span></td>
                 <td><span class="author" wicket:id="commentAuthor">[comment author]</span><br/>
                     <span class="date" wicket:id="commentDate">[comment date]</span>
                 </td>
                 <td><span wicket:id="commentText">[comment text]</span></td>
               </tr>
           </tbody>
src/com/gitblit/wicket/pages/TicGitTicketPage.java
@@ -8,7 +8,7 @@
import org.eclipse.jgit.lib.Repository;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.Utils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.RepositoryPage;
import com.gitblit.wicket.WicketUtils;
@@ -32,7 +32,7 @@
        Label stateLabel = new Label("ticketState", t.state);
        WicketUtils.setTicketCssClass(stateLabel, t.state);
        add(stateLabel);
        add(new Label("ticketTags", WicketUtils.flattenStrings(t.tags)));
        add(new Label("ticketTags", StringUtils.flattenStrings(t.tags)));
        ListDataProvider<Comment> commentsDp = new ListDataProvider<Comment>(t.comments);
        DataView<Comment> commentsView = new DataView<Comment>("comment", commentsDp) {
@@ -57,8 +57,8 @@
    }
    private String prepareComment(String comment) {
        String html = Utils.escapeForHtml(comment, false);
        html = WicketUtils.breakLines(comment).trim();
        String html = StringUtils.escapeForHtml(comment, false);
        html = StringUtils.breakLinesForHtml(comment).trim();
        return html.replaceAll("\\bcommit\\s*([A-Za-z0-9]*)\\b", "<a href=\"/commit/" + repositoryName + "/$1\">commit $1</a>");
    }
}
src/com/gitblit/wicket/panels/BasePanel.java
@@ -4,8 +4,8 @@
import org.apache.wicket.markup.html.panel.Panel;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.StoredSettings;
import com.gitblit.wicket.GitBlitWebSession;
public abstract class BasePanel extends Panel {
@@ -17,6 +17,6 @@
    }
    protected TimeZone getTimeZone() {
        return StoredSettings.getBoolean(Keys.web_useClientTimezone, false) ? GitBlitWebSession.get().getTimezone() : TimeZone.getDefault();
        return GitBlit.self().settings().getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get().getTimezone() : TimeZone.getDefault();
    }
}
src/com/gitblit/wicket/panels/BranchesPanel.java
@@ -14,6 +14,7 @@
import org.eclipse.jgit.lib.Repository;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.models.RefModel;
@@ -59,7 +60,7 @@
                item.add(WicketUtils.createDateLabel("branchDate", entry.getDate(), getTimeZone()));
                item.add(new LinkPanel("branchName", "list name", WicketUtils.trimString(entry.getDisplayName(), 28), LogPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getName())));
                item.add(new LinkPanel("branchName", "list name", StringUtils.trimString(entry.getDisplayName(), 28), LogPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getName())));
                // only show branch type on the branches page
                boolean remote = entry.getName().startsWith(Constants.R_REMOTES);
src/com/gitblit/wicket/panels/LogPanel.java
@@ -14,9 +14,10 @@
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.StoredSettings;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.pages.CommitDiffPage;
@@ -32,7 +33,7 @@
    public LogPanel(String wicketId, final String repositoryName, String objectId, Repository r, int limit, int pageOffset) {
        super(wicketId);
        boolean pageResults = limit <= 0;
        int itemsPerPage = StoredSettings.getInteger(Keys.web_logPageCommitCount, 50);
        int itemsPerPage = GitBlit.self().settings().getInteger(Keys.web.logPageCommitCount, 50);
        if (itemsPerPage <= 1) {
            itemsPerPage = 50;
        }
@@ -73,7 +74,7 @@
                item.add(WicketUtils.createAuthorLabel("commitAuthor", author));
                String shortMessage = entry.getShortMessage();
                String trimmedMessage = WicketUtils.trimShortLog(shortMessage);
                String trimmedMessage = StringUtils.trimShortLog(shortMessage);
                LinkPanel shortlog = new LinkPanel("commitShortMessage", "list subject", trimmedMessage, CommitPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getName()));
                if (!shortMessage.equals(trimmedMessage)) {
                    WicketUtils.setHtmlTitle(shortlog, shortMessage);
src/com/gitblit/wicket/panels/PageLinksPanel.java
@@ -15,7 +15,8 @@
import org.apache.wicket.markup.repeater.data.ListDataProvider;
import org.eclipse.jgit.lib.Repository;
import com.gitblit.StoredSettings;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.utils.JGitUtils;
import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.WicketUtils;
@@ -55,8 +56,8 @@
        add(new BookmarkablePageLink<Void>("tree", TreePage.class, WicketUtils.newRepositoryParameter(repositoryName)));
        // Get the repository ticgit setting
        boolean checkTicgit = StoredSettings.getBoolean("ticgit.global", false);
        checkTicgit |= StoredSettings.getBoolean(MessageFormat.format("ticgit.{0}", repositoryName), false);
        boolean checkTicgit = GitBlit.self().settings().getBoolean(Keys.ticgit.global, false);
        checkTicgit |= GitBlit.self().settings().getBoolean(MessageFormat.format(Keys.ticgit._ROOT + ".{0}", repositoryName), false);
        // Add dynamic repository extras
        List<String> extras = new ArrayList<String>();
src/com/gitblit/wicket/panels/TagsPanel.java
@@ -11,6 +11,7 @@
import org.eclipse.jgit.lib.Repository;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.models.RefModel;
@@ -52,7 +53,7 @@
                item.add(new LinkPanel("tagName", "list name", entry.getDisplayName(), CommitPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getCommitId().getName())));
                String message;
                if (maxCount > 0) {
                    message = WicketUtils.trimString(entry.getShortLog(), 40);
                    message = StringUtils.trimString(entry.getShortLog(), 40);
                } else {
                    message = entry.getShortLog();
                }