Posts Tagged Java

Default HTML-escape using Freemarker

Most java developers have at least heard of Freemarker.

FreeMarker is a “template engine”; a generic tool to generate text output (anything from HTML to autogenerated source code) based on templates. It’s a Java package, a class library for Java programmers. It’s not an application for end-users in itself, but something that programmers can embed into their products.

It is the “generic” nature of Freemarker that trips up java web developers. Freemarker by default does not provide any facilities to allow default HTML-escaping of content – a necessity if you want to attempt to prevent Cross-Site Scripting attacks on your web applications. Yes I know that it has the ?html built-in, and that you can wrap blocks of text in <#escape x as x?html> directives, but you have to remember to do that on each page.

What if there was another way?

The class below is a Freemarker TemplateLoader that automatically wraps each loaded template with the HTML-escape directive. Now there is no need to remember to do that in your templates. You can find it being used in my example project on GitHub.

import freemarker.cache.TemplateLoader;
import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class HtmlTemplateLoader implements TemplateLoader {

    public static final String ESCAPE_PREFIX = "<#ftl strip_whitespace=true><#escape x as x?html>";
    public static final String ESCAPE_SUFFIX = "</#escape>";

    private final TemplateLoader delegate;

    public HtmlTemplateLoader(TemplateLoader delegate) {
        this.delegate = delegate;
    }

    @Override
    public Object findTemplateSource(String name) throws IOException {
        return delegate.findTemplateSource(name);
    }

    @Override
    public long getLastModified(Object templateSource) {
        return delegate.getLastModified(templateSource);
    }

    @Override
    public Reader getReader(Object templateSource, String encoding) throws IOException {
        Reader reader = delegate.getReader(templateSource, encoding);
        try {
            String templateText = IOUtils.toString(reader);
            return new StringReader(ESCAPE_PREFIX + templateText + ESCAPE_SUFFIX);
        } finally {
            IOUtils.closeQuietly(reader);
        }
    }

    @Override
    public void closeTemplateSource(Object templateSource) throws IOException {
        delegate.closeTemplateSource(templateSource);
    }
}

To wire this up using SpringFramework’s Freemarker support you do have to take another step and extend its FreeMarkerConfigurer to register the HtmlTemplateLoader as the one to use for view resolution and rendering. If on the other hand you don’t use Spring then you have one less bit of code to maintain.

import freemarker.cache.TemplateLoader;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import java.util.List;

public class HtmlFreeMarkerConfigurer extends FreeMarkerConfigurer {

    @Override
    protected TemplateLoader getAggregateTemplateLoader(List<TemplateLoader> templateLoaders) {
        logger.info("Using HtmlTemplateLoader to enforce HTML-safe content");
        return new HtmlTemplateLoader(super.getAggregateTemplateLoader(templateLoaders));
    }
}

Tags: , , , , , ,

RubyGems in a JAR

On a few projects now I’ve used jruby with rake. I know that I can use rvm and just fetch the gems per project, but for developers stuck on windows that way is a little more than difficult. So here’s how I package up rubygems in a JAR.

#!/bin/bash
mkdir gemjar
java -jar jruby-complete-1.6.3.jar -S gem install -i ./gemjar haml --version 3.1.2 --no-rdoc --no-ri
java -jar jruby-complete-1.6.3.jar -S gem install -i ./gemjar net-scp --version 1.0.4 --no-rdoc --no-ri
java -jar jruby-complete-1.6.3.jar -S gem install -i ./gemjar jruby-openssl --version 0.7.4 --no-rdoc --no-ri
java -jar jruby-complete-1.6.3.jar -S gem install -i ./gemjar fpm --version 0.3.7 --no-rdoc --no-ri
jar cf ruby-gems.jar -C gemjar .
rm -rf gemjar

You then invoke jruby rake via:

#!/bin/bash
java -jar jruby-complete-1.6.3.jar -rruby-gems.jar -S rake build.rb $@

This means that you can then invoke the following useful little nuggets:

task :list_gems do
  require "rubygems/gem_runner"
  Gem::GemRunner.new.run ["list"]
end

task :sass_watch do
  require 'haml'
  require 'haml/exec'
  opts = Haml::Exec::Sass.new ['--watch', 'src/main/sass:src/main/webapp/static/css']
  opts.parse!
end

task :ssh_copy, :file do |t, args|
  require "net/ssh"
  require "net/scp"
  Net::SSH.start("repository.remote", "user") do |ssh|
    ssh.scp.upload!(args.file, "/tmp/files/")
  end
end

task :make_rpm => :make_war do
  fail "Please install rpm-build to make RPMs!" unless system("rpmbuild --version")

  require "fpm"
  require "fpm/program"
  exit_code = FPM::Program.new.run([
    "-s", "dir", "-t", "rpm", "-n", APPLICATION_NAME, "-v", RPM_VERSION_NUMBER, "-a", "all",
    "--post-install", "target/rpmbuild/opt/application/bin/post_install.sh",
    "--pre-uninstall", "target/rpmbuild/opt/application/bin/pre_uninstall.sh",
    "-C", "target/rpmbuild", "opt"
  ])

  fail "Build failed" if exit_code != 0
end

How awesome is this?

Tags: , , , , , , , , ,

JRuby Rake and Ivy

Here’s a neat way of using ivy with jruby, rake & ant.

task :ivy_retrieve do
  ant.taskdef :resource => "org/apache/ivy/ant/antlib.xml" do
    classpath :location => "ivy/ivy-2.2.0.jar"
  end
  ant.configure :file => "ivy/ivysettings.xml"
  ant.resolve :file => "ivy/ivy.xml"
  ant.retrieve :pattern => "lib/[conf]/[type]/[artifact]-[revision].[ext]", :sync => "true"
  puts
end

Still using ant, still angle bracket free (except for ivy, sigh). Read my previous post if you want to know more about jruby, rake and ant.

Tags: , , , , , ,