Skip to content

Commit

Permalink
Make sure xml strings are safe
Browse files Browse the repository at this point in the history
  • Loading branch information
Mykola Mokhnach committed Oct 26, 2018
1 parent a770dec commit d562ba7
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.appium.uiautomator2.core;

import android.graphics.Point;
Expand All @@ -38,16 +39,10 @@
import io.appium.uiautomator2.utils.Logger;

import static io.appium.uiautomator2.utils.AXWindowHelpers.currentActiveWindowRoot;
import static io.appium.uiautomator2.utils.XMLHelpers.DEFAULT_VIEW_NAME;
import static io.appium.uiautomator2.utils.XMLHelpers.DEFAULT_VIEW_CLASS_NAME;
import static io.appium.uiautomator2.utils.XMLHelpers.toNodeName;
import static io.appium.uiautomator2.utils.XMLHelpers.toSafeXmlString;

/**
* The AccessibilityNodeInfoDumper in Android Open Source Project contains a lot of bugs which will
* stay in old android versions forever. By coping the code of the latest version it is ensured that
* all patches become available on old android versions. <p/> down ported bugs are e.g. { @link
* https://code.google.com/p/android/issues/detail?id=62906 } { @link
* https://code.google.com/p/android/issues/detail?id=58733 }
*/
public class AccessibilityNodeInfoDumper {
// https://github.com/appium/appium/issues/10204
private static final int MAX_DEPTH = 70;
Expand All @@ -68,7 +63,7 @@ private static Element toDOMElement(UiElement<?, ?> uiElement, final Document do
final int depth) {
String className = uiElement.getClassName();
if (className == null) {
className = DEFAULT_VIEW_NAME;
className = DEFAULT_VIEW_CLASS_NAME;
}
Element element = document.createElement(toNodeName(className));
final int uiElementIndex = uiElementsMapping.size();
Expand All @@ -84,7 +79,7 @@ private static Element toDOMElement(UiElement<?, ?> uiElement, final Document do
setNodeLocalName(element, className);

for (Attribute attr : Attribute.values()) {
setAttribute(element, attr, uiElement.get(attr));
setAttribute(element, attr, toSafeXmlString(uiElement.get(attr), "?"));
}
element.setAttribute(UI_ELEMENT_INDEX, Integer.toString(uiElementIndex));

Expand Down
26 changes: 14 additions & 12 deletions app/src/main/java/io/appium/uiautomator2/utils/XMLHelpers.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,41 +16,43 @@

package io.appium.uiautomator2.utils;

import android.support.annotation.Nullable;

import org.apache.commons.lang.StringUtils;

import java.util.regex.Pattern;


public abstract class XMLHelpers {
// XML 1.0 Legal Characters (http://stackoverflow.com/a/4237934/347155)
// #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
private final static Pattern XML10Pattern = Pattern.compile("[^" + "\u0009\r\n" +
private final static Pattern XML10_PATTERN = Pattern.compile("[^" + "\u0009\r\n" +
"\u0020-\uD7FF" + "\uE000-\uFFFD" + "\ud800\udc00-\udbff\udfff" + "]");
public final static String DEFAULT_VIEW_NAME = "android.view.View";
public final static String DEFAULT_VIEW_CLASS_NAME = "android.view.View";

public static String toNodeName(String className) {
if (StringUtils.isBlank(className)) {
return DEFAULT_VIEW_NAME;
return DEFAULT_VIEW_CLASS_NAME;
}

String fixedName = className
.replaceAll("[$@#&]", ".")
// https://github.com/appium/appium/issues/9934
.replaceAll("[ˋˊ\\s]", ""); // "ˋ" is \xCB\x8B in UTF-8
fixedName = safeCharSeqToString(fixedName)
// https://github.com/appium/appium/issues/9934
.replace("?", "")
// https://github.com/appium/appium/issues/9934
//noinspection ConstantConditions
fixedName = toSafeXmlString(fixedName, "?")
.replaceAll("\\?", "")
.replaceAll("\\.+", ".")
.replaceAll("(^\\.|\\.$)", "");
if (!fixedName.equals(className)) {
Logger.info(String.format("Rewrote XML tag name '%s' to '%s'", className, fixedName));
}
return StringUtils.isBlank(fixedName) ? DEFAULT_VIEW_NAME : fixedName;
return StringUtils.isBlank(fixedName) ? DEFAULT_VIEW_CLASS_NAME : fixedName;
}

public static String safeCharSeqToString(CharSequence cs) {
if (cs == null) {
return "";
}
return XML10Pattern.matcher(String.valueOf(cs)).replaceAll("?");
@Nullable
public static String toSafeXmlString(Object source, String replacement) {
return source == null ? null : XML10_PATTERN.matcher(String.valueOf(source)).replaceAll(replacement);
}
}

0 comments on commit d562ba7

Please sign in to comment.