| 1 | /*
|
|---|
| 2 | * Copyright 1997-2011
|
|---|
| 3 | *
|
|---|
| 4 | * http://www.pconline.com.cn
|
|---|
| 5 | *
|
|---|
| 6 | */
|
|---|
| 7 | package org.gelivable.web;
|
|---|
| 8 |
|
|---|
| 9 | import java.net.URLEncoder;
|
|---|
| 10 |
|
|---|
| 11 | /**
|
|---|
| 12 | * EncodeUtils for encode the data use in browser prevent attack like XSS ...
|
|---|
| 13 | *
|
|---|
| 14 | * @author cuiyulong@pconline.com.cn
|
|---|
| 15 | * @author chenxiaohu@pconline.com.cn
|
|---|
| 16 | */
|
|---|
| 17 | public class EncodeUtils {
|
|---|
| 18 |
|
|---|
| 19 | /**
|
|---|
| 20 | * Encode data for use in HTML using HTML entity encoding
|
|---|
| 21 | * Only encode 6 base chars.
|
|---|
| 22 | *
|
|---|
| 23 | * @param input the text to encode for HTML
|
|---|
| 24 | * @return input encoded for HTML
|
|---|
| 25 | */
|
|---|
| 26 | public static String encodeForHTML(String input) {
|
|---|
| 27 | if (input == null) {
|
|---|
| 28 | return input;
|
|---|
| 29 | }
|
|---|
| 30 |
|
|---|
| 31 | StringBuilder sb = new StringBuilder(input.length());
|
|---|
| 32 |
|
|---|
| 33 | for (int i = 0, c = input.length(); i < c; i++) {
|
|---|
| 34 | char ch = input.charAt(i);
|
|---|
| 35 | switch (ch) {
|
|---|
| 36 | case '&':
|
|---|
| 37 | sb.append("&");
|
|---|
| 38 | break;
|
|---|
| 39 | case '<':
|
|---|
| 40 | sb.append("<");
|
|---|
| 41 | break;
|
|---|
| 42 | case '>':
|
|---|
| 43 | sb.append(">");
|
|---|
| 44 | break;
|
|---|
| 45 | case '"':
|
|---|
| 46 | sb.append(""");
|
|---|
| 47 | break;
|
|---|
| 48 | case '\'':
|
|---|
| 49 | sb.append("'");
|
|---|
| 50 | break;
|
|---|
| 51 | case '/':
|
|---|
| 52 | sb.append("/");
|
|---|
| 53 | break;
|
|---|
| 54 | default:
|
|---|
| 55 | sb.append(ch);
|
|---|
| 56 | }
|
|---|
| 57 | }
|
|---|
| 58 | return sb.toString();
|
|---|
| 59 | }
|
|---|
| 60 |
|
|---|
| 61 | /**
|
|---|
| 62 | * Encode data for insertion inside a data value or function argument in JavaScript. Including user data
|
|---|
| 63 | * directly inside a script is quite dangerous. Great care must be taken to prevent including user data
|
|---|
| 64 | * directly into script code itself, as no amount of encoding will prevent attacks there.
|
|---|
| 65 | *
|
|---|
| 66 | * @param input the text to encode for JavaScript
|
|---|
| 67 | * @return input encoded for use in JavaScript
|
|---|
| 68 | */
|
|---|
| 69 | public static String encodeForJavascript(String input) {
|
|---|
| 70 | if (input == null) {
|
|---|
| 71 | return input;
|
|---|
| 72 | }
|
|---|
| 73 |
|
|---|
| 74 | StringBuilder sb = new StringBuilder(input.length());
|
|---|
| 75 |
|
|---|
| 76 | for (int i = 0, c = input.length(); i < c; i++) {
|
|---|
| 77 | char ch = input.charAt(i);
|
|---|
| 78 |
|
|---|
| 79 | // do not encode alphanumeric characters and ',' '.' '_'
|
|---|
| 80 | if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' ||
|
|---|
| 81 | ch >= '0' && ch <= '9' ||
|
|---|
| 82 | ch == ',' || ch == '.' || ch == '_') {
|
|---|
| 83 | sb.append(ch);
|
|---|
| 84 | } else {
|
|---|
| 85 | String temp = Integer.toHexString(ch);
|
|---|
| 86 |
|
|---|
| 87 | // encode up to 256 with \\xHH
|
|---|
| 88 | if (ch < 256) {
|
|---|
| 89 | sb.append('\\').append('x');
|
|---|
| 90 | if (temp.length() == 1) {
|
|---|
| 91 | sb.append('0');
|
|---|
| 92 | }
|
|---|
| 93 | sb.append(temp.toLowerCase());
|
|---|
| 94 |
|
|---|
| 95 | // otherwise encode with \\uHHHH
|
|---|
| 96 | } else {
|
|---|
| 97 | sb.append('\\').append('u');
|
|---|
| 98 | for (int j = 0, d = 4 - temp.length(); j < d; j ++) {
|
|---|
| 99 | sb.append('0');
|
|---|
| 100 | }
|
|---|
| 101 | sb.append(temp.toUpperCase());
|
|---|
| 102 | }
|
|---|
| 103 | }
|
|---|
| 104 | }
|
|---|
| 105 |
|
|---|
| 106 | return sb.toString();
|
|---|
| 107 | }
|
|---|
| 108 |
|
|---|
| 109 | /**
|
|---|
| 110 | * Encode data for use in Cascading Style Sheets (CSS) content.
|
|---|
| 111 | *
|
|---|
| 112 | * @see <a href="http://www.w3.org/TR/CSS21/syndata.html#escaped-characters">CSS Syntax [w3.org]</a>
|
|---|
| 113 | *
|
|---|
| 114 | * @param input
|
|---|
| 115 | * the text to encode for CSS
|
|---|
| 116 | *
|
|---|
| 117 | * @return input encoded for CSS
|
|---|
| 118 | */
|
|---|
| 119 | public static String encodeForCSS(String input) {
|
|---|
| 120 | if (input == null) {
|
|---|
| 121 | return input;
|
|---|
| 122 | }
|
|---|
| 123 |
|
|---|
| 124 | StringBuilder sb = new StringBuilder(input.length());
|
|---|
| 125 |
|
|---|
| 126 | for (int i = 0, c = input.length(); i < c; i++) {
|
|---|
| 127 | char ch = input.charAt(i);
|
|---|
| 128 |
|
|---|
| 129 | // check for alphanumeric characters
|
|---|
| 130 | if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' ||
|
|---|
| 131 | ch >= '0' && ch <= '9') {
|
|---|
| 132 | sb.append(ch);
|
|---|
| 133 | } else {
|
|---|
| 134 | // return the hex and end in whitespace to terminate
|
|---|
| 135 | sb.append('\\').append(Integer.toHexString(ch)).append(' ');
|
|---|
| 136 | }
|
|---|
| 137 | }
|
|---|
| 138 | return sb.toString();
|
|---|
| 139 | }
|
|---|
| 140 |
|
|---|
| 141 | /**
|
|---|
| 142 | * Encode parameter for use in a URL. This method performs
|
|---|
| 143 | * <a href="http://en.wikipedia.org/wiki/Percent-encoding">URL encoding</a>
|
|---|
| 144 | * on the entire string.
|
|---|
| 145 | *
|
|---|
| 146 | * @see <a href="http://en.wikipedia.org/wiki/Percent-encoding">URL encoding</a>
|
|---|
| 147 | *
|
|---|
| 148 | * @param input
|
|---|
| 149 | * the text to encode for use in a URL
|
|---|
| 150 | *
|
|---|
| 151 | * @return input
|
|---|
| 152 | * encoded for use in a URL
|
|---|
| 153 | */
|
|---|
| 154 | public static String encodeURIComponent(String input) {
|
|---|
| 155 | return encodeURIComponent(input, "utf-8");
|
|---|
| 156 | }
|
|---|
| 157 |
|
|---|
| 158 | /**
|
|---|
| 159 | * Encode parameter for use in a URL. This method performs
|
|---|
| 160 | * <a href="http://en.wikipedia.org/wiki/Percent-encoding">URL encoding</a>
|
|---|
| 161 | * on the entire string.
|
|---|
| 162 | *
|
|---|
| 163 | * @see <a href="http://en.wikipedia.org/wiki/Percent-encoding">URL encoding</a>
|
|---|
| 164 | *
|
|---|
| 165 | * @param input
|
|---|
| 166 | * the text to encode for use in a URL
|
|---|
| 167 | * @param encoding
|
|---|
| 168 | * encoding to use
|
|---|
| 169 | *
|
|---|
| 170 | * @return input
|
|---|
| 171 | * encoded for use in a URL
|
|---|
| 172 | */
|
|---|
| 173 | public static String encodeURIComponent(String input, String encoding) {
|
|---|
| 174 | if (input == null) {
|
|---|
| 175 | return input;
|
|---|
| 176 | }
|
|---|
| 177 | String result;
|
|---|
| 178 | try {
|
|---|
| 179 | result = URLEncoder.encode(input, encoding);
|
|---|
| 180 | } catch (Exception e) {
|
|---|
| 181 | result = "";
|
|---|
| 182 | }
|
|---|
| 183 | return result;
|
|---|
| 184 | }
|
|---|
| 185 |
|
|---|
| 186 | /**
|
|---|
| 187 | * Check is input a valid URL
|
|---|
| 188 | * URL must starts with http://, https:// or ftp://
|
|---|
| 189 | * URL must not contains char '\'' and '\"'
|
|---|
| 190 | *
|
|---|
| 191 | * @param input URL to check
|
|---|
| 192 | * @return check result
|
|---|
| 193 | */
|
|---|
| 194 | public static boolean isValidURL(String input) {
|
|---|
| 195 | if (input == null || input.length() < 8) {
|
|---|
| 196 | return false;
|
|---|
| 197 | }
|
|---|
| 198 | char ch0 = input.charAt(0);
|
|---|
| 199 | if (ch0 == 'h') {
|
|---|
| 200 | if (input.charAt(1) == 't' &&
|
|---|
| 201 | input.charAt(2) == 't' &&
|
|---|
| 202 | input.charAt(3) == 'p') {
|
|---|
| 203 | char ch4 = input.charAt(4);
|
|---|
| 204 | if (ch4 == ':') {
|
|---|
| 205 | if (input.charAt(5) == '/' &&
|
|---|
| 206 | input.charAt(6) == '/') {
|
|---|
| 207 |
|
|---|
| 208 | return isValidURLChar(input, 7);
|
|---|
| 209 | } else {
|
|---|
| 210 | return false;
|
|---|
| 211 | }
|
|---|
| 212 | } else if (ch4 == 's') {
|
|---|
| 213 | if (input.charAt(5) == ':' &&
|
|---|
| 214 | input.charAt(6) == '/' &&
|
|---|
| 215 | input.charAt(7) == '/') {
|
|---|
| 216 |
|
|---|
| 217 | return isValidURLChar(input, 8);
|
|---|
| 218 | } else {
|
|---|
| 219 | return false;
|
|---|
| 220 | }
|
|---|
| 221 | } else {
|
|---|
| 222 | return false;
|
|---|
| 223 | }
|
|---|
| 224 | } else {
|
|---|
| 225 | return false;
|
|---|
| 226 | }
|
|---|
| 227 |
|
|---|
| 228 | } else if (ch0 == 'f') {
|
|---|
| 229 | if( input.charAt(1) == 't' &&
|
|---|
| 230 | input.charAt(2) == 'p' &&
|
|---|
| 231 | input.charAt(3) == ':' &&
|
|---|
| 232 | input.charAt(4) == '/' &&
|
|---|
| 233 | input.charAt(5) == '/') {
|
|---|
| 234 |
|
|---|
| 235 | return isValidURLChar(input, 6);
|
|---|
| 236 | } else {
|
|---|
| 237 | return false;
|
|---|
| 238 | }
|
|---|
| 239 | }
|
|---|
| 240 | return false;
|
|---|
| 241 | }
|
|---|
| 242 |
|
|---|
| 243 | static boolean isValidURLChar(String url, int start) {
|
|---|
| 244 | for (int i = start, c = url.length(); i < c; i ++) {
|
|---|
| 245 | char ch = url.charAt(i);
|
|---|
| 246 | if (ch == '"' || ch == '\'') {
|
|---|
| 247 | return false;
|
|---|
| 248 | }
|
|---|
| 249 | }
|
|---|
| 250 | return true;
|
|---|
| 251 | }
|
|---|
| 252 |
|
|---|
| 253 | }
|
|---|