Browse Source

Merge pull request #3809 in DESIGN/design from feature/10.0 to feature/x

* commit '88402de15f6473c221fdd7921f921bccd0c5bf5b':
  KERNEL-6368【代码检测】XML注入(XML External Entity Injection)
research/11.0
superman 4 years ago
parent
commit
b5ba80b1dc
  1. 68
      designer-base/src/main/java/com/fr/design/gui/autocomplete/DefaultCompletionProvider.java
  2. 4
      designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxScheme.java
  3. 9
      designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Theme.java
  4. 8
      designer-base/src/main/java/com/fr/design/gui/syntax/ui/rtextarea/Macro.java
  5. 5
      designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java

68
designer-base/src/main/java/com/fr/design/gui/autocomplete/DefaultCompletionProvider.java

@ -24,7 +24,11 @@ import javax.swing.text.Segment;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import com.fr.log.FineLoggerFactory;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
/**
@ -81,10 +85,10 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
/**
* Returns the text just before the current caret position that could be
* the start of something auto-completable.<p>
*
* <p>
* This method returns all characters before the caret that are matched
* by {@link #isValidChar(char)}.
*
* <p>
* {@inheritDoc}
*/
public String getAlreadyEnteredText(JTextComponent comp) {
@ -96,7 +100,7 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
int index = root.getElementIndex(dot);
Element elem = root.getElement(index);
int start = elem.getStartOffset();
int len = dot-start;
int len = dot - start;
try {
doc.getText(start, len, seg);
} catch (BadLocationException ble) {
@ -106,13 +110,13 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
int segEnd = seg.offset + len;
start = segEnd - 1;
while (start>=seg.offset && isValidChar(seg.array[start])) {
while (start >= seg.offset && isValidChar(seg.array[start])) {
start--;
}
start++;
len = segEnd - start;
return len==0 ? EMPTY_STRING : new String(seg.array, start, len);
return len == 0 ? EMPTY_STRING : new String(seg.array, start, len);
}
@ -123,7 +127,7 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
public List<Completion> getCompletionsAt(JTextComponent tc, Point p) {
int offset = tc.viewToModel(p);
if (offset<0 || offset>=tc.getDocument().getLength()) {
if (offset < 0 || offset >= tc.getDocument().getLength()) {
lastCompletionsAtText = null;
return lastParameterizedCompletionsAt = null;
}
@ -138,25 +142,25 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
try {
doc.getText(start, end-start, s);
doc.getText(start, end - start, s);
// Get the valid chars before the specified offset.
int startOffs = s.offset + (offset-start) - 1;
while (startOffs>=s.offset && isValidChar(s.array[startOffs])) {
int startOffs = s.offset + (offset - start) - 1;
while (startOffs >= s.offset && isValidChar(s.array[startOffs])) {
startOffs--;
}
// Get the valid chars at and after the specified offset.
int endOffs = s.offset + (offset-start);
while (endOffs<s.offset+s.count && isValidChar(s.array[endOffs])) {
int endOffs = s.offset + (offset - start);
while (endOffs < s.offset + s.count && isValidChar(s.array[endOffs])) {
endOffs++;
}
int len = endOffs - startOffs - 1;
if (len<=0) {
if (len <= 0) {
return lastParameterizedCompletionsAt = null;
}
String text = new String(s.array, startOffs+1, len);
String text = new String(s.array, startOffs + 1, len);
if (text.equals(lastCompletionsAtText)) {
return lastParameterizedCompletionsAt;
@ -188,7 +192,7 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
// If this provider doesn't support parameterized completions,
// bail out now.
char paramListStart = getParameterListStart();
if (paramListStart==0) {
if (paramListStart == 0) {
return list; // null
}
@ -200,7 +204,7 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
Element elem = root.getElement(line);
int offs = elem.getStartOffset();
int len = dot - offs - 1/*paramListStart.length()*/;
if (len<=0) { // Not enough chars on line for a method.
if (len <= 0) { // Not enough chars on line for a method.
return list; // null
}
@ -211,27 +215,27 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
// Get the identifier preceding the '(', ignoring any whitespace
// between them.
offs = s.offset + len - 1;
while (offs>=s.offset && Character.isWhitespace(s.array[offs])) {
while (offs >= s.offset && Character.isWhitespace(s.array[offs])) {
offs--;
}
int end = offs;
while (offs>=s.offset && isValidChar(s.array[offs])) {
while (offs >= s.offset && isValidChar(s.array[offs])) {
offs--;
}
String text = new String(s.array, offs+1, end-offs);
String text = new String(s.array, offs + 1, end - offs);
// Get a list of all Completions matching the text, but then
// narrow it down to just the ParameterizedCompletions.
List<Completion> l = getCompletionByInputText(text);
if (l!=null && !l.isEmpty()) {
for (int i=0; i<l.size(); i++) {
if (l != null && !l.isEmpty()) {
for (int i = 0; i < l.size(); i++) {
Object o = l.get(i);
if (o instanceof ParameterizedCompletion) {
if (list==null) {
if (list == null) {
list = new ArrayList<ParameterizedCompletion>(1);
}
list.add((ParameterizedCompletion)o);
list.add((ParameterizedCompletion) o);
}
}
}
@ -264,7 +268,7 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
* @return Whether the character is valid.
*/
protected boolean isValidChar(char ch) {
return Character.isLetterOrDigit(ch) || ch=='_';
return Character.isLetterOrDigit(ch) || ch == '_';
}
@ -314,6 +318,15 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
//long start = System.currentTimeMillis();
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
} catch (ParserConfigurationException | SAXNotSupportedException | SAXNotRecognizedException e) {
FineLoggerFactory.getLogger().warn(e.getMessage(), e);
}
factory.setValidating(true);
CompletionXMLParser handler = new CompletionXMLParser(this, cl);
BufferedInputStream bin = new BufferedInputStream(in);
@ -323,10 +336,10 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
List<Completion> completions = handler.getCompletions();
addCompletions(completions);
char startChar = handler.getParamStartChar();
if (startChar!=0) {
if (startChar != 0) {
char endChar = handler.getParamEndChar();
String sep = handler.getParamSeparator();
if (endChar!=0 && sep!=null && sep.length()>0) { // Sanity
if (endChar != 0 && sep != null && sep.length() > 0) { // Sanity
setParameterizedCompletionParams(startChar, sep, endChar);
}
}
@ -353,12 +366,11 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
public void loadFromXML(String resource) throws IOException {
ClassLoader cl = getClass().getClassLoader();
InputStream in = cl.getResourceAsStream(resource);
if (in==null) {
if (in == null) {
File file = new File(resource);
if (file.isFile()) {
in = new FileInputStream(file);
}
else {
} else {
throw new IOException("No such resource: " + resource);
}
}

4
designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxScheme.java

@ -624,6 +624,10 @@ public class SyntaxScheme implements Cloneable, TokenTypes {
SyntaxSchemeLoader parser = null;
try {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
parser = new SyntaxSchemeLoader(baseFont);
parser.baseFont = baseFont;
reader.setContentHandler(parser);

9
designer-base/src/main/java/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Theme.java

@ -22,6 +22,7 @@ import java.lang.reflect.Field;
import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource;
import javax.swing.text.StyleContext;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
@ -493,6 +494,8 @@ public class Theme {
StreamResult result = new StreamResult(new PrintWriter(
new UnicodeWriter(bout, "UTF-8")));
TransformerFactory transFac = TransformerFactory.newInstance();
transFac.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
transFac.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
Transformer transformer = transFac.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
@ -580,8 +583,12 @@ public class Theme {
public static void load(Theme theme, InputStream in) throws IOException {
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setValidating(true);
try {
spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
spf.setValidating(true);
SAXParser parser = spf.newSAXParser();
XMLReader reader = parser.getXMLReader();
XmlHandler handler = new XmlHandler();

8
designer-base/src/main/java/com/fr/design/gui/syntax/ui/rtextarea/Macro.java

@ -14,6 +14,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
@ -94,6 +95,11 @@ public class Macro {
DocumentBuilder db = null;
Document doc = null;
try {
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setXIncludeAware(false);
db = dbf.newDocumentBuilder();
//InputSource is = new InputSource(new FileReader(file));
InputSource is = new InputSource(new UnicodeReader(
@ -374,6 +380,8 @@ public class Macro {
StreamResult result = new StreamResult(new File(fileName));
DOMSource source = new DOMSource(doc);
TransformerFactory transFac = TransformerFactory.newInstance();
transFac.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
transFac.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
Transformer transformer = transFac.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, FILE_ENCODING);

5
designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java

@ -12,6 +12,7 @@ import com.fr.third.springframework.web.context.support.AnnotationConfigWebAppli
import com.fr.workspace.WorkContext;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Wrapper;
import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.webresources.StandardRoot;
@ -73,6 +74,10 @@ public class FineEmbedServerActivator extends Activator {
String contextPath = "/" + ProductConstants.getAppFolderName();
final Context context = tomcat.addContext(contextPath, docBase);
context.setResources(new StandardRoot(context));
Wrapper servlet = Tomcat.addServlet(context, "DruidStatView", "com.fr.third.alibaba.druid.support.http.StatViewServlet");
context.addServletMappingDecoded("/druid/*", "DruidStatView");
servlet.setLoadOnStartup(1);
servlet.setOverridable(true);
Tomcat.initWebappDefaults(context);
//覆盖tomcat的WebAppClassLoader
context.setLoader(new FRTomcatLoader());

Loading…
Cancel
Save