X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=lib%2Fjetty%2Forg%2Feclipse%2Fjetty%2Futil%2FStringUtil.java;h=9dbd9e49b73daf30b271938f40a5e3a05e3387ba;hp=55868ad5edd9039d36e33e3094dd27729a18ffc4;hb=ba4f228fa9f72d50991a2218cfd83987ef5d385e;hpb=875b5e9651498a0cd8e0001c0742ba843e47cad0;ds=sidebyside diff --git a/lib/jetty/org/eclipse/jetty/util/StringUtil.java b/lib/jetty/org/eclipse/jetty/util/StringUtil.java index 55868ad5..9dbd9e49 100644 --- a/lib/jetty/org/eclipse/jetty/util/StringUtil.java +++ b/lib/jetty/org/eclipse/jetty/util/StringUtil.java @@ -1,6 +1,6 @@ // // ======================================================================== -// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. +// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 @@ -21,6 +21,8 @@ package org.eclipse.jetty.util; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -43,8 +45,10 @@ public class StringUtil public static final String ALL_INTERFACES="0.0.0.0"; public static final String CRLF="\015\012"; - public static final String __LINE_SEPARATOR= - System.getProperty("line.separator","\n"); + + /** @deprecated use {@link System#lineSeparator()} instead */ + @Deprecated + public static final String __LINE_SEPARATOR = System.lineSeparator(); public static final String __ISO_8859_1="ISO-8859-1"; public final static String __UTF8="UTF-8"; @@ -370,6 +374,53 @@ public class StringUtil } } + /** + * Find the index of a control characters in String + *

+ * This will return a result on the first occurrence of a control character, regardless if + * there are more than one. + *

+ *

+ * Note: uses codepoint version of {@link Character#isISOControl(int)} to support Unicode better. + *

+ * + *
+     *   indexOfControlChars(null)      == -1
+     *   indexOfControlChars("")        == -1
+     *   indexOfControlChars("\r\n")    == 0
+     *   indexOfControlChars("\t")      == 0
+     *   indexOfControlChars("   ")     == -1
+     *   indexOfControlChars("a")       == -1
+     *   indexOfControlChars(".")       == -1
+     *   indexOfControlChars(";\n")     == 1
+     *   indexOfControlChars("abc\f")   == 3
+     *   indexOfControlChars("z\010")   == 1
+     *   indexOfControlChars(":\u001c") == 1
+     * 
+ * + * @param str + * the string to test. + * @return the index of first control character in string, -1 if no control characters encountered + */ + public static int indexOfControlChars(String str) + { + if (str == null) + { + return -1; + } + int len = str.length(); + for (int i = 0; i < len; i++) + { + if (Character.isISOControl(str.codePointAt(i))) + { + // found a control character, we can stop searching now + return i; + } + } + // no control characters + return -1; + } + /* ------------------------------------------------------------ */ /** * Test if a string is null or only has whitespace characters in it. @@ -719,6 +770,11 @@ public class StringUtil return str.substring(0,maxSize); } + /** + * Parse the string representation of a list using {@link #csvSplit(List,String,int,int)} + * @param s The string to parse, expected to be enclosed as '[...]' + * @return An array of parsed values. + */ public static String[] arrayFromString(String s) { if (s==null) @@ -729,7 +785,249 @@ public class StringUtil if (s.length()==2) return new String[]{}; - return s.substring(1,s.length()-1).split(" *, *"); + return csvSplit(s,1,s.length()-2); + } + + /** + * Parse a CSV string using {@link #csvSplit(List,String, int, int)} + * @param s The string to parse + * @return An array of parsed values. + */ + public static String[] csvSplit(String s) + { + if (s==null) + return null; + return csvSplit(s,0,s.length()); + } + + /** + * Parse a CSV string using {@link #csvSplit(List,String, int, int)} + * @param s The string to parse + * @param off The offset into the string to start parsing + * @param len The len in characters to parse + * @return An array of parsed values. + */ + public static String[] csvSplit(String s, int off,int len) + { + if (s==null) + return null; + if (off<0 || len<0 || off>s.length()) + throw new IllegalArgumentException(); + + List list = new ArrayList<>(); + csvSplit(list,s,off,len); + return list.toArray(new String[list.size()]); + } + + enum CsvSplitState { PRE_DATA, QUOTE, SLOSH, DATA, WHITE, POST_DATA }; + + /** Split a quoted comma separated string to a list + *

Handle rfc4180-like + * CSV strings, with the exceptions:

+ * @param list The Collection to split to (or null to get a new list) + * @param s The string to parse + * @param off The offset into the string to start parsing + * @param len The len in characters to parse + * @return list containing the parsed list values + */ + public static List csvSplit(List list,String s, int off,int len) + { + if (list==null) + list=new ArrayList<>(); + CsvSplitState state = CsvSplitState.PRE_DATA; + StringBuilder out = new StringBuilder(); + int last=-1; + while (len>0) + { + char ch = s.charAt(off++); + len--; + + switch(state) + { + case PRE_DATA: + if (Character.isWhitespace(ch)) + continue; + + if ('"'==ch) + { + state=CsvSplitState.QUOTE; + continue; + } + + if (','==ch) + { + list.add(""); + continue; + } + + state=CsvSplitState.DATA; + out.append(ch); + continue; + + case DATA: + if (Character.isWhitespace(ch)) + { + last=out.length(); + out.append(ch); + state=CsvSplitState.WHITE; + continue; + } + + if (','==ch) + { + list.add(out.toString()); + out.setLength(0); + state=CsvSplitState.PRE_DATA; + continue; + } + + out.append(ch); + continue; + + case WHITE: + if (Character.isWhitespace(ch)) + { + out.append(ch); + continue; + } + + if (','==ch) + { + out.setLength(last); + list.add(out.toString()); + out.setLength(0); + state=CsvSplitState.PRE_DATA; + continue; + } + + state=CsvSplitState.DATA; + out.append(ch); + last=-1; + continue; + + case QUOTE: + if ('\\'==ch) + { + state=CsvSplitState.SLOSH; + continue; + } + if ('"'==ch) + { + list.add(out.toString()); + out.setLength(0); + state=CsvSplitState.POST_DATA; + continue; + } + out.append(ch); + continue; + + case SLOSH: + out.append(ch); + state=CsvSplitState.QUOTE; + continue; + + case POST_DATA: + if (','==ch) + { + state=CsvSplitState.PRE_DATA; + continue; + } + continue; + } + } + + switch(state) + { + case PRE_DATA: + case POST_DATA: + break; + + case DATA: + case QUOTE: + case SLOSH: + list.add(out.toString()); + break; + + case WHITE: + out.setLength(last); + list.add(out.toString()); + break; + } + + return list; + } + + public static String sanitizeXmlString(String html) + { + if (html==null) + return null; + + int i=0; + + // Are there any characters that need sanitizing? + loop: for (;i' : + case '\'': + case '"': + break loop; + + default: + if (Character.isISOControl(c) && !Character.isWhitespace(c)) + break loop; + } + } + + // No characters need sanitizing, so return original string + if (i==html.length()) + return html; + + // Create builder with OK content so far + StringBuilder out = new StringBuilder(html.length()*4/3); + out.append(html,0,i); + + // sanitize remaining content + for (;i' : + out.append(">"); + break; + case '\'': + out.append("'"); + break; + case '"': + out.append("""); + break; + + default: + if (Character.isISOControl(c) && !Character.isWhitespace(c)) + out.append('?'); + else + out.append(c); + } + } + return out.toString(); } }