• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 Jeff Ichnowski
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions
6 // are met:
7 //
8 //     * Redistributions of source code must retain the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer.
11 //
12 //     * Redistributions in binary form must reproduce the above
13 //       copyright notice, this list of conditions and the following
14 //       disclaimer in the documentation and/or other materials
15 //       provided with the distribution.
16 //
17 //     * Neither the name of the OWASP nor the names of its
18 //       contributors may be used to endorse or promote products
19 //       derived from this software without specific prior written
20 //       permission.
21 //
22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 // COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33 // OF THE POSSIBILITY OF SUCH DAMAGE.
34 
35 package org.owasp.encoder.esapi;
36 
37 import java.io.IOException;
38 import java.net.URI;
39 import org.owasp.encoder.Encode;
40 import org.owasp.esapi.Encoder;
41 import org.owasp.esapi.codecs.Codec;
42 import org.owasp.esapi.errors.EncodingException;
43 import org.owasp.esapi.reference.DefaultEncoder;
44 
45 /**
46  * ESAPIEncoder is a singleton implementation of the ESAPI Encoder API.  It
47  * is meant to allow quick and easy drop-in replacement of the default
48  * encoder included with the ESAPI library, as the Encoder libraries are
49  * faster and use less memory thus cause fewer garbage collections.
50  *
51  * <p>Please note that the OWASP Java Encoders does not implement all
52  * the encodings of the ESAPI Encoder API.  In such situations this
53  * implementation will fallback onto the default reference implementation
54  * included with ESAPI.  Thus you should see the performance benefit from
55  * the methods included in the Encoder, but still maintain compatibility
56  * with all methods from ESAPI Encoder.</p>
57  *
58  * <p>For clarity, the reason the OWASP Java Encoders do not include some
59  * of the ESAPI library is that the Encoders library is specifically focused
60  * on <i>encoding</i>, and thus does not include:</p>
61  *
62  * <ul>
63  *     <li>Input validation/normalization methods:
64  *     {@link org.owasp.esapi.Encoder#canonicalize(String)},
65  *     {@link org.owasp.esapi.Encoder#canonicalize(String, boolean)},
66  *     {@link org.owasp.esapi.Encoder#canonicalize(String, boolean, boolean)}
67  *     {@link org.owasp.esapi.Encoder#getCanonicalizedURI(URI)}</li>
68  *
69  *     <li>Decoding methods:
70  *     {@link org.owasp.esapi.Encoder#decodeForHTML(String)},
71  *     {@link org.owasp.esapi.Encoder#decodeFromURL(String)}</li>
72  *
73  *     <li>Binary-to-text/text-to-binary:
74  *     {@link org.owasp.esapi.Encoder#encodeForBase64(byte[], boolean)},
75  *     {@link org.owasp.esapi.Encoder#decodeFromBase64(String)}.</li>
76  *
77  *     <li>Bind-able APIs (such as {@link java.sql.PreparedStatement}:
78  *     {@link org.owasp.esapi.Encoder#encodeForSQL(org.owasp.esapi.codecs.Codec, String)},
79  *     {@link org.owasp.esapi.Encoder#encodeForXPath(String)},
80  *     {@link org.owasp.esapi.Encoder#encodeForOS(org.owasp.esapi.codecs.Codec, String)}</li>
81  *
82  *     <li>Rarely-used or alternate compatible encoding:
83  *     {@link org.owasp.esapi.Encoder#encodeForVBScript(String)},
84  *     {@link org.owasp.esapi.Encoder#encodeForLDAP(String)},
85  *     {@link org.owasp.esapi.Encoder#encodeForLDAP(String, boolean)},
86  *     {@link org.owasp.esapi.Encoder#encodeForDN(String)}</li>
87  * </ul>
88  *
89  * <p>(Please note that with sufficient feedback from the user base, the above
90  * mentioned methods may be implemented in future releases of the OWASP
91  * Java Encoders, if/when that happens, this shim class will be updated to
92  * call out to the new methods.)</p>
93  *
94  * <p>You may notice that this class does not actually implement Encoder
95  * itself.  Instead it simply provides a {@link #getInstance()} method that
96  * does.  This allows the implementation details maximum flexibility by not
97  * creating a any public API that would restrict changes later</p>
98  *
99  * @author jeffi
100  */
101 public final class ESAPIEncoder {
102 
103     /** No instances. */
ESAPIEncoder()104     private ESAPIEncoder() {}
105 
106     /**
107      * Returns an instance of the Encoder.  This method is the only supported
108      * mechanism by which an ESAPIEncoder instance should be obtained.  The
109      * returned implementation is guaranteed to be thread-safe for the methods
110      * that the OWASP Java Encoders implement (see class documentation).
111      * Though not a requirement of the ESAPI Encoder API, the returned value
112      * is also serializable.
113      *
114      * @return An encoder implementation that uses the OWASP Java Encoders
115      * for most of the common encoding methods.
116      */
getInstance()117     public static Encoder getInstance() {
118         return Impl.INSTANCE;
119     }
120 
121     /**
122      * This is the private singleton that implements the ESAPI Encoder shim.
123      * It is implemented as a single-value enum to get all the "free" singleton
124      * properties associated with enums--such as serialization, and on-demand
125      * initialization.
126      *
127      * <p>The implementation is intentionally private to avoid any API baggage.
128      * The instance should be obtained using
129      * {@link org.owasp.encoder.esapi.ESAPIEncoder#getInstance()}.</p>
130      */
131     private enum Impl implements Encoder {
132         /**
133          * The singleton instance.
134          */
135         INSTANCE;
136 
137         /**
138          * The reference encoder from ESAPI.  Any ESAPI method without an
139          * OWASP Java Encoder equivalent is delegated to this instance.
140          */
141         private final Encoder _referenceEncoder = DefaultEncoder.getInstance();
142 
143         /** {@inheritDoc} */
canonicalize(String s)144         public String canonicalize(String s) {
145             return _referenceEncoder.canonicalize(s);
146         }
147 
148         /** {@inheritDoc} */
canonicalize(String s, boolean strict)149         public String canonicalize(String s, boolean strict) {
150             return _referenceEncoder.canonicalize(s, strict);
151         }
152 
153         /** {@inheritDoc} */
canonicalize(String s, boolean restrictMultiple, boolean restrictMixed)154         public String canonicalize(String s, boolean restrictMultiple, boolean restrictMixed) {
155             return _referenceEncoder.canonicalize(s, restrictMultiple, restrictMixed);
156         }
157 
158         /** {@inheritDoc} */
getCanonicalizedURI(URI dirtyUri)159         public String getCanonicalizedURI(URI dirtyUri) {
160             return _referenceEncoder.getCanonicalizedURI(dirtyUri);
161         }
162 
163         /** {@inheritDoc} */
encodeForCSS(String s)164         public String encodeForCSS(String s) {
165             return Encode.forCssString(s);
166         }
167 
168         /** {@inheritDoc} */
encodeForHTML(String s)169         public String encodeForHTML(String s) {
170             return Encode.forHtml(s);
171         }
172 
173         /** {@inheritDoc} */
decodeForHTML(String s)174         public String decodeForHTML(String s) {
175             return _referenceEncoder.decodeForHTML(s);
176         }
177 
178         /** {@inheritDoc} */
encodeForHTMLAttribute(String s)179         public String encodeForHTMLAttribute(String s) {
180             return Encode.forHtmlAttribute(s);
181         }
182 
183         /** {@inheritDoc} */
encodeForJavaScript(String s)184         public String encodeForJavaScript(String s) {
185             return Encode.forJavaScript(s);
186         }
187 
188         /** {@inheritDoc} */
encodeForVBScript(String s)189         public String encodeForVBScript(String s) {
190             return _referenceEncoder.encodeForVBScript(s);
191         }
192 
193         /** {@inheritDoc} */
encodeForSQL(Codec codec, String s)194         public String encodeForSQL(Codec codec, String s) {
195             return _referenceEncoder.encodeForSQL(codec, s);
196         }
197 
198         /** {@inheritDoc} */
encodeForOS(Codec codec, String s)199         public String encodeForOS(Codec codec, String s) {
200             return _referenceEncoder.encodeForOS(codec, s);
201         }
202 
203         /** {@inheritDoc} */
encodeForLDAP(String s)204         public String encodeForLDAP(String s) {
205             return _referenceEncoder.encodeForLDAP(s);
206         }
207 
208         /** {@inheritDoc} */
encodeForLDAP(String s, boolean b)209         public String encodeForLDAP(String s, boolean b) {
210             return _referenceEncoder.encodeForLDAP(s, b);
211         }
212 
213         /** {@inheritDoc} */
encodeForDN(String s)214         public String encodeForDN(String s) {
215             return _referenceEncoder.encodeForDN(s);
216         }
217 
218         /** {@inheritDoc} */
encodeForXPath(String s)219         public String encodeForXPath(String s) {
220             return _referenceEncoder.encodeForXPath(s);
221         }
222 
223         /** {@inheritDoc} */
encodeForXML(String s)224         public String encodeForXML(String s) {
225             return Encode.forXml(s);
226         }
227 
228         /** {@inheritDoc} */
encodeForXMLAttribute(String s)229         public String encodeForXMLAttribute(String s) {
230             return Encode.forXmlAttribute(s);
231         }
232 
233         /** {@inheritDoc} */
encodeForURL(String s)234         public String encodeForURL(String s) throws EncodingException {
235             return Encode.forUri(s);
236         }
237 
238         /** {@inheritDoc} */
decodeFromURL(String s)239         public String decodeFromURL(String s) throws EncodingException {
240             return _referenceEncoder.decodeFromURL(s);
241         }
242 
243         /** {@inheritDoc} */
encodeForBase64(byte[] bytes, boolean wrap)244         public String encodeForBase64(byte[] bytes, boolean wrap) {
245             return _referenceEncoder.encodeForBase64(bytes, wrap);
246         }
247 
248         /** {@inheritDoc} */
decodeFromBase64(String s)249         public byte[] decodeFromBase64(String s) throws IOException {
250             return _referenceEncoder.decodeFromBase64(s);
251         }
252 
253     }
254 }
255