You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by sn...@apache.org on 2006/02/23 21:32:37 UTC
svn commit: r380218 - in
/incubator/roller/branches/roller_2.1/src/org/roller:
presentation/servlets/ResourceServlet.java util/Utilities.java
Author: snoopdave
Date: Thu Feb 23 12:32:34 2006
New Revision: 380218
URL: http://svn.apache.org/viewcvs?rev=380218&view=rev
Log:
Fixed ROL-1051 and security issue in ResourceServlet
Modified:
incubator/roller/branches/roller_2.1/src/org/roller/presentation/servlets/ResourceServlet.java
incubator/roller/branches/roller_2.1/src/org/roller/util/Utilities.java
Modified: incubator/roller/branches/roller_2.1/src/org/roller/presentation/servlets/ResourceServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.1/src/org/roller/presentation/servlets/ResourceServlet.java?rev=380218&r1=380217&r2=380218&view=diff
==============================================================================
--- incubator/roller/branches/roller_2.1/src/org/roller/presentation/servlets/ResourceServlet.java (original)
+++ incubator/roller/branches/roller_2.1/src/org/roller/presentation/servlets/ResourceServlet.java Thu Feb 23 12:32:34 2006
@@ -1,13 +1,20 @@
package org.roller.presentation.servlets;
-import java.io.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLDecoder;
import java.util.Date;
-
-import javax.servlet.*;
-import javax.servlet.http.*;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.roller.model.RollerFactory;
@@ -15,7 +22,7 @@
* Resources servlet. Acts as a gateway to files uploaded by users.
*
* Since we keep uploaded resources in a location outside of the webapp
- * context we need a way to serve them up. This servlet assumes that
+ * context we need a way to serve them up. This servlet assumes that
* resources are stored on a filesystem in the "uploads.dir" directory.
*
* @author Allen Gilliland
@@ -23,46 +30,41 @@
* @web.servlet name="ResourcesServlet"
* @web.servlet-mapping url-pattern="/resources/*"
*/
-public class ResourceServlet extends HttpServlet
-{
- private static Log mLogger =
- LogFactory.getFactory().getInstance(ResourceServlet.class);
+public class ResourceServlet extends HttpServlet {
+
+ private static Log mLogger = LogFactory.getLog(ResourceServlet.class);
private String upload_dir = null;
private ServletContext context = null;
- /** Initializes the servlet.*/
public void init(ServletConfig config) throws ServletException {
+
super.init(config);
this.context = config.getServletContext();
-
+
try {
this.upload_dir = RollerFactory.getRoller().getFileManager().getUploadDir();
mLogger.debug("upload dir is ["+this.upload_dir+"]");
} catch(Exception e) { mLogger.warn(e); }
-
- }
-
- /** Destroys the servlet.
- */
- public void destroy() {
}
- /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
- * @param request servlet request
- * @param response servlet response
+ /**
+ * Handles requests for user uploaded resources.
*/
- protected void processRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
String context = request.getContextPath();
String servlet = request.getServletPath();
String reqURI = request.getRequestURI();
+ // url decoding
+ reqURI = URLDecoder.decode(reqURI, "UTF-8");
+
// calculate the path of the requested resource
// we expect ... /<context>/<servlet>/path/to/resource
String reqResource = reqURI.substring(servlet.length() + context.length());
@@ -70,12 +72,19 @@
// now we can formulate the *real* path to the resource on the filesystem
String resource_path = this.upload_dir + reqResource;
File resource = new File(resource_path);
-
+
mLogger.debug("Resource requested ["+reqURI+"]");
mLogger.debug("Real path is ["+resource.getAbsolutePath()+"]");
// do a quick check to make sure the resource exits, otherwise 404
- if(!resource.exists() || !resource.canRead()) {
+ if(!resource.exists() || !resource.canRead() || resource.isDirectory()) {
+ response.sendError(HttpServletResponse.SC_NOT_FOUND);
+ return;
+ }
+
+ // make sure someone isn't trying to sneek outside the uploads dir
+ File uploadDir = new File(this.upload_dir);
+ if(!resource.getCanonicalPath().startsWith(uploadDir.getCanonicalPath())) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
@@ -109,28 +118,10 @@
}
- /** Handles the HTTP <code>GET</code> method.
- * @param request servlet request
- * @param response servlet response
- */
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /** Handles the HTTP <code>POST</code> method.
- * @param request servlet request
- * @param response servlet response
- */
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /** Returns a short description of the servlet.
- */
- public String getServletInfo() {
- return "ResourceServlet ... serving you since 2005 ;)";
+ public void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ doGet(request, response);
}
}
+
Modified: incubator/roller/branches/roller_2.1/src/org/roller/util/Utilities.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.1/src/org/roller/util/Utilities.java?rev=380218&r1=380217&r2=380218&view=diff
==============================================================================
--- incubator/roller/branches/roller_2.1/src/org/roller/util/Utilities.java (original)
+++ incubator/roller/branches/roller_2.1/src/org/roller/util/Utilities.java Thu Feb 23 12:32:34 2006
@@ -10,6 +10,7 @@
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
+import java.net.URLDecoder;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Date;
@@ -23,81 +24,96 @@
import org.apache.commons.logging.LogFactory;
/**
- * General purpose utilities.
- *
+ * General purpose utilities.
+ *
* <pre>
- * Includes TextToHTML methods dondated by Erik Thauvin - "Donated to the
- * Roller Weblogger project for publication under the terms of the Roller
- * Software License.
+ * Includes TextToHTML methods donated by Erik Thauvin
* Copyright (C) 2002-2003 by Erik C. Thauvin (erik@thauvin.net).
* All rights reserved.
* </pre>
*
+ * <pre>
+ * Also includes addNoFollow() and transformToHTMLSubset() from Simon
+ * Brown's Pebble blog server.
+ * Copyright (c) 2003-2005, Simon Brown
+ * All rights reserved.
+ * </pre>
+ *
* @author David M Johnson
* @author Lance Lavandowska
* @author Matt Raible (added encryption methods)
*/
-public class Utilities
-{
+public class Utilities {
/** The <code>Log</code> instance for this class. */
private static Log mLogger = LogFactory.getLog(Utilities.class);
/** Pattern for matching HTML links */
- private static Pattern mLinkPattern =
- Pattern.compile("<a href=.*?>", Pattern.CASE_INSENSITIVE);
-
+ private static Pattern mLinkPattern =
+ Pattern.compile("<a href=.*?>", Pattern.CASE_INSENSITIVE);
+
+ private static final Pattern OPENING_B_TAG_PATTERN = Pattern.compile("<b>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern CLOSING_B_TAG_PATTERN = Pattern.compile("</b>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern OPENING_I_TAG_PATTERN = Pattern.compile("<i>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern CLOSING_I_TAG_PATTERN = Pattern.compile("</i>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern OPENING_BLOCKQUOTE_TAG_PATTERN = Pattern.compile("<blockquote>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern CLOSING_BLOCKQUOTE_TAG_PATTERN = Pattern.compile("</blockquote>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern BR_TAG_PATTERN = Pattern.compile("<br */*>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern OPENING_P_TAG_PATTERN = Pattern.compile("<p>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern CLOSING_P_TAG_PATTERN = Pattern.compile("</p>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern OPENING_PRE_TAG_PATTERN = Pattern.compile("<pre>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern CLOSING_PRE_TAG_PATTERN = Pattern.compile("</pre>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern OPENING_UL_TAG_PATTERN = Pattern.compile("<ul>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern CLOSING_UL_TAG_PATTERN = Pattern.compile("</ul>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern OPENING_OL_TAG_PATTERN = Pattern.compile("<ol>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern CLOSING_OL_TAG_PATTERN = Pattern.compile("</ol>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern OPENING_LI_TAG_PATTERN = Pattern.compile("<li>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern CLOSING_LI_TAG_PATTERN = Pattern.compile("</li>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern CLOSING_A_TAG_PATTERN = Pattern.compile("</a>", Pattern.CASE_INSENSITIVE);
+ private static final Pattern OPENING_A_TAG_PATTERN = Pattern.compile("<a href=.*?>", Pattern.CASE_INSENSITIVE);
+
/**
- * Utility methods for calling StringUtils since it cannot be
+ * Utility methods for calling StringUtils since it cannot be
* instantiated and Utilties can.
*/
- public static boolean isNotEmpty(String str)
- {
+ public static boolean isNotEmpty(String str) {
return StringUtils.isNotEmpty(str);
}
//------------------------------------------------------------------------
/** Strip jsessionid off of a URL */
- public static String stripJsessionId( String url )
- {
+ public static String stripJsessionId( String url ) {
// Strip off jsessionid found in referer URL
int startPos = url.indexOf(";jsessionid=");
- if ( startPos != -1 )
- {
+ if ( startPos != -1 ) {
int endPos = url.indexOf("?",startPos);
- if ( endPos == -1 )
- {
- url = url.substring(0,startPos);
- }
- else
- {
+ if ( endPos == -1 ) {
+ url = url.substring(0,startPos);
+ } else {
url = url.substring(0,startPos)
- + url.substring(endPos,url.length());
+ + url.substring(endPos,url.length());
}
}
return url;
}
-
+
//------------------------------------------------------------------------
/**
* Escape, but do not replace HTML.
* The default behaviour is to escape ampersands.
*/
- public static String escapeHTML(String s)
- {
+ public static String escapeHTML(String s) {
return escapeHTML(s, true);
}
-
+
//------------------------------------------------------------------------
/**
* Escape, but do not replace HTML.
- * @param escapseAmpersand Optionally escape
+ * @param escapeAmpersand Optionally escape
* ampersands (&).
*/
- public static String escapeHTML(String s, boolean escapeAmpersand)
- {
+ public static String escapeHTML(String s, boolean escapeAmpersand) {
// got to do amp's first so we don't double escape
- if (escapeAmpersand)
- {
+ if (escapeAmpersand) {
s = stringReplace(s, "&", "&");
}
s = stringReplace(s, " ", " ");
@@ -106,29 +122,31 @@
s = stringReplace(s, ">", ">");
return s;
}
-
+
+ public static String unescapeHTML(String str) {
+ return StringEscapeUtils.unescapeHtml(str);
+ }
+
//------------------------------------------------------------------------
/**
* Remove occurences of html, defined as any text
* between the characters "<" and ">". Replace
* any HTML tags with a space.
*/
- public static String removeHTML(String str)
- {
+ public static String removeHTML(String str) {
return removeHTML(str, true);
}
/**
* Remove occurences of html, defined as any text
- * between the characters "<" and ">".
+ * between the characters "<" and ">".
* Optionally replace HTML tags with a space.
- *
+ *
* @param str
* @param addSpace
* @return
*/
- public static String removeHTML(String str, boolean addSpace)
- {
+ public static String removeHTML(String str, boolean addSpace) {
if (str == null) return "";
StringBuffer ret = new StringBuffer(str.length());
int start = 0;
@@ -136,11 +154,9 @@
int endTag = 0;
if (beginTag == -1)
return str;
-
- while (beginTag >= start)
- {
- if (beginTag > 0)
- {
+
+ while (beginTag >= start) {
+ if (beginTag > 0) {
ret.append(str.substring(start, beginTag));
// replace each tag with a space (looks better)
@@ -149,43 +165,38 @@
endTag = str.indexOf(">", beginTag);
// if endTag found move "cursor" forward
- if (endTag > -1)
- {
+ if (endTag > -1) {
start = endTag + 1;
beginTag = str.indexOf("<", start);
}
// if no endTag found, get rest of str and break
- else
- {
+ else {
ret.append(str.substring(beginTag));
break;
}
}
// append everything after the last endTag
- if (endTag > -1 && endTag + 1 < str.length())
- {
+ if (endTag > -1 && endTag + 1 < str.length()) {
ret.append(str.substring(endTag + 1));
}
return ret.toString().trim();
}
-
+
//------------------------------------------------------------------------
/** Run both removeHTML and escapeHTML on a string.
* @param s String to be run through removeHTML and escapeHTML.
* @return String with HTML removed and HTML special characters escaped.
*/
- public static String removeAndEscapeHTML( String s )
- {
+ public static String removeAndEscapeHTML( String s ) {
if ( s==null ) return "";
else return Utilities.escapeHTML( Utilities.removeHTML(s) );
}
-
+
//------------------------------------------------------------------------
/**
* Autoformat.
*/
- public static String autoformat(String s)
- {
+ public static String autoformat(String s) {
String ret = StringUtils.replace(s, "\n", "<br />");
return ret;
}
@@ -194,100 +205,86 @@
/**
* Format date in ISO-8601 format.
*/
- public static String formatIso8601Date(Date d)
- {
+ public static String formatIso8601Date(Date d) {
return DateUtil.formatIso8601(d);
}
-
+
//------------------------------------------------------------------------
/**
* Format date in ISO-8601 format.
*/
- public static String formatIso8601Day(Date d)
- {
+ public static String formatIso8601Day(Date d) {
return DateUtil.formatIso8601Day(d);
}
-
+
//------------------------------------------------------------------------
/**
* Return a date in RFC-822 format.
*/
- public static String formatRfc822Date(Date date)
- {
+ public static String formatRfc822Date(Date date) {
return DateUtil.formatRfc822(date);
}
-
+
//------------------------------------------------------------------------
/**
* Return a date in RFC-822 format.
*/
- public static String format8charsDate(Date date)
- {
+ public static String format8charsDate(Date date) {
return DateUtil.format8chars(date);
}
-
- //------------------------------------------------------------------------
- /**
- * Replaces occurences of non-alphanumeric characters with an underscore.
- */
- public static String replaceNonAlphanumeric(String str)
- {
- return replaceNonAlphanumeric(str, '_');
- }
-
- //------------------------------------------------------------------------
- /**
- * Replaces occurences of non-alphanumeric characters with a
- * supplied char.
- */
- public static String replaceNonAlphanumeric(String str, char subst)
- {
- StringBuffer ret = new StringBuffer(str.length());
- char[] testChars = str.toCharArray();
- for (int i = 0; i < testChars.length; i++)
- {
- if (Character.isLetterOrDigit(testChars[i]))
- {
- ret.append(testChars[i]);
- }
- else
- {
- ret.append( subst );
- }
- }
- return ret.toString();
- }
-
+
+ //------------------------------------------------------------------------
+ /**
+ * Replaces occurences of non-alphanumeric characters with an underscore.
+ */
+ public static String replaceNonAlphanumeric(String str) {
+ return replaceNonAlphanumeric(str, '_');
+ }
+
+ //------------------------------------------------------------------------
+ /**
+ * Replaces occurences of non-alphanumeric characters with a
+ * supplied char.
+ */
+ public static String replaceNonAlphanumeric(String str, char subst) {
+ StringBuffer ret = new StringBuffer(str.length());
+ char[] testChars = str.toCharArray();
+ for (int i = 0; i < testChars.length; i++) {
+ if (Character.isLetterOrDigit(testChars[i])) {
+ ret.append(testChars[i]);
+ } else {
+ ret.append( subst );
+ }
+ }
+ return ret.toString();
+ }
+
//------------------------------------------------------------------------
/**
* Remove occurences of non-alphanumeric characters.
*/
- public static String removeNonAlphanumeric(String str)
- {
+ public static String removeNonAlphanumeric(String str) {
StringBuffer ret = new StringBuffer(str.length());
char[] testChars = str.toCharArray();
- for (int i = 0; i < testChars.length; i++)
- {
+ for (int i = 0; i < testChars.length; i++) {
// MR: Allow periods in page links
if (Character.isLetterOrDigit(testChars[i]) ||
- testChars[i] == '.')
- {
+ testChars[i] == '.') {
ret.append(testChars[i]);
}
}
return ret.toString();
}
-
+
//------------------------------------------------------------------------
/**
- * @param pathArray
+ * @param stringArray
+ * @param delim
* @return
*/
- public static String stringArrayToString(String[] stringArray, String delim)
- {
+ public static String stringArrayToString(String[] stringArray, String delim) {
String ret = "";
- for (int i = 0; i < stringArray.length; i++)
- {
+ for (int i = 0; i < stringArray.length; i++) {
if (ret.length() > 0)
ret = ret + delim + stringArray[i];
else
@@ -298,73 +295,65 @@
//------------------------------------------------------------------------
/**
- * Replace occurrences of str1 in string str with str2
+ * Replace occurrences of str1 in string str with str2
*/
- public static String stringReplace(String str, String str1, String str2)
- {
+ public static String stringReplace(String str, String str1, String str2) {
String ret = StringUtils.replace(str,str1,str2);
return ret;
}
-
+
//------------------------------------------------------------------------
/**
* Replace occurrences of str1 in string str with str2
- * @param str String to operate on
+ * @param str String to operate on
* @param str1 String to be replaced
* @param str2 String to be used as replacement
* @param maxCount Number of times to replace, 0 for all
*/
public static String stringReplace(
- String str,
- String str1,
- String str2,
- int maxCount)
- {
+ String str,
+ String str1,
+ String str2,
+ int maxCount) {
String ret = StringUtils.replace(str,str1,str2,maxCount);
return ret;
}
-
+
//--------------------------------------------------------------------------
/** Convert string to string array. */
public static String[] stringToStringArray(String instr, String delim)
- throws NoSuchElementException, NumberFormatException
- {
+ throws NoSuchElementException, NumberFormatException {
StringTokenizer toker = new StringTokenizer(instr, delim);
String stringArray[] = new String[toker.countTokens()];
int i = 0;
-
- while (toker.hasMoreTokens())
- {
+
+ while (toker.hasMoreTokens()) {
stringArray[i++] = toker.nextToken();
}
return stringArray;
}
-
+
//--------------------------------------------------------------------------
/** Convert string to integer array. */
public static int[] stringToIntArray(String instr, String delim)
- throws NoSuchElementException, NumberFormatException
- {
+ throws NoSuchElementException, NumberFormatException {
StringTokenizer toker = new StringTokenizer(instr, delim);
int intArray[] = new int[toker.countTokens()];
int i = 0;
-
- while (toker.hasMoreTokens())
- {
+
+ while (toker.hasMoreTokens()) {
String sInt = toker.nextToken();
int nInt = Integer.parseInt(sInt);
intArray[i++] = new Integer(nInt).intValue();
}
return intArray;
}
-
+
//-------------------------------------------------------------------
/** Convert integer array to a string. */
- public static String intArrayToString(int[] intArray)
- {
+ public static String intArrayToString(int[] intArray) {
String ret = "";
- for (int i = 0; i < intArray.length; i++)
- {
+ for (int i = 0; i < intArray.length; i++) {
if (ret.length() > 0)
ret = ret + "," + Integer.toString(intArray[i]);
else
@@ -372,149 +361,117 @@
}
return ret;
}
-
+
//------------------------------------------------------------------------
- public static void copyFile(File from, File to) throws IOException
- {
+ public static void copyFile(File from, File to) throws IOException {
InputStream in = null;
OutputStream out = null;
-
- try
- {
+
+ try {
in = new FileInputStream(from);
- }
- catch (IOException ex)
- {
+ } catch (IOException ex) {
throw new IOException(
- "Utilities.copyFile: opening input stream '"
+ "Utilities.copyFile: opening input stream '"
+ from.getPath()
+ "', "
+ ex.getMessage());
}
-
- try
- {
+
+ try {
out = new FileOutputStream(to);
- }
- catch (Exception ex)
- {
- try
- {
+ } catch (Exception ex) {
+ try {
in.close();
- }
- catch (IOException ex1)
- {
+ } catch (IOException ex1) {
}
throw new IOException(
- "Utilities.copyFile: opening output stream '"
+ "Utilities.copyFile: opening output stream '"
+ to.getPath()
+ "', "
+ ex.getMessage());
}
-
+
copyInputToOutput(in, out, from.length());
}
-
+
//------------------------------------------------------------------------
/**
* Utility method to copy an input stream to an output stream.
* Wraps both streams in buffers. Ensures right numbers of bytes copied.
*/
public static void copyInputToOutput(
- InputStream input,
- OutputStream output,
- long byteCount)
- throws IOException
- {
+ InputStream input,
+ OutputStream output,
+ long byteCount)
+ throws IOException {
int bytes;
long length;
-
+
BufferedInputStream in = new BufferedInputStream(input);
BufferedOutputStream out = new BufferedOutputStream(output);
-
+
byte[] buffer;
buffer = new byte[8192];
-
- for (length = byteCount; length > 0;)
- {
+
+ for (length = byteCount; length > 0;) {
bytes = (int) (length > 8192 ? 8192 : length);
-
- try
- {
+
+ try {
bytes = in.read(buffer, 0, bytes);
- }
- catch (IOException ex)
- {
- try
- {
+ } catch (IOException ex) {
+ try {
in.close();
out.close();
- }
- catch (IOException ex1)
- {
+ } catch (IOException ex1) {
}
throw new IOException(
- "Reading input stream, " + ex.getMessage());
+ "Reading input stream, " + ex.getMessage());
}
-
+
if (bytes < 0)
break;
-
+
length -= bytes;
-
- try
- {
+
+ try {
out.write(buffer, 0, bytes);
- }
- catch (IOException ex)
- {
- try
- {
+ } catch (IOException ex) {
+ try {
in.close();
out.close();
- }
- catch (IOException ex1)
- {
+ } catch (IOException ex1) {
}
throw new IOException(
- "Writing output stream, " + ex.getMessage());
+ "Writing output stream, " + ex.getMessage());
}
}
-
- try
- {
+
+ try {
in.close();
out.close();
- }
- catch (IOException ex)
- {
+ } catch (IOException ex) {
throw new IOException("Closing file streams, " + ex.getMessage());
}
}
-
+
//------------------------------------------------------------------------
public static void copyInputToOutput(
- InputStream input,
- OutputStream output)
- throws IOException
- {
+ InputStream input,
+ OutputStream output)
+ throws IOException {
BufferedInputStream in = new BufferedInputStream(input);
BufferedOutputStream out = new BufferedOutputStream(output);
byte buffer[] = new byte[8192];
- for (int count = 0; count != -1;)
- {
+ for (int count = 0; count != -1;) {
count = in.read(buffer, 0, 8192);
if (count != -1)
out.write(buffer, 0, count);
}
-
- try
- {
+
+ try {
in.close();
out.close();
- }
- catch (IOException ex)
- {
+ } catch (IOException ex) {
throw new IOException("Closing file streams, " + ex.getMessage());
}
}
@@ -530,47 +487,41 @@
*
* @return encypted password based on the algorithm.
*/
- public static String encodePassword(String password, String algorithm)
- {
+ public static String encodePassword(String password, String algorithm) {
byte[] unencodedPassword = password.getBytes();
-
+
MessageDigest md = null;
-
- try
- {
+
+ try {
// first create an instance, given the provider
md = MessageDigest.getInstance(algorithm);
- }
- catch (Exception e)
- {
+ } catch (Exception e) {
mLogger.error("Exception: " + e);
return password;
}
-
+
md.reset();
-
+
// call the update method one or more times
// (useful when you don't know the size of your data, eg. stream)
md.update(unencodedPassword);
-
+
// now calculate the hash
byte[] encodedPassword = md.digest();
-
+
StringBuffer buf = new StringBuffer();
-
- for (int i = 0; i < encodedPassword.length; i++)
- {
- if ((encodedPassword[i] & 0xff) < 0x10)
- {
+
+ for (int i = 0; i < encodedPassword.length; i++) {
+ if ((encodedPassword[i] & 0xff) < 0x10) {
buf.append("0");
}
-
+
buf.append(Long.toString(encodedPassword[i] & 0xff, 16));
}
-
+
return buf.toString();
}
-
+
/**
* Encode a string using Base64 encoding. Used when storing passwords
* as cookies.
@@ -582,14 +533,13 @@
* @return String
* @throws IOException
*/
- public static String encodeString(String str) throws IOException
- {
+ public static String encodeString(String str) throws IOException {
sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
String encodedStr = encoder.encodeBuffer(str.getBytes());
-
+
return (encodedStr.trim());
}
-
+
/**
* Decode a string using Base64 encoding.
*
@@ -597,11 +547,10 @@
* @return String
* @throws IOException
*/
- public static String decodeString(String str) throws IOException
- {
+ public static String decodeString(String str) throws IOException {
sun.misc.BASE64Decoder dec = new sun.misc.BASE64Decoder();
String value = new String(dec.decodeBuffer(str));
-
+
return (value);
}
@@ -609,41 +558,35 @@
* Strips HTML and truncates.
*/
public static String truncate(
- String str, int lower, int upper, String appendToEnd)
- {
+ String str, int lower, int upper, String appendToEnd) {
// strip markup from the string
String str2 = removeHTML(str, false);
// quickly adjust the upper if it is set lower than 'lower'
- if (upper < lower)
- {
+ if (upper < lower) {
upper = lower;
- }
+ }
// now determine if the string fits within the upper limit
// if it does, go straight to return, do not pass 'go' and collect $200
- if(str2.length() > upper)
- {
+ if(str2.length() > upper) {
// the magic location int
int loc;
-
+
// first we determine where the next space appears after lower
loc = str2.lastIndexOf(' ', upper);
// now we'll see if the location is greater than the lower limit
- if(loc >= lower)
- {
+ if(loc >= lower) {
// yes it was, so we'll cut it off here
str2 = str2.substring(0, loc);
- }
- else
- {
+ } else {
// no it wasnt, so we'll cut it off at the upper limit
str2 = str2.substring(0, upper);
loc = upper;
}
-
- // the string was truncated, so we append the appendToEnd String
+
+ // the string was truncated, so we append the appendToEnd String
str2 = str2 + appendToEnd;
}
@@ -655,15 +598,14 @@
* http://cvs.apache.org/viewcvs/jakarta-taglibs/string/src/org/apache/taglibs/string/util/StringW.java?rev=1.16&content-type=text/vnd.viewcvs-markup
* Copyright (c) 1999 The Apache Software Foundation.
* Author: Henri Yandell bayard@generationjava.com
- *
+ *
* @param str
* @param lower
* @param upper
* @param appendToEnd
* @return
*/
- public static String truncateNicely(String str, int lower, int upper, String appendToEnd)
- {
+ public static String truncateNicely(String str, int lower, int upper, String appendToEnd) {
// strip markup from the string
String str2 = removeHTML(str, false);
boolean diff = (str2.length() < str.length());
@@ -671,14 +613,14 @@
// quickly adjust the upper if it is set lower than 'lower'
if(upper < lower) {
upper = lower;
- }
+ }
// now determine if the string fits within the upper limit
// if it does, go straight to return, do not pass 'go' and collect $200
if(str2.length() > upper) {
// the magic location int
int loc;
-
+
// first we determine where the next space appears after lower
loc = str2.lastIndexOf(' ', upper);
@@ -693,8 +635,7 @@
}
// HTML was removed from original str
- if (diff)
- {
+ if (diff) {
// location of last space in truncated string
loc = str2.lastIndexOf(' ', loc);
@@ -718,20 +659,17 @@
// append the appendToEnd String and
// add extracted HTML back onto truncated string
str = str2 + appendToEnd + str3;
- }
- else
- {
- // the string was truncated, so we append the appendToEnd String
+ } else {
+ // the string was truncated, so we append the appendToEnd String
str = str2 + appendToEnd;
}
-
+
}
return str;
}
- public static String truncateText(String str, int lower, int upper, String appendToEnd)
- {
+ public static String truncateText(String str, int lower, int upper, String appendToEnd) {
// strip markup from the string
String str2 = removeHTML(str, false);
boolean diff = (str2.length() < str.length());
@@ -739,14 +677,14 @@
// quickly adjust the upper if it is set lower than 'lower'
if(upper < lower) {
upper = lower;
- }
+ }
// now determine if the string fits within the upper limit
// if it does, go straight to return, do not pass 'go' and collect $200
if(str2.length() > upper) {
// the magic location int
int loc;
-
+
// first we determine where the next space appears after lower
loc = str2.lastIndexOf(' ', upper);
@@ -758,49 +696,47 @@
// no it wasnt, so we'll cut it off at the upper limit
str2 = str2.substring(0, upper);
loc = upper;
- }
- // the string was truncated, so we append the appendToEnd String
+ }
+ // the string was truncated, so we append the appendToEnd String
str = str2 + appendToEnd;
- }
+ }
return str;
}
/**
- * @param str
- * @return
- */
- private static String stripLineBreaks(String str)
- {
+ * @param str
+ * @return
+ */
+ private static String stripLineBreaks(String str) {
// TODO: use a string buffer, ignore case !
- str = str.replaceAll("<br>", "");
+ str = str.replaceAll("<br>", "");
str = str.replaceAll("<br/>", "");
str = str.replaceAll("<br />", "");
str = str.replaceAll("<p></p>", "");
str = str.replaceAll("<p/>","");
str = str.replaceAll("<p />","");
return str;
- }
-
+ }
+
/**
- * Need need to get rid of any user-visible HTML tags once all text has been
- * removed such as <BR>. This sounds like a better approach than removing
+ * Need need to get rid of any user-visible HTML tags once all text has been
+ * removed such as <BR>. This sounds like a better approach than removing
* all HTML tags and taking the chance to leave some tags un-closed.
- *
+ *
* WARNING: this method has serious performance problems a
- *
+ *
* @author Alexis Moussine-Pouchkine <al...@france.sun.com>
* @author Lance Lavandowska
* @param str the String object to modify
* @return the new String object without the HTML "visible" tags
*/
- private static String removeVisibleHTMLTags(String str)
- {
+ private static String removeVisibleHTMLTags(String str) {
str = stripLineBreaks(str);
StringBuffer result = new StringBuffer(str);
StringBuffer lcresult = new StringBuffer(str.toLowerCase());
-
+
// <img should take care of smileys
- String[] visibleTags = {"<img"}; // are there others to add?
+ String[] visibleTags = {"<img"}; // are there others to add?
int stringIndex;
for ( int j = 0 ; j < visibleTags.length ; j++ ) {
while ( (stringIndex = lcresult.indexOf(visibleTags[j])) != -1 ) {
@@ -819,17 +755,15 @@
}
}
}
-
+
// TODO: This code is buggy by nature. It doesn't deal with nesting of tags properly.
// remove certain elements with open & close tags
String[] openCloseTags = {"li", "a", "div", "h1", "h2", "h3", "h4"}; // more ?
- for (int j = 0; j < openCloseTags.length; j++)
- {
+ for (int j = 0; j < openCloseTags.length; j++) {
// could this be better done with a regular expression?
String closeTag = "</"+openCloseTags[j]+">";
int lastStringIndex = 0;
- while ( (stringIndex = lcresult.indexOf( "<"+openCloseTags[j], lastStringIndex)) > -1)
- {
+ while ( (stringIndex = lcresult.indexOf( "<"+openCloseTags[j], lastStringIndex)) > -1) {
lastStringIndex = stringIndex;
// Try to find the matching closing tag (ignores possible nesting!)
int endIndex = lcresult.indexOf(closeTag, stringIndex);
@@ -845,7 +779,7 @@
// Looks like it, so remove it.
result.delete(stringIndex, endIndex + 1);
lcresult.delete(stringIndex, endIndex + 1);
-
+
}
}
}
@@ -853,14 +787,13 @@
return result.toString();
}
-
- /**
+
+ /**
* Extract (keep) JUST the HTML from the String.
* @param str
* @return
*/
- public static String extractHTML(String str)
- {
+ public static String extractHTML(String str) {
if (str == null) return "";
StringBuffer ret = new StringBuffer(str.length());
int start = 0;
@@ -868,14 +801,12 @@
int endTag = 0;
if (beginTag == -1)
return str;
-
- while (beginTag >= start)
- {
+
+ while (beginTag >= start) {
endTag = str.indexOf(">", beginTag);
// if endTag found, keep tag
- if (endTag > -1)
- {
+ if (endTag > -1) {
ret.append( str.substring(beginTag, endTag+1) );
// move start forward and find another tag
@@ -883,27 +814,24 @@
beginTag = str.indexOf("<", start);
}
// if no endTag found, break
- else
- {
+ else {
break;
}
}
return ret.toString();
}
-
- public static String hexEncode(String str)
- {
+
+ public static String hexEncode(String str) {
if (StringUtils.isEmpty(str)) return str;
return RegexUtil.encode(str);
}
- public static String encodeEmail(String str)
- {
+ public static String encodeEmail(String str) {
return str!=null ? RegexUtil.encodeEmail(str) : null;
}
-
+
/**
* Converts a character to HTML or XML entity.
*
@@ -913,56 +841,49 @@
*
* @return The converted string.
*/
- public static final String charToHTML(char ch, boolean xml)
- {
+ public static final String charToHTML(char ch, boolean xml) {
int c;
-
+
// Convert left bracket
- if (ch == '<')
- {
+ if (ch == '<') {
return ("<");
}
-
+
// Convert left bracket
- else if (ch == '>')
- {
+ else if (ch == '>') {
return (">");
}
-
+
// Convert ampersand
- else if (ch == '&')
- {
+ else if (ch == '&') {
return ("&");
}
-
+
// Commented out to eliminate redundant numeric character codes (ROL-507)
// High-ASCII character
//else if (ch >= 128)
//{
- //c = ch;
- //return ("&#" + c + ';');
+ //c = ch;
+ //return ("&#" + c + ';');
//}
-
+
// Convert double quote
- else if (xml && (ch == '"'))
- {
+ else if (xml && (ch == '"')) {
return (""");
}
-
+
// Convert single quote
- else if (xml && (ch == '\''))
- {
+ else if (xml && (ch == '\'')) {
return ("'");
}
-
+
// No conversion
- else
- {
+ else {
// Return character as string
return (String.valueOf(ch));
}
}
-
+
/**
* Converts a text string to HTML or XML entities.
*
@@ -972,22 +893,20 @@
*
* @return The converted string.
*/
- public static final String textToHTML(String text, boolean xml)
- {
+ public static final String textToHTML(String text, boolean xml) {
if (text == null) return "null";
final StringBuffer html = new StringBuffer();
-
+
// Loop thru each characters of the text
- for (int i = 0; i < text.length(); i++)
- {
+ for (int i = 0; i < text.length(); i++) {
// Convert character to HTML/XML
html.append(charToHTML(text.charAt(i), xml));
}
-
+
// Return HTML/XML string
return html.toString();
}
-
+
/**
* Converts a text string to HTML or XML entities.
*
@@ -995,11 +914,10 @@
* @author Erik C. Thauvin
* @return The converted string.
*/
- public static final String textToHTML(String text)
- {
+ public static final String textToHTML(String text) {
return textToHTML(text, false);
}
-
+
/**
* Converts a text string to XML entities.
*
@@ -1007,114 +925,118 @@
* @author Erik C. Thauvin
* @return The converted string.
*/
- public static final String textToXML(String text)
- {
+ public static final String textToXML(String text) {
return textToHTML(text, true);
}
-
+
/**
* Converts a text string to HTML or XML entities.
* @param text The string to convert.
* @return The converted string.
*/
- public static final String textToCDATA(String text)
- {
+ public static final String textToCDATA(String text) {
if (text == null) return "null";
final StringBuffer html = new StringBuffer();
-
+
// Loop thru each characters of the text
- for (int i = 0; i < text.length(); i++)
- {
+ for (int i = 0; i < text.length(); i++) {
// Convert character to HTML/XML
html.append(charToCDATA(text.charAt(i)));
}
-
+
// Return HTML/XML string
return html.toString();
}
-
+
/**
* Converts a character to CDATA character.
* @param ch The character to convert.
* @return The converted string.
*/
- public static final String charToCDATA(char ch)
- {
+ public static final String charToCDATA(char ch) {
int c;
-
- if (ch >= 128)
- {
+
+ if (ch >= 128) {
c = ch;
-
+
return ("&#" + c + ';');
}
-
+
// No conversion
- else
- {
+ else {
// Return character as string
return (String.valueOf(ch));
}
}
-
- public static final String encode(String s)
- {
- try
- {
- if (s != null)
- return URLEncoder.encode(s, "utf-8");
- else
- return s;
- }
- catch (UnsupportedEncodingException e)
- {
- return s;
- }
- }
+
+ /**
+ * URL encoding.
+ * @param s a string to be URL-encoded
+ * @return URL encoding of s using character encoding UTF-8; null if s is null.
+ */
+ public static final String encode(String s) {
+ try {
+ if (s != null)
+ return URLEncoder.encode(s, "UTF-8");
+ else
+ return s;
+ } catch (UnsupportedEncodingException e) {
+ // Java Spec requires UTF-8 be in all Java environments, so this should not happen
+ return s;
+ }
+ }
+
+ /**
+ * URL decoding.
+ * @param s a URL-encoded string to be URL-decoded
+ * @return URL decoded value of s using character encoding UTF-8; null if s is null.
+ */
+ public static final String decode(String s) {
+ try {
+ if (s != null)
+ return URLDecoder.decode(s, "UTF-8");
+ else
+ return s;
+ } catch (UnsupportedEncodingException e) {
+ // Java Spec requires UTF-8 be in all Java environments, so this should not happen
+ return s;
+ }
+ }
+
/**
* @param string
* @return
*/
- public static int stringToInt(String string)
- {
- try
- {
+ public static int stringToInt(String string) {
+ try {
return Integer.valueOf(string).intValue();
- }
- catch (NumberFormatException e)
- {
+ } catch (NumberFormatException e) {
mLogger.debug("Invalid Integer:" + string);
}
return 0;
}
- /**
+ /**
* Code (stolen from Pebble) to add rel="nofollow" string to all links in HTML.
*/
- public static String addNofollow(String html)
- {
- if (html == null || html.length() == 0)
- {
+ public static String addNofollow(String html) {
+ if (html == null || html.length() == 0) {
return html;
}
Matcher m = mLinkPattern.matcher(html);
StringBuffer buf = new StringBuffer();
- while (m.find())
- {
+ while (m.find()) {
int start = m.start();
int end = m.end();
String link = html.substring(start, end);
buf.append(html.substring(0, start));
- if (link.indexOf("rel=\"nofollow\"") == -1)
- {
+ if (link.indexOf("rel=\"nofollow\"") == -1) {
buf.append(
- link.substring(0, link.length() - 1) + " rel=\"nofollow\">");
- }
- else
- {
+ link.substring(0, link.length() - 1) + " rel=\"nofollow\">");
+ } else {
buf.append(link);
- }
+ }
html = html.substring(end, html.length());
m = mLinkPattern.matcher(html);
}
@@ -1122,19 +1044,70 @@
return buf.toString();
}
- public static String unescapeHTML(String str)
- {
- return StringEscapeUtils.unescapeHtml(str);
+ /**
+ * Transforms the given String into a subset of HTML displayable on a web
+ * page. The subset includes <b>, <i>, <p>, <br>,
+ * <pre> and <a href> (and their corresponding end tags).
+ *
+ * @param s the String to transform
+ * @return the transformed String
+ */
+ public static String transformToHTMLSubset(String s) {
+
+ if (s == null) {
+ return null;
+ }
+
+ s = replace(s, OPENING_B_TAG_PATTERN, "<b>");
+ s = replace(s, CLOSING_B_TAG_PATTERN, "</b>");
+ s = replace(s, OPENING_I_TAG_PATTERN, "<i>");
+ s = replace(s, CLOSING_I_TAG_PATTERN, "</i>");
+ s = replace(s, OPENING_BLOCKQUOTE_TAG_PATTERN, "<blockquote>");
+ s = replace(s, CLOSING_BLOCKQUOTE_TAG_PATTERN, "</blockquote>");
+ s = replace(s, BR_TAG_PATTERN, "<br />");
+ s = replace(s, OPENING_P_TAG_PATTERN, "<p>");
+ s = replace(s, CLOSING_P_TAG_PATTERN, "</p>");
+ s = replace(s, OPENING_PRE_TAG_PATTERN, "<pre>");
+ s = replace(s, CLOSING_PRE_TAG_PATTERN, "</pre>");
+ s = replace(s, OPENING_UL_TAG_PATTERN, "<ul>");
+ s = replace(s, CLOSING_UL_TAG_PATTERN, "</ul>");
+ s = replace(s, OPENING_OL_TAG_PATTERN, "<ol>");
+ s = replace(s, CLOSING_OL_TAG_PATTERN, "</ol>");
+ s = replace(s, OPENING_LI_TAG_PATTERN, "<li>");
+ s = replace(s, CLOSING_LI_TAG_PATTERN, "</li>");
+
+ // HTTP links
+ s = replace(s, CLOSING_A_TAG_PATTERN, "</a>");
+ Matcher m = OPENING_A_TAG_PATTERN.matcher(s);
+ while (m.find()) {
+ int start = m.start();
+ int end = m.end();
+ String link = s.substring(start, end);
+ link = "<" + link.substring(4, link.length() - 4) + ">";
+ s = s.substring(0, start) + link + s.substring(end, s.length());
+ m = OPENING_A_TAG_PATTERN.matcher(s);
+ }
+
+ // escaped angle brackets
+ s = s.replaceAll("&lt;", "<");
+ s = s.replaceAll("&gt;", ">");
+ s = s.replaceAll("&#", "&#");
+
+ return s;
}
-
+ private static String replace(String string, Pattern pattern, String replacement) {
+ Matcher m = pattern.matcher(string);
+ return m.replaceAll(replacement);
+ }
+
/**
* Convert a byte array into a Base64 string (as used in mime formats)
*/
public static String toBase64(byte[] aValue) {
final String m_strBase64Chars =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int byte1;
int byte2;
@@ -1158,3 +1131,4 @@
return tt.toString();
}
}
+