/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.appium.android.bootstrap.utils; import java.nio.charset.Charset; import io.appium.android.bootstrap.Logger; public class UnicodeEncoder { private static final Charset M_UTF7 = Charset.forName("x-IMAP-mailbox-name"); private static final Charset ASCII = Charset.forName("US-ASCII"); public static String encode(final String text) { byte[] encoded = text.getBytes(M_UTF7); String ret = new String(encoded, ASCII); if (ret.charAt(ret.length()-1) != text.charAt(text.length()-1) && !ret.endsWith("-")) { // in some cases there is a problem and the closing tag is not added // to the encoded text (for instance, with `ΓΌ`) // // but first, sometimes it is just that the original string is too long // and things get confused if (text.length() >= 2) { Logger.debug("Encoding error. Splitting text and trying again."); int middle = text.length() / 2; ret = encode(text.substring(0, middle)) + encode(text.substring(middle)); } else { Logger.debug("Closing tag missing. Adding."); ret = ret + "-"; } } return ret; } public static boolean needsEncoding(final String text) { char[] chars = text.toCharArray(); for (int i = 0; i < chars.length; i++) { int cp = Character.codePointAt(chars, i); if (cp > 0x7F || cp == '&') { // Selenium uses a Unicode PUA to cover certain special characters // see https://code.google.com/p/selenium/source/browse/java/client/src/org/openqa/selenium/Keys.java // these should juse be passed through as is. return !(cp >= 0xE000 && cp <= 0xE040); } } return false; } }