org.owasp.esapi.PreparedString Maven / Gradle / Ivy
/**
* OWASP Enterprise Security API (ESAPI)
*
* This file is part of the Open Web Application Security Project (OWASP)
* Enterprise Security API (ESAPI) project. For details, please see
* http://www.owasp.org/index.php/ESAPI.
*
* Copyright (c) 2007-2019 - The OWASP Foundation
*
* The ESAPI is published by OWASP under the BSD license. You should read and accept the
* LICENSE before you use, modify, and/or redistribute this software.
*
* @author Jeff Williams Aspect Security
* @created 2009
*/
package org.owasp.esapi;
import java.util.ArrayList;
import org.owasp.esapi.codecs.Codec;
/**
* A parameterized string that uses escaping to make untrusted data safe before combining it with
* a command or query intended for use in an interpreter.
*
* PreparedString div = new PreparedString( "<a href=\"http:\\\\example.com?id=?\" onmouseover=\"alert('?')\">test</a>", new HTMLEntityCodec() );
* div.setURL( 1, request.getParameter( "url" ), new PercentCodec() );
* div.set( 2, request.getParameter( "message" ), new JavaScriptCodec() );
* out.println( div.toString() );
*
* // escaping for SQL
* PreparedString query = new PreparedString( "SELECT * FROM users WHERE name='?' AND password='?'", new OracleCodec() );
* query.set( 1, request.getParameter( "name" ) );
* query.set( 2, request.getParameter( "pass" ) );
* stmt.execute( query.toString() );
*
*
* @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security
* @since June 1, 2007
*/
public class PreparedString {
char parameterCharacter = '?';
Codec codec = null;
String[] parameters = null;
ArrayList parts = new ArrayList();
private final static char[] IMMUNE = {};
/**
* Create a PreparedString with the supplied template and Codec. The template should use the
* default parameter placeholder character (?) in the place where actual parameters are to be inserted.
* The supplied Codec will be used to escape characters in calls to set, unless a specific Codec is
* provided to override it.
* @param template
* @param codec
*/
public PreparedString( String template, Codec codec ) {
this.codec = codec;
split( template, parameterCharacter );
}
/**
* Create a PreparedString with the supplied template, parameter placeholder character, and Codec. The parameter character
* can be any character, but should not be one that will be used in the template. The parameter character can safely
* be used in a parameter passed into the set methods.
* @param template
* @param parameterCharacter
* @param codec
*/
public PreparedString( String template, char parameterCharacter, Codec codec ) {
this.codec = codec;
this.parameterCharacter = parameterCharacter;
split( template, parameterCharacter );
}
/**
* Split a string with a particular character.
* @param str
* @param c
*/
private void split( String str, char c ) {
int index = 0;
int pcount = 0;
for ( int i = 0; i < str.length(); i++ ) {
if ( str.charAt(i) == c ) {
pcount++;
parts.add( str.substring(index,i) );
index = i + 1;
}
}
parts.add( str.substring(index) );
parameters = new String[pcount];
}
/**
* Set the parameter at index with supplied value using the default Codec to escape.
* @param index
* @param value
*/
public void set( int index, String value ) {
if ( index < 1 || index > parameters.length ) {
throw new IllegalArgumentException( "Attempt to set parameter " + index + " on a PreparedString with only " + parameters.length + " placeholders" );
}
String encoded = codec.encode( IMMUNE, value );
parameters[index-1] = encoded;
}
/**
* Set the parameter at index with supplied value using the supplied Codec to escape.
* @param index
* @param value
* @param codec
*/
public void set( int index, String value, Codec codec ) {
if ( index < 1 || index > parameters.length ) {
throw new IllegalArgumentException( "Attempt to set parameter " + index + " on a PreparedString with only " + parameters.length + " placeholders" );
}
String encoded = codec.encode( IMMUNE, value );
parameters[index-1] = encoded;
}
/**
* Render the PreparedString by combining the template with properly escaped parameters.
*/
public String toString() {
for ( int ix = 0; ix < parameters.length; ix++ ) {
if ( parameters[ix] == null ) {
throw new RuntimeException( "Attempt to render PreparedString without setting parameter " + ( ix + 1 ));
}
}
StringBuilder sb = new StringBuilder();
int i = 0;
for ( int p=0; p < parts.size(); p++ ) {
sb.append( parts.get( p ) );
if ( i < parameters.length ) sb.append( parameters[i++] );
}
return sb.toString();
}
}