Friday, July 15, 2011

Rich text component validation

Rich Text Components return HTML code, and if you are going to show it on your pages there is problem that some bad person can submit malicious HTML to your server and if you will display it "as is", this code can do something bad. So you have to check somehow that code that is submitted is generate by your component, or at least is safe. Latter is called HTML sanitization.
Simple pattern matching is too trivial, as malicious code can be hidden behind some strange unicode symbols or so (you can check how tricky it is at http://ha.ckers.org/xss.html). Basically, it usually requires parsing HTML and detecting, what can be used and what can't. Fortunately, there is already nice HTML parser built into JDK. It is intended to be used in Swing, but is abstract enough to be used for validation too. What you need to do is to extend javax.swing.text.html.parser.Parser, like:

import javax.swing.text.html.parser.*
import static javax.swing.text.html.HTML.Tag.*
import static javax.swing.text.html.HTML.Attribute.*

class RteParser extends Parser {
  boolean hasErrors = false
    
  public RteParser() {
    super(DTD.getDTD('html'));
  }
  
  void validateTag(tag) {
    ...
  }
  
  void handleStartTag(TagElement tag) {
    validateTag(tag)
    this.flushAttributes()
  }
  
  void handleEndTag(TagElement tag) {
    validateTag(tag)
    this.flushAttributes()
  }
  
  void handleEmptyTag(TagElement tag) {
    validateTag(tag)
    this.flushAttributes()
  }

  public static boolean validate(String value) {
    RteParser parser = new RteParser()
    StringReader reader = new StringReader("<html>${value}</html>")
    parser.parse(reader)
    return parser.isValid()
  }
  
  public boolean isValid() {
    return !hasErrors
  }

}



All validation can be done by calling static validate method.
All magic is done in validateTag. This method is specific, this is place where you check all tags and attributes against some black list or validation patterns.

Wednesday, July 6, 2011

Whole object validation with Grails

There is nice field validation framework in Grails (based on Spring) with a lot of documentation.
However recently I needed to implement whole object validation (I have some rules across different fields). It is easily supported by Grails, but is not that well documented. All you need to do is to is to implement method beforeValidate in your domain object, like:

def beforeValidate() {
  if (somethingbad()) {
    errors.addError("fieldname", "something bad happened")
  }
}


All errors that you have you should put into errors object, which is instance of
org.springframework.validation.BeanPropertyBindingResult and you can add errors as org.springframework.validation.ObjectError instances.

Monday, July 4, 2011

Handling HTML changes via DOMSubtreeModified

Recently, I needed to handle changes in DOJO rich text editor. It supports all traditional events, but my problem was that I needed to handle also copy/pastes and especially mouse copy/pastes (right button context menu), as I have found, it does not counts as mouse events. After some investigation I have found nice, but for some reason not so popular event DOMSubtreeModified.
So I am able to handle all changes by subscribing to changes like:
rte.addEventListener("DOMSubtreeModified", function(){
   ...
}

One issue with this approach is that it is not supported by all browsers and is depricated by W3, but I need this feature for controlled environment.

Saturday, June 25, 2011

Executable WAR and jetty:run

After creating executable WAR I have noticed that when I run application with jetty:run, there is conflict between jetty libs from maven plugin and application dependencies:

2011-06-26 00:54:14.067:INFO::jetty-8.0.0.M2
2011-06-26 00:54:15.779:WARN::Failed startup of context JettyWebAppContext@5a347448@5a347448/myexecutable,file:/
java.lang.IllegalArgumentException: Object is not of type class org.eclipse.jetty.webapp.WebAppContext
        at org.eclipse.jetty.xml.XmlConfiguration.configure(XmlConfiguration.java:204)
        at org.eclipse.jetty.plus.webapp.EnvConfiguration.configure(EnvConfiguration.java:98)
        at org.eclipse.jetty.webapp.WebAppContext.configure(WebAppContext.java:473)
        at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1174)
        at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:598)
        at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:496)
        at org.mortbay.jetty.plugin.JettyWebAppContext.doStart(JettyWebAppContext.java:175)
        at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:55)
        at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:226)
        at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:164)
        at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:55)
        at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:226)
        at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:55)
        at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:93)
        at org.eclipse.jetty.server.Server.doStart(Server.java:244)
        at org.mortbay.jetty.plugin.JettyServer.doStart(JettyServer.java:67)
        at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:55)
        at org.mortbay.jetty.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:447)
        at org.mortbay.jetty.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:387)
        at org.mortbay.jetty.plugin.JettyRunMojo.execute(JettyRunMojo.java:555)
        at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:490)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:694)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandaloneGoal(DefaultLifecycleExecutor.java:569)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:539)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:387)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:348)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:180)

I have found that this problem can be quickly solved by using maven profiles.
All that is needed to do is to define new profile, and move all dependencies there:

