Author: trong.tran
Date: 2011-09-29 04:08:23 -0400 (Thu, 29 Sep 2011)
New Revision: 7556
Added:
portal/branches/xss/component/common/src/main/java/org/exoplatform/commons/utils/HTMLEntityEncoder.java
portal/branches/xss/component/common/src/test/java/org/exoplatform/commons/utils/TestHTMLEntityEncoder.java
Log:
Introduce an encoder for HTML entity
Added:
portal/branches/xss/component/common/src/main/java/org/exoplatform/commons/utils/HTMLEntityEncoder.java
===================================================================
---
portal/branches/xss/component/common/src/main/java/org/exoplatform/commons/utils/HTMLEntityEncoder.java
(rev 0)
+++
portal/branches/xss/component/common/src/main/java/org/exoplatform/commons/utils/HTMLEntityEncoder.java 2011-09-29
08:08:23 UTC (rev 7556)
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.exoplatform.commons.utils;
+
+import org.gatein.common.io.WriterCharWriter;
+import org.gatein.common.text.CharWriter;
+import org.gatein.common.text.EncodingException;
+import org.gatein.common.util.ParameterValidation;
+
+import java.io.StringWriter;
+import java.io.Writer;
+
+/**
+ * This encoder provides a few methods to encode the String to its HTML entity
representation.
+ *
+ * @author <a href="trongtt(a)gmail.com">Trong Tran</a>
+ * @version $Revision$
+ */
+public class HTMLEntityEncoder
+{
+ private static volatile HTMLEntityEncoder singletonInstance;
+
+ public static HTMLEntityEncoder getInstance()
+ {
+ if (singletonInstance == null)
+ {
+ synchronized (HTMLEntityEncoder.class)
+ {
+ if (singletonInstance == null)
+ {
+ singletonInstance = new HTMLEntityEncoder();
+ }
+ }
+ }
+ return singletonInstance;
+ }
+
+ /** . */
+ private final String[] hexToEntity = buildHexEntityNumberArray();
+
+ /** . */
+ private final String[] charToEntityName = buildEntityNameArray();
+
+ /**
+ * Character set that are immune from encoding in HTML
+ */
+ private static final char[] IMMUNE_HTML = { ',', '.', '-',
'_', ' ' };
+
+ /**
+ * Character set that are immune from encoding in HTML Attribute
+ */
+ private static final char[] IMMUNE_HTMLATTR = { ',', '.', '-',
'_' };
+
+ /**
+ * Encode data for use in HTML
+ *
+ * @param input the string to encode for HTML
+ * @return input encoded for HTML
+ */
+ public String encodeHTML(String input)
+ {
+ return encode(input, IMMUNE_HTML);
+ }
+
+ /**
+ * Encode data for use in HTML attributes.
+ *
+ * @param input the string to encode for a HTML attribute
+ * @return input encoded for use as value of a HTML attribute
+ */
+ public String encodeHTMLAttribute(String input)
+ {
+ return encode(input, IMMUNE_HTMLATTR);
+ }
+
+ /**
+ * @param chars the array to encode
+ * @param off the offset in the chars array
+ * @param len the length of chars to encode
+ * @param writer the writer to use
+ * @param immune the characters array are immune from encoding
+ * @throws EncodingException
+ */
+ protected void safeEncode(char[] chars, int off, int len, CharWriter writer, char[]
immune) throws EncodingException
+ {
+
+ // The index of the last copied char
+ int previous = off;
+
+ //
+ int to = off + len;
+
+ // Perform lookup char by char
+ for (int current = off; current < to; current++)
+ {
+ char c = chars[current];
+
+ // Lookup
+ if (isImmutable(immune, c))
+ {
+ continue;
+ }
+
+ String replacement;
+
+ String hex;
+
+ // Do we have a replacement
+ if ((replacement = lookupEntityName(c)) != null)
+ {
+ // We lazy create the result
+
+ // Append the previous chars if any
+ writer.append(chars, previous, current - previous);
+
+ // Append the replaced entity
+ writer.append('&').append(replacement).append(';');
+
+ // Update the previous pointer
+ previous = current + 1;
+ }
+ else if ((hex = lookupHexEntityNumber(c)) != null)
+ {
+ // We lazy create the result
+
+ // Append the previous chars if any
+ writer.append(chars, previous, current - previous);
+
+ // Append the replaced entity
+ writer.append("&#x").append(hex).append(';');
+
+ // Update the previous pointer
+ previous = current + 1;
+ }
+ }
+
+ //
+ writer.append(chars, previous, chars.length - previous);
+ }
+
+ protected final String lookupEntityName(char c)
+ {
+ return charToEntityName[c];
+ }
+
+ protected final String lookupHexEntityNumber(char c)
+ {
+ if (c < 0xFF)
+ {
+ return hexToEntity[c];
+ }
+
+ return Integer.toHexString(c);
+ }
+
+ private boolean isImmutable(char[] array, char c)
+ {
+ for (char ch : array)
+ {
+ if (c == ch)
+ return true;
+ }
+ return false;
+ }
+
+ private String encode(String input, char[] immutable)
+ {
+ ParameterValidation.throwIllegalArgExceptionIfNull(input, "String");
+
+ Writer sw = new StringWriter();
+ CharWriter charWriter = new WriterCharWriter(sw);
+ safeEncode(input.toCharArray(), 0, input.length(), charWriter, immutable);
+ return sw.toString();
+ }
+
+ /**
+ * Set of characters mapped to Entity name
+ */
+ private String[] buildEntityNameArray()
+ {
+ String[] ar = new String[65536];
+
+ ar[34] = "quot"; // quotation mark
+ ar[38] = "amp"; // ampersand
+ ar[60] = "lt"; // less-than sign
+ ar[62] = "gt"; // greater-than sign
+ ar[160] = "nbsp"; // no-break space
+ ar[161] = "iexcl"; // inverted exclamation mark
+ ar[162] = "cent"; // cent sign
+ ar[163] = "pound"; // pound sign
+ ar[164] = "curren"; // currency sign
+ ar[165] = "yen"; // yen sign
+ ar[166] = "brvbar"; // broken bar
+ ar[167] = "sect"; // section sign
+ ar[168] = "uml"; // diaeresis
+ ar[169] = "copy"; // copyright sign
+ ar[170] = "ordf"; // feminine ordinal indicator
+ ar[171] = "laquo"; // left-pointing double angle quotation mark
+ ar[172] = "not"; // not sign
+ ar[173] = "shy"; // soft hyphen
+ ar[174] = "reg"; // registered sign
+ ar[175] = "macr"; // macron
+ ar[176] = "deg"; // degree sign
+ ar[177] = "plusmn"; // plus-minus sign
+ ar[178] = "sup2"; // superscript two
+ ar[179] = "sup3"; // superscript three
+ ar[180] = "acute"; // acute accent
+ ar[181] = "micro"; // micro sign
+ ar[182] = "para"; // pilcrow sign
+ ar[183] = "middot"; // middle dot
+ ar[184] = "cedil"; // cedilla
+ ar[185] = "sup1"; // superscript one
+ ar[186] = "ordm"; // masculine ordinal indicator
+ ar[187] = "raquo"; // right-pointing double angle quotation mark
+ ar[188] = "frac14"; // vulgar fraction one quarter
+ ar[189] = "frac12"; // vulgar fraction one half
+ ar[190] = "frac34"; // vulgar fraction three quarters
+ ar[191] = "iquest"; // inverted question mark
+ ar[192] = "Agrave"; // Latin capital letter a with grave
+ ar[193] = "Aacute"; // Latin capital letter a with acute
+ ar[194] = "Acirc"; // Latin capital letter a with circumflex
+ ar[195] = "Atilde"; // Latin capital letter a with tilde
+ ar[196] = "Auml"; // Latin capital letter a with diaeresis
+ ar[197] = "Aring"; // Latin capital letter a with ring above
+ ar[198] = "AElig"; // Latin capital letter ae
+ ar[199] = "Ccedil"; // Latin capital letter c with cedilla
+ ar[200] = "Egrave"; // Latin capital letter e with grave
+ ar[201] = "Eacute"; // Latin capital letter e with acute
+ ar[202] = "Ecirc"; // Latin capital letter e with circumflex
+ ar[203] = "Euml"; // Latin capital letter e with diaeresis
+ ar[204] = "Igrave"; // Latin capital letter i with grave
+ ar[205] = "Iacute"; // Latin capital letter i with acute
+ ar[206] = "Icirc"; // Latin capital letter i with circumflex
+ ar[207] = "Iuml"; // Latin capital letter i with diaeresis
+ ar[208] = "ETH"; // Latin capital letter eth
+ ar[209] = "Ntilde"; // Latin capital letter n with tilde
+ ar[210] = "Ograve"; // Latin capital letter o with grave
+ ar[211] = "Oacute"; // Latin capital letter o with acute
+ ar[212] = "Ocirc"; // Latin capital letter o with circumflex
+ ar[213] = "Otilde"; // Latin capital letter o with tilde
+ ar[214] = "Ouml"; // Latin capital letter o with diaeresis
+ ar[215] = "times"; // multiplication sign
+ ar[216] = "Oslash"; // Latin capital letter o with stroke
+ ar[217] = "Ugrave"; // Latin capital letter u with grave
+ ar[218] = "Uacute"; // Latin capital letter u with acute
+ ar[219] = "Ucirc"; // Latin capital letter u with circumflex
+ ar[220] = "Uuml"; // Latin capital letter u with diaeresis
+ ar[221] = "Yacute"; // Latin capital letter y with acute
+ ar[222] = "THORN"; // Latin capital letter thorn
+ ar[223] = "szlig"; // Latin small letter sharp sXCOMMAX German Eszett
+ ar[224] = "agrave"; // Latin small letter a with grave
+ ar[225] = "aacute"; // Latin small letter a with acute
+ ar[226] = "acirc"; // Latin small letter a with circumflex
+ ar[227] = "atilde"; // Latin small letter a with tilde
+ ar[228] = "auml"; // Latin small letter a with diaeresis
+ ar[229] = "aring"; // Latin small letter a with ring above
+ ar[230] = "aelig"; // Latin lowercase ligature ae
+ ar[231] = "ccedil"; // Latin small letter c with cedilla
+ ar[232] = "egrave"; // Latin small letter e with grave
+ ar[233] = "eacute"; // Latin small letter e with acute
+ ar[234] = "ecirc"; // Latin small letter e with circumflex
+ ar[235] = "euml"; // Latin small letter e with diaeresis
+ ar[236] = "igrave"; // Latin small letter i with grave
+ ar[237] = "iacute"; // Latin small letter i with acute
+ ar[238] = "icirc"; // Latin small letter i with circumflex
+ ar[239] = "iuml"; // Latin small letter i with diaeresis
+ ar[240] = "eth"; // Latin small letter eth
+ ar[241] = "ntilde"; // Latin small letter n with tilde
+ ar[242] = "ograve"; // Latin small letter o with grave
+ ar[243] = "oacute"; // Latin small letter o with acute
+ ar[244] = "ocirc"; // Latin small letter o with circumflex
+ ar[245] = "otilde"; // Latin small letter o with tilde
+ ar[246] = "ouml"; // Latin small letter o with diaeresis
+ ar[247] = "divide"; // division sign
+ ar[248] = "oslash"; // Latin small letter o with stroke
+ ar[249] = "ugrave"; // Latin small letter u with grave
+ ar[250] = "uacute"; // Latin small letter u with acute
+ ar[251] = "ucirc"; // Latin small letter u with circumflex
+ ar[252] = "uuml"; // Latin small letter u with diaeresis
+ ar[253] = "yacute"; // Latin small letter y with acute
+ ar[254] = "thorn"; // Latin small letter thorn
+ ar[255] = "yuml"; // Latin small letter y with diaeresis
+ ar[338] = "OElig"; // Latin capital ligature oe
+ ar[339] = "oelig"; // Latin small ligature oe
+ ar[352] = "Scaron"; // Latin capital letter s with caron
+ ar[353] = "scaron"; // Latin small letter s with caron
+ ar[376] = "Yuml"; // Latin capital letter y with diaeresis
+ ar[402] = "fnof"; // Latin small letter f with hook
+ ar[710] = "circ"; // modifier letter circumflex accent
+ ar[732] = "tilde"; // small tilde
+ ar[913] = "Alpha"; // Greek capital letter alpha
+ ar[914] = "Beta"; // Greek capital letter beta
+ ar[915] = "Gamma"; // Greek capital letter gamma
+ ar[916] = "Delta"; // Greek capital letter delta
+ ar[917] = "Epsilon"; // Greek capital letter epsilon
+ ar[918] = "Zeta"; // Greek capital letter zeta
+ ar[919] = "Eta"; // Greek capital letter eta
+ ar[920] = "Theta"; // Greek capital letter theta
+ ar[921] = "Iota"; // Greek capital letter iota
+ ar[922] = "Kappa"; // Greek capital letter kappa
+ ar[923] = "Lambda"; // Greek capital letter lambda
+ ar[924] = "Mu"; // Greek capital letter mu
+ ar[925] = "Nu"; // Greek capital letter nu
+ ar[926] = "Xi"; // Greek capital letter xi
+ ar[927] = "Omicron"; // Greek capital letter omicron
+ ar[928] = "Pi"; // Greek capital letter pi
+ ar[929] = "Rho"; // Greek capital letter rho
+ ar[931] = "Sigma"; // Greek capital letter sigma
+ ar[932] = "Tau"; // Greek capital letter tau
+ ar[933] = "Upsilon"; // Greek capital letter upsilon
+ ar[934] = "Phi"; // Greek capital letter phi
+ ar[935] = "Chi"; // Greek capital letter chi
+ ar[936] = "Psi"; // Greek capital letter psi
+ ar[937] = "Omega"; // Greek capital letter omega
+ ar[945] = "alpha"; // Greek small letter alpha
+ ar[946] = "beta"; // Greek small letter beta
+ ar[947] = "gamma"; // Greek small letter gamma
+ ar[948] = "delta"; // Greek small letter delta
+ ar[949] = "epsilon"; // Greek small letter epsilon
+ ar[950] = "zeta"; // Greek small letter zeta
+ ar[951] = "eta"; // Greek small letter eta
+ ar[952] = "theta"; // Greek small letter theta
+ ar[953] = "iota"; // Greek small letter iota
+ ar[954] = "kappa"; // Greek small letter kappa
+ ar[955] = "lambda"; // Greek small letter lambda
+ ar[956] = "mu"; // Greek small letter mu
+ ar[957] = "nu"; // Greek small letter nu
+ ar[958] = "xi"; // Greek small letter xi
+ ar[959] = "omicron"; // Greek small letter omicron
+ ar[960] = "pi"; // Greek small letter pi
+ ar[961] = "rho"; // Greek small letter rho
+ ar[962] = "sigmaf"; // Greek small letter final sigma
+ ar[963] = "sigma"; // Greek small letter sigma
+ ar[964] = "tau"; // Greek small letter tau
+ ar[965] = "upsilon"; // Greek small letter upsilon
+ ar[966] = "phi"; // Greek small letter phi
+ ar[967] = "chi"; // Greek small letter chi
+ ar[968] = "psi"; // Greek small letter psi
+ ar[969] = "omega"; // Greek small letter omega
+ ar[977] = "thetasym";// Greek theta symbol
+ ar[978] = "upsih"; // Greek upsilon with hook symbol
+ ar[982] = "piv"; // Greek pi symbol
+ ar[8194] = "ensp"; // en space
+ ar[8195] = "emsp"; // em space
+ ar[8201] = "thinsp"; // thin space
+ ar[8204] = "zwnj"; // zero width non-joiner
+ ar[8205] = "zwj"; // zero width joiner
+ ar[8206] = "lrm"; // left-to-right mark
+ ar[8207] = "rlm"; // right-to-left mark
+ ar[8211] = "ndash"; // en dash
+ ar[8212] = "mdash"; // em dash
+ ar[8216] = "lsquo"; // left single quotation mark
+ ar[8217] = "rsquo"; // right single quotation mark
+ ar[8218] = "sbquo"; // single low-9 quotation mark
+ ar[8220] = "ldquo"; // left double quotation mark
+ ar[8221] = "rdquo"; // right double quotation mark
+ ar[8222] = "bdquo"; // double low-9 quotation mark
+ ar[8224] = "dagger"; // dagger
+ ar[8225] = "Dagger"; // double dagger
+ ar[8226] = "bull"; // bullet
+ ar[8230] = "hellip"; // horizontal ellipsis
+ ar[8240] = "permil"; // per mille sign
+ ar[8242] = "prime"; // prime
+ ar[8243] = "Prime"; // double prime
+ ar[8249] = "lsaquo"; // single left-pointing angle quotation mark
+ ar[8250] = "rsaquo"; // single right-pointing angle quotation mark
+ ar[8254] = "oline"; // overline
+ ar[8260] = "frasl"; // fraction slash
+ ar[8364] = "euro"; // euro sign
+ ar[8465] = "image"; // black-letter capital i
+ ar[8472] = "weierp"; // script capital pXCOMMAX Weierstrass p
+ ar[8476] = "real"; // black-letter capital r
+ ar[8482] = "trade"; // trademark sign
+ ar[8501] = "alefsym";// alef symbol
+ ar[8592] = "larr"; // leftwards arrow
+ ar[8593] = "uarr"; // upwards arrow
+ ar[8594] = "rarr"; // rightwards arrow
+ ar[8595] = "darr"; // downwards arrow
+ ar[8596] = "harr"; // left right arrow
+ ar[8629] = "crarr"; // downwards arrow with corner leftwards
+ ar[8656] = "lArr"; // leftwards double arrow
+ ar[8657] = "uArr"; // upwards double arrow
+ ar[8658] = "rArr"; // rightwards double arrow
+ ar[8659] = "dArr"; // downwards double arrow
+ ar[8660] = "hArr"; // left right double arrow
+ ar[8704] = "forall"; // for all
+ ar[8706] = "part"; // partial differential
+ ar[8707] = "exist"; // there exists
+ ar[8709] = "empty"; // empty set
+ ar[8711] = "nabla"; // nabla
+ ar[8712] = "isin"; // element of
+ ar[8713] = "notin"; // not an element of
+ ar[8715] = "ni"; // contains as member
+ ar[8719] = "prod"; // n-ary product
+ ar[8721] = "sum"; // n-ary summation
+ ar[8722] = "minus"; // minus sign
+ ar[8727] = "lowast"; // asterisk operator
+ ar[8730] = "radic"; // square root
+ ar[8733] = "prop"; // proportional to
+ ar[8734] = "infin"; // infinity
+ ar[8736] = "ang"; // angle
+ ar[8743] = "and"; // logical and
+ ar[8744] = "or"; // logical or
+ ar[8745] = "cap"; // intersection
+ ar[8746] = "cup"; // union
+ ar[8747] = "int"; // integral
+ ar[8756] = "there4"; // therefore
+ ar[8764] = "sim"; // tilde operator
+ ar[8773] = "cong"; // congruent to
+ ar[8776] = "asymp"; // almost equal to
+ ar[8800] = "ne"; // not equal to
+ ar[8801] = "equiv"; // identical toXCOMMAX equivalent to
+ ar[8804] = "le"; // less-than or equal to
+ ar[8805] = "ge"; // greater-than or equal to
+ ar[8834] = "sub"; // subset of
+ ar[8835] = "sup"; // superset of
+ ar[8836] = "nsub"; // not a subset of
+ ar[8838] = "sube"; // subset of or equal to
+ ar[8839] = "supe"; // superset of or equal to
+ ar[8853] = "oplus"; // circled plus
+ ar[8855] = "otimes"; // circled times
+ ar[8869] = "perp"; // up tack
+ ar[8901] = "sdot"; // dot operator
+ ar[8968] = "lceil"; // left ceiling
+ ar[8969] = "rceil"; // right ceiling
+ ar[8970] = "lfloor"; // left floor
+ ar[8971] = "rfloor"; // right floor
+ ar[9001] = "lang"; // left-pointing angle bracket
+ ar[9002] = "rang"; // right-pointing angle bracket
+ ar[9674] = "loz"; // lozenge
+ ar[9824] = "spades"; // black spade suit
+ ar[9827] = "clubs"; // black club suit
+ ar[9829] = "hearts"; // black heart suit
+ ar[9830] = "diams"; // black diamond suit
+
+ return ar;
+ }
+
+ /**
+ * Build an array to store the hex string for characters to be encoded.
+ * If the character shouldn't be encoded, then store null.
+ *
+ * @return An array containing characters in hex string that are to be encoded.
+ */
+ private String[] buildHexEntityNumberArray()
+ {
+ String[] array = new String[256];
+
+ /*
+ * Initialize an array to mark which characters are to be encoded. Store the hex
+ * string for that character to save time later. If the character shouldn't be
+ * encoded, then store null.
+ */
+ for (char c = 0; c < 0xFF; c++)
+ {
+ if (c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5A
|| c >= 0x61 && c <= 0x7A)
+ {
+ array[c] = null;
+ }
+ else
+ {
+ array[c] = Integer.toHexString(c);
+ }
+ }
+
+ return array;
+ }
+}
Added:
portal/branches/xss/component/common/src/test/java/org/exoplatform/commons/utils/TestHTMLEntityEncoder.java
===================================================================
---
portal/branches/xss/component/common/src/test/java/org/exoplatform/commons/utils/TestHTMLEntityEncoder.java
(rev 0)
+++
portal/branches/xss/component/common/src/test/java/org/exoplatform/commons/utils/TestHTMLEntityEncoder.java 2011-09-29
08:08:23 UTC (rev 7556)
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.exoplatform.commons.utils;
+
+import junit.framework.TestCase;
+
+/**
+ * @author <a href="trongtt(a)gmail.com">Trong Tran</a>
+ * @version $Revision$
+ */
+public class TestHTMLEntityEncoder extends TestCase
+{
+ private HTMLEntityEncoder htmlEncoder = HTMLEntityEncoder.getInstance();
+
+ public void testHTMLEncoding()
+ {
+ assertEquals("<h1>HELLO WORLD</h1>",
htmlEncoder.encodeHTML("<h1>HELLO WORLD</h1>"));
+
+ assertEquals("alert('HELLO WORLD')",
htmlEncoder.encodeHTML("alert('HELLO WORLD')"));
+
+ assertEquals(
+ "<a
href="http://example.com/?name1=value1&name2=value2&name3=a+b">link</a>",
+ htmlEncoder.encodeHTML("<a
href=\"http://example.com/?name1=value1&name2=value2&name3=a...;
+ }
+
+ public void testHTMLAttributeEncoding()
+ {
+
assertEquals("<h1>HELLO WORLD</h1>",
htmlEncoder.encodeHTMLAttribute("<h1>HELLO WORLD</h1>"));
+
+
assertEquals("alert('HELLO WORLD')",
htmlEncoder.encodeHTMLAttribute("alert('HELLO WORLD')"));
+
+ assertEquals(
+
"<a href="http://example.com/?name1=value1&name2=value2&name3=a+b">link</a>",
+ htmlEncoder.encodeHTMLAttribute("<a
href=\"http://example.com/?name1=value1&name2=value2&name3=a...;
+ }
+}