Methods Summary |
---|
public static boolean | appearsLikeAndroidVCardQuotedPrintable(java.lang.String value)Checks to see if a string looks like it could be an android generated quoted printable.
Identification of quoted printable is not 100% reliable since it's just ascii. But given
the high number and exact location of generated = signs, there is a high likely-hood that
it would be.
// Quoted printable is always in multiple of 3s. With optional 1 '=' at end.
final int remainder = (value.length() % 3);
if (value.length() < 2 || (remainder != 1 && remainder != 0)) {
return false;
}
for (int i = 0; i < value.length(); i += 3) {
if (value.charAt(i) != '=") {
return false;
}
}
return true;
|
public static boolean | areAllEmpty(java.lang.String values)
if (values == null) {
return true;
}
for (final String value : values) {
if (!TextUtils.isEmpty(value)) {
return false;
}
}
return true;
|
public static java.util.List | constructListFromValue(java.lang.String value, int vcardType)Splits the given value into pieces using the delimiter ';' inside it.
Escaped characters in those values are automatically unescaped into original form.
final List<String> list = new ArrayList<String>();
StringBuilder builder = new StringBuilder();
final int length = value.length();
for (int i = 0; i < length; i++) {
char ch = value.charAt(i);
if (ch == '\\" && i < length - 1) {
char nextCh = value.charAt(i + 1);
final String unescapedString;
if (VCardConfig.isVersion40(vcardType)) {
unescapedString = VCardParserImpl_V40.unescapeCharacter(nextCh);
} else if (VCardConfig.isVersion30(vcardType)) {
unescapedString = VCardParserImpl_V30.unescapeCharacter(nextCh);
} else {
if (!VCardConfig.isVersion21(vcardType)) {
// Unknown vCard type
Log.w(LOG_TAG, "Unknown vCard type");
}
unescapedString = VCardParserImpl_V21.unescapeCharacter(nextCh);
}
if (unescapedString != null) {
builder.append(unescapedString);
i++;
} else {
builder.append(ch);
}
} else if (ch == ';") {
list.add(builder.toString());
builder = new StringBuilder();
} else {
builder.append(ch);
}
}
list.add(builder.toString());
return list;
|
public static java.lang.String | constructNameFromElements(int nameOrder, java.lang.String familyName, java.lang.String middleName, java.lang.String givenName)
return constructNameFromElements(nameOrder, familyName, middleName, givenName,
null, null);
|
public static java.lang.String | constructNameFromElements(int nameOrder, java.lang.String familyName, java.lang.String middleName, java.lang.String givenName, java.lang.String prefix, java.lang.String suffix)
final StringBuilder builder = new StringBuilder();
final String[] nameList = sortNameElements(nameOrder, familyName, middleName, givenName);
boolean first = true;
if (!TextUtils.isEmpty(prefix)) {
first = false;
builder.append(prefix);
}
for (final String namePart : nameList) {
if (!TextUtils.isEmpty(namePart)) {
if (first) {
first = false;
} else {
builder.append(' ");
}
builder.append(namePart);
}
}
if (!TextUtils.isEmpty(suffix)) {
if (!first) {
builder.append(' ");
}
builder.append(suffix);
}
return builder.toString();
|
public static boolean | containsOnlyAlphaDigitHyphen(java.lang.String values)
This is useful since vCard 3.0 often requires the ("X-") properties and groups
should contain only alphabets, digits, and hyphen.
Note: It is already known some devices (wrongly) outputs properties with characters
which should not be in the field. One example is "X-GOOGLE TALK". We accept
such kind of input but must never output it unless the target is very specific
to the device which is able to parse the malformed input.
if (values == null) {
return true;
}
return containsOnlyAlphaDigitHyphen(Arrays.asList(values));
|
public static boolean | containsOnlyAlphaDigitHyphen(java.util.Collection values)
if (values == null) {
return true;
}
final int upperAlphabetFirst = 0x41; // A
final int upperAlphabetAfterLast = 0x5b; // [
final int lowerAlphabetFirst = 0x61; // a
final int lowerAlphabetAfterLast = 0x7b; // {
final int digitFirst = 0x30; // 0
final int digitAfterLast = 0x3A; // :
final int hyphen = '-";
for (final String str : values) {
if (TextUtils.isEmpty(str)) {
continue;
}
final int length = str.length();
for (int i = 0; i < length; i = str.offsetByCodePoints(i, 1)) {
int codepoint = str.codePointAt(i);
if (!((lowerAlphabetFirst <= codepoint && codepoint < lowerAlphabetAfterLast) ||
(upperAlphabetFirst <= codepoint && codepoint < upperAlphabetAfterLast) ||
(digitFirst <= codepoint && codepoint < digitAfterLast) ||
(codepoint == hyphen))) {
return false;
}
}
}
return true;
|
public static boolean | containsOnlyNonCrLfPrintableAscii(java.lang.String values)
This is useful when checking the string should be encoded into quoted-printable
or not, which is required by vCard 2.1.
See the definition of "7bit" in vCard 2.1 spec for more information.
if (values == null) {
return true;
}
return containsOnlyNonCrLfPrintableAscii(Arrays.asList(values));
|
public static boolean | containsOnlyNonCrLfPrintableAscii(java.util.Collection values)
if (values == null) {
return true;
}
final int asciiFirst = 0x20;
final int asciiLast = 0x7E; // included
for (final String value : values) {
if (TextUtils.isEmpty(value)) {
continue;
}
final int length = value.length();
for (int i = 0; i < length; i = value.offsetByCodePoints(i, 1)) {
final int c = value.codePointAt(i);
if (!(asciiFirst <= c && c <= asciiLast)) {
return false;
}
}
}
return true;
|
public static boolean | containsOnlyPrintableAscii(java.lang.String values)
if (values == null) {
return true;
}
return containsOnlyPrintableAscii(Arrays.asList(values));
|
public static boolean | containsOnlyPrintableAscii(java.util.Collection values)
if (values == null) {
return true;
}
for (final String value : values) {
if (TextUtils.isEmpty(value)) {
continue;
}
if (!TextUtilsPort.isPrintableAsciiOnly(value)) {
return false;
}
}
return true;
|
public static boolean | containsOnlyWhiteSpaces(java.lang.String values)
if (values == null) {
return true;
}
return containsOnlyWhiteSpaces(Arrays.asList(values));
|
public static boolean | containsOnlyWhiteSpaces(java.util.Collection values)
if (values == null) {
return true;
}
for (final String str : values) {
if (TextUtils.isEmpty(str)) {
continue;
}
final int length = str.length();
for (int i = 0; i < length; i = str.offsetByCodePoints(i, 1)) {
if (!Character.isWhitespace(str.codePointAt(i))) {
return false;
}
}
}
return true;
|
public static final java.lang.String | convertStringCharset(java.lang.String originalString, java.lang.String sourceCharset, java.lang.String targetCharset)
if (sourceCharset.equalsIgnoreCase(targetCharset)) {
return originalString;
}
final Charset charset = Charset.forName(sourceCharset);
final ByteBuffer byteBuffer = charset.encode(originalString);
// byteBuffer.array() "may" return byte array which is larger than
// byteBuffer.remaining(). Here, we keep on the safe side.
final byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
try {
return new String(bytes, targetCharset);
} catch (UnsupportedEncodingException e) {
Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
return null;
}
|
public static final VCardParser | getAppropriateParser(int vcardType)
if (VCardConfig.isVersion21(vcardType)) {
return new VCardParser_V21();
} else if (VCardConfig.isVersion30(vcardType)) {
return new VCardParser_V30();
} else if (VCardConfig.isVersion40(vcardType)) {
return new VCardParser_V40();
} else {
throw new VCardException("Version is not specified");
}
|
public static int | getPhoneNumberFormat(int vcardType)
if (VCardConfig.isJapaneseDevice(vcardType)) {
return PhoneNumberUtils.FORMAT_JAPAN;
} else {
return PhoneNumberUtils.FORMAT_NANP;
}
|
public static java.lang.Object | getPhoneTypeFromStrings(java.util.Collection types, java.lang.String number)Returns Interger when the given types can be parsed as known type. Returns String object
when not, which should be set to label.
if (number == null) {
number = "";
}
int type = -1;
String label = null;
boolean isFax = false;
boolean hasPref = false;
if (types != null) {
for (final String typeStringOrg : types) {
if (typeStringOrg == null) {
continue;
}
final String typeStringUpperCase = typeStringOrg.toUpperCase();
if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_PREF)) {
hasPref = true;
} else if (typeStringUpperCase.equals(VCardConstants.PARAM_TYPE_FAX)) {
isFax = true;
} else {
final String labelCandidate;
if (typeStringUpperCase.startsWith("X-") && type < 0) {
labelCandidate = typeStringOrg.substring(2);
} else {
labelCandidate = typeStringOrg;
}
if (labelCandidate.length() == 0) {
continue;
}
// e.g. "home" -> TYPE_HOME
final Integer tmp = sKnownPhoneTypeMap_StoI.get(labelCandidate.toUpperCase());
if (tmp != null) {
final int typeCandidate = tmp;
// 1. If a type isn't specified yet, we'll choose the new type candidate.
// 2. If the current type is default one (OTHER) or custom one, we'll
// prefer more specific types specified in the vCard. Note that OTHER and
// the other different types may appear simultaneously here, since vCard
// allow to have VOICE and HOME/WORK in one line.
// e.g. "TEL;WORK;VOICE:1" -> WORK + OTHER -> Type should be WORK
// 3. TYPE_PAGER is prefered when the number contains @ surronded by
// a pager number and a domain name.
// e.g.
// o 1111@domain.com
// x @domain.com
// x 1111@
final int indexOfAt = number.indexOf("@");
if ((typeCandidate == Phone.TYPE_PAGER
&& 0 < indexOfAt && indexOfAt < number.length() - 1)
|| type < 0
|| type == Phone.TYPE_CUSTOM
|| type == Phone.TYPE_OTHER) {
type = tmp;
}
} else if (type < 0) {
type = Phone.TYPE_CUSTOM;
label = labelCandidate;
}
}
}
}
if (type < 0) {
if (hasPref) {
type = Phone.TYPE_MAIN;
} else {
// default to TYPE_HOME
type = Phone.TYPE_HOME;
}
}
if (isFax) {
if (type == Phone.TYPE_HOME) {
type = Phone.TYPE_FAX_HOME;
} else if (type == Phone.TYPE_WORK) {
type = Phone.TYPE_FAX_WORK;
} else if (type == Phone.TYPE_OTHER) {
type = Phone.TYPE_OTHER_FAX;
}
}
if (type == Phone.TYPE_CUSTOM) {
return label;
} else {
return type;
}
|
public static java.lang.String | getPhoneTypeString(java.lang.Integer type)
sKnownPhoneTypesMap_ItoS = new HashMap<Integer, String>();
sKnownPhoneTypeMap_StoI = new HashMap<String, Integer>();
sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_CAR, VCardConstants.PARAM_TYPE_CAR);
sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_CAR, Phone.TYPE_CAR);
sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_PAGER, VCardConstants.PARAM_TYPE_PAGER);
sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_PAGER, Phone.TYPE_PAGER);
sKnownPhoneTypesMap_ItoS.put(Phone.TYPE_ISDN, VCardConstants.PARAM_TYPE_ISDN);
sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_ISDN, Phone.TYPE_ISDN);
sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_HOME, Phone.TYPE_HOME);
sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_WORK, Phone.TYPE_WORK);
sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_CELL, Phone.TYPE_MOBILE);
sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_OTHER, Phone.TYPE_OTHER);
sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_CALLBACK,
Phone.TYPE_CALLBACK);
sKnownPhoneTypeMap_StoI.put(
VCardConstants.PARAM_PHONE_EXTRA_TYPE_COMPANY_MAIN, Phone.TYPE_COMPANY_MAIN);
sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_RADIO, Phone.TYPE_RADIO);
sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_TTY_TDD,
Phone.TYPE_TTY_TDD);
sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_PHONE_EXTRA_TYPE_ASSISTANT,
Phone.TYPE_ASSISTANT);
// OTHER (default in Android) should correspond to VOICE (default in vCard).
sKnownPhoneTypeMap_StoI.put(VCardConstants.PARAM_TYPE_VOICE, Phone.TYPE_OTHER);
sPhoneTypesUnknownToContactsSet = new HashSet<String>();
sPhoneTypesUnknownToContactsSet.add(VCardConstants.PARAM_TYPE_MODEM);
sPhoneTypesUnknownToContactsSet.add(VCardConstants.PARAM_TYPE_MSG);
sPhoneTypesUnknownToContactsSet.add(VCardConstants.PARAM_TYPE_BBS);
sPhoneTypesUnknownToContactsSet.add(VCardConstants.PARAM_TYPE_VIDEO);
sKnownImPropNameMap_ItoS = new HashMap<Integer, String>();
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_AIM, VCardConstants.PROPERTY_X_AIM);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_MSN, VCardConstants.PROPERTY_X_MSN);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_YAHOO, VCardConstants.PROPERTY_X_YAHOO);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_SKYPE, VCardConstants.PROPERTY_X_SKYPE_USERNAME);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_GOOGLE_TALK,
VCardConstants.PROPERTY_X_GOOGLE_TALK);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_ICQ, VCardConstants.PROPERTY_X_ICQ);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_JABBER, VCardConstants.PROPERTY_X_JABBER);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_QQ, VCardConstants.PROPERTY_X_QQ);
sKnownImPropNameMap_ItoS.put(Im.PROTOCOL_NETMEETING, VCardConstants.PROPERTY_X_NETMEETING);
// \u643A\u5E2F\u96FB\u8A71 = Full-width Hiragana "Keitai-Denwa" (mobile phone)
// \u643A\u5E2F = Full-width Hiragana "Keitai" (mobile phone)
// \u30B1\u30A4\u30BF\u30A4 = Full-width Katakana "Keitai" (mobile phone)
// \uFF79\uFF72\uFF80\uFF72 = Half-width Katakana "Keitai" (mobile phone)
sMobilePhoneLabelSet = new HashSet<String>(Arrays.asList(
"MOBILE", "\u643A\u5E2F\u96FB\u8A71", "\u643A\u5E2F", "\u30B1\u30A4\u30BF\u30A4",
"\uFF79\uFF72\uFF80\uFF72"));
return sKnownPhoneTypesMap_ItoS.get(type);
|
public static java.lang.String | getPropertyNameForIm(int protocol)
return sKnownImPropNameMap_ItoS.get(protocol);
|
public static java.lang.String | guessImageType(byte[] input)Guesses the format of input image. Currently just the first few bytes are used.
The type "GIF", "PNG", or "JPEG" is returned when possible. Returns null when
the guess failed.
if (input == null) {
return null;
}
if (input.length >= 3 && input[0] == 'G" && input[1] == 'I" && input[2] == 'F") {
return "GIF";
} else if (input.length >= 4 && input[0] == (byte) 0x89
&& input[1] == 'P" && input[2] == 'N" && input[3] == 'G") {
// Note: vCard 2.1 officially does not support PNG, but we may have it and
// using X- word like "X-PNG" may not let importers know it is PNG.
// So we use the String "PNG" as is...
return "PNG";
} else if (input.length >= 2 && input[0] == (byte) 0xff
&& input[1] == (byte) 0xd8) {
return "JPEG";
} else {
return null;
}
|
public static boolean | isMobilePhoneLabel(java.lang.String label)
// For backward compatibility.
// Detail: Until Donut, there isn't TYPE_MOBILE for email while there is now.
// To support mobile type at that time, this custom label had been used.
return ("_AUTO_CELL".equals(label) || sMobilePhoneLabelSet.contains(label));
|
public static boolean | isV21Word(java.lang.String value)
Returns true when the given String is categorized as "word" specified in vCard spec 2.1.
vCard 2.1 specifies:
word = <any printable 7bit us-ascii except []=:., >
if (TextUtils.isEmpty(value)) {
return true;
}
final int asciiFirst = 0x20;
final int asciiLast = 0x7E; // included
final int length = value.length();
for (int i = 0; i < length; i = value.offsetByCodePoints(i, 1)) {
final int c = value.codePointAt(i);
if (!(asciiFirst <= c && c <= asciiLast) ||
sUnAcceptableAsciiInV21WordSet.contains((char)c)) {
return false;
}
}
return true;
|
public static boolean | isValidInV21ButUnknownToContactsPhoteType(java.lang.String label)
return sPhoneTypesUnknownToContactsSet.contains(label);
|
public static java.lang.String | parseQuotedPrintable(java.lang.String value, boolean strictLineBreaking, java.lang.String sourceCharset, java.lang.String targetCharset)Unquotes given Quoted-Printable value. value must not be null.
// "= " -> " ", "=\t" -> "\t".
// Previous code had done this replacement. Keep on the safe side.
final String quotedPrintable;
{
final StringBuilder builder = new StringBuilder();
final int length = value.length();
for (int i = 0; i < length; i++) {
char ch = value.charAt(i);
if (ch == '=" && i < length - 1) {
char nextCh = value.charAt(i + 1);
if (nextCh == ' " || nextCh == '\t") {
builder.append(nextCh);
i++;
continue;
}
}
builder.append(ch);
}
quotedPrintable = builder.toString();
}
String[] lines;
if (strictLineBreaking) {
lines = quotedPrintable.split("\r\n");
} else {
StringBuilder builder = new StringBuilder();
final int length = quotedPrintable.length();
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < length; i++) {
char ch = quotedPrintable.charAt(i);
if (ch == '\n") {
list.add(builder.toString());
builder = new StringBuilder();
} else if (ch == '\r") {
list.add(builder.toString());
builder = new StringBuilder();
if (i < length - 1) {
char nextCh = quotedPrintable.charAt(i + 1);
if (nextCh == '\n") {
i++;
}
}
} else {
builder.append(ch);
}
}
final String lastLine = builder.toString();
if (lastLine.length() > 0) {
list.add(lastLine);
}
lines = list.toArray(new String[0]);
}
final StringBuilder builder = new StringBuilder();
for (String line : lines) {
if (line.endsWith("=")) {
line = line.substring(0, line.length() - 1);
}
builder.append(line);
}
final String rawString = builder.toString();
if (TextUtils.isEmpty(rawString)) {
Log.w(LOG_TAG, "Given raw string is empty.");
}
byte[] rawBytes = null;
try {
rawBytes = rawString.getBytes(sourceCharset);
} catch (UnsupportedEncodingException e) {
Log.w(LOG_TAG, "Failed to decode: " + sourceCharset);
rawBytes = rawString.getBytes();
}
byte[] decodedBytes = null;
try {
decodedBytes = QuotedPrintableCodecPort.decodeQuotedPrintable(rawBytes);
} catch (DecoderException e) {
Log.e(LOG_TAG, "DecoderException is thrown.");
decodedBytes = rawBytes;
}
try {
return new String(decodedBytes, targetCharset);
} catch (UnsupportedEncodingException e) {
Log.e(LOG_TAG, "Failed to encode: charset=" + targetCharset);
return new String(decodedBytes);
}
|
public static java.lang.String[] | sortNameElements(int nameOrder, java.lang.String familyName, java.lang.String middleName, java.lang.String givenName)
final String[] list = new String[3];
final int nameOrderType = VCardConfig.getNameOrderType(nameOrder);
switch (nameOrderType) {
case VCardConfig.NAME_ORDER_JAPANESE: {
if (containsOnlyPrintableAscii(familyName) &&
containsOnlyPrintableAscii(givenName)) {
list[0] = givenName;
list[1] = middleName;
list[2] = familyName;
} else {
list[0] = familyName;
list[1] = middleName;
list[2] = givenName;
}
break;
}
case VCardConfig.NAME_ORDER_EUROPE: {
list[0] = middleName;
list[1] = givenName;
list[2] = familyName;
break;
}
default: {
list[0] = givenName;
list[1] = middleName;
list[2] = familyName;
break;
}
}
return list;
|
public static java.lang.String | toHalfWidthString(java.lang.String orgString)
if (TextUtils.isEmpty(orgString)) {
return null;
}
final StringBuilder builder = new StringBuilder();
final int length = orgString.length();
for (int i = 0; i < length; i = orgString.offsetByCodePoints(i, 1)) {
// All Japanese character is able to be expressed by char.
// Do not need to use String#codepPointAt().
final char ch = orgString.charAt(i);
final String halfWidthText = JapaneseUtils.tryGetHalfWidthText(ch);
if (halfWidthText != null) {
builder.append(halfWidthText);
} else {
builder.append(ch);
}
}
return builder.toString();
|
private static java.lang.String | toStringAsParamValue(java.lang.String value, int[] escapeIndicators)
if (TextUtils.isEmpty(value)) {
value = "";
}
final int asciiFirst = 0x20;
final int asciiLast = 0x7E; // included
final StringBuilder builder = new StringBuilder();
final int length = value.length();
boolean needQuote = false;
for (int i = 0; i < length; i = value.offsetByCodePoints(i, 1)) {
final int codePoint = value.codePointAt(i);
if (codePoint < asciiFirst || codePoint == '"") {
// CTL characters and DQUOTE are never accepted. Remove them.
continue;
}
builder.appendCodePoint(codePoint);
for (int indicator : escapeIndicators) {
if (codePoint == indicator) {
needQuote = true;
break;
}
}
}
final String result = builder.toString();
return ((result.isEmpty() || VCardUtils.containsOnlyWhiteSpaces(result))
? ""
: (needQuote ? ('"" + result + '"")
: result));
|
public static java.lang.String | toStringAsV30ParamValue(java.lang.String value)
Returns String available as parameter value in vCard 3.0.
RFC 2426 requires vCard composer to quote parameter values when it contains
semi-colon, for example (See RFC 2426 for more information).
This method checks whether the given String can be used without quotes.
Note: We remove DQUOTE inside the given value silently for now.
return toStringAsParamValue(value, sEscapeIndicatorsV30);
|
public static java.lang.String | toStringAsV40ParamValue(java.lang.String value)
return toStringAsParamValue(value, sEscapeIndicatorsV40);
|