<profiles>
  <profile>
      <id>myexecutablewar</id>
      <activation>
        <property>
          <name>myexecutablewar</name>
          <value>true</value>
        </property>
      </activation>
    <dependencies>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-jndi</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-plus</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-start</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-webapp</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-util</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-jmx</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>jsp-2.1-glassfish</artifactId>
            <version>2.1.v20100127</version>
        </dependency>
    </dependencies>

  </profile>
</profiles>

Now, when you simply run

mvn jetty:run

it runs without using dependencies, but when you run

mvn install -Dmyexecutablewar=true
it uses dependencies and creates executable package.

Executable WAR

Recently I created very small and lightweight web application. It supposed to be using web sockets, so I decided to use Jetty as application server, but instead of using it like container, I decided to save on project and configuration folders and scripts and deploy it as executable WAR.
It was surprisingly easy to do. Basically, only thing that is needed is maven with Shade plugin. This plugin allows to pack all dependencies together in single JAR. Also it allows to modify manifest, and comes with simple examples.
So, all you need to do is to add jetty dependencies to pom.xml, for example:

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-jndi</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-plus</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-start</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-webapp</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-util</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-jmx</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>jsp-2.1-glassfish</artifactId>
            <version>2.1.v20100127</version>
        </dependency>

And Shade plugin configuration:

            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-shade-plugin</artifactId>
              <version>1.4</version>
            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>shade</goal>
                </goals>
                <configuration>
                  <artifactSet>
                    <includes>
                      <include>org.eclipse.jetty:*</include>
                      <include>org.mortbay.jetty:*</include>
                      <include>net.sourceforge.jtds:jtds</include>
                      <include>org.slf4j:*</include>
                      <include>log4j:*</include>
                      <include>c3p0:c3p0</include>
                    </includes>
                  </artifactSet>
                  <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                      <manifestEntries>
                        <Main-Class>org.eclipse.jetty.start.Main</Main-Class>
                        <Build-Number>123</Build-Number>
                      </manifestEntries>
                    </transformer>
                  </transformers>
                </configuration>
              </execution>
            </executions>
            </plugin>


And as output you should get nice, executable WAR web application, that is ready to be launched as easy as:

java -jar myexecutable.war jetty.xml

Of course it is good idea to externalize logging or jetty configuration in separate jetty.xml file, so you can change it without creating new deployment.
It can be as simple as:

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure id="FileServer" class="org.eclipse.jetty.server.Server">

    <Call name="addConnector">
      <Arg>
          <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
            <Set name="port">8080</Set>
            <Set name="Host">localhost</Set>
          </New>
      </Arg>
    </Call>

    <Set name="handler">
      <New class="org.eclipse.jetty.server.handler.HandlerList">
        <Set name="handlers">
          <Array type="org.eclipse.jetty.server.Handler">
            <Item>
              <New class="org.eclipse.jetty.webapp.WebAppContext">
                <Set name="contextPath">/myexecutable</Set>
                <Set name="war">myexecutable.war</Set>
              </New>
            </Item>
          </Array>
        </Set>
      </New>
    </Set>

  <New id="onewalletDS" class="org.eclipse.jetty.plus.jndi.Resource">
    <Arg>myDS</Arg>
    <Arg>
      <New class="com.mchange.v2.c3p0.ComboPooledDataSource">
         <Set name="driverClass">net.sourceforge.jtds.jdbcx.JtdsDataSource</Set>
         <Set name="user">user</Set>
         <Set name="password">password</Set>
         <Set name="jdbcUrl">jdbc:jtds:sqlserver://localhost/myds</Set>
     </New>
    </Arg>
  </New>

</Configure>

Friday, April 1, 2011

Playing music file from HTML page

This is first time I need this in many years, but finally this day has come: I need to play MP3 file from web page.
Looks like the easiest way to do is by using embed tag, so when I need it is needed to play it, I just call from javascript:
$('#sound_element').html("<embed src='scripts/"+file+".mp3' hidden='true' autostart='true' loop='false'>");
Of course I need to have this div somewhere on the page:
<div id="sound_element"></div>
And it does the magic. I found that it plays flawlessly in Chrome, but for Firefox it asks for Quicktime plugin. But I need it for managed environment, so it is not a big deal.
Finally, I can add some tunes to my blog! ;)

Skip XML declaration in JAXB

By default JAXB outputs XML declaration when you marshal your objects:
For example, this:

JAXBContext context = JAXBContext.newInstance(Command.class, Message.class...);
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(command, writer);
will output this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<message channel="test"/>


If you don't need to use XML declaration in your JAXB output, it is easy to skip it by setting property "jaxb.fragment" to true. So, this:
JAXBContext context = JAXBContext.newInstance(Command.class, Message.class...);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty("jaxb.fragment", Boolean.TRUE);
marshaller.marshal(command, writer);
will output only this:
<message channel="test"/>