All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sakaiproject.util.Validator Maven / Gradle / Ivy

There is a newer version: 23.3
Show newest version
/*********************************************************************************a
 * $URL$
 * $Id$
 ***********************************************************************************
 *
 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 Sakai Foundation
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 **********************************************************************************/

package org.sakaiproject.util;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

import lombok.extern.slf4j.Slf4j;

import org.sakaiproject.component.cover.ServerConfigurationService;
import org.sakaiproject.exception.IdInvalidException;

/**
 * 

* Validator is utility class that helps to validate stuff. *

* @deprecated use apache commons utils or {@link org.sakaiproject.util.api.FormattedText}, this will be removed after 2.9 - Dec 2011 */ @Deprecated @Slf4j public class Validator { /** These characters are not allowed in a resource id */ public static final String INVALID_CHARS_IN_RESOURCE_ID = "^/\\{}[]()%*?#&=\n\r\t\b\f"; /** These characters are not allowed in a user id */ protected static final String INVALID_CHARS_IN_USER_ID = "^/\\%*?\n\r\t\b\f"; /** These characters are not allowed in a site type */ protected static final String INVALID_CHARS_IN_SITE_TYPE = " $&':<>[]{}#%@/;=?\\^|~\""; /** These characters are not allowed in a site skin */ protected static final String INVALID_CHARS_IN_SITE_SKIN = " $&':<>[]{}#%@/;=?\\^|~\""; protected static final String MAP_TO_A = "��������"; protected static final String MAP_TO_B = "��"; protected static final String MAP_TO_C = "����"; protected static final String MAP_TO_E = "��������"; protected static final String MAP_TO_I = "�����"; protected static final String MAP_TO_L = "��"; protected static final String MAP_TO_N = "���"; protected static final String MAP_TO_O = "������"; protected static final String MAP_TO_U = "������"; protected static final String MAP_TO_Y = "ش??"; protected static final String MAP_TO_X = "???�����?����?"; /** * These characters are allowed; but if escapeResourceName() is called, they are escaped (actually, removed) Certain characters cause problems with filenames in certain OSes - so get rid of these characters in filenames */ protected static final String ESCAPE_CHARS_IN_RESOURCE_ID = ";'\""; protected static final String INVALID_CHARS_IN_ZIP_ENTRY = "/\\%:*?'\""; /** These characters are escaped when making a URL */ // protected static final String ESCAPE_URL = "#%?&='\"+ "; // not '/' as that is assumed to be part of the path protected static final String ESCAPE_URL = "$&+,:;=?@ '\"<>#%{}|\\^~[]`"; /** * These can't be encoded in URLs safely even using %nn notation, so encode them using our own custom URL encoding */ protected static final String ESCAPE_URL_SPECIAL = "^?;"; /** Valid special email local id characters (- those that are invalid resource ids) */ protected static final String VALID_EMAIL = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!#$&'*+-=?^_`{|}~."; protected static final String INVALID_CHARS_IN_FILENAME = "[\\/:\"*?<>|]+"; /** * Escape a plaintext string so that it can be output as part of an HTML document. Amperstand, greater-than, less-than, newlines, etc, will be escaped so that they display (instead of being interpreted as formatting). * * @param value * The string to escape. * @return value fully escaped for HTML. * @deprecated this is a passthrough for {@link FormattedText#escapeHtml(String, boolean)} so use that instead */ public static String escapeHtml(String value) { return FormattedText.escapeHtml(value, true); } /** * Escape plaintext for display inside a plain textarea. * @deprecated this is a passthrough for {@link FormattedText#escapeHtml(String, boolean)} so use that instead */ public static String escapeHtmlTextarea(String value) { return FormattedText.escapeHtml(value, false); } /** * Escape HTML-formatted text in preparation to include it in an HTML document. * @deprecated this is a passthrough for {@link FormattedText#escapeHtmlFormattedText(String)} so use that instead */ public static String escapeHtmlFormattedText(String value) { return FormattedText.escapeHtmlFormattedText(value); } /** * Escapes the given HTML-formatted text for editing within the WYSIWYG editor. All HTML meta-characters in the string (such as amperstand, less-than, etc), will be escaped. * * @param value * The formatted text to escape * @return The string to use as the value of the formatted textarea widget * @deprecated this is a passthrough for {@link FormattedText#escapeHtmlFormattedTextarea(String)} so use that instead */ public static String escapeHtmlFormattedTextarea(String value) { return FormattedText.escapeHtmlFormattedTextarea(value); } /** * Return a string based on value that is safe to place into a javascript / html identifier: anything not alphanumeric change to 'x'. If the first character is not alphabetic, a letter 'i' is prepended. * * @param value * The string to escape. * @return value fully escaped using javascript / html identifier rules. * @deprecated use commons-lang StringEscapeUtils */ public static String escapeJavascript(String value) { if (value == null || "".equals(value)) return ""; try { StringBuilder buf = new StringBuilder(); // prepend 'i' if first character is not a letter if (!java.lang.Character.isLetter(value.charAt(0))) { buf.append("i"); } // change non-alphanumeric characters to 'x' for (int i = 0; i < value.length(); i++) { char c = value.charAt(i); if (!java.lang.Character.isLetterOrDigit(c)) { buf.append("x"); } else { buf.append(c); } } String rv = buf.toString(); return rv; } catch (Exception e) { log.warn("Validator.escapeJavascript: ", e); return ""; } } // escapeJavascript /** * Return a string based on id that is fully escaped using URL rules, using a UTF-8 underlying encoding. * One reason for this existing is that the standard URLEncoder in Java will encode slashes ('/') but this method doesn't. * Also watch out as it trims trailing spaces, and other character get lost here too. * * Note: java.net.URLEncode.encode() provides a more standard option * FormattedText.decodeNumericCharacterReferences() undoes this op * * @param id * The string to escape. * @return id fully escaped using URL rules. * @deprecated use java.net.URLEncode.encode() */ public static String escapeUrl(String id) { if (id == null) return ""; id = id.trim(); try { // convert the string to bytes in UTF-8 byte[] bytes = id.getBytes("UTF-8"); StringBuilder buf = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { byte b = bytes[i]; // escape ascii control characters, ascii high bits, specials if (ESCAPE_URL_SPECIAL.indexOf((char) b) != -1) { buf.append("^^x"); // special funky way to encode bad URL characters buf.append(toHex(b)); buf.append('^'); } // 0x1F is the last control character // 0x7F is DEL chatecter // 0x80 is the start of the top of the 256bit set. else if ((ESCAPE_URL.indexOf((char) b) != -1) || (b <= 0x1F) || (b == 0x7F) || (b >= 0x80)) { buf.append("%"); buf.append(toHex(b)); } else { buf.append((char) b); } } String rv = buf.toString(); return rv; } catch (UnsupportedEncodingException e) { log.warn("Validator.escapeUrl: ", e); return ""; } } // escapeUrl /** * Is this a valid local part of an email id? * @deprecated use commons-validator EmailValidator */ public static boolean checkEmailLocal(String id) { // rules based on rfc2882, but a bit more conservative for (int i = 0; i < id.length(); i++) { if (VALID_EMAIL.indexOf(id.charAt(i)) == -1) return false; } return true; } // checkEmailLocal /** * Return a string based on id that is valid according to Resource name validity rules. * * @param id * The string to escape. * @return id fully escaped using Resource name validity rules. */ public static String escapeResourceName(String id) { if (id == null) return ""; id = id.trim(); try { StringBuilder buf = new StringBuilder(); for (int i = 0; i < id.length(); i++) { char c = id.charAt(i); if (MAP_TO_A.indexOf(c) >= 0) { buf.append('a'); } else if (MAP_TO_E.indexOf(c) >= 0) { buf.append('e'); } else if (MAP_TO_I.indexOf(c) >= 0) { buf.append('i'); } else if (MAP_TO_O.indexOf(c) >= 0) { buf.append('o'); } else if (MAP_TO_U.indexOf(c) >= 0) { buf.append('u'); } else if (MAP_TO_Y.indexOf(c) >= 0) { buf.append('y'); } else if (MAP_TO_N.indexOf(c) >= 0) { buf.append('n'); } else if (MAP_TO_B.indexOf(c) >= 0) { buf.append('b'); } else if (MAP_TO_C.indexOf(c) >= 0) { buf.append('c'); } else if (MAP_TO_L.indexOf(c) >= 0) { buf.append('l'); } else if (MAP_TO_X.indexOf(c) >= 0) { buf.append('x'); } else if (c < '\040') // Remove any ascii control characters { buf.append('_'); } else if (INVALID_CHARS_IN_RESOURCE_ID.indexOf(c) >= 0 || ESCAPE_CHARS_IN_RESOURCE_ID.indexOf(c) >= 0) { buf.append('_'); } else { buf.append(c); } } String rv = buf.toString(); return rv; } catch (Exception e) { log.warn("Validator.escapeResourceName: ", e); return ""; } } // escapeResourceName /** * Return a string based on id that is fully escaped the question mark. * * @param id * The string to escape. * @return id fully escaped question mark. */ public static String escapeQuestionMark(String id) { if (id == null) return ""; try { StringBuilder buf = new StringBuilder(); for (int i = 0; i < id.length(); i++) { char c = id.charAt(i); if (c == '?') { buf.append('_'); } else { buf.append(c); } } String rv = buf.toString(); return rv; } catch (Exception e) { log.warn("Validator.escapeQuestionMark: ", e); return ""; } } // escapeQuestionMark /** * Return a string based on id that is fully escaped to create a zip entry * * @param id * The string to escape. * @return id fully escaped to create a zip entry */ public static String escapeZipEntry(String id) { if (id == null) return ""; try { StringBuilder buf = new StringBuilder(); for (int i = 0; i < id.length(); i++) { char c = id.charAt(i); if (INVALID_CHARS_IN_ZIP_ENTRY.indexOf(c) != -1) { buf.append('_'); } else { buf.append(c); } } String rv = buf.toString(); return rv; } catch (Exception e) { log.warn("Validator.escapeZipEntry: ", e); return ""; } } // escapeZipEntry /** * Check for a valid user id. * * @exception IdInvalidException * if the id is invalid. */ public static boolean checkUserId(String id) { // the rules: // Null is rejected // all blank is rejected // INVALID_CHARS_IN_USER_ID characters are rejected if (id == null) return false; if (id.trim().length() == 0) return false; // we must reject certain characters that we cannot even escape and get into Tomcat via a URL for (int i = 0; i < id.length(); i++) { if (INVALID_CHARS_IN_USER_ID.indexOf(id.charAt(i)) != -1) return false; } return true; } // checkUserId /** * Check for a valid resource id. * * @return true if valid, false if not */ public static boolean checkResourceId(String id) { // the rules: // Null is rejected // all blank is rejected // INVALID_CHARS_IN_RESOURCE_ID characters are rejected if (id == null) return false; if (id.trim().length() == 0) return false; // we must reject certain characters that we cannot even escape and get into Tomcat via a URL for (int i = 0; i < id.length(); i++) { if (INVALID_CHARS_IN_RESOURCE_ID.indexOf(id.charAt(i)) != -1) return false; } return true; } // checkResourceId /** * Check for a syntactically valid site type. * * @return true if valid, false if not */ public static boolean checkSiteType(String id) { // the rules: // Null is accepted // all blank is accepted // INVALID_CHARS_IN_SITE_TYPE characters are rejected if (id == null) return true; if (id.trim().length() == 0) return false; // reject certain characters for (int i = 0; i < id.length(); i++) { if (INVALID_CHARS_IN_SITE_TYPE.indexOf(id.charAt(i)) != -1) return false; } return true; } // checkSiteType /** * Check for a syntactically valid skin name * * @return true if valid, false if not */ public static boolean checkSiteSkin(String id) { // the rules: // Null is allowed // all blank is rejected // INVALID_CHARS_IN_SITE_TYPE characters are rejected if (id == null) return true; if (id.trim().length() == 0) return false; // reject certain characters for (int i = 0; i < id.length(); i++) { if (INVALID_CHARS_IN_SITE_SKIN.indexOf(id.charAt(i)) != -1) return false; } return true; } // checkSiteSkin /** * Isolate and return just the file name part of a full drive and path file name. * * @param fullName * The full file name from a local os file system (mac, unix, windoze) * @return Just the name (and extension) of the file, without the drive or path. * @deprecated use commons-io FilenameUtils.getName() instead */ public static String getFileName(String fullName) { // examples: windows: c:\this\that\me.doc // unix: /usr/local/dev/test.txt // mac:? one:two:three:four // so... just take the last characters back till we see a \ or / or : StringBuilder buf = new StringBuilder(); int index = fullName.length() - 1; while (index >= 0) { char c = fullName.charAt(index--); if ((c == '\\') || (c == '/') || (c == ':')) break; buf.insert(0, c); } return buf.toString(); } // getFileName /** * Put the dividor (comma) inside the size string, for example, 1,003 for 1003 * * @param size * The string of size number * @return The size string with the dividor added */ public static String getFileSizeWithDividor(String size) { StringBuilder newSize = new StringBuilder(size); int index = size.length(); while (index > 3) { index = index - 3; newSize.insert(index, ","); } return newSize.toString(); } /** * Isolate and return just the file extension part of a full drive and path file name. * * @param fullName * The full file name from a local os file system (mac, unix, windoze) * @return Just the extension of the file, to the right of the dot, not including the dot, or blank if none. */ public static String getFileExtension(String fullName) { // just take from the last dot to the end, or return "" if there's no dot. int index = fullName.lastIndexOf('.'); if (index == -1) return ""; return fullName.substring(index + 1); } // getFileExtension /** * Determine whether a file resource should be opened in the current window or a new window. * * @param contentType * The content type to check * @return A string identifying the window in which to open the resource: "_self" to open the resource in the current window, "_blank" for a new window, or an empty string if the resource is not a file. */ public static String getResourceTarget(String contentType) { // we will open a new window unless... String rv = "_blank"; // get the resource's type if (contentType != null) { // if the browser will not inline, but mark as attachments, let's not open a new window if (!letBrowserInline(contentType)) { rv = "_self"; } } return rv; } // getResourceTarget /** * Is this a mime type that the browser can handle inline, in a browser window? If so, links to this type should be to a _blank, and content-disposition should be inline. If not, links to this type should be to _self, and content-disposition should be * attachment. * * @param type * The mime type to check. * @return true if this type of resource the browser can handle in line, false if not. */ public static boolean letBrowserInline(String type) { if (type == null) return false; String lType = type.toLowerCase(); // text (plain/html) mime types if (lType.startsWith("text/")) return true; // XHTML mime type if (lType.equals("application/xhtml+xml")) return true; // image mime types if (lType.startsWith("image/")) return true; // PDF mime types if (lType.equals("application/pdf")) return true; if (lType.equals("application/x-pdf")) return true; // internal OSP/Forms if (lType.equals("application/x-osp")) return true; // Shockwave Flash mime types if (lType.equals("application/x-shockwave-flash")) return true; if (lType.equals("application/futuresplash")) return true; // checks for VRML file MIME types:x-world/x-vrml, model/vrml, application/x-blaxxunCC3D, application/x-blaxxunCC3Dpro, application/x-CC3D // need to check for any other MIME types which can be opened by browser plug-ins? %%%zqian if (lType.indexOf("vrml") != -1 || lType.indexOf("cc3d") != -1) return true; // check additional inline types for this instance specified in sakai.properties String moreInlineTypes[] = ServerConfigurationService.getStrings("content.mime.inline"); if (moreInlineTypes != null) { for (int i = 0; i < moreInlineTypes.length; i++) { if (lType.equals(moreInlineTypes[i])) return true; } } return false; } // letBrowserInline /** * Limit the string to a certain number of characters, adding "..." if it was truncated. * * @param value * The string to limit. * @param the * length to limit to (as an Integer). * @return The limited string. */ public static String limit(String value, Integer length) { return limit(value, length.intValue()); } // limit /** * Limit the string to a certain number of characters, adding "..." if it was truncated * * @param value * The string to limit. * @param the * length to limit to (as an int). * @return The limited string. */ public static String limit(String value, int length) { StringBuilder buf = new StringBuilder(value); if (buf.length() > length) { buf.setLength(length); buf.append("..."); } return buf.toString(); } // limit /** * Clean the user input string of strange newlines, etc. * * @param value * The user input string. * @return value cleaned of string newlines, etc. */ public static String cleanInput(String value) { if (value == null) return null; if (value.length() == 0) return value; final int len = value.length(); StringBuilder buf = new StringBuilder(); for (int i = 0; i < len; i++) { char c = value.charAt(i); char next = 0; if (i + 1 < len) next = value.charAt(i + 1); switch (c) { case '\r': { // detect CR LF, make it a \n if (next == '\n') { buf.append('\n'); // eat the next character i++; } else { buf.append(c); } } break; default: { buf.append(c); } } } if (buf.charAt(buf.length() - 1) == '\n') { buf.setLength(buf.length() - 1); } return buf.toString(); } // cleanInput /** * Clean the string parameter of all newlines (replace with space character) and trim leading and trailing spaces * * @param value * The user input string. * @return value cleaned of newlines, etc. */ public static String stripAllNewlines(String value) { if (value == null) return null; value = value.trim(); if (value.length() == 0) return value; final int len = value.length(); StringBuilder buf = new StringBuilder(); for (int i = 0; i < len; i++) { char c = value.charAt(i); //char next = 0; //if (i + 1 < len) next = value.charAt(i + 1); switch (c) { case '\n': case '\r': { buf.append(' '); } break; default: { buf.append(c); } } } return buf.toString(); } // stripAllNewlines /** * Returns a hex representation of a byte. * * @param b * The byte to convert to hex. * @return The 2-digit hex value of the supplied byte. */ private static final String toHex(byte b) { char ret[] = new char[2]; ret[0] = hexDigit((b >>> 4) & (byte) 0x0F); ret[1] = hexDigit((b >>> 0) & (byte) 0x0F); return new String(ret); } /** * Returns the hex digit cooresponding to a number between 0 and 15. * * @param i * The number to get the hex digit for. * @return The hex digit cooresponding to that number. * @exception java.lang.IllegalArgumentException * If supplied digit is not between 0 and 15 inclusive. */ private static final char hexDigit(int i) { switch (i) { case 0: return '0'; case 1: return '1'; case 2: return '2'; case 3: return '3'; case 4: return '4'; case 5: return '5'; case 6: return '6'; case 7: return '7'; case 8: return '8'; case 9: return '9'; case 10: return 'A'; case 11: return 'B'; case 12: return 'C'; case 13: return 'D'; case 14: return 'E'; case 15: return 'F'; } throw new IllegalArgumentException("Invalid digit:" + i); } /** * Validate whether the date input is valid */ public static boolean checkDate(int day, int month, int year) { // Is date valid for month? if (month == 2) { // Check for leap year if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) { // leap year if (day > 29) { return false; } } else { // normal year if (day > 28) { return false; } } } else if ((month == 4) || (month == 6) || (month == 9) || (month == 11)) { if (day > 30) { return false; } } return true; } public static String generateQueryString(HttpServletRequest req) { StringBuilder sb = new StringBuilder(); try { for ( Enumeration e = req.getParameterNames(); e.hasMoreElements(); ) { String name = (String) e.nextElement(); for ( String value : req.getParameterValues(name) ) { sb.append(URLEncoder.encode(name,"UTF-8")).append("=").append(URLEncoder.encode(value,"UTF-8")).append("&"); } } } catch ( UnsupportedEncodingException ex) { log.error("No UTF-8 Encoding on this JVM, !!!!"); } if ( sb.length() < 1 ) return null; return sb.substring(0, sb.length()-1); } /** * Return a safe filename by replacing all whitespace and invalid characters * * @param filename * The string to clean * @return safe filename string */ public static String cleanFilename(String filename) { // replace all whitespace String cleanFilename = filename.replaceAll("\\s", "_"); // replace all invalid characters final int len = cleanFilename.length(); StringBuilder buf = new StringBuilder(); for (int i = 0; i < len; i++) { char c = cleanFilename.charAt(i); if (INVALID_CHARS_IN_FILENAME.indexOf(c) != -1) { buf.append("_"); } else { buf.append(c); } } return buf.toString(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy