001: /*
002: JSPWiki - a JSP-based WikiWiki clone.
003:
004: Copyright (C) 2001-2006 Janne Jalkanen (Janne.Jalkanen@iki.fi)
005:
006: This program is free software; you can redistribute it and/or modify
007: it under the terms of the GNU Lesser General Public License as published by
008: the Free Software Foundation; either version 2.1 of the License, or
009: (at your option) any later version.
010:
011: This program is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: GNU Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public License
017: along with this program; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020: package com.ecyrd.jspwiki.ui;
021:
022: import java.text.MessageFormat;
023: import java.util.ResourceBundle;
024: import java.util.regex.Matcher;
025: import java.util.regex.Pattern;
026:
027: import com.ecyrd.jspwiki.WikiSession;
028: import com.ecyrd.jspwiki.i18n.InternationalizationManager;
029:
030: /**
031: * Provides basic validation services for HTTP parameters. Three standard
032: * validators are provided: email address, identifier and standard input. Standard input
033: * validator will reject any HTML-like input, and any of a number of special
034: * characters. ID validator rejects HTML and quoted strings, and a couple of special characters.
035: * @author Andrew Jaquith
036: * @since 2.3.54
037: */
038: public final class InputValidator {
039: /** Standard input validator. */
040: public static final int STANDARD = 0;
041:
042: /** Input validator for e-mail addresses. **/
043: public static final int EMAIL = 1;
044:
045: /**
046: * @since 2.4.82
047: */
048: public static final int ID = 2;
049:
050: protected static final Pattern EMAIL_PATTERN = Pattern
051: .compile("^[0-9a-zA-Z-_\\.\\+]+@([0-9a-zA-Z-_]+\\.)+[a-zA-Z]+$");
052:
053: protected static final Pattern UNSAFE_PATTERN = Pattern
054: .compile("[\\x00\\r\\n\\x0f\"':<>;&@\\xff{}\\$%\\\\]");
055:
056: /** Used when checking against IDs such as a full name when saving groups.
057: * @since 2.4.82 */
058: protected static final Pattern ID_PATTERN = Pattern
059: .compile("[\\x00\\r\\n\\x0f\"'<>;&\\xff{}]");
060:
061: private final String m_form;
062:
063: private final WikiSession m_session;
064:
065: /**
066: * Constructs a new input validator for a specific form and wiki session.
067: * When validation errors are detected, they will be added to the wiki
068: * session's messages.
069: * @param form the ID or name of the form this validator should be
070: * associated with
071: * @param session the wiki session
072: */
073: public InputValidator(String form, WikiSession session) {
074: m_form = form;
075: m_session = session;
076: }
077:
078: /**
079: * Validates a string against the {@link #STANDARD} validator and
080: * additionally checks that the value is not <code>null</code> or blank.
081: * @param input the string to validate
082: * @param label the label for the string or field ("E-mail address")
083: * @return returns <code>true</code> if valid, <code>false</code>
084: * otherwise
085: */
086: public final boolean validateNotNull(String input, String label) {
087: return validateNotNull(input, label, STANDARD);
088: }
089:
090: /**
091: * Validates a string against a particular pattern type and additionally
092: * checks that the value is not <code>null</code> or blank. Delegates to
093: * {@link #validate(String, String, int)}.
094: * @param input the string to validate
095: * @param label the label for the string or field ("E-mail address")
096: * @param type the pattern type to use (<em>e.g.</em>, {@link #STANDARD, #EMAIL}.
097: * @return returns <code>true</code> if valid, <code>false</code>
098: * otherwise
099: */
100: public final boolean validateNotNull(String input, String label,
101: int type) {
102: if (isBlank(input)) {
103: ResourceBundle rb = ResourceBundle.getBundle(
104: InternationalizationManager.CORE_BUNDLE, m_session
105: .getLocale());
106:
107: Object[] args = { label };
108: m_session.addMessage(m_form, MessageFormat.format(rb
109: .getString("validate.cantbenull"), args));
110: return false;
111: }
112: return validate(input, label, type) && !isBlank(input);
113: }
114:
115: /**
116: * Validates a string against a particular pattern type: e-mail address,
117: * standard HTML input, etc. Note that a blank or null string will
118: * always validate.
119: * @param input the string to validate
120: * @param label the label for the string or field ("E-mail address")
121: * @param type the target pattern to validate against ({@link #STANDARD},
122: * {@link #EMAIL})
123: * @return returns <code>true</code> if valid, <code>false</code>
124: * otherwise
125: */
126: public final boolean validate(String input, String label, int type) {
127: // If blank, it's valid
128: if (isBlank(input)) {
129: return true;
130: }
131:
132: ResourceBundle rb = ResourceBundle.getBundle(
133: InternationalizationManager.CORE_BUNDLE, m_session
134: .getLocale());
135:
136: // Otherwise, see if it matches the pattern for the target type
137: Matcher matcher;
138: boolean valid;
139: switch (type) {
140: case STANDARD:
141: matcher = UNSAFE_PATTERN.matcher(input);
142: valid = !matcher.find();
143: if (!valid) {
144: Object[] args = { label,
145: ""'<>;&\\@{}%$" };
146: m_session.addMessage(m_form, MessageFormat.format(rb
147: .getString("validate.unsafechars"), args));
148: }
149: return valid;
150: case EMAIL:
151: matcher = EMAIL_PATTERN.matcher(input);
152: valid = matcher.matches();
153: if (!valid) {
154: Object[] args = { label };
155: m_session.addMessage(m_form, MessageFormat.format(rb
156: .getString("validate.invalidemail"), args));
157: }
158: return valid;
159: case ID:
160: matcher = ID_PATTERN.matcher(input);
161: valid = !matcher.find();
162: if (!valid) {
163: Object[] args = { label, ""'<>;&{}" };
164: m_session.addMessage(m_form, MessageFormat.format(rb
165: .getString("validate.unsafechars"), args));
166: }
167: return valid;
168: default:
169: break;
170: }
171: throw new IllegalArgumentException("Invalid input type.");
172: }
173:
174: /**
175: * Returns <code>true</code> if a supplied string is null or blank
176: * @param input the string to check
177: * @return <code>true</code> if <code>null</code> or blank (zero-length);
178: * <code>false</code> otherwise
179: */
180: public static final boolean isBlank(String input) {
181: return input == null || input.trim().length() < 1;
182: }
183: }
|